2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
31 function defineCommonExtensionSymbols(apiPrivate
)
33 if (!apiPrivate
.audits
)
34 apiPrivate
.audits
= {};
35 apiPrivate
.audits
.Severity
= {
41 if (!apiPrivate
.panels
)
42 apiPrivate
.panels
= {};
43 apiPrivate
.panels
.SearchAction
= {
44 CancelSearch
: "cancelSearch",
45 PerformSearch
: "performSearch",
46 NextSearchResult
: "nextSearchResult",
47 PreviousSearchResult
: "previousSearchResult"
51 AuditStarted
: "audit-started-",
52 ButtonClicked
: "button-clicked-",
53 PanelObjectSelected
: "panel-objectSelected-",
54 NetworkRequestFinished
: "network-request-finished",
55 OpenResource
: "open-resource",
56 PanelSearch
: "panel-search-",
57 ResourceAdded
: "resource-added",
58 ResourceContentCommitted
: "resource-content-committed",
59 ViewShown
: "view-shown-",
60 ViewHidden
: "view-hidden-"
63 apiPrivate
.Commands
= {
64 AddAuditCategory
: "addAuditCategory",
65 AddAuditResult
: "addAuditResult",
66 AddRequestHeaders
: "addRequestHeaders",
67 ApplyStyleSheet
: "applyStyleSheet",
68 CreatePanel
: "createPanel",
69 CreateSidebarPane
: "createSidebarPane",
70 CreateToolbarButton
: "createToolbarButton",
71 EvaluateOnInspectedPage
: "evaluateOnInspectedPage",
72 ForwardKeyboardEvent
: "_forwardKeyboardEvent",
74 GetPageResources
: "getPageResources",
75 GetRequestContent
: "getRequestContent",
76 GetResourceContent
: "getResourceContent",
77 InspectedURLChanged
: "inspectedURLChanged",
78 OpenResource
: "openResource",
80 Subscribe
: "subscribe",
81 SetOpenResourceHandler
: "setOpenResourceHandler",
82 SetResourceContent
: "setResourceContent",
83 SetSidebarContent
: "setSidebarContent",
84 SetSidebarHeight
: "setSidebarHeight",
85 SetSidebarPage
: "setSidebarPage",
86 ShowPanel
: "showPanel",
87 StopAuditCategoryRun
: "stopAuditCategoryRun",
88 Unsubscribe
: "unsubscribe",
89 UpdateAuditProgress
: "updateAuditProgress",
90 UpdateButton
: "updateButton"
95 * @param {number} injectedScriptId
97 * @suppressGlobalPropertiesCheck
99 function injectedExtensionAPI(injectedScriptId
)
104 defineCommonExtensionSymbols(apiPrivate
);
106 var commands
= apiPrivate
.Commands
;
107 var events
= apiPrivate
.Events
;
108 var userAction
= false;
110 // Here and below, all constructors are private to API implementation.
111 // For a public type Foo, if internal fields are present, these are on
112 // a private FooImpl type, an instance of FooImpl is used in a closure
113 // by Foo consutrctor to re-bind publicly exported members to an instance
119 function EventSinkImpl(type
, customDispatch
)
122 this._listeners
= [];
123 this._customDispatch
= customDispatch
;
126 EventSinkImpl
.prototype = {
127 addListener: function(callback
)
129 if (typeof callback
!== "function")
130 throw "addListener: callback is not a function";
131 if (this._listeners
.length
=== 0)
132 extensionServer
.sendRequest({ command
: commands
.Subscribe
, type
: this._type
});
133 this._listeners
.push(callback
);
134 extensionServer
.registerHandler("notify-" + this._type
, this._dispatch
.bind(this));
137 removeListener: function(callback
)
139 var listeners
= this._listeners
;
141 for (var i
= 0; i
< listeners
.length
; ++i
) {
142 if (listeners
[i
] === callback
) {
143 listeners
.splice(i
, 1);
147 if (this._listeners
.length
=== 0)
148 extensionServer
.sendRequest({ command
: commands
.Unsubscribe
, type
: this._type
});
152 * @param {...} vararg
154 _fire: function(vararg
)
156 var listeners
= this._listeners
.slice();
157 for (var i
= 0; i
< listeners
.length
; ++i
)
158 listeners
[i
].apply(null, arguments
);
161 _dispatch: function(request
)
163 if (this._customDispatch
)
164 this._customDispatch
.call(this, request
);
166 this._fire
.apply(this, request
.arguments
);
173 function InspectorExtensionAPI()
175 this.audits
= new Audits();
176 this.inspectedWindow
= new InspectedWindow();
177 this.panels
= new Panels();
178 this.network
= new Network();
179 defineDeprecatedProperty(this, "webInspector", "resources", "network");
188 * @this {EventSinkImpl}
190 function dispatchRequestEvent(message
)
192 var request
= message
.arguments
[1];
193 request
.__proto__
= new Request(message
.arguments
[0]);
196 this.onRequestFinished
= new EventSink(events
.NetworkRequestFinished
, dispatchRequestEvent
);
197 defineDeprecatedProperty(this, "network", "onFinished", "onRequestFinished");
198 this.onNavigated
= new EventSink(events
.InspectedURLChanged
);
201 Network
.prototype = {
202 getHAR: function(callback
)
204 function callbackWrapper(result
)
206 var entries
= (result
&& result
.entries
) || [];
207 for (var i
= 0; i
< entries
.length
; ++i
) {
208 entries
[i
].__proto__
= new Request(entries
[i
]._requestId
);
209 delete entries
[i
]._requestId
;
213 extensionServer
.sendRequest({ command
: commands
.GetHAR
}, callback
&& callbackWrapper
);
216 addRequestHeaders: function(headers
)
218 extensionServer
.sendRequest({ command
: commands
.AddRequestHeaders
, headers
: headers
, extensionId
: window
.location
.hostname
});
225 function RequestImpl(id
)
230 RequestImpl
.prototype = {
231 getContent: function(callback
)
233 function callbackWrapper(response
)
235 callback(response
.content
, response
.encoding
);
237 extensionServer
.sendRequest({ command
: commands
.GetRequestContent
, id
: this._id
}, callback
&& callbackWrapper
);
247 elements
: new ElementsPanel(),
248 sources
: new SourcesPanel(),
251 function panelGetter(name
)
255 for (var panel
in panels
)
256 this.__defineGetter__(panel
, panelGetter
.bind(null, panel
));
257 this.applyStyleSheet = function(styleSheet
) { extensionServer
.sendRequest({ command
: commands
.ApplyStyleSheet
, styleSheet
: styleSheet
}); };
261 create: function(title
, icon
, page
, callback
)
263 var id
= "extension-panel-" + extensionServer
.nextObjectId();
265 command
: commands
.CreatePanel
,
271 extensionServer
.sendRequest(request
, callback
&& callback
.bind(this, new ExtensionPanel(id
)));
274 setOpenResourceHandler: function(callback
)
276 var hadHandler
= extensionServer
.hasHandler(events
.OpenResource
);
278 function callbackWrapper(message
)
280 // Allow the panel to show itself when handling the event.
283 callback
.call(null, new Resource(message
.resource
), message
.lineNumber
);
290 extensionServer
.unregisterHandler(events
.OpenResource
);
292 extensionServer
.registerHandler(events
.OpenResource
, callbackWrapper
);
294 // Only send command if we either removed an existing handler or added handler and had none before.
295 if (hadHandler
=== !callback
)
296 extensionServer
.sendRequest({ command
: commands
.SetOpenResourceHandler
, "handlerPresent": !!callback
});
299 openResource: function(url
, lineNumber
, callback
)
301 extensionServer
.sendRequest({ command
: commands
.OpenResource
, "url": url
, "lineNumber": lineNumber
}, callback
);
306 return apiPrivate
.panels
.SearchAction
;
313 function ExtensionViewImpl(id
)
318 * @this {EventSinkImpl}
320 function dispatchShowEvent(message
)
322 var frameIndex
= message
.arguments
[0];
323 if (typeof frameIndex
=== "number")
324 this._fire(window
.parent
.frames
[frameIndex
]);
330 this.onShown
= new EventSink(events
.ViewShown
+ id
, dispatchShowEvent
);
331 this.onHidden
= new EventSink(events
.ViewHidden
+ id
);
337 * @extends {ExtensionViewImpl}
338 * @param {string} hostPanelName
340 function PanelWithSidebarImpl(hostPanelName
)
342 ExtensionViewImpl
.call(this, null);
343 this._hostPanelName
= hostPanelName
;
344 this.onSelectionChanged
= new EventSink(events
.PanelObjectSelected
+ hostPanelName
);
347 PanelWithSidebarImpl
.prototype = {
348 createSidebarPane: function(title
, callback
)
350 var id
= "extension-sidebar-" + extensionServer
.nextObjectId();
352 command
: commands
.CreateSidebarPane
,
353 panel
: this._hostPanelName
,
357 function callbackWrapper()
359 callback(new ExtensionSidebarPane(id
));
361 extensionServer
.sendRequest(request
, callback
&& callbackWrapper
);
364 __proto__
: ExtensionViewImpl
.prototype
367 function declareInterfaceClass(implConstructor
)
371 var impl
= { __proto__
: implConstructor
.prototype };
372 implConstructor
.apply(impl
, arguments
);
373 populateInterfaceClass(this, impl
);
377 function defineDeprecatedProperty(object
, className
, oldName
, newName
)
379 var warningGiven
= false;
383 console
.warn(className
+ "." + oldName
+ " is deprecated. Use " + className
+ "." + newName
+ " instead");
386 return object
[newName
];
388 object
.__defineGetter__(oldName
, getter
);
391 function extractCallbackArgument(args
)
393 var lastArgument
= args
[args
.length
- 1];
394 return typeof lastArgument
=== "function" ? lastArgument
: undefined;
397 var AuditCategory
= declareInterfaceClass(AuditCategoryImpl
);
398 var AuditResult
= declareInterfaceClass(AuditResultImpl
);
399 var Button
= declareInterfaceClass(ButtonImpl
);
400 var EventSink
= declareInterfaceClass(EventSinkImpl
);
401 var ExtensionPanel
= declareInterfaceClass(ExtensionPanelImpl
);
402 var ExtensionSidebarPane
= declareInterfaceClass(ExtensionSidebarPaneImpl
);
403 var PanelWithSidebar
= declareInterfaceClass(PanelWithSidebarImpl
);
404 var Request
= declareInterfaceClass(RequestImpl
);
405 var Resource
= declareInterfaceClass(ResourceImpl
);
409 * @extends {PanelWithSidebar}
411 function ElementsPanel()
413 PanelWithSidebar
.call(this, "elements");
416 ElementsPanel
.prototype = {
417 __proto__
: PanelWithSidebar
.prototype
422 * @extends {PanelWithSidebar}
424 function SourcesPanel()
426 PanelWithSidebar
.call(this, "sources");
429 SourcesPanel
.prototype = {
430 __proto__
: PanelWithSidebar
.prototype
435 * @extends {ExtensionViewImpl}
437 function ExtensionPanelImpl(id
)
439 ExtensionViewImpl
.call(this, id
);
440 this.onSearch
= new EventSink(events
.PanelSearch
+ id
);
443 ExtensionPanelImpl
.prototype = {
447 createStatusBarButton: function(iconPath
, tooltipText
, disabled
)
449 var id
= "button-" + extensionServer
.nextObjectId();
451 command
: commands
.CreateToolbarButton
,
455 tooltip
: tooltipText
,
458 extensionServer
.sendRequest(request
);
459 return new Button(id
);
468 command
: commands
.ShowPanel
,
471 extensionServer
.sendRequest(request
);
474 __proto__
: ExtensionViewImpl
.prototype
479 * @extends {ExtensionViewImpl}
481 function ExtensionSidebarPaneImpl(id
)
483 ExtensionViewImpl
.call(this, id
);
486 ExtensionSidebarPaneImpl
.prototype = {
487 setHeight: function(height
)
489 extensionServer
.sendRequest({ command
: commands
.SetSidebarHeight
, id
: this._id
, height
: height
});
492 setExpression: function(expression
, rootTitle
, evaluateOptions
)
495 command
: commands
.SetSidebarContent
,
497 expression
: expression
,
498 rootTitle
: rootTitle
,
499 evaluateOnPage
: true,
501 if (typeof evaluateOptions
=== "object")
502 request
.evaluateOptions
= evaluateOptions
;
503 extensionServer
.sendRequest(request
, extractCallbackArgument(arguments
));
506 setObject: function(jsonObject
, rootTitle
, callback
)
508 extensionServer
.sendRequest({ command
: commands
.SetSidebarContent
, id
: this._id
, expression
: jsonObject
, rootTitle
: rootTitle
}, callback
);
511 setPage: function(page
)
513 extensionServer
.sendRequest({ command
: commands
.SetSidebarPage
, id
: this._id
, page
: page
});
516 __proto__
: ExtensionViewImpl
.prototype
522 function ButtonImpl(id
)
525 this.onClicked
= new EventSink(events
.ButtonClicked
+ id
);
528 ButtonImpl
.prototype = {
529 update: function(iconPath
, tooltipText
, disabled
)
532 command
: commands
.UpdateButton
,
535 tooltip
: tooltipText
,
538 extensionServer
.sendRequest(request
);
551 * @return {!AuditCategory}
553 addCategory: function(displayName
, resultCount
)
555 var id
= "extension-audit-category-" + extensionServer
.nextObjectId();
556 if (typeof resultCount
!== "undefined")
557 console
.warn("Passing resultCount to audits.addCategory() is deprecated. Use AuditResult.updateProgress() instead.");
558 extensionServer
.sendRequest({ command
: commands
.AddAuditCategory
, id
: id
, displayName
: displayName
, resultCount
: resultCount
});
559 return new AuditCategory(id
);
566 function AuditCategoryImpl(id
)
569 * @this {EventSinkImpl}
571 function dispatchAuditEvent(request
)
573 var auditResult
= new AuditResult(request
.arguments
[0]);
575 this._fire(auditResult
);
577 console
.error("Uncaught exception in extension audit event handler: " + e
);
582 this.onAuditStarted
= new EventSink(events
.AuditStarted
+ id
, dispatchAuditEvent
);
588 function AuditResultImpl(id
)
592 this.createURL
= this._nodeFactory
.bind(this, "url");
593 this.createSnippet
= this._nodeFactory
.bind(this, "snippet");
594 this.createText
= this._nodeFactory
.bind(this, "text");
595 this.createObject
= this._nodeFactory
.bind(this, "object");
596 this.createNode
= this._nodeFactory
.bind(this, "node");
599 AuditResultImpl
.prototype = {
600 addResult: function(displayName
, description
, severity
, details
)
602 // shorthand for specifying details directly in addResult().
603 if (details
&& !(details
instanceof AuditResultNode
))
604 details
= new AuditResultNode(Array
.isArray(details
) ? details
: [details
]);
607 command
: commands
.AddAuditResult
,
609 displayName
: displayName
,
610 description
: description
,
614 extensionServer
.sendRequest(request
);
620 createResult: function()
622 return new AuditResultNode(Array
.prototype.slice
.call(arguments
));
625 updateProgress: function(worked
, totalWork
)
627 extensionServer
.sendRequest({ command
: commands
.UpdateAuditProgress
, resultId
: this._id
, progress
: worked
/ totalWork
});
632 extensionServer
.sendRequest({ command
: commands
.StopAuditCategoryRun
, resultId
: this._id
});
636 * @type {!Object.<string, string>}
640 return apiPrivate
.audits
.Severity
;
644 * @return {!{type: string, arguments: !Array.<string|number>}}
646 createResourceLink: function(url
, lineNumber
)
649 type
: "resourceLink",
650 arguments
: [url
, lineNumber
&& lineNumber
- 1]
655 * @return {!{type: string, arguments: !Array.<string|number>}}
657 _nodeFactory: function(type
)
661 arguments
: Array
.prototype.slice
.call(arguments
, 1)
669 function AuditResultNode(contents
)
671 this.contents
= contents
;
673 this.expanded
= false;
676 AuditResultNode
.prototype = {
682 var node
= new AuditResultNode(Array
.prototype.slice
.call(arguments
));
683 this.children
.push(node
);
691 function InspectedWindow()
694 * @this {EventSinkImpl}
696 function dispatchResourceEvent(message
)
698 this._fire(new Resource(message
.arguments
[0]));
702 * @this {EventSinkImpl}
704 function dispatchResourceContentEvent(message
)
706 this._fire(new Resource(message
.arguments
[0]), message
.arguments
[1]);
709 this.onResourceAdded
= new EventSink(events
.ResourceAdded
, dispatchResourceEvent
);
710 this.onResourceContentCommitted
= new EventSink(events
.ResourceContentCommitted
, dispatchResourceContentEvent
);
713 InspectedWindow
.prototype = {
714 reload: function(optionsOrUserAgent
)
717 if (typeof optionsOrUserAgent
=== "object") {
718 options
= optionsOrUserAgent
;
719 } else if (typeof optionsOrUserAgent
=== "string") {
720 options
= { userAgent
: optionsOrUserAgent
};
721 console
.warn("Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. " +
722 "Use inspectedWindow.reload({ userAgent: value}) instead.");
724 extensionServer
.sendRequest({ command
: commands
.Reload
, options
: options
});
730 eval: function(expression
, evaluateOptions
)
732 var callback
= extractCallbackArgument(arguments
);
733 function callbackWrapper(result
)
735 if (result
.isError
|| result
.isException
)
736 callback(undefined, result
);
738 callback(result
.value
);
741 command
: commands
.EvaluateOnInspectedPage
,
742 expression
: expression
744 if (typeof evaluateOptions
=== "object")
745 request
.evaluateOptions
= evaluateOptions
;
746 extensionServer
.sendRequest(request
, callback
&& callbackWrapper
);
750 getResources: function(callback
)
752 function wrapResource(resourceData
)
754 return new Resource(resourceData
);
756 function callbackWrapper(resources
)
758 callback(resources
.map(wrapResource
));
760 extensionServer
.sendRequest({ command
: commands
.GetPageResources
}, callback
&& callbackWrapper
);
767 function ResourceImpl(resourceData
)
769 this._url
= resourceData
.url
;
770 this._type
= resourceData
.type
;
773 ResourceImpl
.prototype = {
784 getContent: function(callback
)
786 function callbackWrapper(response
)
788 callback(response
.content
, response
.encoding
);
791 extensionServer
.sendRequest({ command
: commands
.GetResourceContent
, url
: this._url
}, callback
&& callbackWrapper
);
794 setContent: function(content
, commit
, callback
)
796 extensionServer
.sendRequest({ command
: commands
.SetResourceContent
, url
: this._url
, content
: content
, commit
: commit
}, callback
);
800 var keyboardEventRequestQueue
= [];
801 var forwardTimer
= null;
803 function forwardKeyboardEvent(event
)
805 const Esc
= "U+001B";
806 // We only care about global hotkeys, not about random text
807 if (!event
.ctrlKey
&& !event
.altKey
&& !event
.metaKey
&& !/^F\d+$/.test(event
.keyIdentifier
) && event
.keyIdentifier
!== Esc
)
809 var requestPayload
= {
810 eventType
: event
.type
,
811 ctrlKey
: event
.ctrlKey
,
812 altKey
: event
.altKey
,
813 metaKey
: event
.metaKey
,
814 keyIdentifier
: event
.keyIdentifier
,
815 location
: event
.location
,
816 keyCode
: event
.keyCode
818 keyboardEventRequestQueue
.push(requestPayload
);
820 forwardTimer
= setTimeout(forwardEventQueue
, 0);
823 function forwardEventQueue()
827 command
: commands
.ForwardKeyboardEvent
,
828 entries
: keyboardEventRequestQueue
830 extensionServer
.sendRequest(request
);
831 keyboardEventRequestQueue
= [];
834 document
.addEventListener("keydown", forwardKeyboardEvent
, false);
835 document
.addEventListener("keypress", forwardKeyboardEvent
, false);
840 function ExtensionServerClient()
842 this._callbacks
= {};
844 this._lastRequestId
= 0;
845 this._lastObjectId
= 0;
847 this.registerHandler("callback", this._onCallback
.bind(this));
849 var channel
= new MessageChannel();
850 this._port
= channel
.port1
;
851 this._port
.addEventListener("message", this._onMessage
.bind(this), false);
854 window
.parent
.postMessage("registerExtension", [ channel
.port2
], "*");
857 ExtensionServerClient
.prototype = {
859 * @param {!Object} message
860 * @param {function()=} callback
862 sendRequest: function(message
, callback
)
864 if (typeof callback
=== "function")
865 message
.requestId
= this._registerCallback(callback
);
866 this._port
.postMessage(message
);
872 hasHandler: function(command
)
874 return !!this._handlers
[command
];
877 registerHandler: function(command
, handler
)
879 this._handlers
[command
] = handler
;
882 unregisterHandler: function(command
)
884 delete this._handlers
[command
];
890 nextObjectId: function()
892 return injectedScriptId
.toString() + "_" + ++this._lastObjectId
;
895 _registerCallback: function(callback
)
897 var id
= ++this._lastRequestId
;
898 this._callbacks
[id
] = callback
;
902 _onCallback: function(request
)
904 if (request
.requestId
in this._callbacks
) {
905 var callback
= this._callbacks
[request
.requestId
];
906 delete this._callbacks
[request
.requestId
];
907 callback(request
.result
);
911 _onMessage: function(event
)
913 var request
= event
.data
;
914 var handler
= this._handlers
[request
.command
];
916 handler
.call(this, request
);
920 function populateInterfaceClass(interfaze
, implementation
)
922 for (var member
in implementation
) {
923 if (member
.charAt(0) === "_")
925 var descriptor
= null;
926 // Traverse prototype chain until we find the owner.
927 for (var owner
= implementation
; owner
&& !descriptor
; owner
= owner
.__proto__
)
928 descriptor
= Object
.getOwnPropertyDescriptor(owner
, member
);
931 if (typeof descriptor
.value
=== "function")
932 interfaze
[member
] = descriptor
.value
.bind(implementation
);
933 else if (typeof descriptor
.get === "function")
934 interfaze
.__defineGetter__(member
, descriptor
.get.bind(implementation
));
936 Object
.defineProperty(interfaze
, member
, descriptor
);
940 // extensionServer is a closure variable defined by the glue below -- make sure we fail if it's not there.
941 if (!extensionServer
)
942 extensionServer
= new ExtensionServerClient();
944 return new InspectorExtensionAPI();
948 * @suppress {checkVars, checkTypes}
950 function platformExtensionAPI(coreAPI
)
956 chrome
= window
.chrome
|| {};
957 // Override chrome.devtools as a workaround for a error-throwing getter being exposed
958 // in extension pages loaded into a non-extension process (only happens for remote client
960 var devtools_descriptor
= Object
.getOwnPropertyDescriptor(chrome
, "devtools");
961 if (!devtools_descriptor
|| devtools_descriptor
.get)
962 Object
.defineProperty(chrome
, "devtools", { value
: {}, enumerable
: true });
963 // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
964 chrome
.devtools
.inspectedWindow
= {};
965 chrome
.devtools
.inspectedWindow
.__defineGetter__("tabId", getTabId
);
966 chrome
.devtools
.inspectedWindow
.__proto__
= coreAPI
.inspectedWindow
;
967 chrome
.devtools
.network
= coreAPI
.network
;
968 chrome
.devtools
.panels
= coreAPI
.panels
;
970 // default to expose experimental APIs for now.
971 if (extensionInfo
.exposeExperimentalAPIs
!== false) {
972 chrome
.experimental
= chrome
.experimental
|| {};
973 chrome
.experimental
.devtools
= chrome
.experimental
.devtools
|| {};
975 var properties
= Object
.getOwnPropertyNames(coreAPI
);
976 for (var i
= 0; i
< properties
.length
; ++i
) {
977 var descriptor
= Object
.getOwnPropertyDescriptor(coreAPI
, properties
[i
]);
978 Object
.defineProperty(chrome
.experimental
.devtools
, properties
[i
], descriptor
);
980 chrome
.experimental
.devtools
.inspectedWindow
= chrome
.devtools
.inspectedWindow
;
982 if (extensionInfo
.exposeWebInspectorNamespace
)
983 window
.webInspector
= coreAPI
;
987 * @param {!ExtensionDescriptor} extensionInfo
988 * @param {string} inspectedTabId
991 function buildPlatformExtensionAPI(extensionInfo
, inspectedTabId
)
993 return "var extensionInfo = " + JSON
.stringify(extensionInfo
) + ";" +
994 "var tabId = " + inspectedTabId
+ ";" +
995 platformExtensionAPI
.toString();
999 * @param {!ExtensionDescriptor} extensionInfo
1000 * @param {string} inspectedTabId
1003 function buildExtensionAPIInjectedScript(extensionInfo
, inspectedTabId
)
1005 return "(function(injectedScriptId){ " +
1006 "var extensionServer;" +
1007 defineCommonExtensionSymbols
.toString() + ";" +
1008 injectedExtensionAPI
.toString() + ";" +
1009 buildPlatformExtensionAPI(extensionInfo
, inspectedTabId
) + ";" +
1010 "platformExtensionAPI(injectedExtensionAPI(injectedScriptId));" +