browser_handle_command_timeout.js (4994B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // The expected timeouts are reduced for this test, but we still need to wait 7 // for the commands to fully resolve, and it might be a bit slow. 8 requestLongerTimeout(2); 9 10 const { Log } = ChromeUtils.importESModule( 11 "resource://gre/modules/Log.sys.mjs" 12 ); 13 14 class TestAppender extends Log.Appender { 15 constructor(formatter) { 16 super(formatter); 17 this.messages = []; 18 } 19 20 append(message) { 21 this.doAppend(message); 22 } 23 24 doAppend(message) { 25 this.messages.push(message); 26 } 27 28 reset() { 29 this.messages = []; 30 } 31 } 32 33 add_task(async function test_commandTimeout() { 34 const log = Log.repository.getLogger("RemoteAgent"); 35 const appender = new TestAppender(new Log.BasicFormatter()); 36 appender.level = Log.Level.Trace; 37 log.addAppender(appender); 38 39 const tab = BrowserTestUtils.addTab( 40 gBrowser, 41 "https://example.com/document-builder.sjs?html=tab" 42 ); 43 const browsingContext = tab.linkedBrowser.browsingContext; 44 await BrowserTestUtils.browserLoaded(tab.linkedBrowser); 45 46 const rootMessageHandler = createRootMessageHandler("session-id-timeout"); 47 48 info("Call a relatively fast command which should not trigger a ping"); 49 await rootMessageHandler.handleCommand({ 50 moduleName: "timeout", 51 commandName: "waitFor", 52 params: { 53 delay: 1000, 54 }, 55 destination: { 56 type: WindowGlobalMessageHandler.type, 57 id: browsingContext.id, 58 }, 59 }); 60 61 assertSendingPingMessageLogged(appender.messages, false); 62 appender.reset(); 63 64 info("Call a slow command which will trigger a ping"); 65 await rootMessageHandler.handleCommand({ 66 moduleName: "timeout", 67 commandName: "waitFor", 68 params: { 69 delay: 5000, 70 }, 71 destination: { 72 type: WindowGlobalMessageHandler.type, 73 id: browsingContext.id, 74 }, 75 }); 76 77 // The command should take more time than the (reduced) timeout and a ping 78 // should be sent. The ping should succeed since the content process / main 79 // thread should not hang. 80 assertSendingPingMessageLogged(appender.messages, true); 81 assertSuccessfulPingMessageLogged(appender.messages, true); 82 assertFailedPingMessageLogged(appender.messages, false); 83 appender.reset(); 84 85 info("Call a command which hangs the content process main thread for 10s"); 86 const onBlockedCommand = rootMessageHandler.handleCommand({ 87 moduleName: "timeout", 88 commandName: "blockProcess", 89 params: { 90 delay: 10000, 91 }, 92 destination: { 93 type: WindowGlobalMessageHandler.type, 94 id: browsingContext.id, 95 }, 96 }); 97 98 info("Wait until the ping message has been logged"); 99 await TestUtils.waitForCondition(() => 100 appender.messages.find(m => 101 m.message.startsWith("MessageHandlerFrameParent ping") 102 ) 103 ); 104 105 // This time expect messages logged for a failed Ping. 106 assertSendingPingMessageLogged(appender.messages, true); 107 assertSuccessfulPingMessageLogged(appender.messages, false); 108 assertFailedPingMessageLogged(appender.messages, true); 109 appender.reset(); 110 111 await onBlockedCommand; 112 113 rootMessageHandler.destroy(); 114 gBrowser.removeTab(tab); 115 }); 116 117 /** 118 * Assert helper to check if the message corresponding to MessageHandler 119 * sending a ping can be found or not in the provided messages array. 120 * 121 * @param {Array} messages 122 * The array of log appender messages to check. 123 * @param {boolean} expected 124 * True if the message expects to be found, false otherwise. 125 */ 126 function assertSendingPingMessageLogged(messages, expected) { 127 is( 128 !!messages.find(m => m.message.includes("sending ping")), 129 expected, 130 expected ? "A ping was sent and logged" : "No ping was sent" 131 ); 132 } 133 134 /** 135 * Assert helper to check if the message corresponding to a MessageHandler 136 * successful ping can be found or not in the provided messages array. 137 * 138 * @param {Array} messages 139 * The array of log appender messages to check. 140 * @param {boolean} expected 141 * True if the message expects to be found, false otherwise. 142 */ 143 function assertSuccessfulPingMessageLogged(messages, expected) { 144 is( 145 !!messages.find(m => 146 /MessageHandlerFrameParent ping for command [a-zA-Z.]+ to \w+ was successful/.test( 147 m.message 148 ) 149 ), 150 expected, 151 expected ? "Successful ping logged" : "No successful ping logged" 152 ); 153 } 154 155 /** 156 * Assert helper to check if the message corresponding to a MessageHandler 157 * failed ping can be found or not in the provided messages array. 158 * 159 * @param {Array} messages 160 * The array of log appender messages to check. 161 * @param {boolean} expected 162 * True if the message expects to be found, false otherwise. 163 */ 164 function assertFailedPingMessageLogged(messages, expected) { 165 is( 166 !!messages.find(m => 167 /MessageHandlerFrameParent ping for command [a-zA-Z.]+ to \w+ timed out/.test( 168 m.message 169 ) 170 ), 171 expected, 172 expected ? "Failed ping logged" : "No failed ping logged" 173 ); 174 }