Home | History | Annotate | Download | only in main
      1 /*
      2  * Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
      3  * Copyright (C) 2007 Matt Lilek (pewtermoose (at) 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     _registerModules: function()
     52     {
     53         var configuration;
     54         if (!Capabilities.isMainFrontend) {
     55             configuration = ["main", "sources", "timeline", "profiler", "console", "source_frame", "search"];
     56         } else {
     57             configuration = ["main", "elements", "network", "sources", "timeline", "profiler", "resources", "audits", "console", "source_frame", "extensions", "settings", "search"];
     58             if (WebInspector.experimentsSettings.layersPanel.isEnabled())
     59                 configuration.push("layers");
     60             if (WebInspector.experimentsSettings.devicesPanel.isEnabled())
     61                 configuration.push("devices");
     62         }
     63         WebInspector.moduleManager.registerModules(configuration);
     64     },
     65 
     66     _createGlobalStatusBarItems: function()
     67     {
     68         var extensions = WebInspector.moduleManager.extensions(WebInspector.StatusBarButton.Provider);
     69 
     70         /**
     71          * @param {!WebInspector.ModuleManager.Extension} left
     72          * @param {!WebInspector.ModuleManager.Extension} right
     73          */
     74         function orderComparator(left, right)
     75         {
     76             return left.descriptor()["order"] - right.descriptor()["order"];
     77         }
     78         extensions.sort(orderComparator);
     79         extensions.forEach(function(extension) {
     80             var button;
     81             switch (extension.descriptor()["location"]) {
     82             case "toolbar-left":
     83                 button = createButton(extension);
     84                 if (button)
     85                     WebInspector.inspectorView.appendToLeftToolbar(button.element);
     86                 break;
     87             case "toolbar-right":
     88                 button = createButton(extension);
     89                 if (button)
     90                     WebInspector.inspectorView.appendToRightToolbar(button.element);
     91                 break;
     92             }
     93             if (button && extension.descriptor()["actionId"]) {
     94                 button.addEventListener("click", function() {
     95                     WebInspector.actionRegistry.execute(extension.descriptor()["actionId"]);
     96                 });
     97             }
     98         });
     99 
    100         function createButton(extension)
    101         {
    102             var descriptor = extension.descriptor();
    103             if (descriptor.className)
    104                 return extension.instance().button();
    105             return new WebInspector.StatusBarButton(WebInspector.UIString(descriptor["title"]), descriptor["elementClass"]);
    106         }
    107     },
    108 
    109     _calculateWorkerInspectorTitle: function()
    110     {
    111         var expression = "location.href";
    112         if (WebInspector.queryParam("isSharedWorker"))
    113             expression += " + (this.name ? ' (' + this.name + ')' : '')";
    114         RuntimeAgent.invoke_evaluate({expression:expression, doNotPauseOnExceptionsAndMuteConsole:true, returnByValue: true}, evalCallback);
    115 
    116         /**
    117          * @param {?Protocol.Error} error
    118          * @param {!RuntimeAgent.RemoteObject} result
    119          * @param {boolean=} wasThrown
    120          */
    121         function evalCallback(error, result, wasThrown)
    122         {
    123             if (error || wasThrown) {
    124                 console.error(error);
    125                 return;
    126             }
    127             InspectorFrontendHost.inspectedURLChanged(result.value);
    128         }
    129     },
    130 
    131     _loadCompletedForWorkers: function()
    132     {
    133         // Make sure script execution of dedicated worker or service worker is
    134         // resumed and then paused on the first script statement in case we
    135         // autoattached to it.
    136         if (WebInspector.queryParam("workerPaused")) {
    137             pauseAndResume.call(this);
    138         } else{
    139             RuntimeAgent.isRunRequired(isRunRequiredCallback.bind(this));
    140         }
    141 
    142         /**
    143          * @this {WebInspector.Main}
    144          */
    145         function isRunRequiredCallback(error, result)
    146         {
    147             if (result) {
    148                 pauseAndResume.call(this);
    149             } else if (!Capabilities.isMainFrontend) {
    150                 calculateTitle.call(this);
    151             }
    152         }
    153 
    154         /**
    155          * @this {WebInspector.Main}
    156          */
    157         function pauseAndResume()
    158         {
    159             DebuggerAgent.pause();
    160             RuntimeAgent.run(calculateTitle.bind(this));
    161         }
    162 
    163         /**
    164          * @this {WebInspector.Main}
    165          */
    166         function calculateTitle()
    167         {
    168             this._calculateWorkerInspectorTitle();
    169         }
    170     },
    171 
    172     _resetErrorAndWarningCounts: function()
    173     {
    174         WebInspector.inspectorView.setErrorAndWarningCounts(0, 0);
    175     },
    176 
    177     _updateErrorAndWarningCounts: function()
    178     {
    179         var errors = WebInspector.console.errors;
    180         var warnings = WebInspector.console.warnings;
    181         WebInspector.inspectorView.setErrorAndWarningCounts(errors, warnings);
    182     },
    183 
    184     _debuggerPaused: function()
    185     {
    186         WebInspector.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
    187         WebInspector.inspectorView.showPanel("sources");
    188     },
    189 
    190     _loaded: function()
    191     {
    192         if (WebInspector.queryParam("toolbox")) {
    193             new WebInspector.Toolbox();
    194             return;
    195         }
    196 
    197         WebInspector.settings = new WebInspector.Settings();
    198         WebInspector.experimentsSettings = new WebInspector.ExperimentsSettings(WebInspector.queryParam("experiments") !== null);
    199         // This setting is needed for backwards compatibility with Devtools CodeSchool extension. DO NOT REMOVE
    200         WebInspector.settings.pauseOnExceptionStateString = new WebInspector.PauseOnExceptionStateSetting();
    201 
    202         if (!InspectorFrontendHost.sendMessageToEmbedder) {
    203             var helpScreen = new WebInspector.HelpScreen(WebInspector.UIString("Incompatible Chrome version"));
    204             var p = helpScreen.contentElement.createChild("p", "help-section");
    205             p.textContent = WebInspector.UIString("Please upgrade to a newer Chrome version (you might need a Dev or Canary build).");
    206             helpScreen.showModal();
    207             return;
    208         }
    209 
    210         InspectorBackend.loadFromJSONIfNeeded("../protocol.json");
    211 
    212         var onConnectionReady = this._doLoadedDone.bind(this);
    213 
    214         var workerId = WebInspector.queryParam("dedicatedWorkerId");
    215         if (workerId) {
    216             new WebInspector.ExternalWorkerConnection(workerId, onConnectionReady);
    217             return;
    218         }
    219 
    220         var ws;
    221         if (WebInspector.queryParam("ws")) {
    222             ws = "ws://" + WebInspector.queryParam("ws");
    223         } else if (WebInspector.queryParam("page")) {
    224             var page = WebInspector.queryParam("page");
    225             var host = WebInspector.queryParam("host") || window.location.host;
    226             ws = "ws://" + host + "/devtools/page/" + page;
    227         }
    228 
    229         if (ws) {
    230             document.body.classList.add("remote");
    231             new InspectorBackendClass.WebSocketConnection(ws, onConnectionReady);
    232             return;
    233         }
    234 
    235         if (!InspectorFrontendHost.isStub) {
    236             new InspectorBackendClass.MainConnection(onConnectionReady);
    237             return;
    238         }
    239 
    240         new InspectorBackendClass.StubConnection(onConnectionReady);
    241     },
    242 
    243     /**
    244      * @param {!InspectorBackendClass.Connection} connection
    245      */
    246     _doLoadedDone: function(connection)
    247     {
    248         connection.addEventListener(InspectorBackendClass.Connection.Events.Disconnected, onDisconnected);
    249 
    250         /**
    251          * @param {!WebInspector.Event} event
    252          */
    253         function onDisconnected(event)
    254         {
    255             if (WebInspector._disconnectedScreenWithReasonWasShown)
    256                 return;
    257             new WebInspector.RemoteDebuggingTerminatedScreen(event.data.reason).showModal();
    258         }
    259 
    260         InspectorBackend.setConnection(connection);
    261 
    262         // Install styles and themes
    263         WebInspector.installPortStyles();
    264 
    265         if (WebInspector.queryParam("toolbarColor") && WebInspector.queryParam("textColor"))
    266             WebInspector.setToolbarColors(WebInspector.queryParam("toolbarColor"), WebInspector.queryParam("textColor"));
    267 
    268         WebInspector.targetManager = new WebInspector.TargetManager();
    269         WebInspector.targetManager.createTarget(WebInspector.UIString("Main"), connection, this._doLoadedDoneWithCapabilities.bind(this));
    270         WebInspector.isolatedFileSystemManager = new WebInspector.IsolatedFileSystemManager();
    271         WebInspector.isolatedFileSystemDispatcher = new WebInspector.IsolatedFileSystemDispatcher(WebInspector.isolatedFileSystemManager);
    272         WebInspector.workspace = new WebInspector.Workspace(WebInspector.isolatedFileSystemManager.mapping());
    273         WebInspector.networkWorkspaceBinding = new WebInspector.NetworkWorkspaceBinding(WebInspector.workspace);
    274         new WebInspector.NetworkUISourceCodeProvider(WebInspector.networkWorkspaceBinding, WebInspector.workspace);
    275         new WebInspector.PresentationConsoleMessageHelper(WebInspector.workspace);
    276         WebInspector.fileSystemWorkspaceBinding = new WebInspector.FileSystemWorkspaceBinding(WebInspector.isolatedFileSystemManager, WebInspector.workspace);
    277         WebInspector.breakpointManager = new WebInspector.BreakpointManager(WebInspector.settings.breakpoints, WebInspector.workspace, WebInspector.targetManager);
    278         WebInspector.scriptSnippetModel = new WebInspector.ScriptSnippetModel(WebInspector.workspace);
    279         this._executionContextSelector = new WebInspector.ExecutionContextSelector();
    280     },
    281 
    282     _doLoadedDoneWithCapabilities: function(mainTarget)
    283     {
    284         WebInspector.dockController = new WebInspector.DockController(!!WebInspector.queryParam("can_dock"));
    285         WebInspector.overridesSupport = new WebInspector.OverridesSupport(WebInspector.experimentsSettings.responsiveDesign.isEnabled() && WebInspector.dockController.canDock());
    286 
    287         if (mainTarget.canScreencast)
    288             WebInspector.app = new WebInspector.ScreencastApp();
    289         else if (WebInspector.dockController.canDock())
    290             WebInspector.app = new WebInspector.AdvancedApp();
    291         else
    292             WebInspector.app = new WebInspector.SimpleApp();
    293 
    294         WebInspector.dockController.initialize();
    295 
    296         new WebInspector.VersionController().updateVersion();
    297         WebInspector.shortcutsScreen = new WebInspector.ShortcutsScreen();
    298         this._registerShortcuts();
    299 
    300         // set order of some sections explicitly
    301         WebInspector.shortcutsScreen.section(WebInspector.UIString("Console"));
    302         WebInspector.shortcutsScreen.section(WebInspector.UIString("Elements Panel"));
    303         WebInspector.ShortcutsScreen.registerShortcuts();
    304 
    305         if (WebInspector.experimentsSettings.workersInMainWindow.isEnabled())
    306             new WebInspector.WorkerTargetManager(mainTarget, WebInspector.targetManager);
    307 
    308         WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._resetErrorAndWarningCounts, this);
    309         WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._updateErrorAndWarningCounts, this);
    310 
    311         WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
    312 
    313         WebInspector.inspectorFrontendEventSink = new WebInspector.InspectorFrontendEventSink();
    314         InspectorBackend.registerInspectorDispatcher(this);
    315 
    316         if (Capabilities.isMainFrontend) {
    317             WebInspector.inspectElementModeController = new WebInspector.InspectElementModeController();
    318             WebInspector.workerFrontendManager = new WebInspector.WorkerFrontendManager();
    319         } else {
    320             mainTarget.workerManager.addEventListener(WebInspector.WorkerManager.Events.WorkerDisconnected, onWorkerDisconnected);
    321         }
    322 
    323         function onWorkerDisconnected()
    324         {
    325             var screen = new WebInspector.WorkerTerminatedScreen();
    326             var listener = hideScreen.bind(null, screen);
    327             mainTarget.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, listener);
    328 
    329             /**
    330              * @param {!WebInspector.WorkerTerminatedScreen} screen
    331              */
    332             function hideScreen(screen)
    333             {
    334                 mainTarget.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, listener);
    335                 screen.hide();
    336             }
    337 
    338             screen.showModal();
    339         }
    340 
    341         WebInspector.domBreakpointsSidebarPane = new WebInspector.DOMBreakpointsSidebarPane();
    342 
    343         var autoselectPanel = WebInspector.UIString("a panel chosen automatically");
    344         var openAnchorLocationSetting = WebInspector.settings.createSetting("openLinkHandler", autoselectPanel);
    345         WebInspector.openAnchorLocationRegistry = new WebInspector.HandlerRegistry(openAnchorLocationSetting);
    346         WebInspector.openAnchorLocationRegistry.registerHandler(autoselectPanel, function() { return false; });
    347         WebInspector.Linkifier.setLinkHandler(new WebInspector.HandlerRegistry.LinkHandler());
    348 
    349         new WebInspector.WorkspaceController(WebInspector.workspace);
    350 
    351         WebInspector.liveEditSupport = new WebInspector.LiveEditSupport(WebInspector.workspace);
    352         new WebInspector.CSSStyleSheetMapping(WebInspector.cssModel, WebInspector.workspace, WebInspector.networkWorkspaceBinding);
    353 
    354         // Create settings before loading modules.
    355         WebInspector.settings.initializeBackendSettings();
    356 
    357         this._registerModules();
    358         WebInspector.actionRegistry = new WebInspector.ActionRegistry();
    359         WebInspector.shortcutRegistry = new WebInspector.ShortcutRegistry(WebInspector.actionRegistry);
    360         this._registerForwardedShortcuts();
    361         this._registerMessageSinkListener();
    362 
    363         WebInspector.zoomManager = new WebInspector.ZoomManager();
    364         WebInspector.inspectorView = new WebInspector.InspectorView();
    365         WebInspector.app.createRootView();
    366         this._createGlobalStatusBarItems();
    367 
    368         this._addMainEventListeners(document);
    369 
    370         var errorWarningCount = document.getElementById("error-warning-count");
    371 
    372         function showConsole()
    373         {
    374             WebInspector.console.show();
    375         }
    376         errorWarningCount.addEventListener("click", showConsole, false);
    377         this._updateErrorAndWarningCounts();
    378 
    379         WebInspector.extensionServerProxy.setFrontendReady();
    380 
    381         InspectorAgent.enable(inspectorAgentEnableCallback);
    382 
    383         function inspectorAgentEnableCallback()
    384         {
    385             WebInspector.app.presentUI();
    386         }
    387 
    388         this._loadCompletedForWorkers();
    389         InspectorFrontendAPI.loadCompleted();
    390         WebInspector.notifications.dispatchEventToListeners(WebInspector.NotificationService.Events.InspectorLoaded);
    391     },
    392 
    393     _registerForwardedShortcuts: function()
    394     {
    395         /** @const */ var forwardedActions = ["main.reload", "main.hard-reload"];
    396         var actionKeys = WebInspector.shortcutRegistry.keysForActions(forwardedActions).map(WebInspector.KeyboardShortcut.keyCodeAndModifiersFromKey);
    397 
    398         actionKeys.push({keyCode: WebInspector.KeyboardShortcut.Keys.F8.code});
    399         InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys));
    400     },
    401 
    402     _registerMessageSinkListener: function()
    403     {
    404         WebInspector.messageSink.addEventListener(WebInspector.MessageSink.Events.MessageAdded, messageAdded);
    405 
    406         /**
    407          * @param {!WebInspector.Event} event
    408          */
    409         function messageAdded(event)
    410         {
    411             var message = /** @type {!WebInspector.MessageSink.Message} */ (event.data);
    412             if (message.show)
    413                 WebInspector.actionRegistry.execute("console.show");
    414         }
    415     },
    416 
    417     _documentClick: function(event)
    418     {
    419         var anchor = event.target.enclosingNodeOrSelfWithNodeName("a");
    420         if (!anchor || !anchor.href)
    421             return;
    422 
    423         // Prevent the link from navigating, since we don't do any navigation by following links normally.
    424         event.consume(true);
    425 
    426         if (anchor.target === "_blank") {
    427             InspectorFrontendHost.openInNewTab(anchor.href);
    428             return;
    429         }
    430 
    431         function followLink()
    432         {
    433             if (WebInspector.isBeingEdited(event.target))
    434                 return;
    435             if (WebInspector.openAnchorLocationRegistry.dispatch({ url: anchor.href, lineNumber: anchor.lineNumber}))
    436                 return;
    437 
    438             var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(anchor.href);
    439             if (uiSourceCode) {
    440                 WebInspector.Revealer.reveal(uiSourceCode.uiLocation(anchor.lineNumber || 0, anchor.columnNumber || 0));
    441                 return;
    442             }
    443 
    444             var resource = WebInspector.resourceForURL(anchor.href);
    445             if (resource) {
    446                 WebInspector.Revealer.reveal(resource);
    447                 return;
    448             }
    449 
    450             var request = WebInspector.networkLog.requestForURL(anchor.href);
    451             if (request) {
    452                 WebInspector.Revealer.reveal(request);
    453                 return;
    454             }
    455             InspectorFrontendHost.openInNewTab(anchor.href);
    456         }
    457 
    458         if (WebInspector.followLinkTimeout)
    459             clearTimeout(WebInspector.followLinkTimeout);
    460 
    461         if (anchor.preventFollowOnDoubleClick) {
    462             // Start a timeout if this is the first click, if the timeout is canceled
    463             // before it fires, then a double clicked happened or another link was clicked.
    464             if (event.detail === 1)
    465                 WebInspector.followLinkTimeout = setTimeout(followLink, 333);
    466             return;
    467         }
    468 
    469         followLink();
    470     },
    471 
    472     _registerShortcuts: function()
    473     {
    474         var shortcut = WebInspector.KeyboardShortcut;
    475         var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("All Panels"));
    476         var keys = [
    477             shortcut.makeDescriptor("[", shortcut.Modifiers.CtrlOrMeta),
    478             shortcut.makeDescriptor("]", shortcut.Modifiers.CtrlOrMeta)
    479         ];
    480         section.addRelatedKeys(keys, WebInspector.UIString("Go to the panel to the left/right"));
    481 
    482         keys = [
    483             shortcut.makeDescriptor("[", shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Alt),
    484             shortcut.makeDescriptor("]", shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Alt)
    485         ];
    486         section.addRelatedKeys(keys, WebInspector.UIString("Go back/forward in panel history"));
    487 
    488         var toggleConsoleLabel = WebInspector.UIString("Show console");
    489         section.addKey(shortcut.makeDescriptor(shortcut.Keys.Tilde, shortcut.Modifiers.Ctrl), toggleConsoleLabel);
    490         section.addKey(shortcut.makeDescriptor(shortcut.Keys.Esc), WebInspector.UIString("Toggle drawer"));
    491         section.addKey(shortcut.makeDescriptor("f", shortcut.Modifiers.CtrlOrMeta), WebInspector.UIString("Search"));
    492 
    493         var advancedSearchShortcutModifier = WebInspector.isMac()
    494                 ? WebInspector.KeyboardShortcut.Modifiers.Meta | WebInspector.KeyboardShortcut.Modifiers.Alt
    495                 : WebInspector.KeyboardShortcut.Modifiers.Ctrl | WebInspector.KeyboardShortcut.Modifiers.Shift;
    496         var advancedSearchShortcut = shortcut.makeDescriptor("f", advancedSearchShortcutModifier);
    497         section.addKey(advancedSearchShortcut, WebInspector.UIString("Search across all sources"));
    498 
    499         var inspectElementModeShortcut = WebInspector.InspectElementModeController.createShortcut();
    500         section.addKey(inspectElementModeShortcut, WebInspector.UIString("Select node to inspect"));
    501 
    502         var openResourceShortcut = WebInspector.KeyboardShortcut.makeDescriptor("p", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta);
    503         section.addKey(openResourceShortcut, WebInspector.UIString("Go to source"));
    504 
    505         if (WebInspector.isMac()) {
    506             keys = [
    507                 shortcut.makeDescriptor("g", shortcut.Modifiers.Meta),
    508                 shortcut.makeDescriptor("g", shortcut.Modifiers.Meta | shortcut.Modifiers.Shift)
    509             ];
    510             section.addRelatedKeys(keys, WebInspector.UIString("Find next/previous"));
    511         }
    512     },
    513 
    514     _postDocumentKeyDown: function(event)
    515     {
    516         if (event.handled)
    517             return;
    518 
    519         if (!WebInspector.Dialog.currentInstance() && WebInspector.inspectorView.currentPanel()) {
    520             WebInspector.inspectorView.currentPanel().handleShortcut(event);
    521             if (event.handled) {
    522                 event.consume(true);
    523                 return;
    524             }
    525         }
    526 
    527         WebInspector.shortcutRegistry.handleShortcut(event);
    528     },
    529 
    530     _documentCanCopy: function(event)
    531     {
    532         if (WebInspector.inspectorView.currentPanel() && WebInspector.inspectorView.currentPanel()["handleCopyEvent"])
    533             event.preventDefault();
    534     },
    535 
    536     _documentCopy: function(event)
    537     {
    538         if (WebInspector.inspectorView.currentPanel() && WebInspector.inspectorView.currentPanel()["handleCopyEvent"])
    539             WebInspector.inspectorView.currentPanel()["handleCopyEvent"](event);
    540     },
    541 
    542     _contextMenuEventFired: function(event)
    543     {
    544         if (event.handled || event.target.classList.contains("popup-glasspane"))
    545             event.preventDefault();
    546     },
    547 
    548     _addMainEventListeners: function(doc)
    549     {
    550         doc.addEventListener("keydown", this._postDocumentKeyDown.bind(this), false);
    551         doc.addEventListener("beforecopy", this._documentCanCopy.bind(this), true);
    552         doc.addEventListener("copy", this._documentCopy.bind(this), false);
    553         doc.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);
    554         doc.addEventListener("click", this._documentClick.bind(this), false);
    555     },
    556 
    557     /**
    558      * @override
    559      * @param {!RuntimeAgent.RemoteObject} payload
    560      * @param {!Object=} hints
    561      */
    562     inspect: function(payload, hints)
    563     {
    564         var object = WebInspector.runtimeModel.createRemoteObject(payload);
    565         if (object.isNode()) {
    566             object.pushNodeToFrontend(callback);
    567             var elementsPanel = /** @type {!WebInspector.ElementsPanel} */ (WebInspector.inspectorView.panel("elements"));
    568             elementsPanel.omitDefaultSelection();
    569             WebInspector.inspectorView.setCurrentPanel(elementsPanel);
    570             return;
    571         }
    572 
    573         /**
    574          * @param {!WebInspector.DOMNode} node
    575          */
    576         function callback(node)
    577         {
    578             elementsPanel.stopOmittingDefaultSelection();
    579             node.reveal();
    580             if (!WebInspector.inspectorView.drawerVisible() && !WebInspector._notFirstInspectElement)
    581                 InspectorFrontendHost.inspectElementCompleted();
    582             WebInspector._notFirstInspectElement = true;
    583             object.release();
    584         }
    585 
    586         if (object.type === "function") {
    587             /**
    588              * @param {?Protocol.Error} error
    589              * @param {!DebuggerAgent.FunctionDetails} response
    590              */
    591             object.functionDetails(didGetDetails);
    592             return;
    593         }
    594 
    595         /**
    596          * @param {?DebuggerAgent.FunctionDetails} response
    597          */
    598         function didGetDetails(response)
    599         {
    600             object.release();
    601 
    602             if (!response)
    603                 return;
    604 
    605             WebInspector.Revealer.reveal(WebInspector.DebuggerModel.Location.fromPayload(object.target(), response.location).toUILocation());
    606         }
    607 
    608         if (hints.copyToClipboard)
    609             InspectorFrontendHost.copyText(object.value);
    610         object.release();
    611     },
    612 
    613     /**
    614      * @override
    615      * @param {string} reason
    616      */
    617     detached: function(reason)
    618     {
    619         WebInspector._disconnectedScreenWithReasonWasShown = true;
    620         new WebInspector.RemoteDebuggingTerminatedScreen(reason).showModal();
    621     },
    622 
    623     /**
    624      * @override
    625      */
    626     targetCrashed: function()
    627     {
    628         (new WebInspector.HelpScreenUntilReload(
    629             WebInspector.UIString("Inspected target crashed"),
    630             WebInspector.UIString("Inspected target has crashed. Once it reloads we will attach to it automatically."))).showModal();
    631     },
    632 
    633     /**
    634      * @override
    635      * @param {number} callId
    636      * @param {string} script
    637      */
    638     evaluateForTestInFrontend: function(callId, script)
    639     {
    640         WebInspector.evaluateForTestInFrontend(callId, script);
    641     }
    642 }
    643 
    644 WebInspector.reload = function()
    645 {
    646     InspectorAgent.reset();
    647     window.location.reload();
    648 }
    649 
    650 /**
    651  * @constructor
    652  * @implements {WebInspector.ActionDelegate}
    653  */
    654 WebInspector.Main.ReloadActionDelegate = function()
    655 {
    656 }
    657 
    658 WebInspector.Main.ReloadActionDelegate.prototype = {
    659     /**
    660      * @return {boolean}
    661      */
    662     handleAction: function()
    663     {
    664         WebInspector.debuggerModel.skipAllPauses(true, true);
    665         WebInspector.resourceTreeModel.reloadPage(false);
    666         return true;
    667     }
    668 }
    669 
    670 /**
    671  * @constructor
    672  * @implements {WebInspector.ActionDelegate}
    673  */
    674 WebInspector.Main.HardReloadActionDelegate = function()
    675 {
    676 }
    677 
    678 WebInspector.Main.HardReloadActionDelegate.prototype = {
    679     /**
    680      * @return {boolean}
    681      */
    682     handleAction: function()
    683     {
    684         WebInspector.debuggerModel.skipAllPauses(true, true);
    685         WebInspector.resourceTreeModel.reloadPage(true);
    686         return true;
    687     }
    688 }
    689 
    690 /**
    691  * @constructor
    692  * @implements {WebInspector.ActionDelegate}
    693  */
    694 WebInspector.Main.DebugReloadActionDelegate = function()
    695 {
    696 }
    697 
    698 WebInspector.Main.DebugReloadActionDelegate.prototype = {
    699     /**
    700      * @return {boolean}
    701      */
    702     handleAction: function()
    703     {
    704         WebInspector.reload();
    705         return true;
    706     }
    707 }
    708 
    709 /**
    710  * @constructor
    711  * @implements {WebInspector.ActionDelegate}
    712  */
    713 WebInspector.Main.ZoomInActionDelegate = function()
    714 {
    715 }
    716 
    717 WebInspector.Main.ZoomInActionDelegate.prototype = {
    718     /**
    719      * @return {boolean}
    720      */
    721     handleAction: function()
    722     {
    723         if (InspectorFrontendHost.isStub)
    724             return false;
    725 
    726         InspectorFrontendHost.zoomIn();
    727         return true;
    728     }
    729 }
    730 
    731 /**
    732  * @constructor
    733  * @implements {WebInspector.ActionDelegate}
    734  */
    735 WebInspector.Main.ZoomOutActionDelegate = function()
    736 {
    737 }
    738 
    739 WebInspector.Main.ZoomOutActionDelegate.prototype = {
    740     /**
    741      * @return {boolean}
    742      */
    743     handleAction: function()
    744     {
    745         if (InspectorFrontendHost.isStub)
    746             return false;
    747 
    748         InspectorFrontendHost.zoomOut();
    749         return true;
    750     }
    751 }
    752 
    753 /**
    754  * @constructor
    755  * @implements {WebInspector.ActionDelegate}
    756  */
    757 WebInspector.Main.ZoomResetActionDelegate = function()
    758 {
    759 }
    760 
    761 WebInspector.Main.ZoomResetActionDelegate.prototype = {
    762     /**
    763      * @return {boolean}
    764      */
    765     handleAction: function()
    766     {
    767         if (InspectorFrontendHost.isStub)
    768             return false;
    769 
    770         InspectorFrontendHost.resetZoom();
    771         return true;
    772     }
    773 }
    774 
    775 /**
    776  * @constructor
    777  * @extends {WebInspector.UISettingDelegate}
    778  */
    779 WebInspector.Main.ShortcutPanelSwitchSettingDelegate = function()
    780 {
    781     WebInspector.UISettingDelegate.call(this);
    782 }
    783 
    784 WebInspector.Main.ShortcutPanelSwitchSettingDelegate.prototype = {
    785     /**
    786      * @override
    787      * @return {!Element}
    788      */
    789     settingElement: function()
    790     {
    791         var modifier = WebInspector.platform() === "mac" ? "Cmd" : "Ctrl";
    792         return WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Enable %s + 1-9 shortcut to switch panels", modifier), WebInspector.settings.shortcutPanelSwitch);
    793     },
    794 
    795     __proto__: WebInspector.UISettingDelegate.prototype
    796 }
    797 
    798 /**
    799  * @param {string} ws
    800  */
    801 WebInspector.Main._addWebSocketTarget = function(ws)
    802 {
    803     /**
    804      * @param {!InspectorBackendClass.Connection} connection
    805      */
    806     function callback(connection)
    807     {
    808         WebInspector.targetManager.createTarget(ws, connection);
    809     }
    810     new InspectorBackendClass.WebSocketConnection(ws, callback);
    811 }
    812 
    813 new WebInspector.Main();
    814 
    815 // These methods are added for backwards compatibility with Devtools CodeSchool extension.
    816 // DO NOT REMOVE
    817 
    818 WebInspector.__defineGetter__("inspectedPageURL", function()
    819 {
    820     return WebInspector.resourceTreeModel.inspectedPageURL();
    821 });
    822 
    823 /**
    824  * @param {string} name
    825  * @return {?WebInspector.Panel}
    826  */
    827 WebInspector.panel = function(name)
    828 {
    829     return WebInspector.inspectorView.panel(name);
    830 }
    831