Skip to content

Commit 6d5f104

Browse files
author
Kashav Madan
committed
Bug 1580811 - Make the ContentPage browser work with out-of-process frames, r=nika,zombie
Differential Revision: https://phabricator.services.mozilla.com/D80084
1 parent 3ddcbc3 commit 6d5f104

File tree

4 files changed

+72
-11
lines changed

4 files changed

+72
-11
lines changed

toolkit/components/extensions/ExtensionPolicyService.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,11 @@ void ExtensionPolicyService::CheckDocument(Document* aDocument) {
466466
if ((!mm || !mMessageManagers.Contains(mm)) &&
467467
// With Fission, OOP iframes don't have a frame message manager, so we
468468
// use the browser's MessageManagerGroup attribute to decide if content
469-
// scripts should run. The "browsers" group includes iframes from tabs.
470-
!group.EqualsLiteral("browsers")) {
469+
// scripts should run. The "browsers" group includes iframes from tabs,
470+
// and the "webext-browsers" group includes custom browsers for
471+
// extension popups/sidebars and xpcshell tests.
472+
!group.EqualsLiteral("browsers") &&
473+
!group.EqualsLiteral("webext-browsers")) {
471474
return;
472475
}
473476

toolkit/components/extensions/ExtensionXPCShellUtils.jsm

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ var REMOTE_CONTENT_SCRIPTS = Services.prefs.getBoolPref(
9494
false
9595
);
9696

97+
const REMOTE_CONTENT_SUBFRAMES = Services.prefs.getBoolPref(
98+
"fission.autostart",
99+
false
100+
);
101+
97102
let BASE_MANIFEST = Object.freeze({
98103
applications: Object.freeze({
99104
gecko: Object.freeze({
@@ -181,11 +186,13 @@ function promiseBrowserLoaded(browser, url, redirectUrl) {
181186
class ContentPage {
182187
constructor(
183188
remote = REMOTE_CONTENT_SCRIPTS,
189+
remoteSubframes = REMOTE_CONTENT_SUBFRAMES,
184190
extension = null,
185191
privateBrowsing = false,
186192
userContextId = undefined
187193
) {
188194
this.remote = remote;
195+
this.remoteSubframes = remote && remoteSubframes;
189196
this.extension = extension;
190197
this.privateBrowsing = privateBrowsing;
191198
this.userContextId = userContextId;
@@ -194,14 +201,20 @@ class ContentPage {
194201
}
195202

196203
async _initBrowser() {
197-
this.windowlessBrowser = Services.appShell.createWindowlessBrowser(true);
198-
204+
let chromeFlags = 0;
205+
if (this.remote) {
206+
chromeFlags |= Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW;
207+
}
208+
if (this.remoteSubframes) {
209+
chromeFlags |= Ci.nsIWebBrowserChrome.CHROME_FISSION_WINDOW;
210+
}
199211
if (this.privateBrowsing) {
200-
let loadContext = this.windowlessBrowser.docShell.QueryInterface(
201-
Ci.nsILoadContext
202-
);
203-
loadContext.usePrivateBrowsing = true;
212+
chromeFlags |= Ci.nsIWebBrowserChrome.CHROME_PRIVATE_WINDOW;
204213
}
214+
this.windowlessBrowser = Services.appShell.createWindowlessBrowser(
215+
true,
216+
chromeFlags
217+
);
205218

206219
let system = Services.scriptSecurityManager.getSystemPrincipal();
207220

@@ -229,6 +242,7 @@ class ContentPage {
229242
let browser = chromeDoc.createXULElement("browser");
230243
browser.setAttribute("type", "content");
231244
browser.setAttribute("disableglobalhistory", "true");
245+
browser.setAttribute("messagemanagergroup", "webext-browsers");
232246
if (this.userContextId) {
233247
browser.setAttribute("usercontextid", this.userContextId);
234248
}
@@ -244,6 +258,12 @@ class ContentPage {
244258
if (this.remote) {
245259
awaitFrameLoader = promiseEvent(browser, "XULFrameLoaderCreated");
246260
browser.setAttribute("remote", "true");
261+
262+
browser.setAttribute("maychangeremoteness", "true");
263+
browser.addEventListener(
264+
"DidChangeBrowserRemoteness",
265+
this.didChangeBrowserRemoteness.bind(this)
266+
);
247267
}
248268

249269
chromeDoc.documentElement.appendChild(browser);
@@ -275,6 +295,12 @@ class ContentPage {
275295
this.browser.messageManager.loadFrameScript(frameScript, false, true);
276296
}
277297

298+
didChangeBrowserRemoteness(event) {
299+
// XXX: Tests can load their own additional frame scripts, so we may need to
300+
// track all scripts that have been loaded, and reload them here?
301+
this.loadFrameScript(frameScript);
302+
}
303+
278304
async loadURL(url, redirectUrl = undefined) {
279305
await this.browserReady;
280306

@@ -297,6 +323,10 @@ class ContentPage {
297323

298324
let { messageManager } = this.browser;
299325

326+
this.browser.removeEventListener(
327+
"DidChangeBrowserRemoteness",
328+
this.didChangeBrowserRemoteness.bind(this)
329+
);
300330
this.browser = null;
301331

302332
this.windowlessBrowser.close();
@@ -1024,6 +1054,9 @@ var ExtensionTestUtils = {
10241054
* @param {boolean} [options.remote]
10251055
* If true, load the URL in a content process. If false, load
10261056
* it in the parent process.
1057+
* @param {boolean} [options.remoteSubframes]
1058+
* If true, load cross-origin frames in separate content processes.
1059+
* This is ignored if |options.remote| is false.
10271060
* @param {string} [options.redirectUrl]
10281061
* An optional URL that the initial page is expected to
10291062
* redirect to.
@@ -1035,6 +1068,7 @@ var ExtensionTestUtils = {
10351068
{
10361069
extension = undefined,
10371070
remote = undefined,
1071+
remoteSubframes = undefined,
10381072
redirectUrl = undefined,
10391073
privateBrowsing = false,
10401074
userContextId = undefined,
@@ -1044,6 +1078,7 @@ var ExtensionTestUtils = {
10441078

10451079
let contentPage = new ContentPage(
10461080
remote,
1081+
remoteSubframes,
10471082
extension && extension.extension,
10481083
privateBrowsing,
10491084
userContextId

xpfe/appshell/nsAppShellService.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,18 @@ WindowlessBrowser::GetDocShell(nsIDocShell** aDocShell) {
428428
}
429429

430430
NS_IMETHODIMP
431-
nsAppShellService::CreateWindowlessBrowser(bool aIsChrome,
431+
nsAppShellService::CreateWindowlessBrowser(bool aIsChrome, uint32_t aChromeMask,
432432
nsIWindowlessBrowser** aResult) {
433+
if (aChromeMask) {
434+
MOZ_DIAGNOSTIC_ASSERT(aIsChrome, "Got chrome flags for non-chrome browser");
435+
if (aChromeMask & ~(nsIWebBrowserChrome::CHROME_REMOTE_WINDOW |
436+
nsIWebBrowserChrome::CHROME_FISSION_WINDOW |
437+
nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW)) {
438+
NS_ERROR("Received unexpected chrome flags");
439+
return NS_ERROR_FAILURE;
440+
}
441+
}
442+
433443
/* First, we set the container window for our instance of nsWebBrowser. Since
434444
* we don't actually have a window, we instead set the container window to be
435445
* an instance of WebBrowserChrome2Stub, which provides a stub implementation
@@ -462,6 +472,16 @@ nsAppShellService::CreateWindowlessBrowser(bool aIsChrome,
462472
aIsChrome ? BrowsingContext::Type::Chrome
463473
: BrowsingContext::Type::Content);
464474

475+
if (aChromeMask & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW) {
476+
browsingContext->SetRemoteTabs(true);
477+
}
478+
if (aChromeMask & nsIWebBrowserChrome::CHROME_FISSION_WINDOW) {
479+
browsingContext->SetRemoteSubframes(true);
480+
}
481+
if (aChromeMask & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW) {
482+
browsingContext->SetPrivateBrowsing(true);
483+
}
484+
465485
/* Next, we create an instance of nsWebBrowser. Instances of this class have
466486
* an associated doc shell, which is what we're interested in.
467487
*/

xpfe/appshell/nsIAppShellService.idl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ interface nsIAppShellService : nsISupports
2626
* @param aParent the parent window. Can be null.
2727
* @param aUrl the contents of the new window.
2828
* @param aChromeMask chrome flags affecting the kind of OS border
29-
* given to the window. see nsIBrowserWindow for
29+
* given to the window. see nsIWebBrowserChrome for
3030
* bit/flag definitions.
3131
* @param aCallbacks interface providing C++ hooks for window initialization
3232
* before the window is made visible. Can be null.
@@ -49,8 +49,11 @@ interface nsIAppShellService : nsISupports
4949
* It is used to simulate DOM windows without an actual physical
5050
* representation.
5151
* @param aIsChrome Set true if you want to use it for chrome content.
52+
* @param aChromeMask Used to specify chrome flags that should be set on the
53+
* window. See nsIWebBrowserChrome for flag definitions.
5254
*/
53-
nsIWindowlessBrowser createWindowlessBrowser([optional] in bool aIsChrome);
55+
nsIWindowlessBrowser createWindowlessBrowser([optional] in bool aIsChrome,
56+
[optional] in uint32_t aChromeMask);
5457

5558
[noscript]
5659
void createHiddenWindow();

0 commit comments

Comments
 (0)