summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_viewsource_StreamFilter.js
blob: c624de428069a3c054136217aa838a33dbd74f58 (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
"use strict";

const server = createHttpServer();
const BASE_URL = `http://127.0.0.1:${server.identity.primaryPort}`;

server.registerPathHandler("/dummy", (request, response) => {
  response.setStatusLine(request.httpVersion, 200, "OK");
  response.write("ok");
});

server.registerPathHandler("/redir", (request, response) => {
  response.setStatusLine(request.httpVersion, 303, "See Other");
  response.setHeader("Location", `${BASE_URL}/dummy`);
});

async function testViewSource(viewSourceUrl) {
  function background(BASE_URL) {
    browser.webRequest.onBeforeRequest.addListener(
      details => {
        browser.test.assertEq(`${BASE_URL}/dummy`, details.url, "expected URL");
        browser.test.assertEq("main_frame", details.type, "details.type");

        let filter = browser.webRequest.filterResponseData(details.requestId);
        filter.onstart = () => {
          filter.write(new TextEncoder().encode("PREFIX_"));
        };
        filter.ondata = event => {
          filter.write(event.data);
        };
        filter.onstop = () => {
          filter.write(new TextEncoder().encode("_SUFFIX"));
          filter.disconnect();
          browser.test.notifyPass("filter_end");
        };
        filter.onerror = () => {
          browser.test.fail(`Unexpected error: ${filter.error}`);
          browser.test.notifyFail("filter_end");
        };
      },
      { urls: ["*://*/dummy"] },
      ["blocking"]
    );
    browser.webRequest.onBeforeRequest.addListener(
      details => {
        browser.test.assertEq(`${BASE_URL}/redir`, details.url, "Got redirect");

        let filter = browser.webRequest.filterResponseData(details.requestId);
        filter.onstop = () => {
          filter.disconnect();
          browser.test.fail("Unexpected onstop for redirect");
          browser.test.sendMessage("redirect_done");
        };
        filter.onerror = () => {
          browser.test.assertEq(
            // TODO bug 1683862: must be "Channel redirected", but it is not
            // because document requests are handled differently compared to
            // other requests, see the comment at the top of
            // test_ext_webRequest_redirect_StreamFilter.js.
            "Invalid request ID",
            filter.error,
            "Expected error in filter.onerror"
          );
          browser.test.sendMessage("redirect_done");
        };
      },
      { urls: ["*://*/redir"] },
      ["blocking"]
    );
  }
  let extension = ExtensionTestUtils.loadExtension({
    manifest: {
      permissions: ["webRequest", "webRequestBlocking", "*://*/*"],
    },
    background: `(${background})(${JSON.stringify(BASE_URL)})`,
  });
  await extension.startup();
  let contentPage = await ExtensionTestUtils.loadContentPage(viewSourceUrl);
  if (viewSourceUrl.includes("/redir")) {
    info("Awaiting observed completion of redirection request");
    await extension.awaitMessage("redirect_done");
  }
  info("Awaiting completion of StreamFilter on request");
  await extension.awaitFinish("filter_end");
  let contentText = await contentPage.spawn([], () => {
    return this.content.document.body.textContent;
  });
  equal(contentText, "PREFIX_ok_SUFFIX", "view-source response body");
  await contentPage.close();
  await extension.unload();
}

add_task(async function test_StreamFilter_viewsource() {
  await testViewSource(`view-source:${BASE_URL}/dummy`);
});

add_task(async function test_StreamFilter_viewsource_redirect_target() {
  await testViewSource(`view-source:${BASE_URL}/redir`);
});

// Sanity check: nothing bad happens if the underlying response is aborted.
add_task(async function test_StreamFilter_viewsource_cancel() {
  let extension = ExtensionTestUtils.loadExtension({
    manifest: {
      permissions: ["webRequest", "webRequestBlocking", "*://*/*"],
    },
    background() {
      browser.webRequest.onBeforeRequest.addListener(
        details => {
          let filter = browser.webRequest.filterResponseData(details.requestId);
          filter.onstart = () => {
            filter.disconnect();
            browser.test.fail("Unexpected filter.onstart");
            browser.test.notifyFail("filter_end");
          };
          filter.onerror = () => {
            browser.test.assertEq("Invalid request ID", filter.error, "Error?");
            browser.test.notifyPass("filter_end");
          };
        },
        { urls: ["*://*/dummy"] },
        ["blocking"]
      );
      browser.webRequest.onHeadersReceived.addListener(
        () => {
          browser.test.log("Intentionally canceling view-source request");
          return { cancel: true };
        },
        { urls: ["*://*/dummy"] },
        ["blocking"]
      );
    },
  });
  await extension.startup();
  let contentPage = await ExtensionTestUtils.loadContentPage(
    `${BASE_URL}/dummy`
  );
  await extension.awaitFinish("filter_end");
  let contentText = await contentPage.spawn([], () => {
    return this.content.document.body.textContent;
  });
  equal(contentText, "", "view-source request should have been canceled");
  await contentPage.close();
  await extension.unload();
});