summaryrefslogtreecommitdiffstats
path: root/dom/serviceworkers/test/test_error_reporting.html
blob: 7c2d56fb9eac250b74df0b17a6de04a4e64409f8 (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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
<!DOCTYPE HTML>
<html>
<head>
  <title>Test Error Reporting of Service Worker Failures</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script src="error_reporting_helpers.js"></script>
  <script src="utils.js"></script>
  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
  <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head>
<body>

<script type="text/javascript">
"use strict";

/**
 * Test that a bunch of service worker coding errors and failure modes that
 * might otherwise be hard to diagnose are surfaced as console error messages.
 * The driving use-case is minimizing cursing from a developer looking at a
 * document in Firefox testing a page that involves service workers.
 *
 * This test assumes that errors will be reported via
 * ServiceWorkerManager::ReportToAllClients and that that method is reliable and
 * tested via some other file.
 **/

add_task(function setupPrefs() {
  return SpecialPowers.pushPrefEnv({"set": [
    ["dom.serviceWorkers.enabled", true],
    ["dom.serviceWorkers.testing.enabled", true],
    ["dom.caches.testing.enabled", true],
  ]});
});

/**
 * Ensure an error is logged during the initial registration of a SW when a 404
 * is received.
 */
add_task(async function register_404() {
  // Start monitoring for the error
  let expectedMessage = expect_console_message(
    "ServiceWorkerRegisterNetworkError",
    [make_absolute_url("network_error/"), "404", make_absolute_url("404.js")]);

  // Register, generating the 404 error.  This will reject with a TypeError
  // which we need to consume so it doesn't get thrown at our generator.
  await navigator.serviceWorker.register("404.js", { scope: "network_error/" })
    .then(
      () => { ok(false, "should have rejected"); },
      (e) => { ok(e.name === "TypeError", "404 failed as expected"); });

  await wait_for_expected_message(expectedMessage);
});

/**
 * Ensure an error is logged when the service worker is being served with a
 * MIME type of text/plain rather than a JS type.
 */
add_task(async function register_bad_mime_type() {
  let expectedMessage = expect_console_message(
    "ServiceWorkerRegisterMimeTypeError2",
    [make_absolute_url("bad_mime_type/"), "text/plain",
     make_absolute_url("sw_bad_mime_type.js")]);

  // consume the expected rejection so it doesn't get thrown at us.
  await navigator.serviceWorker.register("sw_bad_mime_type.js", { scope: "bad_mime_type/" })
    .then(
      () => { ok(false, "should have rejected"); },
      (e) => { ok(e.name === "SecurityError", "bad MIME type failed as expected"); });

  await wait_for_expected_message(expectedMessage);
});

async function notAllowStorageAccess() {
  throw new Error("Storage permissions should be used when bug 1774860 overhauls this test.");
}

async function allowStorageAccess() {
  throw new Error("Storage permissions should be used when bug 1774860 overhauls this test.");
}

/**
 * Ensure an error is logged when the storage is not allowed and the content
 * script is trying to register a service worker.
 */
add_task(async function register_storage_error() {
  let expectedMessage = expect_console_message(
    "ServiceWorkerRegisterStorageError",
    [make_absolute_url("storage_not_allow/")]);

  await notAllowStorageAccess();

  // consume the expected rejection so it doesn't get thrown at us.
  await navigator.serviceWorker.register("sw_storage_not_allow.js",
                                         { scope: "storage_not_allow/" })
    .then(
      () => { ok(false, "should have rejected"); },
      (e) => { ok(e.name === "SecurityError",
                  "storage access failed as expected."); });

  await wait_for_expected_message(expectedMessage);

  await allowStorageAccess();
});

/**
 * Ensure an error is logged when the storage is not allowed and the content
 * script is trying to get the service worker registration.
 */
add_task(async function get_registration_storage_error() {
  let expectedMessage =
    expect_console_message("ServiceWorkerGetRegistrationStorageError", []);

  await notAllowStorageAccess();

  // consume the expected rejection so it doesn't get thrown at us.
  await navigator.serviceWorker.getRegistration()
    .then(
      () => { ok(false, "should have rejected"); },
      (e) => { ok(e.name === "SecurityError",
                  "storage access failed as expected."); });

  await wait_for_expected_message(expectedMessage);

  await allowStorageAccess();
});

/**
 * Ensure an error is logged when the storage is not allowed and the content
 * script is trying to get the service worker registrations.
 */
add_task(async function get_registrations_storage_error() {
  let expectedMessage =
    expect_console_message("ServiceWorkerGetRegistrationStorageError", []);

  await notAllowStorageAccess();

  // consume the expected rejection so it doesn't get thrown at us.
  await navigator.serviceWorker.getRegistrations()
    .then(
      () => { ok(false, "should have rejected"); },
      (e) => { ok(e.name === "SecurityError",
                  "storage access failed as expected."); });

  await wait_for_expected_message(expectedMessage);

  await allowStorageAccess();
});

/**
 * Ensure an error is logged when the storage is not allowed and the content
 * script is trying to post a message to the service worker.
 */
add_task(async function postMessage_storage_error() {
  let expectedMessage = expect_console_message(
    "ServiceWorkerPostMessageStorageError",
    [make_absolute_url("storage_not_allow/")]);

  let registration;
  // consume the expected rejection so it doesn't get thrown at us.
  await navigator.serviceWorker.register("sw_storage_not_allow.js",
                                         { scope: "storage_not_allow/" })
    .then(reg => { registration = reg; })
    .then(() => notAllowStorageAccess())
    .then(() => registration.installing ||
                registration.waiting ||
                registration.active)
    .then(worker =>  worker.postMessage('ha'))
    .then(
      () => { ok(false, "should have rejected"); },
      (e) => { ok(e.name === "SecurityError",
                  "storage access failed as expected."); });

  await wait_for_expected_message(expectedMessage);

  await registration.unregister();
  await allowStorageAccess();
});

/**
 * Ensure an error is logged when the storage is not allowed and the service
 * worker is trying to get its client.
 */
add_task(async function get_client_storage_error() {
  let expectedMessage =
    expect_console_message("ServiceWorkerGetClientStorageError", []);

  await SpecialPowers.pushPrefEnv({"set": [
    // Make the test pass the IsOriginPotentiallyTrustworthy.
    ["dom.securecontext.allowlist", "mochi.test"]
  ]});

  let registration;
  // consume the expected rejection so it doesn't get thrown at us.
  await navigator.serviceWorker.register("sw_storage_not_allow.js",
                                         { scope: "test_error_reporting.html" })
    .then(reg => {
      registration = reg;
      return waitForState(registration.installing, "activated");
    })
    // Get the client's ID in the stage 1
    .then(() => fetch("getClient-stage1"))
    .then(() => notAllowStorageAccess())
    // Trigger the clients.get() in the stage 2
    .then(() => fetch("getClient-stage2"))
    .catch(e => ok(false, "fail due to:" + e));

  await wait_for_expected_message(expectedMessage);

  await registration.unregister();
  await allowStorageAccess();
});

/**
 * Ensure an error is logged when the storage is not allowed and the service
 * worker is trying to get its clients.
 */
add_task(async function get_clients_storage_error() {
  let expectedMessage =
    expect_console_message("ServiceWorkerGetClientStorageError", []);

  let registration;
  // consume the expected rejection so it doesn't get thrown at us.
  await navigator.serviceWorker.register("sw_storage_not_allow.js",
                                         { scope: "test_error_reporting.html" })
    .then(reg => {
      registration = reg;
      return waitForState(registration.installing, "activated");
    })
    .then(() => notAllowStorageAccess())
    .then(() => fetch("getClients"))
    .catch(e => ok(false, "fail due to:" + e));

  await wait_for_expected_message(expectedMessage);

  await registration.unregister();
  await allowStorageAccess();
});
</script>
</body>
</html>