browser_session_data.js (7782B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { MessageHandlerRegistry } = ChromeUtils.importESModule( 7 "chrome://remote/content/shared/messagehandler/MessageHandlerRegistry.sys.mjs" 8 ); 9 const { RootMessageHandler } = ChromeUtils.importESModule( 10 "chrome://remote/content/shared/messagehandler/RootMessageHandler.sys.mjs" 11 ); 12 const { SessionData } = ChromeUtils.importESModule( 13 "chrome://remote/content/shared/messagehandler/sessiondata/SessionData.sys.mjs" 14 ); 15 16 const TEST_PAGE = "http://example.com/document-builder.sjs?html=tab"; 17 18 add_task(async function test_sessionData() { 19 info("Navigate the initial tab to the test URL"); 20 const tab1 = gBrowser.selectedTab; 21 await loadURL(tab1.linkedBrowser, TEST_PAGE); 22 23 const sessionId = "sessionData-test"; 24 25 const rootMessageHandlerRegistry = new MessageHandlerRegistry( 26 RootMessageHandler.type 27 ); 28 29 const rootMessageHandler = 30 rootMessageHandlerRegistry.getOrCreateMessageHandler(sessionId); 31 ok(rootMessageHandler, "Valid ROOT MessageHandler created"); 32 33 const sessionData = rootMessageHandler.sessionData; 34 ok( 35 sessionData instanceof SessionData, 36 "ROOT MessageHandler has a valid sessionData" 37 ); 38 39 let sessionDataSnapshot = await getSessionDataFromContent(); 40 is(sessionDataSnapshot.size, 0, "session data is empty"); 41 42 info("Store a string value in session data"); 43 sessionData.updateSessionData([ 44 { 45 method: "add", 46 moduleName: "fakemodule", 47 category: "testCategory", 48 contextDescriptor: contextDescriptorAll, 49 values: ["value-1"], 50 }, 51 ]); 52 53 sessionDataSnapshot = await getSessionDataFromContent(); 54 is(sessionDataSnapshot.size, 1, "session data contains 1 session"); 55 ok(sessionDataSnapshot.has(sessionId)); 56 let snapshot = sessionDataSnapshot.get(sessionId); 57 ok(Array.isArray(snapshot)); 58 is(snapshot.length, 1); 59 60 const stringDataItem = snapshot[0]; 61 checkSessionDataItem( 62 stringDataItem, 63 "fakemodule", 64 "testCategory", 65 ContextDescriptorType.All, 66 "value-1" 67 ); 68 69 info("Store a number value in session data"); 70 sessionData.updateSessionData([ 71 { 72 method: "add", 73 moduleName: "fakemodule", 74 category: "testCategory", 75 contextDescriptor: contextDescriptorAll, 76 values: [12], 77 }, 78 ]); 79 snapshot = (await getSessionDataFromContent()).get(sessionId); 80 is(snapshot.length, 2); 81 82 const numberDataItem = snapshot[1]; 83 checkSessionDataItem( 84 numberDataItem, 85 "fakemodule", 86 "testCategory", 87 ContextDescriptorType.All, 88 12 89 ); 90 91 info("Store a boolean value in session data"); 92 sessionData.updateSessionData([ 93 { 94 method: "add", 95 moduleName: "fakemodule", 96 category: "testCategory", 97 contextDescriptor: contextDescriptorAll, 98 values: [true], 99 }, 100 ]); 101 snapshot = (await getSessionDataFromContent()).get(sessionId); 102 is(snapshot.length, 3); 103 104 const boolDataItem = snapshot[2]; 105 checkSessionDataItem( 106 boolDataItem, 107 "fakemodule", 108 "testCategory", 109 ContextDescriptorType.All, 110 true 111 ); 112 113 info("Remove one value"); 114 sessionData.updateSessionData([ 115 { 116 method: "remove", 117 moduleName: "fakemodule", 118 category: "testCategory", 119 contextDescriptor: contextDescriptorAll, 120 values: [12], 121 }, 122 ]); 123 snapshot = (await getSessionDataFromContent()).get(sessionId); 124 is(snapshot.length, 2); 125 checkSessionDataItem( 126 snapshot[0], 127 "fakemodule", 128 "testCategory", 129 ContextDescriptorType.All, 130 "value-1" 131 ); 132 checkSessionDataItem( 133 snapshot[1], 134 "fakemodule", 135 "testCategory", 136 ContextDescriptorType.All, 137 true 138 ); 139 140 info("Remove all values"); 141 sessionData.updateSessionData([ 142 { 143 method: "remove", 144 moduleName: "fakemodule", 145 category: "testCategory", 146 contextDescriptor: contextDescriptorAll, 147 values: ["value-1", true], 148 }, 149 ]); 150 snapshot = (await getSessionDataFromContent()).get(sessionId); 151 is(snapshot.length, 0, "Session data is now empty"); 152 153 info("Add another value before destroy"); 154 sessionData.updateSessionData([ 155 { 156 method: "add", 157 moduleName: "fakemodule", 158 category: "testCategory", 159 contextDescriptor: contextDescriptorAll, 160 values: ["value-2"], 161 }, 162 ]); 163 snapshot = (await getSessionDataFromContent()).get(sessionId); 164 is(snapshot.length, 1); 165 checkSessionDataItem( 166 snapshot[0], 167 "fakemodule", 168 "testCategory", 169 ContextDescriptorType.All, 170 "value-2" 171 ); 172 173 sessionData.destroy(); 174 sessionDataSnapshot = await getSessionDataFromContent(); 175 is(sessionDataSnapshot.size, 0, "session data should be empty again"); 176 }); 177 178 add_task(async function test_sessionDataRootOnlyModule() { 179 const sessionId = "sessionData-test-rootOnly"; 180 181 const rootMessageHandler = createRootMessageHandler(sessionId); 182 ok(rootMessageHandler, "Valid ROOT MessageHandler created"); 183 184 BrowserTestUtils.startLoadingURIString( 185 gBrowser.selectedBrowser, 186 "https://example.com/document-builder.sjs?html=tab" 187 ); 188 189 const windowGlobalCreated = rootMessageHandler.once( 190 "window-global-handler-created" 191 ); 192 193 info("Test that adding SessionData items works the root module"); 194 // Updating the session data on the root message handler should not cause 195 // failures for other message handlers if the module only exists for root. 196 await rootMessageHandler.addSessionDataItem({ 197 moduleName: "rootOnly", 198 category: "session_data_root_only", 199 contextDescriptor: { 200 type: ContextDescriptorType.All, 201 }, 202 values: [true], 203 }); 204 205 await windowGlobalCreated; 206 ok(true, "Window global has been initialized"); 207 208 let sessionDataReceivedByRoot = await rootMessageHandler.handleCommand({ 209 moduleName: "rootOnly", 210 commandName: "getSessionDataReceived", 211 destination: { 212 type: RootMessageHandler.type, 213 }, 214 }); 215 216 is(sessionDataReceivedByRoot.length, 1); 217 is(sessionDataReceivedByRoot[0].category, "session_data_root_only"); 218 is(sessionDataReceivedByRoot[0].added.length, 1); 219 is(sessionDataReceivedByRoot[0].added[0], true); 220 is( 221 sessionDataReceivedByRoot[0].contextDescriptor.type, 222 ContextDescriptorType.All 223 ); 224 225 info("Now test that removing items also works on the root module"); 226 await rootMessageHandler.removeSessionDataItem({ 227 moduleName: "rootOnly", 228 category: "session_data_root_only", 229 contextDescriptor: { 230 type: ContextDescriptorType.All, 231 }, 232 values: [true], 233 }); 234 235 sessionDataReceivedByRoot = await rootMessageHandler.handleCommand({ 236 moduleName: "rootOnly", 237 commandName: "getSessionDataReceived", 238 destination: { 239 type: RootMessageHandler.type, 240 }, 241 }); 242 243 is(sessionDataReceivedByRoot.length, 2); 244 is(sessionDataReceivedByRoot[1].category, "session_data_root_only"); 245 is(sessionDataReceivedByRoot[1].removed.length, 1); 246 is(sessionDataReceivedByRoot[1].removed[0], true); 247 is( 248 sessionDataReceivedByRoot[1].contextDescriptor.type, 249 ContextDescriptorType.All 250 ); 251 252 rootMessageHandler.destroy(); 253 }); 254 255 function checkSessionDataItem(item, moduleName, category, contextType, value) { 256 is(item.moduleName, moduleName, "Data item has the expected module name"); 257 is(item.category, category, "Data item has the expected category"); 258 is( 259 item.contextDescriptor.type, 260 contextType, 261 "Data item has the expected context type" 262 ); 263 is(item.value, value, "Data item has the expected value"); 264 } 265 266 function getSessionDataFromContent() { 267 return SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { 268 const { readSessionData } = ChromeUtils.importESModule( 269 "chrome://remote/content/shared/messagehandler/sessiondata/SessionDataReader.sys.mjs" 270 ); 271 return readSessionData(); 272 }); 273 }