Bug 1496217 - Support process switching in GeckoView r=esawin

Differential Revision: https://phabricator.services.mozilla.com/D9589
This commit is contained in:
James Willcox 2018-10-23 16:34:05 -05:00
Родитель 1e1cda1530
Коммит 4e683c0261
7 изменённых файлов: 166 добавлений и 11 удалений

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

@ -891,3 +891,8 @@ pref("media.navigator.permission.device", true);
// Allow system add-on updates
pref("extensions.systemAddon.update.url", "https://aus5.mozilla.org/update/3/SystemAddons/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
// E10s stuff. We don't support 'file' or 'priveleged' process types.
pref("browser.tabs.remote.separateFileUriProcess", false);
pref("browser.tabs.remote.allowLinkedWebInFileUriProcess", true);
pref("browser.tabs.remote.separatePrivilegedContentProcess", false);

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

@ -7,6 +7,8 @@ ChromeUtils.import("resource://gre/modules/GeckoViewContentModule.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetters(this, {
BrowserUtils: "resource://gre/modules/BrowserUtils.jsm",
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
ErrorPageEventHandler: "chrome://geckoview/content/ErrorPageEventHandler.js",
LoadURIDelegate: "resource://gre/modules/LoadURIDelegate.jsm",
});
@ -15,6 +17,12 @@ XPCOMUtils.defineLazyModuleGetters(this, {
class GeckoViewNavigationContent extends GeckoViewContentModule {
onInit() {
docShell.loadURIDelegate = this;
if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) {
let tabchild = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsITabChild);
tabchild.webBrowserChrome = this;
}
}
// nsILoadURIDelegate.
@ -51,6 +59,45 @@ class GeckoViewNavigationContent extends GeckoViewContentModule {
return LoadURIDelegate.handleLoadError(content, this.eventDispatcher,
aUri, aError, aErrorModule);
}
// nsIWebBrowserChrome
onBeforeLinkTraversal(aOriginalTarget, aLinkURI, aLinkNode, aIsAppTab) {
debug `onBeforeLinkTraversal ${aLinkURI.displaySpec}`;
return BrowserUtils.onBeforeLinkTraversal(aOriginalTarget, aLinkURI, aLinkNode, aIsAppTab);
}
// nsIWebBrowserChrome
shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData, aTriggeringPrincipal) {
debug `shouldLoadURI ${aURI.displaySpec}`;
// We currently only support one remoteType, "web", so we only need to bail out
// if we want to load this URI in the parent.
// const remoteType = E10SUtils.getRemoteTypeForURIObject(aURI, true);
// if (!remoteType) {
// E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, false);
// return false;
// }
if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData)) {
E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, false);
return false;
}
return true;
}
// nsIWebBrowserChrome
shouldLoadURIInThisProcess(aURI) {
debug `shouldLoadURIInThisProcess ${aURI.displaySpec}`;
return E10SUtils.shouldLoadURIInThisProcess(aURI);
}
// nsIWebBrowserChrome
reloadInFreshProcess(aDocShell, aURI, aReferrer, aTriggeringPrincipal, aLoadFlags) {
debug `reloadInFreshProcess ${aURI.displaySpec}`;
E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, true, aLoadFlags);
return true;
}
}
let {debug, warn} = GeckoViewNavigationContent.initLogging("GeckoViewNavigation");

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

@ -7,6 +7,7 @@
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetters(this, {
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
EventDispatcher: "resource://gre/modules/Messaging.jsm",
GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm",
Services: "resource://gre/modules/Services.jsm",
@ -98,6 +99,64 @@ var ModuleManager = {
this._modules.forEach(aCallback, this);
},
updateRemoteType(aRemoteType) {
debug `updateRemoteType remoteType=${aRemoteType}`;
const currentRemoteType = this.browser.getAttribute("remoteType");
if (aRemoteType && !this.settings.useMultiprocess) {
warn `Tried to create a remote browser in multiprocess mode`;
return false;
}
if (currentRemoteType === aRemoteType) {
// We're already using a child process of the correct type.
return false;
}
// Now we're switching the remoteness (value of "remote" attr).
debug `updateRemoteType: changing from '${currentRemoteType}' to '${aRemoteType}'`;
this.forEach(module => {
if (module.enabled && module.impl) {
module.impl.onDisable();
}
});
this.forEach(module => {
if (module.impl) {
module.impl.onDestroyBrowser();
}
});
const parent = this.browser.parentNode;
this.browser.remove();
if (aRemoteType) {
this.browser.setAttribute("remote", "true");
this.browser.setAttribute("remoteType", aRemoteType);
} else {
this.browser.setAttribute("remote", "false");
this.browser.removeAttribute("remoteType");
}
this.forEach(module => {
if (module.impl) {
module.impl.onInitBrowser();
}
});
parent.appendChild(this.browser);
this.forEach(module => {
if (module.enabled && module.impl) {
module.impl.onEnable();
}
});
this.browser.focus();
return true;
},
_updateSettings(aSettings) {
Object.assign(this._settings, aSettings);
this._frozenSettings = Object.freeze(Object.assign({}, this._settings));
@ -304,6 +363,13 @@ function createBrowser() {
browser.setAttribute("type", "content");
browser.setAttribute("primary", "true");
browser.setAttribute("flex", "1");
const settings = window.arguments[0].QueryInterface(Ci.nsIAndroidView).initData.settings;
if (settings.useMultiprocess) {
browser.setAttribute("remote", "true");
browser.setAttribute("remoteType", E10SUtils.DEFAULT_REMOTE_TYPE);
}
return browser;
}

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

@ -973,4 +973,15 @@ class NavigationDelegateTest : BaseSessionTest() {
sessionRule.session.waitUntilCalled(GeckoSession.NavigationDelegate::class,
"onNewSession")
}
@Test
fun processSwitching() {
// This loads in the parent process
mainSession.loadUri("about:config")
sessionRule.waitForPageStop()
// This will load a page in the child
mainSession.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitForPageStop()
}
}

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

@ -29,28 +29,35 @@ class GeckoViewModule {
}
get window() {
return this._info.manager.window;
return this.moduleManager.window;
}
get browser() {
return this._info.manager.browser;
return this.moduleManager.browser;
}
get messageManager() {
return this._info.manager.messageManager;
return this.moduleManager.messageManager;
}
get eventDispatcher() {
return this._info.manager.eventDispatcher;
return this.moduleManager.eventDispatcher;
}
get settings() {
return this._info.manager.settings;
return this.moduleManager.settings;
}
get moduleManager() {
return this._info.manager;
}
// Override to initialize the browser before it is bound to the window.
onInitBrowser() {}
// Override to cleanup when the browser is destroyed.
onDestroyBrowser() {}
// Override to initialize module.
onInit() {}

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

@ -10,6 +10,8 @@ ChromeUtils.import("resource://gre/modules/GeckoViewModule.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetters(this, {
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
Utils: "resource://gre/modules/sessionstore/Utils.jsm",
LoadURIDelegate: "resource://gre/modules/LoadURIDelegate.jsm",
Services: "resource://gre/modules/Services.jsm",
});
@ -38,6 +40,8 @@ class GeckoViewNavigation extends GeckoViewModule {
"GeckoView:Reload",
"GeckoView:Stop",
]);
this.messageManager.addMessageListener("Browser:LoadURI", this);
}
// Bundle event handler.
@ -73,6 +77,10 @@ class GeckoViewNavigation extends GeckoViewModule {
navFlags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_POPUPS;
}
const remoteType =
E10SUtils.getRemoteTypeForURI(uri, this.settings.useMultiprocess);
this.moduleManager.updateRemoteType(remoteType);
this.browser.loadURI(uri, {
flags: navFlags,
referrerURI: referrer,
@ -90,6 +98,23 @@ class GeckoViewNavigation extends GeckoViewModule {
// Message manager event handler.
receiveMessage(aMsg) {
debug `receiveMessage: ${aMsg.name}`;
switch (aMsg.name) {
case "Browser:LoadURI":
// This is triggered by E10SUtils.redirectLoad(), and means
// we may need to change the remoteness of our browser and
// load the URI.
const { uri, flags, referrer, triggeringPrincipal } = aMsg.data.loadOptions;
const remoteType =
E10SUtils.getRemoteTypeForURI(uri, this.settings.useMultiprocess);
this.moduleManager.updateRemoteType(remoteType);
this.browser.loadURI(aMsg.data.loadOptions.uri, {
flags, referrerURI: referrer,
triggeringPrincipal: Utils.deserializePrincipal(triggeringPrincipal),
});
break;
}
}
waitAndSetupWindow(aSessionId, { opener, nextTabParentId }) {

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

@ -44,12 +44,6 @@ const USER_AGENT_MODE_VR = 2;
// * multiprocess
// * user agent override
class GeckoViewSettings extends GeckoViewModule {
onInitBrowser() {
if (this.settings.useMultiprocess) {
this.browser.setAttribute("remote", "true");
}
}
onInit() {
debug `onInit`;
this._useTrackingProtection = false;