| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 /* eslint-disable indent */ | 31 /* eslint-disable indent */ |
| 32 | 32 |
| 33 function defineCommonExtensionSymbols(apiPrivate) | 33 function defineCommonExtensionSymbols(apiPrivate) { |
| 34 { | 34 if (!apiPrivate.audits) |
| 35 if (!apiPrivate.audits) | 35 apiPrivate.audits = {}; |
| 36 apiPrivate.audits = {}; | 36 apiPrivate.audits.Severity = {Info: 'info', Warning: 'warning', Severe: 'sever
e'}; |
| 37 apiPrivate.audits.Severity = { | |
| 38 Info: "info", | |
| 39 Warning: "warning", | |
| 40 Severe: "severe" | |
| 41 }; | |
| 42 | 37 |
| 43 if (!apiPrivate.panels) | 38 if (!apiPrivate.panels) |
| 44 apiPrivate.panels = {}; | 39 apiPrivate.panels = {}; |
| 45 apiPrivate.panels.SearchAction = { | 40 apiPrivate.panels.SearchAction = { |
| 46 CancelSearch: "cancelSearch", | 41 CancelSearch: 'cancelSearch', |
| 47 PerformSearch: "performSearch", | 42 PerformSearch: 'performSearch', |
| 48 NextSearchResult: "nextSearchResult", | 43 NextSearchResult: 'nextSearchResult', |
| 49 PreviousSearchResult: "previousSearchResult" | 44 PreviousSearchResult: 'previousSearchResult' |
| 50 }; | 45 }; |
| 51 | 46 |
| 52 /** @enum {string} */ | 47 /** @enum {string} */ |
| 53 apiPrivate.Events = { | 48 apiPrivate.Events = { |
| 54 AuditStarted: "audit-started-", | 49 AuditStarted: 'audit-started-', |
| 55 ButtonClicked: "button-clicked-", | 50 ButtonClicked: 'button-clicked-', |
| 56 PanelObjectSelected: "panel-objectSelected-", | 51 PanelObjectSelected: 'panel-objectSelected-', |
| 57 NetworkRequestFinished: "network-request-finished", | 52 NetworkRequestFinished: 'network-request-finished', |
| 58 OpenResource: "open-resource", | 53 OpenResource: 'open-resource', |
| 59 PanelSearch: "panel-search-", | 54 PanelSearch: 'panel-search-', |
| 60 RecordingStarted: "trace-recording-started-", | 55 RecordingStarted: 'trace-recording-started-', |
| 61 RecordingStopped: "trace-recording-stopped-", | 56 RecordingStopped: 'trace-recording-stopped-', |
| 62 ResourceAdded: "resource-added", | 57 ResourceAdded: 'resource-added', |
| 63 ResourceContentCommitted: "resource-content-committed", | 58 ResourceContentCommitted: 'resource-content-committed', |
| 64 ViewShown: "view-shown-", | 59 ViewShown: 'view-shown-', |
| 65 ViewHidden: "view-hidden-" | 60 ViewHidden: 'view-hidden-' |
| 66 }; | 61 }; |
| 67 | 62 |
| 68 /** @enum {string} */ | 63 /** @enum {string} */ |
| 69 apiPrivate.Commands = { | 64 apiPrivate.Commands = { |
| 70 AddAuditCategory: "addAuditCategory", | 65 AddAuditCategory: 'addAuditCategory', |
| 71 AddAuditResult: "addAuditResult", | 66 AddAuditResult: 'addAuditResult', |
| 72 AddRequestHeaders: "addRequestHeaders", | 67 AddRequestHeaders: 'addRequestHeaders', |
| 73 AddTraceProvider: "addTraceProvider", | 68 AddTraceProvider: 'addTraceProvider', |
| 74 ApplyStyleSheet: "applyStyleSheet", | 69 ApplyStyleSheet: 'applyStyleSheet', |
| 75 CreatePanel: "createPanel", | 70 CreatePanel: 'createPanel', |
| 76 CreateSidebarPane: "createSidebarPane", | 71 CreateSidebarPane: 'createSidebarPane', |
| 77 CreateToolbarButton: "createToolbarButton", | 72 CreateToolbarButton: 'createToolbarButton', |
| 78 EvaluateOnInspectedPage: "evaluateOnInspectedPage", | 73 EvaluateOnInspectedPage: 'evaluateOnInspectedPage', |
| 79 ForwardKeyboardEvent: "_forwardKeyboardEvent", | 74 ForwardKeyboardEvent: '_forwardKeyboardEvent', |
| 80 GetHAR: "getHAR", | 75 GetHAR: 'getHAR', |
| 81 GetPageResources: "getPageResources", | 76 GetPageResources: 'getPageResources', |
| 82 GetRequestContent: "getRequestContent", | 77 GetRequestContent: 'getRequestContent', |
| 83 GetResourceContent: "getResourceContent", | 78 GetResourceContent: 'getResourceContent', |
| 84 InspectedURLChanged: "inspectedURLChanged", | 79 InspectedURLChanged: 'inspectedURLChanged', |
| 85 OpenResource: "openResource", | 80 OpenResource: 'openResource', |
| 86 Reload: "Reload", | 81 Reload: 'Reload', |
| 87 Subscribe: "subscribe", | 82 Subscribe: 'subscribe', |
| 88 SetOpenResourceHandler: "setOpenResourceHandler", | 83 SetOpenResourceHandler: 'setOpenResourceHandler', |
| 89 SetResourceContent: "setResourceContent", | 84 SetResourceContent: 'setResourceContent', |
| 90 SetSidebarContent: "setSidebarContent", | 85 SetSidebarContent: 'setSidebarContent', |
| 91 SetSidebarHeight: "setSidebarHeight", | 86 SetSidebarHeight: 'setSidebarHeight', |
| 92 SetSidebarPage: "setSidebarPage", | 87 SetSidebarPage: 'setSidebarPage', |
| 93 ShowPanel: "showPanel", | 88 ShowPanel: 'showPanel', |
| 94 StopAuditCategoryRun: "stopAuditCategoryRun", | 89 StopAuditCategoryRun: 'stopAuditCategoryRun', |
| 95 Unsubscribe: "unsubscribe", | 90 Unsubscribe: 'unsubscribe', |
| 96 UpdateAuditProgress: "updateAuditProgress", | 91 UpdateAuditProgress: 'updateAuditProgress', |
| 97 UpdateButton: "updateButton" | 92 UpdateButton: 'updateButton' |
| 98 }; | 93 }; |
| 99 } | 94 } |
| 100 | 95 |
| 101 /** | 96 /** |
| 102 * @param {!ExtensionDescriptor} extensionInfo | 97 * @param {!ExtensionDescriptor} extensionInfo |
| 103 * @param {string} inspectedTabId | 98 * @param {string} inspectedTabId |
| 104 * @param {string} themeName | 99 * @param {string} themeName |
| 105 * @param {number} injectedScriptId | 100 * @param {number} injectedScriptId |
| 106 * @param {function(!Object, !Object)} testHook | 101 * @param {function(!Object, !Object)} testHook |
| 107 * @suppressGlobalPropertiesCheck | 102 * @suppressGlobalPropertiesCheck |
| 108 */ | 103 */ |
| 109 function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, testHook
, injectedScriptId) | 104 function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, testHook
, injectedScriptId) { |
| 110 { | 105 var apiPrivate = {}; |
| 111 | 106 |
| 112 var apiPrivate = {}; | 107 defineCommonExtensionSymbols(apiPrivate); |
| 113 | 108 |
| 114 defineCommonExtensionSymbols(apiPrivate); | 109 var commands = apiPrivate.Commands; |
| 115 | 110 var events = apiPrivate.Events; |
| 116 var commands = apiPrivate.Commands; | 111 var userAction = false; |
| 117 var events = apiPrivate.Events; | 112 |
| 118 var userAction = false; | 113 // Here and below, all constructors are private to API implementation. |
| 119 | 114 // For a public type Foo, if internal fields are present, these are on |
| 120 // Here and below, all constructors are private to API implementation. | 115 // a private FooImpl type, an instance of FooImpl is used in a closure |
| 121 // For a public type Foo, if internal fields are present, these are on | 116 // by Foo consutrctor to re-bind publicly exported members to an instance |
| 122 // a private FooImpl type, an instance of FooImpl is used in a closure | 117 // of Foo. |
| 123 // by Foo consutrctor to re-bind publicly exported members to an instance | 118 |
| 124 // of Foo. | 119 /** |
| 125 | 120 * @constructor |
| 126 /** | 121 */ |
| 127 * @constructor | 122 function EventSinkImpl(type, customDispatch) { |
| 128 */ | |
| 129 function EventSinkImpl(type, customDispatch) | |
| 130 { | |
| 131 this._type = type; | 123 this._type = type; |
| 132 this._listeners = []; | 124 this._listeners = []; |
| 133 this._customDispatch = customDispatch; | 125 this._customDispatch = customDispatch; |
| 134 } | 126 } |
| 135 | 127 |
| 136 EventSinkImpl.prototype = { | 128 EventSinkImpl.prototype = { |
| 137 addListener: function(callback) | 129 addListener: function(callback) { |
| 138 { | 130 if (typeof callback !== 'function') |
| 139 if (typeof callback !== "function") | 131 throw 'addListener: callback is not a function'; |
| 140 throw "addListener: callback is not a function"; | 132 if (this._listeners.length === 0) |
| 141 if (this._listeners.length === 0) | 133 extensionServer.sendRequest({command: commands.Subscribe, type: this._ty
pe}); |
| 142 extensionServer.sendRequest({ command: commands.Subscribe, type: thi
s._type }); | 134 this._listeners.push(callback); |
| 143 this._listeners.push(callback); | 135 extensionServer.registerHandler('notify-' + this._type, this._dispatch.bin
d(this)); |
| 144 extensionServer.registerHandler("notify-" + this._type, this._dispatch.b
ind(this)); | 136 }, |
| 145 }, | 137 |
| 146 | 138 removeListener: function(callback) { |
| 147 removeListener: function(callback) | 139 var listeners = this._listeners; |
| 148 { | 140 |
| 149 var listeners = this._listeners; | 141 for (var i = 0; i < listeners.length; ++i) { |
| 150 | 142 if (listeners[i] === callback) { |
| 151 for (var i = 0; i < listeners.length; ++i) { | 143 listeners.splice(i, 1); |
| 152 if (listeners[i] === callback) { | 144 break; |
| 153 listeners.splice(i, 1); | |
| 154 break; | |
| 155 } | |
| 156 } | 145 } |
| 157 if (this._listeners.length === 0) | 146 } |
| 158 extensionServer.sendRequest({ command: commands.Unsubscribe, type: t
his._type }); | 147 if (this._listeners.length === 0) |
| 148 extensionServer.sendRequest({command: commands.Unsubscribe, type: this._
type}); |
| 159 }, | 149 }, |
| 160 | 150 |
| 161 /** | 151 /** |
| 162 * @param {...} vararg | 152 * @param {...} vararg |
| 163 */ | 153 */ |
| 164 _fire: function(vararg) | 154 _fire: function(vararg) { |
| 165 { | 155 var listeners = this._listeners.slice(); |
| 166 var listeners = this._listeners.slice(); | 156 for (var i = 0; i < listeners.length; ++i) |
| 167 for (var i = 0; i < listeners.length; ++i) | 157 listeners[i].apply(null, arguments); |
| 168 listeners[i].apply(null, arguments); | 158 }, |
| 169 }, | 159 |
| 170 | 160 _dispatch: function(request) { |
| 171 _dispatch: function(request) | 161 if (this._customDispatch) |
| 172 { | 162 this._customDispatch.call(this, request); |
| 173 if (this._customDispatch) | 163 else |
| 174 this._customDispatch.call(this, request); | 164 this._fire.apply(this, request.arguments); |
| 175 else | 165 } |
| 176 this._fire.apply(this, request.arguments); | 166 }; |
| 177 } | 167 |
| 178 }; | 168 /** |
| 179 | 169 * @constructor |
| 180 /** | 170 */ |
| 181 * @constructor | 171 function InspectorExtensionAPI() { |
| 182 */ | |
| 183 function InspectorExtensionAPI() | |
| 184 { | |
| 185 this.audits = new Audits(); | 172 this.audits = new Audits(); |
| 186 this.inspectedWindow = new InspectedWindow(); | 173 this.inspectedWindow = new InspectedWindow(); |
| 187 this.panels = new Panels(); | 174 this.panels = new Panels(); |
| 188 this.network = new Network(); | 175 this.network = new Network(); |
| 189 this.timeline = new Timeline(); | 176 this.timeline = new Timeline(); |
| 190 defineDeprecatedProperty(this, "webInspector", "resources", "network"); | 177 defineDeprecatedProperty(this, 'webInspector', 'resources', 'network'); |
| 191 } | 178 } |
| 192 | 179 |
| 193 /** | 180 /** |
| 194 * @constructor | 181 * @constructor |
| 195 */ | 182 */ |
| 196 function Network() | 183 function Network() { |
| 197 { | |
| 198 /** | 184 /** |
| 199 * @this {EventSinkImpl} | 185 * @this {EventSinkImpl} |
| 200 */ | 186 */ |
| 201 function dispatchRequestEvent(message) | 187 function dispatchRequestEvent(message) { |
| 202 { | 188 var request = message.arguments[1]; |
| 203 var request = message.arguments[1]; | 189 request.__proto__ = new Request(message.arguments[0]); |
| 204 request.__proto__ = new Request(message.arguments[0]); | 190 this._fire(request); |
| 205 this._fire(request); | |
| 206 } | 191 } |
| 207 this.onRequestFinished = new EventSink(events.NetworkRequestFinished, dispat
chRequestEvent); | 192 this.onRequestFinished = new EventSink(events.NetworkRequestFinished, dispat
chRequestEvent); |
| 208 defineDeprecatedProperty(this, "network", "onFinished", "onRequestFinished")
; | 193 defineDeprecatedProperty(this, 'network', 'onFinished', 'onRequestFinished')
; |
| 209 this.onNavigated = new EventSink(events.InspectedURLChanged); | 194 this.onNavigated = new EventSink(events.InspectedURLChanged); |
| 210 } | 195 } |
| 211 | 196 |
| 212 Network.prototype = { | 197 Network.prototype = { |
| 213 getHAR: function(callback) | 198 getHAR: function(callback) { |
| 214 { | 199 function callbackWrapper(result) { |
| 215 function callbackWrapper(result) | 200 var entries = (result && result.entries) || []; |
| 216 { | 201 for (var i = 0; i < entries.length; ++i) { |
| 217 var entries = (result && result.entries) || []; | 202 entries[i].__proto__ = new Request(entries[i]._requestId); |
| 218 for (var i = 0; i < entries.length; ++i) { | 203 delete entries[i]._requestId; |
| 219 entries[i].__proto__ = new Request(entries[i]._requestId); | |
| 220 delete entries[i]._requestId; | |
| 221 } | |
| 222 callback(result); | |
| 223 } | 204 } |
| 224 extensionServer.sendRequest({ command: commands.GetHAR }, callback && ca
llbackWrapper); | 205 callback(result); |
| 225 }, | 206 } |
| 226 | 207 extensionServer.sendRequest({command: commands.GetHAR}, callback && callba
ckWrapper); |
| 227 addRequestHeaders: function(headers) | 208 }, |
| 228 { | 209 |
| 229 extensionServer.sendRequest({ command: commands.AddRequestHeaders, heade
rs: headers, extensionId: window.location.hostname }); | 210 addRequestHeaders: function(headers) { |
| 230 } | 211 extensionServer.sendRequest( |
| 231 }; | 212 {command: commands.AddRequestHeaders, headers: headers, extensionId: w
indow.location.hostname}); |
| 232 | 213 } |
| 233 /** | 214 }; |
| 234 * @constructor | 215 |
| 235 */ | 216 /** |
| 236 function RequestImpl(id) | 217 * @constructor |
| 237 { | 218 */ |
| 219 function RequestImpl(id) { |
| 238 this._id = id; | 220 this._id = id; |
| 239 } | 221 } |
| 240 | 222 |
| 241 RequestImpl.prototype = { | 223 RequestImpl.prototype = { |
| 242 getContent: function(callback) | 224 getContent: function(callback) { |
| 243 { | 225 function callbackWrapper(response) { |
| 244 function callbackWrapper(response) | 226 callback(response.content, response.encoding); |
| 245 { | 227 } |
| 246 callback(response.content, response.encoding); | 228 extensionServer.sendRequest({command: commands.GetRequestContent, id: this
._id}, callback && callbackWrapper); |
| 229 } |
| 230 }; |
| 231 |
| 232 /** |
| 233 * @constructor |
| 234 */ |
| 235 function Panels() { |
| 236 var panels = { |
| 237 elements: new ElementsPanel(), |
| 238 sources: new SourcesPanel(), |
| 239 }; |
| 240 |
| 241 function panelGetter(name) { |
| 242 return panels[name]; |
| 243 } |
| 244 for (var panel in panels) |
| 245 this.__defineGetter__(panel, panelGetter.bind(null, panel)); |
| 246 this.applyStyleSheet = function(styleSheet) { |
| 247 extensionServer.sendRequest({command: commands.ApplyStyleSheet, styleSheet
: styleSheet}); |
| 248 }; |
| 249 } |
| 250 |
| 251 Panels.prototype = { |
| 252 create: function(title, icon, page, callback) { |
| 253 var id = 'extension-panel-' + extensionServer.nextObjectId(); |
| 254 var request = {command: commands.CreatePanel, id: id, title: title, icon:
icon, page: page}; |
| 255 extensionServer.sendRequest(request, callback && callback.bind(this, new E
xtensionPanel(id))); |
| 256 }, |
| 257 |
| 258 setOpenResourceHandler: function(callback) { |
| 259 var hadHandler = extensionServer.hasHandler(events.OpenResource); |
| 260 |
| 261 function callbackWrapper(message) { |
| 262 // Allow the panel to show itself when handling the event. |
| 263 userAction = true; |
| 264 try { |
| 265 callback.call(null, new Resource(message.resource), message.lineNumber
); |
| 266 } finally { |
| 267 userAction = false; |
| 247 } | 268 } |
| 248 extensionServer.sendRequest({ command: commands.GetRequestContent, id: t
his._id }, callback && callbackWrapper); | 269 } |
| 249 } | 270 |
| 250 }; | 271 if (!callback) |
| 251 | 272 extensionServer.unregisterHandler(events.OpenResource); |
| 252 /** | 273 else |
| 253 * @constructor | 274 extensionServer.registerHandler(events.OpenResource, callbackWrapper); |
| 254 */ | 275 |
| 255 function Panels() | 276 // Only send command if we either removed an existing handler or added han
dler and had none before. |
| 256 { | 277 if (hadHandler === !callback) |
| 257 var panels = { | 278 extensionServer.sendRequest({command: commands.SetOpenResourceHandler, '
handlerPresent': !!callback}); |
| 258 elements: new ElementsPanel(), | 279 }, |
| 259 sources: new SourcesPanel(), | 280 |
| 260 }; | 281 openResource: function(url, lineNumber, callback) { |
| 261 | 282 extensionServer.sendRequest({command: commands.OpenResource, 'url': url, '
lineNumber': lineNumber}, callback); |
| 262 function panelGetter(name) | 283 }, |
| 263 { | 284 |
| 264 return panels[name]; | 285 get SearchAction() { |
| 265 } | 286 return apiPrivate.panels.SearchAction; |
| 266 for (var panel in panels) | 287 } |
| 267 this.__defineGetter__(panel, panelGetter.bind(null, panel)); | 288 }; |
| 268 this.applyStyleSheet = function(styleSheet) { extensionServer.sendRequest({
command: commands.ApplyStyleSheet, styleSheet: styleSheet }); }; | 289 |
| 269 } | 290 /** |
| 270 | 291 * @constructor |
| 271 Panels.prototype = { | 292 */ |
| 272 create: function(title, icon, page, callback) | 293 function ExtensionViewImpl(id) { |
| 273 { | |
| 274 var id = "extension-panel-" + extensionServer.nextObjectId(); | |
| 275 var request = { | |
| 276 command: commands.CreatePanel, | |
| 277 id: id, | |
| 278 title: title, | |
| 279 icon: icon, | |
| 280 page: page | |
| 281 }; | |
| 282 extensionServer.sendRequest(request, callback && callback.bind(this, new
ExtensionPanel(id))); | |
| 283 }, | |
| 284 | |
| 285 setOpenResourceHandler: function(callback) | |
| 286 { | |
| 287 var hadHandler = extensionServer.hasHandler(events.OpenResource); | |
| 288 | |
| 289 function callbackWrapper(message) | |
| 290 { | |
| 291 // Allow the panel to show itself when handling the event. | |
| 292 userAction = true; | |
| 293 try { | |
| 294 callback.call(null, new Resource(message.resource), message.line
Number); | |
| 295 } finally { | |
| 296 userAction = false; | |
| 297 } | |
| 298 } | |
| 299 | |
| 300 if (!callback) | |
| 301 extensionServer.unregisterHandler(events.OpenResource); | |
| 302 else | |
| 303 extensionServer.registerHandler(events.OpenResource, callbackWrapper
); | |
| 304 | |
| 305 // Only send command if we either removed an existing handler or added h
andler and had none before. | |
| 306 if (hadHandler === !callback) | |
| 307 extensionServer.sendRequest({ command: commands.SetOpenResourceHandl
er, "handlerPresent": !!callback }); | |
| 308 }, | |
| 309 | |
| 310 openResource: function(url, lineNumber, callback) | |
| 311 { | |
| 312 extensionServer.sendRequest({ command: commands.OpenResource, "url": url
, "lineNumber": lineNumber }, callback); | |
| 313 }, | |
| 314 | |
| 315 get SearchAction() | |
| 316 { | |
| 317 return apiPrivate.panels.SearchAction; | |
| 318 } | |
| 319 }; | |
| 320 | |
| 321 /** | |
| 322 * @constructor | |
| 323 */ | |
| 324 function ExtensionViewImpl(id) | |
| 325 { | |
| 326 this._id = id; | 294 this._id = id; |
| 327 | 295 |
| 328 /** | 296 /** |
| 329 * @this {EventSinkImpl} | 297 * @this {EventSinkImpl} |
| 330 */ | 298 */ |
| 331 function dispatchShowEvent(message) | 299 function dispatchShowEvent(message) { |
| 332 { | 300 var frameIndex = message.arguments[0]; |
| 333 var frameIndex = message.arguments[0]; | 301 if (typeof frameIndex === 'number') |
| 334 if (typeof frameIndex === "number") | 302 this._fire(window.parent.frames[frameIndex]); |
| 335 this._fire(window.parent.frames[frameIndex]); | 303 else |
| 336 else | 304 this._fire(); |
| 337 this._fire(); | |
| 338 } | 305 } |
| 339 | 306 |
| 340 if (id) { | 307 if (id) { |
| 341 this.onShown = new EventSink(events.ViewShown + id, dispatchShowEvent); | 308 this.onShown = new EventSink(events.ViewShown + id, dispatchShowEvent); |
| 342 this.onHidden = new EventSink(events.ViewHidden + id); | 309 this.onHidden = new EventSink(events.ViewHidden + id); |
| 343 } | 310 } |
| 344 } | 311 } |
| 345 | 312 |
| 346 /** | 313 /** |
| 347 * @constructor | 314 * @constructor |
| 348 * @extends {ExtensionViewImpl} | 315 * @extends {ExtensionViewImpl} |
| 349 * @param {string} hostPanelName | 316 * @param {string} hostPanelName |
| 350 */ | 317 */ |
| 351 function PanelWithSidebarImpl(hostPanelName) | 318 function PanelWithSidebarImpl(hostPanelName) { |
| 352 { | |
| 353 ExtensionViewImpl.call(this, null); | 319 ExtensionViewImpl.call(this, null); |
| 354 this._hostPanelName = hostPanelName; | 320 this._hostPanelName = hostPanelName; |
| 355 this.onSelectionChanged = new EventSink(events.PanelObjectSelected + hostPan
elName); | 321 this.onSelectionChanged = new EventSink(events.PanelObjectSelected + hostPan
elName); |
| 356 } | 322 } |
| 357 | 323 |
| 358 PanelWithSidebarImpl.prototype = { | 324 PanelWithSidebarImpl.prototype = { |
| 359 createSidebarPane: function(title, callback) | 325 createSidebarPane: function(title, callback) { |
| 360 { | 326 var id = 'extension-sidebar-' + extensionServer.nextObjectId(); |
| 361 var id = "extension-sidebar-" + extensionServer.nextObjectId(); | 327 var request = {command: commands.CreateSidebarPane, panel: this._hostPanel
Name, id: id, title: title}; |
| 362 var request = { | 328 function callbackWrapper() { |
| 363 command: commands.CreateSidebarPane, | 329 callback(new ExtensionSidebarPane(id)); |
| 364 panel: this._hostPanelName, | 330 } |
| 365 id: id, | 331 extensionServer.sendRequest(request, callback && callbackWrapper); |
| 366 title: title | |
| 367 }; | |
| 368 function callbackWrapper() | |
| 369 { | |
| 370 callback(new ExtensionSidebarPane(id)); | |
| 371 } | |
| 372 extensionServer.sendRequest(request, callback && callbackWrapper); | |
| 373 }, | 332 }, |
| 374 | 333 |
| 375 __proto__: ExtensionViewImpl.prototype | 334 __proto__: ExtensionViewImpl.prototype |
| 376 }; | 335 }; |
| 377 | 336 |
| 378 function declareInterfaceClass(implConstructor) | 337 function declareInterfaceClass(implConstructor) { |
| 379 { | 338 return function() { |
| 380 return function() | 339 var impl = {__proto__: implConstructor.prototype}; |
| 381 { | 340 implConstructor.apply(impl, arguments); |
| 382 var impl = { __proto__: implConstructor.prototype }; | 341 populateInterfaceClass(this, impl); |
| 383 implConstructor.apply(impl, arguments); | |
| 384 populateInterfaceClass(this, impl); | |
| 385 }; | 342 }; |
| 386 } | 343 } |
| 387 | 344 |
| 388 function defineDeprecatedProperty(object, className, oldName, newName) | 345 function defineDeprecatedProperty(object, className, oldName, newName) { |
| 389 { | |
| 390 var warningGiven = false; | 346 var warningGiven = false; |
| 391 function getter() | 347 function getter() { |
| 392 { | 348 if (!warningGiven) { |
| 393 if (!warningGiven) { | 349 console.warn(className + '.' + oldName + ' is deprecated. Use ' + classN
ame + '.' + newName + ' instead'); |
| 394 console.warn(className + "." + oldName + " is deprecated. Use " + cl
assName + "." + newName + " instead"); | 350 warningGiven = true; |
| 395 warningGiven = true; | 351 } |
| 396 } | 352 return object[newName]; |
| 397 return object[newName]; | |
| 398 } | 353 } |
| 399 object.__defineGetter__(oldName, getter); | 354 object.__defineGetter__(oldName, getter); |
| 400 } | 355 } |
| 401 | 356 |
| 402 function extractCallbackArgument(args) | 357 function extractCallbackArgument(args) { |
| 403 { | |
| 404 var lastArgument = args[args.length - 1]; | 358 var lastArgument = args[args.length - 1]; |
| 405 return typeof lastArgument === "function" ? lastArgument : undefined; | 359 return typeof lastArgument === 'function' ? lastArgument : undefined; |
| 406 } | 360 } |
| 407 | 361 |
| 408 var AuditCategory = declareInterfaceClass(AuditCategoryImpl); | 362 var AuditCategory = declareInterfaceClass(AuditCategoryImpl); |
| 409 var AuditResult = declareInterfaceClass(AuditResultImpl); | 363 var AuditResult = declareInterfaceClass(AuditResultImpl); |
| 410 var Button = declareInterfaceClass(ButtonImpl); | 364 var Button = declareInterfaceClass(ButtonImpl); |
| 411 var EventSink = declareInterfaceClass(EventSinkImpl); | 365 var EventSink = declareInterfaceClass(EventSinkImpl); |
| 412 var ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl); | 366 var ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl); |
| 413 var ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl); | 367 var ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl); |
| 414 var PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl); | 368 var PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl); |
| 415 var Request = declareInterfaceClass(RequestImpl); | 369 var Request = declareInterfaceClass(RequestImpl); |
| 416 var Resource = declareInterfaceClass(ResourceImpl); | 370 var Resource = declareInterfaceClass(ResourceImpl); |
| 417 | 371 |
| 418 /** | 372 /** |
| 419 * @constructor | 373 * @constructor |
| 420 * @extends {PanelWithSidebar} | 374 * @extends {PanelWithSidebar} |
| 421 */ | 375 */ |
| 422 function ElementsPanel() | 376 function ElementsPanel() { |
| 423 { | 377 PanelWithSidebar.call(this, 'elements'); |
| 424 PanelWithSidebar.call(this, "elements"); | 378 } |
| 425 } | 379 |
| 426 | 380 ElementsPanel.prototype = {__proto__: PanelWithSidebar.prototype}; |
| 427 ElementsPanel.prototype = { | 381 |
| 428 __proto__: PanelWithSidebar.prototype | 382 /** |
| 429 }; | 383 * @constructor |
| 430 | 384 * @extends {PanelWithSidebar} |
| 431 /** | 385 */ |
| 432 * @constructor | 386 function SourcesPanel() { |
| 433 * @extends {PanelWithSidebar} | 387 PanelWithSidebar.call(this, 'sources'); |
| 434 */ | 388 } |
| 435 function SourcesPanel() | 389 |
| 436 { | 390 SourcesPanel.prototype = {__proto__: PanelWithSidebar.prototype}; |
| 437 PanelWithSidebar.call(this, "sources"); | 391 |
| 438 } | 392 /** |
| 439 | 393 * @constructor |
| 440 SourcesPanel.prototype = { | 394 * @extends {ExtensionViewImpl} |
| 441 __proto__: PanelWithSidebar.prototype | 395 */ |
| 442 }; | 396 function ExtensionPanelImpl(id) { |
| 443 | |
| 444 /** | |
| 445 * @constructor | |
| 446 * @extends {ExtensionViewImpl} | |
| 447 */ | |
| 448 function ExtensionPanelImpl(id) | |
| 449 { | |
| 450 ExtensionViewImpl.call(this, id); | 397 ExtensionViewImpl.call(this, id); |
| 451 this.onSearch = new EventSink(events.PanelSearch + id); | 398 this.onSearch = new EventSink(events.PanelSearch + id); |
| 452 } | 399 } |
| 453 | 400 |
| 454 ExtensionPanelImpl.prototype = { | 401 ExtensionPanelImpl.prototype = { |
| 455 /** | 402 /** |
| 456 * @return {!Object} | 403 * @return {!Object} |
| 457 */ | 404 */ |
| 458 createStatusBarButton: function(iconPath, tooltipText, disabled) | 405 createStatusBarButton: function(iconPath, tooltipText, disabled) { |
| 459 { | 406 var id = 'button-' + extensionServer.nextObjectId(); |
| 460 var id = "button-" + extensionServer.nextObjectId(); | 407 var request = { |
| 461 var request = { | 408 command: commands.CreateToolbarButton, |
| 462 command: commands.CreateToolbarButton, | 409 panel: this._id, |
| 463 panel: this._id, | 410 id: id, |
| 464 id: id, | 411 icon: iconPath, |
| 465 icon: iconPath, | 412 tooltip: tooltipText, |
| 466 tooltip: tooltipText, | 413 disabled: !!disabled |
| 467 disabled: !!disabled | 414 }; |
| 468 }; | 415 extensionServer.sendRequest(request); |
| 469 extensionServer.sendRequest(request); | 416 return new Button(id); |
| 470 return new Button(id); | 417 }, |
| 471 }, | 418 |
| 472 | 419 show: function() { |
| 473 show: function() | 420 if (!userAction) |
| 474 { | 421 return; |
| 475 if (!userAction) | 422 |
| 476 return; | 423 var request = {command: commands.ShowPanel, id: this._id}; |
| 477 | 424 extensionServer.sendRequest(request); |
| 478 var request = { | |
| 479 command: commands.ShowPanel, | |
| 480 id: this._id | |
| 481 }; | |
| 482 extensionServer.sendRequest(request); | |
| 483 }, | 425 }, |
| 484 | 426 |
| 485 __proto__: ExtensionViewImpl.prototype | 427 __proto__: ExtensionViewImpl.prototype |
| 486 }; | 428 }; |
| 487 | 429 |
| 488 /** | 430 /** |
| 489 * @constructor | 431 * @constructor |
| 490 * @extends {ExtensionViewImpl} | 432 * @extends {ExtensionViewImpl} |
| 491 */ | 433 */ |
| 492 function ExtensionSidebarPaneImpl(id) | 434 function ExtensionSidebarPaneImpl(id) { |
| 493 { | |
| 494 ExtensionViewImpl.call(this, id); | 435 ExtensionViewImpl.call(this, id); |
| 495 } | 436 } |
| 496 | 437 |
| 497 ExtensionSidebarPaneImpl.prototype = { | 438 ExtensionSidebarPaneImpl.prototype = { |
| 498 setHeight: function(height) | 439 setHeight: function(height) { |
| 499 { | 440 extensionServer.sendRequest({command: commands.SetSidebarHeight, id: this.
_id, height: height}); |
| 500 extensionServer.sendRequest({ command: commands.SetSidebarHeight, id: th
is._id, height: height }); | 441 }, |
| 501 }, | 442 |
| 502 | 443 setExpression: function(expression, rootTitle, evaluateOptions) { |
| 503 setExpression: function(expression, rootTitle, evaluateOptions) | 444 var request = { |
| 504 { | 445 command: commands.SetSidebarContent, |
| 505 var request = { | 446 id: this._id, |
| 506 command: commands.SetSidebarContent, | 447 expression: expression, |
| 507 id: this._id, | 448 rootTitle: rootTitle, |
| 508 expression: expression, | 449 evaluateOnPage: true, |
| 509 rootTitle: rootTitle, | 450 }; |
| 510 evaluateOnPage: true, | 451 if (typeof evaluateOptions === 'object') |
| 511 }; | 452 request.evaluateOptions = evaluateOptions; |
| 512 if (typeof evaluateOptions === "object") | 453 extensionServer.sendRequest(request, extractCallbackArgument(arguments)); |
| 513 request.evaluateOptions = evaluateOptions; | 454 }, |
| 514 extensionServer.sendRequest(request, extractCallbackArgument(arguments))
; | 455 |
| 515 }, | 456 setObject: function(jsonObject, rootTitle, callback) { |
| 516 | 457 extensionServer.sendRequest( |
| 517 setObject: function(jsonObject, rootTitle, callback) | 458 {command: commands.SetSidebarContent, id: this._id, expression: jsonOb
ject, rootTitle: rootTitle}, callback); |
| 518 { | 459 }, |
| 519 extensionServer.sendRequest({ command: commands.SetSidebarContent, id: t
his._id, expression: jsonObject, rootTitle: rootTitle }, callback); | 460 |
| 520 }, | 461 setPage: function(page) { |
| 521 | 462 extensionServer.sendRequest({command: commands.SetSidebarPage, id: this._i
d, page: page}); |
| 522 setPage: function(page) | |
| 523 { | |
| 524 extensionServer.sendRequest({ command: commands.SetSidebarPage, id: this
._id, page: page }); | |
| 525 }, | 463 }, |
| 526 | 464 |
| 527 __proto__: ExtensionViewImpl.prototype | 465 __proto__: ExtensionViewImpl.prototype |
| 528 }; | 466 }; |
| 529 | 467 |
| 530 /** | 468 /** |
| 531 * @constructor | 469 * @constructor |
| 532 */ | 470 */ |
| 533 function ButtonImpl(id) | 471 function ButtonImpl(id) { |
| 534 { | |
| 535 this._id = id; | 472 this._id = id; |
| 536 this.onClicked = new EventSink(events.ButtonClicked + id); | 473 this.onClicked = new EventSink(events.ButtonClicked + id); |
| 537 } | 474 } |
| 538 | 475 |
| 539 ButtonImpl.prototype = { | 476 ButtonImpl.prototype = { |
| 540 update: function(iconPath, tooltipText, disabled) | 477 update: function(iconPath, tooltipText, disabled) { |
| 541 { | 478 var request = |
| 542 var request = { | 479 {command: commands.UpdateButton, id: this._id, icon: iconPath, tooltip
: tooltipText, disabled: !!disabled}; |
| 543 command: commands.UpdateButton, | 480 extensionServer.sendRequest(request); |
| 544 id: this._id, | 481 } |
| 545 icon: iconPath, | 482 }; |
| 546 tooltip: tooltipText, | 483 |
| 547 disabled: !!disabled | 484 /** |
| 548 }; | 485 * @constructor |
| 549 extensionServer.sendRequest(request); | 486 */ |
| 550 } | 487 function Timeline() { |
| 551 }; | 488 } |
| 552 | 489 |
| 553 /** | 490 Timeline.prototype = { |
| 554 * @constructor | |
| 555 */ | |
| 556 function Timeline() | |
| 557 { | |
| 558 } | |
| 559 | |
| 560 Timeline.prototype = { | |
| 561 /** | 491 /** |
| 562 * @param {string} categoryName | 492 * @param {string} categoryName |
| 563 * @param {string} categoryTooltip | 493 * @param {string} categoryTooltip |
| 564 * @return {!TraceProvider} | 494 * @return {!TraceProvider} |
| 565 */ | 495 */ |
| 566 addTraceProvider: function(categoryName, categoryTooltip) | 496 addTraceProvider: function(categoryName, categoryTooltip) { |
| 567 { | 497 var id = 'extension-trace-provider-' + extensionServer.nextObjectId(); |
| 568 var id = "extension-trace-provider-" + extensionServer.nextObjectId(); | 498 extensionServer.sendRequest( |
| 569 extensionServer.sendRequest({ command: commands.AddTraceProvider, id: id
, categoryName: categoryName, categoryTooltip: categoryTooltip}); | 499 {command: commands.AddTraceProvider, id: id, categoryName: categoryNam
e, categoryTooltip: categoryTooltip}); |
| 570 return new TraceProvider(id); | 500 return new TraceProvider(id); |
| 571 } | 501 } |
| 572 }; | 502 }; |
| 573 | 503 |
| 574 /** | 504 /** |
| 575 * @constructor | 505 * @constructor |
| 576 * @param {string} id | 506 * @param {string} id |
| 577 */ | 507 */ |
| 578 function TraceProvider(id) | 508 function TraceProvider(id) { |
| 579 { | |
| 580 this.onRecordingStarted = new EventSink(events.RecordingStarted + id); | 509 this.onRecordingStarted = new EventSink(events.RecordingStarted + id); |
| 581 this.onRecordingStopped = new EventSink(events.RecordingStopped + id); | 510 this.onRecordingStopped = new EventSink(events.RecordingStopped + id); |
| 582 } | 511 } |
| 583 | 512 |
| 584 /** | 513 /** |
| 585 * @constructor | 514 * @constructor |
| 586 */ | 515 */ |
| 587 function Audits() | 516 function Audits() { |
| 588 { | 517 } |
| 589 } | 518 |
| 590 | 519 Audits.prototype = { |
| 591 Audits.prototype = { | |
| 592 /** | 520 /** |
| 593 * @return {!AuditCategory} | 521 * @return {!AuditCategory} |
| 594 */ | 522 */ |
| 595 addCategory: function(displayName, resultCount) | 523 addCategory: function(displayName, resultCount) { |
| 596 { | 524 var id = 'extension-audit-category-' + extensionServer.nextObjectId(); |
| 597 var id = "extension-audit-category-" + extensionServer.nextObjectId(); | 525 if (typeof resultCount !== 'undefined') |
| 598 if (typeof resultCount !== "undefined") | 526 console.warn( |
| 599 console.warn("Passing resultCount to audits.addCategory() is depreca
ted. Use AuditResult.updateProgress() instead."); | 527 'Passing resultCount to audits.addCategory() is deprecated. Use Audi
tResult.updateProgress() instead.'); |
| 600 extensionServer.sendRequest({ command: commands.AddAuditCategory, id: id
, displayName: displayName, resultCount: resultCount }); | 528 extensionServer.sendRequest( |
| 601 return new AuditCategory(id); | 529 {command: commands.AddAuditCategory, id: id, displayName: displayName,
resultCount: resultCount}); |
| 602 } | 530 return new AuditCategory(id); |
| 603 }; | 531 } |
| 604 | 532 }; |
| 605 /** | 533 |
| 606 * @constructor | 534 /** |
| 607 */ | 535 * @constructor |
| 608 function AuditCategoryImpl(id) | 536 */ |
| 609 { | 537 function AuditCategoryImpl(id) { |
| 610 /** | 538 /** |
| 611 * @this {EventSinkImpl} | 539 * @this {EventSinkImpl} |
| 612 */ | 540 */ |
| 613 function dispatchAuditEvent(request) | 541 function dispatchAuditEvent(request) { |
| 614 { | 542 var auditResult = new AuditResult(request.arguments[0]); |
| 615 var auditResult = new AuditResult(request.arguments[0]); | 543 try { |
| 616 try { | 544 this._fire(auditResult); |
| 617 this._fire(auditResult); | 545 } catch (e) { |
| 618 } catch (e) { | 546 console.error('Uncaught exception in extension audit event handler: ' +
e); |
| 619 console.error("Uncaught exception in extension audit event handler:
" + e); | 547 auditResult.done(); |
| 620 auditResult.done(); | 548 } |
| 621 } | |
| 622 } | 549 } |
| 623 this._id = id; | 550 this._id = id; |
| 624 this.onAuditStarted = new EventSink(events.AuditStarted + id, dispatchAuditE
vent); | 551 this.onAuditStarted = new EventSink(events.AuditStarted + id, dispatchAuditE
vent); |
| 625 } | 552 } |
| 626 | 553 |
| 627 /** | 554 /** |
| 628 * @constructor | 555 * @constructor |
| 629 */ | 556 */ |
| 630 function AuditResultImpl(id) | 557 function AuditResultImpl(id) { |
| 631 { | |
| 632 this._id = id; | 558 this._id = id; |
| 633 | 559 |
| 634 this.createURL = this._nodeFactory.bind(this, "url"); | 560 this.createURL = this._nodeFactory.bind(this, 'url'); |
| 635 this.createSnippet = this._nodeFactory.bind(this, "snippet"); | 561 this.createSnippet = this._nodeFactory.bind(this, 'snippet'); |
| 636 this.createText = this._nodeFactory.bind(this, "text"); | 562 this.createText = this._nodeFactory.bind(this, 'text'); |
| 637 this.createObject = this._nodeFactory.bind(this, "object"); | 563 this.createObject = this._nodeFactory.bind(this, 'object'); |
| 638 this.createNode = this._nodeFactory.bind(this, "node"); | 564 this.createNode = this._nodeFactory.bind(this, 'node'); |
| 639 } | 565 } |
| 640 | 566 |
| 641 AuditResultImpl.prototype = { | 567 AuditResultImpl.prototype = { |
| 642 addResult: function(displayName, description, severity, details) | 568 addResult: function(displayName, description, severity, details) { |
| 643 { | 569 // shorthand for specifying details directly in addResult(). |
| 644 // shorthand for specifying details directly in addResult(). | 570 if (details && !(details instanceof AuditResultNode)) |
| 645 if (details && !(details instanceof AuditResultNode)) | 571 details = new AuditResultNode(Array.isArray(details) ? details : [detail
s]); |
| 646 details = new AuditResultNode(Array.isArray(details) ? details : [de
tails]); | 572 |
| 647 | 573 var request = { |
| 648 var request = { | 574 command: commands.AddAuditResult, |
| 649 command: commands.AddAuditResult, | 575 resultId: this._id, |
| 650 resultId: this._id, | 576 displayName: displayName, |
| 651 displayName: displayName, | 577 description: description, |
| 652 description: description, | 578 severity: severity, |
| 653 severity: severity, | 579 details: details |
| 654 details: details | 580 }; |
| 655 }; | 581 extensionServer.sendRequest(request); |
| 656 extensionServer.sendRequest(request); | |
| 657 }, | 582 }, |
| 658 | 583 |
| 659 /** | 584 /** |
| 660 * @return {!Object} | 585 * @return {!Object} |
| 661 */ | 586 */ |
| 662 createResult: function() | 587 createResult: function() { |
| 663 { | 588 return new AuditResultNode(Array.prototype.slice.call(arguments)); |
| 664 return new AuditResultNode(Array.prototype.slice.call(arguments)); | 589 }, |
| 665 }, | 590 |
| 666 | 591 updateProgress: function(worked, totalWork) { |
| 667 updateProgress: function(worked, totalWork) | 592 extensionServer.sendRequest( |
| 668 { | 593 {command: commands.UpdateAuditProgress, resultId: this._id, progress:
worked / totalWork}); |
| 669 extensionServer.sendRequest({ command: commands.UpdateAuditProgress, res
ultId: this._id, progress: worked / totalWork }); | 594 }, |
| 670 }, | 595 |
| 671 | 596 done: function() { |
| 672 done: function() | 597 extensionServer.sendRequest({command: commands.StopAuditCategoryRun, resul
tId: this._id}); |
| 673 { | |
| 674 extensionServer.sendRequest({ command: commands.StopAuditCategoryRun, re
sultId: this._id }); | |
| 675 }, | 598 }, |
| 676 | 599 |
| 677 /** | 600 /** |
| 678 * @type {!Object.<string, string>} | 601 * @type {!Object.<string, string>} |
| 679 */ | 602 */ |
| 680 get Severity() | 603 get Severity() { |
| 681 { | 604 return apiPrivate.audits.Severity; |
| 682 return apiPrivate.audits.Severity; | |
| 683 }, | 605 }, |
| 684 | 606 |
| 685 /** | 607 /** |
| 686 * @return {!{type: string, arguments: !Array.<string|number>}} | 608 * @return {!{type: string, arguments: !Array.<string|number>}} |
| 687 */ | 609 */ |
| 688 createResourceLink: function(url, lineNumber) | 610 createResourceLink: function(url, lineNumber) { |
| 689 { | 611 return {type: 'resourceLink', arguments: [url, lineNumber && lineNumber -
1]}; |
| 690 return { | |
| 691 type: "resourceLink", | |
| 692 arguments: [url, lineNumber && lineNumber - 1] | |
| 693 }; | |
| 694 }, | 612 }, |
| 695 | 613 |
| 696 /** | 614 /** |
| 697 * @return {!{type: string, arguments: !Array.<string|number>}} | 615 * @return {!{type: string, arguments: !Array.<string|number>}} |
| 698 */ | 616 */ |
| 699 _nodeFactory: function(type) | 617 _nodeFactory: function(type) { |
| 700 { | 618 return {type: type, arguments: Array.prototype.slice.call(arguments, 1)}; |
| 701 return { | 619 } |
| 702 type: type, | 620 }; |
| 703 arguments: Array.prototype.slice.call(arguments, 1) | 621 |
| 704 }; | 622 /** |
| 705 } | 623 * @constructor |
| 706 }; | 624 */ |
| 707 | 625 function AuditResultNode(contents) { |
| 708 /** | |
| 709 * @constructor | |
| 710 */ | |
| 711 function AuditResultNode(contents) | |
| 712 { | |
| 713 this.contents = contents; | 626 this.contents = contents; |
| 714 this.children = []; | 627 this.children = []; |
| 715 this.expanded = false; | 628 this.expanded = false; |
| 716 } | 629 } |
| 717 | 630 |
| 718 AuditResultNode.prototype = { | 631 AuditResultNode.prototype = { |
| 719 /** | 632 /** |
| 720 * @return {!Object} | 633 * @return {!Object} |
| 721 */ | 634 */ |
| 722 addChild: function() | 635 addChild: function() { |
| 723 { | 636 var node = new AuditResultNode(Array.prototype.slice.call(arguments)); |
| 724 var node = new AuditResultNode(Array.prototype.slice.call(arguments)); | 637 this.children.push(node); |
| 725 this.children.push(node); | 638 return node; |
| 726 return node; | 639 } |
| 727 } | 640 }; |
| 728 }; | 641 |
| 729 | 642 /** |
| 730 /** | 643 * @constructor |
| 731 * @constructor | 644 */ |
| 732 */ | 645 function InspectedWindow() { |
| 733 function InspectedWindow() | |
| 734 { | |
| 735 /** | 646 /** |
| 736 * @this {EventSinkImpl} | 647 * @this {EventSinkImpl} |
| 737 */ | 648 */ |
| 738 function dispatchResourceEvent(message) | 649 function dispatchResourceEvent(message) { |
| 739 { | 650 this._fire(new Resource(message.arguments[0])); |
| 740 this._fire(new Resource(message.arguments[0])); | |
| 741 } | 651 } |
| 742 | 652 |
| 743 /** | 653 /** |
| 744 * @this {EventSinkImpl} | 654 * @this {EventSinkImpl} |
| 745 */ | 655 */ |
| 746 function dispatchResourceContentEvent(message) | 656 function dispatchResourceContentEvent(message) { |
| 747 { | 657 this._fire(new Resource(message.arguments[0]), message.arguments[1]); |
| 748 this._fire(new Resource(message.arguments[0]), message.arguments[1]); | |
| 749 } | 658 } |
| 750 | 659 |
| 751 this.onResourceAdded = new EventSink(events.ResourceAdded, dispatchResourceE
vent); | 660 this.onResourceAdded = new EventSink(events.ResourceAdded, dispatchResourceE
vent); |
| 752 this.onResourceContentCommitted = new EventSink(events.ResourceContentCommit
ted, dispatchResourceContentEvent); | 661 this.onResourceContentCommitted = new EventSink(events.ResourceContentCommit
ted, dispatchResourceContentEvent); |
| 753 } | 662 } |
| 754 | 663 |
| 755 InspectedWindow.prototype = { | 664 InspectedWindow.prototype = { |
| 756 reload: function(optionsOrUserAgent) | 665 reload: function(optionsOrUserAgent) { |
| 757 { | 666 var options = null; |
| 758 var options = null; | 667 if (typeof optionsOrUserAgent === 'object') { |
| 759 if (typeof optionsOrUserAgent === "object") { | 668 options = optionsOrUserAgent; |
| 760 options = optionsOrUserAgent; | 669 } else if (typeof optionsOrUserAgent === 'string') { |
| 761 } else if (typeof optionsOrUserAgent === "string") { | 670 options = {userAgent: optionsOrUserAgent}; |
| 762 options = { userAgent: optionsOrUserAgent }; | 671 console.warn( |
| 763 console.warn("Passing userAgent as string parameter to inspectedWind
ow.reload() is deprecated. " + | 672 'Passing userAgent as string parameter to inspectedWindow.reload() i
s deprecated. ' + |
| 764 "Use inspectedWindow.reload({ userAgent: value}) instea
d."); | 673 'Use inspectedWindow.reload({ userAgent: value}) instead.'); |
| 765 } | 674 } |
| 766 extensionServer.sendRequest({ command: commands.Reload, options: options
}); | 675 extensionServer.sendRequest({command: commands.Reload, options: options}); |
| 767 }, | 676 }, |
| 768 | 677 |
| 769 /** | 678 /** |
| 770 * @return {?Object} | 679 * @return {?Object} |
| 771 */ | 680 */ |
| 772 eval: function(expression, evaluateOptions) | 681 eval: function(expression, evaluateOptions) { |
| 773 { | 682 var callback = extractCallbackArgument(arguments); |
| 774 var callback = extractCallbackArgument(arguments); | 683 function callbackWrapper(result) { |
| 775 function callbackWrapper(result) | 684 if (result.isError || result.isException) |
| 776 { | 685 callback(undefined, result); |
| 777 if (result.isError || result.isException) | 686 else |
| 778 callback(undefined, result); | 687 callback(result.value); |
| 779 else | 688 } |
| 780 callback(result.value); | 689 var request = {command: commands.EvaluateOnInspectedPage, expression: expr
ession}; |
| 781 } | 690 if (typeof evaluateOptions === 'object') |
| 782 var request = { | 691 request.evaluateOptions = evaluateOptions; |
| 783 command: commands.EvaluateOnInspectedPage, | 692 extensionServer.sendRequest(request, callback && callbackWrapper); |
| 784 expression: expression | 693 return null; |
| 785 }; | 694 }, |
| 786 if (typeof evaluateOptions === "object") | 695 |
| 787 request.evaluateOptions = evaluateOptions; | 696 getResources: function(callback) { |
| 788 extensionServer.sendRequest(request, callback && callbackWrapper); | 697 function wrapResource(resourceData) { |
| 789 return null; | 698 return new Resource(resourceData); |
| 790 }, | 699 } |
| 791 | 700 function callbackWrapper(resources) { |
| 792 getResources: function(callback) | 701 callback(resources.map(wrapResource)); |
| 793 { | 702 } |
| 794 function wrapResource(resourceData) | 703 extensionServer.sendRequest({command: commands.GetPageResources}, callback
&& callbackWrapper); |
| 795 { | 704 } |
| 796 return new Resource(resourceData); | 705 }; |
| 797 } | 706 |
| 798 function callbackWrapper(resources) | 707 /** |
| 799 { | 708 * @constructor |
| 800 callback(resources.map(wrapResource)); | 709 */ |
| 801 } | 710 function ResourceImpl(resourceData) { |
| 802 extensionServer.sendRequest({ command: commands.GetPageResources }, call
back && callbackWrapper); | |
| 803 } | |
| 804 }; | |
| 805 | |
| 806 /** | |
| 807 * @constructor | |
| 808 */ | |
| 809 function ResourceImpl(resourceData) | |
| 810 { | |
| 811 this._url = resourceData.url; | 711 this._url = resourceData.url; |
| 812 this._type = resourceData.type; | 712 this._type = resourceData.type; |
| 813 } | 713 } |
| 814 | 714 |
| 815 ResourceImpl.prototype = { | 715 ResourceImpl.prototype = { |
| 816 get url() | 716 get url() { |
| 817 { | 717 return this._url; |
| 818 return this._url; | 718 }, |
| 819 }, | 719 |
| 820 | 720 get type() { |
| 821 get type() | 721 return this._type; |
| 822 { | 722 }, |
| 823 return this._type; | 723 |
| 824 }, | 724 getContent: function(callback) { |
| 825 | 725 function callbackWrapper(response) { |
| 826 getContent: function(callback) | 726 callback(response.content, response.encoding); |
| 827 { | 727 } |
| 828 function callbackWrapper(response) | 728 |
| 829 { | 729 extensionServer.sendRequest({command: commands.GetResourceContent, url: th
is._url}, callback && callbackWrapper); |
| 830 callback(response.content, response.encoding); | 730 }, |
| 831 } | 731 |
| 832 | 732 setContent: function(content, commit, callback) { |
| 833 extensionServer.sendRequest({ command: commands.GetResourceContent, url:
this._url }, callback && callbackWrapper); | 733 extensionServer.sendRequest( |
| 834 }, | 734 {command: commands.SetResourceContent, url: this._url, content: conten
t, commit: commit}, callback); |
| 835 | 735 } |
| 836 setContent: function(content, commit, callback) | 736 }; |
| 837 { | 737 |
| 838 extensionServer.sendRequest({ command: commands.SetResourceContent, url:
this._url, content: content, commit: commit }, callback); | 738 function getTabId() { |
| 839 } | |
| 840 }; | |
| 841 | |
| 842 function getTabId() | |
| 843 { | |
| 844 return inspectedTabId; | 739 return inspectedTabId; |
| 845 } | 740 } |
| 846 | 741 |
| 847 var keyboardEventRequestQueue = []; | 742 var keyboardEventRequestQueue = []; |
| 848 var forwardTimer = null; | 743 var forwardTimer = null; |
| 849 | 744 |
| 850 function forwardKeyboardEvent(event) | 745 function forwardKeyboardEvent(event) { |
| 851 { | |
| 852 // We only care about global hotkeys, not about random text | 746 // We only care about global hotkeys, not about random text |
| 853 if (!event.ctrlKey && !event.altKey && !event.metaKey && !/^F\d+$/.test(even
t.key) && event.key !== "Escape") | 747 if (!event.ctrlKey && !event.altKey && !event.metaKey && !/^F\d+$/.test(even
t.key) && event.key !== 'Escape') |
| 854 return; | 748 return; |
| 855 var requestPayload = { | 749 var requestPayload = { |
| 856 eventType: event.type, | 750 eventType: event.type, |
| 857 ctrlKey: event.ctrlKey, | 751 ctrlKey: event.ctrlKey, |
| 858 altKey: event.altKey, | 752 altKey: event.altKey, |
| 859 metaKey: event.metaKey, | 753 metaKey: event.metaKey, |
| 860 keyIdentifier: event.keyIdentifier, | 754 keyIdentifier: event.keyIdentifier, |
| 861 key: event.key, | 755 key: event.key, |
| 862 code: event.code, | 756 code: event.code, |
| 863 location: event.location, | 757 location: event.location, |
| 864 keyCode: event.keyCode | 758 keyCode: event.keyCode |
| 865 }; | 759 }; |
| 866 keyboardEventRequestQueue.push(requestPayload); | 760 keyboardEventRequestQueue.push(requestPayload); |
| 867 if (!forwardTimer) | 761 if (!forwardTimer) |
| 868 forwardTimer = setTimeout(forwardEventQueue, 0); | 762 forwardTimer = setTimeout(forwardEventQueue, 0); |
| 869 } | 763 } |
| 870 | 764 |
| 871 function forwardEventQueue() | 765 function forwardEventQueue() { |
| 872 { | |
| 873 forwardTimer = null; | 766 forwardTimer = null; |
| 874 var request = { | 767 var request = {command: commands.ForwardKeyboardEvent, entries: keyboardEven
tRequestQueue}; |
| 875 command: commands.ForwardKeyboardEvent, | |
| 876 entries: keyboardEventRequestQueue | |
| 877 }; | |
| 878 extensionServer.sendRequest(request); | 768 extensionServer.sendRequest(request); |
| 879 keyboardEventRequestQueue = []; | 769 keyboardEventRequestQueue = []; |
| 880 } | 770 } |
| 881 | 771 |
| 882 document.addEventListener("keydown", forwardKeyboardEvent, false); | 772 document.addEventListener('keydown', forwardKeyboardEvent, false); |
| 883 document.addEventListener("keypress", forwardKeyboardEvent, false); | 773 document.addEventListener('keypress', forwardKeyboardEvent, false); |
| 884 | 774 |
| 885 /** | 775 /** |
| 886 * @constructor | 776 * @constructor |
| 887 */ | 777 */ |
| 888 function ExtensionServerClient() | 778 function ExtensionServerClient() { |
| 889 { | |
| 890 this._callbacks = {}; | 779 this._callbacks = {}; |
| 891 this._handlers = {}; | 780 this._handlers = {}; |
| 892 this._lastRequestId = 0; | 781 this._lastRequestId = 0; |
| 893 this._lastObjectId = 0; | 782 this._lastObjectId = 0; |
| 894 | 783 |
| 895 this.registerHandler("callback", this._onCallback.bind(this)); | 784 this.registerHandler('callback', this._onCallback.bind(this)); |
| 896 | 785 |
| 897 var channel = new MessageChannel(); | 786 var channel = new MessageChannel(); |
| 898 this._port = channel.port1; | 787 this._port = channel.port1; |
| 899 this._port.addEventListener("message", this._onMessage.bind(this), false); | 788 this._port.addEventListener('message', this._onMessage.bind(this), false); |
| 900 this._port.start(); | 789 this._port.start(); |
| 901 | 790 |
| 902 window.parent.postMessage("registerExtension", "*", [ channel.port2 ]); | 791 window.parent.postMessage('registerExtension', '*', [channel.port2]); |
| 903 } | 792 } |
| 904 | 793 |
| 905 ExtensionServerClient.prototype = { | 794 ExtensionServerClient.prototype = { |
| 906 /** | 795 /** |
| 907 * @param {!Object} message | 796 * @param {!Object} message |
| 908 * @param {function()=} callback | 797 * @param {function()=} callback |
| 909 */ | 798 */ |
| 910 sendRequest: function(message, callback) | 799 sendRequest: function(message, callback) { |
| 911 { | 800 if (typeof callback === 'function') |
| 912 if (typeof callback === "function") | 801 message.requestId = this._registerCallback(callback); |
| 913 message.requestId = this._registerCallback(callback); | 802 this._port.postMessage(message); |
| 914 this._port.postMessage(message); | |
| 915 }, | 803 }, |
| 916 | 804 |
| 917 /** | 805 /** |
| 918 * @return {boolean} | 806 * @return {boolean} |
| 919 */ | 807 */ |
| 920 hasHandler: function(command) | 808 hasHandler: function(command) { |
| 921 { | 809 return !!this._handlers[command]; |
| 922 return !!this._handlers[command]; | 810 }, |
| 923 }, | 811 |
| 924 | 812 registerHandler: function(command, handler) { |
| 925 registerHandler: function(command, handler) | 813 this._handlers[command] = handler; |
| 926 { | 814 }, |
| 927 this._handlers[command] = handler; | 815 |
| 928 }, | 816 unregisterHandler: function(command) { |
| 929 | 817 delete this._handlers[command]; |
| 930 unregisterHandler: function(command) | |
| 931 { | |
| 932 delete this._handlers[command]; | |
| 933 }, | 818 }, |
| 934 | 819 |
| 935 /** | 820 /** |
| 936 * @return {string} | 821 * @return {string} |
| 937 */ | 822 */ |
| 938 nextObjectId: function() | 823 nextObjectId: function() { |
| 939 { | 824 return injectedScriptId.toString() + '_' + ++this._lastObjectId; |
| 940 return injectedScriptId.toString() + "_" + ++this._lastObjectId; | 825 }, |
| 941 }, | 826 |
| 942 | 827 _registerCallback: function(callback) { |
| 943 _registerCallback: function(callback) | 828 var id = ++this._lastRequestId; |
| 944 { | 829 this._callbacks[id] = callback; |
| 945 var id = ++this._lastRequestId; | 830 return id; |
| 946 this._callbacks[id] = callback; | 831 }, |
| 947 return id; | 832 |
| 948 }, | 833 _onCallback: function(request) { |
| 949 | 834 if (request.requestId in this._callbacks) { |
| 950 _onCallback: function(request) | 835 var callback = this._callbacks[request.requestId]; |
| 951 { | 836 delete this._callbacks[request.requestId]; |
| 952 if (request.requestId in this._callbacks) { | 837 callback(request.result); |
| 953 var callback = this._callbacks[request.requestId]; | 838 } |
| 954 delete this._callbacks[request.requestId]; | 839 }, |
| 955 callback(request.result); | 840 |
| 956 } | 841 _onMessage: function(event) { |
| 957 }, | 842 var request = event.data; |
| 958 | 843 var handler = this._handlers[request.command]; |
| 959 _onMessage: function(event) | 844 if (handler) |
| 960 { | 845 handler.call(this, request); |
| 961 var request = event.data; | 846 } |
| 962 var handler = this._handlers[request.command]; | 847 }; |
| 963 if (handler) | 848 |
| 964 handler.call(this, request); | 849 function populateInterfaceClass(interfaze, implementation) { |
| 965 } | |
| 966 }; | |
| 967 | |
| 968 function populateInterfaceClass(interfaze, implementation) | |
| 969 { | |
| 970 for (var member in implementation) { | 850 for (var member in implementation) { |
| 971 if (member.charAt(0) === "_") | 851 if (member.charAt(0) === '_') |
| 972 continue; | 852 continue; |
| 973 var descriptor = null; | 853 var descriptor = null; |
| 974 // Traverse prototype chain until we find the owner. | 854 // Traverse prototype chain until we find the owner. |
| 975 for (var owner = implementation; owner && !descriptor; owner = owner.__p
roto__) | 855 for (var owner = implementation; owner && !descriptor; owner = owner.__pro
to__) |
| 976 descriptor = Object.getOwnPropertyDescriptor(owner, member); | 856 descriptor = Object.getOwnPropertyDescriptor(owner, member); |
| 977 if (!descriptor) | 857 if (!descriptor) |
| 978 continue; | 858 continue; |
| 979 if (typeof descriptor.value === "function") | 859 if (typeof descriptor.value === 'function') |
| 980 interfaze[member] = descriptor.value.bind(implementation); | 860 interfaze[member] = descriptor.value.bind(implementation); |
| 981 else if (typeof descriptor.get === "function") | 861 else if (typeof descriptor.get === 'function') |
| 982 interfaze.__defineGetter__(member, descriptor.get.bind(implementatio
n)); | 862 interfaze.__defineGetter__(member, descriptor.get.bind(implementation)); |
| 983 else | 863 else |
| 984 Object.defineProperty(interfaze, member, descriptor); | 864 Object.defineProperty(interfaze, member, descriptor); |
| 985 } | 865 } |
| 986 } | 866 } |
| 987 | 867 |
| 988 var extensionServer = new ExtensionServerClient(); | 868 var extensionServer = new ExtensionServerClient(); |
| 989 var coreAPI = new InspectorExtensionAPI(); | 869 var coreAPI = new InspectorExtensionAPI(); |
| 990 | 870 |
| 991 var chrome = window.chrome || {}; | 871 var chrome = window.chrome || {}; |
| 992 // Override chrome.devtools as a workaround for a error-throwing getter being ex
posed | 872 // Override chrome.devtools as a workaround for a error-throwing getter being
exposed |
| 993 // in extension pages loaded into a non-extension process (only happens for remo
te client | 873 // in extension pages loaded into a non-extension process (only happens for re
mote client |
| 994 // extensions) | 874 // extensions) |
| 995 var devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, "devtools"); | 875 var devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools'); |
| 996 if (!devtools_descriptor || devtools_descriptor.get) | 876 if (!devtools_descriptor || devtools_descriptor.get) |
| 997 Object.defineProperty(chrome, "devtools", { value: {}, enumerable: true }); | 877 Object.defineProperty(chrome, 'devtools', {value: {}, enumerable: true}); |
| 998 | 878 |
| 999 // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspec
tedWindow. | 879 // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.insp
ectedWindow. |
| 1000 chrome.devtools.inspectedWindow = {}; | 880 chrome.devtools.inspectedWindow = {}; |
| 1001 chrome.devtools.inspectedWindow.__defineGetter__("tabId", getTabId); | 881 chrome.devtools.inspectedWindow.__defineGetter__('tabId', getTabId); |
| 1002 chrome.devtools.inspectedWindow.__proto__ = coreAPI.inspectedWindow; | 882 chrome.devtools.inspectedWindow.__proto__ = coreAPI.inspectedWindow; |
| 1003 chrome.devtools.network = coreAPI.network; | 883 chrome.devtools.network = coreAPI.network; |
| 1004 chrome.devtools.panels = coreAPI.panels; | 884 chrome.devtools.panels = coreAPI.panels; |
| 1005 chrome.devtools.panels.themeName = themeName; | 885 chrome.devtools.panels.themeName = themeName; |
| 1006 | 886 |
| 1007 // default to expose experimental APIs for now. | 887 // default to expose experimental APIs for now. |
| 1008 if (extensionInfo.exposeExperimentalAPIs !== false) { | 888 if (extensionInfo.exposeExperimentalAPIs !== false) { |
| 1009 chrome.experimental = chrome.experimental || {}; | 889 chrome.experimental = chrome.experimental || {}; |
| 1010 chrome.experimental.devtools = chrome.experimental.devtools || {}; | 890 chrome.experimental.devtools = chrome.experimental.devtools || {}; |
| 1011 | 891 |
| 1012 var properties = Object.getOwnPropertyNames(coreAPI); | 892 var properties = Object.getOwnPropertyNames(coreAPI); |
| 1013 for (var i = 0; i < properties.length; ++i) { | 893 for (var i = 0; i < properties.length; ++i) { |
| 1014 var descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i])
; | 894 var descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]); |
| 1015 if (descriptor) | 895 if (descriptor) |
| 1016 Object.defineProperty(chrome.experimental.devtools, properties[i], d
escriptor); | 896 Object.defineProperty(chrome.experimental.devtools, properties[i], descr
iptor); |
| 1017 } | 897 } |
| 1018 chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWind
ow; | 898 chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWind
ow; |
| 899 } |
| 900 |
| 901 if (extensionInfo.exposeWebInspectorNamespace) |
| 902 window.webInspector = coreAPI; |
| 903 testHook(extensionServer, coreAPI); |
| 1019 } | 904 } |
| 1020 | 905 |
| 1021 if (extensionInfo.exposeWebInspectorNamespace) | |
| 1022 window.webInspector = coreAPI; | |
| 1023 testHook(extensionServer, coreAPI); | |
| 1024 } | |
| 1025 | |
| 1026 /** | 906 /** |
| 1027 * @param {!ExtensionDescriptor} extensionInfo | 907 * @param {!ExtensionDescriptor} extensionInfo |
| 1028 * @param {string} inspectedTabId | 908 * @param {string} inspectedTabId |
| 1029 * @param {string} themeName | 909 * @param {string} themeName |
| 1030 * @param {function(!Object, !Object)|undefined} testHook | 910 * @param {function(!Object, !Object)|undefined} testHook |
| 1031 * @return {string} | 911 * @return {string} |
| 1032 */ | 912 */ |
| 1033 function buildExtensionAPIInjectedScript(extensionInfo, inspectedTabId, themeNam
e, testHook) | 913 function buildExtensionAPIInjectedScript(extensionInfo, inspectedTabId, themeNam
e, testHook) { |
| 1034 { | 914 var argumentsJSON = [extensionInfo, inspectedTabId || null, themeName].map(_ =
> JSON.stringify(_)).join(','); |
| 1035 var argumentsJSON = [extensionInfo, inspectedTabId || null, themeName].map(_
=> JSON.stringify(_)).join(","); | 915 if (!testHook) |
| 1036 if (!testHook) | 916 testHook = () => {}; |
| 1037 testHook = () => {}; | 917 return '(function(injectedScriptId){ ' + defineCommonExtensionSymbols.toString
() + ';' + |
| 1038 return "(function(injectedScriptId){ " + | 918 '(' + injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testH
ook + ', injectedScriptId);' + |
| 1039 defineCommonExtensionSymbols.toString() + ";" + | 919 '})'; |
| 1040 "(" + injectedExtensionAPI.toString() + ")(" + argumentsJSON + "," + tes
tHook + ", injectedScriptId);" + | |
| 1041 "})"; | |
| 1042 } | 920 } |
| OLD | NEW |