OLD | NEW |
(Empty) | |
| 1 <!-- |
| 2 Copyright 2017 The Chromium Authors. All rights reserved. |
| 3 Use of this source code is governed by a BSD-style license that can be |
| 4 found in the LICENSE file. |
| 5 --> |
| 6 <html> |
| 7 <head> |
| 8 <script> |
| 9 |
| 10 var InspectorTest = {}; |
| 11 InspectorTest._outputElement = null; |
| 12 InspectorTest._dumpInspectorProtocolMessages = false; |
| 13 InspectorTest._sessions = new Map(); |
| 14 |
| 15 InspectorTest.startDumpingProtocolMessages = function() { |
| 16 InspectorTest._dumpInspectorProtocolMessages = true; |
| 17 }; |
| 18 |
| 19 InspectorTest.completeTest = function() { |
| 20 testRunner.notifyDone(); |
| 21 }; |
| 22 |
| 23 InspectorTest.log = function(text) { |
| 24 if (!InspectorTest._outputElement) { |
| 25 var intermediate = document.createElement('div'); |
| 26 document.body.appendChild(intermediate); |
| 27 var intermediate2 = document.createElement('div'); |
| 28 intermediate.appendChild(intermediate2); |
| 29 InspectorTest._outputElement = document.createElement('div'); |
| 30 InspectorTest._outputElement.className = 'output'; |
| 31 InspectorTest._outputElement.id = 'output'; |
| 32 InspectorTest._outputElement.style.whiteSpace = 'pre'; |
| 33 intermediate2.appendChild(InspectorTest._outputElement); |
| 34 } |
| 35 InspectorTest._outputElement.appendChild(document.createTextNode(text)); |
| 36 InspectorTest._outputElement.appendChild(document.createElement('br')); |
| 37 }; |
| 38 |
| 39 InspectorTest.logMessage = function(originalMessage) { |
| 40 var message = JSON.parse(JSON.stringify(originalMessage)); |
| 41 if (message.id) |
| 42 message.id = "<messageId>"; |
| 43 const nonStableFields = new Set(['nodeId', 'objectId']); |
| 44 var objects = [message]; |
| 45 while (objects.length) { |
| 46 var object = objects.shift(); |
| 47 for (var key in object) { |
| 48 if (nonStableFields.has(key)) |
| 49 object[key] = `<${key}>`; |
| 50 else if (typeof object[key] === "string" && object[key].match(/\d+:\d+:\d+
:debug/)) |
| 51 object[key] = object[key].replace(/\d+/, '<scriptId>'); |
| 52 else if (typeof object[key] === "object") |
| 53 objects.push(object[key]); |
| 54 } |
| 55 } |
| 56 InspectorTest.logObject(message); |
| 57 return originalMessage; |
| 58 }; |
| 59 |
| 60 InspectorTest.logObject = function(object, title) { |
| 61 var lines = []; |
| 62 |
| 63 function dumpValue(value, prefix, prefixWithName) { |
| 64 if (typeof value === "object" && value !== null) { |
| 65 if (value instanceof Array) |
| 66 dumpItems(value, prefix, prefixWithName); |
| 67 else |
| 68 dumpProperties(value, prefix, prefixWithName); |
| 69 } else { |
| 70 lines.push(prefixWithName + String(value).replace(/\n/g, " ")); |
| 71 } |
| 72 } |
| 73 |
| 74 function dumpProperties(object, prefix, firstLinePrefix) { |
| 75 prefix = prefix || ""; |
| 76 firstLinePrefix = firstLinePrefix || prefix; |
| 77 lines.push(firstLinePrefix + "{"); |
| 78 |
| 79 var propertyNames = Object.keys(object); |
| 80 propertyNames.sort(); |
| 81 for (var i = 0; i < propertyNames.length; ++i) { |
| 82 var name = propertyNames[i]; |
| 83 if (!object.hasOwnProperty(name)) |
| 84 continue; |
| 85 var prefixWithName = " " + prefix + name + " : "; |
| 86 dumpValue(object[name], " " + prefix, prefixWithName); |
| 87 } |
| 88 lines.push(prefix + "}"); |
| 89 } |
| 90 |
| 91 function dumpItems(object, prefix, firstLinePrefix) { |
| 92 prefix = prefix || ""; |
| 93 firstLinePrefix = firstLinePrefix || prefix; |
| 94 lines.push(firstLinePrefix + "["); |
| 95 for (var i = 0; i < object.length; ++i) |
| 96 dumpValue(object[i], " " + prefix, " " + prefix + "[" + i + "] : "); |
| 97 lines.push(prefix + "]"); |
| 98 } |
| 99 |
| 100 dumpValue(object, "", title || ""); |
| 101 InspectorTest.log(lines.join("\n")); |
| 102 }; |
| 103 |
| 104 InspectorTest.die = function(message, error) { |
| 105 InspectorTest.log(`${message}: ${error}\n${error.stack}`); |
| 106 InspectorTest.completeTest(); |
| 107 throw new Error(); |
| 108 }; |
| 109 |
| 110 InspectorTest.createPage = async function(url) { |
| 111 var targetId = (await DevToolsAPI._sendCommandOrDie('Target.createTarget', {ur
l: url || 'about:blank'})).targetId; |
| 112 return new InspectorTest.Page(targetId); |
| 113 }; |
| 114 |
| 115 InspectorTest.Page = class { |
| 116 constructor(targetId) { |
| 117 this._targetId = targetId; |
| 118 } |
| 119 |
| 120 async createSession() { |
| 121 await DevToolsAPI._sendCommandOrDie('Target.attachToTarget', {targetId: this
._targetId}); |
| 122 var session = new InspectorTest.Session(this); |
| 123 InspectorTest._sessions.set(this._targetId, session); |
| 124 return session; |
| 125 } |
| 126 }; |
| 127 |
| 128 InspectorTest.Session = class { |
| 129 constructor(page) { |
| 130 this._page = page; |
| 131 this._requestId = 0; |
| 132 this._dispatchTable = new Map(); |
| 133 this._eventHandlers = new Map(); |
| 134 this.Protocol = this._setupProtocol(); |
| 135 } |
| 136 |
| 137 sendRawCommand(requestId, message) { |
| 138 DevToolsAPI._sendCommandOrDie('Target.sendMessageToTarget', {targetId: this.
_page._targetId, message: message}); |
| 139 return new Promise(f => this._dispatchTable.set(requestId, f)); |
| 140 } |
| 141 |
| 142 sendCommand(method, params) { |
| 143 var requestId = ++this._requestId; |
| 144 var messageObject = { 'id': requestId, 'method': method, 'params': params }; |
| 145 if (InspectorTest._dumpInspectorProtocolMessages.has(method)) |
| 146 InspectorTest.log(`frontend => backend: ${JSON.stringify(messageObject)}`)
; |
| 147 return this.sendRawCommand(requestId, JSON.stringify(messageObject)); |
| 148 } |
| 149 |
| 150 _dispatchMessage(message) { |
| 151 if (typeof message.id === 'number') { |
| 152 var handler = this._dispatchTable.get(message.id); |
| 153 if (handler) { |
| 154 this._dispatchTable.delete(message.id); |
| 155 handler(message); |
| 156 } |
| 157 } else { |
| 158 var eventName = message.method; |
| 159 for (var handler of (this._eventHandlers.get(eventName) || [])) |
| 160 handler(message); |
| 161 } |
| 162 } |
| 163 |
| 164 _setupProtocol() { |
| 165 return new Proxy({}, { get: (target, agentName, receiver) => new Proxy({}, { |
| 166 get: (target, methodName, receiver) => { |
| 167 const eventPattern = /^on(ce)?([A-Z][A-Za-z0-9]+)/; |
| 168 var match = eventPattern.exec(methodName); |
| 169 if (!match) |
| 170 return args => this.sendCommand(`${agentName}.${methodName}`, args ||
{}); |
| 171 var eventName = match[2]; |
| 172 eventName = eventName.charAt(0).toLowerCase() + eventName.slice(1); |
| 173 if (match[1]) |
| 174 return () => this._waitForEvent(`${agentName}.${eventName}`); |
| 175 return listener => this._addEventHandler(`${agentName}.${eventName}`, li
stener); |
| 176 } |
| 177 })}); |
| 178 } |
| 179 |
| 180 _addEventHandler(eventName, handler) { |
| 181 var handlers = this._eventHandlers.get(eventName) || []; |
| 182 handlers.push(handler); |
| 183 this._eventHandlers.set(eventName, handlers); |
| 184 } |
| 185 |
| 186 _removeEventHandler(eventName, handler) { |
| 187 var handlers = this._eventHandlers.get(eventName) || []; |
| 188 var index = handlers.indexOf(handler); |
| 189 if (index === -1) |
| 190 return; |
| 191 handlers.splice(index, 1); |
| 192 this._eventHandlers.set(eventName, handlers); |
| 193 } |
| 194 |
| 195 _waitForEvent(eventName) { |
| 196 return new Promise(callback => { |
| 197 var handler = result => { |
| 198 this._removeEventHandler(eventName, handler); |
| 199 callback(result); |
| 200 }; |
| 201 this._addEventHandler(eventName, handler); |
| 202 }); |
| 203 } |
| 204 }; |
| 205 |
| 206 var DevToolsAPI = {}; |
| 207 DevToolsAPI._requestId = 0; |
| 208 DevToolsAPI._embedderMessageId = 0; |
| 209 DevToolsAPI._dispatchTable = new Map(); |
| 210 |
| 211 DevToolsAPI.dispatchMessage = function(messageOrObject) { |
| 212 var messageObject = (typeof messageOrObject === 'string' ? JSON.parse(messageO
rObject) : messageOrObject); |
| 213 var messageId = messageObject.id; |
| 214 try { |
| 215 if (typeof messageId === 'number') { |
| 216 var handler = DevToolsAPI._dispatchTable.get(messageId); |
| 217 if (handler) { |
| 218 DevToolsAPI._dispatchTable.delete(messageId); |
| 219 handler(messageObject); |
| 220 } |
| 221 } else { |
| 222 var eventName = messageObject.method; |
| 223 if (eventName === 'Target.receivedMessageFromTarget') { |
| 224 var targetId = messageObject.params.targetId; |
| 225 var message = messageObject.params.message; |
| 226 var session = InspectorTest._sessions.get(targetId); |
| 227 if (session) |
| 228 session._dispatchMessage(JSON.parse(message)); |
| 229 } |
| 230 } |
| 231 } catch(e) { |
| 232 InspectorTest.die(`Exception when dispatching message\n${JSON.stringify(mess
ageObject)}`, e); |
| 233 } |
| 234 }; |
| 235 |
| 236 DevToolsAPI._sendCommand = function(method, params) { |
| 237 var requestId = ++DevToolsAPI._requestId; |
| 238 var messageObject = { 'id': requestId, 'method': method, 'params': params }; |
| 239 var embedderMessage = { 'id': ++DevToolsAPI._embedderMessageId, 'method': 'dis
patchProtocolMessage', 'params': [JSON.stringify(messageObject)] }; |
| 240 DevToolsHost.sendMessageToEmbedder(JSON.stringify(embedderMessage)); |
| 241 return new Promise(f => DevToolsAPI._dispatchTable.set(requestId, f)); |
| 242 }; |
| 243 |
| 244 DevToolsAPI._sendCommandOrDie = function(method, params, errorMessage) { |
| 245 errorMessage = errorMessage || 'Unexpected error'; |
| 246 return DevToolsAPI._sendCommand(method, params).then(message => { |
| 247 if (message.error) |
| 248 InspectorTest.die('Error starting the test', e); |
| 249 return message.result; |
| 250 }); |
| 251 }; |
| 252 |
| 253 DevToolsAPI.embedderMessageAck = function() { |
| 254 }; |
| 255 |
| 256 InspectorTest.start = async function(description, url) { |
| 257 try { |
| 258 InspectorTest.log(description); |
| 259 var page = await InspectorTest.createPage(url); |
| 260 var session = await page.createSession(); |
| 261 return { page: page, session: session, Protocol: session.Protocol }; |
| 262 } catch (e) { |
| 263 InspectorTest.die('Error starting the test', e); |
| 264 } |
| 265 }; |
| 266 |
| 267 InspectorTest.debugTest = function(testFunction) { |
| 268 window.test = testFunction; |
| 269 InspectorTest.log = console.log; |
| 270 InspectorTest.completeTest = () => console.log('Test completed'); |
| 271 return () => {}; |
| 272 }; |
| 273 |
| 274 window.addEventListener('load', async () => { |
| 275 testRunner.dumpAsText(); |
| 276 testRunner.waitUntilDone(); |
| 277 testRunner.setCanOpenWindows(true); |
| 278 try { |
| 279 var testScriptURL = window.location.search.substring(1); |
| 280 var testScript = await (await fetch(testScriptURL)).text(); |
| 281 eval(`${testScript}\n//# sourceURL=${testScriptURL}`); |
| 282 } catch(e) { |
| 283 InspectorTest.die('Unable to execute test script', e); |
| 284 } |
| 285 }, false); |
| 286 |
| 287 window.addEventListener('error', (message, source, lineno, colno, error) => { |
| 288 InspectorTest.die('General error', error); |
| 289 }, false); |
| 290 |
| 291 window.addEventListener('unhandledrejection', error => { |
| 292 InspectorTest.die('General error', error); |
| 293 }, false); |
| 294 |
| 295 </script> |
| 296 </head> |
| 297 </html> |
OLD | NEW |