040c995cc7b2fb34afa8f95b46c2ba88513dcb38
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / main / Main.js
1 /*
2  * Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
3  * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
4  * Copyright (C) 2009 Joseph Pecoraro
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 /**
32  * @constructor
33  * @implements {InspectorAgent.Dispatcher}
34  */
35 WebInspector.Main = function()
36 {
37     var boundListener = windowLoaded.bind(this);
38
39     /**
40      * @this {WebInspector.Main}
41      */
42     function windowLoaded()
43     {
44         this._loaded();
45         window.removeEventListener("DOMContentLoaded", boundListener, false);
46     }
47     window.addEventListener("DOMContentLoaded", boundListener, false);
48 }
49
50 WebInspector.Main.prototype = {
51     _createGlobalStatusBarItems: function()
52     {
53         var extensions = self.runtime.extensions(WebInspector.StatusBarItem.Provider);
54
55         /**
56          * @param {!Runtime.Extension} left
57          * @param {!Runtime.Extension} right
58          */
59         function orderComparator(left, right)
60         {
61             return left.descriptor()["order"] - right.descriptor()["order"];
62         }
63         extensions.sort(orderComparator);
64         extensions.forEach(function(extension) {
65             var item;
66             switch (extension.descriptor()["location"]) {
67             case "toolbar-left":
68                 item = createItem(extension);
69                 if (item)
70                     WebInspector.inspectorView.appendToLeftToolbar(item);
71                 break;
72             case "toolbar-right":
73                 item = createItem(extension);
74                 if (item)
75                     WebInspector.inspectorView.appendToRightToolbar(item);
76                 break;
77             }
78             if (item && extension.descriptor()["actionId"]) {
79                 item.addEventListener("click", function() {
80                     WebInspector.actionRegistry.execute(extension.descriptor()["actionId"]);
81                 });
82             }
83         });
84
85         function createItem(extension)
86         {
87             var descriptor = extension.descriptor();
88             if (descriptor.className)
89                 return extension.instance().item();
90             return new WebInspector.StatusBarButton(WebInspector.UIString(descriptor["title"]), descriptor["elementClass"]);
91         }
92     },
93
94     _calculateWorkerInspectorTitle: function()
95     {
96         var expression = "location.href";
97         if (WebInspector.queryParam("isSharedWorker"))
98             expression += " + (this.name ? ' (' + this.name + ')' : '')";
99         RuntimeAgent.invoke_evaluate({expression:expression, doNotPauseOnExceptionsAndMuteConsole:true, returnByValue: true}, evalCallback);
100
101         /**
102          * @param {?Protocol.Error} error
103          * @param {!RuntimeAgent.RemoteObject} result
104          * @param {boolean=} wasThrown
105          */
106         function evalCallback(error, result, wasThrown)
107         {
108             if (error || wasThrown) {
109                 console.error(error);
110                 return;
111             }
112             InspectorFrontendHost.inspectedURLChanged(String(result.value));
113         }
114     },
115
116     _loadCompletedForWorkers: function()
117     {
118         // Make sure script execution of dedicated worker or service worker is
119         // resumed and then paused on the first script statement in case we
120         // autoattached to it.
121         if (WebInspector.queryParam("workerPaused")) {
122             pauseAndResume.call(this);
123         } else{
124             RuntimeAgent.isRunRequired(isRunRequiredCallback.bind(this));
125         }
126
127         /**
128          * @this {WebInspector.Main}
129          */
130         function isRunRequiredCallback(error, result)
131         {
132             if (result) {
133                 pauseAndResume.call(this);
134             } else if (WebInspector.isWorkerFrontend()) {
135                 calculateTitle.call(this);
136             }
137         }
138
139         /**
140          * @this {WebInspector.Main}
141          */
142         function pauseAndResume()
143         {
144             DebuggerAgent.pause();
145             RuntimeAgent.run(calculateTitle.bind(this));
146         }
147
148         /**
149          * @this {WebInspector.Main}
150          */
151         function calculateTitle()
152         {
153             this._calculateWorkerInspectorTitle();
154         }
155     },
156
157     _loaded: function()
158     {
159         console.timeStamp("Main._loaded");
160
161         // FIXME: Make toolbox a real app.
162         if (WebInspector.queryParam("toolbox")) {
163             new WebInspector.Toolbox();
164             return;
165         }
166
167         this._createSettings();
168         this._createModuleManager();
169         this._createAppUI();
170     },
171
172     _createSettings: function()
173     {
174         WebInspector.settings = new WebInspector.Settings();
175         WebInspector.experimentsSettings = new WebInspector.ExperimentsSettings(WebInspector.queryParam("experiments") !== null);
176         // This setting is needed for backwards compatibility with Devtools CodeSchool extension. DO NOT REMOVE
177         WebInspector.settings.pauseOnExceptionStateString = new WebInspector.PauseOnExceptionStateSetting();
178         new WebInspector.VersionController().updateVersion();
179     },
180
181     _createModuleManager: function()
182     {
183         console.timeStamp("Main._createModuleManager");
184         self.runtime = new Runtime(allDescriptors);
185
186         // FIXME: define html-per-app, make configuration a part of the app.
187         var configuration = ["main", "elements", "network", "sources", "timeline", "profiler", "resources", "audits", "console", "source_frame", "extensions", "settings"];
188         if (WebInspector.experimentsSettings.layersPanel.isEnabled())
189             configuration.push("layers");
190         if (WebInspector.experimentsSettings.devicesPanel.isEnabled() && !!WebInspector.queryParam("can_dock"))
191             configuration.push("devices");
192         if (WebInspector.experimentsSettings.documentation.isEnabled())
193             configuration.push("documentation");
194         if (WebInspector.isWorkerFrontend())
195             configuration = ["main", "sources", "timeline", "profiler", "console", "source_frame", "extensions"];
196         self.runtime.registerModules(configuration);
197     },
198
199     _createAppUI: function()
200     {
201         console.timeStamp("Main._createApp");
202
203         WebInspector.installPortStyles();
204         if (WebInspector.queryParam("toolbarColor") && WebInspector.queryParam("textColor"))
205             WebInspector.setToolbarColors(WebInspector.queryParam("toolbarColor"), WebInspector.queryParam("textColor"));
206         InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.SetToolbarColors, updateToolbarColors);
207         /**
208          * @param {!WebInspector.Event} event
209          */
210         function updateToolbarColors(event)
211         {
212             WebInspector.setToolbarColors(/** @type {string} */ (event.data["backgroundColor"]), /** @type {string} */ (event.data["color"]));
213         }
214
215         var canDock = !!WebInspector.queryParam("can_dock");
216         WebInspector.zoomManager = new WebInspector.ZoomManager(InspectorFrontendHost);
217         WebInspector.inspectorView = new WebInspector.InspectorView();
218         WebInspector.ContextMenu.initialize();
219         WebInspector.dockController = new WebInspector.DockController(canDock);
220         WebInspector.overridesSupport = new WebInspector.OverridesSupport(canDock);
221         WebInspector.multitargetConsoleModel = new WebInspector.MultitargetConsoleModel();
222
223         WebInspector.shortcutsScreen = new WebInspector.ShortcutsScreen();
224         // set order of some sections explicitly
225         WebInspector.shortcutsScreen.section(WebInspector.UIString("Console"));
226         WebInspector.shortcutsScreen.section(WebInspector.UIString("Elements Panel"));
227
228         if (canDock)
229             WebInspector.app = new WebInspector.AdvancedApp();
230         else if (WebInspector.queryParam("remoteFrontend"))
231             WebInspector.app = new WebInspector.ScreencastApp();
232         else
233             WebInspector.app = new WebInspector.SimpleApp();
234
235         // It is important to kick controller lifetime after apps are instantiated.
236         WebInspector.dockController.initialize();
237         WebInspector.app.createRootView();
238
239         // Give UI cycles to repaint, then proceed with creating connection.
240         setTimeout(this._createConnection.bind(this), 0);
241     },
242
243     _createConnection: function()
244     {
245         console.timeStamp("Main._createConnection");
246         InspectorBackend.loadFromJSONIfNeeded("../protocol.json");
247
248         var workerId = WebInspector.queryParam("dedicatedWorkerId");
249         if (workerId) {
250             this._connectionEstablished(new WebInspector.ExternalWorkerConnection(workerId));
251             return;
252         }
253
254         if (WebInspector.queryParam("ws")) {
255             var ws = "ws://" + WebInspector.queryParam("ws");
256             InspectorBackendClass.WebSocketConnection.Create(ws, this._connectionEstablished.bind(this));
257             return;
258         }
259
260         if (!InspectorFrontendHost.isHostedMode()) {
261             this._connectionEstablished(new InspectorBackendClass.MainConnection());
262             return;
263         }
264
265         this._connectionEstablished(new InspectorBackendClass.StubConnection());
266     },
267
268     /**
269      * @param {!InspectorBackendClass.Connection} connection
270      */
271     _connectionEstablished: function(connection)
272     {
273         console.timeStamp("Main._connectionEstablished");
274         connection.addEventListener(InspectorBackendClass.Connection.Events.Disconnected, onDisconnected);
275
276         /**
277          * @param {!WebInspector.Event} event
278          */
279         function onDisconnected(event)
280         {
281             if (WebInspector._disconnectedScreenWithReasonWasShown)
282                 return;
283             new WebInspector.RemoteDebuggingTerminatedScreen(event.data.reason).showModal();
284         }
285
286         InspectorBackend.setConnection(connection);
287
288         // Install styles and themes
289         WebInspector.installPortStyles();
290
291         if (WebInspector.queryParam("toolbarColor") && WebInspector.queryParam("textColor"))
292             WebInspector.setToolbarColors(WebInspector.queryParam("toolbarColor"), WebInspector.queryParam("textColor"));
293         InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.SetToolbarColors, updateToolbarColors);
294         /**
295          * @param {!WebInspector.Event} event
296          */
297         function updateToolbarColors(event)
298         {
299             WebInspector.setToolbarColors(/** @type {string} */ (event.data["backgroundColor"]), /** @type {string} */ (event.data["color"]));
300         }
301         WebInspector.ContextMenu.initialize();
302         WebInspector.targetManager.createTarget(WebInspector.UIString("Main"), connection, this._mainTargetCreated.bind(this));
303         WebInspector.isolatedFileSystemManager = new WebInspector.IsolatedFileSystemManager();
304         WebInspector.workspace = new WebInspector.Workspace(WebInspector.isolatedFileSystemManager.mapping());
305         WebInspector.networkWorkspaceBinding = new WebInspector.NetworkWorkspaceBinding(WebInspector.workspace);
306         new WebInspector.NetworkUISourceCodeProvider(WebInspector.networkWorkspaceBinding, WebInspector.workspace);
307         new WebInspector.PresentationConsoleMessageHelper(WebInspector.workspace);
308         WebInspector.cssWorkspaceBinding = new WebInspector.CSSWorkspaceBinding();
309         WebInspector.debuggerWorkspaceBinding = new WebInspector.DebuggerWorkspaceBinding(WebInspector.targetManager, WebInspector.workspace, WebInspector.networkWorkspaceBinding);
310         WebInspector.fileSystemWorkspaceBinding = new WebInspector.FileSystemWorkspaceBinding(WebInspector.isolatedFileSystemManager, WebInspector.workspace);
311         WebInspector.breakpointManager = new WebInspector.BreakpointManager(WebInspector.settings.breakpoints, WebInspector.workspace, WebInspector.targetManager, WebInspector.debuggerWorkspaceBinding);
312         WebInspector.scriptSnippetModel = new WebInspector.ScriptSnippetModel(WebInspector.workspace);
313         this._executionContextSelector = new WebInspector.ExecutionContextSelector();
314
315         if (!WebInspector.isWorkerFrontend())
316             WebInspector.inspectElementModeController = new WebInspector.InspectElementModeController();
317         this._createGlobalStatusBarItems();
318     },
319
320     /**
321      * @param {!WebInspector.Target} mainTarget
322      */
323     _mainTargetCreated: function(mainTarget)
324     {
325         console.timeStamp("Main._mainTargetCreated");
326
327         this._registerShortcuts();
328
329         WebInspector.workerTargetManager = new WebInspector.WorkerTargetManager(mainTarget, WebInspector.targetManager);
330
331         InspectorBackend.registerInspectorDispatcher(this);
332
333         if (WebInspector.isWorkerFrontend())
334             mainTarget.workerManager.addEventListener(WebInspector.WorkerManager.Events.WorkerDisconnected, onWorkerDisconnected);
335
336         function onWorkerDisconnected()
337         {
338             var screen = new WebInspector.WorkerTerminatedScreen();
339             var listener = hideScreen.bind(null, screen);
340             mainTarget.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, listener);
341
342             /**
343              * @param {!WebInspector.WorkerTerminatedScreen} screen
344              */
345             function hideScreen(screen)
346             {
347                 mainTarget.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, listener);
348                 screen.hide();
349             }
350
351             screen.showModal();
352         }
353
354         WebInspector.domBreakpointsSidebarPane = new WebInspector.DOMBreakpointsSidebarPane();
355         var autoselectPanel = WebInspector.UIString("a panel chosen automatically");
356         var openAnchorLocationSetting = WebInspector.settings.createSetting("openLinkHandler", autoselectPanel);
357         WebInspector.openAnchorLocationRegistry = new WebInspector.HandlerRegistry(openAnchorLocationSetting);
358         WebInspector.openAnchorLocationRegistry.registerHandler(autoselectPanel, function() { return false; });
359         WebInspector.Linkifier.setLinkHandler(new WebInspector.HandlerRegistry.LinkHandler());
360         new WebInspector.WorkspaceController(WebInspector.workspace);
361         new WebInspector.RenderingOptions();
362         new WebInspector.Main.PauseListener();
363         new WebInspector.Main.InspectedNodeRevealer();
364
365         this._addMainEventListeners(document);
366
367         WebInspector.extensionServerProxy.setFrontendReady();
368
369         InspectorAgent.enable(inspectorAgentEnableCallback);
370
371         function inspectorAgentEnableCallback()
372         {
373             console.timeStamp("Main.inspectorAgentEnableCallback");
374             WebInspector.app.presentUI(mainTarget);
375             console.timeStamp("Main.inspectorAgentEnableCallbackPresentUI");
376             WebInspector.notifications.dispatchEventToListeners(WebInspector.NotificationService.Events.InspectorUILoadedForTests);
377         }
378
379         WebInspector.actionRegistry = new WebInspector.ActionRegistry();
380         WebInspector.shortcutRegistry = new WebInspector.ShortcutRegistry(WebInspector.actionRegistry);
381         WebInspector.ShortcutsScreen.registerShortcuts();
382         this._registerForwardedShortcuts();
383         this._registerMessageSinkListener();
384
385         this._loadCompletedForWorkers();
386         InspectorFrontendAPI.loadCompleted();
387     },
388
389     _registerForwardedShortcuts: function()
390     {
391         /** @const */ var forwardedActions = ["main.reload", "main.hard-reload"];
392         var actionKeys = WebInspector.shortcutRegistry.keysForActions(forwardedActions).map(WebInspector.KeyboardShortcut.keyCodeAndModifiersFromKey);
393
394         actionKeys.push({keyCode: WebInspector.KeyboardShortcut.Keys.F8.code});
395         InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys));
396     },
397
398     _registerMessageSinkListener: function()
399     {
400         WebInspector.console.addEventListener(WebInspector.Console.Events.MessageAdded, messageAdded);
401
402         /**
403          * @param {!WebInspector.Event} event
404          */
405         function messageAdded(event)
406         {
407             var message = /** @type {!WebInspector.Console.Message} */ (event.data);
408             if (message.show)
409                 WebInspector.console.show();
410         }
411     },
412
413     _documentClick: function(event)
414     {
415         var anchor = event.target.enclosingNodeOrSelfWithNodeName("a");
416         if (!anchor || !anchor.href)
417             return;
418
419         // Prevent the link from navigating, since we don't do any navigation by following links normally.
420         event.consume(true);
421
422         if (anchor.target === "_blank") {
423             InspectorFrontendHost.openInNewTab(anchor.href);
424             return;
425         }
426
427         function followLink()
428         {
429             if (WebInspector.isBeingEdited(event.target))
430                 return;
431             if (WebInspector.openAnchorLocationRegistry.dispatch({ url: anchor.href, lineNumber: anchor.lineNumber}))
432                 return;
433
434             var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(anchor.href);
435             if (uiSourceCode) {
436                 WebInspector.Revealer.reveal(uiSourceCode.uiLocation(anchor.lineNumber || 0, anchor.columnNumber || 0));
437                 return;
438             }
439
440             var resource = WebInspector.resourceForURL(anchor.href);
441             if (resource) {
442                 WebInspector.Revealer.reveal(resource);
443                 return;
444             }
445
446             var request = WebInspector.networkLog.requestForURL(anchor.href);
447             if (request) {
448                 WebInspector.Revealer.reveal(request);
449                 return;
450             }
451             InspectorFrontendHost.openInNewTab(anchor.href);
452         }
453
454         if (WebInspector.followLinkTimeout)
455             clearTimeout(WebInspector.followLinkTimeout);
456
457         if (anchor.preventFollowOnDoubleClick) {
458             // Start a timeout if this is the first click, if the timeout is canceled
459             // before it fires, then a double clicked happened or another link was clicked.
460             if (event.detail === 1)
461                 WebInspector.followLinkTimeout = setTimeout(followLink, 333);
462             return;
463         }
464
465         followLink();
466     },
467
468     _registerShortcuts: function()
469     {
470         var shortcut = WebInspector.KeyboardShortcut;
471         var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("All Panels"));
472         var keys = [
473             shortcut.makeDescriptor("[", shortcut.Modifiers.CtrlOrMeta),
474             shortcut.makeDescriptor("]", shortcut.Modifiers.CtrlOrMeta)
475         ];
476         section.addRelatedKeys(keys, WebInspector.UIString("Go to the panel to the left/right"));
477
478         keys = [
479             shortcut.makeDescriptor("[", shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Alt),
480             shortcut.makeDescriptor("]", shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Alt)
481         ];
482         section.addRelatedKeys(keys, WebInspector.UIString("Go back/forward in panel history"));
483
484         var toggleConsoleLabel = WebInspector.UIString("Show console");
485         section.addKey(shortcut.makeDescriptor(shortcut.Keys.Tilde, shortcut.Modifiers.Ctrl), toggleConsoleLabel);
486         section.addKey(shortcut.makeDescriptor(shortcut.Keys.Esc), WebInspector.UIString("Toggle drawer"));
487         if (WebInspector.overridesSupport.responsiveDesignAvailable())
488             section.addKey(shortcut.makeDescriptor("M", shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift), WebInspector.UIString("Toggle device mode"));
489         section.addKey(shortcut.makeDescriptor("f", shortcut.Modifiers.CtrlOrMeta), WebInspector.UIString("Search"));
490
491         var advancedSearchShortcutModifier = WebInspector.isMac()
492                 ? WebInspector.KeyboardShortcut.Modifiers.Meta | WebInspector.KeyboardShortcut.Modifiers.Alt
493                 : WebInspector.KeyboardShortcut.Modifiers.Ctrl | WebInspector.KeyboardShortcut.Modifiers.Shift;
494         var advancedSearchShortcut = shortcut.makeDescriptor("f", advancedSearchShortcutModifier);
495         section.addKey(advancedSearchShortcut, WebInspector.UIString("Search across all sources"));
496
497         var inspectElementModeShortcut = WebInspector.InspectElementModeController.createShortcut();
498         section.addKey(inspectElementModeShortcut, WebInspector.UIString("Select node to inspect"));
499
500         var openResourceShortcut = WebInspector.KeyboardShortcut.makeDescriptor("p", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta);
501         section.addKey(openResourceShortcut, WebInspector.UIString("Go to source"));
502
503         if (WebInspector.isMac()) {
504             keys = [
505                 shortcut.makeDescriptor("g", shortcut.Modifiers.Meta),
506                 shortcut.makeDescriptor("g", shortcut.Modifiers.Meta | shortcut.Modifiers.Shift)
507             ];
508             section.addRelatedKeys(keys, WebInspector.UIString("Find next/previous"));
509         }
510     },
511
512     _postDocumentKeyDown: function(event)
513     {
514         if (event.handled)
515             return;
516
517         if (!WebInspector.Dialog.currentInstance() && WebInspector.inspectorView.currentPanel()) {
518             WebInspector.inspectorView.currentPanel().handleShortcut(event);
519             if (event.handled) {
520                 event.consume(true);
521                 return;
522             }
523         }
524
525         WebInspector.shortcutRegistry.handleShortcut(event);
526     },
527
528     _documentCanCopy: function(event)
529     {
530         var panel = WebInspector.inspectorView.currentPanel();
531         if (panel && panel["handleCopyEvent"])
532             event.preventDefault();
533     },
534
535     _documentCopy: function(event)
536     {
537         var panel = WebInspector.inspectorView.currentPanel();
538         if (panel && panel["handleCopyEvent"])
539             panel["handleCopyEvent"](event);
540     },
541
542     _documentCut: function(event)
543     {
544         var panel = WebInspector.inspectorView.currentPanel();
545         if (panel && panel["handleCutEvent"])
546             panel["handleCutEvent"](event);
547     },
548
549     _documentPaste: function(event)
550     {
551         var panel = WebInspector.inspectorView.currentPanel();
552         if (panel && panel["handlePasteEvent"])
553             panel["handlePasteEvent"](event);
554     },
555
556     _contextMenuEventFired: function(event)
557     {
558         if (event.handled || event.target.classList.contains("popup-glasspane"))
559             event.preventDefault();
560     },
561
562     _addMainEventListeners: function(doc)
563     {
564         doc.addEventListener("keydown", this._postDocumentKeyDown.bind(this), false);
565         doc.addEventListener("beforecopy", this._documentCanCopy.bind(this), true);
566         doc.addEventListener("copy", this._documentCopy.bind(this), false);
567         doc.addEventListener("cut", this._documentCut.bind(this), false);
568         doc.addEventListener("paste", this._documentPaste.bind(this), false);
569         doc.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);
570         doc.addEventListener("click", this._documentClick.bind(this), false);
571     },
572
573     /**
574      * @override
575      * @param {!RuntimeAgent.RemoteObject} payload
576      * @param {!Object=} hints
577      */
578     inspect: function(payload, hints)
579     {
580         var object = WebInspector.runtimeModel.createRemoteObject(payload);
581         if (object.isNode()) {
582             var nodeObjectInspector = runtime.instance(WebInspector.NodeRemoteObjectInspector, object);
583             if (nodeObjectInspector)
584                 nodeObjectInspector.inspectNodeObject(object);
585             return;
586         }
587
588         if (object.type === "function") {
589             object.functionDetails(didGetDetails);
590             return;
591         }
592
593         /**
594          * @param {?WebInspector.DebuggerModel.FunctionDetails} response
595          */
596         function didGetDetails(response)
597         {
598             object.release();
599
600             if (!response || !response.location)
601                 return;
602
603             WebInspector.Revealer.reveal(WebInspector.debuggerWorkspaceBinding.rawLocationToUILocation(response.location));
604         }
605
606         if (hints.copyToClipboard)
607             InspectorFrontendHost.copyText(object.value);
608         object.release();
609     },
610
611     /**
612      * @override
613      * @param {string} reason
614      */
615     detached: function(reason)
616     {
617         WebInspector._disconnectedScreenWithReasonWasShown = true;
618         new WebInspector.RemoteDebuggingTerminatedScreen(reason).showModal();
619     },
620
621     /**
622      * @override
623      */
624     targetCrashed: function()
625     {
626         (new WebInspector.HelpScreenUntilReload(
627             WebInspector.UIString("Inspected target crashed"),
628             WebInspector.UIString("Inspected target has crashed. Once it reloads we will attach to it automatically."))).showModal();
629     },
630
631     /**
632      * @override
633      * @param {number} callId
634      * @param {string} script
635      */
636     evaluateForTestInFrontend: function(callId, script)
637     {
638         WebInspector.evaluateForTestInFrontend(callId, script);
639     }
640 }
641
642 WebInspector.reload = function()
643 {
644     InspectorAgent.reset();
645     window.location.reload();
646 }
647
648 /**
649  * @constructor
650  * @implements {WebInspector.ActionDelegate}
651  */
652 WebInspector.Main.ReloadActionDelegate = function()
653 {
654 }
655
656 WebInspector.Main.ReloadActionDelegate.prototype = {
657     /**
658      * @return {boolean}
659      */
660     handleAction: function()
661     {
662         WebInspector.debuggerModel.skipAllPauses(true, true);
663         WebInspector.resourceTreeModel.reloadPage(false);
664         return true;
665     }
666 }
667
668 /**
669  * @constructor
670  * @implements {WebInspector.ActionDelegate}
671  */
672 WebInspector.Main.HardReloadActionDelegate = function()
673 {
674 }
675
676 WebInspector.Main.HardReloadActionDelegate.prototype = {
677     /**
678      * @return {boolean}
679      */
680     handleAction: function()
681     {
682         WebInspector.debuggerModel.skipAllPauses(true, true);
683         WebInspector.resourceTreeModel.reloadPage(true);
684         return true;
685     }
686 }
687
688 /**
689  * @constructor
690  * @implements {WebInspector.ActionDelegate}
691  */
692 WebInspector.Main.DebugReloadActionDelegate = function()
693 {
694 }
695
696 WebInspector.Main.DebugReloadActionDelegate.prototype = {
697     /**
698      * @return {boolean}
699      */
700     handleAction: function()
701     {
702         WebInspector.reload();
703         return true;
704     }
705 }
706
707 /**
708  * @constructor
709  * @implements {WebInspector.ActionDelegate}
710  */
711 WebInspector.Main.ZoomInActionDelegate = function()
712 {
713 }
714
715 WebInspector.Main.ZoomInActionDelegate.prototype = {
716     /**
717      * @return {boolean}
718      */
719     handleAction: function()
720     {
721         if (InspectorFrontendHost.isHostedMode())
722             return false;
723
724         InspectorFrontendHost.zoomIn();
725         return true;
726     }
727 }
728
729 /**
730  * @constructor
731  * @implements {WebInspector.ActionDelegate}
732  */
733 WebInspector.Main.ZoomOutActionDelegate = function()
734 {
735 }
736
737 WebInspector.Main.ZoomOutActionDelegate.prototype = {
738     /**
739      * @return {boolean}
740      */
741     handleAction: function()
742     {
743         if (InspectorFrontendHost.isHostedMode())
744             return false;
745
746         InspectorFrontendHost.zoomOut();
747         return true;
748     }
749 }
750
751 /**
752  * @constructor
753  * @implements {WebInspector.ActionDelegate}
754  */
755 WebInspector.Main.ZoomResetActionDelegate = function()
756 {
757 }
758
759 WebInspector.Main.ZoomResetActionDelegate.prototype = {
760     /**
761      * @return {boolean}
762      */
763     handleAction: function()
764     {
765         if (InspectorFrontendHost.isHostedMode())
766             return false;
767
768         InspectorFrontendHost.resetZoom();
769         return true;
770     }
771 }
772
773 /**
774  * @constructor
775  * @extends {WebInspector.UISettingDelegate}
776  */
777 WebInspector.Main.ShortcutPanelSwitchSettingDelegate = function()
778 {
779     WebInspector.UISettingDelegate.call(this);
780 }
781
782 WebInspector.Main.ShortcutPanelSwitchSettingDelegate.prototype = {
783     /**
784      * @override
785      * @return {!Element}
786      */
787     settingElement: function()
788     {
789         var modifier = WebInspector.platform() === "mac" ? "Cmd" : "Ctrl";
790         return WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Enable %s + 1-9 shortcut to switch panels", modifier), WebInspector.settings.shortcutPanelSwitch);
791     },
792
793     __proto__: WebInspector.UISettingDelegate.prototype
794 }
795
796 /**
797  * @param {string} ws
798  */
799 WebInspector.Main._addWebSocketTarget = function(ws)
800 {
801     /**
802      * @param {!InspectorBackendClass.Connection} connection
803      */
804     function callback(connection)
805     {
806         WebInspector.targetManager.createTarget(ws, connection);
807     }
808     new InspectorBackendClass.WebSocketConnection(ws, callback);
809 }
810
811 new WebInspector.Main();
812
813 // These methods are added for backwards compatibility with Devtools CodeSchool extension.
814 // DO NOT REMOVE
815
816 WebInspector.__defineGetter__("inspectedPageURL", function()
817 {
818     return WebInspector.resourceTreeModel.inspectedPageURL();
819 });
820
821 /**
822  * @param {string} name
823  * @return {?WebInspector.Panel}
824  */
825 WebInspector.panel = function(name)
826 {
827     return WebInspector.inspectorView.panel(name);
828 }
829
830 /**
831  * @constructor
832  * @implements {WebInspector.StatusBarItem.Provider}
833  */
834 WebInspector.Main.WarningErrorCounter = function()
835 {
836     this._counter = new WebInspector.StatusBarCounter(["error-icon-small", "warning-icon-small"]);
837     this._counter.addEventListener("click", showConsole);
838
839     function showConsole()
840     {
841         WebInspector.console.show();
842     }
843
844     WebInspector.multitargetConsoleModel.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._updateErrorAndWarningCounts, this);
845     WebInspector.multitargetConsoleModel.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._updateErrorAndWarningCounts, this);
846 }
847
848 WebInspector.Main.WarningErrorCounter.prototype = {
849     _updateErrorAndWarningCounts: function()
850     {
851         var errors = 0;
852         var warnings = 0;
853         var targets = WebInspector.targetManager.targets();
854         for (var i = 0; i < targets.length; ++i) {
855             errors = errors + targets[i].consoleModel.errors;
856             warnings = warnings + targets[i].consoleModel.warnings;
857         }
858         this._counter.setCounter("error-icon-small", errors, WebInspector.UIString(errors > 1 ? "%d errors" : "%d error", errors));
859         this._counter.setCounter("warning-icon-small", warnings, WebInspector.UIString(warnings > 1 ? "%d warnings" : "%d warning", warnings));
860         WebInspector.inspectorView.toolbarItemResized();
861     },
862
863     /**
864      * @return {?WebInspector.StatusBarItem}
865      */
866     item: function()
867     {
868         return this._counter;
869     }
870 }
871
872 /**
873  * @constructor
874  */
875 WebInspector.Main.PauseListener = function()
876 {
877     WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
878 }
879
880 WebInspector.Main.PauseListener.prototype = {
881     /**
882      * @param {!WebInspector.Event} event
883      */
884     _debuggerPaused: function(event)
885     {
886         WebInspector.targetManager.removeModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
887         var debuggerModel = /** @type {!WebInspector.DebuggerModel} */ (event.target);
888         WebInspector.context.setFlavor(WebInspector.Target, debuggerModel.target());
889         WebInspector.inspectorView.showPanel("sources");
890     }
891 }
892
893 /**
894  * @constructor
895  */
896 WebInspector.Main.InspectedNodeRevealer = function()
897 {
898     WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.NodeInspected, this._inspectNode, this);
899 }
900
901 WebInspector.Main.InspectedNodeRevealer.prototype = {
902     /**
903      * @param {!WebInspector.Event} event
904      */
905     _inspectNode: function(event)
906     {
907         WebInspector.Revealer.reveal(/** @type {!WebInspector.DOMNode} */ (event.data));
908     }
909 }