summaryrefslogtreecommitdiffstats
path: root/dom/security/test/general/test_block_script_wrong_mime.html
blob: 896823a417a2297fabc519ca1ec27722cadd5620 (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
<!DOCTYPE HTML>
<html>
<head>
  <title>Bug 1288361 - Block scripts with incorrect MIME type</title>
  <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>

<script class="testbody" type="text/javascript">

const MIMETypes = [
  ["application/javascript", true],
  ["text/javascript", true],

  ["audio/mpeg", false],
  ["audio/", false],
  ["image/jpeg", false],
  ["image/", false],
  ["video/mpeg", false],
  ["video/", false],
  ["text/csv", false],
];

// <script src="">
function testScript([mime, shouldLoad]) {
  return new Promise((resolve) => {
    let script = document.createElement("script");
    script.onload = () => {
      document.body.removeChild(script);
      ok(shouldLoad, `script with mime '${mime}' should ${shouldLoad ? "" : "NOT "}load`);
      resolve();
    };
    script.onerror = () => {
      document.body.removeChild(script);
      ok(!shouldLoad, `script with wrong mime '${mime}' should be blocked`);
      resolve();
    };
    script.src = "file_block_script_wrong_mime_server.sjs?type=script&mime="+mime;
    document.body.appendChild(script);
  });
}

// new Worker()
function testWorker([mime, shouldLoad]) {
  return new Promise((resolve) => {
    let worker = new Worker("file_block_script_wrong_mime_server.sjs?type=worker&mime="+mime);
    worker.onmessage = (event) => {
      ok(shouldLoad, `worker with mime '${mime}' should ${shouldLoad ? "" : "NOT "}load`);
      is(event.data, "worker-loaded", "worker should send correct message");
      resolve();
    };
    worker.onerror = (error) => {
      ok(!shouldLoad, `worker with wrong mime '${mime}' should be blocked`);
      error.preventDefault();
      resolve();
    }
    worker.postMessage("dummy");
  });
}

// new Worker() with importScripts()
function testWorkerImportScripts([mime, shouldLoad]) {
  return new Promise((resolve) => {
    let worker = new Worker("file_block_script_wrong_mime_server.sjs?type=worker-import&mime="+mime);
    worker.onmessage = (event) => {
      ok(shouldLoad, `worker/importScripts with mime '${mime}' should ${shouldLoad ? "" : "NOT "}load`);
      is(event.data, "worker-loaded", "worker should send correct message");
      resolve();
    };
    worker.onerror = (error) => {
      ok(!shouldLoad, `worker/importScripts with wrong mime '${mime}' should be blocked`);
      error.preventDefault();
      resolve();
      // The worker doesn't self-terminate via close, so let's do it.
      worker.terminate();
    }
    worker.postMessage("dummy");
  });
}

async function runMimeTypePermutations() {
  info("### Running document script MIME checks.");
  for (const mimeType of MIMETypes) {
    await testScript(mimeType);
  }

  info("### Running worker top-level script MIME checks.");
  for (const mimeType of MIMETypes) {
    await testWorker(mimeType);
  }

  info("### Running worker importScripts MIME checks.");
  for (const mimeType of MIMETypes) {
    await testWorkerImportScripts(mimeType);
  }
}

let gRegistration;

/**
 * Register and wait for the helper ServiceWorker to be active in the given
 * mode.
 */
async function useServiceWorker({ fetchMode }) {
  info(`### Registering ServiceWorker with mode '${fetchMode}'`);
  const activePromise = new Promise((resolve, reject) => {
    navigator.serviceWorker.addEventListener(
      "message",
      event => {
        if (event.data.fetchMode === fetchMode) {
          resolve();
        } else {
          reject(`wrong fetchMode: ${fetchMode}`);
        }
        is(fetchMode, event.data.fetchMode, "right fetch mode");
      },
      { once: true });
  });

  const reg = gRegistration = await navigator.serviceWorker.register(
    `file_block_script_wrong_mime_sw.js?fetchMode=${fetchMode}`);
  info("register resolved. " +
       `installing: ${!!reg.installing} ` +
       `waiting: ${!!reg.waiting} ` +
       `active: ${!!reg.active}`);

  await activePromise;
}

/**
 * Unregister the ServiceWorker, with the caveat that the ServiceWorker will
 * still be controlling us until this window goes away.
 */
async function cleanupServiceWorkerWithCaveat() {
  await gRegistration.unregister();
}

/**
 * Top-level test that runs the MIME type checks in different ServiceWorker/
 * network configurations.
 *
 * We use the ServiceWorker mechanism that allows ServiceWorkers to claim
 * existing scope-matching clients in order to make this window controlled and
 * then run the tests.  When changing the SW behavior the SW also needs to
 * skipWaiting in order to advance to active.
 */
async function runNetworkPermutations() {
  await SpecialPowers.pushPrefEnv({
    set: [
      ["dom.serviceWorkers.enabled", true],
      ["dom.serviceWorkers.exemptFromPerDomainMax", true],
      ["dom.serviceWorkers.testing.enabled", true],
    ],
  });

  info("## Run tests without a ServiceWorker involved.");
  await runMimeTypePermutations();

  info("## Run tests with a pass-through fetch(event.request) handler.");
  await useServiceWorker({ fetchMode: "direct" });
  await runMimeTypePermutations();

  info("## Run tests with a naive URL propagating fetch(event.request.url) handler.");
  await useServiceWorker({ fetchMode: "indirect" });
  await runMimeTypePermutations();

  await cleanupServiceWorkerWithCaveat();
}

add_task(runNetworkPermutations);
</script>
</body>
</html>