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 }