Bug 1147911 Part 2: Add a remote type property and use it to drive the process switching in frontend code. r=gijs, r=jryans, r=mikedeboer

This commit is contained in:
Bob Owen 2016-11-24 15:08:30 +00:00
Родитель db5fb76036
Коммит 4f48f9317d
10 изменённых файлов: 202 добавлений и 122 удалений

Просмотреть файл

@ -830,14 +830,13 @@ function _loadURIWithFlags(browser, uri, params) {
Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT);
let postData = params.postData;
let wasRemote = browser.isRemoteBrowser;
let currentRemoteType = browser.remoteType;
let requiredRemoteType =
E10SUtils.getRemoteTypeForURI(uri, gMultiProcessBrowser, currentRemoteType);
let mustChangeProcess = requiredRemoteType != currentRemoteType;
let process = browser.isRemoteBrowser ? Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT
: Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
let mustChangeProcess = gMultiProcessBrowser &&
!E10SUtils.canLoadURIInProcess(uri, process);
if ((!wasRemote && !mustChangeProcess) ||
(wasRemote && mustChangeProcess)) {
// !requiredRemoteType means we're loading in the parent/this process.
if (!requiredRemoteType) {
browser.inLoadURI = true;
}
try {
@ -888,8 +887,7 @@ function _loadURIWithFlags(browser, uri, params) {
throw e;
}
} finally {
if ((!wasRemote && !mustChangeProcess) ||
(wasRemote && mustChangeProcess)) {
if (!requiredRemoteType) {
browser.inLoadURI = false;
}
}
@ -1145,22 +1143,12 @@ var gBrowserInit = {
gBrowser.selectedBrowser.setAttribute("usercontextid", usercontextid);
}
// If the browser that we're swapping in was remote, then we'd better
// be able to support remote browsers, and then make our selectedTab
// remote.
try {
if (tabToOpen.linkedBrowser.isRemoteBrowser) {
if (!gMultiProcessBrowser) {
throw new Error("Cannot drag a remote browser into a window " +
"without the remote tabs load context.");
}
gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, true);
} else if (gBrowser.selectedBrowser.isRemoteBrowser) {
// If the browser is remote, then it's implied that
// gMultiProcessBrowser is true. We need to flip the remoteness
// of this tab to false in order for the tab drag to work.
gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, false);
}
// Make sure selectedBrowser has the same remote settings as the one
// we are swapping in.
gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser,
tabToOpen.linkedBrowser.isRemoteBrowser,
tabToOpen.linkedBrowser.remoteType);
gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, tabToOpen);
} catch (e) {
Cu.reportError(e);
@ -2271,24 +2259,22 @@ function BrowserViewSourceOfDocument(aArgsOrDocument) {
let inTab = Services.prefs.getBoolPref("view_source.tab");
if (inTab) {
let tabBrowser = gBrowser;
let forceNotRemote = false;
let preferredRemoteType;
if (!tabBrowser) {
if (!args.browser) {
throw new Error("BrowserViewSourceOfDocument should be passed the " +
"subject browser if called from a window without " +
"gBrowser defined.");
}
forceNotRemote = !args.browser.isRemoteBrowser;
preferredRemoteType = args.browser.remoteType;
} else {
// Some internal URLs (such as specific chrome: and about: URLs that are
// not yet remote ready) cannot be loaded in a remote browser. View
// source in tab expects the new view source browser's remoteness to match
// that of the original URL, so disable remoteness if necessary for this
// URL.
let contentProcess = Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT
forceNotRemote =
gMultiProcessBrowser &&
!E10SUtils.canLoadURIInProcess(args.URL, contentProcess)
preferredRemoteType =
E10SUtils.getRemoteTypeForURI(args.URL, gMultiProcessBrowser);
}
// In the case of popups, we need to find a non-popup browser window.
@ -2306,7 +2292,7 @@ function BrowserViewSourceOfDocument(aArgsOrDocument) {
let tab = tabBrowser.loadOneTab("about:blank", {
relatedToCurrent: true,
inBackground: false,
forceNotRemote,
preferredRemoteType,
relatedBrowser: args.browser
});
args.viewSourceBrowser = tabBrowser.getBrowserForTab(tab);
@ -3265,11 +3251,11 @@ var PrintPreviewListener = {
getPrintPreviewBrowser: function() {
if (!this._printPreviewTab) {
let browser = gBrowser.selectedTab.linkedBrowser;
let forceNotRemote = gMultiProcessBrowser && !browser.isRemoteBrowser;
let preferredRemoteType = browser.remoteType;
this._tabBeforePrintPreview = gBrowser.selectedTab;
this._printPreviewTab = gBrowser.loadOneTab("about:blank",
{ inBackground: false,
forceNotRemote,
preferredRemoteType,
relatedBrowser: browser });
gBrowser.selectedTab = this._printPreviewTab;
}
@ -4232,7 +4218,7 @@ var XULBrowserWindow = {
forceInitialBrowserNonRemote: function(aOpener) {
let initBrowser =
document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
gBrowser.updateBrowserRemoteness(initBrowser, false, aOpener);
gBrowser.updateBrowserRemoteness(initBrowser, false, E10SUtils.NOT_REMOTE, aOpener);
},
setDefaultStatus: function(status) {

Просмотреть файл

@ -1514,6 +1514,7 @@
var aAllowMixedContent;
var aSkipAnimation;
var aForceNotRemote;
var aPreferredRemoteType;
var aNoReferrer;
var aUserContextId;
var aRelatedBrowser;
@ -1534,6 +1535,7 @@
aAllowMixedContent = params.allowMixedContent;
aSkipAnimation = params.skipAnimation;
aForceNotRemote = params.forceNotRemote;
aPreferredRemoteType = params.preferredRemoteType;
aNoReferrer = params.noReferrer;
aUserContextId = params.userContextId;
aRelatedBrowser = params.relatedBrowser;
@ -1556,6 +1558,7 @@
skipAnimation: aSkipAnimation,
allowMixedContent: aAllowMixedContent,
forceNotRemote: aForceNotRemote,
preferredRemoteType: aPreferredRemoteType,
noReferrer: aNoReferrer,
userContextId: aUserContextId,
originPrincipal: aOriginPrincipal,
@ -1673,26 +1676,38 @@
<method name="updateBrowserRemoteness">
<parameter name="aBrowser"/>
<parameter name="aShouldBeRemote"/>
<parameter name="aNewRemoteType"/>
<parameter name="aOpener"/>
<parameter name="aFreshProcess"/>
<body>
<![CDATA[
if (!gMultiProcessBrowser && aShouldBeRemote) {
throw new Error("Cannot switch to remote browser in a window " +
"without the remote tabs load context.");
}
let isRemote = aBrowser.getAttribute("remote") == "true";
// If going remote and no aNewRemoteType then use default.
if (aShouldBeRemote && !aNewRemoteType) {
aNewRemoteType = E10SUtils.DEFAULT_REMOTE_TYPE;
}
// If we are passed an opener, we must be making the browser non-remote, and
// if the browser is _currently_ non-remote, we need the openers to match,
// because it is already too late to change it.
if (aOpener) {
if (aShouldBeRemote) {
throw new Exception("Cannot set an opener on a browser which should be remote!");
throw new Error("Cannot set an opener on a browser which should be remote!");
}
if (!isRemote && aBrowser.contentWindow.opener != aOpener) {
throw new Exception("Cannot change opener on an already non-remote browser!");
throw new Error("Cannot change opener on an already non-remote browser!");
}
}
// Abort if we're not going to change anything
if (isRemote == aShouldBeRemote && !aFreshProcess) {
if (isRemote == aShouldBeRemote && !aFreshProcess &&
(!isRemote || aBrowser.getAttribute("remoteType") == aNewRemoteType)) {
return false;
}
@ -1729,7 +1744,13 @@
// Change the "remote" attribute.
let parent = aBrowser.parentNode;
parent.removeChild(aBrowser);
aBrowser.setAttribute("remote", aShouldBeRemote ? "true" : "false");
if (aShouldBeRemote) {
aBrowser.setAttribute("remote", "true");
aBrowser.setAttribute("remoteType", aNewRemoteType);
} else {
aBrowser.setAttribute("remote", "false");
aBrowser.removeAttribute("remoteType");
}
// NB: This works with the hack in the browser constructor that
// turns this normal property into a field.
@ -1813,37 +1834,28 @@
</body>
</method>
<method name="switchBrowserIntoFreshProcess">
<parameter name="aBrowser"/>
<body>
<![CDATA[
if (!gMultiProcessBrowser) {
return this.updateBrowserRemoteness(aBrowser, false);
}
return this.updateBrowserRemoteness(aBrowser,
/* aShouldBeRemote */ true,
/* aOpener */ null,
/* aFreshProcess */ true);
]]>
</body>
</method>
<method name="updateBrowserRemotenessByURL">
<parameter name="aBrowser"/>
<parameter name="aURL"/>
<parameter name="aFreshProcess"/>
<body>
<![CDATA[
if (!gMultiProcessBrowser)
return this.updateBrowserRemoteness(aBrowser, false);
let process = aBrowser.isRemoteBrowser ? Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT
: Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
// If this URL can't load in the browser's current process then flip
// it to the other process
if (!E10SUtils.canLoadURIInProcess(aURL, process))
return this.updateBrowserRemoteness(aBrowser, !aBrowser.isRemoteBrowser);
// If this URL can't load in the current browser then flip it to the
// correct type.
let currentRemoteType = aBrowser.remoteType;
let requiredRemoteType =
E10SUtils.getRemoteTypeForURI(aURL, gMultiProcessBrowser,
currentRemoteType);
if (currentRemoteType != requiredRemoteType || aFreshProcess) {
return this.updateBrowserRemoteness(aBrowser,
!!requiredRemoteType,
requiredRemoteType,
/* aOpener */ null,
aFreshProcess);
}
return false;
]]>
@ -1900,15 +1912,16 @@
return;
}
let remote = gMultiProcessBrowser &&
E10SUtils.canLoadURIInProcess(BROWSER_NEW_TAB_URL, Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT);
let browser = this._createBrowser({isPreloadBrowser: true, remote: remote});
let remoteType =
E10SUtils.getRemoteTypeForURI(BROWSER_NEW_TAB_URL,
gMultiProcessBrowser);
let browser = this._createBrowser({isPreloadBrowser: true, remoteType});
this._preloadedBrowser = browser;
let notificationbox = this.getNotificationBox(browser);
this.mPanelContainer.appendChild(notificationbox);
if (remote) {
if (remoteType != E10SUtils.NOT_REMOTE) {
// For remote browsers, we need to make sure that the webProgress is
// instantiated, otherwise the parent won't get informed about the state
// of the preloaded browser until it gets attached to a tab.
@ -1926,7 +1939,8 @@
<body>
<![CDATA[
// Supported parameters:
// userContextId, remote, isPreloadBrowser, uriIsAboutBlank, permanentKey
// userContextId, remote, remoteType, isPreloadBrowser,
// uriIsAboutBlank, permanentKey
const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@ -1942,12 +1956,18 @@
b.setAttribute("usercontextid", aParams.userContextId);
}
if (aParams.remote) {
// remote parameter used by some addons, use default in this case.
if (aParams.remote && !aParams.remoteType) {
aParams.remoteType = E10SUtils.DEFAULT_REMOTE_TYPE;
}
if (aParams.remoteType) {
b.setAttribute("remoteType", aParams.remoteType);
b.setAttribute("remote", "true");
}
if (aParams.opener) {
if (aParams.remote) {
if (aParams.remoteType) {
throw new Exception("Cannot set opener window on a remote browser!");
}
b.QueryInterface(Ci.nsIFrameLoaderOwner).presetOpenerWindow(aParams.opener);
@ -2020,15 +2040,14 @@
"use strict";
// Supported parameters:
// forceNotRemote, userContextId
// forceNotRemote, preferredRemoteType, userContextId
let uriIsAboutBlank = !aURI || aURI == "about:blank";
// The new browser should be remote if this is an e10s window and
// the uri to load can be loaded remotely.
let remote = gMultiProcessBrowser &&
!aParams.forceNotRemote &&
E10SUtils.canLoadURIInProcess(aURI, Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT);
let remoteType =
aParams.forceNotRemote ? E10SUtils.NOT_REMOTE
: E10SUtils.getRemoteTypeForURI(aURI, gMultiProcessBrowser,
aParams.preferredRemoteType);
let browser;
let usingPreloadedContent = false;
@ -2050,7 +2069,7 @@
if (!browser) {
// No preloaded browser found, create one.
browser = this._createBrowser({permanentKey: aTab.permanentKey,
remote: remote,
remoteType,
uriIsAboutBlank: uriIsAboutBlank,
userContextId: aParams.userContextId,
relatedBrowser: aParams.relatedBrowser,
@ -2095,7 +2114,7 @@
// from being created as soon as the linked <browser> is inserted
// into the DOM. We thus have to register the new outerWindowID
// for non-remote browsers after we have called browser.loadURI().
if (!remote) {
if (remoteType == E10SUtils.NOT_REMOTE) {
this._outerWindowIDBrowserMap.set(browser.outerWindowID, browser);
}
@ -2125,6 +2144,7 @@
var aSkipAnimation;
var aAllowMixedContent;
var aForceNotRemote;
var aPreferredRemoteType;
var aNoReferrer;
var aUserContextId;
var aEventDetail;
@ -2147,6 +2167,7 @@
aSkipAnimation = params.skipAnimation;
aAllowMixedContent = params.allowMixedContent;
aForceNotRemote = params.forceNotRemote;
aPreferredRemoteType = params.preferredRemoteType;
aNoReferrer = params.noReferrer;
aUserContextId = params.userContextId;
aEventDetail = params.eventDetail;
@ -2220,6 +2241,7 @@
// of tab.linkedBrowser.
let browserParams = {
forceNotRemote: aForceNotRemote,
preferredRemoteType: aPreferredRemoteType,
userContextId: aUserContextId,
relatedBrowser: aRelatedBrowser,
opener: aOpener,

Просмотреть файл

@ -3543,13 +3543,8 @@ var SessionStoreInternal = {
// flip the remoteness of any browser that is not being displayed.
this.markTabAsRestoring(aTab);
let isRemotenessUpdate = false;
if (aReloadInFreshProcess) {
isRemotenessUpdate = tabbrowser.switchBrowserIntoFreshProcess(browser);
} else {
isRemotenessUpdate = tabbrowser.updateBrowserRemotenessByURL(browser, uri);
}
let isRemotenessUpdate =
tabbrowser.updateBrowserRemotenessByURL(browser, uri, aReloadInFreshProcess);
if (isRemotenessUpdate) {
// We updated the remoteness, so we need to send the history down again.
//

Просмотреть файл

@ -28,31 +28,69 @@ function getAboutModule(aURL) {
}
}
const NOT_REMOTE = null;
const WEB_REMOTE_TYPE = "web";
const DEFAULT_REMOTE_TYPE = WEB_REMOTE_TYPE;
this.E10SUtils = {
DEFAULT_REMOTE_TYPE,
NOT_REMOTE,
WEB_REMOTE_TYPE,
canLoadURIInProcess: function(aURL, aProcess) {
let remoteType = aProcess == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT
? DEFAULT_REMOTE_TYPE : NOT_REMOTE;
return remoteType == this.getRemoteTypeForURI(aURL, true, remoteType);
},
getRemoteTypeForURI: function(aURL, aMultiProcess,
aPreferredRemoteType = DEFAULT_REMOTE_TYPE) {
if (!aMultiProcess) {
return NOT_REMOTE;
}
// loadURI in browser.xml treats null as about:blank
if (!aURL)
if (!aURL) {
aURL = "about:blank";
}
// Javascript urls can load in any process, they apply to the current document
if (aURL.startsWith("javascript:"))
return true;
if (aURL.startsWith("javascript:")) {
return aPreferredRemoteType;
}
let processIsRemote = aProcess == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
let canLoadRemote = true;
let mustLoadRemote = true;
// We need data: URIs to load in any remote process, because some of our
// tests rely on this.
if (aURL.startsWith("data:")) {
return aPreferredRemoteType == NOT_REMOTE ? DEFAULT_REMOTE_TYPE
: aPreferredRemoteType;
}
if (aURL.startsWith("about:")) {
// We need to special case about:blank because it needs to load in any.
if (aURL == "about:blank") {
return aPreferredRemoteType;
}
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);
// should be ok to load in any process
if (!module) {
return aPreferredRemoteType;
}
let flags = module.getURIFlags(url);
if (flags & Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD) {
return DEFAULT_REMOTE_TYPE;
}
if (flags & Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD &&
aPreferredRemoteType != NOT_REMOTE) {
return DEFAULT_REMOTE_TYPE;
}
return NOT_REMOTE;
}
if (aURL.startsWith("chrome:")) {
@ -62,34 +100,33 @@ this.E10SUtils = {
// not loading anything anyway.
url = Services.io.newURI(aURL, null, null);
} catch (ex) {
canLoadRemote = true;
mustLoadRemote = false;
return aPreferredRemoteType;
}
if (url) {
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
getService(Ci.nsIXULChromeRegistry);
canLoadRemote = chromeReg.canLoadURLRemotely(url);
mustLoadRemote = chromeReg.mustLoadURLRemotely(url);
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
getService(Ci.nsIXULChromeRegistry);
if (chromeReg.mustLoadURLRemotely(url)) {
return DEFAULT_REMOTE_TYPE;
}
if (chromeReg.canLoadURLRemotely(url) &&
aPreferredRemoteType != NOT_REMOTE) {
return DEFAULT_REMOTE_TYPE;
}
return NOT_REMOTE;
}
if (aURL.startsWith("moz-extension:")) {
canLoadRemote = useRemoteWebExtensions;
mustLoadRemote = useRemoteWebExtensions;
return useRemoteWebExtensions ? WEB_REMOTE_TYPE : NOT_REMOTE;
}
if (aURL.startsWith("view-source:")) {
return this.canLoadURIInProcess(aURL.substr("view-source:".length), aProcess);
return this.getRemoteTypeForURI(aURL.substr("view-source:".length),
aMultiProcess, aPreferredRemoteType);
}
if (mustLoadRemote)
return processIsRemote;
if (!canLoadRemote && processIsRemote)
return false;
return true;
return WEB_REMOTE_TYPE;
},
shouldLoadURI: function(aDocShell, aURI, aReferrer) {

Просмотреть файл

@ -139,7 +139,8 @@ function swapToInnerBrowser({ tab, containerURL, getInnerBrowser }) {
// 5. Force the original browser tab to be remote since web content is
// loaded in the child process, and we're about to swap the content
// into this tab.
gBrowser.updateBrowserRemoteness(tab.linkedBrowser, true);
gBrowser.updateBrowserRemoteness(tab.linkedBrowser, true,
contentBrowser.remoteType);
// 6. Swap the content into the original browser tab and close the
// temporary tab used to hold the content via
@ -212,6 +213,15 @@ function addXULBrowserDecorations(browser) {
enumerable: true,
});
}
if (browser.remoteType == undefined) {
Object.defineProperty(browser, "remoteType", {
get() {
return this.getAttribute("remoteType");
},
configurable: true,
enumerable: true,
});
}
if (browser.messageManager == undefined) {
Object.defineProperty(browser, "messageManager", {
get() {

Просмотреть файл

@ -143,6 +143,7 @@ function tunnelToInnerBrowser(outer, inner) {
// down to the inner browser by this tunnel, the tab's remoteness effectively is the
// remoteness of the inner browser.
outer.setAttribute("remote", "true");
outer.setAttribute("remoteType", inner.remoteType);
// Clear out any cached state that references the current non-remote XBL binding,
// such as form fill controllers. Otherwise they will remain in place and leak the
@ -269,6 +270,7 @@ function tunnelToInnerBrowser(outer, inner) {
// Reset @remote since this is now back to a regular, non-remote browser
outer.setAttribute("remote", "false");
outer.removeAttribute("remoteType");
// Delete browser window properties exposed on content's owner global
delete inner.ownerGlobal.PopupNotifications;

Просмотреть файл

@ -127,9 +127,9 @@ module.exports = createClass({
* React uses a whitelist for attributes, so we need some way to set
* attributes it does not know about, such as @mozbrowser. If this were
* the only issue, we could use componentDidMount or ref: node => {} to
* set the atttibutes. In the case of @remote, the attribute must be set
* before the element is added to the DOM to have any effect, which we
* are able to do with this approach.
* set the atttibutes. In the case of @remote and @remoteType, the
* attribute must be set before the element is added to the DOM to have
* any effect, which we are able to do with this approach.
*
* @noisolation and @allowfullscreen are needed so that these frames
* have the same access to browser features as regular browser tabs.
@ -137,7 +137,8 @@ module.exports = createClass({
* before allowing the swap to proceed.
*/
dangerouslySetInnerHTML: {
__html: `<iframe class="browser" mozbrowser="true" remote="true"
__html: `<iframe class="browser" mozbrowser="true"
remote="true" remoteType="web"
noisolation="true" allowfullscreen="true"
src="${location}" width="100%" height="100%">
</iframe>`

Просмотреть файл

@ -190,7 +190,7 @@ ViewSourceBrowser.prototype = {
// If we're dealing with a remote browser, then the browser
// for view source needs to be remote as well.
this.updateBrowserRemoteness(browser.isRemoteBrowser);
this.updateBrowserRemoteness(browser.isRemoteBrowser, browser.remoteType);
} else if (outerWindowID) {
throw new Error("Must supply the browser if passing the outerWindowID");
}
@ -221,9 +221,12 @@ ViewSourceBrowser.prototype = {
* True if the browser should be made remote. If the browsers
* remoteness already matches this value, this function does
* nothing.
* @param remoteType
* The type of remote browser process.
*/
updateBrowserRemoteness(shouldBeRemote) {
if (this.browser.isRemoteBrowser != shouldBeRemote) {
updateBrowserRemoteness(shouldBeRemote, remoteType) {
if (this.browser.isRemoteBrowser != shouldBeRemote ||
this.browser.remoteType != remoteType) {
// In this base case, where we are handed a <browser> someone else is
// managing, we don't know for sure that it's safe to toggle remoteness.
// For view source in a window, this is overridden to actually do the

Просмотреть файл

@ -666,9 +666,12 @@ ViewSourceChrome.prototype = {
* True if the browser should be made remote. If the browsers
* remoteness already matches this value, this function does
* nothing.
* @param remoteType
* The type of remote browser process.
*/
updateBrowserRemoteness(shouldBeRemote) {
if (this.browser.isRemoteBrowser == shouldBeRemote) {
updateBrowserRemoteness(shouldBeRemote, remoteType) {
if (this.browser.isRemoteBrowser == shouldBeRemote &&
this.browser.remoteType == remoteType) {
return;
}
@ -685,8 +688,10 @@ ViewSourceChrome.prototype = {
this.browser.remove();
if (shouldBeRemote) {
this.browser.setAttribute("remote", "true");
this.browser.setAttribute("remoteType", remoteType);
} else {
this.browser.removeAttribute("remote");
this.browser.removeAttribute("remoteType");
}
this.browser.relatedBrowser = relatedBrowser;

Просмотреть файл

@ -338,6 +338,25 @@
onget="return (this.getAttribute('remote') == 'true');"
readonly="true"/>
<property name="remoteType"
readonly="true">
<getter>
<![CDATA[
if (!this.isRemoteBrowser) {
return null;
}
let remoteType = this.getAttribute("remoteType");
if (remoteType) {
return remoteType;
}
let E10SUtils = Components.utils.import("resource://gre/modules/E10SUtils.jsm", {}).E10SUtils;
return E10SUtils.DEFAULT_REMOTE_TYPE;
]]>
</getter>
</property>
<property name="messageManager"
readonly="true">
<getter>