зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1469072 - Add infrastructure to move Activity Stream into its own content process. r=kmag,mconley
Summary: This patch adds the infrastructure to move Activity Stream (about:newtab, about:home, and about:welcome) into its own special content process - the privileged content process. This feature of running Activity Stream in the privileged content process is disabled by default. (See "browser.tabs.remote.separatePrivilegedContentProcess" preference.) We can deal with other about: pages in a follow-up. Reviewers: mconley Tags: #secure-revision Bug #: 1469072 Differential Revision: https://phabricator.services.mozilla.com/D1731 MozReview-Commit-ID: 5gIrP4LxcIt --HG-- extra : rebase_source : d43c411ae60aad3d5a3a496e6729de0b547b4acd
This commit is contained in:
Родитель
5d2f11ce8d
Коммит
4867775c4c
|
@ -32,6 +32,8 @@ skip-if = !e10s # Test only relevant for e10s.
|
|||
[browser_new_tab_insert_position.js]
|
||||
skip-if = (debug && os == 'linux' && bits == 32) #Bug 1455882, disabled on Linux32 for almost permafailing
|
||||
support-files = file_new_tab_page.html
|
||||
[browser_new_tab_in_privileged_process_pref.js]
|
||||
skip-if = !e10s # Pref and test only relevant for e10s.
|
||||
[browser_new_web_tab_in_file_process_pref.js]
|
||||
skip-if = !e10s # Pref and test only relevant for e10s.
|
||||
[browser_newwindow_tabstrip_overflow.js]
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests to ensure that Activity Stream loads in the privileged content process.
|
||||
* Normal http web pages should load in the web content process.
|
||||
* Ref: Bug 1469072.
|
||||
*/
|
||||
|
||||
const ABOUT_BLANK = "about:blank";
|
||||
const ABOUT_HOME = "about:home";
|
||||
const ABOUT_NEWTAB = "about:newtab";
|
||||
const ABOUT_WELCOME = "about:welcome";
|
||||
const TEST_HTTP = "http://example.org/";
|
||||
|
||||
/**
|
||||
* Takes a xul:browser and makes sure that the remoteTypes for the browser in
|
||||
* both the parent and the child processes are the same.
|
||||
*
|
||||
* @param {xul:browser} browser
|
||||
* A xul:browser.
|
||||
* @param {string} expectedRemoteType
|
||||
* The expected remoteType value for the browser in both the parent
|
||||
* and child processes.
|
||||
* @param {optional string} message
|
||||
* If provided, shows this string as the message when remoteType values
|
||||
* do not match. If not present, it uses the default message defined
|
||||
* in the function parameters.
|
||||
*/
|
||||
async function checkBrowserRemoteType(
|
||||
browser,
|
||||
expectedRemoteType,
|
||||
message = `Ensures that tab runs in the ${expectedRemoteType} content process.`
|
||||
) {
|
||||
// Check both parent and child to ensure that they have the correct remoteType.
|
||||
is(browser.remoteType, expectedRemoteType, message);
|
||||
is(browser.messageManager.remoteType, expectedRemoteType,
|
||||
"Parent and child process should agree on the remote type.");
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["browser.newtab.preload", false],
|
||||
["browser.tabs.remote.separatePrivilegedContentProcess", true],
|
||||
["dom.ipc.processCount.privileged", 1],
|
||||
["dom.ipc.keepProcessesAlive.privileged", 1],
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* Test to ensure that the Activity Stream tabs open in privileged content
|
||||
* process. We will first open an about:newtab page that acts as a reference to
|
||||
* the privileged content process. With the reference, we can then open Activity
|
||||
* Stream links in a new tab and ensure that the new tab opens in the same
|
||||
* privileged content process as our reference.
|
||||
*/
|
||||
add_task(async function activity_stream_in_privileged_content_process() {
|
||||
Services.ppmm.releaseCachedProcesses();
|
||||
|
||||
await BrowserTestUtils.withNewTab(ABOUT_NEWTAB, async function(browser1) {
|
||||
await checkBrowserRemoteType(browser1, E10SUtils.PRIVILEGED_REMOTE_TYPE);
|
||||
|
||||
// Note the processID for about:newtab for comparison later.
|
||||
let privilegedPid = browser1.frameLoader.tabParent.osPid;
|
||||
|
||||
for (let url of [
|
||||
ABOUT_NEWTAB,
|
||||
ABOUT_WELCOME,
|
||||
ABOUT_HOME,
|
||||
`${ABOUT_NEWTAB}#foo`,
|
||||
`${ABOUT_WELCOME}#bar`,
|
||||
`${ABOUT_HOME}#baz`,
|
||||
`${ABOUT_NEWTAB}?q=foo`,
|
||||
`${ABOUT_WELCOME}?q=bar`,
|
||||
`${ABOUT_HOME}?q=baz`
|
||||
]) {
|
||||
await BrowserTestUtils.withNewTab(url, async function(browser2) {
|
||||
is(browser2.frameLoader.tabParent.osPid, privilegedPid,
|
||||
"Check that about:newtab tabs are in the same privileged content process.");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Services.ppmm.releaseCachedProcesses();
|
||||
});
|
||||
|
||||
/*
|
||||
* Test to ensure that a process switch occurs when navigating between normal
|
||||
* web pages and Activity Stream pages in the same tab.
|
||||
*/
|
||||
add_task(async function process_switching_through_loading_in_the_same_tab() {
|
||||
Services.ppmm.releaseCachedProcesses();
|
||||
|
||||
await BrowserTestUtils.withNewTab(TEST_HTTP, async function(browser) {
|
||||
await checkBrowserRemoteType(browser, E10SUtils.WEB_REMOTE_TYPE);
|
||||
|
||||
for (let [url, remoteType] of [
|
||||
[ABOUT_NEWTAB, E10SUtils.PRIVILEGED_REMOTE_TYPE],
|
||||
[ABOUT_BLANK, E10SUtils.PRIVILEGED_REMOTE_TYPE],
|
||||
[TEST_HTTP, E10SUtils.WEB_REMOTE_TYPE],
|
||||
[ABOUT_HOME, E10SUtils.PRIVILEGED_REMOTE_TYPE],
|
||||
[TEST_HTTP, E10SUtils.WEB_REMOTE_TYPE],
|
||||
[ABOUT_WELCOME, E10SUtils.PRIVILEGED_REMOTE_TYPE],
|
||||
[TEST_HTTP, E10SUtils.WEB_REMOTE_TYPE],
|
||||
[ABOUT_BLANK, E10SUtils.WEB_REMOTE_TYPE],
|
||||
[`${ABOUT_NEWTAB}#foo`, E10SUtils.PRIVILEGED_REMOTE_TYPE],
|
||||
[TEST_HTTP, E10SUtils.WEB_REMOTE_TYPE],
|
||||
[`${ABOUT_WELCOME}#bar`, E10SUtils.PRIVILEGED_REMOTE_TYPE],
|
||||
[TEST_HTTP, E10SUtils.WEB_REMOTE_TYPE],
|
||||
[`${ABOUT_HOME}#baz`, E10SUtils.PRIVILEGED_REMOTE_TYPE],
|
||||
[TEST_HTTP, E10SUtils.WEB_REMOTE_TYPE],
|
||||
[`${ABOUT_NEWTAB}?q=foo`, E10SUtils.PRIVILEGED_REMOTE_TYPE],
|
||||
[TEST_HTTP, E10SUtils.WEB_REMOTE_TYPE],
|
||||
[`${ABOUT_WELCOME}?q=bar`, E10SUtils.PRIVILEGED_REMOTE_TYPE],
|
||||
[TEST_HTTP, E10SUtils.WEB_REMOTE_TYPE],
|
||||
[`${ABOUT_HOME}?q=baz`, E10SUtils.PRIVILEGED_REMOTE_TYPE],
|
||||
[TEST_HTTP, E10SUtils.WEB_REMOTE_TYPE]
|
||||
]) {
|
||||
BrowserTestUtils.loadURI(browser, url);
|
||||
await BrowserTestUtils.browserLoaded(browser, false, url);
|
||||
await checkBrowserRemoteType(browser, remoteType);
|
||||
}
|
||||
});
|
||||
|
||||
Services.ppmm.releaseCachedProcesses();
|
||||
});
|
||||
|
||||
/*
|
||||
* Test to ensure that a process switch occurs when navigating between normal
|
||||
* web pages and Activity Stream pages using the browser's navigation features
|
||||
* such as history and location change.
|
||||
*/
|
||||
add_task(async function process_switching_through_navigation_features() {
|
||||
Services.ppmm.releaseCachedProcesses();
|
||||
|
||||
await BrowserTestUtils.withNewTab(ABOUT_NEWTAB, async function(browser) {
|
||||
await checkBrowserRemoteType(browser, E10SUtils.PRIVILEGED_REMOTE_TYPE);
|
||||
|
||||
// Note the processID for about:newtab for comparison later.
|
||||
let privilegedPid = browser.frameLoader.tabParent.osPid;
|
||||
|
||||
// Check that about:newtab opened from JS in about:newtab page is in the same process.
|
||||
let promiseTabOpened = BrowserTestUtils.waitForNewTab(gBrowser, ABOUT_NEWTAB, true);
|
||||
await ContentTask.spawn(browser, ABOUT_NEWTAB, uri => {
|
||||
content.open(uri, "_blank");
|
||||
});
|
||||
let newTab = await promiseTabOpened;
|
||||
registerCleanupFunction(async function() {
|
||||
BrowserTestUtils.removeTab(newTab);
|
||||
});
|
||||
browser = newTab.linkedBrowser;
|
||||
is(browser.frameLoader.tabParent.osPid, privilegedPid,
|
||||
"Check that new tab opened from about:newtab is loaded in privileged content process.");
|
||||
|
||||
// Check that reload does not break the privileged content process affinity.
|
||||
BrowserReload();
|
||||
await BrowserTestUtils.browserLoaded(browser, false, ABOUT_NEWTAB);
|
||||
is(browser.frameLoader.tabParent.osPid, privilegedPid,
|
||||
"Check that about:newtab is still in privileged content process after reload.");
|
||||
|
||||
// Load http webpage
|
||||
BrowserTestUtils.loadURI(browser, TEST_HTTP);
|
||||
await BrowserTestUtils.browserLoaded(browser, false, TEST_HTTP);
|
||||
await checkBrowserRemoteType(browser, E10SUtils.WEB_REMOTE_TYPE);
|
||||
|
||||
// Check that using the history back feature switches back to privileged content process.
|
||||
let promiseLocation = BrowserTestUtils.waitForLocationChange(gBrowser, ABOUT_NEWTAB);
|
||||
browser.goBack();
|
||||
await promiseLocation;
|
||||
// We will need to ensure that the process flip has fully completed so that
|
||||
// the navigation history data will be available when we do browser.goForward();
|
||||
await BrowserTestUtils.waitForEvent(newTab, "SSTabRestored");
|
||||
is(browser.frameLoader.tabParent.osPid, privilegedPid,
|
||||
"Check that about:newtab is still in privileged content process after history goBack.");
|
||||
|
||||
// Check that using the history forward feature switches back to the web content process.
|
||||
promiseLocation = BrowserTestUtils.waitForLocationChange(gBrowser, TEST_HTTP);
|
||||
browser.goForward();
|
||||
await promiseLocation;
|
||||
// We will need to ensure that the process flip has fully completed so that
|
||||
// the navigation history data will be available when we do browser.gotoIndex(0);
|
||||
await BrowserTestUtils.waitForEvent(newTab, "SSTabRestored");
|
||||
await checkBrowserRemoteType(browser, E10SUtils.WEB_REMOTE_TYPE,
|
||||
"Check that tab runs in the web content process after using history goForward.");
|
||||
|
||||
// Check that goto history index does not break the affinity.
|
||||
promiseLocation = BrowserTestUtils.waitForLocationChange(gBrowser, ABOUT_NEWTAB);
|
||||
browser.gotoIndex(0);
|
||||
await promiseLocation;
|
||||
is(browser.frameLoader.tabParent.osPid, privilegedPid,
|
||||
"Check that about:newtab is in privileged content process after history gotoIndex.");
|
||||
|
||||
BrowserTestUtils.loadURI(browser, TEST_HTTP);
|
||||
await BrowserTestUtils.browserLoaded(browser, false, TEST_HTTP);
|
||||
await checkBrowserRemoteType(browser, E10SUtils.WEB_REMOTE_TYPE);
|
||||
|
||||
// Check that location change causes a change in process type as well.
|
||||
await ContentTask.spawn(browser, ABOUT_NEWTAB, uri => {
|
||||
content.location = uri;
|
||||
});
|
||||
await BrowserTestUtils.browserLoaded(browser, false, ABOUT_NEWTAB);
|
||||
is(browser.frameLoader.tabParent.osPid, privilegedPid,
|
||||
"Check that about:newtab is in privileged content process after location change.");
|
||||
});
|
||||
|
||||
Services.ppmm.releaseCachedProcesses();
|
||||
});
|
|
@ -2746,6 +2746,8 @@ ContentChild::RecvRemoteType(const nsString& aRemoteType)
|
|||
SetProcessName(NS_LITERAL_STRING("file:// Content"));
|
||||
} else if (aRemoteType.EqualsLiteral(EXTENSION_REMOTE_TYPE)) {
|
||||
SetProcessName(NS_LITERAL_STRING("WebExtensions"));
|
||||
} else if (aRemoteType.EqualsLiteral(PRIVILEGED_REMOTE_TYPE)) {
|
||||
SetProcessName(NS_LITERAL_STRING("Privileged Content"));
|
||||
} else if (aRemoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
|
||||
SetProcessName(NS_LITERAL_STRING("Large Allocation Web Content"));
|
||||
}
|
||||
|
|
|
@ -1857,8 +1857,8 @@ ContentParent::ShouldKeepProcessAlive() const
|
|||
return false;
|
||||
}
|
||||
|
||||
// We might want to keep alive some content processes alive during test runs,
|
||||
// for performance reasons. This should never be used in production.
|
||||
// We might want to keep some content processes alive for performance reasons.
|
||||
// e.g. test runs and privileged content process for some about: pages.
|
||||
// We don't want to alter behavior if the pref is not set, so default to 0.
|
||||
int32_t processesToKeepAlive = 0;
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#define DEFAULT_REMOTE_TYPE "web"
|
||||
#define FILE_REMOTE_TYPE "file"
|
||||
#define EXTENSION_REMOTE_TYPE "extension"
|
||||
#define PRIVILEGED_REMOTE_TYPE "privileged"
|
||||
|
||||
// This must start with the DEFAULT_REMOTE_TYPE above.
|
||||
#define LARGE_ALLOCATION_REMOTE_TYPE "webLargeAllocation"
|
||||
|
|
|
@ -192,6 +192,9 @@ ScriptPreloader::GetChildProcessType(const nsAString& remoteType)
|
|||
if (remoteType.EqualsLiteral(EXTENSION_REMOTE_TYPE)) {
|
||||
return ProcessType::Extension;
|
||||
}
|
||||
if (remoteType.EqualsLiteral(PRIVILEGED_REMOTE_TYPE)) {
|
||||
return ProcessType::Privileged;
|
||||
}
|
||||
return ProcessType::Web;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace loader {
|
|||
Parent,
|
||||
Web,
|
||||
Extension,
|
||||
Privileged,
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -20,6 +20,7 @@ class ProcessTypes:
|
|||
Default = 0
|
||||
Web = 1
|
||||
Extension = 2
|
||||
Privileged = 3
|
||||
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
@ -32,6 +33,8 @@ class ProcessTypes:
|
|||
res.append('Web')
|
||||
if self.val & (1 << self.Extension):
|
||||
res.append('Extension')
|
||||
if self.val & (1 << self.Privileged):
|
||||
res.append('Privileged')
|
||||
return '|'.join(res)
|
||||
|
||||
|
||||
|
|
|
@ -3218,6 +3218,14 @@ pref("dom.ipc.processCount.file", 1);
|
|||
// WebExtensions only support a single extension process.
|
||||
pref("dom.ipc.processCount.extension", 1);
|
||||
|
||||
// Privileged content only supports a single content process.
|
||||
pref("dom.ipc.processCount.privileged", 1);
|
||||
|
||||
// Keep a single privileged content process alive for performance reasons.
|
||||
// e.g. we do not want to throw content processes out every time we navigate
|
||||
// away from about:newtab.
|
||||
pref("dom.ipc.keepProcessesAlive.privileged", 1);
|
||||
|
||||
// Whether a native event loop should be used in the content process.
|
||||
#if defined(XP_WIN)
|
||||
pref("dom.ipc.useNativeEventProcessing.content", false);
|
||||
|
@ -3254,6 +3262,9 @@ pref("browser.tabs.remote.separateFileUriProcess", true);
|
|||
// content process, causes compatibility issues.
|
||||
pref("browser.tabs.remote.allowLinkedWebInFileUriProcess", true);
|
||||
|
||||
// Pref to control whether we use separate privileged content processes.
|
||||
pref("browser.tabs.remote.separatePrivilegedContentProcess", false);
|
||||
|
||||
// Enable the use of display-lists for SVG hit-testing and painting.
|
||||
pref("svg.display-lists.hit-testing.enabled", true);
|
||||
pref("svg.display-lists.painting.enabled", true);
|
||||
|
|
|
@ -13,6 +13,8 @@ XPCOMUtils.defineLazyPreferenceGetter(this, "useSeparateFileUriProcess",
|
|||
"browser.tabs.remote.separateFileUriProcess", false);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "allowLinkedWebInFileUriProcess",
|
||||
"browser.tabs.remote.allowLinkedWebInFileUriProcess", false);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "useSeparatePrivilegedContentProcess",
|
||||
"browser.tabs.remote.separatePrivilegedContentProcess", false);
|
||||
ChromeUtils.defineModuleGetter(this, "Utils",
|
||||
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||
|
||||
|
@ -35,11 +37,14 @@ const NOT_REMOTE = null;
|
|||
const WEB_REMOTE_TYPE = "web";
|
||||
const FILE_REMOTE_TYPE = "file";
|
||||
const EXTENSION_REMOTE_TYPE = "extension";
|
||||
const PRIVILEGED_REMOTE_TYPE = "privileged";
|
||||
|
||||
// This must start with the WEB_REMOTE_TYPE above.
|
||||
const LARGE_ALLOCATION_REMOTE_TYPE = "webLargeAllocation";
|
||||
const DEFAULT_REMOTE_TYPE = WEB_REMOTE_TYPE;
|
||||
|
||||
const ACTIVITY_STREAM_PAGES = new Set(["home", "newtab", "welcome"]);
|
||||
|
||||
function validatedWebRemoteType(aPreferredRemoteType, aTargetUri, aCurrentUri) {
|
||||
// If the domain is whitelisted to allow it to use file:// URIs, then we have
|
||||
// to run it in a file content process, in case it uses file:// sub-resources.
|
||||
|
@ -82,6 +87,7 @@ var E10SUtils = {
|
|||
WEB_REMOTE_TYPE,
|
||||
FILE_REMOTE_TYPE,
|
||||
EXTENSION_REMOTE_TYPE,
|
||||
PRIVILEGED_REMOTE_TYPE,
|
||||
LARGE_ALLOCATION_REMOTE_TYPE,
|
||||
|
||||
canLoadURIInProcess(aURL, aProcess) {
|
||||
|
@ -153,6 +159,11 @@ var E10SUtils = {
|
|||
|
||||
let flags = module.getURIFlags(aURI);
|
||||
if (flags & Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD) {
|
||||
// Load Activity Stream in a separate process.
|
||||
if (useSeparatePrivilegedContentProcess &&
|
||||
ACTIVITY_STREAM_PAGES.has(aURI.filePath)) {
|
||||
return PRIVILEGED_REMOTE_TYPE;
|
||||
}
|
||||
return DEFAULT_REMOTE_TYPE;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче