Bug 1738765: Process-isolate ServiceWorkers if they match an allow-list of sites r=nika,fluent-reviewers,flod

Differential Revision: https://phabricator.services.mozilla.com/D130113
This commit is contained in:
Randell Jesup 2021-11-08 19:53:06 +00:00
Родитель 5ba898abab
Коммит b257161e3a
12 изменённых файлов: 99 добавлений и 14 удалений

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

@ -852,6 +852,8 @@ static WebIDLProcType ProcTypeToWebIDL(mozilla::ProcType aType) {
"In order for this static cast to be okay, "
"WebIDLProcType must match ProcType exactly");
// These must match the similar ones in E10SUtils.jsm, RemoteTypes.h,
// ProcInfo.h and ChromeUtils.webidl
switch (aType) {
PROCTYPE_TO_WEBIDL_CASE(Web, Web);
PROCTYPE_TO_WEBIDL_CASE(WebIsolated, WebIsolated);
@ -860,6 +862,7 @@ static WebIDLProcType ProcTypeToWebIDL(mozilla::ProcType aType) {
PROCTYPE_TO_WEBIDL_CASE(PrivilegedAbout, Privilegedabout);
PROCTYPE_TO_WEBIDL_CASE(PrivilegedMozilla, Privilegedmozilla);
PROCTYPE_TO_WEBIDL_CASE(WebCOOPCOEP, WithCoopCoep);
PROCTYPE_TO_WEBIDL_CASE(WebServiceWorker, WebServiceWorker);
PROCTYPE_TO_WEBIDL_CASE(WebLargeAllocation, WebLargeAllocation);
PROCTYPE_TO_WEBIDL_CASE(Browser, Browser);
PROCTYPE_TO_WEBIDL_CASE(IPDLUnitTest, IpdlUnitTest);
@ -1018,6 +1021,8 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
// `DEFAULT_REMOTE_TYPE` is a prefix of
// `FISSION_WEB_REMOTE_TYPE`.
type = mozilla::ProcType::WebIsolated;
} else if (StringBeginsWith(remoteType, SERVICEWORKER_REMOTE_TYPE)) {
type = mozilla::ProcType::WebServiceWorker;
} else if (StringBeginsWith(remoteType,
WITH_COOP_COEP_REMOTE_TYPE_PREFIX)) {
type = mozilla::ProcType::WebCOOPCOEP;

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

@ -597,6 +597,7 @@ partial namespace ChromeUtils {
/*
* This type is a WebIDL representation of mozilla::ProcType.
* These must match the similar ones in E10SUtils.jsm, RemoteTypes.h, ProcInfo.h and ChromeUtils.cpp
*/
enum WebIDLProcType {
"web",
@ -607,6 +608,7 @@ enum WebIDLProcType {
"privilegedmozilla",
"webLargeAllocation",
"withCoopCoep",
"webServiceWorker",
"browser",
"ipdlUnitTest",
"gmpPlugin",

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

@ -2739,6 +2739,11 @@ mozilla::ipc::IPCResult ContentChild::RecvRemoteType(
nsDependentCSubstring etld =
Substring(aRemoteType, FISSION_WEB_REMOTE_TYPE.Length() + 1);
SetProcessName("Isolated Web Content"_ns, &etld);
} else if (remoteTypePrefix == SERVICEWORKER_REMOTE_TYPE) {
// The profiler can sanitize out the eTLD+1
nsDependentCSubstring etld =
Substring(aRemoteType, SERVICEWORKER_REMOTE_TYPE.Length() + 1);
SetProcessName("Isolated Service Worker"_ns, &etld);
}
// else "prealloc" or "web" type -> "Web Content" already set

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

@ -10,8 +10,8 @@
#include "nsString.h"
#include "nsReadableUtils.h"
// These must match the similar ones in E10SUtils.jsm and ProcInfo.h.
// Process names as reported by about:memory are defined in
// These must match the similar ones in E10SUtils.jsm and ProcInfo.h and
// ChromeUtils.webidl Process names as reported by about:memory are defined in
// ContentChild:RecvRemoteType. Add your value there too or it will be called
// "Web Content".
#define PREALLOC_REMOTE_TYPE "prealloc"_ns
@ -28,6 +28,7 @@
#define WITH_COOP_COEP_REMOTE_TYPE "webCOOP+COEP"_ns
#define WITH_COOP_COEP_REMOTE_TYPE_PREFIX "webCOOP+COEP="_ns
#define LARGE_ALLOCATION_REMOTE_TYPE "webLargeAllocation"_ns
#define SERVICEWORKER_REMOTE_TYPE "webServiceWorker"_ns
// Remote type value used to represent being non-remote.
#define NOT_REMOTE_TYPE VoidCString()

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

@ -235,11 +235,19 @@ async function do_test_sw(host, remoteType, swMode, fileBlob) {
.filter(swURL => swURL == url);
}
);
Assert.deepEqual(
workerDebuggerURLs,
[sw],
"The worker should be running in the correct child process"
);
if (remoteType.startsWith("webServiceWorker=")) {
Assert.notDeepEqual(
workerDebuggerURLs,
[sw],
"Isolated workers should not be running in the content child process"
);
} else {
Assert.deepEqual(
workerDebuggerURLs,
[sw],
"The worker should be running in the correct child process"
);
}
// Unregister the ServiceWorker. The registration will continue to control
// `browser` and therefore continue to exist and its worker to continue
@ -319,5 +327,24 @@ add_task(async function test() {
await do_test_sw(fissionUrl, fissionRemoteType, "synthetic", null);
await do_test_sw(fissionUrl, fissionRemoteType, "synthetic", fileBlob);
// ## ServiceWorker isolation via allow-list
const isolateUrl = "example.com";
const isolateRemoteType = `webServiceWorker=https://` + isolateUrl;
await SpecialPowers.pushPrefEnv({
set: [
[
"browser.tabs.remote.serviceWorkerIsolationList",
"https://" + isolateUrl,
],
[
"browser.tabs.remote.separatePrivilegedMozillaWebContentProcess",
false,
],
["browser.tabs.remote.separatedMozillaDomains", ""],
],
});
await do_test_sw(isolateUrl, isolateRemoteType, "synthetic", null);
await do_test_sw(isolateUrl, isolateRemoteType, "synthetic", fileBlob);
}
});

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

@ -1421,6 +1421,14 @@
value: true
mirror: always
# Temporary pref which makes certain ServiceWorkers be isolated in special
# processes instead of within a the normal web/webIsolated process based on
# the URI. Entries are separated by commas
- name: browser.tabs.remote.serviceWorkerIsolationList
type: String
value: ""
mirror: never
# When this pref is enabled, opaque response is only allowed to enter the
# content process if it's a response for media (audio, image, video), CSS, or
# JavaScript.

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

@ -463,6 +463,10 @@ var View = {
fluentName = "about-processes-web-isolated-process";
fluentArgs.origin = data.origin;
break;
case "webServiceWorker":
fluentName = "about-processes-web-serviceworker";
fluentArgs.origin = data.origin;
break;
case "webLargeAllocation":
fluentName = "about-processes-web-large-allocation-process";
fluentArgs.origin = data.origin;
@ -647,7 +651,7 @@ var View = {
let killButton = cpuCell.nextSibling;
killButton.className = "action-icon";
if (["web", "webIsolated", "webLargeAllocation"].includes(data.type)) {
if (data.type.startsWith("web")) {
// This type of process can be killed.
if (this._killedRecently.some(kill => kill.pid && kill.pid == data.pid)) {
// We're racing between the "kill" action and the visual refresh.
@ -1336,6 +1340,7 @@ var Control = {
return RANK_BROWSER;
// Web content comes next.
case "webIsolated":
case "webServiceWorker":
case "webLargeAllocation":
case "withCoopCoep": {
if (windows.some(w => w.tab)) {

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

@ -31,7 +31,7 @@ nsresult GetCpuTimeSinceProcessStartInMs(uint64_t* aResult);
// WebIDLProcType, ChromeUtils::RequestProcInfo and ProcTypeToWebIDL to
// mirror the changes.
enum class ProcType {
// These must match the ones in ContentParent.h, and E10SUtils.jsm
// These must match the ones in RemoteType.h, and E10SUtils.jsm
Web,
WebIsolated,
File,
@ -40,6 +40,7 @@ enum class ProcType {
PrivilegedMozilla,
WebLargeAllocation,
WebCOOPCOEP,
WebServiceWorker,
// the rest matches GeckoProcessTypes.h
Browser, // Default is named Browser here
IPDLUnitTest,

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

@ -64,6 +64,7 @@ about-processes-unknown-process = Other: { $type } ({ $pid })
## $origin (String) The domain name for this process.
about-processes-web-isolated-process = { $origin } ({ $pid })
about-processes-web-serviceworker = { $origin } ({ $pid }, serviceworker)
about-processes-web-large-allocation-process = { $origin } ({ $pid }, large)
about-processes-with-coop-coep-process = { $origin } ({ $pid }, cross-origin isolated)
about-processes-web-isolated-process-private = { $origin } — Private ({ $pid })

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

@ -29,6 +29,10 @@ process-type-weblargeallocation = Large Allocation
# to improve security
process-type-webisolated = Isolated Web Content
# process used to isolate a ServiceWorker to improve
# performance
process-type-webserviceworker = Isolated Service Worker
# process preallocated; may change to other types
process-type-prealloc = Preallocated

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

@ -44,6 +44,16 @@ XPCOMUtils.defineLazyPreferenceGetter(
"browser.tabs.remote.useCrossOriginOpenerPolicy",
false
);
// Preference containing the list (comma separated) of origins that will
// have ServiceWorkers isolated in special processes
XPCOMUtils.defineLazyPreferenceGetter(
this,
"serviceWorkerIsolationList",
"browser.tabs.remote.serviceWorkerIsolationList",
"",
false,
val => val.split(",")
);
XPCOMUtils.defineLazyServiceGetter(
this,
"serializationHelper",
@ -69,7 +79,7 @@ function getOriginalReaderModeURI(aURI) {
const NOT_REMOTE = null;
// These must match any similar ones in ContentParent.h and ProcInfo.h
// These must match the similar ones in RemoteTypes.h, ProcInfo.h, ChromeUtils.webidl and ChromeUtils.cpp
const WEB_REMOTE_TYPE = "web";
const FISSION_WEB_REMOTE_TYPE = "webIsolated";
const WEB_REMOTE_COOP_COEP_TYPE_PREFIX = "webCOOP+COEP=";
@ -77,6 +87,7 @@ const FILE_REMOTE_TYPE = "file";
const EXTENSION_REMOTE_TYPE = "extension";
const PRIVILEGEDABOUT_REMOTE_TYPE = "privilegedabout";
const PRIVILEGEDMOZILLA_REMOTE_TYPE = "privilegedmozilla";
const SERVICEWORKER_REMOTE_TYPE = "webServiceWorker";
// This must start with the WEB_REMOTE_TYPE above.
const LARGE_ALLOCATION_REMOTE_TYPE = "webLargeAllocation";
@ -130,7 +141,8 @@ function validatedWebRemoteType(
aResultPrincipal,
aRemoteSubframes,
aIsWorker = false,
aOriginAttributes = {}
aOriginAttributes = {},
aWorkerType = Ci.nsIE10SUtils.REMOTE_WORKER_TYPE_SHARED
) {
// To load into the Privileged Mozilla Content Process you must be https,
// and be an exact match or a subdomain of an allowlisted domain.
@ -233,7 +245,17 @@ function validatedWebRemoteType(
return aPreferredRemoteType;
}
if (
aIsWorker &&
aWorkerType === Ci.nsIE10SUtils.REMOTE_WORKER_TYPE_SERVICE &&
serviceWorkerIsolationList.some(function(val) {
return targetPrincipal.siteOriginNoSuffix == val;
})
) {
return `${SERVICEWORKER_REMOTE_TYPE}=${targetPrincipal.siteOrigin}`;
}
return `${FISSION_WEB_REMOTE_TYPE}=${targetPrincipal.siteOrigin}`;
// else fall through and probably return WEB_REMOTE_TYPE
}
if (!aPreferredRemoteType) {
@ -418,7 +440,8 @@ var E10SUtils = {
aResultPrincipal = null,
aIsSubframe = false,
aIsWorker = false,
aOriginAttributes = {}
aOriginAttributes = {},
aWorkerType = Ci.nsIE10SUtils.REMOTE_WORKER_TYPE_SHARED
) {
if (!aMultiProcess) {
return NOT_REMOTE;
@ -613,7 +636,8 @@ var E10SUtils = {
aResultPrincipal,
aRemoteSubframes,
aIsWorker,
aOriginAttributes
aOriginAttributes,
aWorkerType
);
log.debug(` validatedWebRemoteType() returning: ${remoteType}`);
return remoteType;
@ -695,7 +719,8 @@ var E10SUtils = {
aPrincipal,
false, // aIsSubFrame
true, // aIsWorker
aPrincipal.originAttributes
aPrincipal.originAttributes,
aWorkerType
);
}

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

@ -26,6 +26,7 @@ const ProcessType = Object.freeze({
privilegedmozilla: "process-type-privilegedmozilla",
web: "process-type-web",
webIsolated: "process-type-webisolated",
webServiceWorker: "process-type-webserviceworker",
webLargeAllocation: "process-type-weblargeallocation",
},