home *** CD-ROM | disk | FTP | other *** search
/ Computer Active Guide 2009 July / CAG7.ISO / Internetas / SafariSetup.exe / AppleApplicationSupport.msi / WebKit.resources_inspector_inspector.js < prev    next >
Encoding:
JavaScript  |  2010-06-03  |  64.5 KB  |  2,032 lines

  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. function preloadImages()
  32. {
  33.     (new Image()).src = "Images/clearConsoleButtonGlyph.png";
  34.     (new Image()).src = "Images/consoleButtonGlyph.png";
  35.     (new Image()).src = "Images/dockButtonGlyph.png";
  36.     (new Image()).src = "Images/enableOutlineButtonGlyph.png";
  37.     (new Image()).src = "Images/enableSolidButtonGlyph.png";
  38.     (new Image()).src = "Images/excludeButtonGlyph.png";
  39.     (new Image()).src = "Images/focusButtonGlyph.png";
  40.     (new Image()).src = "Images/largerResourcesButtonGlyph.png";
  41.     (new Image()).src = "Images/nodeSearchButtonGlyph.png";
  42.     (new Image()).src = "Images/pauseOnExceptionButtonGlyph.png";
  43.     (new Image()).src = "Images/percentButtonGlyph.png";
  44.     (new Image()).src = "Images/recordButtonGlyph.png";
  45.     (new Image()).src = "Images/recordToggledButtonGlyph.png";
  46.     (new Image()).src = "Images/reloadButtonGlyph.png";
  47.     (new Image()).src = "Images/undockButtonGlyph.png";
  48. }
  49.  
  50. preloadImages();
  51.  
  52. var WebInspector = {
  53.     resources: {},
  54.     resourceURLMap: {},
  55.     cookieDomains: {},
  56.     missingLocalizedStrings: {},
  57.     pendingDispatches: 0,
  58.  
  59.     // RegExp groups:
  60.     // 1 - scheme
  61.     // 2 - hostname
  62.     // 3 - ?port
  63.     // 4 - ?path
  64.     // 5 - ?fragment
  65.     URLRegExp: /^(http[s]?|file):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i,
  66.     GenericURLRegExp: /^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i,
  67.  
  68.     get platform()
  69.     {
  70.         if (!("_platform" in this))
  71.             this._platform = InspectorFrontendHost.platform();
  72.  
  73.         return this._platform;
  74.     },
  75.  
  76.     get platformFlavor()
  77.     {
  78.         if (!("_platformFlavor" in this))
  79.             this._platformFlavor = this._detectPlatformFlavor();
  80.  
  81.         return this._platformFlavor;
  82.     },
  83.  
  84.     _detectPlatformFlavor: function()
  85.     {
  86.         const userAgent = navigator.userAgent;
  87.  
  88.         if (this.platform === "windows") {
  89.             var match = userAgent.match(/Windows NT (\d+)\.(?:\d+)/);
  90.             if (match && match[1] >= 6)
  91.                 return WebInspector.PlatformFlavor.WindowsVista;
  92.             return null;
  93.         } else if (this.platform === "mac") {
  94.             var match = userAgent.match(/Mac OS X\s*(?:(\d+)_(\d+))?/);
  95.             if (!match || match[1] != 10)
  96.                 return WebInspector.PlatformFlavor.MacSnowLeopard;
  97.             switch (Number(match[2])) {
  98.                 case 4:
  99.                     return WebInspector.PlatformFlavor.MacTiger;
  100.                 case 5:
  101.                     return WebInspector.PlatformFlavor.MacLeopard;
  102.                 case 6:
  103.                 default:
  104.                     return WebInspector.PlatformFlavor.MacSnowLeopard;
  105.             }
  106.         }
  107.  
  108.         return null;
  109.     },
  110.  
  111.     get port()
  112.     {
  113.         if (!("_port" in this))
  114.             this._port = InspectorFrontendHost.port();
  115.  
  116.         return this._port;
  117.     },
  118.  
  119.     get previousFocusElement()
  120.     {
  121.         return this._previousFocusElement;
  122.     },
  123.  
  124.     get currentFocusElement()
  125.     {
  126.         return this._currentFocusElement;
  127.     },
  128.  
  129.     set currentFocusElement(x)
  130.     {
  131.         if (this._currentFocusElement !== x)
  132.             this._previousFocusElement = this._currentFocusElement;
  133.         this._currentFocusElement = x;
  134.  
  135.         if (this._currentFocusElement) {
  136.             this._currentFocusElement.focus();
  137.  
  138.             // Make a caret selection inside the new element if there isn't a range selection and
  139.             // there isn't already a caret selection inside.
  140.             var selection = window.getSelection();
  141.             if (selection.isCollapsed && !this._currentFocusElement.isInsertionCaretInside()) {
  142.                 var selectionRange = this._currentFocusElement.ownerDocument.createRange();
  143.                 selectionRange.setStart(this._currentFocusElement, 0);
  144.                 selectionRange.setEnd(this._currentFocusElement, 0);
  145.  
  146.                 selection.removeAllRanges();
  147.                 selection.addRange(selectionRange);
  148.             }
  149.         } else if (this._previousFocusElement)
  150.             this._previousFocusElement.blur();
  151.     },
  152.  
  153.     get currentPanel()
  154.     {
  155.         return this._currentPanel;
  156.     },
  157.  
  158.     set currentPanel(x)
  159.     {
  160.         if (this._currentPanel === x)
  161.             return;
  162.  
  163.         if (this._currentPanel)
  164.             this._currentPanel.hide();
  165.  
  166.         this._currentPanel = x;
  167.  
  168.         this.updateSearchLabel();
  169.  
  170.         if (x) {
  171.             x.show();
  172.  
  173.             if (this.currentQuery) {
  174.                 if (x.performSearch) {
  175.                     function performPanelSearch()
  176.                     {
  177.                         this.updateSearchMatchesCount();
  178.  
  179.                         x.currentQuery = this.currentQuery;
  180.                         x.performSearch(this.currentQuery);
  181.                     }
  182.  
  183.                     // Perform the search on a timeout so the panel switches fast.
  184.                     setTimeout(performPanelSearch.bind(this), 0);
  185.                 } else {
  186.                     // Update to show Not found for panels that can't be searched.
  187.                     this.updateSearchMatchesCount();
  188.                 }
  189.             }
  190.         }
  191.  
  192.         for (var panelName in WebInspector.panels) {
  193.             if (WebInspector.panels[panelName] === x) {
  194.                 InspectorBackend.storeLastActivePanel(panelName);
  195.                 this._panelHistory.setPanel(panelName);
  196.             }
  197.         }
  198.     },
  199.  
  200.     _createPanels: function()
  201.     {
  202.         var hiddenPanels = (InspectorFrontendHost.hiddenPanels() || "").split(',');
  203.         if (hiddenPanels.indexOf("elements") === -1)
  204.             this.panels.elements = new WebInspector.ElementsPanel();
  205.         if (hiddenPanels.indexOf("resources") === -1)
  206.             this.panels.resources = new WebInspector.ResourcesPanel();
  207.         if (hiddenPanels.indexOf("scripts") === -1)
  208.             this.panels.scripts = new WebInspector.ScriptsPanel();
  209.         if (hiddenPanels.indexOf("timeline") === -1)
  210.             this.panels.timeline = new WebInspector.TimelinePanel();
  211.         if (hiddenPanels.indexOf("profiles") === -1) {
  212.             this.panels.profiles = new WebInspector.ProfilesPanel();
  213.             this.panels.profiles.registerProfileType(new WebInspector.CPUProfileType());
  214.         }
  215.         if (hiddenPanels.indexOf("storage") === -1 && hiddenPanels.indexOf("databases") === -1)
  216.             this.panels.storage = new WebInspector.StoragePanel();
  217.         if (Preferences.auditsPanelEnabled && hiddenPanels.indexOf("audits") === -1)
  218.             this.panels.audits = new WebInspector.AuditsPanel();
  219.         if (hiddenPanels.indexOf("console") === -1)
  220.             this.panels.console = new WebInspector.ConsolePanel();
  221.     },
  222.  
  223.     get attached()
  224.     {
  225.         return this._attached;
  226.     },
  227.  
  228.     set attached(x)
  229.     {
  230.         if (this._attached === x)
  231.             return;
  232.  
  233.         this._attached = x;
  234.  
  235.         this.updateSearchLabel();
  236.  
  237.         var dockToggleButton = document.getElementById("dock-status-bar-item");
  238.         var body = document.body;
  239.  
  240.         if (x) {
  241.             body.removeStyleClass("detached");
  242.             body.addStyleClass("attached");
  243.             dockToggleButton.title = WebInspector.UIString("Undock into separate window.");
  244.         } else {
  245.             body.removeStyleClass("attached");
  246.             body.addStyleClass("detached");
  247.             dockToggleButton.title = WebInspector.UIString("Dock to main window.");
  248.         }
  249.         if (this.drawer)
  250.             this.drawer.resize();
  251.     },
  252.  
  253.     get errors()
  254.     {
  255.         return this._errors || 0;
  256.     },
  257.  
  258.     set errors(x)
  259.     {
  260.         x = Math.max(x, 0);
  261.  
  262.         if (this._errors === x)
  263.             return;
  264.         this._errors = x;
  265.         this._updateErrorAndWarningCounts();
  266.     },
  267.  
  268.     get warnings()
  269.     {
  270.         return this._warnings || 0;
  271.     },
  272.  
  273.     set warnings(x)
  274.     {
  275.         x = Math.max(x, 0);
  276.  
  277.         if (this._warnings === x)
  278.             return;
  279.         this._warnings = x;
  280.         this._updateErrorAndWarningCounts();
  281.     },
  282.  
  283.     _updateErrorAndWarningCounts: function()
  284.     {
  285.         var errorWarningElement = document.getElementById("error-warning-count");
  286.         if (!errorWarningElement)
  287.             return;
  288.  
  289.         if (!this.errors && !this.warnings) {
  290.             errorWarningElement.addStyleClass("hidden");
  291.             return;
  292.         }
  293.  
  294.         errorWarningElement.removeStyleClass("hidden");
  295.  
  296.         errorWarningElement.removeChildren();
  297.  
  298.         if (this.errors) {
  299.             var errorElement = document.createElement("span");
  300.             errorElement.id = "error-count";
  301.             errorElement.textContent = this.errors;
  302.             errorWarningElement.appendChild(errorElement);
  303.         }
  304.  
  305.         if (this.warnings) {
  306.             var warningsElement = document.createElement("span");
  307.             warningsElement.id = "warning-count";
  308.             warningsElement.textContent = this.warnings;
  309.             errorWarningElement.appendChild(warningsElement);
  310.         }
  311.  
  312.         if (this.errors) {
  313.             if (this.warnings) {
  314.                 if (this.errors == 1) {
  315.                     if (this.warnings == 1)
  316.                         errorWarningElement.title = WebInspector.UIString("%d error, %d warning", this.errors, this.warnings);
  317.                     else
  318.                         errorWarningElement.title = WebInspector.UIString("%d error, %d warnings", this.errors, this.warnings);
  319.                 } else if (this.warnings == 1)
  320.                     errorWarningElement.title = WebInspector.UIString("%d errors, %d warning", this.errors, this.warnings);
  321.                 else
  322.                     errorWarningElement.title = WebInspector.UIString("%d errors, %d warnings", this.errors, this.warnings);
  323.             } else if (this.errors == 1)
  324.                 errorWarningElement.title = WebInspector.UIString("%d error", this.errors);
  325.             else
  326.                 errorWarningElement.title = WebInspector.UIString("%d errors", this.errors);
  327.         } else if (this.warnings == 1)
  328.             errorWarningElement.title = WebInspector.UIString("%d warning", this.warnings);
  329.         else if (this.warnings)
  330.             errorWarningElement.title = WebInspector.UIString("%d warnings", this.warnings);
  331.         else
  332.             errorWarningElement.title = null;
  333.     },
  334.  
  335.     get styleChanges()
  336.     {
  337.         return this._styleChanges;
  338.     },
  339.  
  340.     set styleChanges(x)
  341.     {
  342.         x = Math.max(x, 0);
  343.  
  344.         if (this._styleChanges === x)
  345.             return;
  346.         this._styleChanges = x;
  347.         this._updateChangesCount();
  348.     },
  349.  
  350.     _updateChangesCount: function()
  351.     {
  352.         // TODO: Remove immediate return when enabling the Changes Panel
  353.         return;
  354.  
  355.         var changesElement = document.getElementById("changes-count");
  356.         if (!changesElement)
  357.             return;
  358.  
  359.         if (!this.styleChanges) {
  360.             changesElement.addStyleClass("hidden");
  361.             return;
  362.         }
  363.  
  364.         changesElement.removeStyleClass("hidden");
  365.         changesElement.removeChildren();
  366.  
  367.         if (this.styleChanges) {
  368.             var styleChangesElement = document.createElement("span");
  369.             styleChangesElement.id = "style-changes-count";
  370.             styleChangesElement.textContent = this.styleChanges;
  371.             changesElement.appendChild(styleChangesElement);
  372.         }
  373.  
  374.         if (this.styleChanges) {
  375.             if (this.styleChanges === 1)
  376.                 changesElement.title = WebInspector.UIString("%d style change", this.styleChanges);
  377.             else
  378.                 changesElement.title = WebInspector.UIString("%d style changes", this.styleChanges);
  379.         }
  380.     },
  381.  
  382.     get hoveredDOMNode()
  383.     {
  384.         return this._hoveredDOMNode;
  385.     },
  386.  
  387.     set hoveredDOMNode(x)
  388.     {
  389.         if (this._hoveredDOMNode === x)
  390.             return;
  391.  
  392.         this._hoveredDOMNode = x;
  393.  
  394.         if (this._hoveredDOMNode)
  395.             this._updateHoverHighlightSoon(this.showingDOMNodeHighlight ? 50 : 500);
  396.         else
  397.             this._updateHoverHighlight();
  398.     },
  399.  
  400.     _updateHoverHighlightSoon: function(delay)
  401.     {
  402.         if ("_updateHoverHighlightTimeout" in this)
  403.             clearTimeout(this._updateHoverHighlightTimeout);
  404.         this._updateHoverHighlightTimeout = setTimeout(this._updateHoverHighlight.bind(this), delay);
  405.     },
  406.  
  407.     _updateHoverHighlight: function()
  408.     {
  409.         if ("_updateHoverHighlightTimeout" in this) {
  410.             clearTimeout(this._updateHoverHighlightTimeout);
  411.             delete this._updateHoverHighlightTimeout;
  412.         }
  413.  
  414.         if (this._hoveredDOMNode) {
  415.             InspectorBackend.highlightDOMNode(this._hoveredDOMNode.id);
  416.             this.showingDOMNodeHighlight = true;
  417.         } else {
  418.             InspectorBackend.hideDOMNodeHighlight();
  419.             this.showingDOMNodeHighlight = false;
  420.         }
  421.     }
  422. }
  423.  
  424. WebInspector.PlatformFlavor = {
  425.     WindowsVista: "windows-vista",
  426.     MacTiger: "mac-tiger",
  427.     MacLeopard: "mac-leopard",
  428.     MacSnowLeopard: "mac-snowleopard"
  429. }
  430.  
  431. WebInspector.loaded = function()
  432. {
  433.     InspectorBackend.setInjectedScriptSource("(" + injectedScriptConstructor + ");");
  434.  
  435.     var platform = WebInspector.platform;
  436.     document.body.addStyleClass("platform-" + platform);
  437.     var flavor = WebInspector.platformFlavor;
  438.     if (flavor)
  439.         document.body.addStyleClass("platform-" + flavor);
  440.     var port = WebInspector.port;
  441.     document.body.addStyleClass("port-" + port);
  442.  
  443.     this.settings = new WebInspector.Settings();
  444.  
  445.     this.drawer = new WebInspector.Drawer();
  446.     this.console = new WebInspector.ConsoleView(this.drawer);
  447.     // TODO: Uncomment when enabling the Changes Panel
  448.     // this.changes = new WebInspector.ChangesView(this.drawer);
  449.     // TODO: Remove class="hidden" from inspector.html on button#changes-status-bar-item
  450.     this.drawer.visibleView = this.console;
  451.     this.domAgent = new WebInspector.DOMAgent();
  452.  
  453.     this.resourceCategories = {
  454.         documents: new WebInspector.ResourceCategory("documents", WebInspector.UIString("Documents"), "rgb(47,102,236)"),
  455.         stylesheets: new WebInspector.ResourceCategory("stylesheets", WebInspector.UIString("Stylesheets"), "rgb(157,231,119)"),
  456.         images: new WebInspector.ResourceCategory("images", WebInspector.UIString("Images"), "rgb(164,60,255)"),
  457.         scripts: new WebInspector.ResourceCategory("scripts", WebInspector.UIString("Scripts"), "rgb(255,121,0)"),
  458.         xhr: new WebInspector.ResourceCategory("xhr", WebInspector.UIString("XHR"), "rgb(231,231,10)"),
  459.         fonts: new WebInspector.ResourceCategory("fonts", WebInspector.UIString("Fonts"), "rgb(255,82,62)"),
  460.         other: new WebInspector.ResourceCategory("other", WebInspector.UIString("Other"), "rgb(186,186,186)")
  461.     };
  462.  
  463.     this.panels = {};
  464.     this._createPanels();
  465.     this._panelHistory = new WebInspector.PanelHistory();
  466.  
  467.     var toolbarElement = document.getElementById("toolbar");
  468.     var previousToolbarItem = toolbarElement.children[0];
  469.  
  470.     this.panelOrder = [];
  471.     for (var panelName in this.panels)
  472.         previousToolbarItem = WebInspector.addPanelToolbarIcon(toolbarElement, this.panels[panelName], previousToolbarItem);
  473.  
  474.     this.Tips = {
  475.         ResourceNotCompressed: {id: 0, message: WebInspector.UIString("You could save bandwidth by having your web server compress this transfer with gzip or zlib.")}
  476.     };
  477.  
  478.     this.Warnings = {
  479.         IncorrectMIMEType: {id: 0, message: WebInspector.UIString("Resource interpreted as %s but transferred with MIME type %s.")}
  480.     };
  481.  
  482.     this.addMainEventListeners(document);
  483.  
  484.     window.addEventListener("resize", this.windowResize.bind(this), true);
  485.  
  486.     document.addEventListener("focus", this.focusChanged.bind(this), true);
  487.     document.addEventListener("keydown", this.documentKeyDown.bind(this), false);
  488.     document.addEventListener("beforecopy", this.documentCanCopy.bind(this), true);
  489.     document.addEventListener("copy", this.documentCopy.bind(this), true);
  490.     document.addEventListener("contextmenu", this.contextMenuEventFired.bind(this), true);
  491.  
  492.     var dockToggleButton = document.getElementById("dock-status-bar-item");
  493.     dockToggleButton.addEventListener("click", this.toggleAttach.bind(this), false);
  494.  
  495.     if (this.attached)
  496.         dockToggleButton.title = WebInspector.UIString("Undock into separate window.");
  497.     else
  498.         dockToggleButton.title = WebInspector.UIString("Dock to main window.");
  499.  
  500.     var errorWarningCount = document.getElementById("error-warning-count");
  501.     errorWarningCount.addEventListener("click", this.showConsole.bind(this), false);
  502.     this._updateErrorAndWarningCounts();
  503.  
  504.     this.styleChanges = 0;
  505.     // TODO: Uncomment when enabling the Changes Panel
  506.     // var changesElement = document.getElementById("changes-count");
  507.     // changesElement.addEventListener("click", this.showChanges.bind(this), false);
  508.     // this._updateErrorAndWarningCounts();
  509.  
  510.     var searchField = document.getElementById("search");
  511.     searchField.addEventListener("search", this.performSearch.bind(this), false); // when the search is emptied
  512.     searchField.addEventListener("mousedown", this._searchFieldManualFocus.bind(this), false); // when the search field is manually selected
  513.     searchField.addEventListener("keydown", this._searchKeyDown.bind(this), true);
  514.  
  515.     toolbarElement.addEventListener("mousedown", this.toolbarDragStart, true);
  516.     document.getElementById("close-button-left").addEventListener("click", this.close, true);
  517.     document.getElementById("close-button-right").addEventListener("click", this.close, true);
  518.  
  519.     InspectorFrontendHost.loaded();
  520. }
  521.  
  522. WebInspector.addPanelToolbarIcon = function(toolbarElement, panel, previousToolbarItem)
  523. {
  524.     var panelToolbarItem = panel.toolbarItem;
  525.     this.panelOrder.push(panel);
  526.     panelToolbarItem.addEventListener("click", this._toolbarItemClicked.bind(this));
  527.     if (previousToolbarItem)
  528.         toolbarElement.insertBefore(panelToolbarItem, previousToolbarItem.nextSibling);
  529.     else
  530.         toolbarElement.insertBefore(panelToolbarItem, toolbarElement.firstChild);
  531.     return panelToolbarItem;
  532. }
  533.  
  534. var windowLoaded = function()
  535. {
  536.     var localizedStringsURL = InspectorFrontendHost.localizedStringsURL();
  537.     if (localizedStringsURL) {
  538.         var localizedStringsScriptElement = document.createElement("script");
  539.         localizedStringsScriptElement.addEventListener("load", WebInspector.loaded.bind(WebInspector), false);
  540.         localizedStringsScriptElement.type = "text/javascript";
  541.         localizedStringsScriptElement.src = localizedStringsURL;
  542.         document.head.appendChild(localizedStringsScriptElement);
  543.     } else
  544.         WebInspector.loaded();
  545.  
  546.     window.removeEventListener("load", windowLoaded, false);
  547.     delete windowLoaded;
  548. };
  549.  
  550. window.addEventListener("load", windowLoaded, false);
  551.  
  552. WebInspector.dispatch = function() {
  553.     var methodName = arguments[0];
  554.     var parameters = Array.prototype.slice.call(arguments, 1);
  555.  
  556.     // We'd like to enforce asynchronous interaction between the inspector controller and the frontend.
  557.     // This is important to LayoutTests.
  558.     function delayDispatch()
  559.     {
  560.         WebInspector[methodName].apply(WebInspector, parameters);
  561.         WebInspector.pendingDispatches--;
  562.     }
  563.     WebInspector.pendingDispatches++;
  564.     setTimeout(delayDispatch, 0);
  565. }
  566.  
  567. WebInspector.windowResize = function(event)
  568. {
  569.     if (this.currentPanel)
  570.         this.currentPanel.resize();
  571.     this.drawer.resize();
  572. }
  573.  
  574. WebInspector.windowFocused = function(event)
  575. {
  576.     // Fires after blur, so when focusing on either the main inspector
  577.     // or an <iframe> within the inspector we should always remove the
  578.     // "inactive" class.
  579.     if (event.target.document.nodeType === Node.DOCUMENT_NODE)
  580.         document.body.removeStyleClass("inactive");
  581. }
  582.  
  583. WebInspector.windowBlurred = function(event)
  584. {
  585.     // Leaving the main inspector or an <iframe> within the inspector.
  586.     // We can add "inactive" now, and if we are moving the focus to another
  587.     // part of the inspector then windowFocused will correct this.
  588.     if (event.target.document.nodeType === Node.DOCUMENT_NODE)
  589.         document.body.addStyleClass("inactive");
  590. }
  591.  
  592. WebInspector.focusChanged = function(event)
  593. {
  594.     this.currentFocusElement = event.target;
  595. }
  596.  
  597. WebInspector.setAttachedWindow = function(attached)
  598. {
  599.     this.attached = attached;
  600. }
  601.  
  602. WebInspector.close = function(event)
  603. {
  604.     if (this._isClosing)
  605.         return;
  606.     this._isClosing = true;
  607.     InspectorFrontendHost.closeWindow();
  608. }
  609.  
  610. WebInspector.inspectedPageDestroyed = function()
  611. {
  612.     WebInspector.close();
  613. }
  614.  
  615. WebInspector.documentMouseOver = function(event)
  616. {
  617.     if (event.target.tagName !== "A")
  618.         return;
  619.  
  620.     const anchor = event.target;
  621.     if (!anchor.hasStyleClass("webkit-html-resource-link"))
  622.         return;
  623.     if (anchor.href && anchor.href.indexOf("/data:") != -1)
  624.         return;
  625. }
  626.  
  627. WebInspector.documentClick = function(event)
  628. {
  629.     var anchor = event.target.enclosingNodeOrSelfWithNodeName("a");
  630.     if (!anchor)
  631.         return;
  632.  
  633.     // Prevent the link from navigating, since we don't do any navigation by following links normally.
  634.     event.preventDefault();
  635.     event.stopPropagation();
  636.  
  637.     function followLink()
  638.     {
  639.         // FIXME: support webkit-html-external-link links here.
  640.         if (WebInspector.canShowSourceLine(anchor.href, anchor.lineNumber, anchor.preferredPanel)) {
  641.             if (anchor.hasStyleClass("webkit-html-external-link")) {
  642.                 anchor.removeStyleClass("webkit-html-external-link");
  643.                 anchor.addStyleClass("webkit-html-resource-link");
  644.             }
  645.  
  646.             WebInspector.showSourceLine(anchor.href, anchor.lineNumber, anchor.preferredPanel);
  647.             return;
  648.         }
  649.  
  650.         const profileMatch = WebInspector.ProfileType.URLRegExp.exec(anchor.href);
  651.         if (profileMatch) {
  652.             WebInspector.showProfileForURL(anchor.href);
  653.             return;
  654.         }
  655.  
  656.         const urlMatch = WebInspector.GenericURLRegExp.exec(anchor.href);
  657.         if (urlMatch && urlMatch[1] === "webkit-link-action") {
  658.             if (urlMatch[2] === "show-panel") {
  659.                 const panel = urlMatch[4].substring(1);
  660.                 if (WebInspector.panels[panel])
  661.                     WebInspector.currentPanel = WebInspector.panels[panel];
  662.             }
  663.             return;
  664.         }
  665.  
  666.         WebInspector.showResourcesPanel();
  667.     }
  668.  
  669.     if (WebInspector.followLinkTimeout)
  670.         clearTimeout(WebInspector.followLinkTimeout);
  671.  
  672.     if (anchor.preventFollowOnDoubleClick) {
  673.         // Start a timeout if this is the first click, if the timeout is canceled
  674.         // before it fires, then a double clicked happened or another link was clicked.
  675.         if (event.detail === 1)
  676.             WebInspector.followLinkTimeout = setTimeout(followLink, 333);
  677.         return;
  678.     }
  679.  
  680.     followLink();
  681. }
  682.  
  683. WebInspector.documentKeyDown = function(event)
  684. {
  685.     if (WebInspector.isEditingAnyField())
  686.         return;
  687.  
  688.     var isInTextPrompt = event.target.enclosingNodeOrSelfWithClass("text-prompt");
  689.     if (this.currentFocusElement && this.currentFocusElement.handleKeyEvent) {
  690.         this.currentFocusElement.handleKeyEvent(event);
  691.         if (event.handled) {
  692.             event.preventDefault();
  693.             return;
  694.         }
  695.     }
  696.  
  697.     if (this.currentPanel && this.currentPanel.handleShortcut) {
  698.         this.currentPanel.handleShortcut(event);
  699.         if (event.handled) {
  700.             event.preventDefault();
  701.             return;
  702.         }
  703.     }
  704.  
  705.     var isMac = WebInspector.isMac();
  706.     switch (event.keyIdentifier) {
  707.         case "Left":
  708.             var isBackKey = !isInTextPrompt && (isMac ? event.metaKey : event.ctrlKey);
  709.             if (isBackKey && this._panelHistory.canGoBack()) {
  710.                 this._panelHistory.goBack();
  711.                 event.preventDefault();
  712.             }
  713.             break;
  714.  
  715.         case "Right":
  716.             var isForwardKey = !isInTextPrompt && (isMac ? event.metaKey : event.ctrlKey);
  717.             if (isForwardKey && this._panelHistory.canGoForward()) {
  718.                 this._panelHistory.goForward();
  719.                 event.preventDefault();
  720.             }
  721.             break;
  722.  
  723.         case "U+001B": // Escape key
  724.             event.preventDefault();
  725.             if (this.drawer.fullPanel)
  726.                 return;
  727.  
  728.             this.drawer.visible = !this.drawer.visible;
  729.             break;
  730.  
  731.         case "U+0046": // F key
  732.             if (isMac)
  733.                 var isFindKey = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
  734.             else
  735.                 var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey;
  736.  
  737.             if (isFindKey) {
  738.                 WebInspector.focusSearchField();
  739.                 event.preventDefault();
  740.             }
  741.             break;
  742.  
  743.         case "F3":
  744.             if (!isMac) {
  745.                 WebInspector.focusSearchField();
  746.                 event.preventDefault();
  747.             }
  748.             break;
  749.  
  750.         case "U+0047": // G key
  751.             if (isMac)
  752.                 var isFindAgainKey = event.metaKey && !event.ctrlKey && !event.altKey;
  753.             else
  754.                 var isFindAgainKey = event.ctrlKey && !event.metaKey && !event.altKey;
  755.  
  756.             if (isFindAgainKey) {
  757.                 if (event.shiftKey) {
  758.                     if (this.currentPanel.jumpToPreviousSearchResult)
  759.                         this.currentPanel.jumpToPreviousSearchResult();
  760.                 } else if (this.currentPanel.jumpToNextSearchResult)
  761.                     this.currentPanel.jumpToNextSearchResult();
  762.                 event.preventDefault();
  763.             }
  764.  
  765.             break;
  766.  
  767.         // Windows and Mac have two different definitions of [, so accept both.
  768.         case "U+005B":
  769.         case "U+00DB": // [ key
  770.             if (isMac)
  771.                 var isRotateLeft = event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey;
  772.             else
  773.                 var isRotateLeft = event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;
  774.  
  775.             if (isRotateLeft) {
  776.                 var index = this.panelOrder.indexOf(this.currentPanel);
  777.                 index = (index === 0) ? this.panelOrder.length - 1 : index - 1;
  778.                 this.panelOrder[index].toolbarItem.click();
  779.                 event.preventDefault();
  780.             }
  781.  
  782.             break;
  783.  
  784.         // Windows and Mac have two different definitions of ], so accept both.
  785.         case "U+005D":
  786.         case "U+00DD":  // ] key
  787.             if (isMac)
  788.                 var isRotateRight = event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey;
  789.             else
  790.                 var isRotateRight = event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;
  791.  
  792.             if (isRotateRight) {
  793.                 var index = this.panelOrder.indexOf(this.currentPanel);
  794.                 index = (index + 1) % this.panelOrder.length;
  795.                 this.panelOrder[index].toolbarItem.click();
  796.                 event.preventDefault();
  797.             }
  798.  
  799.             break;
  800.  
  801.         case "U+0052": // R key
  802.             if ((event.metaKey && isMac) || (event.ctrlKey && !isMac)) {
  803.                 InspectorBackend.reloadPage();
  804.                 event.preventDefault();
  805.             }
  806.             break;
  807.         case "F5":
  808.             if (!isMac)
  809.                 InspectorBackend.reloadPage();
  810.             break;
  811.     }
  812. }
  813.  
  814. WebInspector.documentCanCopy = function(event)
  815. {
  816.     if (this.currentPanel && this.currentPanel.handleCopyEvent)
  817.         event.preventDefault();
  818. }
  819.  
  820. WebInspector.documentCopy = function(event)
  821. {
  822.     if (this.currentPanel && this.currentPanel.handleCopyEvent)
  823.         this.currentPanel.handleCopyEvent(event);
  824. }
  825.  
  826. WebInspector.contextMenuEventFired = function(event)
  827. {
  828.     if (event.handled || event.target.hasStyleClass("popup-glasspane"))
  829.         event.preventDefault();
  830. }
  831.  
  832. WebInspector.animateStyle = function(animations, duration, callback)
  833. {
  834.     var interval;
  835.     var complete = 0;
  836.  
  837.     const intervalDuration = (1000 / 30); // 30 frames per second.
  838.     const animationsLength = animations.length;
  839.     const propertyUnit = {opacity: ""};
  840.     const defaultUnit = "px";
  841.  
  842.     function cubicInOut(t, b, c, d)
  843.     {
  844.         if ((t/=d/2) < 1) return c/2*t*t*t + b;
  845.         return c/2*((t-=2)*t*t + 2) + b;
  846.     }
  847.  
  848.     // Pre-process animations.
  849.     for (var i = 0; i < animationsLength; ++i) {
  850.         var animation = animations[i];
  851.         var element = null, start = null, end = null, key = null;
  852.         for (key in animation) {
  853.             if (key === "element")
  854.                 element = animation[key];
  855.             else if (key === "start")
  856.                 start = animation[key];
  857.             else if (key === "end")
  858.                 end = animation[key];
  859.         }
  860.  
  861.         if (!element || !end)
  862.             continue;
  863.  
  864.         if (!start) {
  865.             var computedStyle = element.ownerDocument.defaultView.getComputedStyle(element);
  866.             start = {};
  867.             for (key in end)
  868.                 start[key] = parseInt(computedStyle.getPropertyValue(key));
  869.             animation.start = start;
  870.         } else
  871.             for (key in start)
  872.                 element.style.setProperty(key, start[key] + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
  873.     }
  874.  
  875.     function animateLoop()
  876.     {
  877.         // Advance forward.
  878.         complete += intervalDuration;
  879.         var next = complete + intervalDuration;
  880.  
  881.         // Make style changes.
  882.         for (var i = 0; i < animationsLength; ++i) {
  883.             var animation = animations[i];
  884.             var element = animation.element;
  885.             var start = animation.start;
  886.             var end = animation.end;
  887.             if (!element || !end)
  888.                 continue;
  889.  
  890.             var style = element.style;
  891.             for (key in end) {
  892.                 var endValue = end[key];
  893.                 if (next < duration) {
  894.                     var startValue = start[key];
  895.                     var newValue = cubicInOut(complete, startValue, endValue - startValue, duration);
  896.                     style.setProperty(key, newValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
  897.                 } else
  898.                     style.setProperty(key, endValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
  899.             }
  900.         }
  901.  
  902.         // End condition.
  903.         if (complete >= duration) {
  904.             clearInterval(interval);
  905.             if (callback)
  906.                 callback();
  907.         }
  908.     }
  909.  
  910.     interval = setInterval(animateLoop, intervalDuration);
  911.     return interval;
  912. }
  913.  
  914. WebInspector.updateSearchLabel = function()
  915. {
  916.     if (!this.currentPanel)
  917.         return;
  918.  
  919.     var newLabel = WebInspector.UIString("Search %s", this.currentPanel.toolbarItemLabel);
  920.     if (this.attached)
  921.         document.getElementById("search").setAttribute("placeholder", newLabel);
  922.     else {
  923.         document.getElementById("search").removeAttribute("placeholder");
  924.         document.getElementById("search-toolbar-label").textContent = newLabel;
  925.     }
  926. }
  927.  
  928. WebInspector.focusSearchField = function()
  929. {
  930.     var searchField = document.getElementById("search");
  931.     searchField.focus();
  932.     searchField.select();
  933. }
  934.  
  935. WebInspector.toggleAttach = function()
  936. {
  937.     if (!this.attached)
  938.         InspectorFrontendHost.requestAttachWindow();
  939.     else
  940.         InspectorFrontendHost.requestDetachWindow();
  941. }
  942.  
  943. WebInspector.toolbarDragStart = function(event)
  944. {
  945.     if ((!WebInspector.attached && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacLeopard && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacSnowLeopard) || WebInspector.port == "qt")
  946.         return;
  947.  
  948.     var target = event.target;
  949.     if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable"))
  950.         return;
  951.  
  952.     var toolbar = document.getElementById("toolbar");
  953.     if (target !== toolbar && !target.hasStyleClass("toolbar-item"))
  954.         return;
  955.  
  956.     toolbar.lastScreenX = event.screenX;
  957.     toolbar.lastScreenY = event.screenY;
  958.  
  959.     WebInspector.elementDragStart(toolbar, WebInspector.toolbarDrag, WebInspector.toolbarDragEnd, event, (WebInspector.attached ? "row-resize" : "default"));
  960. }
  961.  
  962. WebInspector.toolbarDragEnd = function(event)
  963. {
  964.     var toolbar = document.getElementById("toolbar");
  965.  
  966.     WebInspector.elementDragEnd(event);
  967.  
  968.     delete toolbar.lastScreenX;
  969.     delete toolbar.lastScreenY;
  970. }
  971.  
  972. WebInspector.toolbarDrag = function(event)
  973. {
  974.     var toolbar = document.getElementById("toolbar");
  975.  
  976.     if (WebInspector.attached) {
  977.         var height = window.innerHeight - (event.screenY - toolbar.lastScreenY);
  978.  
  979.         InspectorFrontendHost.setAttachedWindowHeight(height);
  980.     } else {
  981.         var x = event.screenX - toolbar.lastScreenX;
  982.         var y = event.screenY - toolbar.lastScreenY;
  983.  
  984.         // We cannot call window.moveBy here because it restricts the movement
  985.         // of the window at the edges.
  986.         InspectorFrontendHost.moveWindowBy(x, y);
  987.     }
  988.  
  989.     toolbar.lastScreenX = event.screenX;
  990.     toolbar.lastScreenY = event.screenY;
  991.  
  992.     event.preventDefault();
  993. }
  994.  
  995. WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor)
  996. {
  997.     if (this._elementDraggingEventListener || this._elementEndDraggingEventListener)
  998.         this.elementDragEnd(event);
  999.  
  1000.     this._elementDraggingEventListener = dividerDrag;
  1001.     this._elementEndDraggingEventListener = elementDragEnd;
  1002.  
  1003.     document.addEventListener("mousemove", dividerDrag, true);
  1004.     document.addEventListener("mouseup", elementDragEnd, true);
  1005.  
  1006.     document.body.style.cursor = cursor;
  1007.  
  1008.     event.preventDefault();
  1009. }
  1010.  
  1011. WebInspector.elementDragEnd = function(event)
  1012. {
  1013.     document.removeEventListener("mousemove", this._elementDraggingEventListener, true);
  1014.     document.removeEventListener("mouseup", this._elementEndDraggingEventListener, true);
  1015.  
  1016.     document.body.style.removeProperty("cursor");
  1017.  
  1018.     delete this._elementDraggingEventListener;
  1019.     delete this._elementEndDraggingEventListener;
  1020.  
  1021.     event.preventDefault();
  1022. }
  1023.  
  1024. WebInspector.showConsole = function()
  1025. {
  1026.     this.drawer.showView(this.console);
  1027. }
  1028.  
  1029. WebInspector.showChanges = function()
  1030. {
  1031.     this.drawer.showView(this.changes);
  1032. }
  1033.  
  1034. WebInspector.showElementsPanel = function()
  1035. {
  1036.     this.currentPanel = this.panels.elements;
  1037. }
  1038.  
  1039. WebInspector.showResourcesPanel = function()
  1040. {
  1041.     this.currentPanel = this.panels.resources;
  1042. }
  1043.  
  1044. WebInspector.showScriptsPanel = function()
  1045. {
  1046.     this.currentPanel = this.panels.scripts;
  1047. }
  1048.  
  1049. WebInspector.showTimelinePanel = function()
  1050. {
  1051.     this.currentPanel = this.panels.timeline;
  1052. }
  1053.  
  1054. WebInspector.showProfilesPanel = function()
  1055. {
  1056.     this.currentPanel = this.panels.profiles;
  1057. }
  1058.  
  1059. WebInspector.showStoragePanel = function()
  1060. {
  1061.     this.currentPanel = this.panels.storage;
  1062. }
  1063.  
  1064. WebInspector.showConsolePanel = function()
  1065. {
  1066.     this.currentPanel = this.panels.console;
  1067. }
  1068.  
  1069. WebInspector.showAuditsPanel = function()
  1070. {
  1071.     this.currentPanel = this.panels.audits;
  1072. }
  1073.  
  1074. WebInspector.clearConsoleMessages = function()
  1075. {
  1076.     WebInspector.console.clearMessages();
  1077. }
  1078.  
  1079. WebInspector.selectDatabase = function(o)
  1080. {
  1081.     WebInspector.showStoragePanel();
  1082.     WebInspector.panels.storage.selectDatabase(o);
  1083. }
  1084.  
  1085. WebInspector.selectDOMStorage = function(o)
  1086. {
  1087.     WebInspector.showStoragePanel();
  1088.     WebInspector.panels.storage.selectDOMStorage(o);
  1089. }
  1090.  
  1091. WebInspector.updateResource = function(identifier, payload)
  1092. {
  1093.     var resource = this.resources[identifier];
  1094.     if (!resource) {
  1095.         resource = new WebInspector.Resource(identifier, payload.url);
  1096.         this.resources[identifier] = resource;
  1097.         this.resourceURLMap[resource.url] = resource;
  1098.         if (this.panels.resources)
  1099.             this.panels.resources.addResource(resource);
  1100.         if (this.panels.audits)
  1101.             this.panels.audits.resourceStarted(resource);
  1102.     }
  1103.  
  1104.     if (payload.didRequestChange) {
  1105.         resource.domain = payload.host;
  1106.         resource.path = payload.path;
  1107.         resource.lastPathComponent = payload.lastPathComponent;
  1108.         resource.requestHeaders = payload.requestHeaders;
  1109.         resource.mainResource = payload.mainResource;
  1110.         resource.requestMethod = payload.requestMethod;
  1111.         resource.requestFormData = payload.requestFormData;
  1112.         resource.cached = payload.cached;
  1113.         resource.documentURL = payload.documentURL;
  1114.  
  1115.         if (resource.mainResource)
  1116.             this.mainResource = resource;
  1117.  
  1118.         var match = payload.documentURL.match(WebInspector.GenericURLRegExp);
  1119.         if (match) {
  1120.             var protocol = match[1].toLowerCase();
  1121.             this._addCookieDomain(match[2]);
  1122.         }
  1123.     }
  1124.  
  1125.     if (payload.didResponseChange) {
  1126.         resource.mimeType = payload.mimeType;
  1127.         resource.suggestedFilename = payload.suggestedFilename;
  1128.         resource.expectedContentLength = payload.expectedContentLength;
  1129.         resource.statusCode = payload.statusCode;
  1130.         resource.suggestedFilename = payload.suggestedFilename;
  1131.         resource.responseHeaders = payload.responseHeaders;
  1132.     }
  1133.  
  1134.     if (payload.didTypeChange) {
  1135.         resource.type = payload.type;
  1136.     }
  1137.  
  1138.     if (payload.didLengthChange) {
  1139.         resource.resourceSize = payload.resourceSize;
  1140.     }
  1141.  
  1142.     if (payload.didCompletionChange) {
  1143.         resource.failed = payload.failed;
  1144.         resource.finished = payload.finished;
  1145.         if (this.panels.audits)
  1146.             this.panels.audits.resourceFinished(resource);
  1147.     }
  1148.  
  1149.     if (payload.didTimingChange) {
  1150.         if (payload.startTime)
  1151.             resource.startTime = payload.startTime;
  1152.         if (payload.responseReceivedTime)
  1153.             resource.responseReceivedTime = payload.responseReceivedTime;
  1154.         if (payload.endTime)
  1155.             resource.endTime = payload.endTime;
  1156.  
  1157.         if (payload.loadEventTime) {
  1158.             // This loadEventTime is for the main resource, and we want to show it
  1159.             // for all resources on this page. This means we want to set it as a member
  1160.             // of the resources panel instead of the individual resource.
  1161.             if (this.panels.resources)
  1162.                 this.panels.resources.mainResourceLoadTime = payload.loadEventTime;
  1163.             if (this.panels.audits)
  1164.                 this.panels.audits.mainResourceLoadTime = payload.loadEventTime;
  1165.         }
  1166.  
  1167.         if (payload.domContentEventTime) {
  1168.             // This domContentEventTime is for the main resource, so it should go in
  1169.             // the resources panel for the same reasons as above.
  1170.             if (this.panels.resources)
  1171.                 this.panels.resources.mainResourceDOMContentTime = payload.domContentEventTime;
  1172.             if (this.panels.audits)
  1173.                 this.panels.audits.mainResourceDOMContentTime = payload.domContentEventTime;
  1174.         }
  1175.     }
  1176. }
  1177.  
  1178. WebInspector.removeResource = function(identifier)
  1179. {
  1180.     var resource = this.resources[identifier];
  1181.     if (!resource)
  1182.         return;
  1183.  
  1184.     resource.category.removeResource(resource);
  1185.     delete this.resourceURLMap[resource.url];
  1186.     delete this.resources[identifier];
  1187.  
  1188.     if (this.panels.resources)
  1189.         this.panels.resources.removeResource(resource);
  1190. }
  1191.  
  1192. WebInspector.addDatabase = function(payload)
  1193. {
  1194.     if (!this.panels.storage)
  1195.         return;
  1196.     var database = new WebInspector.Database(
  1197.         payload.id,
  1198.         payload.domain,
  1199.         payload.name,
  1200.         payload.version);
  1201.     this.panels.storage.addDatabase(database);
  1202. }
  1203.  
  1204. WebInspector._addCookieDomain = function(domain)
  1205. {
  1206.     // Eliminate duplicate domains from the list.
  1207.     if (domain in this.cookieDomains)
  1208.         return;
  1209.     this.cookieDomains[domain] = true;
  1210.  
  1211.     if (!this.panels.storage)
  1212.         return;
  1213.     this.panels.storage.addCookieDomain(domain);
  1214. }
  1215.  
  1216. WebInspector.addDOMStorage = function(payload)
  1217. {
  1218.     if (!this.panels.storage)
  1219.         return;
  1220.     var domStorage = new WebInspector.DOMStorage(
  1221.         payload.id,
  1222.         payload.host,
  1223.         payload.isLocalStorage);
  1224.     this.panels.storage.addDOMStorage(domStorage);
  1225. }
  1226.  
  1227. WebInspector.updateDOMStorage = function(storageId)
  1228. {
  1229.     if (!this.panels.storage)
  1230.         return;
  1231.     this.panels.storage.updateDOMStorage(storageId);
  1232. }
  1233.  
  1234. WebInspector.resourceTrackingWasEnabled = function()
  1235. {
  1236.     this.panels.resources.resourceTrackingWasEnabled();
  1237. }
  1238.  
  1239. WebInspector.resourceTrackingWasDisabled = function()
  1240. {
  1241.     this.panels.resources.resourceTrackingWasDisabled();
  1242. }
  1243.  
  1244.  
  1245. WebInspector.searchingForNodeWasEnabled = function()
  1246. {
  1247.     this.panels.elements.searchingForNodeWasEnabled();
  1248. }
  1249.  
  1250. WebInspector.searchingForNodeWasDisabled = function()
  1251. {
  1252.     this.panels.elements.searchingForNodeWasDisabled();
  1253. }
  1254.  
  1255. WebInspector.attachDebuggerWhenShown = function()
  1256. {
  1257.     this.panels.scripts.attachDebuggerWhenShown();
  1258. }
  1259.  
  1260. WebInspector.debuggerWasEnabled = function()
  1261. {
  1262.     this.panels.scripts.debuggerWasEnabled();
  1263. }
  1264.  
  1265. WebInspector.updatePauseOnExceptionsState = function(pauseOnExceptionsState)
  1266. {
  1267.     this.panels.scripts.updatePauseOnExceptionsState(pauseOnExceptionsState);
  1268. }
  1269.  
  1270. WebInspector.debuggerWasDisabled = function()
  1271. {
  1272.     this.panels.scripts.debuggerWasDisabled();
  1273. }
  1274.  
  1275. WebInspector.profilerWasEnabled = function()
  1276. {
  1277.     this.panels.profiles.profilerWasEnabled();
  1278. }
  1279.  
  1280. WebInspector.profilerWasDisabled = function()
  1281. {
  1282.     this.panels.profiles.profilerWasDisabled();
  1283. }
  1284.  
  1285. WebInspector.parsedScriptSource = function(sourceID, sourceURL, source, startingLine)
  1286. {
  1287.     this.panels.scripts.addScript(sourceID, sourceURL, source, startingLine);
  1288. }
  1289.  
  1290. WebInspector.restoredBreakpoint = function(sourceID, sourceURL, line, enabled, condition)
  1291. {
  1292.     var breakpoint = new WebInspector.Breakpoint(sourceURL, line, sourceID, condition);
  1293.     breakpoint.enabled = enabled;
  1294.     this.panels.scripts.addBreakpoint(breakpoint);
  1295. }
  1296.  
  1297. WebInspector.failedToParseScriptSource = function(sourceURL, source, startingLine, errorLine, errorMessage)
  1298. {
  1299.     this.panels.scripts.addScript(null, sourceURL, source, startingLine, errorLine, errorMessage);
  1300. }
  1301.  
  1302. WebInspector.pausedScript = function(callFrames)
  1303. {
  1304.     this.panels.scripts.debuggerPaused(callFrames);
  1305. }
  1306.  
  1307. WebInspector.resumedScript = function()
  1308. {
  1309.     this.panels.scripts.debuggerResumed();
  1310. }
  1311.  
  1312. WebInspector.populateInterface = function()
  1313. {
  1314.     for (var panelName in this.panels) {
  1315.         var panel = this.panels[panelName];
  1316.         if ("populateInterface" in panel)
  1317.             panel.populateInterface();
  1318.     }
  1319. }
  1320.  
  1321. WebInspector.reset = function()
  1322. {
  1323.     for (var panelName in this.panels) {
  1324.         var panel = this.panels[panelName];
  1325.         if ("reset" in panel)
  1326.             panel.reset();
  1327.     }
  1328.  
  1329.     for (var category in this.resourceCategories)
  1330.         this.resourceCategories[category].removeAllResources();
  1331.  
  1332.     this.resources = {};
  1333.     this.resourceURLMap = {};
  1334.     this.cookieDomains = {};
  1335.     this.hoveredDOMNode = null;
  1336.  
  1337.     delete this.mainResource;
  1338.  
  1339.     this.console.clearMessages();
  1340. }
  1341.  
  1342. WebInspector.bringToFront = function()
  1343. {
  1344.     InspectorFrontendHost.bringToFront();
  1345. }
  1346.  
  1347. WebInspector.inspectedURLChanged = function(url)
  1348. {
  1349.     InspectorFrontendHost.inspectedURLChanged(url);
  1350. }
  1351.  
  1352. WebInspector.resourceURLChanged = function(resource, oldURL)
  1353. {
  1354.     delete this.resourceURLMap[oldURL];
  1355.     this.resourceURLMap[resource.url] = resource;
  1356. }
  1357.  
  1358. WebInspector.didCommitLoad = function()
  1359. {
  1360.     // Cleanup elements panel early on inspected page refresh.
  1361.     WebInspector.setDocument(null);
  1362. }
  1363.  
  1364. WebInspector.updateConsoleMessageExpiredCount = function(count)
  1365. {
  1366.     var message = String.sprintf(WebInspector.UIString("%d console messages are not shown."), count);
  1367.     WebInspector.console.addMessage(new WebInspector.ConsoleTextMessage(message, WebInspector.ConsoleMessage.MessageLevel.Warning));
  1368. }
  1369.  
  1370. WebInspector.addConsoleMessage = function(payload, opt_args)
  1371. {
  1372.     var consoleMessage = new WebInspector.ConsoleMessage(
  1373.         payload.source,
  1374.         payload.type,
  1375.         payload.level,
  1376.         payload.line,
  1377.         payload.url,
  1378.         payload.groupLevel,
  1379.         payload.repeatCount);
  1380.     consoleMessage.setMessageBody(Array.prototype.slice.call(arguments, 1));
  1381.     this.console.addMessage(consoleMessage);
  1382. }
  1383.  
  1384. WebInspector.updateConsoleMessageRepeatCount = function(count)
  1385. {
  1386.     this.console.updateMessageRepeatCount(count);
  1387. }
  1388.  
  1389. WebInspector.log = function(message, messageLevel)
  1390. {
  1391.     // remember 'this' for setInterval() callback
  1392.     var self = this;
  1393.  
  1394.     // return indication if we can actually log a message
  1395.     function isLogAvailable()
  1396.     {
  1397.         return WebInspector.ConsoleMessage && WebInspector.ObjectProxy && self.console;
  1398.     }
  1399.  
  1400.     // flush the queue of pending messages
  1401.     function flushQueue()
  1402.     {
  1403.         var queued = WebInspector.log.queued;
  1404.         if (!queued)
  1405.             return;
  1406.  
  1407.         for (var i = 0; i < queued.length; ++i)
  1408.             logMessage(queued[i]);
  1409.  
  1410.         delete WebInspector.log.queued;
  1411.     }
  1412.  
  1413.     // flush the queue if it console is available
  1414.     // - this function is run on an interval
  1415.     function flushQueueIfAvailable()
  1416.     {
  1417.         if (!isLogAvailable())
  1418.             return;
  1419.  
  1420.         clearInterval(WebInspector.log.interval);
  1421.         delete WebInspector.log.interval;
  1422.  
  1423.         flushQueue();
  1424.     }
  1425.  
  1426.     // actually log the message
  1427.     function logMessage(message)
  1428.     {
  1429.         var repeatCount = 1;
  1430.         if (message == WebInspector.log.lastMessage)
  1431.             repeatCount = WebInspector.log.repeatCount + 1;
  1432.  
  1433.         WebInspector.log.lastMessage = message;
  1434.         WebInspector.log.repeatCount = repeatCount;
  1435.  
  1436.         // ConsoleMessage expects a proxy object
  1437.         message = new WebInspector.ObjectProxy(null, null, [], message, false);
  1438.  
  1439.         // post the message
  1440.         var msg = new WebInspector.ConsoleMessage(
  1441.             WebInspector.ConsoleMessage.MessageSource.Other,
  1442.             WebInspector.ConsoleMessage.MessageType.Log,
  1443.             messageLevel || WebInspector.ConsoleMessage.MessageLevel.Debug,
  1444.             -1,
  1445.             null,
  1446.             null,
  1447.             repeatCount,
  1448.             message);
  1449.  
  1450.         self.console.addMessage(msg);
  1451.     }
  1452.  
  1453.     // if we can't log the message, queue it
  1454.     if (!isLogAvailable()) {
  1455.         if (!WebInspector.log.queued)
  1456.             WebInspector.log.queued = [];
  1457.  
  1458.         WebInspector.log.queued.push(message);
  1459.  
  1460.         if (!WebInspector.log.interval)
  1461.             WebInspector.log.interval = setInterval(flushQueueIfAvailable, 1000);
  1462.  
  1463.         return;
  1464.     }
  1465.  
  1466.     // flush the pending queue if any
  1467.     flushQueue();
  1468.  
  1469.     // log the message
  1470.     logMessage(message);
  1471. }
  1472.  
  1473. WebInspector.addProfileHeader = function(profile)
  1474. {
  1475.     this.panels.profiles.addProfileHeader(profile);
  1476. }
  1477.  
  1478. WebInspector.setRecordingProfile = function(isProfiling)
  1479. {
  1480.     this.panels.profiles.getProfileType(WebInspector.CPUProfileType.TypeId).setRecordingProfile(isProfiling);
  1481.     if (this._previousIsProfiling !== isProfiling) {
  1482.         if (!this._temporaryRecordingProfile) {
  1483.             this._temporaryRecordingProfile = {
  1484.                 typeId: WebInspector.CPUProfileType.TypeId,
  1485.                 title: WebInspector.UIString('Recording...'),
  1486.                 uid: -1,
  1487.                 isTemporary: true
  1488.             };
  1489.         }
  1490.         this._previousIsProfiling = isProfiling;
  1491.         if (isProfiling)
  1492.             this.panels.profiles.addProfileHeader(this._temporaryRecordingProfile);
  1493.         else
  1494.             this.panels.profiles.removeProfileHeader(this._temporaryRecordingProfile);
  1495.     }
  1496.     this.panels.profiles.updateProfileTypeButtons();
  1497. }
  1498.  
  1499. WebInspector.drawLoadingPieChart = function(canvas, percent) {
  1500.     var g = canvas.getContext("2d");
  1501.     var darkColor = "rgb(122, 168, 218)";
  1502.     var lightColor = "rgb(228, 241, 251)";
  1503.     var cx = 8;
  1504.     var cy = 8;
  1505.     var r = 7;
  1506.  
  1507.     g.beginPath();
  1508.     g.arc(cx, cy, r, 0, Math.PI * 2, false);
  1509.     g.closePath();
  1510.  
  1511.     g.lineWidth = 1;
  1512.     g.strokeStyle = darkColor;
  1513.     g.fillStyle = lightColor;
  1514.     g.fill();
  1515.     g.stroke();
  1516.  
  1517.     var startangle = -Math.PI / 2;
  1518.     var endangle = startangle + (percent * Math.PI * 2);
  1519.  
  1520.     g.beginPath();
  1521.     g.moveTo(cx, cy);
  1522.     g.arc(cx, cy, r, startangle, endangle, false);
  1523.     g.closePath();
  1524.  
  1525.     g.fillStyle = darkColor;
  1526.     g.fill();
  1527. }
  1528.  
  1529. WebInspector.updateFocusedNode = function(nodeId)
  1530. {
  1531.     var node = WebInspector.domAgent.nodeForId(nodeId);
  1532.     if (!node)
  1533.         // FIXME: Should we deselect if null is passed in?
  1534.         return;
  1535.  
  1536.     this.currentPanel = this.panels.elements;
  1537.     this.panels.elements.focusedDOMNode = node;
  1538. }
  1539.  
  1540. WebInspector.displayNameForURL = function(url)
  1541. {
  1542.     if (!url)
  1543.         return "";
  1544.     var resource = this.resourceURLMap[url];
  1545.     if (resource)
  1546.         return resource.displayName;
  1547.  
  1548.     if (!WebInspector.mainResource)
  1549.         return url.trimURL("");
  1550.  
  1551.     var lastPathComponent = WebInspector.mainResource.lastPathComponent;
  1552.     var index = WebInspector.mainResource.url.indexOf(lastPathComponent);
  1553.     if (index !== -1 && index + lastPathComponent.length === WebInspector.mainResource.url.length) {
  1554.         var baseURL = WebInspector.mainResource.url.substring(0, index);
  1555.         if (url.indexOf(baseURL) === 0)
  1556.             return url.substring(index);
  1557.     }
  1558.  
  1559.     return url.trimURL(WebInspector.mainResource.domain);
  1560. }
  1561.  
  1562. WebInspector.resourceForURL = function(url)
  1563. {
  1564.     if (url in this.resourceURLMap)
  1565.         return this.resourceURLMap[url];
  1566.  
  1567.     // No direct match found. Search for resources that contain
  1568.     // a substring of the URL.
  1569.     for (var resourceURL in this.resourceURLMap) {
  1570.         if (resourceURL.hasSubstring(url))
  1571.             return this.resourceURLMap[resourceURL];
  1572.     }
  1573.  
  1574.     return null;
  1575. }
  1576.  
  1577. WebInspector._choosePanelToShowSourceLine = function(url, line, preferredPanel)
  1578. {
  1579.     preferredPanel = preferredPanel || "resources";
  1580.     var panel = this.panels[preferredPanel];
  1581.     if (panel && panel.canShowSourceLine(url, line))
  1582.         return panel;
  1583.     panel = this.panels.resources;
  1584.     return panel.canShowSourceLine(url, line) ? panel : null;
  1585. }
  1586.  
  1587. WebInspector.canShowSourceLine = function(url, line, preferredPanel)
  1588. {
  1589.     return !!this._choosePanelToShowSourceLine(url, line, preferredPanel);
  1590. }
  1591.  
  1592. WebInspector.showSourceLine = function(url, line, preferredPanel)
  1593. {
  1594.     this.currentPanel = this._choosePanelToShowSourceLine(url, line, preferredPanel);
  1595.     if (!this.currentPanel)
  1596.         return false;
  1597.     this.currentPanel.showSourceLine(url, line);
  1598.     return true;
  1599. }
  1600.  
  1601. WebInspector.linkifyStringAsFragment = function(string)
  1602. {
  1603.     var container = document.createDocumentFragment();
  1604.     var linkStringRegEx = /(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\/\/|www\.)[\w$\-_+*'=\|\/\\(){}[\]%@&#~,:;.!?]{2,}[\w$\-_+*=\|\/\\({%@&#~]/;
  1605.  
  1606.     while (string) {
  1607.         var linkString = linkStringRegEx.exec(string);
  1608.         if (!linkString)
  1609.             break;
  1610.  
  1611.         linkString = linkString[0];
  1612.         var title = linkString;
  1613.         var linkIndex = string.indexOf(linkString);
  1614.         var nonLink = string.substring(0, linkIndex);
  1615.         container.appendChild(document.createTextNode(nonLink));
  1616.  
  1617.         var profileStringMatches = WebInspector.ProfileType.URLRegExp.exec(title);
  1618.         if (profileStringMatches)
  1619.             title = WebInspector.panels.profiles.displayTitleForProfileLink(profileStringMatches[2], profileStringMatches[1]);
  1620.  
  1621.         var realURL = (linkString.indexOf("www.") === 0 ? "http://" + linkString : linkString);
  1622.         container.appendChild(WebInspector.linkifyURLAsNode(realURL, title, null, (realURL in WebInspector.resourceURLMap)));
  1623.         string = string.substring(linkIndex + linkString.length, string.length);
  1624.     }
  1625.  
  1626.     if (string)
  1627.         container.appendChild(document.createTextNode(string));
  1628.  
  1629.     return container;
  1630. }
  1631.  
  1632. WebInspector.showProfileForURL = function(url)
  1633. {
  1634.     WebInspector.showProfilesPanel();
  1635.     WebInspector.panels.profiles.showProfileForURL(url);
  1636. }
  1637.  
  1638. WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal, tooltipText)
  1639. {
  1640.     if (!linkText)
  1641.         linkText = url;
  1642.     classes = (classes ? classes + " " : "");
  1643.     classes += isExternal ? "webkit-html-external-link" : "webkit-html-resource-link";
  1644.  
  1645.     var a = document.createElement("a");
  1646.     a.href = url;
  1647.     a.className = classes;
  1648.     a.title = tooltipText || url;
  1649.     a.target = "_blank";
  1650.     a.textContent = linkText;
  1651.  
  1652.     return a;
  1653. }
  1654.  
  1655. WebInspector.linkifyURL = function(url, linkText, classes, isExternal, tooltipText)
  1656. {
  1657.     // Use the DOM version of this function so as to avoid needing to escape attributes.
  1658.     // FIXME:  Get rid of linkifyURL entirely.
  1659.     return WebInspector.linkifyURLAsNode(url, linkText, classes, isExternal, tooltipText).outerHTML;
  1660. }
  1661.  
  1662. WebInspector.linkifyResourceAsNode = function(url, preferredPanel, lineNumber, classes, tooltipText)
  1663. {
  1664.     var linkText = WebInspector.displayNameForURL(url);
  1665.     if (lineNumber)
  1666.         linkText += ":" + lineNumber;
  1667.     var node = WebInspector.linkifyURLAsNode(url, linkText, classes, false, tooltipText);
  1668.     node.lineNumber = lineNumber;
  1669.     node.preferredPanel = preferredPanel;
  1670.     return node;
  1671. }
  1672.  
  1673. WebInspector.completeURL = function(baseURL, href)
  1674. {
  1675.     var match = baseURL.match(WebInspector.URLRegExp);
  1676.     if (match) {
  1677.         var path = href;
  1678.         if (path.charAt(0) !== "/") {
  1679.             var basePath = match[4] || "/";
  1680.             path = basePath.substring(0, basePath.lastIndexOf("/")) + "/" + path;
  1681.         }
  1682.         return match[1] + "://" + match[2] + (match[3] ? (":" + match[3]) : "") + path;
  1683.     }
  1684.     return null;
  1685. }
  1686.  
  1687. WebInspector.addMainEventListeners = function(doc)
  1688. {
  1689.     doc.defaultView.addEventListener("focus", this.windowFocused.bind(this), false);
  1690.     doc.defaultView.addEventListener("blur", this.windowBlurred.bind(this), false);
  1691.     doc.addEventListener("click", this.documentClick.bind(this), true);
  1692.     doc.addEventListener("mouseover", this.documentMouseOver.bind(this), true);
  1693. }
  1694.  
  1695. WebInspector._searchFieldManualFocus = function(event)
  1696. {
  1697.     this.currentFocusElement = event.target;
  1698.     this._previousFocusElement = event.target;
  1699. }
  1700.  
  1701. WebInspector._searchKeyDown = function(event)
  1702. {
  1703.     // Escape Key will clear the field and clear the search results
  1704.     if (event.keyCode === WebInspector.KeyboardShortcut.KeyCodes.Esc) {
  1705.         // If focus belongs here and text is empty - nothing to do, return unhandled.
  1706.         if (event.target.value === "" && this.currentFocusElement === this.previousFocusElement)
  1707.             return;
  1708.         event.preventDefault();
  1709.         event.stopPropagation();
  1710.         // When search was selected manually and is currently blank, we'd like Esc stay unhandled
  1711.         // and hit console drawer handler.
  1712.         event.target.value = "";
  1713.  
  1714.         this.performSearch(event);
  1715.         this.currentFocusElement = this.previousFocusElement;
  1716.         if (this.currentFocusElement === event.target)
  1717.             this.currentFocusElement.select();
  1718.         return false;
  1719.     }
  1720.  
  1721.     if (!isEnterKey(event))
  1722.         return false;
  1723.  
  1724.     // Select all of the text so the user can easily type an entirely new query.
  1725.     event.target.select();
  1726.  
  1727.     // Only call performSearch if the Enter key was pressed. Otherwise the search
  1728.     // performance is poor because of searching on every key. The search field has
  1729.     // the incremental attribute set, so we still get incremental searches.
  1730.     this.performSearch(event);
  1731.  
  1732.     // Call preventDefault since this was the Enter key. This prevents a "search" event
  1733.     // from firing for key down. This stops performSearch from being called twice in a row.
  1734.     event.preventDefault();
  1735. }
  1736.  
  1737. WebInspector.performSearch = function(event)
  1738. {
  1739.     var query = event.target.value;
  1740.     var forceSearch = event.keyIdentifier === "Enter";
  1741.     var isShortSearch = (query.length < 3);
  1742.  
  1743.     // Clear a leftover short search flag due to a non-conflicting forced search.
  1744.     if (isShortSearch && this.shortSearchWasForcedByKeyEvent && this.currentQuery !== query)
  1745.         delete this.shortSearchWasForcedByKeyEvent;
  1746.  
  1747.     // Indicate this was a forced search on a short query.
  1748.     if (isShortSearch && forceSearch)
  1749.         this.shortSearchWasForcedByKeyEvent = true;
  1750.  
  1751.     if (!query || !query.length || (!forceSearch && isShortSearch)) {
  1752.         // Prevent clobbering a short search forced by the user.
  1753.         if (this.shortSearchWasForcedByKeyEvent) {
  1754.             delete this.shortSearchWasForcedByKeyEvent;
  1755.             return;
  1756.         }
  1757.  
  1758.         delete this.currentQuery;
  1759.  
  1760.         for (var panelName in this.panels) {
  1761.             var panel = this.panels[panelName];
  1762.             if (panel.currentQuery && panel.searchCanceled)
  1763.                 panel.searchCanceled();
  1764.             delete panel.currentQuery;
  1765.         }
  1766.  
  1767.         this.updateSearchMatchesCount();
  1768.  
  1769.         return;
  1770.     }
  1771.  
  1772.     if (query === this.currentPanel.currentQuery && this.currentPanel.currentQuery === this.currentQuery) {
  1773.         // When this is the same query and a forced search, jump to the next
  1774.         // search result for a good user experience.
  1775.         if (forceSearch && this.currentPanel.jumpToNextSearchResult)
  1776.             this.currentPanel.jumpToNextSearchResult();
  1777.         return;
  1778.     }
  1779.  
  1780.     this.currentQuery = query;
  1781.  
  1782.     this.updateSearchMatchesCount();
  1783.  
  1784.     if (!this.currentPanel.performSearch)
  1785.         return;
  1786.  
  1787.     this.currentPanel.currentQuery = query;
  1788.     this.currentPanel.performSearch(query);
  1789. }
  1790.  
  1791. WebInspector.addNodesToSearchResult = function(nodeIds)
  1792. {
  1793.     WebInspector.panels.elements.addNodesToSearchResult(nodeIds);
  1794. }
  1795.  
  1796. WebInspector.updateSearchMatchesCount = function(matches, panel)
  1797. {
  1798.     if (!panel)
  1799.         panel = this.currentPanel;
  1800.  
  1801.     panel.currentSearchMatches = matches;
  1802.  
  1803.     if (panel !== this.currentPanel)
  1804.         return;
  1805.  
  1806.     if (!this.currentPanel.currentQuery) {
  1807.         document.getElementById("search-results-matches").addStyleClass("hidden");
  1808.         return;
  1809.     }
  1810.  
  1811.     if (matches) {
  1812.         if (matches === 1)
  1813.             var matchesString = WebInspector.UIString("1 match");
  1814.         else
  1815.             var matchesString = WebInspector.UIString("%d matches", matches);
  1816.     } else
  1817.         var matchesString = WebInspector.UIString("Not Found");
  1818.  
  1819.     var matchesToolbarElement = document.getElementById("search-results-matches");
  1820.     matchesToolbarElement.removeStyleClass("hidden");
  1821.     matchesToolbarElement.textContent = matchesString;
  1822. }
  1823.  
  1824. WebInspector.UIString = function(string)
  1825. {
  1826.     if (window.localizedStrings && string in window.localizedStrings)
  1827.         string = window.localizedStrings[string];
  1828.     else {
  1829.         if (!(string in this.missingLocalizedStrings)) {
  1830.             if (!WebInspector.InspectorBackendStub)
  1831.                 console.error("Localized string \"" + string + "\" not found.");
  1832.             this.missingLocalizedStrings[string] = true;
  1833.         }
  1834.  
  1835.         if (Preferences.showMissingLocalizedStrings)
  1836.             string += " (not localized)";
  1837.     }
  1838.  
  1839.     return String.vsprintf(string, Array.prototype.slice.call(arguments, 1));
  1840. }
  1841.  
  1842. WebInspector.isMac = function()
  1843. {
  1844.     if (!("_isMac" in this))
  1845.         this._isMac = WebInspector.platform === "mac";
  1846.  
  1847.     return this._isMac;
  1848. }
  1849.  
  1850. WebInspector.isBeingEdited = function(element)
  1851. {
  1852.     return element.__editing;
  1853. }
  1854.  
  1855. WebInspector.isEditingAnyField = function()
  1856. {
  1857.     return this.__editing;
  1858. }
  1859.  
  1860. WebInspector.startEditing = function(element, committedCallback, cancelledCallback, context, multiline)
  1861. {
  1862.     if (element.__editing)
  1863.         return;
  1864.     element.__editing = true;
  1865.     WebInspector.__editing = true;
  1866.  
  1867.     var oldText = getContent(element);
  1868.     var moveDirection = "";
  1869.  
  1870.     element.addStyleClass("editing");
  1871.  
  1872.     var oldTabIndex = element.tabIndex;
  1873.     if (element.tabIndex < 0)
  1874.         element.tabIndex = 0;
  1875.  
  1876.     function blurEventListener() {
  1877.         editingCommitted.call(element);
  1878.     }
  1879.  
  1880.     function getContent(element) {
  1881.         if (element.tagName === "INPUT" && element.type === "text")
  1882.             return element.value;
  1883.         else
  1884.             return element.textContent;
  1885.     }
  1886.  
  1887.     function cleanUpAfterEditing() {
  1888.         delete this.__editing;
  1889.         delete WebInspector.__editing;
  1890.  
  1891.         this.removeStyleClass("editing");
  1892.         this.tabIndex = oldTabIndex;
  1893.         this.scrollTop = 0;
  1894.         this.scrollLeft = 0;
  1895.  
  1896.         element.removeEventListener("blur", blurEventListener, false);
  1897.         element.removeEventListener("keydown", keyDownEventListener, true);
  1898.  
  1899.         if (element === WebInspector.currentFocusElement || element.isAncestor(WebInspector.currentFocusElement))
  1900.             WebInspector.currentFocusElement = WebInspector.previousFocusElement;
  1901.     }
  1902.  
  1903.     function editingCancelled() {
  1904.         if (this.tagName === "INPUT" && this.type === "text")
  1905.             this.value = oldText;
  1906.         else
  1907.             this.textContent = oldText;
  1908.  
  1909.         cleanUpAfterEditing.call(this);
  1910.  
  1911.         if (cancelledCallback)
  1912.             cancelledCallback(this, context);
  1913.     }
  1914.  
  1915.     function editingCommitted() {
  1916.         cleanUpAfterEditing.call(this);
  1917.  
  1918.         if (committedCallback)
  1919.             committedCallback(this, getContent(this), oldText, context, moveDirection);
  1920.     }
  1921.  
  1922.     function keyDownEventListener(event) {
  1923.         var isMetaOrCtrl = WebInspector.isMac() ?
  1924.             event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey :
  1925.             event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;
  1926.         if (isEnterKey(event) && (!multiline || isMetaOrCtrl)) {
  1927.             editingCommitted.call(element);
  1928.             event.preventDefault();
  1929.             event.stopPropagation();
  1930.         } else if (event.keyCode === WebInspector.KeyboardShortcut.KeyCodes.Esc) {
  1931.             editingCancelled.call(element);
  1932.             event.preventDefault();
  1933.             event.stopPropagation();
  1934.         } else if (event.keyIdentifier === "U+0009") // Tab key
  1935.             moveDirection = (event.shiftKey ? "backward" : "forward");
  1936.     }
  1937.  
  1938.     element.addEventListener("blur", blurEventListener, false);
  1939.     element.addEventListener("keydown", keyDownEventListener, true);
  1940.  
  1941.     WebInspector.currentFocusElement = element;
  1942.     return {
  1943.         cancel: editingCancelled.bind(element),
  1944.         commit: editingCommitted.bind(element)
  1945.     };
  1946. }
  1947.  
  1948. WebInspector._toolbarItemClicked = function(event)
  1949. {
  1950.     var toolbarItem = event.currentTarget;
  1951.     this.currentPanel = toolbarItem.panel;
  1952. }
  1953.  
  1954. // This table maps MIME types to the Resource.Types which are valid for them.
  1955. // The following line:
  1956. //    "text/html":                {0: 1},
  1957. // means that text/html is a valid MIME type for resources that have type
  1958. // WebInspector.Resource.Type.Document (which has a value of 0).
  1959. WebInspector.MIMETypes = {
  1960.     "text/html":                   {0: true},
  1961.     "text/xml":                    {0: true},
  1962.     "text/plain":                  {0: true},
  1963.     "application/xhtml+xml":       {0: true},
  1964.     "text/css":                    {1: true},
  1965.     "text/xsl":                    {1: true},
  1966.     "image/jpeg":                  {2: true},
  1967.     "image/png":                   {2: true},
  1968.     "image/gif":                   {2: true},
  1969.     "image/bmp":                   {2: true},
  1970.     "image/vnd.microsoft.icon":    {2: true},
  1971.     "image/x-icon":                {2: true},
  1972.     "image/x-xbitmap":             {2: true},
  1973.     "font/ttf":                    {3: true},
  1974.     "font/opentype":               {3: true},
  1975.     "application/x-font-type1":    {3: true},
  1976.     "application/x-font-ttf":      {3: true},
  1977.     "application/x-truetype-font": {3: true},
  1978.     "text/javascript":             {4: true},
  1979.     "text/ecmascript":             {4: true},
  1980.     "application/javascript":      {4: true},
  1981.     "application/ecmascript":      {4: true},
  1982.     "application/x-javascript":    {4: true},
  1983.     "text/javascript1.1":          {4: true},
  1984.     "text/javascript1.2":          {4: true},
  1985.     "text/javascript1.3":          {4: true},
  1986.     "text/jscript":                {4: true},
  1987.     "text/livescript":             {4: true},
  1988. }
  1989.  
  1990. WebInspector.PanelHistory = function()
  1991. {
  1992.     this._history = [];
  1993.     this._historyIterator = -1;
  1994. }
  1995.  
  1996. WebInspector.PanelHistory.prototype = {
  1997.     canGoBack: function()
  1998.     {
  1999.         return this._historyIterator > 0;
  2000.     },
  2001.  
  2002.     goBack: function()
  2003.     {
  2004.         this._inHistory = true;
  2005.         WebInspector.currentPanel = WebInspector.panels[this._history[--this._historyIterator]];
  2006.         delete this._inHistory;
  2007.     },
  2008.  
  2009.     canGoForward: function()
  2010.     {
  2011.         return this._historyIterator < this._history.length - 1;
  2012.     },
  2013.  
  2014.     goForward: function()
  2015.     {
  2016.         this._inHistory = true;
  2017.         WebInspector.currentPanel = WebInspector.panels[this._history[++this._historyIterator]];
  2018.         delete this._inHistory;
  2019.     },
  2020.  
  2021.     setPanel: function(panelName)
  2022.     {
  2023.         if (this._inHistory)
  2024.             return;
  2025.  
  2026.         this._history.splice(this._historyIterator + 1, this._history.length - this._historyIterator - 1);
  2027.         if (!this._history.length || this._history[this._history.length - 1] !== panelName)
  2028.             this._history.push(panelName);
  2029.         this._historyIterator = this._history.length - 1;
  2030.     }
  2031. }
  2032.