1/* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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. 29 */ 30 31function defineCommonExtensionSymbols(apiPrivate) 32{ 33 if (!apiPrivate.audits) 34 apiPrivate.audits = {}; 35 apiPrivate.audits.Severity = { 36 Info: "info", 37 Warning: "warning", 38 Severe: "severe" 39 }; 40 41 if (!apiPrivate.console) 42 apiPrivate.console = {}; 43 apiPrivate.console.Severity = { 44 Debug: "debug", 45 Log: "log", 46 Warning: "warning", 47 Error: "error" 48 }; 49 50 if (!apiPrivate.panels) 51 apiPrivate.panels = {}; 52 apiPrivate.panels.SearchAction = { 53 CancelSearch: "cancelSearch", 54 PerformSearch: "performSearch", 55 NextSearchResult: "nextSearchResult", 56 PreviousSearchResult: "previousSearchResult" 57 }; 58 59 apiPrivate.Events = { 60 AuditStarted: "audit-started-", 61 ButtonClicked: "button-clicked-", 62 ConsoleMessageAdded: "console-message-added", 63 ElementsPanelObjectSelected: "panel-objectSelected-elements", 64 NetworkRequestFinished: "network-request-finished", 65 OpenResource: "open-resource", 66 PanelSearch: "panel-search-", 67 Reload: "Reload", 68 ResourceAdded: "resource-added", 69 ResourceContentCommitted: "resource-content-committed", 70 TimelineEventRecorded: "timeline-event-recorded", 71 ViewShown: "view-shown-", 72 ViewHidden: "view-hidden-" 73 }; 74 75 apiPrivate.Commands = { 76 AddAuditCategory: "addAuditCategory", 77 AddAuditResult: "addAuditResult", 78 AddConsoleMessage: "addConsoleMessage", 79 AddRequestHeaders: "addRequestHeaders", 80 CreatePanel: "createPanel", 81 CreateSidebarPane: "createSidebarPane", 82 CreateStatusBarButton: "createStatusBarButton", 83 EvaluateOnInspectedPage: "evaluateOnInspectedPage", 84 GetConsoleMessages: "getConsoleMessages", 85 GetHAR: "getHAR", 86 GetPageResources: "getPageResources", 87 GetRequestContent: "getRequestContent", 88 GetResourceContent: "getResourceContent", 89 Subscribe: "subscribe", 90 SetOpenResourceHandler: "setOpenResourceHandler", 91 SetResourceContent: "setResourceContent", 92 SetSidebarContent: "setSidebarContent", 93 SetSidebarHeight: "setSidebarHeight", 94 SetSidebarPage: "setSidebarPage", 95 ShowPanel: "showPanel", 96 StopAuditCategoryRun: "stopAuditCategoryRun", 97 Unsubscribe: "unsubscribe", 98 UpdateAuditProgress: "updateAuditProgress", 99 UpdateButton: "updateButton", 100 InspectedURLChanged: "inspectedURLChanged" 101 }; 102} 103 104function injectedExtensionAPI(injectedScriptId) 105{ 106 107var apiPrivate = {}; 108 109defineCommonExtensionSymbols(apiPrivate); 110 111var commands = apiPrivate.Commands; 112var events = apiPrivate.Events; 113var userAction = false; 114 115// Here and below, all constructors are private to API implementation. 116// For a public type Foo, if internal fields are present, these are on 117// a private FooImpl type, an instance of FooImpl is used in a closure 118// by Foo consutrctor to re-bind publicly exported members to an instance 119// of Foo. 120 121/** 122 * @constructor 123 */ 124function EventSinkImpl(type, customDispatch) 125{ 126 this._type = type; 127 this._listeners = []; 128 this._customDispatch = customDispatch; 129} 130 131EventSinkImpl.prototype = { 132 addListener: function(callback) 133 { 134 if (typeof callback !== "function") 135 throw "addListener: callback is not a function"; 136 if (this._listeners.length === 0) 137 extensionServer.sendRequest({ command: commands.Subscribe, type: this._type }); 138 this._listeners.push(callback); 139 extensionServer.registerHandler("notify-" + this._type, this._dispatch.bind(this)); 140 }, 141 142 removeListener: function(callback) 143 { 144 var listeners = this._listeners; 145 146 for (var i = 0; i < listeners.length; ++i) { 147 if (listeners[i] === callback) { 148 listeners.splice(i, 1); 149 break; 150 } 151 } 152 if (this._listeners.length === 0) 153 extensionServer.sendRequest({ command: commands.Unsubscribe, type: this._type }); 154 }, 155 156 _fire: function() 157 { 158 var listeners = this._listeners.slice(); 159 for (var i = 0; i < listeners.length; ++i) 160 listeners[i].apply(null, arguments); 161 }, 162 163 _dispatch: function(request) 164 { 165 if (this._customDispatch) 166 this._customDispatch.call(this, request); 167 else 168 this._fire.apply(this, request.arguments); 169 } 170} 171 172/** 173 * @constructor 174 */ 175function InspectorExtensionAPI() 176{ 177 this.audits = new Audits(); 178 this.inspectedWindow = new InspectedWindow(); 179 this.panels = new Panels(); 180 this.network = new Network(); 181 defineDeprecatedProperty(this, "webInspector", "resources", "network"); 182 this.timeline = new Timeline(); 183 this.console = new ConsoleAPI(); 184} 185 186/** 187 * @constructor 188 */ 189InspectorExtensionAPI.prototype = { 190 log: function(message) 191 { 192 extensionServer.sendRequest({ command: commands.Log, message: message }); 193 } 194} 195 196/** 197 * @constructor 198 */ 199function ConsoleAPI() 200{ 201 this.onMessageAdded = new EventSink(events.ConsoleMessageAdded); 202} 203 204ConsoleAPI.prototype = { 205 getMessages: function(callback) 206 { 207 extensionServer.sendRequest({ command: commands.GetConsoleMessages }, callback); 208 }, 209 210 addMessage: function(severity, text, url, line) 211 { 212 extensionServer.sendRequest({ command: commands.AddConsoleMessage, severity: severity, text: text, url: url, line: line }); 213 }, 214 215 get Severity() 216 { 217 return apiPrivate.console.Severity; 218 } 219} 220 221/** 222 * @constructor 223 */ 224function Network() 225{ 226 function dispatchRequestEvent(message) 227 { 228 var request = message.arguments[1]; 229 request.__proto__ = new Request(message.arguments[0]); 230 this._fire(request); 231 } 232 this.onRequestFinished = new EventSink(events.NetworkRequestFinished, dispatchRequestEvent); 233 defineDeprecatedProperty(this, "network", "onFinished", "onRequestFinished"); 234 this.onNavigated = new EventSink(events.InspectedURLChanged); 235} 236 237Network.prototype = { 238 getHAR: function(callback) 239 { 240 function callbackWrapper(result) 241 { 242 var entries = (result && result.entries) || []; 243 for (var i = 0; i < entries.length; ++i) { 244 entries[i].__proto__ = new Request(entries[i]._requestId); 245 delete entries[i]._requestId; 246 } 247 callback(result); 248 } 249 return extensionServer.sendRequest({ command: commands.GetHAR }, callback && callbackWrapper); 250 }, 251 252 addRequestHeaders: function(headers) 253 { 254 return extensionServer.sendRequest({ command: commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname }); 255 } 256} 257 258/** 259 * @constructor 260 */ 261function RequestImpl(id) 262{ 263 this._id = id; 264} 265 266RequestImpl.prototype = { 267 getContent: function(callback) 268 { 269 function callbackWrapper(response) 270 { 271 callback(response.content, response.encoding); 272 } 273 extensionServer.sendRequest({ command: commands.GetRequestContent, id: this._id }, callback && callbackWrapper); 274 } 275} 276 277/** 278 * @constructor 279 */ 280function Panels() 281{ 282 var panels = { 283 elements: new ElementsPanel() 284 }; 285 286 function panelGetter(name) 287 { 288 return panels[name]; 289 } 290 for (var panel in panels) 291 this.__defineGetter__(panel, panelGetter.bind(null, panel)); 292} 293 294Panels.prototype = { 295 create: function(title, icon, page, callback) 296 { 297 var id = "extension-panel-" + extensionServer.nextObjectId(); 298 var request = { 299 command: commands.CreatePanel, 300 id: id, 301 title: title, 302 icon: icon, 303 page: page 304 }; 305 extensionServer.sendRequest(request, callback && callback.bind(this, new ExtensionPanel(id))); 306 }, 307 308 setOpenResourceHandler: function(callback) 309 { 310 var hadHandler = extensionServer.hasHandler(events.OpenResource); 311 312 if (!callback) 313 extensionServer.unregisterHandler(events.OpenResource); 314 else { 315 function callbackWrapper(message) 316 { 317 // Allow the panel to show itself when handling the event. 318 userAction = true; 319 try { 320 callback.call(null, new Resource(message.resource), message.lineNumber); 321 } finally { 322 userAction = false; 323 } 324 } 325 extensionServer.registerHandler(events.OpenResource, callbackWrapper); 326 } 327 // Only send command if we either removed an existing handler or added handler and had none before. 328 if (hadHandler === !callback) 329 extensionServer.sendRequest({ command: commands.SetOpenResourceHandler, "handlerPresent": !!callback }); 330 }, 331 332 get SearchAction() 333 { 334 return apiPrivate.panels.SearchAction; 335 } 336} 337 338/** 339 * @constructor 340 */ 341function ExtensionViewImpl(id) 342{ 343 this._id = id; 344 345 function dispatchShowEvent(message) 346 { 347 var frameIndex = message.arguments[0]; 348 this._fire(window.parent.frames[frameIndex]); 349 } 350 this.onShown = new EventSink(events.ViewShown + id, dispatchShowEvent); 351 this.onHidden = new EventSink(events.ViewHidden + id); 352} 353 354/** 355 * @constructor 356 */ 357function PanelWithSidebarImpl(id) 358{ 359 this._id = id; 360} 361 362PanelWithSidebarImpl.prototype = { 363 createSidebarPane: function(title, callback) 364 { 365 var id = "extension-sidebar-" + extensionServer.nextObjectId(); 366 var request = { 367 command: commands.CreateSidebarPane, 368 panel: this._id, 369 id: id, 370 title: title 371 }; 372 function callbackWrapper() 373 { 374 callback(new ExtensionSidebarPane(id)); 375 } 376 extensionServer.sendRequest(request, callback && callbackWrapper); 377 }, 378 379 __proto__: ExtensionViewImpl.prototype 380} 381 382/** 383 * @constructor 384 * @extends {PanelWithSidebar} 385 */ 386function ElementsPanel() 387{ 388 var id = "elements"; 389 PanelWithSidebar.call(this, id); 390 this.onSelectionChanged = new EventSink(events.ElementsPanelObjectSelected); 391} 392 393/** 394 * @constructor 395 * @extends {ExtensionViewImpl} 396 */ 397function ExtensionPanelImpl(id) 398{ 399 ExtensionViewImpl.call(this, id); 400 this.onSearch = new EventSink(events.PanelSearch + id); 401} 402 403ExtensionPanelImpl.prototype = { 404 createStatusBarButton: function(iconPath, tooltipText, disabled) 405 { 406 var id = "button-" + extensionServer.nextObjectId(); 407 var request = { 408 command: commands.CreateStatusBarButton, 409 panel: this._id, 410 id: id, 411 icon: iconPath, 412 tooltip: tooltipText, 413 disabled: !!disabled 414 }; 415 extensionServer.sendRequest(request); 416 return new Button(id); 417 }, 418 419 show: function() 420 { 421 if (!userAction) 422 return; 423 424 var request = { 425 command: commands.ShowPanel, 426 id: this._id 427 }; 428 extensionServer.sendRequest(request); 429 }, 430 431 __proto__: ExtensionViewImpl.prototype 432} 433 434/** 435 * @constructor 436 * @extends {ExtensionViewImpl} 437 */ 438function ExtensionSidebarPaneImpl(id) 439{ 440 ExtensionViewImpl.call(this, id); 441} 442 443ExtensionSidebarPaneImpl.prototype = { 444 setHeight: function(height) 445 { 446 extensionServer.sendRequest({ command: commands.SetSidebarHeight, id: this._id, height: height }); 447 }, 448 449 setExpression: function(expression, rootTitle, evaluateOptions) 450 { 451 var request = { 452 command: commands.SetSidebarContent, 453 id: this._id, 454 expression: expression, 455 rootTitle: rootTitle, 456 evaluateOnPage: true, 457 }; 458 if (typeof evaluateOptions === "object") 459 request.evaluateOptions = evaluateOptions; 460 extensionServer.sendRequest(request, extractCallbackArgument(arguments)); 461 }, 462 463 setObject: function(jsonObject, rootTitle, callback) 464 { 465 extensionServer.sendRequest({ command: commands.SetSidebarContent, id: this._id, expression: jsonObject, rootTitle: rootTitle }, callback); 466 }, 467 468 setPage: function(page) 469 { 470 extensionServer.sendRequest({ command: commands.SetSidebarPage, id: this._id, page: page }); 471 } 472} 473 474/** 475 * @constructor 476 */ 477function ButtonImpl(id) 478{ 479 this._id = id; 480 this.onClicked = new EventSink(events.ButtonClicked + id); 481} 482 483ButtonImpl.prototype = { 484 update: function(iconPath, tooltipText, disabled) 485 { 486 var request = { 487 command: commands.UpdateButton, 488 id: this._id, 489 icon: iconPath, 490 tooltip: tooltipText, 491 disabled: !!disabled 492 }; 493 extensionServer.sendRequest(request); 494 } 495}; 496 497/** 498 * @constructor 499 */ 500function Audits() 501{ 502} 503 504Audits.prototype = { 505 addCategory: function(displayName, resultCount) 506 { 507 var id = "extension-audit-category-" + extensionServer.nextObjectId(); 508 if (typeof resultCount !== "undefined") 509 console.warn("Passing resultCount to audits.addCategory() is deprecated. Use AuditResult.updateProgress() instead."); 510 extensionServer.sendRequest({ command: commands.AddAuditCategory, id: id, displayName: displayName, resultCount: resultCount }); 511 return new AuditCategory(id); 512 } 513} 514 515/** 516 * @constructor 517 */ 518function AuditCategoryImpl(id) 519{ 520 function dispatchAuditEvent(request) 521 { 522 var auditResult = new AuditResult(request.arguments[0]); 523 try { 524 this._fire(auditResult); 525 } catch (e) { 526 console.error("Uncaught exception in extension audit event handler: " + e); 527 auditResult.done(); 528 } 529 } 530 this._id = id; 531 this.onAuditStarted = new EventSink(events.AuditStarted + id, dispatchAuditEvent); 532} 533 534/** 535 * @constructor 536 */ 537function AuditResultImpl(id) 538{ 539 this._id = id; 540 541 this.createURL = this._nodeFactory.bind(null, "url"); 542 this.createSnippet = this._nodeFactory.bind(null, "snippet"); 543 this.createText = this._nodeFactory.bind(null, "text"); 544 this.createObject = this._nodeFactory.bind(null, "object"); 545 this.createNode = this._nodeFactory.bind(null, "node"); 546} 547 548AuditResultImpl.prototype = { 549 addResult: function(displayName, description, severity, details) 550 { 551 // shorthand for specifying details directly in addResult(). 552 if (details && !(details instanceof AuditResultNode)) 553 details = new AuditResultNode(details instanceof Array ? details : [details]); 554 555 var request = { 556 command: commands.AddAuditResult, 557 resultId: this._id, 558 displayName: displayName, 559 description: description, 560 severity: severity, 561 details: details 562 }; 563 extensionServer.sendRequest(request); 564 }, 565 566 createResult: function() 567 { 568 return new AuditResultNode(Array.prototype.slice.call(arguments)); 569 }, 570 571 updateProgress: function(worked, totalWork) 572 { 573 extensionServer.sendRequest({ command: commands.UpdateAuditProgress, resultId: this._id, progress: worked / totalWork }); 574 }, 575 576 done: function() 577 { 578 extensionServer.sendRequest({ command: commands.StopAuditCategoryRun, resultId: this._id }); 579 }, 580 581 get Severity() 582 { 583 return apiPrivate.audits.Severity; 584 }, 585 586 createResourceLink: function(url, lineNumber) 587 { 588 return { 589 type: "resourceLink", 590 arguments: [url, lineNumber && lineNumber - 1] 591 }; 592 }, 593 594 _nodeFactory: function(type) 595 { 596 return { 597 type: type, 598 arguments: Array.prototype.slice.call(arguments, 1) 599 }; 600 } 601} 602 603/** 604 * @constructor 605 */ 606function AuditResultNode(contents) 607{ 608 this.contents = contents; 609 this.children = []; 610 this.expanded = false; 611} 612 613AuditResultNode.prototype = { 614 addChild: function() 615 { 616 var node = new AuditResultNode(Array.prototype.slice.call(arguments)); 617 this.children.push(node); 618 return node; 619 } 620}; 621 622/** 623 * @constructor 624 */ 625function InspectedWindow() 626{ 627 function dispatchResourceEvent(message) 628 { 629 this._fire(new Resource(message.arguments[0])); 630 } 631 function dispatchResourceContentEvent(message) 632 { 633 this._fire(new Resource(message.arguments[0]), message.arguments[1]); 634 } 635 this.onResourceAdded = new EventSink(events.ResourceAdded, dispatchResourceEvent); 636 this.onResourceContentCommitted = new EventSink(events.ResourceContentCommitted, dispatchResourceContentEvent); 637} 638 639InspectedWindow.prototype = { 640 reload: function(optionsOrUserAgent) 641 { 642 var options = null; 643 if (typeof optionsOrUserAgent === "object") 644 options = optionsOrUserAgent; 645 else if (typeof optionsOrUserAgent === "string") { 646 options = { userAgent: optionsOrUserAgent }; 647 console.warn("Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. " + 648 "Use inspectedWindow.reload({ userAgent: value}) instead."); 649 } 650 return extensionServer.sendRequest({ command: commands.Reload, options: options }); 651 }, 652 653 eval: function(expression, evaluateOptions) 654 { 655 var callback = extractCallbackArgument(arguments); 656 function callbackWrapper(result) 657 { 658 if (result.isError || result.isException) 659 callback(undefined, result); 660 else 661 callback(result.value); 662 } 663 var request = { 664 command: commands.EvaluateOnInspectedPage, 665 expression: expression 666 }; 667 if (typeof evaluateOptions === "object") 668 request.evaluateOptions = evaluateOptions; 669 return extensionServer.sendRequest(request, callback && callbackWrapper); 670 }, 671 672 getResources: function(callback) 673 { 674 function wrapResource(resourceData) 675 { 676 return new Resource(resourceData); 677 } 678 function callbackWrapper(resources) 679 { 680 callback(resources.map(wrapResource)); 681 } 682 return extensionServer.sendRequest({ command: commands.GetPageResources }, callback && callbackWrapper); 683 } 684} 685 686/** 687 * @constructor 688 */ 689function ResourceImpl(resourceData) 690{ 691 this._url = resourceData.url 692 this._type = resourceData.type; 693} 694 695ResourceImpl.prototype = { 696 get url() 697 { 698 return this._url; 699 }, 700 701 get type() 702 { 703 return this._type; 704 }, 705 706 getContent: function(callback) 707 { 708 function callbackWrapper(response) 709 { 710 callback(response.content, response.encoding); 711 } 712 713 return extensionServer.sendRequest({ command: commands.GetResourceContent, url: this._url }, callback && callbackWrapper); 714 }, 715 716 setContent: function(content, commit, callback) 717 { 718 return extensionServer.sendRequest({ command: commands.SetResourceContent, url: this._url, content: content, commit: commit }, callback); 719 } 720} 721 722/** 723 * @constructor 724 */ 725function TimelineImpl() 726{ 727 this.onEventRecorded = new EventSink(events.TimelineEventRecorded); 728} 729 730/** 731 * @constructor 732 */ 733function ExtensionServerClient() 734{ 735 this._callbacks = {}; 736 this._handlers = {}; 737 this._lastRequestId = 0; 738 this._lastObjectId = 0; 739 740 this.registerHandler("callback", this._onCallback.bind(this)); 741 742 var channel = new MessageChannel(); 743 this._port = channel.port1; 744 this._port.addEventListener("message", this._onMessage.bind(this), false); 745 this._port.start(); 746 747 window.parent.postMessage("registerExtension", [ channel.port2 ], "*"); 748} 749 750ExtensionServerClient.prototype = { 751 /** 752 * @param {function()=} callback 753 */ 754 sendRequest: function(message, callback) 755 { 756 if (typeof callback === "function") 757 message.requestId = this._registerCallback(callback); 758 return this._port.postMessage(message); 759 }, 760 761 hasHandler: function(command) 762 { 763 return !!this._handlers[command]; 764 }, 765 766 registerHandler: function(command, handler) 767 { 768 this._handlers[command] = handler; 769 }, 770 771 unregisterHandler: function(command) 772 { 773 delete this._handlers[command]; 774 }, 775 776 nextObjectId: function() 777 { 778 return injectedScriptId + "_" + ++this._lastObjectId; 779 }, 780 781 _registerCallback: function(callback) 782 { 783 var id = ++this._lastRequestId; 784 this._callbacks[id] = callback; 785 return id; 786 }, 787 788 _onCallback: function(request) 789 { 790 if (request.requestId in this._callbacks) { 791 var callback = this._callbacks[request.requestId]; 792 delete this._callbacks[request.requestId]; 793 callback(request.result); 794 } 795 }, 796 797 _onMessage: function(event) 798 { 799 var request = event.data; 800 var handler = this._handlers[request.command]; 801 if (handler) 802 handler.call(this, request); 803 } 804} 805 806function populateInterfaceClass(interface, implementation) 807{ 808 for (var member in implementation) { 809 if (member.charAt(0) === "_") 810 continue; 811 var descriptor = null; 812 // Traverse prototype chain until we find the owner. 813 for (var owner = implementation; owner && !descriptor; owner = owner.__proto__) 814 descriptor = Object.getOwnPropertyDescriptor(owner, member); 815 if (!descriptor) 816 continue; 817 if (typeof descriptor.value === "function") 818 interface[member] = descriptor.value.bind(implementation); 819 else if (typeof descriptor.get === "function") 820 interface.__defineGetter__(member, descriptor.get.bind(implementation)); 821 else 822 Object.defineProperty(interface, member, descriptor); 823 } 824} 825 826function declareInterfaceClass(implConstructor) 827{ 828 return function() 829 { 830 var impl = { __proto__: implConstructor.prototype }; 831 implConstructor.apply(impl, arguments); 832 populateInterfaceClass(this, impl); 833 } 834} 835 836function defineDeprecatedProperty(object, className, oldName, newName) 837{ 838 var warningGiven = false; 839 function getter() 840 { 841 if (!warningGiven) { 842 console.warn(className + "." + oldName + " is deprecated. Use " + className + "." + newName + " instead"); 843 warningGiven = true; 844 } 845 return object[newName]; 846 } 847 object.__defineGetter__(oldName, getter); 848} 849 850function extractCallbackArgument(args) 851{ 852 var lastArgument = args[args.length - 1]; 853 return typeof lastArgument === "function" ? lastArgument : undefined; 854} 855 856var AuditCategory = declareInterfaceClass(AuditCategoryImpl); 857var AuditResult = declareInterfaceClass(AuditResultImpl); 858var Button = declareInterfaceClass(ButtonImpl); 859var EventSink = declareInterfaceClass(EventSinkImpl); 860var ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl); 861var ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl); 862var PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl); 863var Request = declareInterfaceClass(RequestImpl); 864var Resource = declareInterfaceClass(ResourceImpl); 865var Timeline = declareInterfaceClass(TimelineImpl); 866 867// extensionServer is a closure variable defined by the glue below -- make sure we fail if it's not there. 868if (!extensionServer) 869 extensionServer = new ExtensionServerClient(); 870 871return new InspectorExtensionAPI(); 872} 873 874// Default implementation; platforms will override. 875function buildPlatformExtensionAPI(extensionInfo) 876{ 877 function platformExtensionAPI(coreAPI) 878 { 879 window.webInspector = coreAPI; 880 } 881 return platformExtensionAPI.toString(); 882} 883 884 885function buildExtensionAPIInjectedScript(extensionInfo) 886{ 887 return "(function(injectedScriptId){ " + 888 "var extensionServer;" + 889 defineCommonExtensionSymbols.toString() + ";" + 890 injectedExtensionAPI.toString() + ";" + 891 buildPlatformExtensionAPI(extensionInfo) + ";" + 892 "platformExtensionAPI(injectedExtensionAPI(injectedScriptId));" + 893 "return {};" + 894 "})"; 895} 896