mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1154277: Part 2 - support running Social API documents to run in a remote browser, i.e. the content process. f=mixedpuppy, r=Standard8
This commit is contained in:
parent
6c7fdd37b9
commit
f72d46f1cc
@ -370,7 +370,7 @@ SocialFlyout = {
|
|||||||
// the xbl bindings for the iframe probably don't exist yet, so we can't
|
// the xbl bindings for the iframe probably don't exist yet, so we can't
|
||||||
// access iframe.messageManager directly - but can get at it with this dance.
|
// access iframe.messageManager directly - but can get at it with this dance.
|
||||||
let mm = iframe.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.messageManager;
|
let mm = iframe.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.messageManager;
|
||||||
mm.sendAsyncMessage("Social:SetErrorURL", null,
|
mm.sendAsyncMessage("Social:SetErrorURL",
|
||||||
{ template: "about:socialerror?mode=compactInfo&origin=%{origin}" });
|
{ template: "about:socialerror?mode=compactInfo&origin=%{origin}" });
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -512,7 +512,7 @@ SocialShare = {
|
|||||||
iframe.setAttribute("messagemanagergroup", "social");
|
iframe.setAttribute("messagemanagergroup", "social");
|
||||||
panel.lastChild.appendChild(iframe);
|
panel.lastChild.appendChild(iframe);
|
||||||
let mm = iframe.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.messageManager;
|
let mm = iframe.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.messageManager;
|
||||||
mm.sendAsyncMessage("Social:SetErrorURL", null,
|
mm.sendAsyncMessage("Social:SetErrorURL",
|
||||||
{ template: "about:socialerror?mode=compactInfo&origin=%{origin}&url=%{url}" });
|
{ template: "about:socialerror?mode=compactInfo&origin=%{origin}&url=%{url}" });
|
||||||
|
|
||||||
this.populateProviderMenu();
|
this.populateProviderMenu();
|
||||||
|
@ -118,6 +118,10 @@ panelview:not([mainview]):not([current]) {
|
|||||||
visibility: collapse;
|
visibility: collapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
browser[frameType="social"][remote="true"] {
|
||||||
|
-moz-binding: url("chrome://global/content/bindings/remote-browser.xml#remote-browser");
|
||||||
|
}
|
||||||
|
|
||||||
tabbrowser {
|
tabbrowser {
|
||||||
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser");
|
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser");
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,26 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||||||
// social frames are always treated as app tabs
|
// social frames are always treated as app tabs
|
||||||
docShell.isAppTab = true;
|
docShell.isAppTab = true;
|
||||||
|
|
||||||
|
var gDOMContentLoaded = false;
|
||||||
|
addEventListener("DOMContentLoaded", function() {
|
||||||
|
gDOMContentLoaded = true;
|
||||||
|
sendAsyncMessage("DOMContentLoaded");
|
||||||
|
});
|
||||||
|
var gDOMTitleChangedByUs = false;
|
||||||
|
addEventListener("DOMTitleChanged", function(e) {
|
||||||
|
if (!gDOMTitleChangedByUs) {
|
||||||
|
sendAsyncMessage("DOMTitleChanged", {
|
||||||
|
title: e.target.title
|
||||||
|
});
|
||||||
|
gDOMTitleChangedByUs = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Error handling class used to listen for network errors in the social frames
|
// Error handling class used to listen for network errors in the social frames
|
||||||
// and replace them with a social-specific error page
|
// and replace them with a social-specific error page
|
||||||
SocialErrorListener = {
|
SocialErrorListener = {
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener,
|
||||||
|
Ci.nsIWebProgressListener,
|
||||||
Ci.nsISupportsWeakReference,
|
Ci.nsISupportsWeakReference,
|
||||||
Ci.nsISupports]),
|
Ci.nsISupports]),
|
||||||
|
|
||||||
@ -25,21 +41,132 @@ SocialErrorListener = {
|
|||||||
urlTemplate: null,
|
urlTemplate: null,
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
addMessageListener("Loop:MonitorPeerConnectionLifecycle", this);
|
||||||
|
addMessageListener("Loop:GetAllWebrtcStats", this);
|
||||||
|
addMessageListener("Social:CustomEvent", this);
|
||||||
|
addMessageListener("Social:EnsureFocus", this);
|
||||||
|
addMessageListener("Social:EnsureFocusElement", this);
|
||||||
|
addMessageListener("Social:HookWindowCloseForPanelClose", this);
|
||||||
|
addMessageListener("Social:ListenForEvents", this);
|
||||||
|
addMessageListener("Social:SetDocumentTitle", this);
|
||||||
addMessageListener("Social:SetErrorURL", this);
|
addMessageListener("Social:SetErrorURL", this);
|
||||||
|
addMessageListener("Social:WaitForDocumentVisible", this);
|
||||||
|
addMessageListener("WaitForDOMContentLoaded", this);
|
||||||
let webProgress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
let webProgress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||||
.getInterface(Components.interfaces.nsIWebProgress);
|
.getInterface(Components.interfaces.nsIWebProgress);
|
||||||
webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_REQUEST |
|
webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_REQUEST |
|
||||||
Ci.nsIWebProgress.NOTIFY_LOCATION);
|
Ci.nsIWebProgress.NOTIFY_LOCATION);
|
||||||
},
|
},
|
||||||
|
|
||||||
receiveMessage(message) {
|
receiveMessage(message) {
|
||||||
switch(message.name) {
|
let document = content.document;
|
||||||
case "Social:SetErrorURL": {
|
|
||||||
// either a url or null to reset to default template
|
switch (message.name) {
|
||||||
this.urlTemplate = message.objects.template;
|
case "Loop:GetAllWebrtcStats":
|
||||||
}
|
content.WebrtcGlobalInformation.getAllStats(allStats => {
|
||||||
|
content.WebrtcGlobalInformation.getLogging("", logs => {
|
||||||
|
sendAsyncMessage("Loop:GetAllWebrtcStats", {
|
||||||
|
allStats: allStats,
|
||||||
|
logs: logs
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, message.data.peerConnectionID);
|
||||||
|
break;
|
||||||
|
case "Loop:MonitorPeerConnectionLifecycle":
|
||||||
|
let ourID = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
|
||||||
|
|
||||||
|
let onPCLifecycleChange = (pc, winID, type) => {
|
||||||
|
if (winID != ourID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendAsyncMessage("Loop:PeerConnectionLifecycleChange", {
|
||||||
|
iceConnectionState: pc.iceConnectionState,
|
||||||
|
locationHash: content.location.hash,
|
||||||
|
peerConnectionID: pc.id,
|
||||||
|
type: type
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let pc_static = new content.RTCPeerConnectionStatic();
|
||||||
|
pc_static.registerPeerConnectionLifecycleCallback(onPCLifecycleChange);
|
||||||
|
break;
|
||||||
|
case "Social:CustomEvent":
|
||||||
|
let ev = new content.CustomEvent(message.data.name, message.data.detail ?
|
||||||
|
{ detail: message.data.detail } : null);
|
||||||
|
content.dispatchEvent(ev);
|
||||||
|
break;
|
||||||
|
case "Social:EnsureFocus":
|
||||||
|
Services.focus.focusedWindow = content;
|
||||||
|
break;
|
||||||
|
case "Social:EnsureFocusElement":
|
||||||
|
let fm = Services.focus;
|
||||||
|
fm.moveFocus(document.defaultView, null, fm.MOVEFOCUS_FIRST, fm.FLAG_NOSCROLL);
|
||||||
|
break;
|
||||||
|
case "Social:HookWindowCloseForPanelClose":
|
||||||
|
// We allow window.close() to close the panel, so add an event handler for
|
||||||
|
// this, then cancel the event (so the window itself doesn't die) and
|
||||||
|
// close the panel instead.
|
||||||
|
// However, this is typically affected by the dom.allow_scripts_to_close_windows
|
||||||
|
// preference, but we can avoid that check by setting a flag on the window.
|
||||||
|
let dwu = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDOMWindowUtils);
|
||||||
|
dwu.allowScriptsToClose();
|
||||||
|
|
||||||
|
content.addEventListener("DOMWindowClose", function _mozSocialDOMWindowClose(evt) {
|
||||||
|
sendAsyncMessage("DOMWindowClose");
|
||||||
|
// preventDefault stops the default window.close() function being called,
|
||||||
|
// which doesn't actually close anything but causes things to get into
|
||||||
|
// a bad state (an internal 'closed' flag is set and debug builds start
|
||||||
|
// asserting as the window is used.).
|
||||||
|
// None of the windows we inject this API into are suitable for this
|
||||||
|
// default close behaviour, so even if we took no action above, we avoid
|
||||||
|
// the default close from doing anything.
|
||||||
|
evt.preventDefault();
|
||||||
|
}, true);
|
||||||
|
break;
|
||||||
|
case "Social:ListenForEvents":
|
||||||
|
for (let eventName of message.data.eventNames) {
|
||||||
|
content.addEventListener(eventName, this);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Social:SetDocumentTitle":
|
||||||
|
let title = message.data.title;
|
||||||
|
if (title && (title = title.trim())) {
|
||||||
|
gDOMTitleChangedByUs = true;
|
||||||
|
document.title = title;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Social:SetErrorURL":
|
||||||
|
// Either a url or null to reset to default template.
|
||||||
|
this.urlTemplate = message.data.template;
|
||||||
|
break;
|
||||||
|
case "Social:WaitForDocumentVisible":
|
||||||
|
if (!document.hidden) {
|
||||||
|
sendAsyncMessage("Social:DocumentVisible");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("visibilitychange", function onVisibilityChanged() {
|
||||||
|
document.removeEventListener("visibilitychange", onVisibilityChanged);
|
||||||
|
sendAsyncMessage("Social:DocumentVisible");
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "WaitForDOMContentLoaded":
|
||||||
|
if (gDOMContentLoaded) {
|
||||||
|
sendAsyncMessage("DOMContentLoaded");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleEvent: function(event) {
|
||||||
|
sendAsyncMessage("Social:CustomEvent", {
|
||||||
|
name: event.type
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
setErrorPage() {
|
setErrorPage() {
|
||||||
// if this is about:providerdirectory, use the directory iframe
|
// if this is about:providerdirectory, use the directory iframe
|
||||||
let frame = docShell.chromeEventHandler;
|
let frame = docShell.chromeEventHandler;
|
||||||
|
@ -27,33 +27,51 @@
|
|||||||
<xul:toolbarbutton anonid="close" class="chat-close-button chat-toolbarbutton"
|
<xul:toolbarbutton anonid="close" class="chat-close-button chat-toolbarbutton"
|
||||||
oncommand="document.getBindingParent(this).close();"/>
|
oncommand="document.getBindingParent(this).close();"/>
|
||||||
</xul:hbox>
|
</xul:hbox>
|
||||||
|
<xul:browser anonid="remote-content" class="chat-frame" flex="1"
|
||||||
|
context="contentAreaContextMenu"
|
||||||
|
disableglobalhistory="true"
|
||||||
|
frameType="social"
|
||||||
|
message="true"
|
||||||
|
messagemanagergroup="social"
|
||||||
|
tooltip="aHTMLTooltip"
|
||||||
|
remote="true"
|
||||||
|
xbl:inherits="src,origin"
|
||||||
|
type="content"/>
|
||||||
|
|
||||||
<xul:browser anonid="content" class="chat-frame" flex="1"
|
<xul:browser anonid="content" class="chat-frame" flex="1"
|
||||||
context="contentAreaContextMenu"
|
context="contentAreaContextMenu"
|
||||||
disableglobalhistory="true"
|
disableglobalhistory="true"
|
||||||
message="true"
|
message="true"
|
||||||
messagemanagergroup="social"
|
messagemanagergroup="social"
|
||||||
tooltip="aHTMLTooltip"
|
tooltip="aHTMLTooltip"
|
||||||
xbl:inherits="src,origin" type="content"/>
|
xbl:inherits="src,origin"
|
||||||
|
type="content"/>
|
||||||
</content>
|
</content>
|
||||||
|
|
||||||
<implementation implements="nsIDOMEventListener">
|
<implementation implements="nsIDOMEventListener, nsIMessageListener">
|
||||||
<constructor><![CDATA[
|
<constructor><![CDATA[
|
||||||
const kAnchorMap = new Map([
|
const kAnchorMap = new Map([
|
||||||
["", "notification-"],
|
["", "notification-"],
|
||||||
["webRTC-shareScreen-", ""],
|
["webRTC-shareScreen-", ""],
|
||||||
["webRTC-sharingScreen-", ""]
|
["webRTC-sharingScreen-", ""]
|
||||||
]);
|
]);
|
||||||
for (let [getterPrefix, idPrefix] of kAnchorMap) {
|
const kBrowsers = [
|
||||||
let getter = getterPrefix + "popupnotificationanchor";
|
document.getAnonymousElementByAttribute(this, "anonid", "content"),
|
||||||
let anonid = (idPrefix || getterPrefix) + "icon";
|
document.getAnonymousElementByAttribute(this, "anonid", "remote-content")
|
||||||
this.content.__defineGetter__(getter, () => {
|
];
|
||||||
delete this.content[getter];
|
for (let content of kBrowsers) {
|
||||||
return this.content[getter] = document.getAnonymousElementByAttribute(
|
for (let [getterPrefix, idPrefix] of kAnchorMap) {
|
||||||
this, "anonid", anonid);
|
let getter = getterPrefix + "popupnotificationanchor";
|
||||||
});
|
let anonid = (idPrefix || getterPrefix) + "icon";
|
||||||
|
content.__defineGetter__(getter, () => {
|
||||||
|
delete content[getter];
|
||||||
|
return content[getter] = document.getAnonymousElementByAttribute(
|
||||||
|
this, "anonid", anonid);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let contentWindow = this.contentWindow;
|
let mm = this.content.messageManager;
|
||||||
// process this._callbacks, then set to null so the chatbox creator
|
// process this._callbacks, then set to null so the chatbox creator
|
||||||
// knows to make new callbacks immediately.
|
// knows to make new callbacks immediately.
|
||||||
if (this._callbacks) {
|
if (this._callbacks) {
|
||||||
@ -62,17 +80,18 @@
|
|||||||
}
|
}
|
||||||
this._callbacks = null;
|
this._callbacks = null;
|
||||||
}
|
}
|
||||||
this.addEventListener("DOMContentLoaded", function DOMContentLoaded(event) {
|
|
||||||
if (event.target != this.contentDocument)
|
mm.addMessageListener("DOMTitleChanged", this);
|
||||||
return;
|
|
||||||
this.removeEventListener("DOMContentLoaded", DOMContentLoaded, true);
|
mm.sendAsyncMessage("WaitForDOMContentLoaded");
|
||||||
|
mm.addMessageListener("DOMContentLoaded", function DOMContentLoaded(event) {
|
||||||
|
mm.removeMessageListener("DOMContentLoaded", DOMContentLoaded);
|
||||||
this.isActive = !this.minimized;
|
this.isActive = !this.minimized;
|
||||||
this._chat.loadButtonSet(this, this.getAttribute("buttonSet"));
|
this._chat.loadButtonSet(this, this.getAttribute("buttonSet"));
|
||||||
this._deferredChatLoaded.resolve(this);
|
this._deferredChatLoaded.resolve(this);
|
||||||
}, true);
|
}.bind(this));
|
||||||
|
|
||||||
if (this.src)
|
this.setActiveBrowser();
|
||||||
this.setAttribute("src", this.src);
|
|
||||||
]]></constructor>
|
]]></constructor>
|
||||||
|
|
||||||
<field name="_deferredChatLoaded" readonly="true">
|
<field name="_deferredChatLoaded" readonly="true">
|
||||||
@ -85,26 +104,17 @@
|
|||||||
</getter>
|
</getter>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
<field name="content" readonly="true">
|
<property name="content">
|
||||||
document.getAnonymousElementByAttribute(this, "anonid", "content");
|
<getter>
|
||||||
</field>
|
return document.getAnonymousElementByAttribute(this, "anonid",
|
||||||
|
(this.remote ? "remote-" : "") + "content");
|
||||||
|
</getter>
|
||||||
|
</property>
|
||||||
|
|
||||||
<field name="_chat" readonly="true">
|
<field name="_chat" readonly="true">
|
||||||
Cu.import("resource:///modules/Chat.jsm", {}).Chat;
|
Cu.import("resource:///modules/Chat.jsm", {}).Chat;
|
||||||
</field>
|
</field>
|
||||||
|
|
||||||
<property name="contentWindow">
|
|
||||||
<getter>
|
|
||||||
return this.content.contentWindow;
|
|
||||||
</getter>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<property name="contentDocument">
|
|
||||||
<getter>
|
|
||||||
return this.content.contentDocument;
|
|
||||||
</getter>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<property name="minimized">
|
<property name="minimized">
|
||||||
<getter>
|
<getter>
|
||||||
return this.getAttribute("minimized") == "true";
|
return this.getAttribute("minimized") == "true";
|
||||||
@ -143,12 +153,41 @@
|
|||||||
this.content.docShellIsActive = !!val;
|
this.content.docShellIsActive = !!val;
|
||||||
|
|
||||||
// let the chat frame know if it is being shown or hidden
|
// let the chat frame know if it is being shown or hidden
|
||||||
let evt = this.contentDocument.createEvent("CustomEvent");
|
this.content.messageManager.sendAsyncMessage("Social:CustomEvent", {
|
||||||
evt.initCustomEvent(val ? "socialFrameShow" : "socialFrameHide", true, true, {});
|
name: val ? "socialFrameShow" : "socialFrameHide"
|
||||||
this.contentDocument.documentElement.dispatchEvent(evt);
|
});
|
||||||
</setter>
|
</setter>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<field name="_remote">false</field>
|
||||||
|
<property name="remote" onget="return this._remote;">
|
||||||
|
<setter><![CDATA[
|
||||||
|
this._remote = !!val;
|
||||||
|
|
||||||
|
this.setActiveBrowser();
|
||||||
|
]]></setter>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<method name="setActiveBrowser">
|
||||||
|
<body><![CDATA[
|
||||||
|
// Make sure we only show one browser element at a time.
|
||||||
|
let content = document.getAnonymousElementByAttribute(this, "anonid", "content");
|
||||||
|
let remoteContent = document.getAnonymousElementByAttribute(this, "anonid", "remote-content");
|
||||||
|
remoteContent.setAttribute("hidden", !this.remote);
|
||||||
|
content.setAttribute("hidden", this.remote);
|
||||||
|
remoteContent.removeAttribute("src");
|
||||||
|
content.removeAttribute("src");
|
||||||
|
|
||||||
|
if (this.src) {
|
||||||
|
this.setAttribute("src", this.src);
|
||||||
|
|
||||||
|
// Stop loading of the document - that is set before this method was
|
||||||
|
// called - in the now hidden browser.
|
||||||
|
(this.remote ? content : remoteContent).setAttribute("src", "about:blank");
|
||||||
|
}
|
||||||
|
]]></body>
|
||||||
|
</method>
|
||||||
|
|
||||||
<method name="showNotifications">
|
<method name="showNotifications">
|
||||||
<parameter name="aAnchor"/>
|
<parameter name="aAnchor"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
@ -160,12 +199,14 @@
|
|||||||
<method name="swapDocShells">
|
<method name="swapDocShells">
|
||||||
<parameter name="aTarget"/>
|
<parameter name="aTarget"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
aTarget.setAttribute("label", this.contentDocument.title);
|
aTarget.setAttribute("label", this.content.contentTitle);
|
||||||
|
|
||||||
|
aTarget.remote = this.remote;
|
||||||
aTarget.src = this.src;
|
aTarget.src = this.src;
|
||||||
aTarget.content.setAttribute("origin", this.content.getAttribute("origin"));
|
let content = aTarget.content;
|
||||||
aTarget.content.popupnotificationanchor.className = this.content.popupnotificationanchor.className;
|
content.setAttribute("origin", this.content.getAttribute("origin"));
|
||||||
aTarget.content.swapDocShells(this.content);
|
content.popupnotificationanchor.className = this.content.popupnotificationanchor.className;
|
||||||
|
content.swapDocShells(this.content);
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
@ -209,7 +250,9 @@
|
|||||||
if (this.chatbar) {
|
if (this.chatbar) {
|
||||||
this.chatbar.detachChatbox(this, { "centerscreen": "yes" }).then(
|
this.chatbar.detachChatbox(this, { "centerscreen": "yes" }).then(
|
||||||
chatbox => {
|
chatbox => {
|
||||||
chatbox.contentWindow.document.title = title;
|
chatbox.content.messageManager.sendAsyncMessage("Social:SetDocumentTitle", {
|
||||||
|
title: title
|
||||||
|
});
|
||||||
deferred.resolve(chatbox);
|
deferred.resolve(chatbox);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -219,11 +262,16 @@
|
|||||||
let win = Chat.findChromeWindowForChats();
|
let win = Chat.findChromeWindowForChats();
|
||||||
let chatbar = win.document.getElementById("pinnedchats");
|
let chatbar = win.document.getElementById("pinnedchats");
|
||||||
let origin = this.content.getAttribute("origin");
|
let origin = this.content.getAttribute("origin");
|
||||||
let cb = chatbar.openChat(origin, title, "about:blank");
|
let cb = chatbar.openChat({
|
||||||
this.setDecorationAttributes(cb);
|
origin: origin,
|
||||||
|
title: title,
|
||||||
|
url: "about:blank"
|
||||||
|
});
|
||||||
|
|
||||||
cb.promiseChatLoaded.then(
|
cb.promiseChatLoaded.then(
|
||||||
() => {
|
() => {
|
||||||
|
this.setDecorationAttributes(cb);
|
||||||
|
|
||||||
this.swapDocShells(cb);
|
this.swapDocShells(cb);
|
||||||
|
|
||||||
chatbar.focus();
|
chatbar.focus();
|
||||||
@ -236,11 +284,9 @@
|
|||||||
chatbar.chatboxForURL.delete("about:blank");
|
chatbar.chatboxForURL.delete("about:blank");
|
||||||
chatbar.chatboxForURL.set(this.src, Cu.getWeakReference(cb));
|
chatbar.chatboxForURL.set(this.src, Cu.getWeakReference(cb));
|
||||||
|
|
||||||
let attachEvent = new cb.contentWindow.CustomEvent("socialFrameAttached", {
|
cb.content.messageManager.sendAsyncMessage("Social:CustomEvent", {
|
||||||
bubbles: true,
|
name: "socialFrameAttached"
|
||||||
cancelable: true,
|
|
||||||
});
|
});
|
||||||
cb.contentDocument.dispatchEvent(attachEvent);
|
|
||||||
|
|
||||||
deferred.resolve(cb);
|
deferred.resolve(cb);
|
||||||
}
|
}
|
||||||
@ -255,6 +301,27 @@
|
|||||||
this.minimized = !this.minimized;
|
this.minimized = !this.minimized;
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
<method name="setTitle">
|
||||||
|
<body><![CDATA[
|
||||||
|
try {
|
||||||
|
this.setAttribute("label", this.content.contentTitle);
|
||||||
|
} catch (ex) {}
|
||||||
|
if (this.chatbar)
|
||||||
|
this.chatbar.updateTitlebar(this);
|
||||||
|
]]></body>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="receiveMessage">
|
||||||
|
<parameter name="aMessage" />
|
||||||
|
<body><![CDATA[
|
||||||
|
switch (aMessage.name) {
|
||||||
|
case "DOMTitleChanged":
|
||||||
|
this.setTitle();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
]]></body>
|
||||||
|
</method>
|
||||||
</implementation>
|
</implementation>
|
||||||
|
|
||||||
<handlers>
|
<handlers>
|
||||||
@ -262,14 +329,13 @@
|
|||||||
if (this.chatbar)
|
if (this.chatbar)
|
||||||
this.chatbar.selectedChat = this;
|
this.chatbar.selectedChat = this;
|
||||||
</handler>
|
</handler>
|
||||||
<handler event="DOMTitleChanged"><![CDATA[
|
<handler event="DOMTitleChanged">
|
||||||
this.setAttribute('label', this.contentDocument.title);
|
this.setTitle();
|
||||||
if (this.chatbar)
|
</handler>
|
||||||
this.chatbar.updateTitlebar(this);
|
|
||||||
]]></handler>
|
|
||||||
<handler event="DOMLinkAdded"><![CDATA[
|
<handler event="DOMLinkAdded"><![CDATA[
|
||||||
// much of this logic is from DOMLinkHandler in browser.js
|
// Much of this logic is from DOMLinkHandler in browser.js.
|
||||||
// this sets the presence icon for a chat user, we simply use favicon style updating
|
// This sets the presence icon for a chat user, we simply use favicon
|
||||||
|
// style updating.
|
||||||
let link = event.originalTarget;
|
let link = event.originalTarget;
|
||||||
let rel = link.rel && link.rel.toLowerCase();
|
let rel = link.rel && link.rel.toLowerCase();
|
||||||
if (!link || !link.ownerDocument || !rel || !link.href)
|
if (!link || !link.ownerDocument || !rel || !link.href)
|
||||||
@ -277,15 +343,17 @@
|
|||||||
if (link.rel.indexOf("icon") < 0)
|
if (link.rel.indexOf("icon") < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let ContentLinkHandler = Cu.import("resource:///modules/ContentLinkHandler.jsm", {}).ContentLinkHandler;
|
let ContentLinkHandler = Cu.import("resource:///modules/ContentLinkHandler.jsm", {})
|
||||||
|
.ContentLinkHandler;
|
||||||
let uri = ContentLinkHandler.getLinkIconURI(link);
|
let uri = ContentLinkHandler.getLinkIconURI(link);
|
||||||
if (!uri)
|
if (!uri)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// we made it this far, use it
|
// We made it this far, use it.
|
||||||
this.setAttribute('image', uri.spec);
|
this.setAttribute("image", uri.spec);
|
||||||
if (this.chatbar)
|
if (this.chatbar)
|
||||||
this.chatbar.updateTitlebar(this);
|
this.chatbar.updateTitlebar(this);
|
||||||
|
break;
|
||||||
]]></handler>
|
]]></handler>
|
||||||
<handler event="transitionend">
|
<handler event="transitionend">
|
||||||
if (this.isActive == this.minimized)
|
if (this.isActive == this.minimized)
|
||||||
@ -328,7 +396,7 @@
|
|||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
if (!this.selectedChat)
|
if (!this.selectedChat)
|
||||||
return;
|
return;
|
||||||
Services.focus.focusedWindow = this.selectedChat.contentWindow;
|
this.selectedChat.content.messageManager.sendAsyncMessage("Social:EnsureFocus");
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
@ -499,7 +567,7 @@
|
|||||||
aChatbox.isActive = false;
|
aChatbox.isActive = false;
|
||||||
let menu = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "menuitem");
|
let menu = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "menuitem");
|
||||||
menu.setAttribute("class", "menuitem-iconic");
|
menu.setAttribute("class", "menuitem-iconic");
|
||||||
menu.setAttribute("label", aChatbox.contentDocument.title);
|
menu.setAttribute("label", aChatbox.content.contentTitle);
|
||||||
menu.setAttribute("image", aChatbox.getAttribute("image"));
|
menu.setAttribute("image", aChatbox.getAttribute("image"));
|
||||||
menu.chat = aChatbox;
|
menu.chat = aChatbox;
|
||||||
this.menuitemMap.set(aChatbox, menu);
|
this.menuitemMap.set(aChatbox, menu);
|
||||||
@ -568,18 +636,16 @@
|
|||||||
</method>
|
</method>
|
||||||
|
|
||||||
<method name="openChat">
|
<method name="openChat">
|
||||||
<parameter name="aOrigin"/>
|
<parameter name="aOptions"/>
|
||||||
<parameter name="aTitle"/>
|
|
||||||
<parameter name="aURL"/>
|
|
||||||
<parameter name="aMode"/>
|
|
||||||
<parameter name="aCallback"/>
|
<parameter name="aCallback"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
let cb = this.chatboxForURL.get(aURL);
|
let {origin, title, url, mode} = aOptions;
|
||||||
|
let cb = this.chatboxForURL.get(url);
|
||||||
if (cb && (cb = cb.get())) {
|
if (cb && (cb = cb.get())) {
|
||||||
// A chatbox is still alive to us when it's parented and still has
|
// A chatbox is still alive to us when it's parented and still has
|
||||||
// content.
|
// content.
|
||||||
if (cb.parentNode && cb.contentWindow) {
|
if (cb.parentNode) {
|
||||||
this.showChat(cb, aMode);
|
this.showChat(cb, mode);
|
||||||
if (aCallback) {
|
if (aCallback) {
|
||||||
if (cb._callbacks == null) {
|
if (cb._callbacks == null) {
|
||||||
// Chatbox has already been created, so callback now.
|
// Chatbox has already been created, so callback now.
|
||||||
@ -591,7 +657,7 @@
|
|||||||
}
|
}
|
||||||
return cb;
|
return cb;
|
||||||
}
|
}
|
||||||
this.chatboxForURL.delete(aURL);
|
this.chatboxForURL.delete(url);
|
||||||
}
|
}
|
||||||
cb = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "chatbox");
|
cb = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "chatbox");
|
||||||
cb._callbacks = [];
|
cb._callbacks = [];
|
||||||
@ -600,15 +666,17 @@
|
|||||||
// must exist before the (possibly delayed) bindings are created.
|
// must exist before the (possibly delayed) bindings are created.
|
||||||
cb._callbacks.push(aCallback);
|
cb._callbacks.push(aCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cb.remote = !!aOptions.remote;
|
||||||
// src also a javascript property; the src attribute is set in the ctor.
|
// src also a javascript property; the src attribute is set in the ctor.
|
||||||
cb.src = aURL;
|
cb.src = url;
|
||||||
if (aMode == "minimized")
|
if (mode == "minimized")
|
||||||
cb.setAttribute("minimized", "true");
|
cb.setAttribute("minimized", "true");
|
||||||
cb.setAttribute("origin", aOrigin);
|
cb.setAttribute("origin", origin);
|
||||||
cb.setAttribute("label", aTitle);
|
cb.setAttribute("label", title);
|
||||||
this.insertBefore(cb, this.firstChild);
|
this.insertBefore(cb, this.firstChild);
|
||||||
this.selectedChat = cb;
|
this.selectedChat = cb;
|
||||||
this.chatboxForURL.set(aURL, Cu.getWeakReference(cb));
|
this.chatboxForURL.set(url, Cu.getWeakReference(cb));
|
||||||
this.resize();
|
this.resize();
|
||||||
return cb;
|
return cb;
|
||||||
]]></body>
|
]]></body>
|
||||||
@ -714,21 +782,18 @@
|
|||||||
setAttribute("customSize", aChatbox.getAttribute("customSize"));
|
setAttribute("customSize", aChatbox.getAttribute("customSize"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let document = aChatbox.contentDocument;
|
|
||||||
let detachEvent = new aChatbox.contentWindow.CustomEvent("socialFrameDetached", {
|
|
||||||
bubbles: true,
|
|
||||||
cancelable: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
otherWin.removeEventListener("load", _chatLoad, true);
|
otherWin.removeEventListener("load", _chatLoad, true);
|
||||||
let otherChatbox = otherWin.document.getElementById("chatter");
|
let otherChatbox = otherWin.document.getElementById("chatter");
|
||||||
aChatbox.setDecorationAttributes(otherChatbox);
|
aChatbox.setDecorationAttributes(otherChatbox);
|
||||||
aChatbox.swapDocShells(otherChatbox);
|
aChatbox.swapDocShells(otherChatbox);
|
||||||
|
|
||||||
aChatbox.close();
|
aChatbox.close();
|
||||||
chatbar.chatboxForURL.set(aChatbox.src, Cu.getWeakReference(otherChatbox));
|
chatbar.chatboxForURL.set(aChatbox.src, Cu.getWeakReference(otherChatbox));
|
||||||
|
|
||||||
// All processing is done, now we can fire the event.
|
// All processing is done, now we can fire the event.
|
||||||
document.dispatchEvent(detachEvent);
|
otherChatbox.content.messageManager.sendAsyncMessage("Social:CustomEvent", {
|
||||||
|
name: "socialFrameDetached"
|
||||||
|
});
|
||||||
|
|
||||||
deferred.resolve(otherChatbox);
|
deferred.resolve(otherChatbox);
|
||||||
}, true);
|
}, true);
|
||||||
|
@ -28,7 +28,13 @@ function promiseOpenChat(url, mode, focus, buttonSet = null) {
|
|||||||
deferred.resolve(chatbox);
|
deferred.resolve(chatbox);
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
let chatbox = Chat.open(null, origin, title, url, mode, focus, callback);
|
let chatbox = Chat.open(null, {
|
||||||
|
origin: origin,
|
||||||
|
title: title,
|
||||||
|
url: url,
|
||||||
|
mode: mode,
|
||||||
|
focus: focus
|
||||||
|
}, callback);
|
||||||
if (buttonSet) {
|
if (buttonSet) {
|
||||||
chatbox.setAttribute("buttonSet", buttonSet);
|
chatbox.setAttribute("buttonSet", buttonSet);
|
||||||
}
|
}
|
||||||
@ -42,7 +48,12 @@ function promiseOpenChatCallback(url, mode) {
|
|||||||
let title = origin;
|
let title = origin;
|
||||||
let deferred = Promise.defer();
|
let deferred = Promise.defer();
|
||||||
let callback = deferred.resolve;
|
let callback = deferred.resolve;
|
||||||
Chat.open(null, origin, title, url, mode, undefined, callback);
|
Chat.open(null, {
|
||||||
|
origin: origin,
|
||||||
|
title: title,
|
||||||
|
url: url,
|
||||||
|
mode: mode
|
||||||
|
}, callback);
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,13 +40,12 @@ function openChatViaWorkerMessage(port, data, callback) {
|
|||||||
// so the child has been added, but we don't know if it
|
// so the child has been added, but we don't know if it
|
||||||
// has been intialized - re-request it and the callback
|
// has been intialized - re-request it and the callback
|
||||||
// means it's done. Minimized, same as the worker.
|
// means it's done. Minimized, same as the worker.
|
||||||
chatbar.openChat(SocialSidebar.provider.origin,
|
chatbar.openChat({
|
||||||
SocialSidebar.provider.name,
|
origin: SocialSidebar.provider.origin,
|
||||||
data,
|
title: SocialSidebar.provider.name,
|
||||||
"minimized",
|
url: data,
|
||||||
function() {
|
mode: "minimized"
|
||||||
callback();
|
}, function() { callback(); });
|
||||||
});
|
|
||||||
},
|
},
|
||||||
"No new chat appeared");
|
"No new chat appeared");
|
||||||
}
|
}
|
||||||
|
@ -92,27 +92,35 @@ var Chat = {
|
|||||||
*
|
*
|
||||||
* @param contentWindow [optional]
|
* @param contentWindow [optional]
|
||||||
* The content window that requested this chat. May be null.
|
* The content window that requested this chat. May be null.
|
||||||
* @param origin
|
* @param options
|
||||||
|
* Object that may contain the following properties:
|
||||||
|
* - origin
|
||||||
* The origin for the chat. This is primarily used as an identifier
|
* The origin for the chat. This is primarily used as an identifier
|
||||||
* to help identify all chats from the same provider.
|
* to help identify all chats from the same provider.
|
||||||
* @param title
|
* - title
|
||||||
* The title to be used if a new chat window is created.
|
* The title to be used if a new chat window is created.
|
||||||
* @param url
|
* - url
|
||||||
* The URL for the that. Should be under the origin. If an existing
|
* The URL for the that. Should be under the origin. If an existing
|
||||||
* chatbox exists with the same URL, it will be reused and returned.
|
* chatbox exists with the same URL, it will be reused and returned.
|
||||||
* @param mode [optional]
|
* - mode [optional]
|
||||||
* May be undefined or 'minimized'
|
* May be undefined or 'minimized'
|
||||||
* @param focus [optional]
|
* - focus [optional]
|
||||||
* Indicates if the chatbox should be focused. If undefined the chat
|
* Indicates if the chatbox should be focused. If undefined the chat
|
||||||
* will be focused if the window is currently handling user input (ie,
|
* will be focused if the window is currently handling user input (ie,
|
||||||
* if the chat is being opened as a direct result of user input)
|
* if the chat is being opened as a direct result of user input)
|
||||||
|
* - remote [optional]
|
||||||
|
* Indicates if the chatbox browser should use the remote bindings
|
||||||
|
* to run in the content process when TRUE.
|
||||||
|
* @param callback
|
||||||
|
* Function to be invoked once the chat constructed. The chatbox binding
|
||||||
|
* is passed as the first argument.
|
||||||
|
*
|
||||||
* @return A chatbox binding. This binding has a number of promises which
|
* @return A chatbox binding. This binding has a number of promises which
|
||||||
* can be used to determine when the chatbox is being created and
|
* can be used to determine when the chatbox is being created and
|
||||||
* has loaded. Will return null if no chat can be created (Which
|
* has loaded. Will return null if no chat can be created (Which
|
||||||
* should only happen in edge-cases)
|
* should only happen in edge-cases)
|
||||||
*/
|
*/
|
||||||
open: function(contentWindow, origin, title, url, mode, focus, callback) {
|
open: function(contentWindow, options, callback) {
|
||||||
let chromeWindow = this.findChromeWindowForChats(contentWindow);
|
let chromeWindow = this.findChromeWindowForChats(contentWindow);
|
||||||
if (!chromeWindow) {
|
if (!chromeWindow) {
|
||||||
Cu.reportError("Failed to open a chat window - no host window could be found.");
|
Cu.reportError("Failed to open a chat window - no host window could be found.");
|
||||||
@ -121,18 +129,25 @@ var Chat = {
|
|||||||
|
|
||||||
let chatbar = chromeWindow.document.getElementById("pinnedchats");
|
let chatbar = chromeWindow.document.getElementById("pinnedchats");
|
||||||
chatbar.hidden = false;
|
chatbar.hidden = false;
|
||||||
let chatbox = chatbar.openChat(origin, title, url, mode, callback);
|
if (options.remote) {
|
||||||
|
// Double check that current window can handle remote browser elements.
|
||||||
|
let browser = chromeWindow.gBrowser && chromeWindow.gBrowser.selectedBrowser;
|
||||||
|
if (!browser || browser.getAttribute("remote") != "true") {
|
||||||
|
options.remote = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let chatbox = chatbar.openChat(options, callback);
|
||||||
// getAttention is ignored if the target window is already foreground, so
|
// getAttention is ignored if the target window is already foreground, so
|
||||||
// we can call it unconditionally.
|
// we can call it unconditionally.
|
||||||
chromeWindow.getAttention();
|
chromeWindow.getAttention();
|
||||||
// If focus is undefined we want automatic focus handling, and only focus
|
// If focus is undefined we want automatic focus handling, and only focus
|
||||||
// if a direct result of user action.
|
// if a direct result of user action.
|
||||||
if (focus === undefined) {
|
if (!("focus" in options)) {
|
||||||
let dwu = chromeWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
let dwu = chromeWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Ci.nsIDOMWindowUtils);
|
.getInterface(Ci.nsIDOMWindowUtils);
|
||||||
focus = dwu.isHandlingUserInput;
|
options.focus = dwu.isHandlingUserInput;
|
||||||
}
|
}
|
||||||
if (focus) {
|
if (options.focus) {
|
||||||
chatbar.focus();
|
chatbar.focus();
|
||||||
}
|
}
|
||||||
return chatbox;
|
return chatbox;
|
||||||
|
@ -81,6 +81,11 @@ var PanelFrameInternal = {
|
|||||||
attrs["message"] = "true";
|
attrs["message"] = "true";
|
||||||
attrs["messagemanagergroup"] = aType;
|
attrs["messagemanagergroup"] = aType;
|
||||||
}
|
}
|
||||||
|
if (aType == "loop") {
|
||||||
|
attrs.message = true;
|
||||||
|
attrs.messagemanagergroup = "social";
|
||||||
|
attrs.autocompletepopup = "PopupAutoComplete";
|
||||||
|
}
|
||||||
for (let [k, v] of Iterator(attrs)) {
|
for (let [k, v] of Iterator(attrs)) {
|
||||||
frame.setAttribute(k, v);
|
frame.setAttribute(k, v);
|
||||||
}
|
}
|
||||||
@ -127,6 +132,9 @@ var PanelFrame = {
|
|||||||
let notificationFrameId = aToolbarButton.getAttribute("notificationFrameId");
|
let notificationFrameId = aToolbarButton.getAttribute("notificationFrameId");
|
||||||
let notificationFrame = aWindow.document.getElementById(notificationFrameId);
|
let notificationFrame = aWindow.document.getElementById(notificationFrameId);
|
||||||
|
|
||||||
|
// the xbl bindings for the iframe probably don't exist yet, so we can't
|
||||||
|
// access iframe.messageManager directly - but can get at it with this dance.
|
||||||
|
let mm = notificationFrame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
|
||||||
|
|
||||||
// Clear dimensions on all browsers so the panel size will
|
// Clear dimensions on all browsers so the panel size will
|
||||||
// only use the selected browser.
|
// only use the selected browser.
|
||||||
@ -137,9 +145,7 @@ var PanelFrame = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function dispatchPanelEvent(name) {
|
function dispatchPanelEvent(name) {
|
||||||
let evt = notificationFrame.contentDocument.createEvent("CustomEvent");
|
mm.sendAsyncMessage("Social:CustomEvent", { name: name });
|
||||||
evt.initCustomEvent(name, true, true, {});
|
|
||||||
notificationFrame.contentDocument.documentElement.dispatchEvent(evt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we only use a dynamic resizer when we're located the toolbar.
|
// we only use a dynamic resizer when we're located the toolbar.
|
||||||
@ -152,35 +158,28 @@ var PanelFrame = {
|
|||||||
anchorBtn.removeAttribute("open");
|
anchorBtn.removeAttribute("open");
|
||||||
if (dynamicResizer)
|
if (dynamicResizer)
|
||||||
dynamicResizer.stop();
|
dynamicResizer.stop();
|
||||||
notificationFrame.docShell.isActive = false;
|
notificationFrame.docShellIsActive = false;
|
||||||
dispatchPanelEvent(aType + "FrameHide");
|
dispatchPanelEvent(aType + "FrameHide");
|
||||||
});
|
});
|
||||||
|
|
||||||
panel.addEventListener("popupshown", function onpopupshown() {
|
panel.addEventListener("popupshown", function onpopupshown() {
|
||||||
panel.removeEventListener("popupshown", onpopupshown);
|
panel.removeEventListener("popupshown", onpopupshown);
|
||||||
let initFrameShow = () => {
|
|
||||||
notificationFrame.docShell.isActive = true;
|
|
||||||
notificationFrame.docShell.isAppTab = true;
|
|
||||||
if (dynamicResizer)
|
|
||||||
dynamicResizer.start(panel, notificationFrame);
|
|
||||||
dispatchPanelEvent(aType + "FrameShow");
|
|
||||||
};
|
|
||||||
// This attribute is needed on both the button and the
|
// This attribute is needed on both the button and the
|
||||||
// containing toolbaritem since the buttons on OS X have
|
// containing toolbaritem since the buttons on OS X have
|
||||||
// moz-appearance:none, while their container gets
|
// moz-appearance:none, while their container gets
|
||||||
// moz-appearance:toolbarbutton due to the way that toolbar buttons
|
// moz-appearance:toolbarbutton due to the way that toolbar buttons
|
||||||
// get combined on OS X.
|
// get combined on OS X.
|
||||||
anchorBtn.setAttribute("open", "true");
|
anchorBtn.setAttribute("open", "true");
|
||||||
if (notificationFrame.contentDocument &&
|
|
||||||
notificationFrame.contentDocument.readyState == "complete") {
|
mm.sendAsyncMessage("WaitForDOMContentLoaded");
|
||||||
initFrameShow();
|
mm.addMessageListener("DOMContentLoaded", function onloaded() {
|
||||||
} else {
|
mm.removeMessageListener("DOMContentLoaded", onloaded);
|
||||||
// first time load, wait for load and dispatch after load
|
mm = notificationFrame.messageManager;
|
||||||
notificationFrame.addEventListener("load", function panelBrowserOnload(e) {
|
notificationFrame.docShellIsActive = true;
|
||||||
notificationFrame.removeEventListener("load", panelBrowserOnload, true);
|
if (dynamicResizer)
|
||||||
initFrameShow();
|
dynamicResizer.start(panel, notificationFrame);
|
||||||
}, true);
|
dispatchPanelEvent(aType + "FrameShow");
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let anchor = aWindow.document.getAnonymousElementByAttribute(anchorBtn, "class", "toolbarbutton-icon");
|
let anchor = aWindow.document.getAnonymousElementByAttribute(anchorBtn, "class", "toolbarbutton-icon");
|
||||||
|
@ -242,6 +242,17 @@ function attachToWindow(provider, targetWindow) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function hookWindowCloseForPanelClose(targetWindow) {
|
function hookWindowCloseForPanelClose(targetWindow) {
|
||||||
|
let _mozSocialDOMWindowClose;
|
||||||
|
|
||||||
|
if ("messageManager" in targetWindow) {
|
||||||
|
let mm = targetWindow.messageManager;
|
||||||
|
mm.sendAsyncMessage("Social:HookWindowCloseForPanelClose");
|
||||||
|
mm.addMessageListener("DOMWindowClose", _mozSocialDOMWindowClose = function() {
|
||||||
|
closePanel(targetWindow);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We allow window.close() to close the panel, so add an event handler for
|
// We allow window.close() to close the panel, so add an event handler for
|
||||||
// this, then cancel the event (so the window itself doesn't die) and
|
// this, then cancel the event (so the window itself doesn't die) and
|
||||||
// close the panel instead.
|
// close the panel instead.
|
||||||
@ -251,21 +262,12 @@ function hookWindowCloseForPanelClose(targetWindow) {
|
|||||||
.getInterface(Ci.nsIDOMWindowUtils);
|
.getInterface(Ci.nsIDOMWindowUtils);
|
||||||
dwu.allowScriptsToClose();
|
dwu.allowScriptsToClose();
|
||||||
|
|
||||||
targetWindow.addEventListener("DOMWindowClose", function _mozSocialDOMWindowClose(evt) {
|
targetWindow.addEventListener("DOMWindowClose", _mozSocialDOMWindowClose = function(evt) {
|
||||||
let elt = targetWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
let elt = targetWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Ci.nsIWebNavigation)
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
.QueryInterface(Ci.nsIDocShell)
|
.QueryInterface(Ci.nsIDocShell)
|
||||||
.chromeEventHandler;
|
.chromeEventHandler;
|
||||||
while (elt) {
|
closePanel(elt);
|
||||||
if (elt.localName == "panel") {
|
|
||||||
elt.hidePopup();
|
|
||||||
break;
|
|
||||||
} else if (elt.localName == "chatbox") {
|
|
||||||
elt.close();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
elt = elt.parentNode;
|
|
||||||
}
|
|
||||||
// preventDefault stops the default window.close() function being called,
|
// preventDefault stops the default window.close() function being called,
|
||||||
// which doesn't actually close anything but causes things to get into
|
// which doesn't actually close anything but causes things to get into
|
||||||
// a bad state (an internal 'closed' flag is set and debug builds start
|
// a bad state (an internal 'closed' flag is set and debug builds start
|
||||||
@ -277,6 +279,19 @@ function hookWindowCloseForPanelClose(targetWindow) {
|
|||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function closePanel(elt) {
|
||||||
|
while (elt) {
|
||||||
|
if (elt.localName == "panel") {
|
||||||
|
elt.hidePopup();
|
||||||
|
break;
|
||||||
|
} else if (elt.localName == "chatbox") {
|
||||||
|
elt.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
elt = elt.parentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function schedule(callback) {
|
function schedule(callback) {
|
||||||
Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
|
Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
@ -298,11 +313,15 @@ this.openChatWindow =
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let chatbox = Chat.open(contentWindow, provider.origin, provider.name,
|
let chatbox = Chat.open(contentWindow, {
|
||||||
fullURI.spec, mode);
|
origin: provider.origin,
|
||||||
|
title: provider.name,
|
||||||
|
url: fullURI.spec,
|
||||||
|
mode: mode
|
||||||
|
});
|
||||||
if (callback) {
|
if (callback) {
|
||||||
chatbox.promiseChatLoaded.then(() => {
|
chatbox.promiseChatLoaded.then(() => {
|
||||||
callback(chatbox.contentWindow);
|
callback(chatbox);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -599,7 +599,7 @@ var outerWindowID = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
|||||||
.getInterface(Ci.nsIDOMWindowUtils)
|
.getInterface(Ci.nsIDOMWindowUtils)
|
||||||
.outerWindowID;
|
.outerWindowID;
|
||||||
var initData = sendSyncMessage("Browser:Init", {outerWindowID: outerWindowID});
|
var initData = sendSyncMessage("Browser:Init", {outerWindowID: outerWindowID});
|
||||||
if (initData.length) {
|
if (initData.length && initData[0]) {
|
||||||
docShell.useGlobalHistory = initData[0].useGlobalHistory;
|
docShell.useGlobalHistory = initData[0].useGlobalHistory;
|
||||||
if (initData[0].initPopup) {
|
if (initData[0].initPopup) {
|
||||||
setTimeout(() => AutoCompletePopup.init(), 0);
|
setTimeout(() => AutoCompletePopup.init(), 0);
|
||||||
|
@ -1207,8 +1207,13 @@
|
|||||||
if (window.PopupNotifications)
|
if (window.PopupNotifications)
|
||||||
PopupNotifications._swapBrowserNotifications(aOtherBrowser, this);
|
PopupNotifications._swapBrowserNotifications(aOtherBrowser, this);
|
||||||
|
|
||||||
this.QueryInterface(Components.interfaces.nsIFrameLoaderOwner)
|
try {
|
||||||
.swapFrameLoaders(aOtherBrowser);
|
this.QueryInterface(Components.interfaces.nsIFrameLoaderOwner)
|
||||||
|
.swapFrameLoaders(aOtherBrowser);
|
||||||
|
} catch(ex) {
|
||||||
|
// This may not be implemented for browser elements that are not
|
||||||
|
// attached to a BrowserDOMWindow.
|
||||||
|
}
|
||||||
|
|
||||||
// Before we swap the actual docShell property we need to detach the
|
// Before we swap the actual docShell property we need to detach the
|
||||||
// form fill controller from those docShells.
|
// form fill controller from those docShells.
|
||||||
@ -1237,8 +1242,10 @@
|
|||||||
this._remoteWebNavigationImpl.swapBrowser(this);
|
this._remoteWebNavigationImpl.swapBrowser(this);
|
||||||
aOtherBrowser._remoteWebNavigationImpl.swapBrowser(aOtherBrowser);
|
aOtherBrowser._remoteWebNavigationImpl.swapBrowser(aOtherBrowser);
|
||||||
|
|
||||||
this._remoteWebProgressManager.swapBrowser(this);
|
if (this._remoteWebProgressManager && aOtherBrowser._remoteWebProgressManager) {
|
||||||
aOtherBrowser._remoteWebProgressManager.swapBrowser(aOtherBrowser);
|
this._remoteWebProgressManager.swapBrowser(this);
|
||||||
|
aOtherBrowser._remoteWebProgressManager.swapBrowser(aOtherBrowser);
|
||||||
|
}
|
||||||
|
|
||||||
if (this._remoteFinder)
|
if (this._remoteFinder)
|
||||||
this._remoteFinder.swapBrowser(this);
|
this._remoteFinder.swapBrowser(this);
|
||||||
|
@ -390,7 +390,12 @@
|
|||||||
return;
|
return;
|
||||||
this.mDestroyed = true;
|
this.mDestroyed = true;
|
||||||
|
|
||||||
this.controllers.removeController(this._controller);
|
try {
|
||||||
|
this.controllers.removeController(this._controller);
|
||||||
|
} catch (ex) {
|
||||||
|
// This can fail when this browser element is not attached to a
|
||||||
|
// BrowserDOMWindow.
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.hasAttribute("disablehistory")) {
|
if (!this.hasAttribute("disablehistory")) {
|
||||||
try {
|
try {
|
||||||
|
Loading…
Reference in New Issue
Block a user