summaryrefslogtreecommitdiffstats
path: root/dom/workers/test/xpcshell/test_remoteworker_launch_new_process.js
blob: e13b0fc96c89bf13e990261a17eff4b569e0f456 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";

const { TestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/TestUtils.sys.mjs"
);

const { AddonTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/AddonTestUtils.sys.mjs"
);
const { createHttpServer } = AddonTestUtils;

// Force ServiceWorkerRegistrar to init by calling do_get_profile.
// (This has to be called before AddonTestUtils.init, because it does
// also call do_get_profile internally but it doesn't notify
// profile-after-change).
do_get_profile(true);

AddonTestUtils.init(this);

const server = createHttpServer({ hosts: ["localhost"] });

server.registerPathHandler("/sw.js", (request, response) => {
  info(`/sw.js is being requested: ${JSON.stringify(request)}`);
  response.setHeader("Content-Type", "application/javascript");
  response.write("");
});

add_task(async function setup_prefs() {
  equal(
    Services.prefs.getBoolPref("browser.tabs.remote.autostart"),
    true,
    "e10s is expected to be enabled"
  );

  // Enable nsIServiceWorkerManager.registerForTest.
  Services.prefs.setBoolPref("dom.serviceWorkers.testing.enabled", true);

  registerCleanupFunction(() => {
    Services.prefs.clearUserPref("dom.serviceWorkers.testing.enabled");
  });
});

/**
 * This test installs a ServiceWorker via test API and verify that the install
 * process spawns a new process. (Normally ServiceWorker installation won't
 * cause a new content process to be spawned because the call to register must
 * be coming from within an existing content process, but the registerForTest
 * API allows us to bypass this restriction.)
 *
 * This models the real-world situation of a push notification being received
 * from the network which results in a ServiceWorker being spawned without their
 * necessarily being an existing content process to host it (especially under Fission).
 */
add_task(async function launch_remoteworkers_in_new_processes() {
  const swm = Cc["@mozilla.org/serviceworkers/manager;1"].getService(
    Ci.nsIServiceWorkerManager
  );

  const ssm = Services.scriptSecurityManager;

  const initialChildCount = Services.ppmm.childCount;

  // A test service worker that should spawn a regular web content child process.
  const swRegInfoWeb = await swm.registerForTest(
    ssm.createContentPrincipal(Services.io.newURI("http://localhost"), {}),
    "http://localhost/scope",
    "http://localhost/sw.js"
  );
  swRegInfoWeb.QueryInterface(Ci.nsIServiceWorkerRegistrationInfo);

  info(
    `web content service worker registered: ${JSON.stringify({
      principal: swRegInfoWeb.principal.spec,
      scope: swRegInfoWeb.scope,
    })}`
  );

  info("Wait new process to be launched");
  await TestUtils.waitForCondition(() => {
    return Services.ppmm.childCount - initialChildCount >= 1;
  }, "wait for a new child processes to be started");

  // Wait both workers to become active to be sure that. besides spawning
  // the new child processes as expected, the two remote worker have been
  // able to run successfully (in other word their remote worker data did
  // pass successfull the IsRemoteTypeAllowed check in RemoteworkerChild).
  info("Wait for webcontent worker to become active");
  await TestUtils.waitForCondition(
    () => swRegInfoWeb.activeWorker,
    `wait workers for scope ${swRegInfoWeb.scope} to be active`
  );
});