browser_handle_command_errors.js (6477B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { RootMessageHandler } = ChromeUtils.importESModule( 7 "chrome://remote/content/shared/messagehandler/RootMessageHandler.sys.mjs" 8 ); 9 10 // Check that errors from WindowGlobal modules can be caught by the consumer 11 // of the RootMessageHandler. 12 add_task(async function test_module_error() { 13 const browsingContextId = gBrowser.selectedBrowser.browsingContext.id; 14 15 const rootMessageHandler = createRootMessageHandler("session-id-error"); 16 17 info("Call a module method which will throw"); 18 19 await Assert.rejects( 20 rootMessageHandler.handleCommand({ 21 moduleName: "commandwindowglobalonly", 22 commandName: "testError", 23 destination: { 24 type: WindowGlobalMessageHandler.type, 25 id: browsingContextId, 26 }, 27 }), 28 err => err.message.includes("error-from-module"), 29 "Error from window global module caught" 30 ); 31 32 rootMessageHandler.destroy(); 33 }); 34 35 // Check that sending commands to incorrect destinations creates an error which 36 // can be caught by the consumer of the RootMessageHandler. 37 add_task(async function test_destination_error() { 38 const rootMessageHandler = createRootMessageHandler("session-id-error"); 39 40 const fakeBrowsingContextId = -1; 41 ok( 42 !BrowsingContext.get(fakeBrowsingContextId), 43 "No browsing context matches fakeBrowsingContextId" 44 ); 45 46 info("Call a valid module method, but on a non-existent browsing context id"); 47 Assert.throws( 48 () => 49 rootMessageHandler.handleCommand({ 50 moduleName: "commandwindowglobalonly", 51 commandName: "testOnlyInWindowGlobal", 52 destination: { 53 type: WindowGlobalMessageHandler.type, 54 id: fakeBrowsingContextId, 55 }, 56 }), 57 err => err.message == `Unable to find a BrowsingContext for id "-1"` 58 ); 59 60 rootMessageHandler.destroy(); 61 }); 62 63 add_task(async function test_invalid_module_error() { 64 const rootMessageHandler = createRootMessageHandler( 65 "session-id-missing_module" 66 ); 67 68 info("Attempt to call a Root module which has a syntax error"); 69 Assert.throws( 70 () => 71 rootMessageHandler.handleCommand({ 72 moduleName: "invalid", 73 commandName: "someMethod", 74 destination: { 75 type: RootMessageHandler.type, 76 }, 77 }), 78 err => 79 err.name === "SyntaxError" && 80 err.message == "expected expression, got ';'" 81 ); 82 83 rootMessageHandler.destroy(); 84 }); 85 86 add_task(async function test_missing_root_module_error() { 87 const rootMessageHandler = createRootMessageHandler( 88 "session-id-missing_module" 89 ); 90 91 info("Attempt to call a Root module which doesn't exist"); 92 Assert.throws( 93 () => 94 rootMessageHandler.handleCommand({ 95 moduleName: "missingmodule", 96 commandName: "someMethod", 97 destination: { 98 type: RootMessageHandler.type, 99 }, 100 }), 101 err => 102 err.name == "UnsupportedCommandError" && 103 err.message == 104 `missingmodule.someMethod not supported for destination ROOT` 105 ); 106 107 rootMessageHandler.destroy(); 108 }); 109 110 add_task(async function test_missing_windowglobal_module_error() { 111 const browsingContextId = gBrowser.selectedBrowser.browsingContext.id; 112 const rootMessageHandler = createRootMessageHandler( 113 "session-id-missing_windowglobal_module" 114 ); 115 116 info("Attempt to call a WindowGlobal module which doesn't exist"); 117 Assert.throws( 118 () => 119 rootMessageHandler.handleCommand({ 120 moduleName: "missingmodule", 121 commandName: "someMethod", 122 destination: { 123 type: WindowGlobalMessageHandler.type, 124 id: browsingContextId, 125 }, 126 }), 127 err => 128 err.name == "UnsupportedCommandError" && 129 err.message == 130 `missingmodule.someMethod not supported for destination WINDOW_GLOBAL` 131 ); 132 133 rootMessageHandler.destroy(); 134 }); 135 136 add_task(async function test_missing_root_method_error() { 137 const rootMessageHandler = createRootMessageHandler( 138 "session-id-missing_root_method" 139 ); 140 141 info("Attempt to call an invalid method on a Root module"); 142 Assert.throws( 143 () => 144 rootMessageHandler.handleCommand({ 145 moduleName: "command", 146 commandName: "wrongMethod", 147 destination: { 148 type: RootMessageHandler.type, 149 }, 150 }), 151 err => 152 err.name == "UnsupportedCommandError" && 153 err.message == `command.wrongMethod not supported for destination ROOT` 154 ); 155 156 rootMessageHandler.destroy(); 157 }); 158 159 add_task(async function test_missing_windowglobal_method_error() { 160 const browsingContextId = gBrowser.selectedBrowser.browsingContext.id; 161 const rootMessageHandler = createRootMessageHandler( 162 "session-id-missing_windowglobal_method" 163 ); 164 165 info("Attempt to call an invalid method on a WindowGlobal module"); 166 Assert.throws( 167 () => 168 rootMessageHandler.handleCommand({ 169 moduleName: "commandwindowglobalonly", 170 commandName: "wrongMethod", 171 destination: { 172 type: WindowGlobalMessageHandler.type, 173 id: browsingContextId, 174 }, 175 }), 176 err => 177 err.name == "UnsupportedCommandError" && 178 err.message == 179 `commandwindowglobalonly.wrongMethod not supported for destination WINDOW_GLOBAL` 180 ); 181 182 rootMessageHandler.destroy(); 183 }); 184 185 /** 186 * This test checks that even if a command is rerouted to another command after 187 * the RootMessageHandler, we still check the new command and log a useful 188 * error message. 189 * 190 * This illustrates why it is important to perform the command check at each 191 * layer of the MessageHandler network. 192 */ 193 add_task(async function test_missing_intermediary_method_error() { 194 const browsingContextId = gBrowser.selectedBrowser.browsingContext.id; 195 const rootMessageHandler = createRootMessageHandler( 196 "session-id-missing_intermediary_method" 197 ); 198 199 info( 200 "Call a (valid) command that relies on another (missing) command on a WindowGlobal module" 201 ); 202 await Assert.rejects( 203 rootMessageHandler.handleCommand({ 204 moduleName: "commandwindowglobalonly", 205 commandName: "testMissingIntermediaryMethod", 206 destination: { 207 type: WindowGlobalMessageHandler.type, 208 id: browsingContextId, 209 }, 210 }), 211 err => 212 err.name == "UnsupportedCommandError" && 213 err.message == 214 `commandwindowglobalonly.missingMethod not supported for destination WINDOW_GLOBAL` 215 ); 216 217 rootMessageHandler.destroy(); 218 });