tor-browser

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

message-target.js (6472B)


      1 'use strict';
      2 
      3 // This script depends on the following scripts:
      4 //    /fs/resources/messaging-helpers.js
      5 //    /fs/resources/test-helpers.js
      6 
      7 // add_message_event_handlers() is the helper function used to setup all
      8 // message targets, including iframes and workers.
      9 //
     10 // Adds a message event handler and a message error handler to |receiver|.
     11 // The 'data' property from received MessageEvents must include a 'type'
     12 // property. The 'type' selects the test logic to run. Most message type
     13 // handlers use postMessage() to respond to the sender with test results.
     14 // The sender then validates the test results after receiving the response.
     15 //
     16 // Both |target| and |target_origin| are optional. |target| is used
     17 // to send message responses back to the sender. When omitted, the
     18 // 'source' from received MessageEvents is used instead.
     19 //
     20 // For window messaging, |target_origin| specifies the origin to receive
     21 // responses. Most window tests use '*' for the |target_origin|. Worker
     22 // and message port tests must use undefined for |target_origin| to avoid
     23 // exceptions.
     24 function add_message_event_handlers(receiver, target, target_origin) {
     25  receiver.addEventListener('message', async function (message_event) {
     26    const message_data = message_event.data;
     27 
     28    // Reply to the sender using the 'source' from the received MessageEvent.
     29    let message_source = message_event.source;
     30    if (message_source === null) {
     31      // However, some message senders, like DedicatedWorkers, don't include
     32      // a source. Fallback to the target when the source is null.
     33      message_source = target;
     34    }
     35 
     36    try {
     37      switch (message_data.type) {
     38        case 'receive-message-port':
     39          // Receive a MessagePort to use as a message target for testing.
     40          add_message_event_handlers(
     41            /*receiver=*/message_data.message_port,
     42            /*target=*/message_data.message_port);
     43          message_data.message_port.start();
     44          break;
     45 
     46        case 'create-broadcast-channel':
     47          // Create a BroadcastChannel to use as a message target for testing.
     48          const broadcast_channel =
     49            new BroadcastChannel(message_data.broadcast_channel_name);
     50          add_message_event_handlers(
     51            /*receiver=*/broadcast_channel,
     52            /*target=*/broadcast_channel);
     53          message_source.postMessage(
     54            { type: 'broadcast-channel-created' },
     55            { targetOrigin: target_origin });
     56          break;
     57 
     58        case 'receive-file-system-handles':
     59          // Receive a list of cloned FileSystemFileHandles. Access the
     60          // properties of each FileSystemFileHandle by serializing the
     61          // handle to a JavaScript object. Then respond with the serialized
     62          // results, enabling the sender to verify that the cloned handle
     63          // produced the expected property values from this execution context.
     64          const serialized_handles = [];
     65          const cloned_handles = message_data.cloned_handles;
     66          for (let i = 0; i < cloned_handles.length; ++i) {
     67            const serialized = await serialize_handle(cloned_handles[i]);
     68            serialized_handles.push(serialized);
     69          }
     70          message_source.postMessage({
     71            type: 'receive-serialized-file-system-handles',
     72            serialized_handles,
     73            // Respond with the cloned handles to create new clones for
     74            // the sender to verify.
     75            cloned_handles,
     76          }, { targetOrigin: target_origin });
     77          break;
     78 
     79        case 'receive-serialized-file-system-handles':
     80          // Do nothing. This message is meant for test runner validation.
     81          // Other message targets may receive this message while testing
     82          // broadcast channels.
     83          break;
     84 
     85        case 'create-file':
     86          // Create a new file and then respond to the sender with it.
     87          const directory = await navigator.storage.getDirectory();
     88          const file_handle =
     89            await directory.getFileHandle('temp-file', { create: true });
     90          message_source.postMessage(
     91            { type: 'receive-file', file_handle },
     92            { targetOrigin: target_origin });
     93          break;
     94 
     95        case 'create-directory':
     96          // Create a new directory and then respond to the sender with it.
     97          const parent_directory = await navigator.storage.getDirectory();
     98          const directory_handle =
     99            await parent_directory.getDirectoryHandle('temp-directory',
    100              { create: true });
    101          message_source.postMessage(
    102            { type: 'receive-directory', directory_handle },
    103            { targetOrigin: target_origin });
    104          break;
    105 
    106        case 'create-sync-access-handle':
    107          // Receive a file and create a sync access handle out of it. Report
    108          // success to the sender.
    109          let success = true;
    110          try {
    111            const access_handle =
    112                await message_data.file_handle.createSyncAccessHandle();
    113            access_handle.close();
    114          } catch (error) {
    115            success = false;
    116          }
    117 
    118          message_source.postMessage(
    119            { type: 'receive-sync-access-handle-result', success },
    120            { targetOrigin: target_origin });
    121          break;
    122 
    123        default:
    124          throw `Unknown message type: '${message_data.type}'`;
    125      }
    126    } catch (error) {
    127      // Respond with an error to trigger a failure in the sender's
    128      // test runner.
    129      message_source.postMessage(`ERROR: ${error}`,
    130        { targetOrigin: target_origin });
    131    }
    132  });
    133 
    134  receiver.addEventListener('messageerror', async function (message_event) {
    135    // Select the target for message responses (see comment in 'message' event
    136    // listener above).
    137    let message_source = message_event.source;
    138    if (message_source === null) {
    139      message_source = target;
    140    }
    141 
    142    try {
    143      // Respond with the MessageEvent's property values, enabling the sender
    144      // to verify results.
    145      const serialized_message_error_event =
    146        serialize_message_error_event(message_event);
    147      message_source.postMessage({
    148        type: 'serialized-message-error',
    149        serialized_message_error_event
    150      }, { targetOrigin: target_origin });
    151    } catch (error) {
    152      // Respond with an error to trigger a failure in the sender's
    153      // test runner.
    154      message_source.postMessage(`ERROR: ${error}`,
    155        { targetOrigin: target_origin });
    156    }
    157  });
    158 }