summaryrefslogtreecommitdiffstats
path: root/browser/modules/E10SUtils.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'browser/modules/E10SUtils.jsm')
-rw-r--r--browser/modules/E10SUtils.jsm128
1 files changed, 128 insertions, 0 deletions
diff --git a/browser/modules/E10SUtils.jsm b/browser/modules/E10SUtils.jsm
new file mode 100644
index 000000000..7ed51ee96
--- /dev/null
+++ b/browser/modules/E10SUtils.jsm
@@ -0,0 +1,128 @@
+/* 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/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["E10SUtils"];
+
+const {interfaces: Ci, utils: Cu, classes: Cc} = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+function getAboutModule(aURL) {
+ // Needs to match NS_GetAboutModuleName
+ let moduleName = aURL.path.replace(/[#?].*/, "").toLowerCase();
+ let contract = "@mozilla.org/network/protocol/about;1?what=" + moduleName;
+ try {
+ return Cc[contract].getService(Ci.nsIAboutModule);
+ }
+ catch (e) {
+ // Either the about module isn't defined or it is broken. In either case
+ // ignore it.
+ return null;
+ }
+}
+
+this.E10SUtils = {
+ canLoadURIInProcess: function(aURL, aProcess) {
+ // loadURI in browser.xml treats null as about:blank
+ if (!aURL)
+ aURL = "about:blank";
+
+ // Javascript urls can load in any process, they apply to the current document
+ if (aURL.startsWith("javascript:"))
+ return true;
+
+ let processIsRemote = aProcess == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
+
+ let canLoadRemote = true;
+ let mustLoadRemote = true;
+
+ if (aURL.startsWith("about:")) {
+ let url = Services.io.newURI(aURL, null, null);
+ let module = getAboutModule(url);
+ // If the module doesn't exist then an error page will be loading, that
+ // should be ok to load in either process
+ if (module) {
+ let flags = module.getURIFlags(url);
+ canLoadRemote = !!(flags & Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD);
+ mustLoadRemote = !!(flags & Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD);
+ }
+ }
+
+ if (aURL.startsWith("chrome:")) {
+ let url;
+ try {
+ // This can fail for invalid Chrome URIs, in which case we will end up
+ // not loading anything anyway.
+ url = Services.io.newURI(aURL, null, null);
+ } catch (ex) {
+ canLoadRemote = true;
+ mustLoadRemote = false;
+ }
+ if (url) {
+ let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
+ getService(Ci.nsIXULChromeRegistry);
+ canLoadRemote = chromeReg.canLoadURLRemotely(url);
+ mustLoadRemote = chromeReg.mustLoadURLRemotely(url);
+ }
+ }
+
+ if (aURL.startsWith("moz-extension:")) {
+ canLoadRemote = false;
+ mustLoadRemote = false;
+ }
+
+ if (aURL.startsWith("view-source:")) {
+ return this.canLoadURIInProcess(aURL.substr("view-source:".length), aProcess);
+ }
+
+ if (mustLoadRemote)
+ return processIsRemote;
+
+ if (!canLoadRemote && processIsRemote)
+ return false;
+
+ return true;
+ },
+
+ shouldLoadURI: function(aDocShell, aURI, aReferrer) {
+ // Inner frames should always load in the current process
+ if (aDocShell.QueryInterface(Ci.nsIDocShellTreeItem).sameTypeParent)
+ return true;
+
+ // If the URI can be loaded in the current process then continue
+ return this.canLoadURIInProcess(aURI.spec, Services.appinfo.processType);
+ },
+
+ redirectLoad: function(aDocShell, aURI, aReferrer, aFreshProcess) {
+ // Retarget the load to the correct process
+ let messageManager = aDocShell.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIContentFrameMessageManager);
+ let sessionHistory = aDocShell.getInterface(Ci.nsIWebNavigation).sessionHistory;
+
+ messageManager.sendAsyncMessage("Browser:LoadURI", {
+ loadOptions: {
+ uri: aURI.spec,
+ flags: Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
+ referrer: aReferrer ? aReferrer.spec : null,
+ reloadInFreshProcess: !!aFreshProcess,
+ },
+ historyIndex: sessionHistory.requestedIndex,
+ });
+ return false;
+ },
+
+ wrapHandlingUserInput: function(aWindow, aIsHandling, aCallback) {
+ var handlingUserInput;
+ try {
+ handlingUserInput = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils)
+ .setHandlingUserInput(aIsHandling);
+ aCallback();
+ } finally {
+ handlingUserInput.destruct();
+ }
+ },
+};