tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

fetch_event_worker.js (12395B)


      1 // eslint-disable-next-line complexity
      2 onfetch = function (ev) {
      3  if (ev.request.url.includes("ignore")) {
      4    return;
      5  }
      6 
      7  if (ev.request.url.includes("bare-synthesized.txt")) {
      8    ev.respondWith(
      9      Promise.resolve(new Response("synthesized response body", {}))
     10    );
     11  } else if (ev.request.url.includes("file_CrossSiteXHR_server.sjs")) {
     12    // N.B. this response would break the rules of CORS if it were allowed, but
     13    //      this test relies upon the preflight request not being intercepted and
     14    //      thus this response should not be used.
     15    if (ev.request.method == "OPTIONS") {
     16      ev.respondWith(
     17        new Response("", {
     18          headers: {
     19            "Access-Control-Allow-Origin": "*",
     20            "Access-Control-Allow-Headers": "X-Unsafe",
     21          },
     22        })
     23      );
     24    } else if (ev.request.url.includes("example.org")) {
     25      ev.respondWith(fetch(ev.request));
     26    }
     27  } else if (ev.request.url.includes("synthesized-404.txt")) {
     28    ev.respondWith(
     29      Promise.resolve(
     30        new Response("synthesized response body", { status: 404 })
     31      )
     32    );
     33  } else if (ev.request.url.includes("synthesized-headers.txt")) {
     34    ev.respondWith(
     35      Promise.resolve(
     36        new Response("synthesized response body", {
     37          headers: {
     38            "X-Custom-Greeting": "Hello",
     39          },
     40        })
     41      )
     42    );
     43  } else if (ev.request.url.includes("test-respondwith-response.txt")) {
     44    ev.respondWith(new Response("test-respondwith-response response body", {}));
     45  } else if (ev.request.url.includes("synthesized-redirect-real-file.txt")) {
     46    ev.respondWith(Promise.resolve(Response.redirect("fetch/real-file.txt")));
     47  } else if (
     48    ev.request.url.includes("synthesized-redirect-twice-real-file.txt")
     49  ) {
     50    ev.respondWith(
     51      Promise.resolve(Response.redirect("synthesized-redirect-real-file.txt"))
     52    );
     53  } else if (ev.request.url.includes("synthesized-redirect-synthesized.txt")) {
     54    ev.respondWith(Promise.resolve(Response.redirect("bare-synthesized.txt")));
     55  } else if (
     56    ev.request.url.includes("synthesized-redirect-twice-synthesized.txt")
     57  ) {
     58    ev.respondWith(
     59      Promise.resolve(Response.redirect("synthesized-redirect-synthesized.txt"))
     60    );
     61  } else if (ev.request.url.includes("rejected.txt")) {
     62    ev.respondWith(Promise.reject());
     63  } else if (ev.request.url.includes("nonresponse.txt")) {
     64    ev.respondWith(Promise.resolve(5));
     65  } else if (ev.request.url.includes("nonresponse2.txt")) {
     66    ev.respondWith(Promise.resolve({}));
     67  } else if (ev.request.url.includes("nonpromise.txt")) {
     68    try {
     69      // This should coerce to Promise(5) instead of throwing
     70      ev.respondWith(5);
     71    } catch (e) {
     72      // test is expecting failure, so return a success if we get a thrown
     73      // exception
     74      ev.respondWith(new Response("respondWith(5) threw " + e));
     75    }
     76  } else if (ev.request.url.includes("headers.txt")) {
     77    var ok = true;
     78    ok &= ev.request.headers.get("X-Test1") == "header1";
     79    ok &= ev.request.headers.get("X-Test2") == "header2";
     80    ev.respondWith(Promise.resolve(new Response(ok.toString(), {})));
     81  } else if (ev.request.url.includes("readable-stream.txt")) {
     82    ev.respondWith(
     83      new Response(
     84        new ReadableStream({
     85          start(controller) {
     86            controller.enqueue(
     87              new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21])
     88            );
     89            controller.close();
     90          },
     91        })
     92      )
     93    );
     94  } else if (ev.request.url.includes("readable-stream-locked.txt")) {
     95    let stream = new ReadableStream({
     96      start(controller) {
     97        controller.enqueue(
     98          new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21])
     99        );
    100        controller.close();
    101      },
    102    });
    103 
    104    ev.respondWith(new Response(stream));
    105 
    106    // This locks the stream.
    107    stream.getReader();
    108  } else if (ev.request.url.includes("readable-stream-with-exception.txt")) {
    109    ev.respondWith(
    110      new Response(
    111        new ReadableStream({
    112          start(controller) {},
    113          pull() {
    114            throw "EXCEPTION!";
    115          },
    116        })
    117      )
    118    );
    119  } else if (ev.request.url.includes("readable-stream-with-exception2.txt")) {
    120    ev.respondWith(
    121      new Response(
    122        new ReadableStream({
    123          _controller: null,
    124          _count: 0,
    125 
    126          start(controller) {
    127            this._controller = controller;
    128          },
    129          pull() {
    130            if (++this._count == 5) {
    131              throw "EXCEPTION 2!";
    132            }
    133            this._controller.enqueue(new Uint8Array([this._count]));
    134          },
    135        })
    136      )
    137    );
    138  } else if (ev.request.url.includes("readable-stream-already-consumed.txt")) {
    139    let r = new Response(
    140      new ReadableStream({
    141        start(controller) {
    142          controller.enqueue(
    143            new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21])
    144          );
    145          controller.close();
    146        },
    147      })
    148    );
    149 
    150    r.blob();
    151 
    152    ev.respondWith(r);
    153  } else if (ev.request.url.includes("user-pass")) {
    154    ev.respondWith(new Response(ev.request.url));
    155  } else if (ev.request.url.includes("nonexistent_image.gif")) {
    156    var imageAsBinaryString = atob(
    157      "R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs"
    158    );
    159    var imageLength = imageAsBinaryString.length;
    160 
    161    // If we just pass |imageAsBinaryString| to the Response constructor, an
    162    // encoding conversion occurs that corrupts the image. Instead, we need to
    163    // convert it to a typed array.
    164    // typed array.
    165    var imageAsArray = new Uint8Array(imageLength);
    166    for (var i = 0; i < imageLength; ++i) {
    167      imageAsArray[i] = imageAsBinaryString.charCodeAt(i);
    168    }
    169 
    170    ev.respondWith(
    171      Promise.resolve(
    172        new Response(imageAsArray, { headers: { "Content-Type": "image/gif" } })
    173      )
    174    );
    175  } else if (ev.request.url.includes("nonexistent_script.js")) {
    176    ev.respondWith(
    177      Promise.resolve(new Response("check_intercepted_script();", {}))
    178    );
    179  } else if (ev.request.url.includes("nonexistent_stylesheet.css")) {
    180    ev.respondWith(
    181      Promise.resolve(
    182        new Response("#style-test { background-color: black !important; }", {
    183          headers: {
    184            "Content-Type": "text/css",
    185          },
    186        })
    187      )
    188    );
    189  } else if (ev.request.url.includes("nonexistent_page.html")) {
    190    ev.respondWith(
    191      Promise.resolve(
    192        new Response(
    193          "<script>window.frameElement.test_result = true;</script>",
    194          {
    195            headers: {
    196              "Content-Type": "text/html",
    197            },
    198          }
    199        )
    200      )
    201    );
    202  } else if (ev.request.url.includes("navigate.html")) {
    203    var requests = [
    204      // should not throw
    205      new Request(ev.request),
    206      new Request(ev.request, undefined),
    207      new Request(ev.request, null),
    208      new Request(ev.request, {}),
    209      new Request(ev.request, { someUnrelatedProperty: 42 }),
    210      new Request(ev.request, { method: "GET" }),
    211    ];
    212    ev.respondWith(
    213      Promise.resolve(
    214        new Response(
    215          "<script>window.frameElement.test_result = true;</script>",
    216          {
    217            headers: {
    218              "Content-Type": "text/html",
    219            },
    220          }
    221        )
    222      )
    223    );
    224  } else if (ev.request.url.includes("nonexistent_worker_script.js")) {
    225    ev.respondWith(
    226      Promise.resolve(
    227        new Response("postMessage('worker-intercept-success')", {
    228          headers: { "Content-Type": "text/javascript" },
    229        })
    230      )
    231    );
    232  } else if (ev.request.url.includes("nonexistent_imported_script.js")) {
    233    ev.respondWith(
    234      Promise.resolve(
    235        new Response("check_intercepted_script();", {
    236          headers: { "Content-Type": "text/javascript" },
    237        })
    238      )
    239    );
    240  } else if (ev.request.url.includes("deliver-gzip")) {
    241    // Don't handle the request, this will make Necko perform a network request, at
    242    // which point SetApplyConversion must be re-enabled, otherwise the request
    243    // will fail.
    244    // eslint-disable-next-line no-useless-return
    245    return;
    246  } else if (ev.request.url.includes("hello.gz")) {
    247    ev.respondWith(fetch("fetch/deliver-gzip.sjs"));
    248  } else if (ev.request.url.includes("hello-after-extracting.gz")) {
    249    ev.respondWith(
    250      fetch("fetch/deliver-gzip.sjs").then(function (res) {
    251        return res.text().then(function (body) {
    252          return new Response(body, {
    253            status: res.status,
    254            statusText: res.statusText,
    255            headers: res.headers,
    256          });
    257        });
    258      })
    259    );
    260  } else if (ev.request.url.includes("opaque-on-same-origin")) {
    261    var url =
    262      "http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200";
    263    ev.respondWith(fetch(url, { mode: "no-cors" }));
    264  } else if (ev.request.url.includes("opaque-no-cors")) {
    265    if (ev.request.mode != "no-cors") {
    266      ev.respondWith(Promise.reject());
    267      return;
    268    }
    269 
    270    var url =
    271      "http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200";
    272    ev.respondWith(fetch(url, { mode: ev.request.mode }));
    273  } else if (ev.request.url.includes("cors-for-no-cors")) {
    274    if (ev.request.mode != "no-cors") {
    275      ev.respondWith(Promise.reject());
    276      return;
    277    }
    278 
    279    var url =
    280      "http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200&allowOrigin=*";
    281    ev.respondWith(fetch(url));
    282  } else if (ev.request.url.includes("example.com")) {
    283    ev.respondWith(fetch(ev.request));
    284  } else if (ev.request.url.includes("body-")) {
    285    ev.respondWith(
    286      ev.request.text().then(function (body) {
    287        return new Response(body + body);
    288      })
    289    );
    290  } else if (ev.request.url.includes("something.txt")) {
    291    ev.respondWith(Response.redirect("fetch/somethingelse.txt"));
    292  } else if (ev.request.url.includes("somethingelse.txt")) {
    293    ev.respondWith(new Response("something else response body", {}));
    294  } else if (ev.request.url.includes("redirect_serviceworker.sjs")) {
    295    // The redirect_serviceworker.sjs server-side JavaScript file redirects to
    296    // 'http://mochi.test:8888/tests/dom/serviceworkers/test/worker.js'
    297    // The redirected fetch should not go through the SW since the original
    298    // fetch was initiated from a SW.
    299    ev.respondWith(fetch("redirect_serviceworker.sjs"));
    300  } else if (
    301    ev.request.url.includes("load_cross_origin_xml_document_synthetic.xml")
    302  ) {
    303    ev.respondWith(
    304      Promise.resolve(
    305        new Response("<response>body</response>", {
    306          headers: { "Content-Type": "text/xtml" },
    307        })
    308      )
    309    );
    310  } else if (
    311    ev.request.url.includes("load_cross_origin_xml_document_cors.xml")
    312  ) {
    313    if (ev.request.mode != "same-origin") {
    314      ev.respondWith(Promise.reject());
    315      return;
    316    }
    317 
    318    var url =
    319      "http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200&allowOrigin=*";
    320    ev.respondWith(fetch(url, { mode: "cors" }));
    321  } else if (
    322    ev.request.url.includes("load_cross_origin_xml_document_opaque.xml")
    323  ) {
    324    if (ev.request.mode != "same-origin") {
    325      Promise.resolve(
    326        new Response("<error>Invalid Request mode</error>", {
    327          headers: { "Content-Type": "text/xtml" },
    328        })
    329      );
    330      return;
    331    }
    332 
    333    var url =
    334      "http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200";
    335    ev.respondWith(fetch(url, { mode: "no-cors" }));
    336  } else if (ev.request.url.includes("xhr-method-test.txt")) {
    337    ev.respondWith(new Response("intercepted " + ev.request.method));
    338  } else if (ev.request.url.includes("empty-header")) {
    339    if (
    340      !ev.request.headers.has("emptyheader") ||
    341      ev.request.headers.get("emptyheader") !== ""
    342    ) {
    343      ev.respondWith(Promise.reject());
    344      return;
    345    }
    346    ev.respondWith(new Response("emptyheader"));
    347  } else if (ev.request.url.includes("fetchevent-extendable")) {
    348    if (ev instanceof ExtendableEvent) {
    349      ev.respondWith(new Response("extendable"));
    350    } else {
    351      ev.respondWith(Promise.reject());
    352    }
    353  } else if (ev.request.url.includes("fetchevent-request")) {
    354    var threw = false;
    355    try {
    356      new FetchEvent("foo");
    357    } catch (e) {
    358      if (e.name == "TypeError") {
    359        threw = true;
    360      }
    361    } finally {
    362      ev.respondWith(new Response(threw ? "non-nullable" : "nullable"));
    363    }
    364  }
    365 };