tor-browser

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

webchannel-js-sources.html (6606B)


      1 <!DOCTYPE html>
      2 <!-- This Source Code Form is subject to the terms of the Mozilla Public
      3   - License, v. 2.0. If a copy of the MPL was not distributed with this
      4   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
      5 <html>
      6  <head>
      7    <meta charset="utf-8"/>
      8    <title></title>
      9  </head>
     10  <body>
     11    <script>
     12      "use strict";
     13      // This file is used to test the retrieval of JS sources from a front-end.
     14      // Rather than using some kind of complicated message passing scheme to
     15      // talk to the test harness, modify the title of the page. The tests can
     16      // easily read the window title to see if things worked as expected.
     17 
     18      // The following are the titles used to communicate the page's state to the tests.
     19      // Keep these in sync with any tests that read them.
     20      const initialTitle = "Waiting for the JS sources";
     21      const successTitle = "JS sources received";
     22      const errorTitle = "Error"
     23 
     24      document.title = initialTitle;
     25 
     26      // A function which requests the JS sources from the browser using the GET_JS_SOURCES
     27      // WebChannel message.
     28      function getJSSources(sourceUuids, expectError = false) {
     29        return new Promise((resolve, reject) => {
     30          const requestId = Date.now();
     31 
     32          function listener(event) {
     33            window.removeEventListener(
     34              "WebChannelMessageToContent",
     35              listener,
     36              true
     37            );
     38 
     39            const { id, message } = event.detail;
     40 
     41            dump(JSON.stringify(message));
     42            dump("\n");
     43            if (id !== "profiler.firefox.com" ||
     44              !message ||
     45              typeof message !== "object"
     46            ) {
     47              console.error(message);
     48              reject(new Error("A malformed WebChannel event was received."));
     49              return;
     50            }
     51 
     52            if (!message.type) {
     53              console.error(message);
     54              reject(new Error("The WebChannel event indicates an error."));
     55              return;
     56            }
     57 
     58            if (message.requestId === requestId) {
     59              if (message.type === "SUCCESS_RESPONSE") {
     60                resolve(message.response);
     61              } else if (message.type === "ERROR_RESPONSE") {
     62                if (expectError) {
     63                  resolve({ error: message.error });
     64                } else {
     65                  reject(new Error(message.error));
     66                }
     67              } else {
     68                reject(new Error("Unknown response type: " + message.type));
     69              }
     70            }
     71          }
     72 
     73          window.addEventListener("WebChannelMessageToContent", listener, true);
     74 
     75          window.dispatchEvent(
     76            new CustomEvent("WebChannelMessageToChrome", {
     77              detail: JSON.stringify({
     78                id: "profiler.firefox.com",
     79                message: { type: "GET_JS_SOURCES", requestId, sourceUuids },
     80              }),
     81            })
     82          );
     83        })
     84      }
     85 
     86      async function runTest() {
     87        try {
     88          // Get test configuration from URL parameters
     89          const params = new URLSearchParams(document.location.search);
     90          const testType = params.get("testType") || "basic";
     91          const expectError = params.get("expectError") === "true";
     92 
     93          let sourcesToRequest;
     94          let expectedResponse;
     95 
     96          // Handle invalid-request test case where sourceUuids is intentionally not JSON
     97          if (testType === "invalid-request") {
     98            sourcesToRequest = params.get("sourceUuids"); // Keep as string for invalid test
     99            expectedResponse = null;
    100          } else {
    101            sourcesToRequest = JSON.parse(params.get("sourceUuids") || "[]");
    102            expectedResponse = JSON.parse(params.get("expectedResponse") || "null");
    103          }
    104 
    105          let response;
    106          if (expectError) {
    107            response = await getJSSources(sourcesToRequest, true);
    108          } else {
    109            response = await getJSSources(sourcesToRequest, false);
    110          }
    111 
    112          dump("response\n")
    113          dump(JSON.stringify(response));
    114 
    115          let testPassed = false;
    116 
    117          function deepEqual(obj1, obj2) {
    118            return JSON.stringify(obj1) === JSON.stringify(obj2);
    119          }
    120 
    121          switch (testType) {
    122            case "basic":
    123              // Test case: Request existing JS sources
    124              testPassed = response &&
    125                Array.isArray(response) &&
    126                response.length === expectedResponse.length &&
    127                response.every((item, index) => deepEqual(item, expectedResponse[index]));
    128              break;
    129 
    130            case "nonexistent":
    131              // Test case: Request non-existent sources (should return error objects)
    132              testPassed = response &&
    133                Array.isArray(response) &&
    134                response.length === expectedResponse.length &&
    135                response.every((item, index) => deepEqual(item, expectedResponse[index]));
    136              break;
    137 
    138            case "no-data":
    139              // Test case: No JS source data registered (should return error)
    140              testPassed = response &&
    141                response.error &&
    142                response.error.includes("No JS source data found for this tab");
    143              break;
    144 
    145            case "invalid-request":
    146              // Test case: Invalid sources parameter (should return error)
    147              testPassed = response &&
    148                response.error &&
    149                response.error.includes("sourceUuids must be an array");
    150              break;
    151 
    152            default:
    153              throw new Error("Unknown test type: " + testType);
    154          }
    155 
    156          if (testPassed) {
    157            document.title = successTitle;
    158          } else {
    159            dump('Test failed in webchannel-js-sources.html\n');
    160            dump(`Test type: ${testType}\n`);
    161            dump(`Expected: ${JSON.stringify(expectedResponse)}\n`);
    162            dump(`Actual: ${JSON.stringify(response)}\n`);
    163 
    164            console.error(
    165              "Test failed in webchannel-js-sources.html",
    166              { testType, expectedResponse, response }
    167            );
    168 
    169            document.title = errorTitle;
    170          }
    171        } catch (error) {
    172          // Catch any error and notify the test.
    173          document.title = errorTitle;
    174          dump('An error was caught in webchannel-js-sources.html\n');
    175          dump(`${error}\n`);
    176          console.error(
    177            "An error was caught in webchannel-js-sources.html",
    178            error
    179          );
    180        }
    181      }
    182 
    183      runTest();
    184    </script>
    185  </body>
    186 </html>