Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(265)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/extensions/ExtensionServer.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved. 2 * Copyright (C) 2011 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
11 * copyright notice, this list of conditions and the following disclaimer 11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the 12 * in the documentation and/or other materials provided with the
13 * distribution. 13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its 14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from 15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission. 16 * this software without specific prior written permission.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
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
31 /** 30 /**
32 * @constructor 31 * @unrestricted
33 * @extends {WebInspector.Object}
34 * @suppressGlobalPropertiesCheck
35 */ 32 */
36 WebInspector.ExtensionServer = function() 33 WebInspector.ExtensionServer = class extends WebInspector.Object {
37 { 34 /**
35 * @suppressGlobalPropertiesCheck
36 */
37 constructor() {
38 super();
38 this._clientObjects = {}; 39 this._clientObjects = {};
39 this._handlers = {}; 40 this._handlers = {};
40 this._subscribers = {}; 41 this._subscribers = {};
41 this._subscriptionStartHandlers = {}; 42 this._subscriptionStartHandlers = {};
42 this._subscriptionStopHandlers = {}; 43 this._subscriptionStopHandlers = {};
43 this._extraHeaders = {}; 44 this._extraHeaders = {};
44 this._requests = {}; 45 this._requests = {};
45 this._lastRequestId = 0; 46 this._lastRequestId = 0;
46 this._registeredExtensions = {}; 47 this._registeredExtensions = {};
47 this._status = new WebInspector.ExtensionStatus(); 48 this._status = new WebInspector.ExtensionStatus();
(...skipping 26 matching lines...) Expand all
74 this._registerHandler(commands.SetSidebarHeight, this._onSetSidebarHeight.bi nd(this)); 75 this._registerHandler(commands.SetSidebarHeight, this._onSetSidebarHeight.bi nd(this));
75 this._registerHandler(commands.SetSidebarContent, this._onSetSidebarContent. bind(this)); 76 this._registerHandler(commands.SetSidebarContent, this._onSetSidebarContent. bind(this));
76 this._registerHandler(commands.SetSidebarPage, this._onSetSidebarPage.bind(t his)); 77 this._registerHandler(commands.SetSidebarPage, this._onSetSidebarPage.bind(t his));
77 this._registerHandler(commands.ShowPanel, this._onShowPanel.bind(this)); 78 this._registerHandler(commands.ShowPanel, this._onShowPanel.bind(this));
78 this._registerHandler(commands.StopAuditCategoryRun, this._onStopAuditCatego ryRun.bind(this)); 79 this._registerHandler(commands.StopAuditCategoryRun, this._onStopAuditCatego ryRun.bind(this));
79 this._registerHandler(commands.Subscribe, this._onSubscribe.bind(this)); 80 this._registerHandler(commands.Subscribe, this._onSubscribe.bind(this));
80 this._registerHandler(commands.OpenResource, this._onOpenResource.bind(this) ); 81 this._registerHandler(commands.OpenResource, this._onOpenResource.bind(this) );
81 this._registerHandler(commands.Unsubscribe, this._onUnsubscribe.bind(this)); 82 this._registerHandler(commands.Unsubscribe, this._onUnsubscribe.bind(this));
82 this._registerHandler(commands.UpdateButton, this._onUpdateButton.bind(this) ); 83 this._registerHandler(commands.UpdateButton, this._onUpdateButton.bind(this) );
83 this._registerHandler(commands.UpdateAuditProgress, this._onUpdateAuditProgr ess.bind(this)); 84 this._registerHandler(commands.UpdateAuditProgress, this._onUpdateAuditProgr ess.bind(this));
84 window.addEventListener("message", this._onWindowMessage.bind(this), false); // Only for main window. 85 window.addEventListener('message', this._onWindowMessage.bind(this), false); // Only for main window.
85 86
86 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Event s.AddExtensions, this._addExtensions, this); 87 InspectorFrontendHost.events.addEventListener(
87 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Event s.SetInspectedTabId, this._setInspectedTabId, this); 88 InspectorFrontendHostAPI.Events.AddExtensions, this._addExtensions, this );
89 InspectorFrontendHost.events.addEventListener(
90 InspectorFrontendHostAPI.Events.SetInspectedTabId, this._setInspectedTab Id, this);
88 91
89 this._initExtensions(); 92 this._initExtensions();
93 }
94
95 initializeExtensions() {
96 this._initializeCommandIssued = true;
97 if (this._pendingExtensionInfos) {
98 this._pendingExtensionInfos.forEach(this._addExtension, this);
99 delete this._pendingExtensionInfos;
100 }
101 }
102
103 /**
104 * @return {boolean}
105 */
106 hasExtensions() {
107 return !!Object.keys(this._registeredExtensions).length;
108 }
109
110 /**
111 * @param {string} panelId
112 * @param {string} action
113 * @param {string=} searchString
114 */
115 notifySearchAction(panelId, action, searchString) {
116 this._postNotification(WebInspector.extensionAPI.Events.PanelSearch + panelI d, action, searchString);
117 }
118
119 /**
120 * @param {string} identifier
121 * @param {number=} frameIndex
122 */
123 notifyViewShown(identifier, frameIndex) {
124 this._postNotification(WebInspector.extensionAPI.Events.ViewShown + identifi er, frameIndex);
125 }
126
127 /**
128 * @param {string} identifier
129 */
130 notifyViewHidden(identifier) {
131 this._postNotification(WebInspector.extensionAPI.Events.ViewHidden + identif ier);
132 }
133
134 /**
135 * @param {string} identifier
136 */
137 notifyButtonClicked(identifier) {
138 this._postNotification(WebInspector.extensionAPI.Events.ButtonClicked + iden tifier);
139 }
140
141 _inspectedURLChanged(event) {
142 if (event.data !== WebInspector.targetManager.mainTarget())
143 return;
144 this._requests = {};
145 var url = event.data.inspectedURL();
146 this._postNotification(WebInspector.extensionAPI.Events.InspectedURLChanged, url);
147 }
148
149 /**
150 * @param {string} categoryId
151 * @param {!WebInspector.ExtensionAuditCategoryResults} auditResults
152 */
153 startAuditRun(categoryId, auditResults) {
154 this._clientObjects[auditResults.id()] = auditResults;
155 this._postNotification('audit-started-' + categoryId, auditResults.id());
156 }
157
158 /**
159 * @param {!WebInspector.ExtensionAuditCategoryResults} auditResults
160 */
161 stopAuditRun(auditResults) {
162 delete this._clientObjects[auditResults.id()];
163 }
164
165 /**
166 * @param {string} traceProviderId
167 */
168 startTraceRecording(traceProviderId) {
169 this._postNotification('trace-recording-started-' + traceProviderId);
170 }
171
172 /**
173 * @param {string} traceProviderId
174 */
175 stopTraceRecording(traceProviderId) {
176 this._postNotification('trace-recording-stopped-' + traceProviderId);
177 }
178
179 /**
180 * @param {string} type
181 * @return {boolean}
182 */
183 hasSubscribers(type) {
184 return !!this._subscribers[type];
185 }
186
187 /**
188 * @param {string} type
189 * @param {...*} vararg
190 */
191 _postNotification(type, vararg) {
192 var subscribers = this._subscribers[type];
193 if (!subscribers)
194 return;
195 var message = {command: 'notify-' + type, arguments: Array.prototype.slice.c all(arguments, 1)};
196 for (var i = 0; i < subscribers.length; ++i)
197 subscribers[i].postMessage(message);
198 }
199
200 _onSubscribe(message, port) {
201 var subscribers = this._subscribers[message.type];
202 if (subscribers)
203 subscribers.push(port);
204 else {
205 this._subscribers[message.type] = [port];
206 if (this._subscriptionStartHandlers[message.type])
207 this._subscriptionStartHandlers[message.type]();
208 }
209 }
210
211 _onUnsubscribe(message, port) {
212 var subscribers = this._subscribers[message.type];
213 if (!subscribers)
214 return;
215 subscribers.remove(port);
216 if (!subscribers.length) {
217 delete this._subscribers[message.type];
218 if (this._subscriptionStopHandlers[message.type])
219 this._subscriptionStopHandlers[message.type]();
220 }
221 }
222
223 _onAddRequestHeaders(message) {
224 var id = message.extensionId;
225 if (typeof id !== 'string')
226 return this._status.E_BADARGTYPE('extensionId', typeof id, 'string');
227 var extensionHeaders = this._extraHeaders[id];
228 if (!extensionHeaders) {
229 extensionHeaders = {};
230 this._extraHeaders[id] = extensionHeaders;
231 }
232 for (var name in message.headers)
233 extensionHeaders[name] = message.headers[name];
234 var allHeaders = /** @type {!NetworkAgent.Headers} */ ({});
235 for (var extension in this._extraHeaders) {
236 var headers = this._extraHeaders[extension];
237 for (name in headers) {
238 if (typeof headers[name] === 'string')
239 allHeaders[name] = headers[name];
240 }
241 }
242
243 WebInspector.multitargetNetworkManager.setExtraHTTPHeaders(allHeaders);
244 }
245
246 /**
247 * @param {*} message
248 * @suppressGlobalPropertiesCheck
249 */
250 _onApplyStyleSheet(message) {
251 if (!Runtime.experiments.isEnabled('applyCustomStylesheet'))
252 return;
253 var styleSheet = createElement('style');
254 styleSheet.textContent = message.styleSheet;
255 document.head.appendChild(styleSheet);
256 }
257
258 _onCreatePanel(message, port) {
259 var id = message.id;
260 // The ids are generated on the client API side and must be unique, so the c heck below
261 // shouldn't be hit unless someone is bypassing the API.
262 if (id in this._clientObjects || WebInspector.inspectorView.hasPanel(id))
263 return this._status.E_EXISTS(id);
264
265 var page = this._expandResourcePath(port._extensionOrigin, message.page);
266 var persistentId = port._extensionOrigin + message.title;
267 persistentId = persistentId.replace(/\s/g, '');
268 var panelView = new WebInspector.ExtensionServerPanelView(
269 persistentId, message.title, new WebInspector.ExtensionPanel(this, persi stentId, id, page));
270 this._clientObjects[id] = panelView;
271 WebInspector.inspectorView.addPanel(panelView);
272 return this._status.OK();
273 }
274
275 _onShowPanel(message) {
276 var panelViewId = message.id;
277 var panelView = this._clientObjects[message.id];
278 if (panelView && panelView instanceof WebInspector.ExtensionServerPanelView)
279 panelViewId = panelView.viewId();
280 WebInspector.inspectorView.showPanel(panelViewId);
281 }
282
283 _onCreateToolbarButton(message, port) {
284 var panelView = this._clientObjects[message.panel];
285 if (!panelView || !(panelView instanceof WebInspector.ExtensionServerPanelVi ew))
286 return this._status.E_NOTFOUND(message.panel);
287 var button = new WebInspector.ExtensionButton(
288 this, message.id, this._expandResourcePath(port._extensionOrigin, messag e.icon), message.tooltip,
289 message.disabled);
290 this._clientObjects[message.id] = button;
291
292 panelView.widget().then(appendButton);
293
294 /**
295 * @param {!WebInspector.Widget} panel
296 */
297 function appendButton(panel) {
298 /** @type {!WebInspector.ExtensionPanel} panel*/ (panel).addToolbarItem(bu tton.toolbarButton());
299 }
300
301 return this._status.OK();
302 }
303
304 _onUpdateButton(message, port) {
305 var button = this._clientObjects[message.id];
306 if (!button || !(button instanceof WebInspector.ExtensionButton))
307 return this._status.E_NOTFOUND(message.id);
308 button.update(this._expandResourcePath(port._extensionOrigin, message.icon), message.tooltip, message.disabled);
309 return this._status.OK();
310 }
311
312 _onCreateSidebarPane(message) {
313 if (message.panel !== 'elements' && message.panel !== 'sources')
314 return this._status.E_NOTFOUND(message.panel);
315 var id = message.id;
316 var sidebar = new WebInspector.ExtensionSidebarPane(this, message.panel, mes sage.title, id);
317 this._sidebarPanes.push(sidebar);
318 this._clientObjects[id] = sidebar;
319 this.dispatchEventToListeners(WebInspector.ExtensionServer.Events.SidebarPan eAdded, sidebar);
320
321 return this._status.OK();
322 }
323
324 /**
325 * @return {!Array.<!WebInspector.ExtensionSidebarPane>}
326 */
327 sidebarPanes() {
328 return this._sidebarPanes;
329 }
330
331 _onSetSidebarHeight(message) {
332 var sidebar = this._clientObjects[message.id];
333 if (!sidebar)
334 return this._status.E_NOTFOUND(message.id);
335 sidebar.setHeight(message.height);
336 return this._status.OK();
337 }
338
339 _onSetSidebarContent(message, port) {
340 var sidebar = this._clientObjects[message.id];
341 if (!sidebar)
342 return this._status.E_NOTFOUND(message.id);
343
344 /**
345 * @this {WebInspector.ExtensionServer}
346 */
347 function callback(error) {
348 var result = error ? this._status.E_FAILED(error) : this._status.OK();
349 this._dispatchCallback(message.requestId, port, result);
350 }
351 if (message.evaluateOnPage)
352 return sidebar.setExpression(
353 message.expression, message.rootTitle, message.evaluateOptions, port._ extensionOrigin, callback.bind(this));
354 sidebar.setObject(message.expression, message.rootTitle, callback.bind(this) );
355 }
356
357 _onSetSidebarPage(message, port) {
358 var sidebar = this._clientObjects[message.id];
359 if (!sidebar)
360 return this._status.E_NOTFOUND(message.id);
361 sidebar.setPage(this._expandResourcePath(port._extensionOrigin, message.page ));
362 }
363
364 _onOpenResource(message) {
365 var uiSourceCode = WebInspector.networkMapping.uiSourceCodeForURLForAnyTarge t(message.url);
366 if (uiSourceCode) {
367 WebInspector.Revealer.reveal(uiSourceCode.uiLocation(message.lineNumber, 0 ));
368 return this._status.OK();
369 }
370
371 var resource = WebInspector.resourceForURL(message.url);
372 if (resource) {
373 WebInspector.Revealer.reveal(resource);
374 return this._status.OK();
375 }
376
377 var request = WebInspector.NetworkLog.requestForURL(message.url);
378 if (request) {
379 WebInspector.Revealer.reveal(request);
380 return this._status.OK();
381 }
382
383 return this._status.E_NOTFOUND(message.url);
384 }
385
386 _onSetOpenResourceHandler(message, port) {
387 var name = this._registeredExtensions[port._extensionOrigin].name || ('Exten sion ' + port._extensionOrigin);
388 if (message.handlerPresent)
389 WebInspector.openAnchorLocationRegistry.registerHandler(name, this._handle OpenURL.bind(this, port));
390 else
391 WebInspector.openAnchorLocationRegistry.unregisterHandler(name);
392 }
393
394 _handleOpenURL(port, details) {
395 var url = /** @type {string} */ (details.url);
396 var contentProvider = WebInspector.workspace.uiSourceCodeForURL(url) || WebI nspector.resourceForURL(url);
397 if (!contentProvider)
398 return false;
399
400 var lineNumber = details.lineNumber;
401 if (typeof lineNumber === 'number')
402 lineNumber += 1;
403 port.postMessage({command: 'open-resource', resource: this._makeResource(con tentProvider), lineNumber: lineNumber});
404 return true;
405 }
406
407 _onReload(message) {
408 var options = /** @type {!ExtensionReloadOptions} */ (message.options || {}) ;
409
410 WebInspector.multitargetNetworkManager.setUserAgentOverride(
411 typeof options.userAgent === 'string' ? options.userAgent : '');
412 var injectedScript;
413 if (options.injectedScript)
414 injectedScript = '(function(){' + options.injectedScript + '})()';
415 WebInspector.targetManager.reloadPage(!!options.ignoreCache, injectedScript) ;
416 return this._status.OK();
417 }
418
419 _onEvaluateOnInspectedPage(message, port) {
420 /**
421 * @param {?Protocol.Error} error
422 * @param {?WebInspector.RemoteObject} remoteObject
423 * @param {boolean=} wasThrown
424 * @this {WebInspector.ExtensionServer}
425 */
426 function callback(error, remoteObject, wasThrown) {
427 var result;
428 if (error || !remoteObject)
429 result = this._status.E_PROTOCOLERROR(error.toString());
430 else if (wasThrown)
431 result = {isException: true, value: remoteObject.description};
432 else
433 result = {value: remoteObject.value};
434
435 this._dispatchCallback(message.requestId, port, result);
436 }
437 return this.evaluate(
438 message.expression, true, true, message.evaluateOptions, port._extension Origin, callback.bind(this));
439 }
440
441 _onGetHAR() {
442 var requests = WebInspector.NetworkLog.requests();
443 var harLog = (new WebInspector.HARLog(requests)).build();
444 for (var i = 0; i < harLog.entries.length; ++i)
445 harLog.entries[i]._requestId = this._requestId(requests[i]);
446 return harLog;
447 }
448
449 /**
450 * @param {!WebInspector.ContentProvider} contentProvider
451 */
452 _makeResource(contentProvider) {
453 return {url: contentProvider.contentURL(), type: contentProvider.contentType ().name()};
454 }
455
456 /**
457 * @return {!Array<!WebInspector.ContentProvider>}
458 */
459 _onGetPageResources() {
460 /** @type {!Map<string, !WebInspector.ContentProvider>} */
461 var resources = new Map();
462
463 /**
464 * @this {WebInspector.ExtensionServer}
465 */
466 function pushResourceData(contentProvider) {
467 if (!resources.has(contentProvider.contentURL()))
468 resources.set(contentProvider.contentURL(), this._makeResource(contentPr ovider));
469 }
470 var uiSourceCodes = WebInspector.workspace.uiSourceCodesForProjectType(WebIn spector.projectTypes.Network);
471 uiSourceCodes = uiSourceCodes.concat(
472 WebInspector.workspace.uiSourceCodesForProjectType(WebInspector.projectT ypes.ContentScripts));
473 uiSourceCodes.forEach(pushResourceData.bind(this));
474 for (var target of WebInspector.targetManager.targets(WebInspector.Target.Ca pability.DOM))
475 WebInspector.ResourceTreeModel.fromTarget(target).forAllResources(pushReso urceData.bind(this));
476 return resources.valuesArray();
477 }
478
479 /**
480 * @param {!WebInspector.ContentProvider} contentProvider
481 * @param {!Object} message
482 * @param {!MessagePort} port
483 */
484 _getResourceContent(contentProvider, message, port) {
485 /**
486 * @param {?string} content
487 * @this {WebInspector.ExtensionServer}
488 */
489 function onContentAvailable(content) {
490 var contentEncoded = false;
491 if (contentProvider instanceof WebInspector.Resource)
492 contentEncoded = contentProvider.contentEncoded;
493 if (contentProvider instanceof WebInspector.NetworkRequest)
494 contentEncoded = contentProvider.contentEncoded;
495 var response = {encoding: contentEncoded && content ? 'base64' : '', conte nt: content};
496 this._dispatchCallback(message.requestId, port, response);
497 }
498
499 contentProvider.requestContent().then(onContentAvailable.bind(this));
500 }
501
502 _onGetRequestContent(message, port) {
503 var request = this._requestById(message.id);
504 if (!request)
505 return this._status.E_NOTFOUND(message.id);
506 this._getResourceContent(request, message, port);
507 }
508
509 _onGetResourceContent(message, port) {
510 var url = /** @type {string} */ (message.url);
511 var contentProvider = WebInspector.workspace.uiSourceCodeForURL(url) || WebI nspector.resourceForURL(url);
512 if (!contentProvider)
513 return this._status.E_NOTFOUND(url);
514 this._getResourceContent(contentProvider, message, port);
515 }
516
517 _onSetResourceContent(message, port) {
518 /**
519 * @param {?Protocol.Error} error
520 * @this {WebInspector.ExtensionServer}
521 */
522 function callbackWrapper(error) {
523 var response = error ? this._status.E_FAILED(error) : this._status.OK();
524 this._dispatchCallback(message.requestId, port, response);
525 }
526
527 var url = /** @type {string} */ (message.url);
528 var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(url);
529 if (!uiSourceCode || !uiSourceCode.contentType().isDocumentOrScriptOrStyleSh eet()) {
530 var resource = WebInspector.ResourceTreeModel.resourceForURL(url);
531 if (!resource)
532 return this._status.E_NOTFOUND(url);
533 return this._status.E_NOTSUPPORTED('Resource is not editable');
534 }
535 uiSourceCode.setWorkingCopy(message.content);
536 if (message.commit)
537 uiSourceCode.commitWorkingCopy();
538 callbackWrapper.call(this, null);
539 }
540
541 _requestId(request) {
542 if (!request._extensionRequestId) {
543 request._extensionRequestId = ++this._lastRequestId;
544 this._requests[request._extensionRequestId] = request;
545 }
546 return request._extensionRequestId;
547 }
548
549 _requestById(id) {
550 return this._requests[id];
551 }
552
553 _onAddAuditCategory(message, port) {
554 var category = new WebInspector.ExtensionAuditCategory(
555 port._extensionOrigin, message.id, message.displayName, message.resultCo unt);
556 this._clientObjects[message.id] = category;
557 this._auditCategories.push(category);
558 this.dispatchEventToListeners(WebInspector.ExtensionServer.Events.AuditCateg oryAdded, category);
559 }
560
561 /**
562 * @param {!Object} message
563 * @param {!MessagePort} port
564 */
565 _onAddTraceProvider(message, port) {
566 var provider = new WebInspector.ExtensionTraceProvider(
567 port._extensionOrigin, message.id, message.categoryName, message.categor yTooltip);
568 this._clientObjects[message.id] = provider;
569 this._traceProviders.push(provider);
570 }
571
572 /**
573 * @return {!Array<!WebInspector.ExtensionTraceProvider>}
574 */
575 traceProviders() {
576 return this._traceProviders;
577 }
578
579 /**
580 * @return {!Array.<!WebInspector.ExtensionAuditCategory>}
581 */
582 auditCategories() {
583 return this._auditCategories;
584 }
585
586 _onAddAuditResult(message) {
587 var auditResult = /** {!WebInspector.ExtensionAuditCategoryResults} */ (this ._clientObjects[message.resultId]);
588 if (!auditResult)
589 return this._status.E_NOTFOUND(message.resultId);
590 try {
591 auditResult.addResult(message.displayName, message.description, message.se verity, message.details);
592 } catch (e) {
593 return e;
594 }
595 return this._status.OK();
596 }
597
598 _onUpdateAuditProgress(message) {
599 var auditResult = /** {!WebInspector.ExtensionAuditCategoryResults} */ (this ._clientObjects[message.resultId]);
600 if (!auditResult)
601 return this._status.E_NOTFOUND(message.resultId);
602 auditResult.updateProgress(Math.min(Math.max(0, message.progress), 1));
603 }
604
605 _onStopAuditCategoryRun(message) {
606 var auditRun = /** {!WebInspector.ExtensionAuditCategoryResults} */ (this._c lientObjects[message.resultId]);
607 if (!auditRun)
608 return this._status.E_NOTFOUND(message.resultId);
609 auditRun.done();
610 }
611
612 _onForwardKeyboardEvent(message) {
613 message.entries.forEach(handleEventEntry);
614
615 /**
616 * @param {*} entry
617 * @suppressGlobalPropertiesCheck
618 */
619 function handleEventEntry(entry) {
620 if (!entry.ctrlKey && !entry.altKey && !entry.metaKey && !/^F\d+$/.test(en try.key) && entry.key !== 'Escape')
621 return;
622 // Fool around closure compiler -- it has its own notion of both KeyboardE vent constructor
623 // and initKeyboardEvent methods and overriding these in externs.js does n ot have effect.
624 var event = new window.KeyboardEvent(entry.eventType, {
625 key: entry.key,
626 code: entry.code,
627 keyCode: entry.keyCode,
628 location: entry.location,
629 ctrlKey: entry.ctrlKey,
630 altKey: entry.altKey,
631 shiftKey: entry.shiftKey,
632 metaKey: entry.metaKey
633 });
634 event.__keyCode = keyCodeForEntry(entry);
635 document.dispatchEvent(event);
636 }
637
638 function keyCodeForEntry(entry) {
639 var keyCode = entry.keyCode;
640 if (!keyCode) {
641 // This is required only for synthetic events (e.g. dispatched in tests) .
642 if (entry.key === 'Escape')
643 keyCode = 27;
644 }
645 return keyCode || 0;
646 }
647 }
648
649 _dispatchCallback(requestId, port, result) {
650 if (requestId)
651 port.postMessage({command: 'callback', requestId: requestId, result: resul t});
652 }
653
654 _initExtensions() {
655 this._registerAutosubscriptionHandler(
656 WebInspector.extensionAPI.Events.ResourceAdded, WebInspector.workspace,
657 WebInspector.Workspace.Events.UISourceCodeAdded, this._notifyResourceAdd ed);
658 this._registerAutosubscriptionTargetManagerHandler(
659 WebInspector.extensionAPI.Events.NetworkRequestFinished, WebInspector.Ne tworkManager,
660 WebInspector.NetworkManager.Events.RequestFinished, this._notifyRequestF inished);
661
662 /**
663 * @this {WebInspector.ExtensionServer}
664 */
665 function onElementsSubscriptionStarted() {
666 WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._n otifyElementsSelectionChanged, this);
667 }
668
669 /**
670 * @this {WebInspector.ExtensionServer}
671 */
672 function onElementsSubscriptionStopped() {
673 WebInspector.context.removeFlavorChangeListener(WebInspector.DOMNode, this ._notifyElementsSelectionChanged, this);
674 }
675
676 this._registerSubscriptionHandler(
677 WebInspector.extensionAPI.Events.PanelObjectSelected + 'elements', onEle mentsSubscriptionStarted.bind(this),
678 onElementsSubscriptionStopped.bind(this));
679 this._registerResourceContentCommittedHandler(this._notifyUISourceCodeConten tCommitted);
680
681 WebInspector.targetManager.addEventListener(
682 WebInspector.TargetManager.Events.InspectedURLChanged, this._inspectedUR LChanged, this);
683
684 InspectorExtensionRegistry.getExtensionsAsync();
685 }
686
687 _notifyResourceAdded(event) {
688 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
689 this._postNotification(WebInspector.extensionAPI.Events.ResourceAdded, this. _makeResource(uiSourceCode));
690 }
691
692 _notifyUISourceCodeContentCommitted(event) {
693 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.uiS ourceCode);
694 var content = /** @type {string} */ (event.data.content);
695 this._postNotification(
696 WebInspector.extensionAPI.Events.ResourceContentCommitted, this._makeRes ource(uiSourceCode), content);
697 }
698
699 _notifyRequestFinished(event) {
700 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data);
701 this._postNotification(
702 WebInspector.extensionAPI.Events.NetworkRequestFinished, this._requestId (request),
703 (new WebInspector.HAREntry(request)).build());
704 }
705
706 _notifyElementsSelectionChanged() {
707 this._postNotification(WebInspector.extensionAPI.Events.PanelObjectSelected + 'elements');
708 }
709
710 /**
711 * @param {!WebInspector.Event} event
712 */
713 _addExtensions(event) {
714 if (WebInspector.extensionServer._overridePlatformExtensionAPIForTest)
715 window.buildPlatformExtensionAPI = WebInspector.extensionServer._overrideP latformExtensionAPIForTest;
716
717 var extensionInfos = /** @type {!Array.<!ExtensionDescriptor>} */ (event.dat a);
718 if (this._initializeCommandIssued)
719 extensionInfos.forEach(this._addExtension, this);
720 else
721 this._pendingExtensionInfos = extensionInfos;
722 }
723
724 /**
725 * @param {!WebInspector.Event} event
726 */
727 _setInspectedTabId(event) {
728 this._inspectedTabId = /** @type {string} */ (event.data);
729 }
730
731 /**
732 * @param {!ExtensionDescriptor} extensionInfo
733 * @suppressGlobalPropertiesCheck
734 */
735 _addExtension(extensionInfo) {
736 const urlOriginRegExp = new RegExp('([^:]+:\/\/[^/]*)\/'); // Can't use reg exp literal here, MinJS chokes on it.
737 var startPage = extensionInfo.startPage;
738 var name = extensionInfo.name;
739
740 try {
741 var originMatch = urlOriginRegExp.exec(startPage);
742 if (!originMatch) {
743 console.error('Skipping extension with invalid URL: ' + startPage);
744 return false;
745 }
746 var extensionOrigin = originMatch[1];
747 if (!this._registeredExtensions[extensionOrigin]) {
748 // See ExtensionAPI.js for details.
749 var injectedAPI = buildExtensionAPIInjectedScript(
750 extensionInfo, this._inspectedTabId, WebInspector.themeSupport.theme Name(),
751 WebInspector.extensionServer['_extensionAPITestHook']);
752 InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, inject edAPI);
753 this._registeredExtensions[extensionOrigin] = {name: name};
754 }
755 var iframe = createElement('iframe');
756 iframe.src = startPage;
757 iframe.style.display = 'none';
758 document.body.appendChild(iframe); // Only for main window.
759 } catch (e) {
760 console.error('Failed to initialize extension ' + startPage + ':' + e);
761 return false;
762 }
763 return true;
764 }
765
766 _registerExtension(origin, port) {
767 if (!this._registeredExtensions.hasOwnProperty(origin)) {
768 if (origin !== window.location.origin) // Just ignore inspector frames.
769 console.error('Ignoring unauthorized client request from ' + origin);
770 return;
771 }
772 port._extensionOrigin = origin;
773 port.addEventListener('message', this._onmessage.bind(this), false);
774 port.start();
775 }
776
777 _onWindowMessage(event) {
778 if (event.data === 'registerExtension')
779 this._registerExtension(event.origin, event.ports[0]);
780 }
781
782 _onmessage(event) {
783 var message = event.data;
784 var result;
785
786 if (message.command in this._handlers)
787 result = this._handlers[message.command](message, event.target);
788 else
789 result = this._status.E_NOTSUPPORTED(message.command);
790
791 if (result && message.requestId)
792 this._dispatchCallback(message.requestId, event.target, result);
793 }
794
795 _registerHandler(command, callback) {
796 console.assert(command);
797 this._handlers[command] = callback;
798 }
799
800 _registerSubscriptionHandler(eventTopic, onSubscribeFirst, onUnsubscribeLast) {
801 this._subscriptionStartHandlers[eventTopic] = onSubscribeFirst;
802 this._subscriptionStopHandlers[eventTopic] = onUnsubscribeLast;
803 }
804
805 /**
806 * @param {string} eventTopic
807 * @param {!Object} eventTarget
808 * @param {string} frontendEventType
809 * @param {function(!WebInspector.Event)} handler
810 */
811 _registerAutosubscriptionHandler(eventTopic, eventTarget, frontendEventType, h andler) {
812 this._registerSubscriptionHandler(
813 eventTopic, eventTarget.addEventListener.bind(eventTarget, frontendEvent Type, handler, this),
814 eventTarget.removeEventListener.bind(eventTarget, frontendEventType, han dler, this));
815 }
816
817 /**
818 * @param {string} eventTopic
819 * @param {!Function} modelClass
820 * @param {string} frontendEventType
821 * @param {function(!WebInspector.Event)} handler
822 */
823 _registerAutosubscriptionTargetManagerHandler(eventTopic, modelClass, frontend EventType, handler) {
824 this._registerSubscriptionHandler(
825 eventTopic, WebInspector.targetManager.addModelListener.bind(
826 WebInspector.targetManager, modelClass, frontendEventTyp e, handler, this),
827 WebInspector.targetManager.removeModelListener.bind(
828 WebInspector.targetManager, modelClass, frontendEventType, handler, this));
829 }
830
831 _registerResourceContentCommittedHandler(handler) {
832 /**
833 * @this {WebInspector.ExtensionServer}
834 */
835 function addFirstEventListener() {
836 WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.Work ingCopyCommittedByUser, handler, this);
837 WebInspector.workspace.setHasResourceContentTrackingExtensions(true);
838 }
839
840 /**
841 * @this {WebInspector.ExtensionServer}
842 */
843 function removeLastEventListener() {
844 WebInspector.workspace.setHasResourceContentTrackingExtensions(false);
845 WebInspector.workspace.removeEventListener(
846 WebInspector.Workspace.Events.WorkingCopyCommittedByUser, handler, thi s);
847 }
848
849 this._registerSubscriptionHandler(
850 WebInspector.extensionAPI.Events.ResourceContentCommitted, addFirstEvent Listener.bind(this),
851 removeLastEventListener.bind(this));
852 }
853
854 _expandResourcePath(extensionPath, resourcePath) {
855 if (!resourcePath)
856 return;
857 return extensionPath + this._normalizePath(resourcePath);
858 }
859
860 _normalizePath(path) {
861 var source = path.split('/');
862 var result = [];
863
864 for (var i = 0; i < source.length; ++i) {
865 if (source[i] === '.')
866 continue;
867 // Ignore empty path components resulting from //, as well as a leading an d traling slashes.
868 if (source[i] === '')
869 continue;
870 if (source[i] === '..')
871 result.pop();
872 else
873 result.push(source[i]);
874 }
875 return '/' + result.join('/');
876 }
877
878 /**
879 * @param {string} expression
880 * @param {boolean} exposeCommandLineAPI
881 * @param {boolean} returnByValue
882 * @param {?Object} options
883 * @param {string} securityOrigin
884 * @param {function(?string, ?WebInspector.RemoteObject, boolean=)} callback
885 * @return {!WebInspector.ExtensionStatus.Record|undefined}
886 */
887 evaluate(expression, exposeCommandLineAPI, returnByValue, options, securityOri gin, callback) {
888 var contextId;
889
890 /**
891 * @param {string} url
892 * @return {boolean}
893 */
894 function resolveURLToFrame(url) {
895 var found;
896 function hasMatchingURL(frame) {
897 found = (frame.url === url) ? frame : null;
898 return found;
899 }
900 WebInspector.ResourceTreeModel.frames().some(hasMatchingURL);
901 return found;
902 }
903
904 if (typeof options === 'object') {
905 var frame;
906 if (options.frameURL) {
907 frame = resolveURLToFrame(options.frameURL);
908 } else {
909 var target = WebInspector.targetManager.mainTarget();
910 var resourceTreeModel = target && WebInspector.ResourceTreeModel.fromTar get(target);
911 frame = resourceTreeModel && resourceTreeModel.mainFrame;
912 }
913 if (!frame) {
914 if (options.frameURL)
915 console.warn('evaluate: there is no frame with URL ' + options.frameUR L);
916 else
917 console.warn('evaluate: the main frame is not yet available');
918 return this._status.E_NOTFOUND(options.frameURL || '<top>');
919 }
920
921 var contextSecurityOrigin;
922 if (options.useContentScriptContext)
923 contextSecurityOrigin = securityOrigin;
924 else if (options.scriptExecutionContext)
925 contextSecurityOrigin = options.scriptExecutionContext;
926
927 var context;
928 var executionContexts = frame.target().runtimeModel.executionContexts();
929 if (contextSecurityOrigin) {
930 for (var i = 0; i < executionContexts.length; ++i) {
931 var executionContext = executionContexts[i];
932 if (executionContext.frameId === frame.id && executionContext.origin = == contextSecurityOrigin &&
933 !executionContext.isDefault)
934 context = executionContext;
935 }
936 if (!context) {
937 console.warn('The JavaScript context ' + contextSecurityOrigin + ' was not found in the frame ' + frame.url);
938 return this._status.E_NOTFOUND(contextSecurityOrigin);
939 }
940 } else {
941 for (var i = 0; i < executionContexts.length; ++i) {
942 var executionContext = executionContexts[i];
943 if (executionContext.frameId === frame.id && executionContext.isDefaul t)
944 context = executionContext;
945 }
946 if (!context)
947 return this._status.E_FAILED(frame.url + ' has no execution context');
948 }
949
950 contextId = context.id;
951 }
952 var target = target ? target : WebInspector.targetManager.mainTarget();
953 if (!target)
954 return;
955
956 target.runtimeAgent().evaluate(
957 expression, 'extension', exposeCommandLineAPI, true, contextId, returnBy Value, false, false, false, onEvalute);
958
959 /**
960 * @param {?Protocol.Error} error
961 * @param {!RuntimeAgent.RemoteObject} result
962 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails
963 */
964 function onEvalute(error, result, exceptionDetails) {
965 if (error) {
966 callback(error, null, !!exceptionDetails);
967 return;
968 }
969 callback(error, target.runtimeModel.createRemoteObject(result), !!exceptio nDetails);
970 }
971 }
90 }; 972 };
91 973
92 /** @enum {symbol} */ 974 /** @enum {symbol} */
93 WebInspector.ExtensionServer.Events = { 975 WebInspector.ExtensionServer.Events = {
94 SidebarPaneAdded: Symbol("SidebarPaneAdded"), 976 SidebarPaneAdded: Symbol('SidebarPaneAdded'),
95 AuditCategoryAdded: Symbol("AuditCategoryAdded") 977 AuditCategoryAdded: Symbol('AuditCategoryAdded')
96 }; 978 };
97 979
98 WebInspector.ExtensionServer.prototype = {
99 initializeExtensions: function()
100 {
101 this._initializeCommandIssued = true;
102 if (this._pendingExtensionInfos) {
103 this._pendingExtensionInfos.forEach(this._addExtension, this);
104 delete this._pendingExtensionInfos;
105 }
106 },
107
108 /**
109 * @return {boolean}
110 */
111 hasExtensions: function()
112 {
113 return !!Object.keys(this._registeredExtensions).length;
114 },
115
116 /**
117 * @param {string} panelId
118 * @param {string} action
119 * @param {string=} searchString
120 */
121 notifySearchAction: function(panelId, action, searchString)
122 {
123 this._postNotification(WebInspector.extensionAPI.Events.PanelSearch + pa nelId, action, searchString);
124 },
125
126 /**
127 * @param {string} identifier
128 * @param {number=} frameIndex
129 */
130 notifyViewShown: function(identifier, frameIndex)
131 {
132 this._postNotification(WebInspector.extensionAPI.Events.ViewShown + iden tifier, frameIndex);
133 },
134
135 /**
136 * @param {string} identifier
137 */
138 notifyViewHidden: function(identifier)
139 {
140 this._postNotification(WebInspector.extensionAPI.Events.ViewHidden + ide ntifier);
141 },
142
143 /**
144 * @param {string} identifier
145 */
146 notifyButtonClicked: function(identifier)
147 {
148 this._postNotification(WebInspector.extensionAPI.Events.ButtonClicked + identifier);
149 },
150
151 _inspectedURLChanged: function(event)
152 {
153 if (event.data !== WebInspector.targetManager.mainTarget())
154 return;
155 this._requests = {};
156 var url = event.data.inspectedURL();
157 this._postNotification(WebInspector.extensionAPI.Events.InspectedURLChan ged, url);
158 },
159
160 /**
161 * @param {string} categoryId
162 * @param {!WebInspector.ExtensionAuditCategoryResults} auditResults
163 */
164 startAuditRun: function(categoryId, auditResults)
165 {
166 this._clientObjects[auditResults.id()] = auditResults;
167 this._postNotification("audit-started-" + categoryId, auditResults.id()) ;
168 },
169
170 /**
171 * @param {!WebInspector.ExtensionAuditCategoryResults} auditResults
172 */
173 stopAuditRun: function(auditResults)
174 {
175 delete this._clientObjects[auditResults.id()];
176 },
177
178 /**
179 * @param {string} traceProviderId
180 */
181 startTraceRecording: function(traceProviderId)
182 {
183 this._postNotification("trace-recording-started-" + traceProviderId);
184 },
185
186 /**
187 * @param {string} traceProviderId
188 */
189 stopTraceRecording: function(traceProviderId)
190 {
191 this._postNotification("trace-recording-stopped-" + traceProviderId);
192 },
193
194 /**
195 * @param {string} type
196 * @return {boolean}
197 */
198 hasSubscribers: function(type)
199 {
200 return !!this._subscribers[type];
201 },
202
203 /**
204 * @param {string} type
205 * @param {...*} vararg
206 */
207 _postNotification: function(type, vararg)
208 {
209 var subscribers = this._subscribers[type];
210 if (!subscribers)
211 return;
212 var message = {
213 command: "notify-" + type,
214 arguments: Array.prototype.slice.call(arguments, 1)
215 };
216 for (var i = 0; i < subscribers.length; ++i)
217 subscribers[i].postMessage(message);
218 },
219
220 _onSubscribe: function(message, port)
221 {
222 var subscribers = this._subscribers[message.type];
223 if (subscribers)
224 subscribers.push(port);
225 else {
226 this._subscribers[message.type] = [ port ];
227 if (this._subscriptionStartHandlers[message.type])
228 this._subscriptionStartHandlers[message.type]();
229 }
230 },
231
232 _onUnsubscribe: function(message, port)
233 {
234 var subscribers = this._subscribers[message.type];
235 if (!subscribers)
236 return;
237 subscribers.remove(port);
238 if (!subscribers.length) {
239 delete this._subscribers[message.type];
240 if (this._subscriptionStopHandlers[message.type])
241 this._subscriptionStopHandlers[message.type]();
242 }
243 },
244
245 _onAddRequestHeaders: function(message)
246 {
247 var id = message.extensionId;
248 if (typeof id !== "string")
249 return this._status.E_BADARGTYPE("extensionId", typeof id, "string") ;
250 var extensionHeaders = this._extraHeaders[id];
251 if (!extensionHeaders) {
252 extensionHeaders = {};
253 this._extraHeaders[id] = extensionHeaders;
254 }
255 for (var name in message.headers)
256 extensionHeaders[name] = message.headers[name];
257 var allHeaders = /** @type {!NetworkAgent.Headers} */ ({});
258 for (var extension in this._extraHeaders) {
259 var headers = this._extraHeaders[extension];
260 for (name in headers) {
261 if (typeof headers[name] === "string")
262 allHeaders[name] = headers[name];
263 }
264 }
265
266 WebInspector.multitargetNetworkManager.setExtraHTTPHeaders(allHeaders);
267 },
268
269 /**
270 * @param {*} message
271 * @suppressGlobalPropertiesCheck
272 */
273 _onApplyStyleSheet: function(message)
274 {
275 if (!Runtime.experiments.isEnabled("applyCustomStylesheet"))
276 return;
277 var styleSheet = createElement("style");
278 styleSheet.textContent = message.styleSheet;
279 document.head.appendChild(styleSheet);
280 },
281
282 _onCreatePanel: function(message, port)
283 {
284 var id = message.id;
285 // The ids are generated on the client API side and must be unique, so t he check below
286 // shouldn't be hit unless someone is bypassing the API.
287 if (id in this._clientObjects || WebInspector.inspectorView.hasPanel(id) )
288 return this._status.E_EXISTS(id);
289
290 var page = this._expandResourcePath(port._extensionOrigin, message.page) ;
291 var persistentId = port._extensionOrigin + message.title;
292 persistentId = persistentId.replace(/\s/g, "");
293 var panelView = new WebInspector.ExtensionServerPanelView(persistentId, message.title, new WebInspector.ExtensionPanel(this, persistentId, id, page));
294 this._clientObjects[id] = panelView;
295 WebInspector.inspectorView.addPanel(panelView);
296 return this._status.OK();
297 },
298
299 _onShowPanel: function(message)
300 {
301 var panelViewId = message.id;
302 var panelView = this._clientObjects[message.id];
303 if (panelView && panelView instanceof WebInspector.ExtensionServerPanelV iew)
304 panelViewId = panelView.viewId();
305 WebInspector.inspectorView.showPanel(panelViewId);
306 },
307
308 _onCreateToolbarButton: function(message, port)
309 {
310 var panelView = this._clientObjects[message.panel];
311 if (!panelView || !(panelView instanceof WebInspector.ExtensionServerPan elView))
312 return this._status.E_NOTFOUND(message.panel);
313 var button = new WebInspector.ExtensionButton(this, message.id, this._ex pandResourcePath(port._extensionOrigin, message.icon), message.tooltip, message. disabled);
314 this._clientObjects[message.id] = button;
315
316 panelView.widget().then(appendButton);
317
318 /**
319 * @param {!WebInspector.Widget} panel
320 */
321 function appendButton(panel)
322 {
323 /** @type {!WebInspector.ExtensionPanel} panel*/ (panel).addToolbarI tem(button.toolbarButton());
324 }
325
326 return this._status.OK();
327 },
328
329 _onUpdateButton: function(message, port)
330 {
331 var button = this._clientObjects[message.id];
332 if (!button || !(button instanceof WebInspector.ExtensionButton))
333 return this._status.E_NOTFOUND(message.id);
334 button.update(this._expandResourcePath(port._extensionOrigin, message.ic on), message.tooltip, message.disabled);
335 return this._status.OK();
336 },
337
338 _onCreateSidebarPane: function(message)
339 {
340 if (message.panel !== "elements" && message.panel !== "sources")
341 return this._status.E_NOTFOUND(message.panel);
342 var id = message.id;
343 var sidebar = new WebInspector.ExtensionSidebarPane(this, message.panel, message.title, id);
344 this._sidebarPanes.push(sidebar);
345 this._clientObjects[id] = sidebar;
346 this.dispatchEventToListeners(WebInspector.ExtensionServer.Events.Sideba rPaneAdded, sidebar);
347
348 return this._status.OK();
349 },
350
351 /**
352 * @return {!Array.<!WebInspector.ExtensionSidebarPane>}
353 */
354 sidebarPanes: function()
355 {
356 return this._sidebarPanes;
357 },
358
359 _onSetSidebarHeight: function(message)
360 {
361 var sidebar = this._clientObjects[message.id];
362 if (!sidebar)
363 return this._status.E_NOTFOUND(message.id);
364 sidebar.setHeight(message.height);
365 return this._status.OK();
366 },
367
368 _onSetSidebarContent: function(message, port)
369 {
370 var sidebar = this._clientObjects[message.id];
371 if (!sidebar)
372 return this._status.E_NOTFOUND(message.id);
373
374 /**
375 * @this {WebInspector.ExtensionServer}
376 */
377 function callback(error)
378 {
379 var result = error ? this._status.E_FAILED(error) : this._status.OK( );
380 this._dispatchCallback(message.requestId, port, result);
381 }
382 if (message.evaluateOnPage)
383 return sidebar.setExpression(message.expression, message.rootTitle, message.evaluateOptions, port._extensionOrigin, callback.bind(this));
384 sidebar.setObject(message.expression, message.rootTitle, callback.bind(t his));
385 },
386
387 _onSetSidebarPage: function(message, port)
388 {
389 var sidebar = this._clientObjects[message.id];
390 if (!sidebar)
391 return this._status.E_NOTFOUND(message.id);
392 sidebar.setPage(this._expandResourcePath(port._extensionOrigin, message. page));
393 },
394
395 _onOpenResource: function(message)
396 {
397 var uiSourceCode = WebInspector.networkMapping.uiSourceCodeForURLForAnyT arget(message.url);
398 if (uiSourceCode) {
399 WebInspector.Revealer.reveal(uiSourceCode.uiLocation(message.lineNum ber, 0));
400 return this._status.OK();
401 }
402
403 var resource = WebInspector.resourceForURL(message.url);
404 if (resource) {
405 WebInspector.Revealer.reveal(resource);
406 return this._status.OK();
407 }
408
409 var request = WebInspector.NetworkLog.requestForURL(message.url);
410 if (request) {
411 WebInspector.Revealer.reveal(request);
412 return this._status.OK();
413 }
414
415 return this._status.E_NOTFOUND(message.url);
416 },
417
418 _onSetOpenResourceHandler: function(message, port)
419 {
420 var name = this._registeredExtensions[port._extensionOrigin].name || ("E xtension " + port._extensionOrigin);
421 if (message.handlerPresent)
422 WebInspector.openAnchorLocationRegistry.registerHandler(name, this._ handleOpenURL.bind(this, port));
423 else
424 WebInspector.openAnchorLocationRegistry.unregisterHandler(name);
425 },
426
427 _handleOpenURL: function(port, details)
428 {
429 var url = /** @type {string} */ (details.url);
430 var contentProvider = WebInspector.workspace.uiSourceCodeForURL(url) || WebInspector.resourceForURL(url);
431 if (!contentProvider)
432 return false;
433
434 var lineNumber = details.lineNumber;
435 if (typeof lineNumber === "number")
436 lineNumber += 1;
437 port.postMessage({
438 command: "open-resource",
439 resource: this._makeResource(contentProvider),
440 lineNumber: lineNumber
441 });
442 return true;
443 },
444
445 _onReload: function(message)
446 {
447 var options = /** @type {!ExtensionReloadOptions} */ (message.options || {});
448
449 WebInspector.multitargetNetworkManager.setUserAgentOverride(typeof optio ns.userAgent === "string" ? options.userAgent : "");
450 var injectedScript;
451 if (options.injectedScript)
452 injectedScript = "(function(){" + options.injectedScript + "})()";
453 WebInspector.targetManager.reloadPage(!!options.ignoreCache, injectedScr ipt);
454 return this._status.OK();
455 },
456
457 _onEvaluateOnInspectedPage: function(message, port)
458 {
459 /**
460 * @param {?Protocol.Error} error
461 * @param {?WebInspector.RemoteObject} remoteObject
462 * @param {boolean=} wasThrown
463 * @this {WebInspector.ExtensionServer}
464 */
465 function callback(error, remoteObject, wasThrown)
466 {
467 var result;
468 if (error || !remoteObject)
469 result = this._status.E_PROTOCOLERROR(error.toString());
470 else if (wasThrown)
471 result = { isException: true, value: remoteObject.description };
472 else
473 result = { value: remoteObject.value };
474
475 this._dispatchCallback(message.requestId, port, result);
476 }
477 return this.evaluate(message.expression, true, true, message.evaluateOpt ions, port._extensionOrigin, callback.bind(this));
478 },
479
480 _onGetHAR: function()
481 {
482 var requests = WebInspector.NetworkLog.requests();
483 var harLog = (new WebInspector.HARLog(requests)).build();
484 for (var i = 0; i < harLog.entries.length; ++i)
485 harLog.entries[i]._requestId = this._requestId(requests[i]);
486 return harLog;
487 },
488
489 /**
490 * @param {!WebInspector.ContentProvider} contentProvider
491 */
492 _makeResource: function(contentProvider)
493 {
494 return {
495 url: contentProvider.contentURL(),
496 type: contentProvider.contentType().name()
497 };
498 },
499
500 /**
501 * @return {!Array<!WebInspector.ContentProvider>}
502 */
503 _onGetPageResources: function()
504 {
505 /** @type {!Map<string, !WebInspector.ContentProvider>} */
506 var resources = new Map();
507
508 /**
509 * @this {WebInspector.ExtensionServer}
510 */
511 function pushResourceData(contentProvider)
512 {
513 if (!resources.has(contentProvider.contentURL()))
514 resources.set(contentProvider.contentURL(), this._makeResource(c ontentProvider));
515 }
516 var uiSourceCodes = WebInspector.workspace.uiSourceCodesForProjectType(W ebInspector.projectTypes.Network);
517 uiSourceCodes = uiSourceCodes.concat(WebInspector.workspace.uiSourceCode sForProjectType(WebInspector.projectTypes.ContentScripts));
518 uiSourceCodes.forEach(pushResourceData.bind(this));
519 for (var target of WebInspector.targetManager.targets(WebInspector.Targe t.Capability.DOM))
520 WebInspector.ResourceTreeModel.fromTarget(target).forAllResources(pu shResourceData.bind(this));
521 return resources.valuesArray();
522 },
523
524 /**
525 * @param {!WebInspector.ContentProvider} contentProvider
526 * @param {!Object} message
527 * @param {!MessagePort} port
528 */
529 _getResourceContent: function(contentProvider, message, port)
530 {
531 /**
532 * @param {?string} content
533 * @this {WebInspector.ExtensionServer}
534 */
535 function onContentAvailable(content)
536 {
537 var contentEncoded = false;
538 if (contentProvider instanceof WebInspector.Resource)
539 contentEncoded = contentProvider.contentEncoded;
540 if (contentProvider instanceof WebInspector.NetworkRequest)
541 contentEncoded = contentProvider.contentEncoded;
542 var response = {
543 encoding: contentEncoded && content ? "base64" : "",
544 content: content
545 };
546 this._dispatchCallback(message.requestId, port, response);
547 }
548
549 contentProvider.requestContent().then(onContentAvailable.bind(this));
550 },
551
552 _onGetRequestContent: function(message, port)
553 {
554 var request = this._requestById(message.id);
555 if (!request)
556 return this._status.E_NOTFOUND(message.id);
557 this._getResourceContent(request, message, port);
558 },
559
560 _onGetResourceContent: function(message, port)
561 {
562 var url = /** @type {string} */ (message.url);
563 var contentProvider = WebInspector.workspace.uiSourceCodeForURL(url) || WebInspector.resourceForURL(url);
564 if (!contentProvider)
565 return this._status.E_NOTFOUND(url);
566 this._getResourceContent(contentProvider, message, port);
567 },
568
569 _onSetResourceContent: function(message, port)
570 {
571 /**
572 * @param {?Protocol.Error} error
573 * @this {WebInspector.ExtensionServer}
574 */
575 function callbackWrapper(error)
576 {
577 var response = error ? this._status.E_FAILED(error) : this._status.O K();
578 this._dispatchCallback(message.requestId, port, response);
579 }
580
581 var url = /** @type {string} */ (message.url);
582 var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(url);
583 if (!uiSourceCode || !uiSourceCode.contentType().isDocumentOrScriptOrSty leSheet()) {
584 var resource = WebInspector.ResourceTreeModel.resourceForURL(url);
585 if (!resource)
586 return this._status.E_NOTFOUND(url);
587 return this._status.E_NOTSUPPORTED("Resource is not editable");
588 }
589 uiSourceCode.setWorkingCopy(message.content);
590 if (message.commit)
591 uiSourceCode.commitWorkingCopy();
592 callbackWrapper.call(this, null);
593 },
594
595 _requestId: function(request)
596 {
597 if (!request._extensionRequestId) {
598 request._extensionRequestId = ++this._lastRequestId;
599 this._requests[request._extensionRequestId] = request;
600 }
601 return request._extensionRequestId;
602 },
603
604 _requestById: function(id)
605 {
606 return this._requests[id];
607 },
608
609 _onAddAuditCategory: function(message, port)
610 {
611 var category = new WebInspector.ExtensionAuditCategory(port._extensionOr igin, message.id, message.displayName, message.resultCount);
612 this._clientObjects[message.id] = category;
613 this._auditCategories.push(category);
614 this.dispatchEventToListeners(WebInspector.ExtensionServer.Events.AuditC ategoryAdded, category);
615 },
616
617 /**
618 * @param {!Object} message
619 * @param {!MessagePort} port
620 */
621 _onAddTraceProvider: function(message, port)
622 {
623 var provider = new WebInspector.ExtensionTraceProvider(port._extensionOr igin, message.id, message.categoryName, message.categoryTooltip);
624 this._clientObjects[message.id] = provider;
625 this._traceProviders.push(provider);
626 },
627
628 /**
629 * @return {!Array<!WebInspector.ExtensionTraceProvider>}
630 */
631 traceProviders: function()
632 {
633 return this._traceProviders;
634 },
635
636 /**
637 * @return {!Array.<!WebInspector.ExtensionAuditCategory>}
638 */
639 auditCategories: function()
640 {
641 return this._auditCategories;
642 },
643
644 _onAddAuditResult: function(message)
645 {
646 var auditResult = /** {!WebInspector.ExtensionAuditCategoryResults} */ ( this._clientObjects[message.resultId]);
647 if (!auditResult)
648 return this._status.E_NOTFOUND(message.resultId);
649 try {
650 auditResult.addResult(message.displayName, message.description, mess age.severity, message.details);
651 } catch (e) {
652 return e;
653 }
654 return this._status.OK();
655 },
656
657 _onUpdateAuditProgress: function(message)
658 {
659 var auditResult = /** {!WebInspector.ExtensionAuditCategoryResults} */ ( this._clientObjects[message.resultId]);
660 if (!auditResult)
661 return this._status.E_NOTFOUND(message.resultId);
662 auditResult.updateProgress(Math.min(Math.max(0, message.progress), 1));
663 },
664
665 _onStopAuditCategoryRun: function(message)
666 {
667 var auditRun = /** {!WebInspector.ExtensionAuditCategoryResults} */ (thi s._clientObjects[message.resultId]);
668 if (!auditRun)
669 return this._status.E_NOTFOUND(message.resultId);
670 auditRun.done();
671 },
672
673 _onForwardKeyboardEvent: function(message)
674 {
675 message.entries.forEach(handleEventEntry);
676
677 /**
678 * @param {*} entry
679 * @suppressGlobalPropertiesCheck
680 */
681 function handleEventEntry(entry)
682 {
683 if (!entry.ctrlKey && !entry.altKey && !entry.metaKey && !/^F\d+$/.t est(entry.key) && entry.key !== "Escape")
684 return;
685 // Fool around closure compiler -- it has its own notion of both Key boardEvent constructor
686 // and initKeyboardEvent methods and overriding these in externs.js does not have effect.
687 var event = new window.KeyboardEvent(entry.eventType, {
688 key: entry.key,
689 code: entry.code,
690 keyCode: entry.keyCode,
691 location: entry.location,
692 ctrlKey: entry.ctrlKey,
693 altKey: entry.altKey,
694 shiftKey: entry.shiftKey,
695 metaKey: entry.metaKey
696 });
697 event.__keyCode = keyCodeForEntry(entry);
698 document.dispatchEvent(event);
699 }
700
701 function keyCodeForEntry(entry)
702 {
703 var keyCode = entry.keyCode;
704 if (!keyCode) {
705 // This is required only for synthetic events (e.g. dispatched i n tests).
706 if (entry.key === "Escape")
707 keyCode = 27;
708 }
709 return keyCode || 0;
710 }
711 },
712
713 _dispatchCallback: function(requestId, port, result)
714 {
715 if (requestId)
716 port.postMessage({ command: "callback", requestId: requestId, result : result });
717 },
718
719 _initExtensions: function()
720 {
721 this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.R esourceAdded,
722 WebInspector.workspace, WebInspector.Workspace.Events.UISourceCodeAd ded, this._notifyResourceAdded);
723 this._registerAutosubscriptionTargetManagerHandler(WebInspector.extensio nAPI.Events.NetworkRequestFinished,
724 WebInspector.NetworkManager, WebInspector.NetworkManager.Events.Requ estFinished, this._notifyRequestFinished);
725
726 /**
727 * @this {WebInspector.ExtensionServer}
728 */
729 function onElementsSubscriptionStarted()
730 {
731 WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, t his._notifyElementsSelectionChanged, this);
732 }
733
734 /**
735 * @this {WebInspector.ExtensionServer}
736 */
737 function onElementsSubscriptionStopped()
738 {
739 WebInspector.context.removeFlavorChangeListener(WebInspector.DOMNode , this._notifyElementsSelectionChanged, this);
740 }
741
742 this._registerSubscriptionHandler(WebInspector.extensionAPI.Events.Panel ObjectSelected + "elements",
743 onElementsSubscriptionStarted.bind(this), onElementsSubscriptionStop ped.bind(this));
744 this._registerResourceContentCommittedHandler(this._notifyUISourceCodeCo ntentCommitted);
745
746 WebInspector.targetManager.addEventListener(WebInspector.TargetManager.E vents.InspectedURLChanged,
747 this._inspectedURLChanged, this);
748
749 InspectorExtensionRegistry.getExtensionsAsync();
750 },
751
752 _notifyResourceAdded: function(event)
753 {
754 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data );
755 this._postNotification(WebInspector.extensionAPI.Events.ResourceAdded, t his._makeResource(uiSourceCode));
756 },
757
758 _notifyUISourceCodeContentCommitted: function(event)
759 {
760 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data .uiSourceCode);
761 var content = /** @type {string} */ (event.data.content);
762 this._postNotification(WebInspector.extensionAPI.Events.ResourceContentC ommitted, this._makeResource(uiSourceCode), content);
763 },
764
765 _notifyRequestFinished: function(event)
766 {
767 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data);
768 this._postNotification(WebInspector.extensionAPI.Events.NetworkRequestFi nished, this._requestId(request), (new WebInspector.HAREntry(request)).build());
769 },
770
771 _notifyElementsSelectionChanged: function()
772 {
773 this._postNotification(WebInspector.extensionAPI.Events.PanelObjectSelec ted + "elements");
774 },
775
776 /**
777 * @param {!WebInspector.Event} event
778 */
779 _addExtensions: function(event)
780 {
781 if (WebInspector.extensionServer._overridePlatformExtensionAPIForTest)
782 window.buildPlatformExtensionAPI = WebInspector.extensionServer._ove rridePlatformExtensionAPIForTest;
783
784 var extensionInfos = /** @type {!Array.<!ExtensionDescriptor>} */ (event .data);
785 if (this._initializeCommandIssued)
786 extensionInfos.forEach(this._addExtension, this);
787 else
788 this._pendingExtensionInfos = extensionInfos;
789 },
790
791 /**
792 * @param {!WebInspector.Event} event
793 */
794 _setInspectedTabId: function(event)
795 {
796 this._inspectedTabId = /** @type {string} */ (event.data);
797 },
798
799 /**
800 * @param {!ExtensionDescriptor} extensionInfo
801 * @suppressGlobalPropertiesCheck
802 */
803 _addExtension: function(extensionInfo)
804 {
805 const urlOriginRegExp = new RegExp("([^:]+:\/\/[^/]*)\/"); // Can't use regexp literal here, MinJS chokes on it.
806 var startPage = extensionInfo.startPage;
807 var name = extensionInfo.name;
808
809 try {
810 var originMatch = urlOriginRegExp.exec(startPage);
811 if (!originMatch) {
812 console.error("Skipping extension with invalid URL: " + startPag e);
813 return false;
814 }
815 var extensionOrigin = originMatch[1];
816 if (!this._registeredExtensions[extensionOrigin]) {
817 // See ExtensionAPI.js for details.
818 var injectedAPI = buildExtensionAPIInjectedScript(extensionInfo, this._inspectedTabId, WebInspector.themeSupport.themeName(), WebInspector.exten sionServer["_extensionAPITestHook"]);
819 InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin , injectedAPI);
820 this._registeredExtensions[extensionOrigin] = { name: name };
821 }
822 var iframe = createElement("iframe");
823 iframe.src = startPage;
824 iframe.style.display = "none";
825 document.body.appendChild(iframe); // Only for main window.
826 } catch (e) {
827 console.error("Failed to initialize extension " + startPage + ":" + e);
828 return false;
829 }
830 return true;
831 },
832
833 _registerExtension: function(origin, port)
834 {
835 if (!this._registeredExtensions.hasOwnProperty(origin)) {
836 if (origin !== window.location.origin) // Just ignore inspector fram es.
837 console.error("Ignoring unauthorized client request from " + ori gin);
838 return;
839 }
840 port._extensionOrigin = origin;
841 port.addEventListener("message", this._onmessage.bind(this), false);
842 port.start();
843 },
844
845 _onWindowMessage: function(event)
846 {
847 if (event.data === "registerExtension")
848 this._registerExtension(event.origin, event.ports[0]);
849 },
850
851 _onmessage: function(event)
852 {
853 var message = event.data;
854 var result;
855
856 if (message.command in this._handlers)
857 result = this._handlers[message.command](message, event.target);
858 else
859 result = this._status.E_NOTSUPPORTED(message.command);
860
861 if (result && message.requestId)
862 this._dispatchCallback(message.requestId, event.target, result);
863 },
864
865 _registerHandler: function(command, callback)
866 {
867 console.assert(command);
868 this._handlers[command] = callback;
869 },
870
871 _registerSubscriptionHandler: function(eventTopic, onSubscribeFirst, onUnsub scribeLast)
872 {
873 this._subscriptionStartHandlers[eventTopic] = onSubscribeFirst;
874 this._subscriptionStopHandlers[eventTopic] = onUnsubscribeLast;
875 },
876
877 /**
878 * @param {string} eventTopic
879 * @param {!Object} eventTarget
880 * @param {string} frontendEventType
881 * @param {function(!WebInspector.Event)} handler
882 */
883 _registerAutosubscriptionHandler: function(eventTopic, eventTarget, frontend EventType, handler)
884 {
885 this._registerSubscriptionHandler(eventTopic,
886 eventTarget.addEventListener.bind(eventTarget, frontendEventType, ha ndler, this),
887 eventTarget.removeEventListener.bind(eventTarget, frontendEventType, handler, this));
888 },
889
890 /**
891 * @param {string} eventTopic
892 * @param {!Function} modelClass
893 * @param {string} frontendEventType
894 * @param {function(!WebInspector.Event)} handler
895 */
896 _registerAutosubscriptionTargetManagerHandler: function(eventTopic, modelCla ss, frontendEventType, handler)
897 {
898 this._registerSubscriptionHandler(eventTopic,
899 WebInspector.targetManager.addModelListener.bind(WebInspector.target Manager, modelClass, frontendEventType, handler, this),
900 WebInspector.targetManager.removeModelListener.bind(WebInspector.tar getManager, modelClass, frontendEventType, handler, this));
901 },
902
903 _registerResourceContentCommittedHandler: function(handler)
904 {
905 /**
906 * @this {WebInspector.ExtensionServer}
907 */
908 function addFirstEventListener()
909 {
910 WebInspector.workspace.addEventListener(WebInspector.Workspace.Event s.WorkingCopyCommittedByUser, handler, this);
911 WebInspector.workspace.setHasResourceContentTrackingExtensions(true) ;
912 }
913
914 /**
915 * @this {WebInspector.ExtensionServer}
916 */
917 function removeLastEventListener()
918 {
919 WebInspector.workspace.setHasResourceContentTrackingExtensions(false );
920 WebInspector.workspace.removeEventListener(WebInspector.Workspace.Ev ents.WorkingCopyCommittedByUser, handler, this);
921 }
922
923 this._registerSubscriptionHandler(WebInspector.extensionAPI.Events.Resou rceContentCommitted,
924 addFirstEventListener.bind(this),
925 removeLastEventListener.bind(this));
926 },
927
928 _expandResourcePath: function(extensionPath, resourcePath)
929 {
930 if (!resourcePath)
931 return;
932 return extensionPath + this._normalizePath(resourcePath);
933 },
934
935 _normalizePath: function(path)
936 {
937 var source = path.split("/");
938 var result = [];
939
940 for (var i = 0; i < source.length; ++i) {
941 if (source[i] === ".")
942 continue;
943 // Ignore empty path components resulting from //, as well as a lead ing and traling slashes.
944 if (source[i] === "")
945 continue;
946 if (source[i] === "..")
947 result.pop();
948 else
949 result.push(source[i]);
950 }
951 return "/" + result.join("/");
952 },
953
954 /**
955 * @param {string} expression
956 * @param {boolean} exposeCommandLineAPI
957 * @param {boolean} returnByValue
958 * @param {?Object} options
959 * @param {string} securityOrigin
960 * @param {function(?string, ?WebInspector.RemoteObject, boolean=)} callback
961 * @return {!WebInspector.ExtensionStatus.Record|undefined}
962 */
963 evaluate: function(expression, exposeCommandLineAPI, returnByValue, options, securityOrigin, callback)
964 {
965 var contextId;
966
967 /**
968 * @param {string} url
969 * @return {boolean}
970 */
971 function resolveURLToFrame(url)
972 {
973 var found;
974 function hasMatchingURL(frame)
975 {
976 found = (frame.url === url) ? frame : null;
977 return found;
978 }
979 WebInspector.ResourceTreeModel.frames().some(hasMatchingURL);
980 return found;
981 }
982
983 if (typeof options === "object") {
984 var frame;
985 if (options.frameURL) {
986 frame = resolveURLToFrame(options.frameURL);
987 } else {
988 var target = WebInspector.targetManager.mainTarget();
989 var resourceTreeModel = target && WebInspector.ResourceTreeModel .fromTarget(target);
990 frame = resourceTreeModel && resourceTreeModel.mainFrame;
991 }
992 if (!frame) {
993 if (options.frameURL)
994 console.warn("evaluate: there is no frame with URL " + optio ns.frameURL);
995 else
996 console.warn("evaluate: the main frame is not yet available" );
997 return this._status.E_NOTFOUND(options.frameURL || "<top>");
998 }
999
1000 var contextSecurityOrigin;
1001 if (options.useContentScriptContext)
1002 contextSecurityOrigin = securityOrigin;
1003 else if (options.scriptExecutionContext)
1004 contextSecurityOrigin = options.scriptExecutionContext;
1005
1006 var context;
1007 var executionContexts = frame.target().runtimeModel.executionContext s();
1008 if (contextSecurityOrigin) {
1009 for (var i = 0; i < executionContexts.length; ++i) {
1010 var executionContext = executionContexts[i];
1011 if (executionContext.frameId === frame.id && executionContex t.origin === contextSecurityOrigin && !executionContext.isDefault)
1012 context = executionContext;
1013
1014 }
1015 if (!context) {
1016 console.warn("The JavaScript context " + contextSecurityOrig in + " was not found in the frame " + frame.url);
1017 return this._status.E_NOTFOUND(contextSecurityOrigin);
1018 }
1019 } else {
1020 for (var i = 0; i < executionContexts.length; ++i) {
1021 var executionContext = executionContexts[i];
1022 if (executionContext.frameId === frame.id && executionContex t.isDefault)
1023 context = executionContext;
1024
1025 }
1026 if (!context)
1027 return this._status.E_FAILED(frame.url + " has no execution context");
1028 }
1029
1030 contextId = context.id;
1031 }
1032 var target = target ? target : WebInspector.targetManager.mainTarget();
1033 if (!target)
1034 return;
1035
1036 target.runtimeAgent().evaluate(expression, "extension", exposeCommandLin eAPI, true, contextId, returnByValue, false, false, false, onEvalute);
1037
1038 /**
1039 * @param {?Protocol.Error} error
1040 * @param {!RuntimeAgent.RemoteObject} result
1041 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails
1042 */
1043 function onEvalute(error, result, exceptionDetails)
1044 {
1045 if (error) {
1046 callback(error, null, !!exceptionDetails);
1047 return;
1048 }
1049 callback(error, target.runtimeModel.createRemoteObject(result), !!ex ceptionDetails);
1050 }
1051 },
1052
1053 __proto__: WebInspector.Object.prototype
1054 };
1055
1056 /** 980 /**
1057 * @constructor 981 * @unrestricted
1058 * @param {string} name
1059 * @param {string} title
1060 * @param {!WebInspector.Panel} panel
1061 * @extends {WebInspector.SimpleView}
1062 */ 982 */
1063 WebInspector.ExtensionServerPanelView = function(name, title, panel) 983 WebInspector.ExtensionServerPanelView = class extends WebInspector.SimpleView {
1064 { 984 /**
1065 WebInspector.SimpleView.call(this, title); 985 * @param {string} name
986 * @param {string} title
987 * @param {!WebInspector.Panel} panel
988 */
989 constructor(name, title, panel) {
990 super(title);
1066 this._name = name; 991 this._name = name;
1067 this._panel = panel; 992 this._panel = panel;
993 }
994
995 /**
996 * @override
997 * @return {string}
998 */
999 viewId() {
1000 return this._name;
1001 }
1002
1003 /**
1004 * @override
1005 * @return {!Promise.<!WebInspector.Widget>}
1006 */
1007 widget() {
1008 return /** @type {!Promise.<!WebInspector.Widget>} */ (Promise.resolve(this. _panel));
1009 }
1068 }; 1010 };
1069 1011
1070 WebInspector.ExtensionServerPanelView.prototype = {
1071 /**
1072 * @override
1073 * @return {string}
1074 */
1075 viewId: function()
1076 {
1077 return this._name;
1078 },
1079
1080 /**
1081 * @override
1082 * @return {!Promise.<!WebInspector.Widget>}
1083 */
1084 widget: function()
1085 {
1086 return /** @type {!Promise.<!WebInspector.Widget>} */ (Promise.resolve(t his._panel));
1087 },
1088
1089 __proto__: WebInspector.SimpleView.prototype
1090 };
1091
1092 /** 1012 /**
1093 * @constructor 1013 * @unrestricted
1094 */ 1014 */
1095 WebInspector.ExtensionStatus = function() 1015 WebInspector.ExtensionStatus = class {
1096 { 1016 constructor() {
1097 /** 1017 /**
1098 * @param {string} code 1018 * @param {string} code
1099 * @param {string} description 1019 * @param {string} description
1100 * @return {!WebInspector.ExtensionStatus.Record} 1020 * @return {!WebInspector.ExtensionStatus.Record}
1101 */ 1021 */
1102 function makeStatus(code, description) 1022 function makeStatus(code, description) {
1103 { 1023 var details = Array.prototype.slice.call(arguments, 2);
1104 var details = Array.prototype.slice.call(arguments, 2); 1024 var status = {code: code, description: description, details: details};
1105 var status = { code: code, description: description, details: details }; 1025 if (code !== 'OK') {
1106 if (code !== "OK") { 1026 status.isError = true;
1107 status.isError = true; 1027 console.log('Extension server error: ' + String.vsprintf(description, de tails));
1108 console.log("Extension server error: " + String.vsprintf(description , details)); 1028 }
1109 } 1029 return status;
1110 return status; 1030 }
1111 } 1031
1112 1032 this.OK = makeStatus.bind(null, 'OK', 'OK');
1113 this.OK = makeStatus.bind(null, "OK", "OK"); 1033 this.E_EXISTS = makeStatus.bind(null, 'E_EXISTS', 'Object already exists: %s ');
1114 this.E_EXISTS = makeStatus.bind(null, "E_EXISTS", "Object already exists: %s "); 1034 this.E_BADARG = makeStatus.bind(null, 'E_BADARG', 'Invalid argument %s: %s') ;
1115 this.E_BADARG = makeStatus.bind(null, "E_BADARG", "Invalid argument %s: %s") ; 1035 this.E_BADARGTYPE = makeStatus.bind(null, 'E_BADARGTYPE', 'Invalid type for argument %s: got %s, expected %s');
1116 this.E_BADARGTYPE = makeStatus.bind(null, "E_BADARGTYPE", "Invalid type for argument %s: got %s, expected %s"); 1036 this.E_NOTFOUND = makeStatus.bind(null, 'E_NOTFOUND', 'Object not found: %s' );
1117 this.E_NOTFOUND = makeStatus.bind(null, "E_NOTFOUND", "Object not found: %s" ); 1037 this.E_NOTSUPPORTED = makeStatus.bind(null, 'E_NOTSUPPORTED', 'Object does n ot support requested operation: %s');
1118 this.E_NOTSUPPORTED = makeStatus.bind(null, "E_NOTSUPPORTED", "Object does n ot support requested operation: %s"); 1038 this.E_PROTOCOLERROR = makeStatus.bind(null, 'E_PROTOCOLERROR', 'Inspector p rotocol error: %s');
1119 this.E_PROTOCOLERROR = makeStatus.bind(null, "E_PROTOCOLERROR", "Inspector p rotocol error: %s"); 1039 this.E_FAILED = makeStatus.bind(null, 'E_FAILED', 'Operation failed: %s');
1120 this.E_FAILED = makeStatus.bind(null, "E_FAILED", "Operation failed: %s"); 1040 }
1121 }; 1041 };
1122 1042
1123 /** 1043 /**
1124 * @typedef {{code: string, description: string, details: !Array.<*>}} 1044 * @typedef {{code: string, description: string, details: !Array.<*>}}
1125 */ 1045 */
1126 WebInspector.ExtensionStatus.Record; 1046 WebInspector.ExtensionStatus.Record;
1127 1047
1128 WebInspector.extensionAPI = {}; 1048 WebInspector.extensionAPI = {};
1129 defineCommonExtensionSymbols(WebInspector.extensionAPI); 1049 defineCommonExtensionSymbols(WebInspector.extensionAPI);
1130 1050
1131 /** @type {!WebInspector.ExtensionServer} */ 1051 /** @type {!WebInspector.ExtensionServer} */
1132 WebInspector.extensionServer; 1052 WebInspector.extensionServer;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698