Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / devtools.js
blob91fc50ddcd9f9a41fdf1a318fd6673a19e667094
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 (function(window) {
7 // DevToolsAPI ----------------------------------------------------------------
9 /**
10  * @constructor
11  */
12 function DevToolsAPIImpl()
14     /**
15      * @type {number}
16      */
17     this._lastCallId = 0;
19     /**
20      * @type {!Object.<number, function(?Object)>}
21      */
22     this._callbacks = {};
25 DevToolsAPIImpl.prototype = {
26     /**
27      * @param {number} id
28      * @param {?Object} arg
29      */
30     embedderMessageAck: function(id, arg)
31     {
32         var callback = this._callbacks[id];
33         delete this._callbacks[id];
34         if (callback)
35             callback(arg);
36     },
38     /**
39      * @param {string} method
40      * @param {!Array.<*>} args
41      * @param {?function(?Object)} callback
42      */
43     sendMessageToEmbedder: function(method, args, callback)
44     {
45         var callId = ++this._lastCallId;
46         if (callback)
47             this._callbacks[callId] = callback;
48         var message = { "id": callId, "method": method };
49         if (args.length)
50             message.params = args;
51         DevToolsHost.sendMessageToEmbedder(JSON.stringify(message));
52     },
54     /**
55      * @param {string} method
56      * @param {!Array.<*>} args
57      */
58     _dispatchOnInspectorFrontendAPI: function(method, args)
59     {
60         var api = window["InspectorFrontendAPI"];
61         api[method].apply(api, args);
62     },
64     // API methods below this line --------------------------------------------
66     /**
67      * @param {!Array.<!ExtensionDescriptor>} extensions
68      */
69     addExtensions: function(extensions)
70     {
71         // Support for legacy front-ends (<M41).
72         if (window["WebInspector"].addExtensions)
73             window["WebInspector"].addExtensions(extensions);
74         else
75             this._dispatchOnInspectorFrontendAPI("addExtensions", [extensions]);
76     },
78     /**
79      * @param {string} url
80      */
81     appendedToURL: function(url)
82     {
83         this._dispatchOnInspectorFrontendAPI("appendedToURL", [url]);
84     },
86     /**
87      * @param {string} url
88      */
89     canceledSaveURL: function(url)
90     {
91         this._dispatchOnInspectorFrontendAPI("canceledSaveURL", [url]);
92     },
94     contextMenuCleared: function()
95     {
96         this._dispatchOnInspectorFrontendAPI("contextMenuCleared", []);
97     },
99     /**
100      * @param {string} id
101      */
102     contextMenuItemSelected: function(id)
103     {
104         this._dispatchOnInspectorFrontendAPI("contextMenuItemSelected", [id]);
105     },
107     /**
108      * @param {number} count
109      */
110     deviceCountUpdated: function(count)
111     {
112         this._dispatchOnInspectorFrontendAPI("deviceCountUpdated", [count]);
113     },
115     /**
116      * @param {boolean} discoverUsbDevices
117      * @param {boolean} portForwardingEnabled
118      * @param {!Adb.PortForwardingConfig} portForwardingConfig
119      */
120     devicesDiscoveryConfigChanged: function(discoverUsbDevices, portForwardingEnabled, portForwardingConfig)
121     {
122         this._dispatchOnInspectorFrontendAPI("devicesDiscoveryConfigChanged", [discoverUsbDevices, portForwardingEnabled, portForwardingConfig]);
123     },
125     /**
126      * @param {!Array.<!Adb.Device>} devices
127      */
128     devicesUpdated: function(devices)
129     {
130         this._dispatchOnInspectorFrontendAPI("devicesUpdated", [devices]);
131     },
133     /**
134      * @param {string} message
135      */
136     dispatchMessage: function(message)
137     {
138         this._dispatchOnInspectorFrontendAPI("dispatchMessage", [message]);
139     },
141     /**
142      * @param {string} messageChunk
143      * @param {number} messageSize
144      */
145     dispatchMessageChunk: function(messageChunk, messageSize)
146     {
147         this._dispatchOnInspectorFrontendAPI("dispatchMessageChunk", [messageChunk, messageSize]);
148     },
150     enterInspectElementMode: function()
151     {
152         this._dispatchOnInspectorFrontendAPI("enterInspectElementMode", []);
153     },
155     /**
156      * @param {!Array.<!{fileSystemName: string, rootURL: string, fileSystemPath: string}>} fileSystems
157      */
158     fileSystemsLoaded: function(fileSystems)
159     {
160         this._dispatchOnInspectorFrontendAPI("fileSystemsLoaded", [fileSystems]);
161     },
163     /**
164      * @param {string} fileSystemPath
165      */
166     fileSystemRemoved: function(fileSystemPath)
167     {
168         this._dispatchOnInspectorFrontendAPI("fileSystemRemoved", [fileSystemPath]);
169     },
171     /**
172      * @param {string} errorMessage
173      * @param {!{fileSystemName: string, rootURL: string, fileSystemPath: string}} fileSystem
174      */
175     fileSystemAdded: function(errorMessage, fileSystem)
176     {
177         this._dispatchOnInspectorFrontendAPI("fileSystemAdded", [errorMessage, fileSystem]);
178     },
180     /**
181      * @param {number} requestId
182      * @param {string} fileSystemPath
183      * @param {number} totalWork
184      */
185     indexingTotalWorkCalculated: function(requestId, fileSystemPath, totalWork)
186     {
187         this._dispatchOnInspectorFrontendAPI("indexingTotalWorkCalculated", [requestId, fileSystemPath, totalWork]);
188     },
190     /**
191      * @param {number} requestId
192      * @param {string} fileSystemPath
193      * @param {number} worked
194      */
195     indexingWorked: function(requestId, fileSystemPath, worked)
196     {
197         this._dispatchOnInspectorFrontendAPI("indexingWorked", [requestId, fileSystemPath, worked]);
198     },
200     /**
201      * @param {number} requestId
202      * @param {string} fileSystemPath
203      */
204     indexingDone: function(requestId, fileSystemPath)
205     {
206         this._dispatchOnInspectorFrontendAPI("indexingDone", [requestId, fileSystemPath]);
207     },
209     /**
210      * @param {{type: string, keyIdentifier: string, keyCode: number, modifiers: number}} event
211      */
212     keyEventUnhandled: function(event)
213     {
214         this._dispatchOnInspectorFrontendAPI("keyEventUnhandled", [event]);
215     },
217     /**
218      * @param {boolean} hard
219      */
220     reloadInspectedPage: function(hard)
221     {
222         this._dispatchOnInspectorFrontendAPI("reloadInspectedPage", [hard]);
223     },
225     /**
226      * @param {string} url
227      * @param {number} lineNumber
228      * @param {number} columnNumber
229      */
230     revealSourceLine: function(url, lineNumber, columnNumber)
231     {
232         this._dispatchOnInspectorFrontendAPI("revealSourceLine", [url, lineNumber, columnNumber]);
233     },
235     /**
236      * @param {string} url
237      */
238     savedURL: function(url)
239     {
240         this._dispatchOnInspectorFrontendAPI("savedURL", [url]);
241     },
243     /**
244      * @param {number} requestId
245      * @param {string} fileSystemPath
246      * @param {!Array.<string>} files
247      */
248     searchCompleted: function(requestId, fileSystemPath, files)
249     {
250         this._dispatchOnInspectorFrontendAPI("searchCompleted", [requestId, fileSystemPath, files]);
251     },
253     /**
254      * @param {string} tabId
255      */
256     setInspectedTabId: function(tabId)
257     {
258         // Support for legacy front-ends (<M41).
259         if (window["WebInspector"].setInspectedTabId)
260             window["WebInspector"].setInspectedTabId(tabId);
261         else
262             this._dispatchOnInspectorFrontendAPI("setInspectedTabId", [tabId]);
263     },
265     /**
266      * @param {boolean} useSoftMenu
267      */
268     setUseSoftMenu: function(useSoftMenu)
269     {
270         this._dispatchOnInspectorFrontendAPI("setUseSoftMenu", [useSoftMenu]);
271     },
273     showConsole: function()
274     {
275         this._dispatchOnInspectorFrontendAPI("showConsole", []);
276     },
278     /**
279      * @param {number} id
280      * @param {string} chunk
281      */
282     streamWrite: function(id, chunk)
283     {
284         this._dispatchOnInspectorFrontendAPI("streamWrite", [id, chunk]);
285     },
287     frontendAPIAttached: function()
288     {
289         this._dispatchOnInspectorFrontendAPI("frontendAPIAttached", []);
290     },
292     frontendAPIDetached: function()
293     {
294         this._dispatchOnInspectorFrontendAPI("frontendAPIDetached", []);
295     },
297     /**
298      * @param {string} command
299      */
300     dispatchFrontendAPIMessage: function(command)
301     {
302         this._dispatchOnInspectorFrontendAPI("dispatchFrontendAPIMessage", [command]);
303     }
306 var DevToolsAPI = new DevToolsAPIImpl();
307 window.DevToolsAPI = DevToolsAPI;
309 // InspectorFrontendHostImpl --------------------------------------------------
312  * @constructor
313  * @implements {InspectorFrontendHostAPI}
314  */
315 function InspectorFrontendHostImpl()
319 InspectorFrontendHostImpl.prototype = {
320     /**
321      * @override
322      * @return {string}
323      */
324     getSelectionBackgroundColor: function()
325     {
326         return DevToolsHost.getSelectionBackgroundColor();
327     },
329     /**
330      * @override
331      * @return {string}
332      */
333     getSelectionForegroundColor: function()
334     {
335         return DevToolsHost.getSelectionForegroundColor();
336     },
338     /**
339      * @override
340      * @return {string}
341      */
342     platform: function()
343     {
344         return DevToolsHost.platform();
345     },
347     /**
348      * @override
349      */
350     loadCompleted: function()
351     {
352         DevToolsAPI.sendMessageToEmbedder("loadCompleted", [], null);
353     },
355     /**
356      * @override
357      */
358     bringToFront: function()
359     {
360         DevToolsAPI.sendMessageToEmbedder("bringToFront", [], null);
361     },
363     /**
364      * @override
365      */
366     closeWindow: function()
367     {
368         DevToolsAPI.sendMessageToEmbedder("closeWindow", [], null);
369     },
371     /**
372      * @override
373      * @param {boolean} isDocked
374      * @param {function()} callback
375      */
376     setIsDocked: function(isDocked, callback)
377     {
378         DevToolsAPI.sendMessageToEmbedder("setIsDocked", [isDocked], callback);
379     },
381     /**
382      * Requests inspected page to be placed atop of the inspector frontend with specified bounds.
383      * @override
384      * @param {{x: number, y: number, width: number, height: number}} bounds
385      */
386     setInspectedPageBounds: function(bounds)
387     {
388         DevToolsAPI.sendMessageToEmbedder("setInspectedPageBounds", [bounds], null);
389     },
391     /**
392      * @override
393      */
394     inspectElementCompleted: function()
395     {
396         DevToolsAPI.sendMessageToEmbedder("inspectElementCompleted", [], null);
397     },
399     /**
400      * @override
401      * @param {string} url
402      * @param {string} headers
403      * @param {number} streamId
404      * @param {function(!InspectorFrontendHostAPI.LoadNetworkResourceResult)} callback
405      */
406     loadNetworkResource: function(url, headers, streamId, callback)
407     {
408         DevToolsAPI.sendMessageToEmbedder("loadNetworkResource", [url, headers, streamId], /** @type {function(?Object)} */ (callback));
409     },
411     /**
412      * @override
413      * @param {function(!Object<string, string>)} callback
414      */
415     getPreferences: function(callback)
416     {
417         DevToolsAPI.sendMessageToEmbedder("getPreferences", [], /** @type {function(?Object)} */ (callback));
418     },
420     /**
421      * @override
422      * @param {string} name
423      * @param {string} value
424      */
425     setPreference: function(name, value)
426     {
427         DevToolsAPI.sendMessageToEmbedder("setPreference", [name, value], null);
428     },
430     /**
431      * @override
432      * @param {string} name
433      */
434     removePreference: function(name)
435     {
436         DevToolsAPI.sendMessageToEmbedder("removePreference", [name], null);
437     },
439     /**
440      * @override
441      */
442     clearPreferences: function()
443     {
444         DevToolsAPI.sendMessageToEmbedder("clearPreferences", [], null);
445     },
447     /**
448      * @override
449      * @param {string} origin
450      * @param {string} script
451      */
452     setInjectedScriptForOrigin: function(origin, script)
453     {
454         DevToolsHost.setInjectedScriptForOrigin(origin, script);
455     },
457     /**
458      * @override
459      * @param {string} url
460      */
461     inspectedURLChanged: function(url)
462     {
463         DevToolsAPI.sendMessageToEmbedder("inspectedURLChanged", [url], null);
464     },
466     /**
467      * @override
468      * @param {string} text
469      */
470     copyText: function(text)
471     {
472         DevToolsHost.copyText(text);
473     },
475     /**
476      * @override
477      * @param {string} url
478      */
479     openInNewTab: function(url)
480     {
481         DevToolsAPI.sendMessageToEmbedder("openInNewTab", [url], null);
482     },
484     /**
485      * @override
486      * @param {string} url
487      * @param {string} content
488      * @param {boolean} forceSaveAs
489      */
490     save: function(url, content, forceSaveAs)
491     {
492         DevToolsAPI.sendMessageToEmbedder("save", [url, content, forceSaveAs], null);
493     },
495     /**
496      * @override
497      * @param {string} url
498      * @param {string} content
499      */
500     append: function(url, content)
501     {
502         DevToolsAPI.sendMessageToEmbedder("append", [url, content], null);
503     },
505     /**
506      * @override
507      * @param {string} message
508      */
509     sendMessageToBackend: function(message)
510     {
511         DevToolsHost.sendMessageToBackend(message);
512     },
514     /**
515      * @override
516      * @param {string} actionName
517      * @param {number} actionCode
518      * @param {number} bucketSize
519      */
520     recordEnumeratedHistogram: function(actionName, actionCode, bucketSize)
521     {
522         DevToolsAPI.sendMessageToEmbedder("recordEnumeratedHistogram", [actionName, actionCode, bucketSize], null);
523     },
525     /**
526      * @override
527      * @param {string} message
528      */
529     sendFrontendAPINotification: function(message)
530     {
531         DevToolsAPI.sendMessageToEmbedder("sendFrontendAPINotification", [message], null);
532     },
534     /**
535      * @override
536      */
537     requestFileSystems: function()
538     {
539         DevToolsAPI.sendMessageToEmbedder("requestFileSystems", [], null);
540     },
542     /**
543      * @override
544      */
545     addFileSystem: function()
546     {
547         DevToolsAPI.sendMessageToEmbedder("addFileSystem", [], null);
548     },
550     /**
551      * @override
552      * @param {string} fileSystemPath
553      */
554     removeFileSystem: function(fileSystemPath)
555     {
556         DevToolsAPI.sendMessageToEmbedder("removeFileSystem", [fileSystemPath], null);
557     },
559     /**
560      * @override
561      * @param {string} fileSystemId
562      * @param {string} registeredName
563      * @return {?DOMFileSystem}
564      */
565     isolatedFileSystem: function(fileSystemId, registeredName)
566     {
567         return DevToolsHost.isolatedFileSystem(fileSystemId, registeredName);
568     },
570     /**
571      * @override
572      * @param {!FileSystem} fileSystem
573      */
574     upgradeDraggedFileSystemPermissions: function(fileSystem)
575     {
576         DevToolsHost.upgradeDraggedFileSystemPermissions(fileSystem);
577     },
579     /**
580      * @override
581      * @param {number} requestId
582      * @param {string} fileSystemPath
583      */
584     indexPath: function(requestId, fileSystemPath)
585     {
586         DevToolsAPI.sendMessageToEmbedder("indexPath", [requestId, fileSystemPath], null);
587     },
589     /**
590      * @override
591      * @param {number} requestId
592      */
593     stopIndexing: function(requestId)
594     {
595         DevToolsAPI.sendMessageToEmbedder("stopIndexing", [requestId], null);
596     },
598     /**
599      * @override
600      * @param {number} requestId
601      * @param {string} fileSystemPath
602      * @param {string} query
603      */
604     searchInPath: function(requestId, fileSystemPath, query)
605     {
606         DevToolsAPI.sendMessageToEmbedder("searchInPath", [requestId, fileSystemPath, query], null);
607     },
609     /**
610      * @override
611      * @return {number}
612      */
613     zoomFactor: function()
614     {
615         return DevToolsHost.zoomFactor();
616     },
618     /**
619      * @override
620      */
621     zoomIn: function()
622     {
623         DevToolsAPI.sendMessageToEmbedder("zoomIn", [], null);
624     },
626     /**
627      * @override
628      */
629     zoomOut: function()
630     {
631         DevToolsAPI.sendMessageToEmbedder("zoomOut", [], null);
632     },
634     /**
635      * @override
636      */
637     resetZoom: function()
638     {
639         DevToolsAPI.sendMessageToEmbedder("resetZoom", [], null);
640     },
642     /**
643      * @override
644      * @param {string} shortcuts
645      */
646     setWhitelistedShortcuts: function(shortcuts)
647     {
648         DevToolsAPI.sendMessageToEmbedder("setWhitelistedShortcuts", [shortcuts], null);
649     },
651     /**
652      * @override
653      * @return {boolean}
654      */
655     isUnderTest: function()
656     {
657         return DevToolsHost.isUnderTest();
658     },
660     /**
661      * @override
662      * @param {boolean} discoverUsbDevices
663      * @param {boolean} portForwardingEnabled
664      * @param {!Adb.PortForwardingConfig} portForwardingConfig
665      */
666     setDevicesDiscoveryConfig: function(discoverUsbDevices, portForwardingEnabled, portForwardingConfig)
667     {
668         DevToolsAPI.sendMessageToEmbedder("setDevicesDiscoveryConfig", [discoverUsbDevices, portForwardingEnabled, JSON.stringify(portForwardingConfig)], null);
669     },
671     /**
672      * @override
673      * @param {boolean} enabled
674      */
675     setDevicesUpdatesEnabled: function(enabled)
676     {
677         DevToolsAPI.sendMessageToEmbedder("setDevicesUpdatesEnabled", [enabled], null);
678     },
680     /**
681      * @override
682      * @param {string} pageId
683      * @param {string} action
684      */
685     performActionOnRemotePage: function(pageId, action)
686     {
687         DevToolsAPI.sendMessageToEmbedder("performActionOnRemotePage", [pageId, action], null);
688     },
690     /**
691      * @override
692      * @param {number} x
693      * @param {number} y
694      * @param {!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>} items
695      * @param {!Document} document
696      */
697     showContextMenuAtPoint: function(x, y, items, document)
698     {
699         DevToolsHost.showContextMenuAtPoint(x, y, items, document);
700     },
702     /**
703      * @override
704      * @return {boolean}
705      */
706     isHostedMode: function()
707     {
708         return DevToolsHost.isHostedMode();
709     },
711     // Backward-compatible methods below this line --------------------------------------------
713     /**
714      * Support for legacy front-ends (<M41).
715      * @return {string}
716      */
717     port: function()
718     {
719         return "unknown";
720     },
722     /**
723      * Support for legacy front-ends (<M38).
724      * @param {number} zoomFactor
725      */
726     setZoomFactor: function(zoomFactor)
727     {
728     },
730     /**
731      * Support for legacy front-ends (<M34).
732      */
733     sendMessageToEmbedder: function()
734     {
735     },
737     /**
738      * Support for legacy front-ends (<M34).
739      * @param {string} dockSide
740      */
741     requestSetDockSide: function(dockSide)
742     {
743         DevToolsAPI.sendMessageToEmbedder("setIsDocked", [dockSide !== "undocked"], null);
744     },
746     /**
747      * Support for legacy front-ends (<M34).
748      * @return {boolean}
749      */
750     supportsFileSystems: function()
751     {
752         return true;
753     },
755     /**
756      * Support for legacy front-ends (<M28).
757      * @return {boolean}
758      */
759     canInspectWorkers: function()
760     {
761         return true;
762     },
764     /**
765      * Support for legacy front-ends (<M28).
766      * @return {boolean}
767      */
768     canSaveAs: function()
769     {
770         return true;
771     },
773     /**
774      * Support for legacy front-ends (<M28).
775      * @return {boolean}
776      */
777     canSave: function()
778     {
779         return true;
780     },
782     /**
783      * Support for legacy front-ends (<M28).
784      */
785     loaded: function()
786     {
787     },
789     /**
790      * Support for legacy front-ends (<M28).
791      * @return {string}
792      */
793     hiddenPanels: function()
794     {
795         return "";
796     },
798     /**
799      * Support for legacy front-ends (<M28).
800      * @return {string}
801      */
802     localizedStringsURL: function()
803     {
804         return "";
805     },
807     /**
808      * Support for legacy front-ends (<M28).
809      * @param {string} url
810      */
811     close: function(url)
812     {
813     },
815     /**
816      * Support for legacy front-ends (<M44).
817      * @param {number} actionCode
818      */
819     recordActionTaken: function(actionCode)
820     {
821         this.recordEnumeratedHistogram("DevTools.ActionTaken", actionCode, 100);
822     },
824     /**
825      * Support for legacy front-ends (<M44).
826      * @param {number} panelCode
827      */
828     recordPanelShown: function(panelCode)
829     {
830         this.recordEnumeratedHistogram("DevTools.PanelShown", panelCode, 20);
831     }
834 window.InspectorFrontendHost = new InspectorFrontendHostImpl();
836 // DevToolsApp ---------------------------------------------------------------
839  * @suppressGlobalPropertiesCheck
840  */
841 function installBackwardsCompatibility()
843     if (window.location.search.indexOf("remoteFrontend") === -1)
844         return;
846     /**
847      * @this {CSSStyleDeclaration}
848      */
849     function getValue(property)
850     {
851         // Note that |property| comes from another context, so we can't use === here.
852         if (property == "padding-left") {
853             return {
854                 /**
855                  * @suppressReceiverCheck
856                  * @this {Object}
857                  */
858                 getFloatValue: function() { return this.__paddingLeft; },
859                 __paddingLeft: parseFloat(this.paddingLeft)
860             };
861         }
862         throw new Error("getPropertyCSSValue is undefined");
863     }
865     // Support for legacy (<M41) frontends. Remove in M45.
866     window.CSSStyleDeclaration.prototype.getPropertyCSSValue = getValue;
868     function CSSPrimitiveValue()
869     {
870     }
871     CSSPrimitiveValue.CSS_PX = 5;
872     window.CSSPrimitiveValue = CSSPrimitiveValue;
874     // Support for legacy (<M44) frontends. Remove in M48.
875     var styleElement = window.document.createElement("style");
876     styleElement.type = "text/css";
877     styleElement.textContent = "html /deep/ * { min-width: 0; min-height: 0; }";
878     window.document.head.appendChild(styleElement);
881 function windowLoaded()
883     window.removeEventListener("DOMContentLoaded", windowLoaded, false);
884     installBackwardsCompatibility();
887 if (window.document.head && (window.document.readyState === "complete" || window.document.readyState === "interactive"))
888     installBackwardsCompatibility();
889 else
890     window.addEventListener("DOMContentLoaded", windowLoaded, false);
892 // UITests ------------------------------------------------------------------
894 if (window.domAutomationController) {
895     var uiTests = {};
897     uiTests._tryRun = function()
898     {
899         if (uiTests._testSuite && uiTests._pendingTestName) {
900             var name = uiTests._pendingTestName;
901             delete uiTests._pendingTestName;
902             uiTests._testSuite.runTest(name);
903         }
904     }
906     uiTests.runTest = function(name)
907     {
908         uiTests._pendingTestName = name;
909         uiTests._tryRun();
910     };
912     uiTests.testSuiteReady = function(testSuiteConstructor, testBase)
913     {
914         uiTests._testSuite = testSuiteConstructor(window.domAutomationController);
915         uiTests._tryRun();
916     };
918     window.uiTests = uiTests;
921 })(window);