summaryrefslogtreecommitdiffstats
path: root/dom/serviceworkers/test/isolated/multi-e10s-update/browser_multie10s_update.js
blob: 457d47863cdf361277870ab53246292b60f564b7 (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"use strict";

// Testing if 2 child processes are correctly managed when they both try to do
// an SW update.

const BASE_URI =
  "http://mochi.test:8888/browser/dom/serviceworkers/test/isolated/multi-e10s-update/";

add_task(async function test_update() {
  info("Setting the prefs to having multi-e10s enabled");
  await SpecialPowers.pushPrefEnv({
    set: [
      ["dom.ipc.processCount", 4],
      ["dom.serviceWorkers.enabled", true],
      ["dom.serviceWorkers.testing.enabled", true],
    ],
  });

  let url = BASE_URI + "file_multie10s_update.html";

  info("Creating the first tab...");
  let tab1 = BrowserTestUtils.addTab(gBrowser, url);
  let browser1 = gBrowser.getBrowserForTab(tab1);
  await BrowserTestUtils.browserLoaded(browser1);

  info("Creating the second tab...");
  let tab2 = BrowserTestUtils.addTab(gBrowser, url);
  let browser2 = gBrowser.getBrowserForTab(tab2);
  await BrowserTestUtils.browserLoaded(browser2);

  let sw = BASE_URI + "server_multie10s_update.sjs";

  info("Let's make sure there are no existing registrations...");
  let existingCount = await SpecialPowers.spawn(
    browser1,
    [],
    async function () {
      const regs = await content.navigator.serviceWorker.getRegistrations();
      return regs.length;
    }
  );
  is(existingCount, 0, "Previous tests should have cleaned up!");

  info("Let's start the test...");
  /* eslint-disable no-shadow */
  let status = await SpecialPowers.spawn(browser1, [sw], function (url) {
    // Let the SW be served immediately once by triggering a relase immediately.
    // We don't need to await this.  We do this from a frame script because
    // it has fetch.
    content.fetch(url + "?release");

    // Registration of the SW
    return (
      content.navigator.serviceWorker
        .register(url)

        // Activation
        .then(function (r) {
          content.registration = r;
          return new content.window.Promise(resolve => {
            let worker = r.installing;
            worker.addEventListener("statechange", () => {
              if (worker.state === "installed") {
                resolve(true);
              }
            });
          });
        })

        // Waiting for the result.
        .then(() => {
          return new content.window.Promise(resolveResults => {
            // Once both updates have been issued and a single update has failed, we
            // can tell the .sjs to release a single copy of the SW script.
            let updateCount = 0;
            const uc = new content.window.BroadcastChannel("update");
            // This promise tracks the updates tally.
            const updatesIssued = new Promise(resolveUpdatesIssued => {
              uc.onmessage = function (e) {
                updateCount++;
                console.log("got update() number", updateCount);
                if (updateCount === 2) {
                  resolveUpdatesIssued();
                }
              };
            });

            let results = [];
            const rc = new content.window.BroadcastChannel("result");
            // This promise resolves when an update has failed.
            const oneFailed = new Promise(resolveOneFailed => {
              rc.onmessage = function (e) {
                console.log("got result", e.data);
                results.push(e.data);
                if (e.data === 1) {
                  resolveOneFailed();
                }
                if (results.length != 2) {
                  return;
                }

                resolveResults(results[0] + results[1]);
              };
            });

            Promise.all([updatesIssued, oneFailed]).then(() => {
              console.log("releasing update");
              content.fetch(url + "?release").catch(ex => {
                console.error("problem releasing:", ex);
              });
            });

            // Let's inform the tabs.
            const sc = new content.window.BroadcastChannel("start");
            sc.postMessage("go");
          });
        })
    );
  });
  /* eslint-enable no-shadow */

  if (status == 0) {
    ok(false, "both succeeded. This is wrong.");
  } else if (status == 1) {
    ok(true, "one succeded, one failed. This is good.");
  } else {
    ok(false, "both failed. This is definitely wrong.");
  }

  // let's clean up the registration and get the fetch count.  The count
  // should be 1 for the initial fetch and 1 for the update.
  /* eslint-disable no-shadow */
  const count = await SpecialPowers.spawn(browser1, [sw], async function (url) {
    // We stored the registration on the frame script's wrapper, hence directly
    // accesss content without using wrappedJSObject.
    await content.registration.unregister();
    const { count } = await content
      .fetch(url + "?get-and-clear-count")
      .then(r => r.json());
    return count;
  });
  /* eslint-enable no-shadow */
  is(count, 2, "SW should have been fetched only twice");

  BrowserTestUtils.removeTab(tab1);
  BrowserTestUtils.removeTab(tab2);
});