зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1153016 split content.js in two, one tabbrowser dependent, the other independent, r=mossop
This commit is contained in:
Родитель
76a284caf9
Коммит
fcf99f4b40
|
@ -944,6 +944,7 @@ var gBrowserInit = {
|
|||
DevEdition.init();
|
||||
|
||||
let mm = window.getGroupMessageManager("browsers");
|
||||
mm.loadFrameScript("chrome://browser/content/tab-content.js", true);
|
||||
mm.loadFrameScript("chrome://browser/content/content.js", true);
|
||||
mm.loadFrameScript("chrome://browser/content/content-UITour.js", true);
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* This content script should work in any browser or iframe and should not
|
||||
* depend on the frame being contained in tabbrowser. */
|
||||
|
||||
let {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
@ -12,8 +15,6 @@ Cu.import("resource:///modules/ContentObservers.jsm");
|
|||
Cu.import("resource://gre/modules/InlineSpellChecker.jsm");
|
||||
Cu.import("resource://gre/modules/InlineSpellCheckerContent.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "E10SUtils",
|
||||
"resource:///modules/E10SUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
|
||||
"resource://gre/modules/BrowserUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ContentLinkHandler",
|
||||
|
@ -28,28 +29,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
|||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FormSubmitObserver",
|
||||
"resource:///modules/FormSubmitObserver.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AboutReader",
|
||||
"resource://gre/modules/AboutReader.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode",
|
||||
"resource://gre/modules/ReaderMode.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PageMetadata",
|
||||
"resource://gre/modules/PageMetadata.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "SimpleServiceDiscovery", function() {
|
||||
let ssdp = Cu.import("resource://gre/modules/SimpleServiceDiscovery.jsm", {}).SimpleServiceDiscovery;
|
||||
// Register targets
|
||||
ssdp.registerDevice({
|
||||
id: "roku:ecp",
|
||||
target: "roku:ecp",
|
||||
factory: function(aService) {
|
||||
Cu.import("resource://gre/modules/RokuApp.jsm");
|
||||
return new RokuApp(aService);
|
||||
},
|
||||
mirror: true,
|
||||
types: ["video/mp4"],
|
||||
extensions: ["mp4"]
|
||||
});
|
||||
return ssdp;
|
||||
});
|
||||
XPCOMUtils.defineLazyGetter(this, "PageMenuChild", function() {
|
||||
let tmp = {};
|
||||
Cu.import("resource://gre/modules/PageMenu.jsm", tmp);
|
||||
|
@ -62,61 +43,6 @@ var global = this;
|
|||
// Load the form validation popup handler
|
||||
var formSubmitObserver = new FormSubmitObserver(content, this);
|
||||
|
||||
addMessageListener("Browser:HideSessionRestoreButton", function (message) {
|
||||
// Hide session restore button on about:home
|
||||
let doc = content.document;
|
||||
let container;
|
||||
if (doc.documentURI.toLowerCase() == "about:home" &&
|
||||
(container = doc.getElementById("sessionRestoreContainer"))) {
|
||||
container.hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
addMessageListener("Browser:Reload", function(message) {
|
||||
/* First, we'll try to use the session history object to reload so
|
||||
* that framesets are handled properly. If we're in a special
|
||||
* window (such as view-source) that has no session history, fall
|
||||
* back on using the web navigation's reload method.
|
||||
*/
|
||||
|
||||
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
try {
|
||||
let sh = webNav.sessionHistory;
|
||||
if (sh)
|
||||
webNav = sh.QueryInterface(Ci.nsIWebNavigation);
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
let reloadFlags = message.data.flags;
|
||||
let handlingUserInput;
|
||||
try {
|
||||
handlingUserInput = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.setHandlingUserInput(message.data.handlingUserInput);
|
||||
webNav.reload(reloadFlags);
|
||||
} catch (e) {
|
||||
} finally {
|
||||
handlingUserInput.destruct();
|
||||
}
|
||||
});
|
||||
|
||||
addMessageListener("MixedContent:ReenableProtection", function() {
|
||||
docShell.mixedContentChannel = null;
|
||||
});
|
||||
|
||||
addMessageListener("SecondScreen:tab-mirror", function(message) {
|
||||
if (!Services.prefs.getBoolPref("browser.casting.enabled")) {
|
||||
return;
|
||||
}
|
||||
let app = SimpleServiceDiscovery.findAppForService(message.data.service);
|
||||
if (app) {
|
||||
let width = content.innerWidth;
|
||||
let height = content.innerHeight;
|
||||
let viewport = {cssWidth: width, cssHeight: height, width: width, height: height};
|
||||
app.mirror(function() {}, content, viewport, function() {}, content);
|
||||
}
|
||||
});
|
||||
|
||||
addMessageListener("ContextMenu:DoCustomCommand", function(message) {
|
||||
PageMenuChild.executeMenu(message.data);
|
||||
});
|
||||
|
@ -338,254 +264,6 @@ let AboutNetErrorListener = {
|
|||
|
||||
AboutNetErrorListener.init(this);
|
||||
|
||||
let AboutHomeListener = {
|
||||
init: function(chromeGlobal) {
|
||||
chromeGlobal.addEventListener('AboutHomeLoad', this, false, true);
|
||||
},
|
||||
|
||||
get isAboutHome() {
|
||||
return content.document.documentURI.toLowerCase() == "about:home";
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
if (!this.isAboutHome) {
|
||||
return;
|
||||
}
|
||||
switch (aEvent.type) {
|
||||
case "AboutHomeLoad":
|
||||
this.onPageLoad();
|
||||
break;
|
||||
case "AboutHomeSearchEvent":
|
||||
this.onSearch(aEvent);
|
||||
break;
|
||||
case "AboutHomeSearchPanel":
|
||||
this.onOpenSearchPanel(aEvent);
|
||||
break;
|
||||
case "click":
|
||||
this.onClick(aEvent);
|
||||
break;
|
||||
case "pagehide":
|
||||
this.onPageHide(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
if (!this.isAboutHome) {
|
||||
return;
|
||||
}
|
||||
switch (aMessage.name) {
|
||||
case "AboutHome:Update":
|
||||
this.onUpdate(aMessage.data);
|
||||
break;
|
||||
case "AboutHome:FocusInput":
|
||||
this.onFocusInput();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onUpdate: function(aData) {
|
||||
let doc = content.document;
|
||||
if (aData.showRestoreLastSession && !PrivateBrowsingUtils.isContentWindowPrivate(content))
|
||||
doc.getElementById("launcher").setAttribute("session", "true");
|
||||
|
||||
// Inject search engine and snippets URL.
|
||||
let docElt = doc.documentElement;
|
||||
// set the following attributes BEFORE searchEngineName, which triggers to
|
||||
// show the snippets when it's set.
|
||||
docElt.setAttribute("snippetsURL", aData.snippetsURL);
|
||||
if (aData.showKnowYourRights)
|
||||
docElt.setAttribute("showKnowYourRights", "true");
|
||||
docElt.setAttribute("snippetsVersion", aData.snippetsVersion);
|
||||
docElt.setAttribute("searchEngineName", aData.defaultEngineName);
|
||||
},
|
||||
|
||||
onPageLoad: function() {
|
||||
let doc = content.document;
|
||||
if (doc.documentElement.hasAttribute("hasBrowserHandlers")) {
|
||||
return;
|
||||
}
|
||||
|
||||
doc.documentElement.setAttribute("hasBrowserHandlers", "true");
|
||||
addMessageListener("AboutHome:Update", this);
|
||||
addMessageListener("AboutHome:FocusInput", this);
|
||||
addEventListener("click", this, true);
|
||||
addEventListener("pagehide", this, true);
|
||||
|
||||
if (!Services.prefs.getBoolPref("browser.search.showOneOffButtons")) {
|
||||
doc.documentElement.setAttribute("searchUIConfiguration", "oldsearchui");
|
||||
}
|
||||
|
||||
sendAsyncMessage("AboutHome:RequestUpdate");
|
||||
doc.addEventListener("AboutHomeSearchEvent", this, true, true);
|
||||
doc.addEventListener("AboutHomeSearchPanel", this, true, true);
|
||||
},
|
||||
|
||||
onClick: function(aEvent) {
|
||||
if (!aEvent.isTrusted || // Don't trust synthetic events
|
||||
aEvent.button == 2 || aEvent.target.localName != "button") {
|
||||
return;
|
||||
}
|
||||
|
||||
let originalTarget = aEvent.originalTarget;
|
||||
let ownerDoc = originalTarget.ownerDocument;
|
||||
if (ownerDoc.documentURI != "about:home") {
|
||||
// This shouldn't happen, but we're being defensive.
|
||||
return;
|
||||
}
|
||||
|
||||
let elmId = originalTarget.getAttribute("id");
|
||||
|
||||
switch (elmId) {
|
||||
case "restorePreviousSession":
|
||||
sendAsyncMessage("AboutHome:RestorePreviousSession");
|
||||
ownerDoc.getElementById("launcher").removeAttribute("session");
|
||||
break;
|
||||
|
||||
case "downloads":
|
||||
sendAsyncMessage("AboutHome:Downloads");
|
||||
break;
|
||||
|
||||
case "bookmarks":
|
||||
sendAsyncMessage("AboutHome:Bookmarks");
|
||||
break;
|
||||
|
||||
case "history":
|
||||
sendAsyncMessage("AboutHome:History");
|
||||
break;
|
||||
|
||||
case "apps":
|
||||
sendAsyncMessage("AboutHome:Apps");
|
||||
break;
|
||||
|
||||
case "addons":
|
||||
sendAsyncMessage("AboutHome:Addons");
|
||||
break;
|
||||
|
||||
case "sync":
|
||||
sendAsyncMessage("AboutHome:Sync");
|
||||
break;
|
||||
|
||||
case "settings":
|
||||
sendAsyncMessage("AboutHome:Settings");
|
||||
break;
|
||||
|
||||
case "searchIcon":
|
||||
sendAsyncMessage("AboutHome:OpenSearchPanel", null, { anchor: originalTarget });
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onPageHide: function(aEvent) {
|
||||
if (aEvent.target.defaultView.frameElement) {
|
||||
return;
|
||||
}
|
||||
removeMessageListener("AboutHome:Update", this);
|
||||
removeEventListener("click", this, true);
|
||||
removeEventListener("pagehide", this, true);
|
||||
if (aEvent.target.documentElement) {
|
||||
aEvent.target.documentElement.removeAttribute("hasBrowserHandlers");
|
||||
}
|
||||
},
|
||||
|
||||
onSearch: function(aEvent) {
|
||||
sendAsyncMessage("AboutHome:Search", { searchData: aEvent.detail });
|
||||
},
|
||||
|
||||
onOpenSearchPanel: function(aEvent) {
|
||||
sendAsyncMessage("AboutHome:OpenSearchPanel");
|
||||
},
|
||||
|
||||
onFocusInput: function () {
|
||||
let searchInput = content.document.getElementById("searchText");
|
||||
if (searchInput) {
|
||||
searchInput.focus();
|
||||
}
|
||||
},
|
||||
};
|
||||
AboutHomeListener.init(this);
|
||||
|
||||
let AboutReaderListener = {
|
||||
|
||||
_articlePromise: null,
|
||||
|
||||
init: function() {
|
||||
addEventListener("AboutReaderContentLoaded", this, false, true);
|
||||
addEventListener("DOMContentLoaded", this, false);
|
||||
addEventListener("pageshow", this, false);
|
||||
addEventListener("pagehide", this, false);
|
||||
addMessageListener("Reader:ParseDocument", this);
|
||||
addMessageListener("Reader:PushState", this);
|
||||
},
|
||||
|
||||
receiveMessage: function(message) {
|
||||
switch (message.name) {
|
||||
case "Reader:ParseDocument":
|
||||
this._articlePromise = ReaderMode.parseDocument(content.document).catch(Cu.reportError);
|
||||
content.document.location = "about:reader?url=" + encodeURIComponent(message.data.url);
|
||||
break;
|
||||
|
||||
case "Reader:PushState":
|
||||
this.updateReaderButton();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
get isAboutReader() {
|
||||
return content.document.documentURI.startsWith("about:reader");
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
if (aEvent.originalTarget.defaultView != content) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aEvent.type) {
|
||||
case "AboutReaderContentLoaded":
|
||||
if (!this.isAboutReader) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (content.document.body) {
|
||||
// Update the toolbar icon to show the "reader active" icon.
|
||||
sendAsyncMessage("Reader:UpdateReaderButton");
|
||||
new AboutReader(global, content, this._articlePromise);
|
||||
this._articlePromise = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case "pagehide":
|
||||
sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: false });
|
||||
break;
|
||||
|
||||
case "pageshow":
|
||||
// If a page is loaded from the bfcache, we won't get a "DOMContentLoaded"
|
||||
// event, so we need to rely on "pageshow" in this case.
|
||||
if (aEvent.persisted) {
|
||||
this.updateReaderButton();
|
||||
}
|
||||
break;
|
||||
case "DOMContentLoaded":
|
||||
this.updateReaderButton();
|
||||
break;
|
||||
|
||||
}
|
||||
},
|
||||
updateReaderButton: function() {
|
||||
if (!ReaderMode.isEnabledForParseOnLoad || this.isAboutReader ||
|
||||
!(content.document instanceof content.HTMLDocument) ||
|
||||
content.document.mozSyntheticDocument) {
|
||||
return;
|
||||
}
|
||||
// Only send updates when there are articles; there's no point updating with
|
||||
// |false| all the time.
|
||||
if (ReaderMode.isProbablyReaderable(content.document)) {
|
||||
sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: true });
|
||||
}
|
||||
},
|
||||
};
|
||||
AboutReaderListener.init();
|
||||
|
||||
// An event listener for custom "WebChannelMessageToChrome" events on pages
|
||||
addEventListener("WebChannelMessageToChrome", function (e) {
|
||||
// if target is window then we want the document principal, otherwise fallback to target itself.
|
||||
|
@ -613,68 +291,6 @@ addMessageListener("WebChannelMessageToContent", function (e) {
|
|||
});
|
||||
|
||||
|
||||
let ContentSearchMediator = {
|
||||
|
||||
whitelist: new Set([
|
||||
"about:home",
|
||||
"about:newtab",
|
||||
]),
|
||||
|
||||
init: function (chromeGlobal) {
|
||||
chromeGlobal.addEventListener("ContentSearchClient", this, true, true);
|
||||
addMessageListener("ContentSearch", this);
|
||||
},
|
||||
|
||||
handleEvent: function (event) {
|
||||
if (this._contentWhitelisted) {
|
||||
this._sendMsg(event.detail.type, event.detail.data);
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function (msg) {
|
||||
if (msg.data.type == "AddToWhitelist") {
|
||||
for (let uri of msg.data.data) {
|
||||
this.whitelist.add(uri);
|
||||
}
|
||||
this._sendMsg("AddToWhitelistAck");
|
||||
return;
|
||||
}
|
||||
if (this._contentWhitelisted) {
|
||||
this._fireEvent(msg.data.type, msg.data.data);
|
||||
}
|
||||
},
|
||||
|
||||
get _contentWhitelisted() {
|
||||
return this.whitelist.has(content.document.documentURI);
|
||||
},
|
||||
|
||||
_sendMsg: function (type, data=null) {
|
||||
sendAsyncMessage("ContentSearch", {
|
||||
type: type,
|
||||
data: data,
|
||||
});
|
||||
},
|
||||
|
||||
_fireEvent: function (type, data=null) {
|
||||
let event = Cu.cloneInto({
|
||||
detail: {
|
||||
type: type,
|
||||
data: data,
|
||||
},
|
||||
}, content);
|
||||
content.dispatchEvent(new content.CustomEvent("ContentSearchService",
|
||||
event));
|
||||
},
|
||||
};
|
||||
ContentSearchMediator.init(this);
|
||||
|
||||
// Lazily load the finder code
|
||||
addMessageListener("Finder:Initialize", function () {
|
||||
let {RemoteFinderListener} = Cu.import("resource://gre/modules/RemoteFinder.jsm", {});
|
||||
new RemoteFinderListener(global);
|
||||
});
|
||||
|
||||
|
||||
let ClickEventHandler = {
|
||||
init: function init() {
|
||||
Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
|
@ -838,146 +454,6 @@ addEventListener("DOMWebNotificationClicked", function(event) {
|
|||
sendAsyncMessage("DOMWebNotificationClicked", {});
|
||||
}, false);
|
||||
|
||||
let PageStyleHandler = {
|
||||
init: function() {
|
||||
addMessageListener("PageStyle:Switch", this);
|
||||
addMessageListener("PageStyle:Disable", this);
|
||||
|
||||
// Send a CPOW to the parent so that it can synchronously request
|
||||
// the list of style sheets.
|
||||
sendSyncMessage("PageStyle:SetSyncHandler", {}, {syncHandler: this});
|
||||
},
|
||||
|
||||
get markupDocumentViewer() {
|
||||
return docShell.contentViewer;
|
||||
},
|
||||
|
||||
// Called synchronously via CPOW from the parent.
|
||||
getStyleSheetInfo: function() {
|
||||
let styleSheets = this._filterStyleSheets(this.getAllStyleSheets());
|
||||
return {
|
||||
styleSheets: styleSheets,
|
||||
authorStyleDisabled: this.markupDocumentViewer.authorStyleDisabled,
|
||||
preferredStyleSheetSet: content.document.preferredStyleSheetSet
|
||||
};
|
||||
},
|
||||
|
||||
// Called synchronously via CPOW from the parent.
|
||||
getAllStyleSheets: function(frameset = content) {
|
||||
let selfSheets = Array.slice(frameset.document.styleSheets);
|
||||
let subSheets = Array.map(frameset.frames, frame => this.getAllStyleSheets(frame));
|
||||
return selfSheets.concat(...subSheets);
|
||||
},
|
||||
|
||||
receiveMessage: function(msg) {
|
||||
switch (msg.name) {
|
||||
case "PageStyle:Switch":
|
||||
this.markupDocumentViewer.authorStyleDisabled = false;
|
||||
this._stylesheetSwitchAll(content, msg.data.title);
|
||||
break;
|
||||
|
||||
case "PageStyle:Disable":
|
||||
this.markupDocumentViewer.authorStyleDisabled = true;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_stylesheetSwitchAll: function (frameset, title) {
|
||||
if (!title || this._stylesheetInFrame(frameset, title)) {
|
||||
this._stylesheetSwitchFrame(frameset, title);
|
||||
}
|
||||
|
||||
for (let i = 0; i < frameset.frames.length; i++) {
|
||||
// Recurse into sub-frames.
|
||||
this._stylesheetSwitchAll(frameset.frames[i], title);
|
||||
}
|
||||
},
|
||||
|
||||
_stylesheetSwitchFrame: function (frame, title) {
|
||||
var docStyleSheets = frame.document.styleSheets;
|
||||
|
||||
for (let i = 0; i < docStyleSheets.length; ++i) {
|
||||
let docStyleSheet = docStyleSheets[i];
|
||||
if (docStyleSheet.title) {
|
||||
docStyleSheet.disabled = (docStyleSheet.title != title);
|
||||
} else if (docStyleSheet.disabled) {
|
||||
docStyleSheet.disabled = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_stylesheetInFrame: function (frame, title) {
|
||||
return Array.some(frame.document.styleSheets, (styleSheet) => styleSheet.title == title);
|
||||
},
|
||||
|
||||
_filterStyleSheets: function(styleSheets) {
|
||||
let result = [];
|
||||
|
||||
for (let currentStyleSheet of styleSheets) {
|
||||
if (!currentStyleSheet.title)
|
||||
continue;
|
||||
|
||||
// Skip any stylesheets that don't match the screen media type.
|
||||
if (currentStyleSheet.media.length > 0) {
|
||||
let mediaQueryList = currentStyleSheet.media.mediaText;
|
||||
if (!content.matchMedia(mediaQueryList).matches) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.push({title: currentStyleSheet.title,
|
||||
disabled: currentStyleSheet.disabled});
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
};
|
||||
PageStyleHandler.init();
|
||||
|
||||
// Keep a reference to the translation content handler to avoid it it being GC'ed.
|
||||
let trHandler = null;
|
||||
if (Services.prefs.getBoolPref("browser.translation.detectLanguage")) {
|
||||
Cu.import("resource:///modules/translation/TranslationContentHandler.jsm");
|
||||
trHandler = new TranslationContentHandler(global, docShell);
|
||||
}
|
||||
|
||||
let DOMFullscreenHandler = {
|
||||
_fullscreenDoc: null,
|
||||
|
||||
init: function() {
|
||||
addMessageListener("DOMFullscreen:Approved", this);
|
||||
addMessageListener("DOMFullscreen:CleanUp", this);
|
||||
addEventListener("MozEnteredDomFullscreen", this);
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
switch(aMessage.name) {
|
||||
case "DOMFullscreen:Approved": {
|
||||
if (this._fullscreenDoc) {
|
||||
Services.obs.notifyObservers(this._fullscreenDoc,
|
||||
"fullscreen-approved",
|
||||
"");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "DOMFullscreen:CleanUp": {
|
||||
this._fullscreenDoc = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
if (aEvent.type == "MozEnteredDomFullscreen") {
|
||||
this._fullscreenDoc = aEvent.target;
|
||||
sendAsyncMessage("MozEnteredDomFullscreen", {
|
||||
origin: this._fullscreenDoc.nodePrincipal.origin,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
DOMFullscreenHandler.init();
|
||||
|
||||
ContentWebRTC.init();
|
||||
addMessageListener("webrtc:Allow", ContentWebRTC);
|
||||
addMessageListener("webrtc:Deny", ContentWebRTC);
|
||||
|
@ -990,59 +466,6 @@ addMessageListener("webrtc:StartBrowserSharing", () => {
|
|||
});
|
||||
});
|
||||
|
||||
function gKeywordURIFixup(fixupInfo) {
|
||||
fixupInfo.QueryInterface(Ci.nsIURIFixupInfo);
|
||||
|
||||
// Ignore info from other docshells
|
||||
let parent = fixupInfo.consumer.QueryInterface(Ci.nsIDocShellTreeItem).sameTypeRootTreeItem;
|
||||
if (parent != docShell)
|
||||
return;
|
||||
|
||||
let data = {};
|
||||
for (let f of Object.keys(fixupInfo)) {
|
||||
if (f == "consumer" || typeof fixupInfo[f] == "function")
|
||||
continue;
|
||||
|
||||
if (fixupInfo[f] && fixupInfo[f] instanceof Ci.nsIURI) {
|
||||
data[f] = fixupInfo[f].spec;
|
||||
} else {
|
||||
data[f] = fixupInfo[f];
|
||||
}
|
||||
}
|
||||
|
||||
sendAsyncMessage("Browser:URIFixup", data);
|
||||
}
|
||||
Services.obs.addObserver(gKeywordURIFixup, "keyword-uri-fixup", false);
|
||||
addEventListener("unload", () => {
|
||||
Services.obs.removeObserver(gKeywordURIFixup, "keyword-uri-fixup");
|
||||
}, false);
|
||||
|
||||
addMessageListener("Browser:AppTab", function(message) {
|
||||
docShell.isAppTab = message.data.isAppTab;
|
||||
});
|
||||
|
||||
let WebBrowserChrome = {
|
||||
onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
|
||||
return BrowserUtils.onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
|
||||
},
|
||||
|
||||
// Check whether this URI should load in the current process
|
||||
shouldLoadURI: function(aDocShell, aURI, aReferrer) {
|
||||
if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aReferrer)) {
|
||||
E10SUtils.redirectLoad(aDocShell, aURI, aReferrer);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
let tabchild = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsITabChild);
|
||||
tabchild.webBrowserChrome = WebBrowserChrome;
|
||||
}
|
||||
|
||||
addEventListener("pageshow", function(event) {
|
||||
if (event.target == content.document) {
|
||||
sendAsyncMessage("PageVisibility:Show", {
|
||||
|
|
|
@ -0,0 +1,596 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* This content script contains code that requires a tab browser. */
|
||||
|
||||
let {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "E10SUtils",
|
||||
"resource:///modules/E10SUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
|
||||
"resource://gre/modules/BrowserUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AboutReader",
|
||||
"resource://gre/modules/AboutReader.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode",
|
||||
"resource://gre/modules/ReaderMode.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "SimpleServiceDiscovery", function() {
|
||||
let ssdp = Cu.import("resource://gre/modules/SimpleServiceDiscovery.jsm", {}).SimpleServiceDiscovery;
|
||||
// Register targets
|
||||
ssdp.registerDevice({
|
||||
id: "roku:ecp",
|
||||
target: "roku:ecp",
|
||||
factory: function(aService) {
|
||||
Cu.import("resource://gre/modules/RokuApp.jsm");
|
||||
return new RokuApp(aService);
|
||||
},
|
||||
mirror: true,
|
||||
types: ["video/mp4"],
|
||||
extensions: ["mp4"]
|
||||
});
|
||||
return ssdp;
|
||||
});
|
||||
|
||||
// TabChildGlobal
|
||||
var global = this;
|
||||
|
||||
|
||||
addMessageListener("Browser:HideSessionRestoreButton", function (message) {
|
||||
// Hide session restore button on about:home
|
||||
let doc = content.document;
|
||||
let container;
|
||||
if (doc.documentURI.toLowerCase() == "about:home" &&
|
||||
(container = doc.getElementById("sessionRestoreContainer"))) {
|
||||
container.hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
addMessageListener("Browser:Reload", function(message) {
|
||||
/* First, we'll try to use the session history object to reload so
|
||||
* that framesets are handled properly. If we're in a special
|
||||
* window (such as view-source) that has no session history, fall
|
||||
* back on using the web navigation's reload method.
|
||||
*/
|
||||
|
||||
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
try {
|
||||
let sh = webNav.sessionHistory;
|
||||
if (sh)
|
||||
webNav = sh.QueryInterface(Ci.nsIWebNavigation);
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
let reloadFlags = message.data.flags;
|
||||
let handlingUserInput;
|
||||
try {
|
||||
handlingUserInput = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.setHandlingUserInput(message.data.handlingUserInput);
|
||||
webNav.reload(reloadFlags);
|
||||
} catch (e) {
|
||||
} finally {
|
||||
handlingUserInput.destruct();
|
||||
}
|
||||
});
|
||||
|
||||
addMessageListener("MixedContent:ReenableProtection", function() {
|
||||
docShell.mixedContentChannel = null;
|
||||
});
|
||||
|
||||
addMessageListener("SecondScreen:tab-mirror", function(message) {
|
||||
if (!Services.prefs.getBoolPref("browser.casting.enabled")) {
|
||||
return;
|
||||
}
|
||||
let app = SimpleServiceDiscovery.findAppForService(message.data.service);
|
||||
if (app) {
|
||||
let width = content.innerWidth;
|
||||
let height = content.innerHeight;
|
||||
let viewport = {cssWidth: width, cssHeight: height, width: width, height: height};
|
||||
app.mirror(function() {}, content, viewport, function() {}, content);
|
||||
}
|
||||
});
|
||||
|
||||
let AboutHomeListener = {
|
||||
init: function(chromeGlobal) {
|
||||
chromeGlobal.addEventListener('AboutHomeLoad', this, false, true);
|
||||
},
|
||||
|
||||
get isAboutHome() {
|
||||
return content.document.documentURI.toLowerCase() == "about:home";
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
if (!this.isAboutHome) {
|
||||
return;
|
||||
}
|
||||
switch (aEvent.type) {
|
||||
case "AboutHomeLoad":
|
||||
this.onPageLoad();
|
||||
break;
|
||||
case "AboutHomeSearchEvent":
|
||||
this.onSearch(aEvent);
|
||||
break;
|
||||
case "AboutHomeSearchPanel":
|
||||
this.onOpenSearchPanel(aEvent);
|
||||
break;
|
||||
case "click":
|
||||
this.onClick(aEvent);
|
||||
break;
|
||||
case "pagehide":
|
||||
this.onPageHide(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
if (!this.isAboutHome) {
|
||||
return;
|
||||
}
|
||||
switch (aMessage.name) {
|
||||
case "AboutHome:Update":
|
||||
this.onUpdate(aMessage.data);
|
||||
break;
|
||||
case "AboutHome:FocusInput":
|
||||
this.onFocusInput();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onUpdate: function(aData) {
|
||||
let doc = content.document;
|
||||
if (aData.showRestoreLastSession && !PrivateBrowsingUtils.isContentWindowPrivate(content))
|
||||
doc.getElementById("launcher").setAttribute("session", "true");
|
||||
|
||||
// Inject search engine and snippets URL.
|
||||
let docElt = doc.documentElement;
|
||||
// set the following attributes BEFORE searchEngineName, which triggers to
|
||||
// show the snippets when it's set.
|
||||
docElt.setAttribute("snippetsURL", aData.snippetsURL);
|
||||
if (aData.showKnowYourRights)
|
||||
docElt.setAttribute("showKnowYourRights", "true");
|
||||
docElt.setAttribute("snippetsVersion", aData.snippetsVersion);
|
||||
docElt.setAttribute("searchEngineName", aData.defaultEngineName);
|
||||
},
|
||||
|
||||
onPageLoad: function() {
|
||||
let doc = content.document;
|
||||
if (doc.documentElement.hasAttribute("hasBrowserHandlers")) {
|
||||
return;
|
||||
}
|
||||
|
||||
doc.documentElement.setAttribute("hasBrowserHandlers", "true");
|
||||
addMessageListener("AboutHome:Update", this);
|
||||
addMessageListener("AboutHome:FocusInput", this);
|
||||
addEventListener("click", this, true);
|
||||
addEventListener("pagehide", this, true);
|
||||
|
||||
if (!Services.prefs.getBoolPref("browser.search.showOneOffButtons")) {
|
||||
doc.documentElement.setAttribute("searchUIConfiguration", "oldsearchui");
|
||||
}
|
||||
|
||||
sendAsyncMessage("AboutHome:RequestUpdate");
|
||||
doc.addEventListener("AboutHomeSearchEvent", this, true, true);
|
||||
doc.addEventListener("AboutHomeSearchPanel", this, true, true);
|
||||
},
|
||||
|
||||
onClick: function(aEvent) {
|
||||
if (!aEvent.isTrusted || // Don't trust synthetic events
|
||||
aEvent.button == 2 || aEvent.target.localName != "button") {
|
||||
return;
|
||||
}
|
||||
|
||||
let originalTarget = aEvent.originalTarget;
|
||||
let ownerDoc = originalTarget.ownerDocument;
|
||||
if (ownerDoc.documentURI != "about:home") {
|
||||
// This shouldn't happen, but we're being defensive.
|
||||
return;
|
||||
}
|
||||
|
||||
let elmId = originalTarget.getAttribute("id");
|
||||
|
||||
switch (elmId) {
|
||||
case "restorePreviousSession":
|
||||
sendAsyncMessage("AboutHome:RestorePreviousSession");
|
||||
ownerDoc.getElementById("launcher").removeAttribute("session");
|
||||
break;
|
||||
|
||||
case "downloads":
|
||||
sendAsyncMessage("AboutHome:Downloads");
|
||||
break;
|
||||
|
||||
case "bookmarks":
|
||||
sendAsyncMessage("AboutHome:Bookmarks");
|
||||
break;
|
||||
|
||||
case "history":
|
||||
sendAsyncMessage("AboutHome:History");
|
||||
break;
|
||||
|
||||
case "apps":
|
||||
sendAsyncMessage("AboutHome:Apps");
|
||||
break;
|
||||
|
||||
case "addons":
|
||||
sendAsyncMessage("AboutHome:Addons");
|
||||
break;
|
||||
|
||||
case "sync":
|
||||
sendAsyncMessage("AboutHome:Sync");
|
||||
break;
|
||||
|
||||
case "settings":
|
||||
sendAsyncMessage("AboutHome:Settings");
|
||||
break;
|
||||
|
||||
case "searchIcon":
|
||||
sendAsyncMessage("AboutHome:OpenSearchPanel", null, { anchor: originalTarget });
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onPageHide: function(aEvent) {
|
||||
if (aEvent.target.defaultView.frameElement) {
|
||||
return;
|
||||
}
|
||||
removeMessageListener("AboutHome:Update", this);
|
||||
removeEventListener("click", this, true);
|
||||
removeEventListener("pagehide", this, true);
|
||||
if (aEvent.target.documentElement) {
|
||||
aEvent.target.documentElement.removeAttribute("hasBrowserHandlers");
|
||||
}
|
||||
},
|
||||
|
||||
onSearch: function(aEvent) {
|
||||
sendAsyncMessage("AboutHome:Search", { searchData: aEvent.detail });
|
||||
},
|
||||
|
||||
onOpenSearchPanel: function(aEvent) {
|
||||
sendAsyncMessage("AboutHome:OpenSearchPanel");
|
||||
},
|
||||
|
||||
onFocusInput: function () {
|
||||
let searchInput = content.document.getElementById("searchText");
|
||||
if (searchInput) {
|
||||
searchInput.focus();
|
||||
}
|
||||
},
|
||||
};
|
||||
AboutHomeListener.init(this);
|
||||
|
||||
let AboutReaderListener = {
|
||||
|
||||
_articlePromise: null,
|
||||
|
||||
init: function() {
|
||||
addEventListener("AboutReaderContentLoaded", this, false, true);
|
||||
addEventListener("DOMContentLoaded", this, false);
|
||||
addEventListener("pageshow", this, false);
|
||||
addEventListener("pagehide", this, false);
|
||||
addMessageListener("Reader:ParseDocument", this);
|
||||
addMessageListener("Reader:PushState", this);
|
||||
},
|
||||
|
||||
receiveMessage: function(message) {
|
||||
switch (message.name) {
|
||||
case "Reader:ParseDocument":
|
||||
this._articlePromise = ReaderMode.parseDocument(content.document).catch(Cu.reportError);
|
||||
content.document.location = "about:reader?url=" + encodeURIComponent(message.data.url);
|
||||
break;
|
||||
|
||||
case "Reader:PushState":
|
||||
this.updateReaderButton();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
get isAboutReader() {
|
||||
return content.document.documentURI.startsWith("about:reader");
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
if (aEvent.originalTarget.defaultView != content) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aEvent.type) {
|
||||
case "AboutReaderContentLoaded":
|
||||
if (!this.isAboutReader) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (content.document.body) {
|
||||
// Update the toolbar icon to show the "reader active" icon.
|
||||
sendAsyncMessage("Reader:UpdateReaderButton");
|
||||
new AboutReader(global, content, this._articlePromise);
|
||||
this._articlePromise = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case "pagehide":
|
||||
sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: false });
|
||||
break;
|
||||
|
||||
case "pageshow":
|
||||
// If a page is loaded from the bfcache, we won't get a "DOMContentLoaded"
|
||||
// event, so we need to rely on "pageshow" in this case.
|
||||
if (aEvent.persisted) {
|
||||
this.updateReaderButton();
|
||||
}
|
||||
break;
|
||||
case "DOMContentLoaded":
|
||||
this.updateReaderButton();
|
||||
break;
|
||||
|
||||
}
|
||||
},
|
||||
updateReaderButton: function() {
|
||||
if (!ReaderMode.isEnabledForParseOnLoad || this.isAboutReader ||
|
||||
!(content.document instanceof content.HTMLDocument) ||
|
||||
content.document.mozSyntheticDocument) {
|
||||
return;
|
||||
}
|
||||
// Only send updates when there are articles; there's no point updating with
|
||||
// |false| all the time.
|
||||
if (ReaderMode.isProbablyReaderable(content.document)) {
|
||||
sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: true });
|
||||
}
|
||||
},
|
||||
};
|
||||
AboutReaderListener.init();
|
||||
|
||||
|
||||
let ContentSearchMediator = {
|
||||
|
||||
whitelist: new Set([
|
||||
"about:home",
|
||||
"about:newtab",
|
||||
]),
|
||||
|
||||
init: function (chromeGlobal) {
|
||||
chromeGlobal.addEventListener("ContentSearchClient", this, true, true);
|
||||
addMessageListener("ContentSearch", this);
|
||||
},
|
||||
|
||||
handleEvent: function (event) {
|
||||
if (this._contentWhitelisted) {
|
||||
this._sendMsg(event.detail.type, event.detail.data);
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function (msg) {
|
||||
if (msg.data.type == "AddToWhitelist") {
|
||||
for (let uri of msg.data.data) {
|
||||
this.whitelist.add(uri);
|
||||
}
|
||||
this._sendMsg("AddToWhitelistAck");
|
||||
return;
|
||||
}
|
||||
if (this._contentWhitelisted) {
|
||||
this._fireEvent(msg.data.type, msg.data.data);
|
||||
}
|
||||
},
|
||||
|
||||
get _contentWhitelisted() {
|
||||
return this.whitelist.has(content.document.documentURI);
|
||||
},
|
||||
|
||||
_sendMsg: function (type, data=null) {
|
||||
sendAsyncMessage("ContentSearch", {
|
||||
type: type,
|
||||
data: data,
|
||||
});
|
||||
},
|
||||
|
||||
_fireEvent: function (type, data=null) {
|
||||
let event = Cu.cloneInto({
|
||||
detail: {
|
||||
type: type,
|
||||
data: data,
|
||||
},
|
||||
}, content);
|
||||
content.dispatchEvent(new content.CustomEvent("ContentSearchService",
|
||||
event));
|
||||
},
|
||||
};
|
||||
ContentSearchMediator.init(this);
|
||||
|
||||
let PageStyleHandler = {
|
||||
init: function() {
|
||||
addMessageListener("PageStyle:Switch", this);
|
||||
addMessageListener("PageStyle:Disable", this);
|
||||
|
||||
// Send a CPOW to the parent so that it can synchronously request
|
||||
// the list of style sheets.
|
||||
sendSyncMessage("PageStyle:SetSyncHandler", {}, {syncHandler: this});
|
||||
},
|
||||
|
||||
get markupDocumentViewer() {
|
||||
return docShell.contentViewer;
|
||||
},
|
||||
|
||||
// Called synchronously via CPOW from the parent.
|
||||
getStyleSheetInfo: function() {
|
||||
let styleSheets = this._filterStyleSheets(this.getAllStyleSheets());
|
||||
return {
|
||||
styleSheets: styleSheets,
|
||||
authorStyleDisabled: this.markupDocumentViewer.authorStyleDisabled,
|
||||
preferredStyleSheetSet: content.document.preferredStyleSheetSet
|
||||
};
|
||||
},
|
||||
|
||||
// Called synchronously via CPOW from the parent.
|
||||
getAllStyleSheets: function(frameset = content) {
|
||||
let selfSheets = Array.slice(frameset.document.styleSheets);
|
||||
let subSheets = Array.map(frameset.frames, frame => this.getAllStyleSheets(frame));
|
||||
return selfSheets.concat(...subSheets);
|
||||
},
|
||||
|
||||
receiveMessage: function(msg) {
|
||||
switch (msg.name) {
|
||||
case "PageStyle:Switch":
|
||||
this.markupDocumentViewer.authorStyleDisabled = false;
|
||||
this._stylesheetSwitchAll(content, msg.data.title);
|
||||
break;
|
||||
|
||||
case "PageStyle:Disable":
|
||||
this.markupDocumentViewer.authorStyleDisabled = true;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_stylesheetSwitchAll: function (frameset, title) {
|
||||
if (!title || this._stylesheetInFrame(frameset, title)) {
|
||||
this._stylesheetSwitchFrame(frameset, title);
|
||||
}
|
||||
|
||||
for (let i = 0; i < frameset.frames.length; i++) {
|
||||
// Recurse into sub-frames.
|
||||
this._stylesheetSwitchAll(frameset.frames[i], title);
|
||||
}
|
||||
},
|
||||
|
||||
_stylesheetSwitchFrame: function (frame, title) {
|
||||
var docStyleSheets = frame.document.styleSheets;
|
||||
|
||||
for (let i = 0; i < docStyleSheets.length; ++i) {
|
||||
let docStyleSheet = docStyleSheets[i];
|
||||
if (docStyleSheet.title) {
|
||||
docStyleSheet.disabled = (docStyleSheet.title != title);
|
||||
} else if (docStyleSheet.disabled) {
|
||||
docStyleSheet.disabled = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_stylesheetInFrame: function (frame, title) {
|
||||
return Array.some(frame.document.styleSheets, (styleSheet) => styleSheet.title == title);
|
||||
},
|
||||
|
||||
_filterStyleSheets: function(styleSheets) {
|
||||
let result = [];
|
||||
|
||||
for (let currentStyleSheet of styleSheets) {
|
||||
if (!currentStyleSheet.title)
|
||||
continue;
|
||||
|
||||
// Skip any stylesheets that don't match the screen media type.
|
||||
if (currentStyleSheet.media.length > 0) {
|
||||
let mediaQueryList = currentStyleSheet.media.mediaText;
|
||||
if (!content.matchMedia(mediaQueryList).matches) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.push({title: currentStyleSheet.title,
|
||||
disabled: currentStyleSheet.disabled});
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
};
|
||||
PageStyleHandler.init();
|
||||
|
||||
// Keep a reference to the translation content handler to avoid it it being GC'ed.
|
||||
let trHandler = null;
|
||||
if (Services.prefs.getBoolPref("browser.translation.detectLanguage")) {
|
||||
Cu.import("resource:///modules/translation/TranslationContentHandler.jsm");
|
||||
trHandler = new TranslationContentHandler(global, docShell);
|
||||
}
|
||||
|
||||
function gKeywordURIFixup(fixupInfo) {
|
||||
fixupInfo.QueryInterface(Ci.nsIURIFixupInfo);
|
||||
|
||||
// Ignore info from other docshells
|
||||
let parent = fixupInfo.consumer.QueryInterface(Ci.nsIDocShellTreeItem).sameTypeRootTreeItem;
|
||||
if (parent != docShell)
|
||||
return;
|
||||
|
||||
let data = {};
|
||||
for (let f of Object.keys(fixupInfo)) {
|
||||
if (f == "consumer" || typeof fixupInfo[f] == "function")
|
||||
continue;
|
||||
|
||||
if (fixupInfo[f] && fixupInfo[f] instanceof Ci.nsIURI) {
|
||||
data[f] = fixupInfo[f].spec;
|
||||
} else {
|
||||
data[f] = fixupInfo[f];
|
||||
}
|
||||
}
|
||||
|
||||
sendAsyncMessage("Browser:URIFixup", data);
|
||||
}
|
||||
Services.obs.addObserver(gKeywordURIFixup, "keyword-uri-fixup", false);
|
||||
addEventListener("unload", () => {
|
||||
Services.obs.removeObserver(gKeywordURIFixup, "keyword-uri-fixup");
|
||||
}, false);
|
||||
|
||||
addMessageListener("Browser:AppTab", function(message) {
|
||||
docShell.isAppTab = message.data.isAppTab;
|
||||
});
|
||||
|
||||
let WebBrowserChrome = {
|
||||
onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
|
||||
return BrowserUtils.onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
|
||||
},
|
||||
|
||||
// Check whether this URI should load in the current process
|
||||
shouldLoadURI: function(aDocShell, aURI, aReferrer) {
|
||||
if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aReferrer)) {
|
||||
E10SUtils.redirectLoad(aDocShell, aURI, aReferrer);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
let tabchild = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsITabChild);
|
||||
tabchild.webBrowserChrome = WebBrowserChrome;
|
||||
}
|
||||
|
||||
|
||||
let DOMFullscreenHandler = {
|
||||
_fullscreenDoc: null,
|
||||
|
||||
init: function() {
|
||||
addMessageListener("DOMFullscreen:Approved", this);
|
||||
addMessageListener("DOMFullscreen:CleanUp", this);
|
||||
addEventListener("MozEnteredDomFullscreen", this);
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
switch(aMessage.name) {
|
||||
case "DOMFullscreen:Approved": {
|
||||
if (this._fullscreenDoc) {
|
||||
Services.obs.notifyObservers(this._fullscreenDoc,
|
||||
"fullscreen-approved",
|
||||
"");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "DOMFullscreen:CleanUp": {
|
||||
this._fullscreenDoc = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
if (aEvent.type == "MozEnteredDomFullscreen") {
|
||||
this._fullscreenDoc = aEvent.target;
|
||||
sendAsyncMessage("MozEnteredDomFullscreen", {
|
||||
origin: this._fullscreenDoc.nodePrincipal.origin,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
DOMFullscreenHandler.init();
|
|
@ -77,6 +77,7 @@ browser.jar:
|
|||
* content/browser/browser.xul (content/browser.xul)
|
||||
* content/browser/browser-tabPreviews.xml (content/browser-tabPreviews.xml)
|
||||
* content/browser/chatWindow.xul (content/chatWindow.xul)
|
||||
content/browser/tab-content.js (content/tab-content.js)
|
||||
content/browser/content.js (content/content.js)
|
||||
content/browser/defaultthemes/1.footer.jpg (content/defaultthemes/1.footer.jpg)
|
||||
content/browser/defaultthemes/1.header.jpg (content/defaultthemes/1.header.jpg)
|
||||
|
|
|
@ -13,6 +13,13 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
|
||||
var global = this;
|
||||
|
||||
|
||||
// Lazily load the finder code
|
||||
addMessageListener("Finder:Initialize", function () {
|
||||
let {RemoteFinderListener} = Cu.import("resource://gre/modules/RemoteFinder.jsm", {});
|
||||
new RemoteFinderListener(global);
|
||||
});
|
||||
|
||||
let ClickEventHandler = {
|
||||
init: function init() {
|
||||
this._scrollable = null;
|
||||
|
|
Загрузка…
Ссылка в новой задаче