summaryrefslogtreecommitdiffstats
path: root/toolkit/modules/tests/xpcshell/test_E10SUtils_workers_remote_types.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--toolkit/modules/tests/xpcshell/test_E10SUtils_workers_remote_types.js424
1 files changed, 424 insertions, 0 deletions
diff --git a/toolkit/modules/tests/xpcshell/test_E10SUtils_workers_remote_types.js b/toolkit/modules/tests/xpcshell/test_E10SUtils_workers_remote_types.js
new file mode 100644
index 0000000000..69fda19055
--- /dev/null
+++ b/toolkit/modules/tests/xpcshell/test_E10SUtils_workers_remote_types.js
@@ -0,0 +1,424 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+
+const { E10SUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/E10SUtils.sys.mjs"
+);
+
+const URI_SECURE_COM = Services.io.newURI("https://example.com");
+const URI_SECURE_ORG = Services.io.newURI("https://example.org");
+const URI_INSECURE_ORG = Services.io.newURI("http://example.org");
+const URI_FILE = Services.io.newURI("file:///path/to/dir");
+const URI_EXTENSION = Services.io.newURI("moz-extension://fake-uuid");
+const URI_EXT_PROTOCOL = Services.io.newURI("ext+custom://fake-url");
+const URI_WEB_PROTOCOL = Services.io.newURI("web+custom://fake-url");
+const URI_PRIVILEGEDMOZILLA = Services.io.newURI("https://addons.mozilla.org");
+
+const fakeContentScriptSandbox = Cu.Sandbox(
+ ["https://example.org", "moz-extension://fake-uuid"],
+ {}
+);
+
+const ssm = Services.scriptSecurityManager;
+const systemPrincipal = ssm.getSystemPrincipal();
+const nullPrincipal = ssm.createNullPrincipal({});
+const principalSecureCom = ssm.createContentPrincipal(URI_SECURE_COM, {});
+const principalSecureOrg = ssm.createContentPrincipal(URI_SECURE_ORG, {});
+const principalInsecureOrg = ssm.createContentPrincipal(URI_INSECURE_ORG, {});
+const principalFile = ssm.createContentPrincipal(URI_FILE, {});
+const principalExtension = ssm.createContentPrincipal(URI_EXTENSION, {});
+const principalExpanded = Cu.getObjectPrincipal(fakeContentScriptSandbox);
+const principalExtProtocol = ssm.createContentPrincipal(URI_EXT_PROTOCOL, {});
+const principalWebProtocol = ssm.createContentPrincipal(URI_WEB_PROTOCOL, {});
+const principalPrivilegedMozilla = ssm.createContentPrincipal(
+ URI_PRIVILEGEDMOZILLA,
+ {}
+);
+
+const {
+ EXTENSION_REMOTE_TYPE,
+ FILE_REMOTE_TYPE,
+ FISSION_WEB_REMOTE_TYPE,
+ NOT_REMOTE,
+ PRIVILEGEDABOUT_REMOTE_TYPE,
+ PRIVILEGEDMOZILLA_REMOTE_TYPE,
+ SERVICEWORKER_REMOTE_TYPE,
+ WEB_REMOTE_COOP_COEP_TYPE_PREFIX,
+ WEB_REMOTE_TYPE,
+} = E10SUtils;
+
+const { REMOTE_WORKER_TYPE_SHARED, REMOTE_WORKER_TYPE_SERVICE } =
+ Ci.nsIE10SUtils;
+
+// Test ServiceWorker remoteType selection with multiprocess and/or site
+// isolation enabled.
+add_task(function test_get_remote_type_for_service_worker() {
+ // ServiceWorkers with system or null principal are unexpected and we expect
+ // the method call to throw.
+ for (const principal of [systemPrincipal, nullPrincipal]) {
+ Assert.throws(
+ () =>
+ E10SUtils.getRemoteTypeForWorkerPrincipal(
+ principal,
+ REMOTE_WORKER_TYPE_SERVICE,
+ true,
+ false
+ ),
+ /Unexpected system or null principal/,
+ `Did raise an exception on "${principal.origin}" principal ServiceWorker`
+ );
+ }
+
+ // ServiceWorker test cases:
+ // - e10s + fission disabled:
+ // - extension principal + any preferred remote type => extension remote type
+ // - content principal + any preferred remote type => web remote type
+ // - fission enabled:
+ // - extension principal + any preferred remote type => extension remote type
+ // - content principal + any preferred remote type => webServiceWorker=siteOrigin remote type
+ function* getTestCase(fission = false) {
+ const TEST_PRINCIPALS = [
+ principalSecureCom,
+ principalSecureOrg,
+ principalExtension,
+ ];
+
+ const PREFERRED_REMOTE_TYPES = [
+ E10SUtils.DEFAULT_REMOTE_TYPE,
+ E10SUtils.WEB_REMOTE_TYPE,
+ "fakeRemoteType",
+ ];
+
+ for (const principal of TEST_PRINCIPALS) {
+ for (const preferred of PREFERRED_REMOTE_TYPES) {
+ const msg = `ServiceWorker, principal=${
+ principal.origin
+ }, preferredRemoteType=${preferred}, ${fission ? "fission" : "e10s"}`;
+ yield [
+ msg,
+ principal,
+ REMOTE_WORKER_TYPE_SERVICE,
+ true,
+ fission,
+ preferred,
+ ];
+ }
+ }
+ }
+
+ // Test cases for e10s mode + fission disabled.
+ for (const testCase of getTestCase(false)) {
+ const [msg, principal, ...args] = testCase;
+ let expected = E10SUtils.WEB_REMOTE_TYPE;
+
+ if (principal == principalExtension) {
+ expected = WebExtensionPolicy.useRemoteWebExtensions
+ ? E10SUtils.EXTENSION_REMOTE_TYPE
+ : E10SUtils.NOT_REMOTE;
+ }
+
+ equal(
+ E10SUtils.getRemoteTypeForWorkerPrincipal(principal, ...args),
+ expected,
+ msg
+ );
+ }
+
+ // Test cases for e10s mode + fission enabled.
+ for (const testCase of getTestCase(true)) {
+ const [msg, principal, ...args] = testCase;
+ let expected = `${SERVICEWORKER_REMOTE_TYPE}=${principal.siteOrigin}`;
+
+ if (principal == principalExtension) {
+ expected = WebExtensionPolicy.useRemoteWebExtensions
+ ? E10SUtils.EXTENSION_REMOTE_TYPE
+ : E10SUtils.NOT_REMOTE;
+ }
+
+ equal(
+ E10SUtils.getRemoteTypeForWorkerPrincipal(principal, ...args),
+ expected,
+ msg
+ );
+ }
+});
+
+// Test SharedWorker remoteType selection with multiprocess and/or site
+// isolation enabled.
+add_task(function test_get_remote_type_for_shared_worker() {
+ // Verify that for shared worker registered from a web coop+coep remote type
+ // we are going to select a web or fission remote type.
+ for (const [principal, preferredRemoteType] of [
+ [
+ principalSecureCom,
+ `${WEB_REMOTE_COOP_COEP_TYPE_PREFIX}=${principalSecureCom.siteOrigin}`,
+ ],
+ ]) {
+ equal(
+ E10SUtils.getRemoteTypeForWorkerPrincipal(
+ principal,
+ REMOTE_WORKER_TYPE_SHARED,
+ true,
+ false,
+ preferredRemoteType
+ ),
+ WEB_REMOTE_TYPE,
+ `Got WEB_REMOTE_TYPE on preferred ${preferredRemoteType} and fission disabled`
+ );
+
+ equal(
+ E10SUtils.getRemoteTypeForWorkerPrincipal(
+ principal,
+ REMOTE_WORKER_TYPE_SHARED,
+ true,
+ true,
+ preferredRemoteType
+ ),
+ `${FISSION_WEB_REMOTE_TYPE}=${principal.siteOrigin}`,
+ `Got WEB_REMOTE_TYPE on preferred ${preferredRemoteType} and fission enabled`
+ );
+ }
+
+ // For System principal shared worker we do select NOT_REMOTE or the preferred
+ // remote type if is one of the explicitly allowed (NOT_REMOTE and
+ // PRIVILEGEDABOUT_REMOTE_TYPE).
+ for (const [principal, preferredRemoteType] of [
+ [systemPrincipal, NOT_REMOTE],
+ [systemPrincipal, PRIVILEGEDABOUT_REMOTE_TYPE],
+ ]) {
+ equal(
+ E10SUtils.getRemoteTypeForWorkerPrincipal(
+ principal,
+ REMOTE_WORKER_TYPE_SHARED,
+ true,
+ true,
+ preferredRemoteType
+ ),
+ preferredRemoteType,
+ `Selected the preferred ${preferredRemoteType} on system principal shared worker`
+ );
+ }
+
+ Assert.throws(
+ () =>
+ E10SUtils.getRemoteTypeForWorkerPrincipal(
+ systemPrincipal,
+ REMOTE_WORKER_TYPE_SHARED,
+ true,
+ true,
+ "fakeRemoteType"
+ ),
+ /Failed to get a remoteType/,
+ "Does fail explicitly on system worker for arbitrary preferredRemoteType"
+ );
+
+ // Behavior NOT_REMOTE preferredRemoteType for content principals with
+ // multiprocess enabled.
+ for (const [principal, expectedRemoteType] of [
+ [
+ principalSecureCom,
+ `${FISSION_WEB_REMOTE_TYPE}=${principalSecureCom.siteOrigin}`,
+ ],
+ [
+ principalExtension,
+ WebExtensionPolicy.useRemoteWebExtensions
+ ? EXTENSION_REMOTE_TYPE
+ : NOT_REMOTE,
+ ],
+ ]) {
+ equal(
+ E10SUtils.getRemoteTypeForWorkerPrincipal(
+ principal,
+ REMOTE_WORKER_TYPE_SHARED,
+ true,
+ true,
+ NOT_REMOTE
+ ),
+ expectedRemoteType,
+ `Got ${expectedRemoteType} for content principal ${principal.siteOrigin}`
+ );
+ }
+
+ // Shared worker registered for web+custom urls.
+ for (const [preferredRemoteType, expectedRemoteType] of [
+ [WEB_REMOTE_TYPE, WEB_REMOTE_TYPE],
+ ["fakeRemoteType", "fakeRemoteType"],
+ // This seems to be actually failing with a SecurityError
+ // as soon as the SharedWorker constructor is being called with
+ // a web+...:// url from an extension principal:
+ //
+ // [EXTENSION_REMOTE_TYPE, EXTENSION_REMOTE_TYPE],
+ ]) {
+ equal(
+ E10SUtils.getRemoteTypeForWorkerPrincipal(
+ principalWebProtocol,
+ REMOTE_WORKER_TYPE_SHARED,
+ true,
+ true,
+ preferredRemoteType
+ ),
+ expectedRemoteType,
+ "Selected expected process for web+custom:// shared worker"
+ );
+ }
+
+ // Shared worker registered for ext+custom urls.
+ for (const [preferredRemoteType, expectedRemoteType] of [
+ [WEB_REMOTE_TYPE, WEB_REMOTE_TYPE],
+ ["fakeRemoteType", "fakeRemoteType"],
+ // This seems to be actually prevented by failing a ClientIsValidPrincipalInfo
+ // check (but only when the remote worker is being launched in the child process
+ // and so after a remote Type has been selected).
+ // [EXTENSION_REMOTE_TYPE, EXTENSION_REMOTE_TYPE],
+ ]) {
+ equal(
+ E10SUtils.getRemoteTypeForWorkerPrincipal(
+ principalExtProtocol,
+ REMOTE_WORKER_TYPE_SHARED,
+ true,
+ true,
+ preferredRemoteType
+ ),
+ expectedRemoteType,
+ "Selected expected process for ext+custom:// shared worker"
+ );
+ }
+
+ // Shared worker with a file principal.
+ // NOTE: on android useSeparateFileUriProcess will be false and file uri are
+ // going to run in the default web process.
+ const expectedFileRemoteType = Services.prefs.getBoolPref(
+ "browser.tabs.remote.separateFileUriProcess",
+ false
+ )
+ ? FILE_REMOTE_TYPE
+ : WEB_REMOTE_TYPE;
+
+ for (const [preferredRemoteType, expectedRemoteType] of [
+ [WEB_REMOTE_TYPE, expectedFileRemoteType],
+ ["fakeRemoteType", expectedFileRemoteType],
+ ]) {
+ equal(
+ E10SUtils.getRemoteTypeForWorkerPrincipal(
+ principalFile,
+ REMOTE_WORKER_TYPE_SHARED,
+ true,
+ true,
+ preferredRemoteType
+ ),
+ expectedRemoteType,
+ "Got expected remote type on file principal shared worker"
+ );
+ }
+
+ // Shared worker related to a privilegedmozilla domain.
+ // NOTE: separatePrivilegedMozilla will be false on android builds.
+ const usePrivilegedMozilla = Services.prefs.getBoolPref(
+ "browser.tabs.remote.separatePrivilegedMozillaWebContentProcess",
+ false
+ );
+ const expectedRemoteType = usePrivilegedMozilla
+ ? PRIVILEGEDMOZILLA_REMOTE_TYPE
+ : `${FISSION_WEB_REMOTE_TYPE}=https://mozilla.org`;
+ for (const preferredRemoteType of [
+ PRIVILEGEDMOZILLA_REMOTE_TYPE,
+ "fakeRemoteType",
+ ]) {
+ equal(
+ E10SUtils.getRemoteTypeForWorkerPrincipal(
+ principalPrivilegedMozilla,
+ REMOTE_WORKER_TYPE_SHARED,
+ true,
+ true,
+ preferredRemoteType
+ ),
+ expectedRemoteType,
+ "Got expected remote type on privilegedmozilla principal shared worker"
+ );
+ }
+});
+
+// Test that we do throw on expanded principals.
+add_task(function test_get_remote_type_throws_on_expanded_principals() {
+ for (const workerType of [
+ REMOTE_WORKER_TYPE_SHARED,
+ REMOTE_WORKER_TYPE_SERVICE,
+ ]) {
+ Assert.throws(
+ () =>
+ E10SUtils.getRemoteTypeForWorkerPrincipal(
+ principalExpanded,
+ workerType,
+ true,
+ false
+ ),
+ /Unexpected expanded principal/,
+ "Did raise an exception as expected"
+ );
+ }
+});
+
+// Test that NO_REMOTE is the remote type selected when multiprocess is disabled,
+// there is no other checks special behaviors on particular principal or worker type.
+add_task(function test_get_remote_type_multiprocess_disabled() {
+ function* getTestCase() {
+ const TEST_PRINCIPALS = [
+ systemPrincipal,
+ nullPrincipal,
+ principalSecureCom,
+ principalSecureOrg,
+ principalInsecureOrg,
+ principalFile,
+ principalExtension,
+ ];
+
+ const PREFERRED_REMOTE_TYPES = [
+ E10SUtils.DEFAULT_REMOTE_TYPE,
+ E10SUtils.WEB_REMOTE_TYPE,
+ "fakeRemoteType",
+ ];
+
+ for (const principal of TEST_PRINCIPALS) {
+ for (const preferred of PREFERRED_REMOTE_TYPES) {
+ const msg = `SharedWorker, principal=${principal.origin}, preferredRemoteType=${preferred}`;
+ yield [
+ msg,
+ principal,
+ REMOTE_WORKER_TYPE_SHARED,
+ false,
+ false,
+ preferred,
+ ];
+ }
+ }
+
+ for (const principal of TEST_PRINCIPALS) {
+ // system and null principals are disallowed for service workers, we throw
+ // if passed to the E10SUtils method and we cover this scenario with a
+ // separate test.
+ if (principal.isSystemPrincipal || principal.isNullPrincipal) {
+ continue;
+ }
+ for (const preferred of PREFERRED_REMOTE_TYPES) {
+ const msg = `ServiceWorker with principal ${principal.origin} and preferredRemoteType ${preferred}`;
+ yield [
+ msg,
+ principal,
+ REMOTE_WORKER_TYPE_SERVICE,
+ false,
+ false,
+ preferred,
+ ];
+ }
+ }
+ }
+
+ for (const testCase of getTestCase()) {
+ const [msg, ...args] = testCase;
+ equal(
+ E10SUtils.getRemoteTypeForWorkerPrincipal(...args),
+ E10SUtils.NOT_REMOTE,
+ `Expect NOT_REMOTE on disabled multiprocess: ${msg}`
+ );
+ }
+});