summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/devtools/front_end/sources
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/devtools/front_end/sources
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/devtools/front_end/sources')
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/BreakpointsSidebarPane.js816
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js100
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/CallStackSidebarPane.js369
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/EditingLocationHistoryManager.js196
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/FilePathScoreFunction.js210
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/FilteredItemSelectionDialog.js941
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/InplaceFormatterEditorAction.js115
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js845
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js1434
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/Placard.js132
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/RevisionHistoryView.js322
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js184
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatter.js270
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatterEditorAction.js379
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/SimpleHistoryManager.js167
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js205
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js1479
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js708
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/StyleSheetOutlineDialog.js120
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/TabbedEditorContainer.js739
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/TargetsToolbar.js78
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js190
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js518
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/WorkersSidebarPane.js119
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sources/module.json173
25 files changed, 10809 insertions, 0 deletions
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/BreakpointsSidebarPane.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/BreakpointsSidebarPane.js
new file mode 100644
index 00000000000..ab6b8b18a74
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/BreakpointsSidebarPane.js
@@ -0,0 +1,816 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.SidebarPane}
+ * @param {!WebInspector.DebuggerModel} debuggerModel
+ * @param {!WebInspector.BreakpointManager} breakpointManager
+ * @param {function(!WebInspector.UISourceCode, number=, number=, boolean=)} showSourceLineDelegate
+ */
+WebInspector.JavaScriptBreakpointsSidebarPane = function(debuggerModel, breakpointManager, showSourceLineDelegate)
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints"));
+ this._debuggerModel = debuggerModel;
+ this.registerRequiredCSS("breakpointsList.css");
+
+ this._breakpointManager = breakpointManager;
+ this._showSourceLineDelegate = showSourceLineDelegate;
+
+ this.listElement = document.createElement("ol");
+ this.listElement.className = "breakpoint-list";
+
+ this.emptyElement = document.createElement("div");
+ this.emptyElement.className = "info";
+ this.emptyElement.textContent = WebInspector.UIString("No Breakpoints");
+
+ this.bodyElement.appendChild(this.emptyElement);
+
+ this._items = new Map();
+
+ var breakpointLocations = this._breakpointManager.allBreakpointLocations();
+ for (var i = 0; i < breakpointLocations.length; ++i)
+ this._addBreakpoint(breakpointLocations[i].breakpoint, breakpointLocations[i].uiLocation);
+
+ this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
+ this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this);
+
+ this.emptyElement.addEventListener("contextmenu", this._emptyElementContextMenu.bind(this), true);
+}
+
+WebInspector.JavaScriptBreakpointsSidebarPane.prototype = {
+ _emptyElementContextMenu: function(event)
+ {
+ var contextMenu = new WebInspector.ContextMenu(event);
+ var breakpointActive = this._debuggerModel.breakpointsActive();
+ var breakpointActiveTitle = breakpointActive ?
+ WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Deactivate breakpoints" : "Deactivate Breakpoints") :
+ WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Activate breakpoints" : "Activate Breakpoints");
+ contextMenu.appendItem(breakpointActiveTitle, this._debuggerModel.setBreakpointsActive.bind(this._debuggerModel, !breakpointActive));
+ contextMenu.show();
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _breakpointAdded: function(event)
+ {
+ this._breakpointRemoved(event);
+
+ var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
+ var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiLocation);
+ this._addBreakpoint(breakpoint, uiLocation);
+ },
+
+ /**
+ * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
+ * @param {!WebInspector.UILocation} uiLocation
+ */
+ _addBreakpoint: function(breakpoint, uiLocation)
+ {
+ var element = document.createElement("li");
+ element.classList.add("cursor-pointer");
+ element.addEventListener("contextmenu", this._breakpointContextMenu.bind(this, breakpoint), true);
+ element.addEventListener("click", this._breakpointClicked.bind(this, uiLocation), false);
+
+ var checkbox = document.createElement("input");
+ checkbox.className = "checkbox-elem";
+ checkbox.type = "checkbox";
+ checkbox.checked = breakpoint.enabled();
+ checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, breakpoint), false);
+ element.appendChild(checkbox);
+
+ var labelElement = document.createTextNode(uiLocation.linkText());
+ element.appendChild(labelElement);
+
+ var snippetElement = document.createElement("div");
+ snippetElement.className = "source-text monospace";
+ element.appendChild(snippetElement);
+
+ /**
+ * @param {?string} content
+ */
+ function didRequestContent(content)
+ {
+ var lineNumber = uiLocation.lineNumber
+ var columnNumber = uiLocation.columnNumber;
+ var contentString = new String(content);
+ if (lineNumber < contentString.lineCount()) {
+ var lineText = contentString.lineAt(lineNumber);
+ var maxSnippetLength = 200;
+ snippetElement.textContent = lineText.substr(columnNumber).trimEnd(maxSnippetLength);
+ }
+ }
+
+ uiLocation.uiSourceCode.requestContent(didRequestContent);
+
+ element._data = uiLocation;
+ var currentElement = this.listElement.firstChild;
+ while (currentElement) {
+ if (currentElement._data && this._compareBreakpoints(currentElement._data, element._data) > 0)
+ break;
+ currentElement = currentElement.nextSibling;
+ }
+ this._addListElement(element, currentElement);
+
+ var breakpointItem = {};
+ breakpointItem.element = element;
+ breakpointItem.checkbox = checkbox;
+ this._items.put(breakpoint, breakpointItem);
+
+ this.expand();
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _breakpointRemoved: function(event)
+ {
+ var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
+ var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiLocation);
+ var breakpointItem = this._items.get(breakpoint);
+ if (!breakpointItem)
+ return;
+ this._items.remove(breakpoint);
+ this._removeListElement(breakpointItem.element);
+ },
+
+ /**
+ * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
+ */
+ highlightBreakpoint: function(breakpoint)
+ {
+ var breakpointItem = this._items.get(breakpoint);
+ if (!breakpointItem)
+ return;
+ breakpointItem.element.classList.add("breakpoint-hit");
+ this._highlightedBreakpointItem = breakpointItem;
+ },
+
+ clearBreakpointHighlight: function()
+ {
+ if (this._highlightedBreakpointItem) {
+ this._highlightedBreakpointItem.element.classList.remove("breakpoint-hit");
+ delete this._highlightedBreakpointItem;
+ }
+ },
+
+ _breakpointClicked: function(uiLocation, event)
+ {
+ this._showSourceLineDelegate(uiLocation.uiSourceCode, uiLocation.lineNumber);
+ },
+
+ /**
+ * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
+ * @param {?Event} event
+ */
+ _breakpointCheckboxClicked: function(breakpoint, event)
+ {
+ // Breakpoint element has it's own click handler.
+ event.consume();
+ breakpoint.setEnabled(event.target.checked);
+ },
+
+ /**
+ * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
+ * @param {?Event} event
+ */
+ _breakpointContextMenu: function(breakpoint, event)
+ {
+ var breakpoints = this._items.values();
+ var contextMenu = new WebInspector.ContextMenu(event);
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), breakpoint.remove.bind(breakpoint));
+ if (breakpoints.length > 1) {
+ var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all breakpoints" : "Remove All Breakpoints");
+ contextMenu.appendItem(removeAllTitle, this._breakpointManager.removeAllBreakpoints.bind(this._breakpointManager));
+ }
+
+ contextMenu.appendSeparator();
+ var breakpointActive = this._debuggerModel.breakpointsActive();
+ var breakpointActiveTitle = breakpointActive ?
+ WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Deactivate breakpoints" : "Deactivate Breakpoints") :
+ WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Activate breakpoints" : "Activate Breakpoints");
+ contextMenu.appendItem(breakpointActiveTitle, this._debuggerModel.setBreakpointsActive.bind(this._debuggerModel, !breakpointActive));
+
+ function enabledBreakpointCount(breakpoints)
+ {
+ var count = 0;
+ for (var i = 0; i < breakpoints.length; ++i) {
+ if (breakpoints[i].checkbox.checked)
+ count++;
+ }
+ return count;
+ }
+ if (breakpoints.length > 1) {
+ var enableBreakpointCount = enabledBreakpointCount(breakpoints);
+ var enableTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Enable all breakpoints" : "Enable All Breakpoints");
+ var disableTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Disable all breakpoints" : "Disable All Breakpoints");
+
+ contextMenu.appendSeparator();
+
+ contextMenu.appendItem(enableTitle, this._breakpointManager.toggleAllBreakpoints.bind(this._breakpointManager, true), !(enableBreakpointCount != breakpoints.length));
+ contextMenu.appendItem(disableTitle, this._breakpointManager.toggleAllBreakpoints.bind(this._breakpointManager, false), !(enableBreakpointCount > 1));
+ }
+
+ contextMenu.show();
+ },
+
+ _addListElement: function(element, beforeElement)
+ {
+ if (beforeElement)
+ this.listElement.insertBefore(element, beforeElement);
+ else {
+ if (!this.listElement.firstChild) {
+ this.bodyElement.removeChild(this.emptyElement);
+ this.bodyElement.appendChild(this.listElement);
+ }
+ this.listElement.appendChild(element);
+ }
+ },
+
+ _removeListElement: function(element)
+ {
+ this.listElement.removeChild(element);
+ if (!this.listElement.firstChild) {
+ this.bodyElement.removeChild(this.listElement);
+ this.bodyElement.appendChild(this.emptyElement);
+ }
+ },
+
+ _compare: function(x, y)
+ {
+ if (x !== y)
+ return x < y ? -1 : 1;
+ return 0;
+ },
+
+ _compareBreakpoints: function(b1, b2)
+ {
+ return this._compare(b1.uiSourceCode.originURL(), b2.uiSourceCode.originURL()) || this._compare(b1.lineNumber, b2.lineNumber);
+ },
+
+ reset: function()
+ {
+ this.listElement.removeChildren();
+ if (this.listElement.parentElement) {
+ this.bodyElement.removeChild(this.listElement);
+ this.bodyElement.appendChild(this.emptyElement);
+ }
+ this._items.clear();
+ },
+
+ __proto__: WebInspector.SidebarPane.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.NativeBreakpointsSidebarPane}
+ */
+WebInspector.XHRBreakpointsSidebarPane = function()
+{
+ WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("XHR Breakpoints"));
+
+ this._breakpointElements = {};
+
+ var addButton = document.createElement("button");
+ addButton.className = "pane-title-button add";
+ addButton.addEventListener("click", this._addButtonClicked.bind(this), false);
+ addButton.title = WebInspector.UIString("Add XHR breakpoint");
+ this.titleElement.appendChild(addButton);
+
+ this.emptyElement.addEventListener("contextmenu", this._emptyElementContextMenu.bind(this), true);
+
+ this._restoreBreakpoints();
+}
+
+WebInspector.XHRBreakpointsSidebarPane.prototype = {
+ _emptyElementContextMenu: function(event)
+ {
+ var contextMenu = new WebInspector.ContextMenu(event);
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._addButtonClicked.bind(this));
+ contextMenu.show();
+ },
+
+ _addButtonClicked: function(event)
+ {
+ if (event)
+ event.consume();
+
+ this.expand();
+
+ var inputElementContainer = document.createElement("p");
+ inputElementContainer.className = "breakpoint-condition";
+ var inputElement = document.createElement("span");
+ inputElementContainer.textContent = WebInspector.UIString("Break when URL contains:");
+ inputElement.className = "editing";
+ inputElement.id = "breakpoint-condition-input";
+ inputElementContainer.appendChild(inputElement);
+ this._addListElement(inputElementContainer, this.listElement.firstChild);
+
+ /**
+ * @param {boolean} accept
+ * @param {!Element} e
+ * @param {string} text
+ * @this {WebInspector.XHRBreakpointsSidebarPane}
+ */
+ function finishEditing(accept, e, text)
+ {
+ this._removeListElement(inputElementContainer);
+ if (accept) {
+ this._setBreakpoint(text, true);
+ this._saveBreakpoints();
+ }
+ }
+
+ var config = new WebInspector.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false));
+ WebInspector.InplaceEditor.startEditing(inputElement, config);
+ },
+
+ _setBreakpoint: function(url, enabled)
+ {
+ if (url in this._breakpointElements)
+ return;
+
+ var element = document.createElement("li");
+ element._url = url;
+ element.addEventListener("contextmenu", this._contextMenu.bind(this, url), true);
+
+ var checkboxElement = document.createElement("input");
+ checkboxElement.className = "checkbox-elem";
+ checkboxElement.type = "checkbox";
+ checkboxElement.checked = enabled;
+ checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, url), false);
+ element._checkboxElement = checkboxElement;
+ element.appendChild(checkboxElement);
+
+ var labelElement = document.createElement("span");
+ if (!url)
+ labelElement.textContent = WebInspector.UIString("Any XHR");
+ else
+ labelElement.textContent = WebInspector.UIString("URL contains \"%s\"", url);
+ labelElement.classList.add("cursor-auto");
+ labelElement.addEventListener("dblclick", this._labelClicked.bind(this, url), false);
+ element.appendChild(labelElement);
+
+ var currentElement = this.listElement.firstChild;
+ while (currentElement) {
+ if (currentElement._url && currentElement._url < element._url)
+ break;
+ currentElement = currentElement.nextSibling;
+ }
+ this._addListElement(element, currentElement);
+ this._breakpointElements[url] = element;
+ if (enabled)
+ DOMDebuggerAgent.setXHRBreakpoint(url);
+ },
+
+ _removeBreakpoint: function(url)
+ {
+ var element = this._breakpointElements[url];
+ if (!element)
+ return;
+
+ this._removeListElement(element);
+ delete this._breakpointElements[url];
+ if (element._checkboxElement.checked)
+ DOMDebuggerAgent.removeXHRBreakpoint(url);
+ },
+
+ _contextMenu: function(url, event)
+ {
+ var contextMenu = new WebInspector.ContextMenu(event);
+
+ /**
+ * @this {WebInspector.XHRBreakpointsSidebarPane}
+ */
+ function removeBreakpoint()
+ {
+ this._removeBreakpoint(url);
+ this._saveBreakpoints();
+ }
+
+ /**
+ * @this {WebInspector.XHRBreakpointsSidebarPane}
+ */
+ function removeAllBreakpoints()
+ {
+ for (var url in this._breakpointElements)
+ this._removeBreakpoint(url);
+ this._saveBreakpoints();
+ }
+ var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all breakpoints" : "Remove All Breakpoints");
+
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._addButtonClicked.bind(this));
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), removeBreakpoint.bind(this));
+ contextMenu.appendItem(removeAllTitle, removeAllBreakpoints.bind(this));
+ contextMenu.show();
+ },
+
+ _checkboxClicked: function(url, event)
+ {
+ if (event.target.checked)
+ DOMDebuggerAgent.setXHRBreakpoint(url);
+ else
+ DOMDebuggerAgent.removeXHRBreakpoint(url);
+ this._saveBreakpoints();
+ },
+
+ _labelClicked: function(url)
+ {
+ var element = this._breakpointElements[url];
+ var inputElement = document.createElement("span");
+ inputElement.className = "breakpoint-condition editing";
+ inputElement.textContent = url;
+ this.listElement.insertBefore(inputElement, element);
+ element.classList.add("hidden");
+
+ /**
+ * @param {boolean} accept
+ * @param {!Element} e
+ * @param {string} text
+ * @this {WebInspector.XHRBreakpointsSidebarPane}
+ */
+ function finishEditing(accept, e, text)
+ {
+ this._removeListElement(inputElement);
+ if (accept) {
+ this._removeBreakpoint(url);
+ this._setBreakpoint(text, element._checkboxElement.checked);
+ this._saveBreakpoints();
+ } else
+ element.classList.remove("hidden");
+ }
+
+ WebInspector.InplaceEditor.startEditing(inputElement, new WebInspector.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false)));
+ },
+
+ highlightBreakpoint: function(url)
+ {
+ var element = this._breakpointElements[url];
+ if (!element)
+ return;
+ this.expand();
+ element.classList.add("breakpoint-hit");
+ this._highlightedElement = element;
+ },
+
+ clearBreakpointHighlight: function()
+ {
+ if (this._highlightedElement) {
+ this._highlightedElement.classList.remove("breakpoint-hit");
+ delete this._highlightedElement;
+ }
+ },
+
+ _saveBreakpoints: function()
+ {
+ var breakpoints = [];
+ for (var url in this._breakpointElements)
+ breakpoints.push({ url: url, enabled: this._breakpointElements[url]._checkboxElement.checked });
+ WebInspector.settings.xhrBreakpoints.set(breakpoints);
+ },
+
+ _restoreBreakpoints: function()
+ {
+ var breakpoints = WebInspector.settings.xhrBreakpoints.get();
+ for (var i = 0; i < breakpoints.length; ++i) {
+ var breakpoint = breakpoints[i];
+ if (breakpoint && typeof breakpoint.url === "string")
+ this._setBreakpoint(breakpoint.url, breakpoint.enabled);
+ }
+ },
+
+ __proto__: WebInspector.NativeBreakpointsSidebarPane.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.SidebarPane}
+ */
+WebInspector.EventListenerBreakpointsSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listener Breakpoints"));
+ this.registerRequiredCSS("breakpointsList.css");
+
+ this.categoriesElement = document.createElement("ol");
+ this.categoriesElement.tabIndex = 0;
+ this.categoriesElement.classList.add("properties-tree");
+ this.categoriesElement.classList.add("event-listener-breakpoints");
+ this.categoriesTreeOutline = new TreeOutline(this.categoriesElement);
+ this.bodyElement.appendChild(this.categoriesElement);
+
+ this._categoryItems = [];
+ // FIXME: uncomment following once inspector stops being drop targer in major ports.
+ // Otherwise, inspector page reacts on drop event and tries to load the event data.
+ // this._createCategory(WebInspector.UIString("Drag"), ["drag", "drop", "dragstart", "dragend", "dragenter", "dragleave", "dragover"]);
+ this._createCategory(WebInspector.UIString("Animation"), ["requestAnimationFrame", "cancelAnimationFrame", "animationFrameFired"], true);
+ this._createCategory(WebInspector.UIString("Control"), ["resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset"]);
+ this._createCategory(WebInspector.UIString("Clipboard"), ["copy", "cut", "paste", "beforecopy", "beforecut", "beforepaste"]);
+ this._createCategory(WebInspector.UIString("DOM Mutation"), ["DOMActivate", "DOMFocusIn", "DOMFocusOut", "DOMAttrModified", "DOMCharacterDataModified", "DOMNodeInserted", "DOMNodeInsertedIntoDocument", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMSubtreeModified", "DOMContentLoaded"]);
+ this._createCategory(WebInspector.UIString("Device"), ["deviceorientation", "devicemotion"]);
+ this._createCategory(WebInspector.UIString("Drag / drop"), ["dragenter", "dragover", "dragleave", "drop"]);
+ this._createCategory(WebInspector.UIString("Keyboard"), ["keydown", "keyup", "keypress", "input"]);
+ this._createCategory(WebInspector.UIString("Load"), ["load", "beforeunload", "unload", "abort", "error", "hashchange", "popstate"]);
+ this._createCategory(WebInspector.UIString("Mouse"), ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mousewheel", "wheel"]);
+ this._createCategory(WebInspector.UIString("Timer"), ["setTimer", "clearTimer", "timerFired"], true);
+ this._createCategory(WebInspector.UIString("Touch"), ["touchstart", "touchmove", "touchend", "touchcancel"]);
+ this._createCategory(WebInspector.UIString("XHR"), ["readystatechange", "load", "loadstart", "loadend", "abort", "error", "progress", "timeout"], false, ["XMLHttpRequest", "XMLHttpRequestUpload"]);
+ this._createCategory(WebInspector.UIString("WebGL"), ["webglErrorFired", "webglWarningFired"], true);
+
+ this._restoreBreakpoints();
+}
+
+WebInspector.EventListenerBreakpointsSidebarPane.categoryListener = "listener:";
+WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation = "instrumentation:";
+WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny = "*";
+
+/**
+ * @param {string} eventName
+ * @param {!Object=} auxData
+ * @return {string}
+ */
+WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI = function(eventName, auxData)
+{
+ if (!WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI) {
+ WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI = {
+ "instrumentation:setTimer": WebInspector.UIString("Set Timer"),
+ "instrumentation:clearTimer": WebInspector.UIString("Clear Timer"),
+ "instrumentation:timerFired": WebInspector.UIString("Timer Fired"),
+ "instrumentation:requestAnimationFrame": WebInspector.UIString("Request Animation Frame"),
+ "instrumentation:cancelAnimationFrame": WebInspector.UIString("Cancel Animation Frame"),
+ "instrumentation:animationFrameFired": WebInspector.UIString("Animation Frame Fired"),
+ "instrumentation:webglErrorFired": WebInspector.UIString("WebGL Error Fired"),
+ "instrumentation:webglWarningFired": WebInspector.UIString("WebGL Warning Fired")
+ };
+ }
+ if (auxData) {
+ if (eventName === "instrumentation:webglErrorFired" && auxData["webglErrorName"]) {
+ var errorName = auxData["webglErrorName"];
+ // If there is a hex code of the error, display only this.
+ errorName = errorName.replace(/^.*(0x[0-9a-f]+).*$/i, "$1");
+ return WebInspector.UIString("WebGL Error Fired (%s)", errorName);
+ }
+ }
+ return WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI[eventName] || eventName.substring(eventName.indexOf(":") + 1);
+}
+
+WebInspector.EventListenerBreakpointsSidebarPane.prototype = {
+ /**
+ * @param {string} name
+ * @param {!Array.<string>} eventNames
+ * @param {boolean=} isInstrumentationEvent
+ * @param {!Array.<string>=} targetNames
+ */
+ _createCategory: function(name, eventNames, isInstrumentationEvent, targetNames)
+ {
+ var labelNode = document.createElement("label");
+ labelNode.textContent = name;
+
+ var categoryItem = {};
+ categoryItem.element = new TreeElement(labelNode);
+ this.categoriesTreeOutline.appendChild(categoryItem.element);
+ categoryItem.element.listItemElement.classList.add("event-category");
+ categoryItem.element.selectable = true;
+
+ categoryItem.checkbox = this._createCheckbox(labelNode);
+ categoryItem.checkbox.addEventListener("click", this._categoryCheckboxClicked.bind(this, categoryItem), true);
+
+ categoryItem.targetNames = this._stringArrayToLowerCase(targetNames || [WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny]);
+ categoryItem.children = {};
+ var category = (isInstrumentationEvent ? WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation : WebInspector.EventListenerBreakpointsSidebarPane.categoryListener);
+ for (var i = 0; i < eventNames.length; ++i) {
+ var eventName = category + eventNames[i];
+
+ var breakpointItem = {};
+ var title = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName);
+
+ labelNode = document.createElement("label");
+ labelNode.textContent = title;
+
+ breakpointItem.element = new TreeElement(labelNode);
+ categoryItem.element.appendChild(breakpointItem.element);
+
+ breakpointItem.element.listItemElement.createChild("div", "breakpoint-hit-marker");
+ breakpointItem.element.listItemElement.classList.add("source-code");
+ breakpointItem.element.selectable = false;
+
+ breakpointItem.checkbox = this._createCheckbox(labelNode);
+ breakpointItem.checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, eventName, categoryItem.targetNames), true);
+ breakpointItem.parent = categoryItem;
+
+ categoryItem.children[eventName] = breakpointItem;
+ }
+ this._categoryItems.push(categoryItem);
+ },
+
+ /**
+ * @param {!Array.<string>} array
+ * @return {!Array.<string>}
+ */
+ _stringArrayToLowerCase: function(array)
+ {
+ return array.map(function(value) {
+ return value.toLowerCase();
+ });
+ },
+
+ /**
+ * @param {!Element} labelNode
+ * @return {!Element}
+ */
+ _createCheckbox: function(labelNode)
+ {
+ var checkbox = document.createElement("input");
+ checkbox.className = "checkbox-elem";
+ checkbox.type = "checkbox";
+
+ labelNode.insertBefore(checkbox, labelNode.firstChild);
+ return checkbox;
+ },
+
+ _categoryCheckboxClicked: function(categoryItem)
+ {
+ var checked = categoryItem.checkbox.checked;
+ for (var eventName in categoryItem.children) {
+ var breakpointItem = categoryItem.children[eventName];
+ if (breakpointItem.checkbox.checked === checked)
+ continue;
+ if (checked)
+ this._setBreakpoint(eventName, categoryItem.targetNames);
+ else
+ this._removeBreakpoint(eventName, categoryItem.targetNames);
+ }
+ this._saveBreakpoints();
+ },
+
+ /**
+ * @param {string} eventName
+ * @param {!Array.<string>} targetNames
+ * @param {?Event} event
+ */
+ _breakpointCheckboxClicked: function(eventName, targetNames, event)
+ {
+ if (event.target.checked)
+ this._setBreakpoint(eventName, targetNames);
+ else
+ this._removeBreakpoint(eventName, targetNames);
+ this._saveBreakpoints();
+ },
+
+ /**
+ * @param {string} eventName
+ * @param {?Array.<string>=} targetNames
+ */
+ _setBreakpoint: function(eventName, targetNames)
+ {
+ targetNames = targetNames || [WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny];
+ for (var i = 0; i < targetNames.length; ++i) {
+ var targetName = targetNames[i];
+ var breakpointItem = this._findBreakpointItem(eventName, targetName);
+ if (!breakpointItem)
+ continue;
+ breakpointItem.checkbox.checked = true;
+ breakpointItem.parent.dirtyCheckbox = true;
+ if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categoryListener))
+ DOMDebuggerAgent.setEventListenerBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categoryListener.length), targetName);
+ else if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation))
+ DOMDebuggerAgent.setInstrumentationBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation.length));
+ }
+ this._updateCategoryCheckboxes();
+ },
+
+ /**
+ * @param {string} eventName
+ * @param {?Array.<string>=} targetNames
+ */
+ _removeBreakpoint: function(eventName, targetNames)
+ {
+ targetNames = targetNames || [WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny];
+ for (var i = 0; i < targetNames.length; ++i) {
+ var targetName = targetNames[i];
+ var breakpointItem = this._findBreakpointItem(eventName, targetName);
+ if (!breakpointItem)
+ continue;
+ breakpointItem.checkbox.checked = false;
+ breakpointItem.parent.dirtyCheckbox = true;
+ if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categoryListener))
+ DOMDebuggerAgent.removeEventListenerBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categoryListener.length), targetName);
+ else if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation))
+ DOMDebuggerAgent.removeInstrumentationBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation.length));
+ }
+ this._updateCategoryCheckboxes();
+ },
+
+ _updateCategoryCheckboxes: function()
+ {
+ for (var i = 0; i < this._categoryItems.length; ++i) {
+ var categoryItem = this._categoryItems[i];
+ if (!categoryItem.dirtyCheckbox)
+ continue;
+ categoryItem.dirtyCheckbox = false;
+ var hasEnabled = false;
+ var hasDisabled = false;
+ for (var eventName in categoryItem.children) {
+ var breakpointItem = categoryItem.children[eventName];
+ if (breakpointItem.checkbox.checked)
+ hasEnabled = true;
+ else
+ hasDisabled = true;
+ }
+ categoryItem.checkbox.checked = hasEnabled;
+ categoryItem.checkbox.indeterminate = hasEnabled && hasDisabled;
+ }
+ },
+
+ /**
+ * @param {string} eventName
+ * @param {string=} targetName
+ * @return {?Object}
+ */
+ _findBreakpointItem: function(eventName, targetName)
+ {
+ targetName = (targetName || WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny).toLowerCase();
+ for (var i = 0; i < this._categoryItems.length; ++i) {
+ var categoryItem = this._categoryItems[i];
+ if (categoryItem.targetNames.indexOf(targetName) === -1)
+ continue;
+ var breakpointItem = categoryItem.children[eventName];
+ if (breakpointItem)
+ return breakpointItem;
+ }
+ return null;
+ },
+
+ /**
+ * @param {string} eventName
+ * @param {string=} targetName
+ */
+ highlightBreakpoint: function(eventName, targetName)
+ {
+ var breakpointItem = this._findBreakpointItem(eventName, targetName);
+ if (!breakpointItem || !breakpointItem.checkbox.checked)
+ breakpointItem = this._findBreakpointItem(eventName, WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny);
+ if (!breakpointItem)
+ return;
+ this.expand();
+ breakpointItem.parent.element.expand();
+ breakpointItem.element.listItemElement.classList.add("breakpoint-hit");
+ this._highlightedElement = breakpointItem.element.listItemElement;
+ },
+
+ clearBreakpointHighlight: function()
+ {
+ if (this._highlightedElement) {
+ this._highlightedElement.classList.remove("breakpoint-hit");
+ delete this._highlightedElement;
+ }
+ },
+
+ _saveBreakpoints: function()
+ {
+ var breakpoints = [];
+ for (var i = 0; i < this._categoryItems.length; ++i) {
+ var categoryItem = this._categoryItems[i];
+ for (var eventName in categoryItem.children) {
+ var breakpointItem = categoryItem.children[eventName];
+ if (breakpointItem.checkbox.checked)
+ breakpoints.push({ eventName: eventName, targetNames: categoryItem.targetNames });
+ }
+ }
+ WebInspector.settings.eventListenerBreakpoints.set(breakpoints);
+ },
+
+ _restoreBreakpoints: function()
+ {
+ var breakpoints = WebInspector.settings.eventListenerBreakpoints.get();
+ for (var i = 0; i < breakpoints.length; ++i) {
+ var breakpoint = breakpoints[i];
+ if (breakpoint && typeof breakpoint.eventName === "string")
+ this._setBreakpoint(breakpoint.eventName, breakpoint.targetNames);
+ }
+ },
+
+ __proto__: WebInspector.SidebarPane.prototype
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js
new file mode 100644
index 00000000000..3feba90437b
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.UISourceCodeFrame}
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+WebInspector.CSSSourceFrame = function(uiSourceCode)
+{
+ WebInspector.UISourceCodeFrame.call(this, uiSourceCode);
+ this._registerShortcuts();
+}
+
+WebInspector.CSSSourceFrame.prototype = {
+ _registerShortcuts: function()
+ {
+ var shortcutKeys = WebInspector.ShortcutsScreen.SourcesPanelShortcuts;
+ for (var i = 0; i < shortcutKeys.IncreaseCSSUnitByOne.length; ++i)
+ this.addShortcut(shortcutKeys.IncreaseCSSUnitByOne[i].key, this._handleUnitModification.bind(this, 1));
+ for (var i = 0; i < shortcutKeys.DecreaseCSSUnitByOne.length; ++i)
+ this.addShortcut(shortcutKeys.DecreaseCSSUnitByOne[i].key, this._handleUnitModification.bind(this, -1));
+ for (var i = 0; i < shortcutKeys.IncreaseCSSUnitByTen.length; ++i)
+ this.addShortcut(shortcutKeys.IncreaseCSSUnitByTen[i].key, this._handleUnitModification.bind(this, 10));
+ for (var i = 0; i < shortcutKeys.DecreaseCSSUnitByTen.length; ++i)
+ this.addShortcut(shortcutKeys.DecreaseCSSUnitByTen[i].key, this._handleUnitModification.bind(this, -10));
+ },
+
+ /**
+ * @param {string} unit
+ * @param {number} change
+ * @return {?string}
+ */
+ _modifyUnit: function(unit, change)
+ {
+ var unitValue = parseInt(unit, 10);
+ if (isNaN(unitValue))
+ return null;
+ var tail = unit.substring((unitValue).toString().length);
+ return String.sprintf("%d%s", unitValue + change, tail);
+ },
+
+ /**
+ * @param {number} change
+ * @return {boolean}
+ */
+ _handleUnitModification: function(change)
+ {
+ var selection = this.textEditor.selection().normalize();
+ var token = this.textEditor.tokenAtTextPosition(selection.startLine, selection.startColumn);
+ if (!token) {
+ if (selection.startColumn > 0)
+ token = this.textEditor.tokenAtTextPosition(selection.startLine, selection.startColumn - 1);
+ if (!token)
+ return false;
+ }
+ if (token.type !== "css-number")
+ return false;
+
+ var cssUnitRange = new WebInspector.TextRange(selection.startLine, token.startColumn, selection.startLine, token.endColumn + 1);
+ var cssUnitText = this.textEditor.copyRange(cssUnitRange);
+ var newUnitText = this._modifyUnit(cssUnitText, change);
+ if (!newUnitText)
+ return false;
+ this.textEditor.editRange(cssUnitRange, newUnitText);
+ selection.startColumn = token.startColumn;
+ selection.endColumn = selection.startColumn + newUnitText.length;
+ this.textEditor.setSelection(selection);
+ return true;
+ },
+
+ __proto__: WebInspector.UISourceCodeFrame.prototype
+} \ No newline at end of file
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/CallStackSidebarPane.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/CallStackSidebarPane.js
new file mode 100644
index 00000000000..ce6eb9cd5b6
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/CallStackSidebarPane.js
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.SidebarPane}
+ */
+WebInspector.CallStackSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
+ this.bodyElement.addEventListener("keydown", this._keyDown.bind(this), true);
+ this.bodyElement.tabIndex = 0;
+
+ var asyncCheckbox = this.titleElement.appendChild(WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Async"), WebInspector.settings.enableAsyncStackTraces, true, undefined, WebInspector.UIString("Capture async stack traces")));
+ asyncCheckbox.classList.add("scripts-callstack-async");
+ asyncCheckbox.addEventListener("click", consumeEvent, false);
+ WebInspector.settings.enableAsyncStackTraces.addChangeListener(this._asyncStackTracesStateChanged, this);
+}
+
+WebInspector.CallStackSidebarPane.Events = {
+ CallFrameRestarted: "CallFrameRestarted",
+ CallFrameSelected: "CallFrameSelected"
+}
+
+WebInspector.CallStackSidebarPane.prototype = {
+ /**
+ * @param {?WebInspector.DebuggerPausedDetails} details
+ */
+ update: function(details)
+ {
+ this.bodyElement.removeChildren();
+
+ if (!details) {
+ var infoElement = this.bodyElement.createChild("div", "info");
+ infoElement.textContent = WebInspector.UIString("Not Paused");
+ return;
+ }
+
+ this._target = details.target();
+ var callFrames = details.callFrames;
+ var asyncStackTrace = details.asyncStackTrace;
+
+ delete this._statusMessageElement;
+ delete this._hiddenPlacardsMessageElement;
+ /** @type {!Array.<!WebInspector.CallStackSidebarPane.Placard>} */
+ this.placards = [];
+ this._hiddenPlacards = 0;
+
+ this._appendSidebarPlacards(callFrames);
+ var topStackHidden = (this._hiddenPlacards === this.placards.length);
+
+ while (asyncStackTrace) {
+ var title = asyncStackTrace.description;
+ if (title)
+ title += " " + WebInspector.UIString("(async)");
+ else
+ title = WebInspector.UIString("Async Call");
+ var asyncPlacard = new WebInspector.Placard(title, "");
+ asyncPlacard.element.addEventListener("click", this._selectNextVisiblePlacard.bind(this, this.placards.length, false), false);
+ asyncPlacard.element.addEventListener("contextmenu", this._asyncPlacardContextMenu.bind(this, this.placards.length), true);
+ asyncPlacard.element.classList.add("placard-label");
+ this.bodyElement.appendChild(asyncPlacard.element);
+ this._appendSidebarPlacards(asyncStackTrace.callFrames, asyncPlacard);
+ asyncStackTrace = asyncStackTrace.asyncStackTrace;
+ }
+
+ if (topStackHidden)
+ this._revealHiddenPlacards();
+ if (this._hiddenPlacards) {
+ var element = document.createElementWithClass("div", "hidden-placards-message");
+ if (this._hiddenPlacards === 1)
+ element.textContent = WebInspector.UIString("1 stack frame is hidden (black-boxed).");
+ else
+ element.textContent = WebInspector.UIString("%d stack frames are hidden (black-boxed).", this._hiddenPlacards);
+ element.createTextChild(" ");
+ var showAllLink = element.createChild("span", "node-link");
+ showAllLink.textContent = WebInspector.UIString("Show");
+ showAllLink.addEventListener("click", this._revealHiddenPlacards.bind(this), false);
+ this.bodyElement.insertBefore(element, this.bodyElement.firstChild);
+ this._hiddenPlacardsMessageElement = element;
+ }
+ },
+
+ /**
+ * @param {!Array.<!WebInspector.DebuggerModel.CallFrame>} callFrames
+ * @param {!WebInspector.Placard=} asyncPlacard
+ */
+ _appendSidebarPlacards: function(callFrames, asyncPlacard)
+ {
+ var allPlacardsHidden = true;
+ for (var i = 0, n = callFrames.length; i < n; ++i) {
+ var callFrame = callFrames[i];
+ var placard = new WebInspector.CallStackSidebarPane.Placard(callFrame, asyncPlacard);
+ placard.element.addEventListener("click", this._placardSelected.bind(this, placard), false);
+ placard.element.addEventListener("contextmenu", this._placardContextMenu.bind(this, placard), true);
+ this.placards.push(placard);
+ this.bodyElement.appendChild(placard.element);
+
+ if (callFrame.script.isFramework()) {
+ placard.setHidden(true);
+ placard.element.classList.add("dimmed");
+ ++this._hiddenPlacards;
+ } else {
+ allPlacardsHidden = false;
+ }
+ }
+ if (allPlacardsHidden && asyncPlacard)
+ asyncPlacard.setHidden(true);
+ },
+
+ _revealHiddenPlacards: function()
+ {
+ if (!this._hiddenPlacards)
+ return;
+ this._hiddenPlacards = 0;
+ for (var i = 0; i < this.placards.length; ++i) {
+ var placard = this.placards[i];
+ placard.setHidden(false);
+ if (placard._asyncPlacard)
+ placard._asyncPlacard.setHidden(false);
+ }
+ if (this._hiddenPlacardsMessageElement) {
+ this._hiddenPlacardsMessageElement.remove();
+ delete this._hiddenPlacardsMessageElement;
+ }
+ },
+
+ /**
+ * @param {!WebInspector.CallStackSidebarPane.Placard} placard
+ * @param {?Event} event
+ */
+ _placardContextMenu: function(placard, event)
+ {
+ var contextMenu = new WebInspector.ContextMenu(event);
+
+ if (!placard._callFrame.isAsync())
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Restart frame" : "Restart Frame"), this._restartFrame.bind(this, placard));
+
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy stack trace" : "Copy Stack Trace"), this._copyStackTrace.bind(this));
+ contextMenu.show();
+ },
+
+ /**
+ * @param {number} index
+ * @param {?Event} event
+ */
+ _asyncPlacardContextMenu: function(index, event)
+ {
+ for (; index < this.placards.length; ++index) {
+ var placard = this.placards[index];
+ if (!placard.isHidden()) {
+ this._placardContextMenu(placard, event);
+ break;
+ }
+ }
+ },
+
+ /**
+ * @param {!WebInspector.CallStackSidebarPane.Placard} placard
+ */
+ _restartFrame: function(placard)
+ {
+ placard._callFrame.restart();
+ this.dispatchEventToListeners(WebInspector.CallStackSidebarPane.Events.CallFrameRestarted, placard._callFrame);
+ },
+
+ _asyncStackTracesStateChanged: function()
+ {
+ var enabled = WebInspector.settings.enableAsyncStackTraces.get();
+ if (!enabled && this.placards)
+ this._removeAsyncPlacards();
+ },
+
+ _removeAsyncPlacards: function()
+ {
+ var shouldSelectTopFrame = false;
+ var lastSyncPlacardIndex = -1;
+ for (var i = 0; i < this.placards.length; ++i) {
+ var placard = this.placards[i];
+ if (placard._asyncPlacard) {
+ if (placard.selected)
+ shouldSelectTopFrame = true;
+ placard._asyncPlacard.element.remove();
+ placard.element.remove();
+ } else {
+ lastSyncPlacardIndex = i;
+ }
+ }
+ this.placards.length = lastSyncPlacardIndex + 1;
+ if (shouldSelectTopFrame)
+ this._selectNextVisiblePlacard(0);
+ },
+
+ /**
+ * @param {!WebInspector.DebuggerModel.CallFrame} x
+ */
+ setSelectedCallFrame: function(x)
+ {
+ for (var i = 0; i < this.placards.length; ++i) {
+ var placard = this.placards[i];
+ placard.selected = (placard._callFrame === x);
+ if (placard.selected && placard.isHidden())
+ this._revealHiddenPlacards();
+ }
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _selectNextCallFrameOnStack: function()
+ {
+ var index = this._selectedCallFrameIndex();
+ if (index === -1)
+ return false;
+ return this._selectNextVisiblePlacard(index + 1);
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _selectPreviousCallFrameOnStack: function()
+ {
+ var index = this._selectedCallFrameIndex();
+ if (index === -1)
+ return false;
+ return this._selectNextVisiblePlacard(index - 1, true);
+ },
+
+ /**
+ * @param {number} index
+ * @param {boolean=} backward
+ * @return {boolean}
+ */
+ _selectNextVisiblePlacard: function(index, backward)
+ {
+ while (0 <= index && index < this.placards.length) {
+ var placard = this.placards[index];
+ if (!placard.isHidden()) {
+ this._placardSelected(placard);
+ return true;
+ }
+ index += backward ? -1 : 1;
+ }
+ return false;
+ },
+
+ /**
+ * @return {number}
+ */
+ _selectedCallFrameIndex: function()
+ {
+ var selectedCallFrame = this._target.debuggerModel.selectedCallFrame();
+ if (!selectedCallFrame)
+ return -1;
+ for (var i = 0; i < this.placards.length; ++i) {
+ var placard = this.placards[i];
+ if (placard._callFrame === selectedCallFrame)
+ return i;
+ }
+ return -1;
+ },
+
+ /**
+ * @param {!WebInspector.CallStackSidebarPane.Placard} placard
+ */
+ _placardSelected: function(placard)
+ {
+ placard.element.scrollIntoViewIfNeeded();
+ this.dispatchEventToListeners(WebInspector.CallStackSidebarPane.Events.CallFrameSelected, placard._callFrame);
+ },
+
+ _copyStackTrace: function()
+ {
+ var text = "";
+ var lastPlacard = null;
+ for (var i = 0; i < this.placards.length; ++i) {
+ var placard = this.placards[i];
+ if (placard.isHidden())
+ continue;
+ if (lastPlacard && placard._asyncPlacard !== lastPlacard._asyncPlacard)
+ text += placard._asyncPlacard.title + "\n";
+ text += placard.title + " (" + placard.subtitle + ")\n";
+ lastPlacard = placard;
+ }
+ InspectorFrontendHost.copyText(text);
+ },
+
+ /**
+ * @param {function(!Array.<!WebInspector.KeyboardShortcut.Descriptor>, function(?Event=):boolean)} registerShortcutDelegate
+ */
+ registerShortcuts: function(registerShortcutDelegate)
+ {
+ registerShortcutDelegate(WebInspector.ShortcutsScreen.SourcesPanelShortcuts.NextCallFrame, this._selectNextCallFrameOnStack.bind(this));
+ registerShortcutDelegate(WebInspector.ShortcutsScreen.SourcesPanelShortcuts.PrevCallFrame, this._selectPreviousCallFrameOnStack.bind(this));
+ },
+
+ /**
+ * @param {!Element|string} status
+ */
+ setStatus: function(status)
+ {
+ if (!this._statusMessageElement)
+ this._statusMessageElement = this.bodyElement.createChild("div", "info");
+ if (typeof status === "string") {
+ this._statusMessageElement.textContent = status;
+ } else {
+ this._statusMessageElement.removeChildren();
+ this._statusMessageElement.appendChild(status);
+ }
+ },
+
+ _keyDown: function(event)
+ {
+ if (event.altKey || event.shiftKey || event.metaKey || event.ctrlKey)
+ return;
+ if (event.keyIdentifier === "Up" && this._selectPreviousCallFrameOnStack() || event.keyIdentifier === "Down" && this._selectNextCallFrameOnStack())
+ event.consume(true);
+ },
+
+ __proto__: WebInspector.SidebarPane.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.Placard}
+ * @param {!WebInspector.DebuggerModel.CallFrame} callFrame
+ * @param {!WebInspector.Placard=} asyncPlacard
+ */
+WebInspector.CallStackSidebarPane.Placard = function(callFrame, asyncPlacard)
+{
+ WebInspector.Placard.call(this, callFrame.functionName || WebInspector.UIString("(anonymous function)"), "");
+ callFrame.createLiveLocation(this._update.bind(this));
+ this._callFrame = callFrame;
+ this._asyncPlacard = asyncPlacard;
+}
+
+WebInspector.CallStackSidebarPane.Placard.prototype = {
+ /**
+ * @param {!WebInspector.UILocation} uiLocation
+ */
+ _update: function(uiLocation)
+ {
+ this.subtitle = uiLocation.linkText().trimMiddle(100);
+ },
+
+ __proto__: WebInspector.Placard.prototype
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/EditingLocationHistoryManager.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/EditingLocationHistoryManager.js
new file mode 100644
index 00000000000..9883664e060
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/EditingLocationHistoryManager.js
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @param {!WebInspector.SourcesView} sourcesView
+ * @param {!function():?WebInspector.SourceFrame} currentSourceFrameCallback
+ */
+WebInspector.EditingLocationHistoryManager = function(sourcesView, currentSourceFrameCallback)
+{
+ this._sourcesView = sourcesView;
+ this._historyManager = new WebInspector.SimpleHistoryManager(WebInspector.EditingLocationHistoryManager.HistoryDepth);
+ this._currentSourceFrameCallback = currentSourceFrameCallback;
+}
+
+WebInspector.EditingLocationHistoryManager.HistoryDepth = 20;
+
+WebInspector.EditingLocationHistoryManager.prototype = {
+ /**
+ * @param {!WebInspector.UISourceCodeFrame} sourceFrame
+ */
+ trackSourceFrameCursorJumps: function(sourceFrame)
+ {
+ sourceFrame.addEventListener(WebInspector.SourceFrame.Events.JumpHappened, this._onJumpHappened.bind(this));
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _onJumpHappened: function(event)
+ {
+ if (event.data.from)
+ this._updateActiveState(event.data.from);
+ if (event.data.to)
+ this._pushActiveState(event.data.to);
+ },
+
+ rollback: function()
+ {
+ this._historyManager.rollback();
+ },
+
+ rollover: function()
+ {
+ this._historyManager.rollover();
+ },
+
+ updateCurrentState: function()
+ {
+ var sourceFrame = this._currentSourceFrameCallback();
+ if (!sourceFrame)
+ return;
+ this._updateActiveState(sourceFrame.textEditor.selection());
+ },
+
+ pushNewState: function()
+ {
+ var sourceFrame = this._currentSourceFrameCallback();
+ if (!sourceFrame)
+ return;
+ this._pushActiveState(sourceFrame.textEditor.selection());
+ },
+
+ /**
+ * @param {!WebInspector.TextRange} selection
+ */
+ _updateActiveState: function(selection)
+ {
+ var active = this._historyManager.active();
+ if (!active)
+ return;
+ var sourceFrame = this._currentSourceFrameCallback();
+ if (!sourceFrame)
+ return;
+ var entry = new WebInspector.EditingLocationHistoryEntry(this._sourcesView, this, sourceFrame, selection);
+ active.merge(entry);
+ },
+
+ /**
+ * @param {!WebInspector.TextRange} selection
+ */
+ _pushActiveState: function(selection)
+ {
+ var sourceFrame = this._currentSourceFrameCallback();
+ if (!sourceFrame)
+ return;
+ var entry = new WebInspector.EditingLocationHistoryEntry(this._sourcesView, this, sourceFrame, selection);
+ this._historyManager.push(entry);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ removeHistoryForSourceCode: function(uiSourceCode)
+ {
+ function filterOut(entry)
+ {
+ return entry._projectId === uiSourceCode.project().id() && entry._path === uiSourceCode.path();
+ }
+
+ this._historyManager.filterOut(filterOut);
+ },
+}
+
+
+/**
+ * @constructor
+ * @implements {WebInspector.HistoryEntry}
+ * @param {!WebInspector.SourcesView} sourcesView
+ * @param {!WebInspector.EditingLocationHistoryManager} editingLocationManager
+ * @param {!WebInspector.SourceFrame} sourceFrame
+ * @param {!WebInspector.TextRange} selection
+ */
+WebInspector.EditingLocationHistoryEntry = function(sourcesView, editingLocationManager, sourceFrame, selection)
+{
+ this._sourcesView = sourcesView;
+ this._editingLocationManager = editingLocationManager;
+ var uiSourceCode = sourceFrame.uiSourceCode();
+ this._projectId = uiSourceCode.project().id();
+ this._path = uiSourceCode.path();
+
+ var position = this._positionFromSelection(selection);
+ this._positionHandle = sourceFrame.textEditor.textEditorPositionHandle(position.lineNumber, position.columnNumber);
+}
+
+WebInspector.EditingLocationHistoryEntry.prototype = {
+ /**
+ * @param {!WebInspector.HistoryEntry} entry
+ */
+ merge: function(entry)
+ {
+ if (this._projectId !== entry._projectId || this._path !== entry._path)
+ return;
+ this._positionHandle = entry._positionHandle;
+ },
+
+ /**
+ * @param {!WebInspector.TextRange} selection
+ * @return {!{lineNumber: number, columnNumber: number}}
+ */
+ _positionFromSelection: function(selection)
+ {
+ return {
+ lineNumber: selection.endLine,
+ columnNumber: selection.endColumn
+ };
+ },
+
+ /**
+ * @return {boolean}
+ */
+ valid: function()
+ {
+ var position = this._positionHandle.resolve();
+ var uiSourceCode = WebInspector.workspace.project(this._projectId).uiSourceCode(this._path);
+ return !!(position && uiSourceCode);
+ },
+
+ reveal: function()
+ {
+ var position = this._positionHandle.resolve();
+ var uiSourceCode = WebInspector.workspace.project(this._projectId).uiSourceCode(this._path);
+ if (!position || !uiSourceCode)
+ return;
+
+ this._editingLocationManager.updateCurrentState();
+ this._sourcesView.showSourceLocation(uiSourceCode, position.lineNumber, position.columnNumber);
+ }
+};
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/FilePathScoreFunction.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/FilePathScoreFunction.js
new file mode 100644
index 00000000000..cc6fc68d216
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/FilePathScoreFunction.js
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @param {string} query
+ */
+WebInspector.FilePathScoreFunction = function(query)
+{
+ this._query = query;
+ this._queryUpperCase = query.toUpperCase();
+ this._score = null;
+ this._sequence = null;
+ this._dataUpperCase = "";
+ this._fileNameIndex = 0;
+}
+
+/**
+ * @param {string} query
+ * @return {!RegExp}
+ */
+WebInspector.FilePathScoreFunction.filterRegex = function(query)
+{
+ const toEscape = String.regexSpecialCharacters();
+ var regexString = "";
+ for (var i = 0; i < query.length; ++i) {
+ var c = query.charAt(i);
+ if (toEscape.indexOf(c) !== -1)
+ c = "\\" + c;
+ if (i)
+ regexString += "[^" + c + "]*";
+ regexString += c;
+ }
+ return new RegExp(regexString, "i");
+}
+
+WebInspector.FilePathScoreFunction.prototype = {
+ /**
+ * @param {string} data
+ * @param {?Array.<!Number>} matchIndexes
+ * @return {number}
+ */
+ score: function(data, matchIndexes)
+ {
+ if (!data || !this._query)
+ return 0;
+ var n = this._query.length;
+ var m = data.length;
+ if (!this._score || this._score.length < n * m) {
+ this._score = new Int32Array(n * m * 2);
+ this._sequence = new Int32Array(n * m * 2);
+ }
+ var score = this._score;
+ var sequence = /** @type {!Int32Array} */ (this._sequence);
+ this._dataUpperCase = data.toUpperCase();
+ this._fileNameIndex = data.lastIndexOf("/");
+ for (var i = 0; i < n; ++i) {
+ for (var j = 0; j < m; ++j) {
+ var skipCharScore = j === 0 ? 0 : score[i * m + j - 1];
+ var prevCharScore = i === 0 || j === 0 ? 0 : score[(i - 1) * m + j - 1];
+ var consecutiveMatch = i === 0 || j === 0 ? 0 : sequence[(i - 1) * m + j - 1];
+ var pickCharScore = this._match(this._query, data, i, j, consecutiveMatch);
+ if (pickCharScore && prevCharScore + pickCharScore > skipCharScore) {
+ sequence[i * m + j] = consecutiveMatch + 1;
+ score[i * m + j] = (prevCharScore + pickCharScore);
+ } else {
+ sequence[i * m + j] = 0;
+ score[i * m + j] = skipCharScore;
+ }
+ }
+ }
+ if (matchIndexes)
+ this._restoreMatchIndexes(sequence, n, m, matchIndexes);
+ return score[n * m - 1];
+ },
+
+ /**
+ * @param {string} data
+ * @param {number} j
+ * @return {boolean}
+ */
+ _testWordStart: function(data, j)
+ {
+ var prevChar = data.charAt(j - 1);
+ return j === 0 || prevChar === "_" || prevChar === "-" || prevChar === "/" ||
+ (data[j - 1] !== this._dataUpperCase[j - 1] && data[j] === this._dataUpperCase[j]);
+ },
+
+ /**
+ * @param {!Int32Array} sequence
+ * @param {number} n
+ * @param {number} m
+ * @param {!Array.<!Number>} out
+ */
+ _restoreMatchIndexes: function(sequence, n, m, out)
+ {
+ var i = n - 1, j = m - 1;
+ while (i >= 0 && j >= 0) {
+ switch (sequence[i * m + j]) {
+ case 0:
+ --j;
+ break;
+ default:
+ out.push(j);
+ --i;
+ --j;
+ break;
+ }
+ }
+ out.reverse();
+ },
+
+ /**
+ * @param {string} query
+ * @param {string} data
+ * @param {number} i
+ * @param {number} j
+ * @return {number}
+ */
+ _singleCharScore: function(query, data, i, j)
+ {
+ var isWordStart = this._testWordStart(data, j);
+ var isFileName = j > this._fileNameIndex;
+ var isPathTokenStart = j === 0 || data[j - 1] === "/";
+ var isCapsMatch = query[i] === data[j] && query[i] == this._queryUpperCase[i];
+ var score = 10;
+ if (isPathTokenStart)
+ score += 4;
+ if (isWordStart)
+ score += 2;
+ if (isCapsMatch)
+ score += 6;
+ if (isFileName)
+ score += 4;
+ // promote the case of making the whole match in the filename
+ if (j === this._fileNameIndex + 1 && i === 0)
+ score += 5;
+ if (isFileName && isWordStart)
+ score += 3;
+ return score;
+ },
+
+ /**
+ * @param {string} query
+ * @param {string} data
+ * @param {number} i
+ * @param {number} j
+ * @param {number} sequenceLength
+ * @return {number}
+ */
+ _sequenceCharScore: function(query, data, i, j, sequenceLength)
+ {
+ var isFileName = j > this._fileNameIndex;
+ var isPathTokenStart = j === 0 || data[j - 1] === "/";
+ var score = 10;
+ if (isFileName)
+ score += 4;
+ if (isPathTokenStart)
+ score += 5;
+ score += sequenceLength * 4;
+ return score;
+ },
+
+ /**
+ * @param {string} query
+ * @param {string} data
+ * @param {number} i
+ * @param {number} j
+ * @param {number} consecutiveMatch
+ * @return {number}
+ */
+ _match: function(query, data, i, j, consecutiveMatch)
+ {
+ if (this._queryUpperCase[i] !== this._dataUpperCase[j])
+ return 0;
+
+ if (!consecutiveMatch)
+ return this._singleCharScore(query, data, i, j);
+ else
+ return this._sequenceCharScore(query, data, i, j - consecutiveMatch, consecutiveMatch);
+ },
+}
+
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/FilteredItemSelectionDialog.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/FilteredItemSelectionDialog.js
new file mode 100644
index 00000000000..b5deee9cff0
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/FilteredItemSelectionDialog.js
@@ -0,0 +1,941 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.DialogDelegate}
+ * @implements {WebInspector.ViewportControl.Provider}
+ * @param {!WebInspector.SelectionDialogContentProvider} delegate
+ */
+WebInspector.FilteredItemSelectionDialog = function(delegate)
+{
+ WebInspector.DialogDelegate.call(this);
+
+ if (!WebInspector.FilteredItemSelectionDialog._stylesLoaded) {
+ WebInspector.View.createStyleElement("filteredItemSelectionDialog.css");
+ WebInspector.FilteredItemSelectionDialog._stylesLoaded = true;
+ }
+
+ this.element = document.createElement("div");
+ this.element.className = "filtered-item-list-dialog";
+ this.element.addEventListener("keydown", this._onKeyDown.bind(this), false);
+
+ this._promptElement = this.element.createChild("input", "monospace");
+ this._promptElement.addEventListener("input", this._onInput.bind(this), false);
+ this._promptElement.type = "text";
+ this._promptElement.setAttribute("spellcheck", "false");
+
+ this._filteredItems = [];
+ this._viewportControl = new WebInspector.ViewportControl(this);
+ this._viewportControl.element.classList.add("fill");
+ this._itemElementsContainer = this._viewportControl.element;
+ this._itemElementsContainer.classList.add("container");
+ this._itemElementsContainer.classList.add("monospace");
+ this._itemElementsContainer.addEventListener("click", this._onClick.bind(this), false);
+ this.element.appendChild(this._itemElementsContainer);
+
+ this._delegate = delegate;
+ this._delegate.setRefreshCallback(this._itemsLoaded.bind(this));
+ this._itemsLoaded();
+}
+
+WebInspector.FilteredItemSelectionDialog.prototype = {
+ /**
+ * @param {!Element} element
+ * @param {!Element} relativeToElement
+ */
+ position: function(element, relativeToElement)
+ {
+ const shadow = 10;
+ const shadowPadding = 20; // shadow + padding
+ var container = WebInspector.Dialog.modalHostView().element;
+ var preferredWidth = Math.max(relativeToElement.offsetWidth * 2 / 3, 500);
+ var width = Math.min(preferredWidth, container.offsetWidth - 2 * shadowPadding);
+ var preferredHeight = Math.max(relativeToElement.offsetHeight * 2 / 3, 204);
+ var height = Math.min(preferredHeight, container.offsetHeight - 2 * shadowPadding);
+
+ this.element.style.width = width + "px";
+ var box = relativeToElement.boxInWindow(window).relativeToElement(container);
+ var positionX = box.x + Math.max((box.width - width - 2 * shadowPadding) / 2, shadow);
+ positionX = Math.max(shadow, Math.min(container.offsetWidth - width - 2 * shadowPadding, positionX));
+ var positionY = box.y + Math.max((box.height - height - 2 * shadowPadding) / 2, shadow);
+ positionY = Math.max(shadow, Math.min(container.offsetHeight - height - 2 * shadowPadding, positionY));
+ element.positionAt(positionX, positionY, container);
+ this._dialogHeight = height;
+
+ this._updateShowMatchingItems();
+ },
+
+ focus: function()
+ {
+ WebInspector.setCurrentFocusElement(this._promptElement);
+ if (this._filteredItems.length && this._viewportControl.lastVisibleIndex() === -1)
+ this._viewportControl.refresh();
+ },
+
+ willHide: function()
+ {
+ if (this._isHiding)
+ return;
+ this._isHiding = true;
+ this._delegate.dispose();
+ if (this._filterTimer)
+ clearTimeout(this._filterTimer);
+ },
+
+ renderAsTwoRows: function()
+ {
+ this._renderAsTwoRows = true;
+ },
+
+ onEnter: function()
+ {
+ if (!this._delegate.itemCount())
+ return;
+ var selectedIndex = this._shouldShowMatchingItems() && this._selectedIndexInFiltered < this._filteredItems.length ? this._filteredItems[this._selectedIndexInFiltered] : null;
+ this._delegate.selectItem(selectedIndex, this._promptElement.value.trim());
+ },
+
+ _itemsLoaded: function()
+ {
+
+ if (this._loadTimeout)
+ return;
+ this._loadTimeout = setTimeout(this._updateAfterItemsLoaded.bind(this), 0);
+ },
+
+ _updateAfterItemsLoaded: function()
+ {
+ delete this._loadTimeout;
+ this._filterItems();
+ },
+
+ /**
+ * @param {number} index
+ * @return {!Element}
+ */
+ _createItemElement: function(index)
+ {
+ var itemElement = document.createElement("div");
+ itemElement.className = "filtered-item-list-dialog-item " + (this._renderAsTwoRows ? "two-rows" : "one-row");
+ itemElement._titleElement = itemElement.createChild("div", "filtered-item-list-dialog-title");
+ itemElement._subtitleElement = itemElement.createChild("div", "filtered-item-list-dialog-subtitle");
+ itemElement._subtitleElement.textContent = "\u200B";
+ itemElement._index = index;
+ this._delegate.renderItem(index, this._promptElement.value.trim(), itemElement._titleElement, itemElement._subtitleElement);
+ return itemElement;
+ },
+
+ /**
+ * @param {string} query
+ */
+ setQuery: function(query)
+ {
+ this._promptElement.value = query;
+ this._scheduleFilter();
+ },
+
+ _filterItems: function()
+ {
+ delete this._filterTimer;
+ if (this._scoringTimer) {
+ clearTimeout(this._scoringTimer);
+ delete this._scoringTimer;
+ }
+
+ var query = this._delegate.rewriteQuery(this._promptElement.value.trim());
+ this._query = query;
+ var queryLength = query.length;
+ var filterRegex = query ? WebInspector.FilePathScoreFunction.filterRegex(query) : null;
+
+ var oldSelectedAbsoluteIndex = this._selectedIndexInFiltered ? this._filteredItems[this._selectedIndexInFiltered] : null;
+ var filteredItems = [];
+ this._selectedIndexInFiltered = 0;
+
+ var bestScores = [];
+ var bestItems = [];
+ var bestItemsToCollect = 100;
+ var minBestScore = 0;
+ var overflowItems = [];
+
+ scoreItems.call(this, 0);
+
+ /**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+ function compareIntegers(a, b)
+ {
+ return b - a;
+ }
+
+ /**
+ * @param {number} fromIndex
+ * @this {WebInspector.FilteredItemSelectionDialog}
+ */
+ function scoreItems(fromIndex)
+ {
+ var maxWorkItems = 1000;
+ var workDone = 0;
+ for (var i = fromIndex; i < this._delegate.itemCount() && workDone < maxWorkItems; ++i) {
+ // Filter out non-matching items quickly.
+ if (filterRegex && !filterRegex.test(this._delegate.itemKeyAt(i)))
+ continue;
+
+ // Score item.
+ var score = this._delegate.itemScoreAt(i, query);
+ if (query)
+ workDone++;
+
+ // Find its index in the scores array (earlier elements have bigger scores).
+ if (score > minBestScore || bestScores.length < bestItemsToCollect) {
+ var index = insertionIndexForObjectInListSortedByFunction(score, bestScores, compareIntegers, true);
+ bestScores.splice(index, 0, score);
+ bestItems.splice(index, 0, i);
+ if (bestScores.length > bestItemsToCollect) {
+ // Best list is too large -> drop last elements.
+ overflowItems.push(bestItems.peekLast());
+ bestScores.length = bestItemsToCollect;
+ bestItems.length = bestItemsToCollect;
+ }
+ minBestScore = bestScores.peekLast();
+ } else
+ filteredItems.push(i);
+ }
+
+ // Process everything in chunks.
+ if (i < this._delegate.itemCount()) {
+ this._scoringTimer = setTimeout(scoreItems.bind(this, i), 0);
+ return;
+ }
+ delete this._scoringTimer;
+
+ this._filteredItems = bestItems.concat(overflowItems).concat(filteredItems);
+ for (var i = 0; i < this._filteredItems.length; ++i) {
+ if (this._filteredItems[i] === oldSelectedAbsoluteIndex) {
+ this._selectedIndexInFiltered = i;
+ break;
+ }
+ }
+ this._viewportControl.invalidate();
+ if (!query)
+ this._selectedIndexInFiltered = 0;
+ this._updateSelection(this._selectedIndexInFiltered, false);
+ }
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _shouldShowMatchingItems: function()
+ {
+ return this._delegate.shouldShowMatchingItems(this._promptElement.value);
+ },
+
+ _onInput: function(event)
+ {
+ this._updateShowMatchingItems();
+ this._scheduleFilter();
+ },
+
+ _updateShowMatchingItems: function()
+ {
+ var shouldShowMatchingItems = this._shouldShowMatchingItems();
+ this._itemElementsContainer.classList.toggle("hidden", !shouldShowMatchingItems);
+ this.element.style.height = shouldShowMatchingItems ? this._dialogHeight + "px" : "auto";
+ },
+
+ /**
+ * @return {number}
+ */
+ _rowsPerViewport: function()
+ {
+ return Math.floor(this._viewportControl.element.clientHeight / this._rowHeight);
+ },
+
+ _onKeyDown: function(event)
+ {
+ var newSelectedIndex = this._selectedIndexInFiltered;
+
+ switch (event.keyCode) {
+ case WebInspector.KeyboardShortcut.Keys.Down.code:
+ if (++newSelectedIndex >= this._filteredItems.length)
+ newSelectedIndex = this._filteredItems.length - 1;
+ this._updateSelection(newSelectedIndex, true);
+ event.consume(true);
+ break;
+ case WebInspector.KeyboardShortcut.Keys.Up.code:
+ if (--newSelectedIndex < 0)
+ newSelectedIndex = 0;
+ this._updateSelection(newSelectedIndex, false);
+ event.consume(true);
+ break;
+ case WebInspector.KeyboardShortcut.Keys.PageDown.code:
+ newSelectedIndex = Math.min(newSelectedIndex + this._rowsPerViewport(), this._filteredItems.length - 1);
+ this._updateSelection(newSelectedIndex, true);
+ event.consume(true);
+ break;
+ case WebInspector.KeyboardShortcut.Keys.PageUp.code:
+ newSelectedIndex = Math.max(newSelectedIndex - this._rowsPerViewport(), 0);
+ this._updateSelection(newSelectedIndex, false);
+ event.consume(true);
+ break;
+ default:
+ }
+ },
+
+ _scheduleFilter: function()
+ {
+ if (this._filterTimer)
+ return;
+ this._filterTimer = setTimeout(this._filterItems.bind(this), 0);
+ },
+
+ /**
+ * @param {number} index
+ * @param {boolean} makeLast
+ */
+ _updateSelection: function(index, makeLast)
+ {
+ var element = this._viewportControl.renderedElementAt(this._selectedIndexInFiltered);
+ if (element)
+ element.classList.remove("selected");
+ this._viewportControl.scrollItemIntoView(index, makeLast);
+ this._selectedIndexInFiltered = index;
+ element = this._viewportControl.renderedElementAt(index);
+ if (element)
+ element.classList.add("selected");
+ },
+
+ _onClick: function(event)
+ {
+ var itemElement = event.target.enclosingNodeOrSelfWithClass("filtered-item-list-dialog-item");
+ if (!itemElement)
+ return;
+ this._delegate.selectItem(itemElement._index, this._promptElement.value.trim());
+ WebInspector.Dialog.hide();
+ },
+
+ /**
+ * @return {number}
+ */
+ itemCount: function()
+ {
+ return this._filteredItems.length;
+ },
+
+ /**
+ * @param {number} index
+ * @return {number}
+ */
+ fastHeight: function(index)
+ {
+ if (!this._rowHeight) {
+ var delegateIndex = this._filteredItems[index];
+ var element = this._createItemElement(delegateIndex);
+ this._rowHeight = element.measurePreferredSize(this._viewportControl.contentElement()).height;
+ }
+ return this._rowHeight;
+ },
+
+ /**
+ * @param {number} index
+ * @return {!WebInspector.ViewportElement}
+ */
+ itemElement: function(index)
+ {
+ var delegateIndex = this._filteredItems[index];
+ var element = this._createItemElement(delegateIndex);
+ if (index === this._selectedIndexInFiltered)
+ element.classList.add("selected");
+ return new WebInspector.StaticViewportElement(element);
+ },
+
+ /**
+ * @return {number}
+ */
+ minimumRowHeight: function()
+ {
+ return this.fastHeight(0);
+ },
+
+ __proto__: WebInspector.DialogDelegate.prototype
+}
+
+/**
+ * @constructor
+ */
+WebInspector.SelectionDialogContentProvider = function()
+{
+}
+
+WebInspector.SelectionDialogContentProvider.prototype = {
+ /**
+ * @param {function():void} refreshCallback
+ */
+ setRefreshCallback: function(refreshCallback)
+ {
+ this._refreshCallback = refreshCallback;
+ },
+
+ /**
+ * @param {string} query
+ * @return {boolean}
+ */
+ shouldShowMatchingItems: function(query)
+ {
+ return true;
+ },
+
+ /**
+ * @return {number}
+ */
+ itemCount: function()
+ {
+ return 0;
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @return {string}
+ */
+ itemKeyAt: function(itemIndex)
+ {
+ return "";
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @param {string} query
+ * @return {number}
+ */
+ itemScoreAt: function(itemIndex, query)
+ {
+ return 1;
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @param {string} query
+ * @param {!Element} titleElement
+ * @param {!Element} subtitleElement
+ */
+ renderItem: function(itemIndex, query, titleElement, subtitleElement)
+ {
+ },
+
+ /**
+ * @param {!Element} element
+ * @param {string} query
+ * @return {boolean}
+ */
+ highlightRanges: function(element, query)
+ {
+ if (!query)
+ return false;
+
+ /**
+ * @param {string} text
+ * @param {string} query
+ * @return {?Array.<!WebInspector.SourceRange>}
+ */
+ function rangesForMatch(text, query)
+ {
+ var sm = new difflib.SequenceMatcher(query, text);
+ var opcodes = sm.get_opcodes();
+ var ranges = [];
+
+ for (var i = 0; i < opcodes.length; ++i) {
+ var opcode = opcodes[i];
+ if (opcode[0] === "equal")
+ ranges.push(new WebInspector.SourceRange(opcode[3], opcode[4] - opcode[3]));
+ else if (opcode[0] !== "insert")
+ return null;
+ }
+ return ranges;
+ }
+
+ var text = element.textContent;
+ var ranges = rangesForMatch(text, query);
+ if (!ranges)
+ ranges = rangesForMatch(text.toUpperCase(), query.toUpperCase());
+ if (ranges) {
+ WebInspector.highlightRangesWithStyleClass(element, ranges, "highlight");
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * @param {?number} itemIndex
+ * @param {string} promptValue
+ */
+ selectItem: function(itemIndex, promptValue)
+ {
+ },
+
+ refresh: function()
+ {
+ this._refreshCallback();
+ },
+
+ /**
+ * @param {string} query
+ * @return {string}
+ */
+ rewriteQuery: function(query)
+ {
+ return query;
+ },
+
+ dispose: function()
+ {
+ }
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.SelectionDialogContentProvider}
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {function(number, number)} selectItemCallback
+ */
+WebInspector.JavaScriptOutlineDialog = function(uiSourceCode, selectItemCallback)
+{
+ WebInspector.SelectionDialogContentProvider.call(this);
+
+ this._functionItems = [];
+ this._selectItemCallback = selectItemCallback;
+ this._outlineWorker = new Worker("script_formatter_worker/ScriptFormatterWorker.js");
+ this._outlineWorker.onmessage = this._didBuildOutlineChunk.bind(this);
+ this._outlineWorker.postMessage({ method: "javaScriptOutline", params: { content: uiSourceCode.workingCopy() } });
+}
+
+/**
+ * @param {!WebInspector.View} view
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {function(number, number)} selectItemCallback
+ */
+WebInspector.JavaScriptOutlineDialog.show = function(view, uiSourceCode, selectItemCallback)
+{
+ if (WebInspector.Dialog.currentInstance())
+ return;
+ var filteredItemSelectionDialog = new WebInspector.FilteredItemSelectionDialog(new WebInspector.JavaScriptOutlineDialog(uiSourceCode, selectItemCallback));
+ WebInspector.Dialog.show(view.element, filteredItemSelectionDialog);
+}
+
+WebInspector.JavaScriptOutlineDialog.prototype = {
+ /**
+ * @param {!MessageEvent} event
+ */
+ _didBuildOutlineChunk: function(event)
+ {
+ var data = /** @type {!WebInspector.JavaScriptOutlineDialog.MessageEventData} */ (event.data);
+ var chunk = data.chunk;
+ for (var i = 0; i < chunk.length; ++i)
+ this._functionItems.push(chunk[i]);
+
+ if (data.total === data.index + 1)
+ this.dispose();
+
+ this.refresh();
+ },
+
+ /**
+ * @return {number}
+ */
+ itemCount: function()
+ {
+ return this._functionItems.length;
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @return {string}
+ */
+ itemKeyAt: function(itemIndex)
+ {
+ return this._functionItems[itemIndex].name;
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @param {string} query
+ * @return {number}
+ */
+ itemScoreAt: function(itemIndex, query)
+ {
+ var item = this._functionItems[itemIndex];
+ return -item.line;
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @param {string} query
+ * @param {!Element} titleElement
+ * @param {!Element} subtitleElement
+ */
+ renderItem: function(itemIndex, query, titleElement, subtitleElement)
+ {
+ var item = this._functionItems[itemIndex];
+ titleElement.textContent = item.name + (item.arguments ? item.arguments : "");
+ this.highlightRanges(titleElement, query);
+ subtitleElement.textContent = ":" + (item.line + 1);
+ },
+
+ /**
+ * @param {?number} itemIndex
+ * @param {string} promptValue
+ */
+ selectItem: function(itemIndex, promptValue)
+ {
+ if (itemIndex === null)
+ return;
+ var lineNumber = this._functionItems[itemIndex].line;
+ if (!isNaN(lineNumber) && lineNumber >= 0)
+ this._selectItemCallback(lineNumber, this._functionItems[itemIndex].column);
+ },
+
+ dispose: function()
+ {
+ if (this._outlineWorker) {
+ this._outlineWorker.terminate();
+ delete this._outlineWorker;
+ }
+ },
+
+ __proto__: WebInspector.SelectionDialogContentProvider.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.SelectionDialogContentProvider}
+ * @param {!Map.<!WebInspector.UISourceCode, number>=} defaultScores
+ */
+WebInspector.SelectUISourceCodeDialog = function(defaultScores)
+{
+ WebInspector.SelectionDialogContentProvider.call(this);
+
+ this._populate();
+ this._defaultScores = defaultScores;
+ this._scorer = new WebInspector.FilePathScoreFunction("");
+ WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
+ WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
+}
+
+WebInspector.SelectUISourceCodeDialog.prototype = {
+ _projectRemoved: function(event)
+ {
+ var project = /** @type {!WebInspector.Project} */ (event.data);
+ this._populate(project);
+ this.refresh();
+ },
+
+ /**
+ * @param {!WebInspector.Project=} skipProject
+ */
+ _populate: function(skipProject)
+ {
+ /** @type {!Array.<!WebInspector.UISourceCode>} */
+ this._uiSourceCodes = [];
+ var projects = WebInspector.workspace.projects().filter(this.filterProject.bind(this));
+ for (var i = 0; i < projects.length; ++i) {
+ if (skipProject && projects[i] === skipProject)
+ continue;
+ this._uiSourceCodes = this._uiSourceCodes.concat(projects[i].uiSourceCodes());
+ }
+ },
+
+ /**
+ * @param {?WebInspector.UISourceCode} uiSourceCode
+ * @param {number=} lineNumber
+ * @param {number=} columnNumber
+ */
+ uiSourceCodeSelected: function(uiSourceCode, lineNumber, columnNumber)
+ {
+ // Overridden by subclasses
+ },
+
+ /**
+ * @param {!WebInspector.Project} project
+ * @return {boolean}
+ */
+ filterProject: function(project)
+ {
+ return true;
+ // Overridden by subclasses
+ },
+
+ /**
+ * @return {number}
+ */
+ itemCount: function()
+ {
+ return this._uiSourceCodes.length;
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @return {string}
+ */
+ itemKeyAt: function(itemIndex)
+ {
+ return this._uiSourceCodes[itemIndex].fullDisplayName();
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @param {string} query
+ * @return {number}
+ */
+ itemScoreAt: function(itemIndex, query)
+ {
+ var uiSourceCode = this._uiSourceCodes[itemIndex];
+ var score = this._defaultScores ? (this._defaultScores.get(uiSourceCode) || 0) : 0;
+ if (!query || query.length < 2)
+ return score;
+
+ if (this._query !== query) {
+ this._query = query;
+ this._scorer = new WebInspector.FilePathScoreFunction(query);
+ }
+
+ var path = uiSourceCode.fullDisplayName();
+ return score + 10 * this._scorer.score(path, null);
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @param {string} query
+ * @param {!Element} titleElement
+ * @param {!Element} subtitleElement
+ * @return {!Array.<!Element>}
+ */
+ renderItem: function(itemIndex, query, titleElement, subtitleElement)
+ {
+ query = this.rewriteQuery(query);
+ var uiSourceCode = this._uiSourceCodes[itemIndex];
+ titleElement.textContent = uiSourceCode.displayName() + (this._queryLineNumberAndColumnNumber || "");
+ subtitleElement.textContent = uiSourceCode.fullDisplayName().trimEnd(100);
+
+ var indexes = [];
+ var score = new WebInspector.FilePathScoreFunction(query).score(subtitleElement.textContent, indexes);
+ var fileNameIndex = subtitleElement.textContent.lastIndexOf("/");
+ var ranges = [];
+ for (var i = 0; i < indexes.length; ++i)
+ ranges.push({offset: indexes[i], length: 1});
+ if (indexes[0] > fileNameIndex) {
+ for (var i = 0; i < ranges.length; ++i)
+ ranges[i].offset -= fileNameIndex + 1;
+ return WebInspector.highlightRangesWithStyleClass(titleElement, ranges, "highlight");
+ } else {
+ return WebInspector.highlightRangesWithStyleClass(subtitleElement, ranges, "highlight");
+ }
+ },
+
+ /**
+ * @param {?number} itemIndex
+ * @param {string} promptValue
+ */
+ selectItem: function(itemIndex, promptValue)
+ {
+ var parsedExpression = promptValue.trim().match(/^([^:]*)(:\d+)?(:\d+)?$/);
+ if (!parsedExpression)
+ return;
+
+ var lineNumber;
+ var columnNumber;
+ if (parsedExpression[2])
+ lineNumber = parseInt(parsedExpression[2].substr(1), 10) - 1;
+ if (parsedExpression[3])
+ columnNumber = parseInt(parsedExpression[3].substr(1), 10) - 1;
+ var uiSourceCode = itemIndex !== null ? this._uiSourceCodes[itemIndex] : null;
+ this.uiSourceCodeSelected(uiSourceCode, lineNumber, columnNumber);
+ },
+
+ /**
+ * @param {string} query
+ * @return {string}
+ */
+ rewriteQuery: function(query)
+ {
+ if (!query)
+ return query;
+ query = query.trim();
+ var lineNumberMatch = query.match(/^([^:]+)((?::[^:]*){0,2})$/);
+ this._queryLineNumberAndColumnNumber = lineNumberMatch ? lineNumberMatch[2] : "";
+ return lineNumberMatch ? lineNumberMatch[1] : query;
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _uiSourceCodeAdded: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
+ if (!this.filterProject(uiSourceCode.project()))
+ return;
+ this._uiSourceCodes.push(uiSourceCode)
+ this.refresh();
+ },
+
+ dispose: function()
+ {
+ WebInspector.workspace.removeEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
+ WebInspector.workspace.removeEventListener(WebInspector.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
+ },
+
+ __proto__: WebInspector.SelectionDialogContentProvider.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.SelectUISourceCodeDialog}
+ * @param {!WebInspector.SourcesView} sourcesView
+ * @param {!Map.<!WebInspector.UISourceCode, number>=} defaultScores
+ */
+WebInspector.OpenResourceDialog = function(sourcesView, defaultScores)
+{
+ WebInspector.SelectUISourceCodeDialog.call(this, defaultScores);
+ this._sourcesView = sourcesView;
+}
+
+WebInspector.OpenResourceDialog.prototype = {
+
+ /**
+ * @param {?WebInspector.UISourceCode} uiSourceCode
+ * @param {number=} lineNumber
+ * @param {number=} columnNumber
+ */
+ uiSourceCodeSelected: function(uiSourceCode, lineNumber, columnNumber)
+ {
+ if (!uiSourceCode)
+ uiSourceCode = this._sourcesView.currentUISourceCode();
+ if (!uiSourceCode)
+ return;
+ this._sourcesView.showSourceLocation(uiSourceCode, lineNumber, columnNumber);
+ },
+
+ /**
+ * @param {string} query
+ * @return {boolean}
+ */
+ shouldShowMatchingItems: function(query)
+ {
+ return !query.startsWith(":");
+ },
+
+ /**
+ * @param {!WebInspector.Project} project
+ * @return {boolean}
+ */
+ filterProject: function(project)
+ {
+ return !project.isServiceProject();
+ },
+
+ __proto__: WebInspector.SelectUISourceCodeDialog.prototype
+}
+
+/**
+ * @param {!WebInspector.SourcesView} sourcesView
+ * @param {!Element} relativeToElement
+ * @param {string=} query
+ * @param {!Map.<!WebInspector.UISourceCode, number>=} defaultScores
+ */
+WebInspector.OpenResourceDialog.show = function(sourcesView, relativeToElement, query, defaultScores)
+{
+ if (WebInspector.Dialog.currentInstance())
+ return;
+
+ var filteredItemSelectionDialog = new WebInspector.FilteredItemSelectionDialog(new WebInspector.OpenResourceDialog(sourcesView, defaultScores));
+ filteredItemSelectionDialog.renderAsTwoRows();
+ if (query)
+ filteredItemSelectionDialog.setQuery(query);
+ WebInspector.Dialog.show(relativeToElement, filteredItemSelectionDialog);
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.SelectUISourceCodeDialog}
+ * @param {!Array.<string>} types
+ * @param {function(!WebInspector.UISourceCode)} callback
+ */
+WebInspector.SelectUISourceCodeForProjectTypesDialog = function(types, callback)
+{
+ this._types = types;
+ WebInspector.SelectUISourceCodeDialog.call(this);
+ this._callback = callback;
+}
+
+WebInspector.SelectUISourceCodeForProjectTypesDialog.prototype = {
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {number=} lineNumber
+ * @param {number=} columnNumber
+ */
+ uiSourceCodeSelected: function(uiSourceCode, lineNumber, columnNumber)
+ {
+ this._callback(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.Project} project
+ * @return {boolean}
+ */
+ filterProject: function(project)
+ {
+ return this._types.indexOf(project.type()) !== -1;
+ },
+
+ __proto__: WebInspector.SelectUISourceCodeDialog.prototype
+}
+
+/**
+ * @param {string} name
+ * @param {!Array.<string>} types
+ * @param {function(!WebInspector.UISourceCode)} callback
+ * @param {!Element} relativeToElement
+ */
+WebInspector.SelectUISourceCodeForProjectTypesDialog.show = function(name, types, callback, relativeToElement)
+{
+ if (WebInspector.Dialog.currentInstance())
+ return;
+
+ var filteredItemSelectionDialog = new WebInspector.FilteredItemSelectionDialog(new WebInspector.SelectUISourceCodeForProjectTypesDialog(types, callback));
+ filteredItemSelectionDialog.setQuery(name);
+ filteredItemSelectionDialog.renderAsTwoRows();
+ WebInspector.Dialog.show(relativeToElement, filteredItemSelectionDialog);
+}
+
+/**
+ * @typedef {{index: number, total: number, chunk: !Array.<!{selectorText: string, lineNumber: number, columnNumber: number}>}}
+ */
+WebInspector.JavaScriptOutlineDialog.MessageEventData;
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/InplaceFormatterEditorAction.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/InplaceFormatterEditorAction.js
new file mode 100644
index 00000000000..37d93b3c06e
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/InplaceFormatterEditorAction.js
@@ -0,0 +1,115 @@
+
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @constructor
+ * @implements {WebInspector.SourcesView.EditorAction}
+ */
+WebInspector.InplaceFormatterEditorAction = function()
+{
+}
+
+WebInspector.InplaceFormatterEditorAction.prototype = {
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _editorSelected: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
+ this._updateButton(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _editorClosed: function(event)
+ {
+ var wasSelected = /** @type {boolean} */ (event.data.wasSelected);
+ if (wasSelected)
+ this._updateButton(null);
+ },
+
+ /**
+ * @param {?WebInspector.UISourceCode} uiSourceCode
+ */
+ _updateButton: function(uiSourceCode)
+ {
+ this._button.element.classList.toggle("hidden", !this._isFormattable(uiSourceCode));
+ },
+
+ /**
+ * @param {!WebInspector.SourcesView} sourcesView
+ * @return {!Element}
+ */
+ button: function(sourcesView)
+ {
+ if (this._button)
+ return this._button.element;
+
+ this._sourcesView = sourcesView;
+ this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorSelected, this._editorSelected.bind(this));
+ this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorClosed, this._editorClosed.bind(this));
+
+ this._button = new WebInspector.StatusBarButton(WebInspector.UIString("Format"), "sources-toggle-pretty-print-status-bar-item");
+ this._button.toggled = false;
+ this._button.addEventListener("click", this._formatSourceInPlace, this);
+ this._updateButton(null);
+
+ return this._button.element;
+ },
+
+ /**
+ * @param {?WebInspector.UISourceCode} uiSourceCode
+ * @return {boolean}
+ */
+ _isFormattable: function(uiSourceCode)
+ {
+ if (!uiSourceCode)
+ return false;
+ return uiSourceCode.contentType() === WebInspector.resourceTypes.Stylesheet
+ || uiSourceCode.project().type() === WebInspector.projectTypes.Snippets;
+ },
+
+ _formatSourceInPlace: function()
+ {
+ var uiSourceCode = this._sourcesView.currentUISourceCode();
+ if (!this._isFormattable(uiSourceCode))
+ return;
+
+ if (uiSourceCode.isDirty())
+ contentLoaded.call(this, uiSourceCode.workingCopy());
+ else
+ uiSourceCode.requestContent(contentLoaded.bind(this));
+
+ /**
+ * @this {WebInspector.InplaceFormatterEditorAction}
+ * @param {?string} content
+ */
+ function contentLoaded(content)
+ {
+ var formatter = WebInspector.Formatter.createFormatter(uiSourceCode.contentType());
+ formatter.formatContent(uiSourceCode.highlighterType(), content || "", innerCallback.bind(this));
+ }
+
+ /**
+ * @this {WebInspector.InplaceFormatterEditorAction}
+ * @param {string} formattedContent
+ * @param {!WebInspector.FormatterSourceMapping} formatterMapping
+ */
+ function innerCallback(formattedContent, formatterMapping)
+ {
+ if (uiSourceCode.workingCopy() === formattedContent)
+ return;
+ var sourceFrame = this._sourcesView.viewForFile(uiSourceCode);
+ var start = [0, 0];
+ if (sourceFrame) {
+ var selection = sourceFrame.selection();
+ start = formatterMapping.originalToFormatted(selection.startLine, selection.startColumn);
+ }
+ uiSourceCode.setWorkingCopy(formattedContent);
+ this._sourcesView.showSourceLocation(uiSourceCode, start[0], start[1]);
+ }
+ },
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
new file mode 100644
index 00000000000..f2331b8913c
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
@@ -0,0 +1,845 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.UISourceCodeFrame}
+ * @param {!WebInspector.SourcesPanel} scriptsPanel
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+WebInspector.JavaScriptSourceFrame = function(scriptsPanel, uiSourceCode)
+{
+ this._scriptsPanel = scriptsPanel;
+ this._breakpointManager = WebInspector.breakpointManager;
+ this._uiSourceCode = uiSourceCode;
+
+ WebInspector.UISourceCodeFrame.call(this, uiSourceCode);
+ if (uiSourceCode.project().type() === WebInspector.projectTypes.Debugger)
+ this.element.classList.add("source-frame-debugger-script");
+
+ this._popoverHelper = new WebInspector.ObjectPopoverHelper(this.textEditor.element,
+ this._getPopoverAnchor.bind(this), this._resolveObjectForPopover.bind(this), this._onHidePopover.bind(this), true);
+
+ this.textEditor.element.addEventListener("keydown", this._onKeyDown.bind(this), true);
+
+ this.textEditor.addEventListener(WebInspector.TextEditor.Events.GutterClick, this._handleGutterClick.bind(this), this);
+
+ this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
+ this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this);
+
+ this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.ConsoleMessageAdded, this._consoleMessageAdded, this);
+ this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.ConsoleMessageRemoved, this._consoleMessageRemoved, this);
+ this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.ConsoleMessagesCleared, this._consoleMessagesCleared, this);
+ this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.SourceMappingChanged, this._onSourceMappingChanged, this);
+ this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
+ this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);
+
+ /** @type {!Map.<!WebInspector.Target, !WebInspector.ScriptFile>}*/
+ this._scriptFileForTarget = new Map();
+ this._registerShortcuts();
+ var targets = WebInspector.targetManager.targets();
+ for (var i = 0; i < targets.length; ++i) {
+ var scriptFile = uiSourceCode.scriptFileForTarget(targets[i]);
+ if (scriptFile)
+ this._updateScriptFile(targets[i]);
+ }
+}
+
+WebInspector.JavaScriptSourceFrame.prototype = {
+ /**
+ * @param {!Element} infobarElement
+ */
+ _showInfobar: function(infobarElement)
+ {
+ if (this._infobarElement)
+ this._infobarElement.remove();
+ this._infobarElement = infobarElement;
+ this._infobarElement.classList.add("java-script-source-frame-infobar");
+ this.element.insertBefore(this._infobarElement, this.element.children[0]);
+ this.doResize();
+ },
+
+ /**
+ * @param {!Element} infobarElement
+ */
+ _hideInfobar: function(infobarElement)
+ {
+ infobarElement.remove();
+ this.doResize();
+ },
+
+ _showDivergedInfobar: function()
+ {
+ if (this._uiSourceCode.contentType() !== WebInspector.resourceTypes.Script)
+ return;
+
+ this._divergedInfobarElement = document.createElement("div");
+ var infobarMainRow = this._divergedInfobarElement.createChild("div", "java-script-source-frame-infobar-main-row");
+ var infobarDetailsContainer = this._divergedInfobarElement.createChild("span", "java-script-source-frame-infobar-details-container");
+
+ infobarMainRow.createChild("span", "java-script-source-frame-infobar-warning-icon");
+ var infobarMessage = infobarMainRow.createChild("span", "java-script-source-frame-infobar-row-message");
+ infobarMessage.textContent = WebInspector.UIString("Workspace mapping mismatch");
+
+ /**
+ * @this {WebInspector.JavaScriptSourceFrame}
+ */
+ function updateDetailsVisibility()
+ {
+ detailsToggleElement.textContent = detailsToggleElement._toggled ? WebInspector.UIString("less") : WebInspector.UIString("more");
+ infobarDetailsContainer.classList.toggle("hidden", !detailsToggleElement._toggled);
+ this.doResize();
+ }
+
+ /**
+ * @this {WebInspector.JavaScriptSourceFrame}
+ */
+ function toggleDetails()
+ {
+ detailsToggleElement._toggled = !detailsToggleElement._toggled;
+ updateDetailsVisibility.call(this);
+ }
+
+ infobarMainRow.appendChild(document.createTextNode("\u00a0"));
+ var detailsToggleElement = infobarMainRow.createChild("div", "java-script-source-frame-infobar-toggle");
+ detailsToggleElement.addEventListener("click", toggleDetails.bind(this), false);
+ updateDetailsVisibility.call(this);
+
+ function createDetailsRowMessage()
+ {
+ var infobarDetailsRow = infobarDetailsContainer.createChild("div", "java-script-source-frame-infobar-details-row");
+ return infobarDetailsRow.createChild("span", "java-script-source-frame-infobar-row-message");
+ }
+
+ var infobarDetailsRowMessage;
+
+ infobarDetailsRowMessage = createDetailsRowMessage();
+ infobarDetailsRowMessage.appendChild(document.createTextNode(WebInspector.UIString("The content of this file on the file system:\u00a0")));
+ var fileURL = this._uiSourceCode.originURL();
+ infobarDetailsRowMessage.appendChild(WebInspector.linkifyURLAsNode(fileURL, fileURL, "java-script-source-frame-infobar-details-url", true, fileURL));
+
+ infobarDetailsRowMessage = createDetailsRowMessage();
+ infobarDetailsRowMessage.appendChild(document.createTextNode(WebInspector.UIString("does not match the loaded script:\u00a0")));
+ var scriptURL = this._uiSourceCode.url;
+ infobarDetailsRowMessage.appendChild(WebInspector.linkifyURLAsNode(scriptURL, scriptURL, "java-script-source-frame-infobar-details-url", true, scriptURL));
+
+ // Add an empty row
+ createDetailsRowMessage();
+
+ createDetailsRowMessage().textContent = WebInspector.UIString("Possible solutions are:");;
+
+ function createDetailsRowMessageAction(title)
+ {
+ infobarDetailsRowMessage = createDetailsRowMessage();
+ infobarDetailsRowMessage.appendChild(document.createTextNode(" - "));
+ infobarDetailsRowMessage.appendChild(document.createTextNode(title));
+ }
+
+ if (WebInspector.settings.cacheDisabled.get())
+ createDetailsRowMessageAction(WebInspector.UIString("Reload inspected page"));
+ else
+ createDetailsRowMessageAction(WebInspector.UIString("Check \"Disable cache\" in settings and reload inspected page (recommended setup for authoring and debugging)"));
+ createDetailsRowMessageAction(WebInspector.UIString("Check that your file and script are both loaded from the correct source and their contents match."));
+
+ this._showInfobar(this._divergedInfobarElement);
+ },
+
+ _hideDivergedInfobar: function()
+ {
+ if (!this._divergedInfobarElement)
+ return;
+ this._hideInfobar(this._divergedInfobarElement);
+ delete this._divergedInfobarElement;
+ },
+
+ _registerShortcuts: function()
+ {
+ var shortcutKeys = WebInspector.ShortcutsScreen.SourcesPanelShortcuts;
+ for (var i = 0; i < shortcutKeys.EvaluateSelectionInConsole.length; ++i) {
+ var keyDescriptor = shortcutKeys.EvaluateSelectionInConsole[i];
+ this.addShortcut(keyDescriptor.key, this._evaluateSelectionInConsole.bind(this));
+ }
+ for (var i = 0; i < shortcutKeys.AddSelectionToWatch.length; ++i) {
+ var keyDescriptor = shortcutKeys.AddSelectionToWatch[i];
+ this.addShortcut(keyDescriptor.key, this._addCurrentSelectionToWatch.bind(this));
+ }
+ },
+
+ _addCurrentSelectionToWatch: function()
+ {
+ var textSelection = this.textEditor.selection();
+ if (textSelection && !textSelection.isEmpty())
+ this._innerAddToWatch(this.textEditor.copyRange(textSelection));
+ },
+
+ /**
+ * @param {string} expression
+ */
+ _innerAddToWatch: function(expression)
+ {
+ this._scriptsPanel.addToWatch(expression);
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _evaluateSelectionInConsole: function()
+ {
+ var selection = this.textEditor.selection();
+ if (!selection || selection.isEmpty())
+ return false;
+ this._evaluateInConsole(this.textEditor.copyRange(selection));
+ return true;
+ },
+
+ /**
+ * @param {string} expression
+ */
+ _evaluateInConsole: function(expression)
+ {
+ var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
+ if (currentExecutionContext)
+ WebInspector.ConsoleModel.evaluateCommandInConsole(currentExecutionContext, expression);
+ },
+
+ // View events
+ wasShown: function()
+ {
+ WebInspector.UISourceCodeFrame.prototype.wasShown.call(this);
+ },
+
+ willHide: function()
+ {
+ WebInspector.UISourceCodeFrame.prototype.willHide.call(this);
+ this._popoverHelper.hidePopover();
+ },
+
+ onUISourceCodeContentChanged: function()
+ {
+ this._removeAllBreakpoints();
+ WebInspector.UISourceCodeFrame.prototype.onUISourceCodeContentChanged.call(this);
+ },
+
+ populateLineGutterContextMenu: function(contextMenu, lineNumber)
+ {
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Continue to here" : "Continue to Here"), this._continueToLine.bind(this, lineNumber));
+ var breakpoint = this._breakpointManager.findBreakpointOnLine(this._uiSourceCode, lineNumber);
+ if (!breakpoint) {
+ // This row doesn't have a breakpoint: We want to show Add Breakpoint and Add and Edit Breakpoint.
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._setBreakpoint.bind(this, lineNumber, 0, "", true));
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add conditional breakpoint…" : "Add Conditional Breakpoint…"), this._editBreakpointCondition.bind(this, lineNumber));
+ } else {
+ // This row has a breakpoint, we want to show edit and remove breakpoint, and either disable or enable.
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), breakpoint.remove.bind(breakpoint));
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit breakpoint…" : "Edit Breakpoint…"), this._editBreakpointCondition.bind(this, lineNumber, breakpoint));
+ if (breakpoint.enabled())
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Disable breakpoint" : "Disable Breakpoint"), breakpoint.setEnabled.bind(breakpoint, false));
+ else
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Enable breakpoint" : "Enable Breakpoint"), breakpoint.setEnabled.bind(breakpoint, true));
+ }
+ },
+
+ populateTextAreaContextMenu: function(contextMenu, lineNumber)
+ {
+ var textSelection = this.textEditor.selection();
+ if (textSelection && !textSelection.isEmpty()) {
+ var selection = this.textEditor.copyRange(textSelection);
+ var addToWatchLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add to watch" : "Add to Watch");
+ contextMenu.appendItem(addToWatchLabel, this._innerAddToWatch.bind(this, selection));
+ var evaluateLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Evaluate in console" : "Evaluate in Console");
+ contextMenu.appendItem(evaluateLabel, this._evaluateInConsole.bind(this, selection));
+ contextMenu.appendSeparator();
+ } else if (this._uiSourceCode.project().type() === WebInspector.projectTypes.Debugger) {
+ // FIXME: Change condition above to explicitly check that current uiSourceCode is created by default debugger mapping
+ // and move the code adding this menu item to generic context menu provider for UISourceCode.
+ var liveEditLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Live edit" : "Live Edit");
+ contextMenu.appendItem(liveEditLabel, liveEdit.bind(this));
+ contextMenu.appendSeparator();
+ }
+
+ /**
+ * @this {WebInspector.JavaScriptSourceFrame}
+ */
+ function liveEdit()
+ {
+ var liveEditUISourceCode = WebInspector.liveEditSupport.uiSourceCodeForLiveEdit(this._uiSourceCode);
+ WebInspector.Revealer.reveal(liveEditUISourceCode.uiLocation(lineNumber));
+ }
+
+ WebInspector.UISourceCodeFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber);
+ },
+
+ _workingCopyChanged: function(event)
+ {
+ if (this._supportsEnabledBreakpointsWhileEditing() || this._scriptFileForTarget.size())
+ return;
+
+ if (this._uiSourceCode.isDirty())
+ this._muteBreakpointsWhileEditing();
+ else
+ this._restoreBreakpointsAfterEditing();
+ },
+
+ _workingCopyCommitted: function(event)
+ {
+ if (this._supportsEnabledBreakpointsWhileEditing())
+ return;
+ if (this._scriptFileForTarget.size()) {
+ this._hasCommittedLiveEdit = true;
+ var scriptFiles = this._scriptFileForTarget.values();
+ for (var i = 0; i < scriptFiles.length; ++i)
+ scriptFiles[i].commitLiveEdit();
+ return;
+ }
+ this._restoreBreakpointsAfterEditing();
+ },
+
+ _didMergeToVM: function()
+ {
+ if (this._supportsEnabledBreakpointsWhileEditing())
+ return;
+ this._updateDivergedInfobar();
+ this._restoreBreakpointsIfConsistentScripts();
+ },
+
+ _didDivergeFromVM: function()
+ {
+ if (this._supportsEnabledBreakpointsWhileEditing())
+ return;
+ this._updateDivergedInfobar();
+ this._muteBreakpointsWhileEditing();
+ },
+
+ _muteBreakpointsWhileEditing: function()
+ {
+ if (this._muted)
+ return;
+ for (var lineNumber = 0; lineNumber < this._textEditor.linesCount; ++lineNumber) {
+ var breakpointDecoration = this._textEditor.getAttribute(lineNumber, "breakpoint");
+ if (!breakpointDecoration)
+ continue;
+ this._removeBreakpointDecoration(lineNumber);
+ this._addBreakpointDecoration(lineNumber, breakpointDecoration.columnNumber, breakpointDecoration.condition, breakpointDecoration.enabled, true);
+ }
+ this._muted = true;
+ },
+
+ _updateDivergedInfobar: function()
+ {
+ if (this._uiSourceCode.project().type() !== WebInspector.projectTypes.FileSystem) {
+ this._hideDivergedInfobar();
+ return;
+ }
+
+ var scriptFiles = this._scriptFileForTarget.values();
+ var hasDivergedScript = false;
+ for (var i = 0; i < scriptFiles.length; ++i)
+ hasDivergedScript = hasDivergedScript || scriptFiles[i].hasDivergedFromVM();
+
+ if (this._divergedInfobarElement) {
+ if (!hasDivergedScript || this._hasCommittedLiveEdit)
+ this._hideDivergedInfobar();
+ } else {
+ if (hasDivergedScript && !this._uiSourceCode.isDirty() && !this._hasCommittedLiveEdit)
+ this._showDivergedInfobar();
+ }
+ },
+
+ _supportsEnabledBreakpointsWhileEditing: function()
+ {
+ return this._uiSourceCode.project().type() === WebInspector.projectTypes.Snippets;
+ },
+
+ _restoreBreakpointsIfConsistentScripts: function()
+ {
+ var scriptFiles = this._scriptFileForTarget.values();
+ for (var i = 0; i < scriptFiles.length; ++i)
+ if (scriptFiles[i].hasDivergedFromVM() || scriptFiles[i].isMergingToVM())
+ return;
+
+ this._restoreBreakpointsAfterEditing();
+ },
+
+ _restoreBreakpointsAfterEditing: function()
+ {
+ delete this._muted;
+ var breakpoints = {};
+ // Save and remove muted breakpoint decorations.
+ for (var lineNumber = 0; lineNumber < this._textEditor.linesCount; ++lineNumber) {
+ var breakpointDecoration = this._textEditor.getAttribute(lineNumber, "breakpoint");
+ if (breakpointDecoration) {
+ breakpoints[lineNumber] = breakpointDecoration;
+ this._removeBreakpointDecoration(lineNumber);
+ }
+ }
+
+ // Remove all breakpoints.
+ this._removeAllBreakpoints();
+
+ // Restore all breakpoints from saved decorations.
+ for (var lineNumberString in breakpoints) {
+ var lineNumber = parseInt(lineNumberString, 10);
+ if (isNaN(lineNumber))
+ continue;
+ var breakpointDecoration = breakpoints[lineNumberString];
+ this._setBreakpoint(lineNumber, breakpointDecoration.columnNumber, breakpointDecoration.condition, breakpointDecoration.enabled);
+ }
+ },
+
+ _removeAllBreakpoints: function()
+ {
+ var breakpoints = this._breakpointManager.breakpointsForUISourceCode(this._uiSourceCode);
+ for (var i = 0; i < breakpoints.length; ++i)
+ breakpoints[i].remove();
+ },
+
+ _getPopoverAnchor: function(element, event)
+ {
+ if (!WebInspector.debuggerModel.isPaused())
+ return null;
+
+ var textPosition = this.textEditor.coordinatesToCursorPosition(event.x, event.y);
+ if (!textPosition)
+ return null;
+ var mouseLine = textPosition.startLine;
+ var mouseColumn = textPosition.startColumn;
+ var textSelection = this.textEditor.selection().normalize();
+ if (textSelection && !textSelection.isEmpty()) {
+ if (textSelection.startLine !== textSelection.endLine || textSelection.startLine !== mouseLine || mouseColumn < textSelection.startColumn || mouseColumn > textSelection.endColumn)
+ return null;
+
+ var leftCorner = this.textEditor.cursorPositionToCoordinates(textSelection.startLine, textSelection.startColumn);
+ var rightCorner = this.textEditor.cursorPositionToCoordinates(textSelection.endLine, textSelection.endColumn);
+ var anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height);
+ anchorBox.highlight = {
+ lineNumber: textSelection.startLine,
+ startColumn: textSelection.startColumn,
+ endColumn: textSelection.endColumn - 1
+ };
+ anchorBox.forSelection = true;
+ return anchorBox;
+ }
+
+ var token = this.textEditor.tokenAtTextPosition(textPosition.startLine, textPosition.startColumn);
+ if (!token)
+ return null;
+ var lineNumber = textPosition.startLine;
+ var line = this.textEditor.line(lineNumber);
+ var tokenContent = line.substring(token.startColumn, token.endColumn + 1);
+
+ var isIdentifier = token.type.startsWith("js-variable") || token.type.startsWith("js-property") || token.type == "js-def";
+ if (!isIdentifier && (token.type !== "js-keyword" || tokenContent !== "this"))
+ return null;
+
+ var leftCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, token.startColumn);
+ var rightCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, token.endColumn + 1);
+ var anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height);
+
+ anchorBox.highlight = {
+ lineNumber: lineNumber,
+ startColumn: token.startColumn,
+ endColumn: token.endColumn
+ };
+
+ return anchorBox;
+ },
+
+ _resolveObjectForPopover: function(anchorBox, showCallback, objectGroupName)
+ {
+ if (!WebInspector.debuggerModel.isPaused()) {
+ this._popoverHelper.hidePopover();
+ return;
+ }
+ var lineNumber = anchorBox.highlight.lineNumber;
+ var startHighlight = anchorBox.highlight.startColumn;
+ var endHighlight = anchorBox.highlight.endColumn;
+ var line = this.textEditor.line(lineNumber);
+ if (!anchorBox.forSelection) {
+ while (startHighlight > 1 && line.charAt(startHighlight - 1) === '.') {
+ var token = this.textEditor.tokenAtTextPosition(lineNumber, startHighlight - 2);
+ if (!token) {
+ this._popoverHelper.hidePopover();
+ return;
+ }
+ startHighlight = token.startColumn;
+ }
+ }
+ var evaluationText = line.substring(startHighlight, endHighlight + 1);
+ var selectedCallFrame = WebInspector.debuggerModel.selectedCallFrame();
+ selectedCallFrame.evaluate(evaluationText, objectGroupName, false, true, false, false, showObjectPopover.bind(this));
+
+ /**
+ * @param {?RuntimeAgent.RemoteObject} result
+ * @param {boolean=} wasThrown
+ * @this {WebInspector.JavaScriptSourceFrame}
+ */
+ function showObjectPopover(result, wasThrown)
+ {
+ if (!WebInspector.debuggerModel.isPaused() || !result) {
+ this._popoverHelper.hidePopover();
+ return;
+ }
+ this._popoverAnchorBox = anchorBox;
+ showCallback(selectedCallFrame.target().runtimeModel.createRemoteObject(result), wasThrown, this._popoverAnchorBox);
+ // Popover may have been removed by showCallback().
+ if (this._popoverAnchorBox) {
+ var highlightRange = new WebInspector.TextRange(lineNumber, startHighlight, lineNumber, endHighlight);
+ this._popoverAnchorBox._highlightDescriptor = this.textEditor.highlightRange(highlightRange, "source-frame-eval-expression");
+ }
+ }
+ },
+
+ _onHidePopover: function()
+ {
+ if (!this._popoverAnchorBox)
+ return;
+ if (this._popoverAnchorBox._highlightDescriptor)
+ this.textEditor.removeHighlight(this._popoverAnchorBox._highlightDescriptor);
+ delete this._popoverAnchorBox;
+ },
+
+ /**
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @param {string} condition
+ * @param {boolean} enabled
+ * @param {boolean} mutedWhileEditing
+ */
+ _addBreakpointDecoration: function(lineNumber, columnNumber, condition, enabled, mutedWhileEditing)
+ {
+ var breakpoint = {
+ condition: condition,
+ enabled: enabled,
+ columnNumber: columnNumber
+ };
+
+ this.textEditor.setAttribute(lineNumber, "breakpoint", breakpoint);
+
+ var disabled = !enabled || mutedWhileEditing;
+ this.textEditor.addBreakpoint(lineNumber, disabled, !!condition);
+ },
+
+ _removeBreakpointDecoration: function(lineNumber)
+ {
+ this.textEditor.removeAttribute(lineNumber, "breakpoint");
+ this.textEditor.removeBreakpoint(lineNumber);
+ },
+
+ _onKeyDown: function(event)
+ {
+ if (event.keyIdentifier === "U+001B") { // Escape key
+ if (this._popoverHelper.isPopoverVisible()) {
+ this._popoverHelper.hidePopover();
+ event.consume();
+ }
+ }
+ },
+
+ /**
+ * @param {number} lineNumber
+ * @param {!WebInspector.BreakpointManager.Breakpoint=} breakpoint
+ */
+ _editBreakpointCondition: function(lineNumber, breakpoint)
+ {
+ this._conditionElement = this._createConditionElement(lineNumber);
+ this.textEditor.addDecoration(lineNumber, this._conditionElement);
+
+ /**
+ * @this {WebInspector.JavaScriptSourceFrame}
+ */
+ function finishEditing(committed, element, newText)
+ {
+ this.textEditor.removeDecoration(lineNumber, this._conditionElement);
+ delete this._conditionEditorElement;
+ delete this._conditionElement;
+ if (!committed)
+ return;
+
+ if (breakpoint)
+ breakpoint.setCondition(newText);
+ else
+ this._setBreakpoint(lineNumber, 0, newText, true);
+ }
+
+ var config = new WebInspector.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false));
+ WebInspector.InplaceEditor.startEditing(this._conditionEditorElement, config);
+ this._conditionEditorElement.value = breakpoint ? breakpoint.condition() : "";
+ this._conditionEditorElement.select();
+ },
+
+ _createConditionElement: function(lineNumber)
+ {
+ var conditionElement = document.createElement("div");
+ conditionElement.className = "source-frame-breakpoint-condition";
+
+ var labelElement = document.createElement("label");
+ labelElement.className = "source-frame-breakpoint-message";
+ labelElement.htmlFor = "source-frame-breakpoint-condition";
+ labelElement.appendChild(document.createTextNode(WebInspector.UIString("The breakpoint on line %d will stop only if this expression is true:", lineNumber + 1)));
+ conditionElement.appendChild(labelElement);
+
+ var editorElement = document.createElement("input");
+ editorElement.id = "source-frame-breakpoint-condition";
+ editorElement.className = "monospace";
+ editorElement.type = "text";
+ conditionElement.appendChild(editorElement);
+ this._conditionEditorElement = editorElement;
+
+ return conditionElement;
+ },
+
+ /**
+ * @param {number} lineNumber
+ */
+ setExecutionLine: function(lineNumber)
+ {
+ this._executionLineNumber = lineNumber;
+ if (this.loaded)
+ this.textEditor.setExecutionLine(lineNumber);
+ },
+
+ clearExecutionLine: function()
+ {
+ if (this.loaded && typeof this._executionLineNumber === "number")
+ this.textEditor.clearExecutionLine();
+ delete this._executionLineNumber;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _shouldIgnoreExternalBreakpointEvents: function()
+ {
+ if (this._supportsEnabledBreakpointsWhileEditing())
+ return false;
+ if (this._muted)
+ return true;
+ var scriptFiles = this._scriptFileForTarget.values();
+ var hasDivergingOrMergingFile = false;
+ for (var i = 0; i < scriptFiles.length; ++i)
+ if (scriptFiles[i].isDivergingFromVM() || scriptFiles[i].isMergingToVM())
+ return true;
+ return false;
+ },
+
+ _breakpointAdded: function(event)
+ {
+ var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiLocation);
+ if (uiLocation.uiSourceCode !== this._uiSourceCode)
+ return;
+ if (this._shouldIgnoreExternalBreakpointEvents())
+ return;
+
+ var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
+ if (this.loaded)
+ this._addBreakpointDecoration(uiLocation.lineNumber, uiLocation.columnNumber, breakpoint.condition(), breakpoint.enabled(), false);
+ },
+
+ _breakpointRemoved: function(event)
+ {
+ var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiLocation);
+ if (uiLocation.uiSourceCode !== this._uiSourceCode)
+ return;
+ if (this._shouldIgnoreExternalBreakpointEvents())
+ return;
+
+ var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
+ var remainingBreakpoint = this._breakpointManager.findBreakpointOnLine(this._uiSourceCode, uiLocation.lineNumber);
+ if (!remainingBreakpoint && this.loaded)
+ this._removeBreakpointDecoration(uiLocation.lineNumber);
+ },
+
+ _consoleMessageAdded: function(event)
+ {
+ var message = /** @type {!WebInspector.PresentationConsoleMessage} */ (event.data);
+ if (this.loaded)
+ this.addMessageToSource(message.lineNumber, message.originalMessage);
+ },
+
+ _consoleMessageRemoved: function(event)
+ {
+ var message = /** @type {!WebInspector.PresentationConsoleMessage} */ (event.data);
+ if (this.loaded)
+ this.removeMessageFromSource(message.lineNumber, message.originalMessage);
+ },
+
+ _consoleMessagesCleared: function(event)
+ {
+ this.clearMessages();
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _onSourceMappingChanged: function(event)
+ {
+ var data = /** @type {{target: !WebInspector.Target}} */ (event.data);
+ this._updateScriptFile(data.target);
+ },
+
+ /**
+ * @param {!WebInspector.Target} target
+ */
+ _updateScriptFile: function(target)
+ {
+ var oldScriptFile = this._scriptFileForTarget.get(target);
+ var newScriptFile = this._uiSourceCode.scriptFileForTarget(target);
+ this._scriptFileForTarget.remove(target);
+ if (oldScriptFile) {
+ oldScriptFile.removeEventListener(WebInspector.ScriptFile.Events.DidMergeToVM, this._didMergeToVM, this);
+ oldScriptFile.removeEventListener(WebInspector.ScriptFile.Events.DidDivergeFromVM, this._didDivergeFromVM, this);
+ if (this._muted && !this._uiSourceCode.isDirty())
+ this._restoreBreakpointsIfConsistentScripts();
+ }
+ if (newScriptFile)
+ this._scriptFileForTarget.put(target, newScriptFile);
+
+ delete this._hasCommittedLiveEdit;
+ this._updateDivergedInfobar();
+
+ if (newScriptFile) {
+ newScriptFile.addEventListener(WebInspector.ScriptFile.Events.DidMergeToVM, this._didMergeToVM, this);
+ newScriptFile.addEventListener(WebInspector.ScriptFile.Events.DidDivergeFromVM, this._didDivergeFromVM, this);
+ if (this.loaded)
+ newScriptFile.checkMapping();
+ }
+ },
+
+ onTextEditorContentLoaded: function()
+ {
+ if (typeof this._executionLineNumber === "number")
+ this.setExecutionLine(this._executionLineNumber);
+
+ var breakpointLocations = this._breakpointManager.breakpointLocationsForUISourceCode(this._uiSourceCode);
+ for (var i = 0; i < breakpointLocations.length; ++i)
+ this._breakpointAdded({data:breakpointLocations[i]});
+
+ var messages = this._uiSourceCode.consoleMessages();
+ for (var i = 0; i < messages.length; ++i) {
+ var message = messages[i];
+ this.addMessageToSource(message.lineNumber, message.originalMessage);
+ }
+
+ var scriptFiles = this._scriptFileForTarget.values();
+ for (var i = 0; i < scriptFiles.length; ++i)
+ scriptFiles[i].checkMapping();
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _handleGutterClick: function(event)
+ {
+ if (this._muted)
+ return;
+
+ var eventData = /** @type {!WebInspector.TextEditor.GutterClickEventData} */ (event.data);
+ var lineNumber = eventData.lineNumber;
+ var eventObject = /** @type {!Event} */ (eventData.event);
+
+ if (eventObject.button != 0 || eventObject.altKey || eventObject.ctrlKey || eventObject.metaKey)
+ return;
+
+ this._toggleBreakpoint(lineNumber, eventObject.shiftKey);
+ eventObject.consume(true);
+ },
+
+ /**
+ * @param {number} lineNumber
+ * @param {boolean} onlyDisable
+ */
+ _toggleBreakpoint: function(lineNumber, onlyDisable)
+ {
+ var breakpoint = this._breakpointManager.findBreakpointOnLine(this._uiSourceCode, lineNumber);
+ if (breakpoint) {
+ if (onlyDisable)
+ breakpoint.setEnabled(!breakpoint.enabled());
+ else
+ breakpoint.remove();
+ } else
+ this._setBreakpoint(lineNumber, 0, "", true);
+ },
+
+ toggleBreakpointOnCurrentLine: function()
+ {
+ if (this._muted)
+ return;
+
+ var selection = this.textEditor.selection();
+ if (!selection)
+ return;
+ this._toggleBreakpoint(selection.startLine, false);
+ },
+
+ /**
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @param {string} condition
+ * @param {boolean} enabled
+ */
+ _setBreakpoint: function(lineNumber, columnNumber, condition, enabled)
+ {
+ this._breakpointManager.setBreakpoint(this._uiSourceCode, lineNumber, columnNumber, condition, enabled);
+
+ WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
+ action: WebInspector.UserMetrics.UserActionNames.SetBreakpoint,
+ url: this._uiSourceCode.originURL(),
+ line: lineNumber,
+ enabled: enabled
+ });
+ },
+
+ /**
+ * @param {number} lineNumber
+ */
+ _continueToLine: function(lineNumber)
+ {
+ var executionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
+ if (!executionContext)
+ return;
+ var rawLocation = /** @type {!WebInspector.DebuggerModel.Location} */ (this._uiSourceCode.uiLocationToRawLocation(executionContext.target(), lineNumber, 0));
+ this._scriptsPanel.continueToLocation(rawLocation);
+ },
+
+ dispose: function()
+ {
+ this._breakpointManager.removeEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
+ this._breakpointManager.removeEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this);
+ this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.ConsoleMessageAdded, this._consoleMessageAdded, this);
+ this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.ConsoleMessageRemoved, this._consoleMessageRemoved, this);
+ this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.ConsoleMessagesCleared, this._consoleMessagesCleared, this);
+ this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.SourceMappingChanged, this._onSourceMappingChanged, this);
+ this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
+ this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);
+ WebInspector.UISourceCodeFrame.prototype.dispose.call(this);
+ },
+
+ __proto__: WebInspector.UISourceCodeFrame.prototype
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
new file mode 100644
index 00000000000..9ff239d3b5f
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
@@ -0,0 +1,1434 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
+ * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.VBox}
+ */
+WebInspector.NavigatorView = function()
+{
+ WebInspector.VBox.call(this);
+ this.registerRequiredCSS("navigatorView.css");
+
+ var scriptsTreeElement = document.createElement("ol");
+ this._scriptsTree = new WebInspector.NavigatorTreeOutline(scriptsTreeElement);
+
+ var scriptsOutlineElement = document.createElement("div");
+ scriptsOutlineElement.classList.add("outline-disclosure");
+ scriptsOutlineElement.classList.add("navigator");
+ scriptsOutlineElement.appendChild(scriptsTreeElement);
+
+ this.element.classList.add("navigator-container");
+ this.element.appendChild(scriptsOutlineElement);
+ this.setDefaultFocusedElement(this._scriptsTree.element);
+
+ /** @type {!Map.<!WebInspector.UISourceCode, !WebInspector.NavigatorUISourceCodeTreeNode>} */
+ this._uiSourceCodeNodes = new Map();
+ /** @type {!Map.<!WebInspector.NavigatorTreeNode, !StringMap.<!WebInspector.NavigatorFolderTreeNode>>} */
+ this._subfolderNodes = new Map();
+
+ this._rootNode = new WebInspector.NavigatorRootTreeNode(this);
+ this._rootNode.populate();
+
+ this.element.addEventListener("contextmenu", this.handleContextMenu.bind(this), false);
+}
+
+WebInspector.NavigatorView.Events = {
+ ItemSelected: "ItemSelected",
+ ItemRenamed: "ItemRenamed",
+}
+
+/**
+ * @param {string} type
+ * @return {string}
+ */
+WebInspector.NavigatorView.iconClassForType = function(type)
+{
+ if (type === WebInspector.NavigatorTreeOutline.Types.Domain)
+ return "navigator-domain-tree-item";
+ if (type === WebInspector.NavigatorTreeOutline.Types.FileSystem)
+ return "navigator-folder-tree-item";
+ return "navigator-folder-tree-item";
+}
+
+WebInspector.NavigatorView.prototype = {
+ setWorkspace: function(workspace)
+ {
+ this._workspace = workspace;
+ this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
+ this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this);
+ this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectRemoved, this._projectRemoved.bind(this), this);
+ },
+
+ wasShown: function()
+ {
+ if (this._loaded)
+ return;
+ this._loaded = true;
+ this._workspace.uiSourceCodes().forEach(this._addUISourceCode.bind(this));
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {boolean}
+ */
+ accept: function(uiSourceCode)
+ {
+ return !uiSourceCode.project().isServiceProject();
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _addUISourceCode: function(uiSourceCode)
+ {
+ if (!this.accept(uiSourceCode))
+ return;
+ var projectNode = this._projectNode(uiSourceCode.project());
+ var folderNode = this._folderNode(projectNode, uiSourceCode.parentPath());
+ var uiSourceCodeNode = new WebInspector.NavigatorUISourceCodeTreeNode(this, uiSourceCode);
+ this._uiSourceCodeNodes.put(uiSourceCode, uiSourceCodeNode);
+ folderNode.appendChild(uiSourceCodeNode);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _uiSourceCodeAdded: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
+ this._addUISourceCode(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _uiSourceCodeRemoved: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
+ this._removeUISourceCode(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _projectRemoved: function(event)
+ {
+ var project = /** @type {!WebInspector.Project} */ (event.data);
+ var uiSourceCodes = project.uiSourceCodes();
+ for (var i = 0; i < uiSourceCodes.length; ++i)
+ this._removeUISourceCode(uiSourceCodes[i]);
+ },
+
+ /**
+ * @param {!WebInspector.Project} project
+ * @return {!WebInspector.NavigatorTreeNode}
+ */
+ _projectNode: function(project)
+ {
+ if (!project.displayName())
+ return this._rootNode;
+
+ var projectNode = this._rootNode.child(project.id());
+ if (!projectNode) {
+ var type = project.type() === WebInspector.projectTypes.FileSystem ? WebInspector.NavigatorTreeOutline.Types.FileSystem : WebInspector.NavigatorTreeOutline.Types.Domain;
+ projectNode = new WebInspector.NavigatorFolderTreeNode(this, project, project.id(), type, "", project.displayName());
+ this._rootNode.appendChild(projectNode);
+ }
+ return projectNode;
+ },
+
+ /**
+ * @param {!WebInspector.NavigatorTreeNode} projectNode
+ * @param {string} folderPath
+ * @return {!WebInspector.NavigatorTreeNode}
+ */
+ _folderNode: function(projectNode, folderPath)
+ {
+ if (!folderPath)
+ return projectNode;
+
+ var subfolderNodes = this._subfolderNodes.get(projectNode);
+ if (!subfolderNodes) {
+ subfolderNodes = /** @type {!StringMap.<!WebInspector.NavigatorFolderTreeNode>} */ (new StringMap());
+ this._subfolderNodes.put(projectNode, subfolderNodes);
+ }
+
+ var folderNode = subfolderNodes.get(folderPath);
+ if (folderNode)
+ return folderNode;
+
+ var parentNode = projectNode;
+ var index = folderPath.lastIndexOf("/");
+ if (index !== -1)
+ parentNode = this._folderNode(projectNode, folderPath.substring(0, index));
+
+ var name = folderPath.substring(index + 1);
+ folderNode = new WebInspector.NavigatorFolderTreeNode(this, null, name, WebInspector.NavigatorTreeOutline.Types.Folder, folderPath, name);
+ subfolderNodes.put(folderPath, folderNode);
+ parentNode.appendChild(folderNode);
+ return folderNode;
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {boolean=} select
+ */
+ revealUISourceCode: function(uiSourceCode, select)
+ {
+ var node = this._uiSourceCodeNodes.get(uiSourceCode);
+ if (!node)
+ return;
+ if (this._scriptsTree.selectedTreeElement)
+ this._scriptsTree.selectedTreeElement.deselect();
+ this._lastSelectedUISourceCode = uiSourceCode;
+ node.reveal(select);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {boolean} focusSource
+ */
+ _sourceSelected: function(uiSourceCode, focusSource)
+ {
+ this._lastSelectedUISourceCode = uiSourceCode;
+ var data = { uiSourceCode: uiSourceCode, focusSource: focusSource};
+ this.dispatchEventToListeners(WebInspector.NavigatorView.Events.ItemSelected, data);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ sourceDeleted: function(uiSourceCode)
+ {
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _removeUISourceCode: function(uiSourceCode)
+ {
+ var node = this._uiSourceCodeNodes.get(uiSourceCode);
+ if (!node)
+ return;
+
+ var projectNode = this._projectNode(uiSourceCode.project());
+ var subfolderNodes = this._subfolderNodes.get(projectNode);
+ var parentNode = node.parent;
+ this._uiSourceCodeNodes.remove(uiSourceCode);
+ parentNode.removeChild(node);
+ node = parentNode;
+
+ while (node) {
+ parentNode = node.parent;
+ if (!parentNode || !node.isEmpty())
+ break;
+ if (subfolderNodes)
+ subfolderNodes.remove(node._folderPath);
+ parentNode.removeChild(node);
+ node = parentNode;
+ }
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _updateIcon: function(uiSourceCode)
+ {
+ var node = this._uiSourceCodeNodes.get(uiSourceCode);
+ node.updateIcon();
+ },
+
+ reset: function()
+ {
+ var nodes = this._uiSourceCodeNodes.values();
+ for (var i = 0; i < nodes.length; ++i)
+ nodes[i].dispose();
+
+ this._scriptsTree.removeChildren();
+ this._uiSourceCodeNodes.clear();
+ this._subfolderNodes.clear();
+ this._rootNode.reset();
+ },
+
+ /**
+ * @param {?Event} event
+ */
+ handleContextMenu: function(event)
+ {
+ var contextMenu = new WebInspector.ContextMenu(event);
+ this._appendAddFolderItem(contextMenu);
+ contextMenu.show();
+ },
+
+ /**
+ * @param {!WebInspector.ContextMenu} contextMenu
+ */
+ _appendAddFolderItem: function(contextMenu)
+ {
+ function addFolder()
+ {
+ WebInspector.isolatedFileSystemManager.addFileSystem();
+ }
+
+ var addFolderLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add folder to workspace" : "Add Folder to Workspace");
+ contextMenu.appendItem(addFolderLabel, addFolder);
+ },
+
+ /**
+ * @param {!WebInspector.Project} project
+ * @param {string} path
+ */
+ _handleContextMenuRefresh: function(project, path)
+ {
+ project.refresh(path);
+ },
+
+ /**
+ * @param {!WebInspector.Project} project
+ * @param {string} path
+ * @param {!WebInspector.UISourceCode=} uiSourceCode
+ */
+ _handleContextMenuCreate: function(project, path, uiSourceCode)
+ {
+ this.create(project, path, uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _handleContextMenuRename: function(uiSourceCode)
+ {
+ this.rename(uiSourceCode, false);
+ },
+
+ /**
+ * @param {!WebInspector.Project} project
+ * @param {string} path
+ */
+ _handleContextMenuExclude: function(project, path)
+ {
+ var shouldExclude = window.confirm(WebInspector.UIString("Are you sure you want to exclude this folder?"));
+ if (shouldExclude) {
+ WebInspector.startBatchUpdate();
+ project.excludeFolder(path);
+ WebInspector.endBatchUpdate();
+ }
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _handleContextMenuDelete: function(uiSourceCode)
+ {
+ var shouldDelete = window.confirm(WebInspector.UIString("Are you sure you want to delete this file?"));
+ if (shouldDelete)
+ uiSourceCode.project().deleteFile(uiSourceCode.path());
+ },
+
+ /**
+ * @param {!Event} event
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ handleFileContextMenu: function(event, uiSourceCode)
+ {
+ var contextMenu = new WebInspector.ContextMenu(event);
+ contextMenu.appendApplicableItems(uiSourceCode);
+ contextMenu.appendSeparator();
+
+ var project = uiSourceCode.project();
+ if (project.type() === WebInspector.projectTypes.FileSystem) {
+ var path = uiSourceCode.parentPath();
+ contextMenu.appendItem(WebInspector.UIString("Rename\u2026"), this._handleContextMenuRename.bind(this, uiSourceCode));
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Make a copy\u2026" : "Make a Copy\u2026"), this._handleContextMenuCreate.bind(this, project, path, uiSourceCode));
+ contextMenu.appendItem(WebInspector.UIString("Delete"), this._handleContextMenuDelete.bind(this, uiSourceCode));
+ contextMenu.appendSeparator();
+ }
+
+ this._appendAddFolderItem(contextMenu);
+ contextMenu.show();
+ },
+
+ /**
+ * @param {!Event} event
+ * @param {!WebInspector.NavigatorFolderTreeNode} node
+ */
+ handleFolderContextMenu: function(event, node)
+ {
+ var contextMenu = new WebInspector.ContextMenu(event);
+ var path = "/";
+ var projectNode = node;
+ while (projectNode.parent !== this._rootNode) {
+ path = "/" + projectNode.id + path;
+ projectNode = projectNode.parent;
+ }
+
+ var project = projectNode._project;
+
+ if (project.type() === WebInspector.projectTypes.FileSystem) {
+ contextMenu.appendItem(WebInspector.UIString("Refresh"), this._handleContextMenuRefresh.bind(this, project, path));
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "New file" : "New File"), this._handleContextMenuCreate.bind(this, project, path));
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Exclude folder" : "Exclude Folder"), this._handleContextMenuExclude.bind(this, project, path));
+ }
+ contextMenu.appendSeparator();
+ this._appendAddFolderItem(contextMenu);
+
+ function removeFolder()
+ {
+ var shouldRemove = window.confirm(WebInspector.UIString("Are you sure you want to remove this folder?"));
+ if (shouldRemove)
+ project.remove();
+ }
+
+ if (project.type() === WebInspector.projectTypes.FileSystem && node === projectNode) {
+ var removeFolderLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove folder from workspace" : "Remove Folder from Workspace");
+ contextMenu.appendItem(removeFolderLabel, removeFolder);
+ }
+
+ contextMenu.show();
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {boolean} deleteIfCanceled
+ */
+ rename: function(uiSourceCode, deleteIfCanceled)
+ {
+ var node = this._uiSourceCodeNodes.get(uiSourceCode);
+ console.assert(node);
+ node.rename(callback.bind(this));
+
+ /**
+ * @this {WebInspector.NavigatorView}
+ * @param {boolean} committed
+ */
+ function callback(committed)
+ {
+ if (!committed) {
+ if (deleteIfCanceled)
+ uiSourceCode.remove();
+ return;
+ }
+
+ this.dispatchEventToListeners(WebInspector.NavigatorView.Events.ItemRenamed, uiSourceCode);
+ this._updateIcon(uiSourceCode);
+ this._sourceSelected(uiSourceCode, true)
+ }
+ },
+
+ /**
+ * @param {!WebInspector.Project} project
+ * @param {string} path
+ * @param {!WebInspector.UISourceCode=} uiSourceCodeToCopy
+ */
+ create: function(project, path, uiSourceCodeToCopy)
+ {
+ var filePath;
+ var uiSourceCode;
+
+ /**
+ * @this {WebInspector.NavigatorView}
+ * @param {?string} content
+ */
+ function contentLoaded(content)
+ {
+ createFile.call(this, content || "");
+ }
+
+ if (uiSourceCodeToCopy)
+ uiSourceCodeToCopy.requestContent(contentLoaded.bind(this));
+ else
+ createFile.call(this);
+
+ /**
+ * @this {WebInspector.NavigatorView}
+ * @param {string=} content
+ */
+ function createFile(content)
+ {
+ project.createFile(path, null, content || "", fileCreated.bind(this));
+ }
+
+ /**
+ * @this {WebInspector.NavigatorView}
+ * @param {?string} path
+ */
+ function fileCreated(path)
+ {
+ if (!path)
+ return;
+ filePath = path;
+ uiSourceCode = project.uiSourceCode(filePath);
+ if (!uiSourceCode) {
+ console.assert(uiSourceCode)
+ return;
+ }
+ this._sourceSelected(uiSourceCode, false);
+ this.revealUISourceCode(uiSourceCode, true);
+ this.rename(uiSourceCode, true);
+ }
+ },
+
+ __proto__: WebInspector.VBox.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.NavigatorView}
+ */
+WebInspector.SourcesNavigatorView = function()
+{
+ WebInspector.NavigatorView.call(this);
+ WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this);
+}
+
+WebInspector.SourcesNavigatorView.prototype = {
+ /**
+ * @override
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {boolean}
+ */
+ accept: function(uiSourceCode)
+ {
+ if (!WebInspector.NavigatorView.prototype.accept(uiSourceCode))
+ return false;
+ return uiSourceCode.project().type() !== WebInspector.projectTypes.ContentScripts && uiSourceCode.project().type() !== WebInspector.projectTypes.Snippets;
+
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _inspectedURLChanged: function(event)
+ {
+ var nodes = this._uiSourceCodeNodes.values();
+ for (var i = 0; i < nodes.length; ++i) {
+ var uiSourceCode = nodes[i].uiSourceCode();
+ if (uiSourceCode.url === WebInspector.resourceTreeModel.inspectedPageURL())
+ this.revealUISourceCode(uiSourceCode, true);
+ }
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _addUISourceCode: function(uiSourceCode)
+ {
+ WebInspector.NavigatorView.prototype._addUISourceCode.call(this, uiSourceCode);
+ if (uiSourceCode.url === WebInspector.resourceTreeModel.inspectedPageURL())
+ this.revealUISourceCode(uiSourceCode, true);
+ },
+
+ __proto__: WebInspector.NavigatorView.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.NavigatorView}
+ */
+WebInspector.ContentScriptsNavigatorView = function()
+{
+ WebInspector.NavigatorView.call(this);
+}
+
+WebInspector.ContentScriptsNavigatorView.prototype = {
+ /**
+ * @override
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {boolean}
+ */
+ accept: function(uiSourceCode)
+ {
+ if (!WebInspector.NavigatorView.prototype.accept(uiSourceCode))
+ return false;
+ return uiSourceCode.project().type() === WebInspector.projectTypes.ContentScripts;
+ },
+
+ __proto__: WebInspector.NavigatorView.prototype
+}
+
+/**
+ * @constructor
+ * @extends {TreeOutline}
+ * @param {!Element} element
+ */
+WebInspector.NavigatorTreeOutline = function(element)
+{
+ TreeOutline.call(this, element);
+ this.element = element;
+
+ this.comparator = WebInspector.NavigatorTreeOutline._treeElementsCompare;
+}
+
+WebInspector.NavigatorTreeOutline.Types = {
+ Root: "Root",
+ Domain: "Domain",
+ Folder: "Folder",
+ UISourceCode: "UISourceCode",
+ FileSystem: "FileSystem"
+}
+
+/**
+ * @param {!TreeElement} treeElement1
+ * @param {!TreeElement} treeElement2
+ * @return {number}
+ */
+WebInspector.NavigatorTreeOutline._treeElementsCompare = function compare(treeElement1, treeElement2)
+{
+ // Insert in the alphabetical order, first domains, then folders, then scripts.
+ function typeWeight(treeElement)
+ {
+ var type = treeElement.type();
+ if (type === WebInspector.NavigatorTreeOutline.Types.Domain) {
+ if (treeElement.titleText === WebInspector.resourceTreeModel.inspectedPageDomain())
+ return 1;
+ return 2;
+ }
+ if (type === WebInspector.NavigatorTreeOutline.Types.FileSystem)
+ return 3;
+ if (type === WebInspector.NavigatorTreeOutline.Types.Folder)
+ return 4;
+ return 5;
+ }
+
+ var typeWeight1 = typeWeight(treeElement1);
+ var typeWeight2 = typeWeight(treeElement2);
+
+ var result;
+ if (typeWeight1 > typeWeight2)
+ result = 1;
+ else if (typeWeight1 < typeWeight2)
+ result = -1;
+ else {
+ var title1 = treeElement1.titleText;
+ var title2 = treeElement2.titleText;
+ result = title1.compareTo(title2);
+ }
+ return result;
+}
+
+WebInspector.NavigatorTreeOutline.prototype = {
+ /**
+ * @return {!Array.<!WebInspector.UISourceCode>}
+ */
+ scriptTreeElements: function()
+ {
+ var result = [];
+ if (this.children.length) {
+ for (var treeElement = this.children[0]; treeElement; treeElement = treeElement.traverseNextTreeElement(false, this, true)) {
+ if (treeElement instanceof WebInspector.NavigatorSourceTreeElement)
+ result.push(treeElement.uiSourceCode);
+ }
+ }
+ return result;
+ },
+
+ __proto__: TreeOutline.prototype
+}
+
+/**
+ * @constructor
+ * @extends {TreeElement}
+ * @param {string} type
+ * @param {string} title
+ * @param {!Array.<string>} iconClasses
+ * @param {boolean} hasChildren
+ * @param {boolean=} noIcon
+ */
+WebInspector.BaseNavigatorTreeElement = function(type, title, iconClasses, hasChildren, noIcon)
+{
+ this._type = type;
+ TreeElement.call(this, "", null, hasChildren);
+ this._titleText = title;
+ this._iconClasses = iconClasses;
+ this._noIcon = noIcon;
+}
+
+WebInspector.BaseNavigatorTreeElement.prototype = {
+ onattach: function()
+ {
+ this.listItemElement.removeChildren();
+ if (this._iconClasses) {
+ for (var i = 0; i < this._iconClasses.length; ++i)
+ this.listItemElement.classList.add(this._iconClasses[i]);
+ }
+
+ var selectionElement = document.createElement("div");
+ selectionElement.className = "selection";
+ this.listItemElement.appendChild(selectionElement);
+
+ if (!this._noIcon) {
+ this.imageElement = document.createElement("img");
+ this.imageElement.className = "icon";
+ this.listItemElement.appendChild(this.imageElement);
+ }
+
+ this.titleElement = document.createElement("div");
+ this.titleElement.className = "base-navigator-tree-element-title";
+ this._titleTextNode = document.createTextNode("");
+ this._titleTextNode.textContent = this._titleText;
+ this.titleElement.appendChild(this._titleTextNode);
+ this.listItemElement.appendChild(this.titleElement);
+ },
+
+ updateIconClasses: function(iconClasses)
+ {
+ for (var i = 0; i < this._iconClasses.length; ++i)
+ this.listItemElement.classList.remove(this._iconClasses[i]);
+ this._iconClasses = iconClasses;
+ for (var i = 0; i < this._iconClasses.length; ++i)
+ this.listItemElement.classList.add(this._iconClasses[i]);
+ },
+
+ onreveal: function()
+ {
+ if (this.listItemElement)
+ this.listItemElement.scrollIntoViewIfNeeded(true);
+ },
+
+ /**
+ * @return {string}
+ */
+ get titleText()
+ {
+ return this._titleText;
+ },
+
+ set titleText(titleText)
+ {
+ if (this._titleText === titleText)
+ return;
+ this._titleText = titleText || "";
+ if (this.titleElement)
+ this.titleElement.textContent = this._titleText;
+ },
+
+ /**
+ * @return {string}
+ */
+ type: function()
+ {
+ return this._type;
+ },
+
+ __proto__: TreeElement.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.BaseNavigatorTreeElement}
+ * @param {!WebInspector.NavigatorView} navigatorView
+ * @param {string} type
+ * @param {string} title
+ */
+WebInspector.NavigatorFolderTreeElement = function(navigatorView, type, title)
+{
+ var iconClass = WebInspector.NavigatorView.iconClassForType(type);
+ WebInspector.BaseNavigatorTreeElement.call(this, type, title, [iconClass], true);
+ this._navigatorView = navigatorView;
+}
+
+WebInspector.NavigatorFolderTreeElement.prototype = {
+ onpopulate: function()
+ {
+ this._node.populate();
+ },
+
+ onattach: function()
+ {
+ WebInspector.BaseNavigatorTreeElement.prototype.onattach.call(this);
+ this.collapse();
+ this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false);
+ },
+
+ /**
+ * @param {!WebInspector.NavigatorFolderTreeNode} node
+ */
+ setNode: function(node)
+ {
+ this._node = node;
+ var paths = [];
+ while (node && !node.isRoot()) {
+ paths.push(node._title);
+ node = node.parent;
+ }
+ paths.reverse();
+ this.tooltip = paths.join("/");
+ },
+
+ /**
+ * @param {?Event} event
+ */
+ _handleContextMenuEvent: function(event)
+ {
+ if (!this._node)
+ return;
+ this.select();
+ this._navigatorView.handleFolderContextMenu(/** @type {!Event} */ (event), this._node);
+ },
+
+ __proto__: WebInspector.BaseNavigatorTreeElement.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.BaseNavigatorTreeElement}
+ * @param {!WebInspector.NavigatorView} navigatorView
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {string} title
+ */
+WebInspector.NavigatorSourceTreeElement = function(navigatorView, uiSourceCode, title)
+{
+ this._navigatorView = navigatorView;
+ this._uiSourceCode = uiSourceCode;
+ WebInspector.BaseNavigatorTreeElement.call(this, WebInspector.NavigatorTreeOutline.Types.UISourceCode, title, this._calculateIconClasses(), false);
+ this.tooltip = uiSourceCode.originURL();
+}
+
+WebInspector.NavigatorSourceTreeElement.prototype = {
+ /**
+ * @return {!WebInspector.UISourceCode}
+ */
+ get uiSourceCode()
+ {
+ return this._uiSourceCode;
+ },
+
+ /**
+ * @return {!Array.<string>}
+ */
+ _calculateIconClasses: function()
+ {
+ return ["navigator-" + this._uiSourceCode.contentType().name() + "-tree-item"];
+ },
+
+ updateIcon: function()
+ {
+ this.updateIconClasses(this._calculateIconClasses());
+ },
+
+ onattach: function()
+ {
+ WebInspector.BaseNavigatorTreeElement.prototype.onattach.call(this);
+ this.listItemElement.draggable = true;
+ this.listItemElement.addEventListener("click", this._onclick.bind(this), false);
+ this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false);
+ this.listItemElement.addEventListener("mousedown", this._onmousedown.bind(this), false);
+ this.listItemElement.addEventListener("dragstart", this._ondragstart.bind(this), false);
+ },
+
+ _onmousedown: function(event)
+ {
+ if (event.which === 1) // Warm-up data for drag'n'drop
+ this._uiSourceCode.requestContent(callback.bind(this));
+ /**
+ * @param {?string} content
+ * @this {WebInspector.NavigatorSourceTreeElement}
+ */
+ function callback(content)
+ {
+ this._warmedUpContent = content;
+ }
+ },
+
+ _shouldRenameOnMouseDown: function()
+ {
+ if (!this._uiSourceCode.canRename())
+ return false;
+ var isSelected = this === this.treeOutline.selectedTreeElement;
+ var isFocused = this.treeOutline.childrenListElement.isSelfOrAncestor(document.activeElement);
+ return isSelected && isFocused && !WebInspector.isBeingEdited(this.treeOutline.element);
+ },
+
+ selectOnMouseDown: function(event)
+ {
+ if (event.which !== 1 || !this._shouldRenameOnMouseDown()) {
+ TreeElement.prototype.selectOnMouseDown.call(this, event);
+ return;
+ }
+ setTimeout(rename.bind(this), 300);
+
+ /**
+ * @this {WebInspector.NavigatorSourceTreeElement}
+ */
+ function rename()
+ {
+ if (this._shouldRenameOnMouseDown())
+ this._navigatorView.rename(this.uiSourceCode, false);
+ }
+ },
+
+ _ondragstart: function(event)
+ {
+ event.dataTransfer.setData("text/plain", this._warmedUpContent);
+ event.dataTransfer.effectAllowed = "copy";
+ return true;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ onspace: function()
+ {
+ this._navigatorView._sourceSelected(this.uiSourceCode, true);
+ return true;
+ },
+
+ /**
+ * @param {!Event} event
+ */
+ _onclick: function(event)
+ {
+ this._navigatorView._sourceSelected(this.uiSourceCode, false);
+ },
+
+ /**
+ * @override
+ * @return {boolean}
+ */
+ ondblclick: function(event)
+ {
+ var middleClick = event.button === 1;
+ this._navigatorView._sourceSelected(this.uiSourceCode, !middleClick);
+ return false;
+ },
+
+ /**
+ * @override
+ * @return {boolean}
+ */
+ onenter: function()
+ {
+ this._navigatorView._sourceSelected(this.uiSourceCode, true);
+ return true;
+ },
+
+ /**
+ * @override
+ * @return {boolean}
+ */
+ ondelete: function()
+ {
+ this._navigatorView.sourceDeleted(this.uiSourceCode);
+ return true;
+ },
+
+ /**
+ * @param {!Event} event
+ */
+ _handleContextMenuEvent: function(event)
+ {
+ this.select();
+ this._navigatorView.handleFileContextMenu(event, this._uiSourceCode);
+ },
+
+ __proto__: WebInspector.BaseNavigatorTreeElement.prototype
+}
+
+/**
+ * @constructor
+ * @param {string} id
+ */
+WebInspector.NavigatorTreeNode = function(id)
+{
+ this.id = id;
+ /** @type {!StringMap.<!WebInspector.NavigatorTreeNode>} */
+ this._children = new StringMap();
+}
+
+WebInspector.NavigatorTreeNode.prototype = {
+ /**
+ * @return {!TreeElement}
+ */
+ treeElement: function() { throw "Not implemented"; },
+
+ dispose: function() { },
+
+ /**
+ * @return {boolean}
+ */
+ isRoot: function()
+ {
+ return false;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ hasChildren: function()
+ {
+ return true;
+ },
+
+ populate: function()
+ {
+ if (this.isPopulated())
+ return;
+ if (this.parent)
+ this.parent.populate();
+ this._populated = true;
+ this.wasPopulated();
+ },
+
+ wasPopulated: function()
+ {
+ var children = this.children();
+ for (var i = 0; i < children.length; ++i)
+ this.treeElement().appendChild(children[i].treeElement());
+ },
+
+ /**
+ * @param {!WebInspector.NavigatorTreeNode} node
+ */
+ didAddChild: function(node)
+ {
+ if (this.isPopulated())
+ this.treeElement().appendChild(node.treeElement());
+ },
+
+ /**
+ * @param {!WebInspector.NavigatorTreeNode} node
+ */
+ willRemoveChild: function(node)
+ {
+ if (this.isPopulated())
+ this.treeElement().removeChild(node.treeElement());
+ },
+
+ /**
+ * @return {boolean}
+ */
+ isPopulated: function()
+ {
+ return this._populated;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ isEmpty: function()
+ {
+ return !this._children.size();
+ },
+
+ /**
+ * @param {string} id
+ * @return {?WebInspector.NavigatorTreeNode}
+ */
+ child: function(id)
+ {
+ return this._children.get(id) || null;
+ },
+
+ /**
+ * @return {!Array.<!WebInspector.NavigatorTreeNode>}
+ */
+ children: function()
+ {
+ return this._children.values();
+ },
+
+ /**
+ * @param {!WebInspector.NavigatorTreeNode} node
+ */
+ appendChild: function(node)
+ {
+ this._children.put(node.id, node);
+ node.parent = this;
+ this.didAddChild(node);
+ },
+
+ /**
+ * @param {!WebInspector.NavigatorTreeNode} node
+ */
+ removeChild: function(node)
+ {
+ this.willRemoveChild(node);
+ this._children.remove(node.id);
+ delete node.parent;
+ node.dispose();
+ },
+
+ reset: function()
+ {
+ this._children.clear();
+ }
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.NavigatorTreeNode}
+ * @param {!WebInspector.NavigatorView} navigatorView
+ */
+WebInspector.NavigatorRootTreeNode = function(navigatorView)
+{
+ WebInspector.NavigatorTreeNode.call(this, "");
+ this._navigatorView = navigatorView;
+}
+
+WebInspector.NavigatorRootTreeNode.prototype = {
+ /**
+ * @return {boolean}
+ */
+ isRoot: function()
+ {
+ return true;
+ },
+
+ /**
+ * @return {!TreeOutline}
+ */
+ treeElement: function()
+ {
+ return this._navigatorView._scriptsTree;
+ },
+
+ __proto__: WebInspector.NavigatorTreeNode.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.NavigatorTreeNode}
+ * @param {!WebInspector.NavigatorView} navigatorView
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+WebInspector.NavigatorUISourceCodeTreeNode = function(navigatorView, uiSourceCode)
+{
+ WebInspector.NavigatorTreeNode.call(this, uiSourceCode.name());
+ this._navigatorView = navigatorView;
+ this._uiSourceCode = uiSourceCode;
+ this._treeElement = null;
+}
+
+WebInspector.NavigatorUISourceCodeTreeNode.prototype = {
+ /**
+ * @return {!WebInspector.UISourceCode}
+ */
+ uiSourceCode: function()
+ {
+ return this._uiSourceCode;
+ },
+
+ updateIcon: function()
+ {
+ if (this._treeElement)
+ this._treeElement.updateIcon();
+ },
+
+ /**
+ * @return {!TreeElement}
+ */
+ treeElement: function()
+ {
+ if (this._treeElement)
+ return this._treeElement;
+
+ this._treeElement = new WebInspector.NavigatorSourceTreeElement(this._navigatorView, this._uiSourceCode, "");
+ this.updateTitle();
+
+ this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.TitleChanged, this._titleChanged, this);
+ this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
+ this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);
+
+ return this._treeElement;
+ },
+
+ /**
+ * @param {boolean=} ignoreIsDirty
+ */
+ updateTitle: function(ignoreIsDirty)
+ {
+ if (!this._treeElement)
+ return;
+
+ var titleText = this._uiSourceCode.displayName();
+ if (!ignoreIsDirty && (this._uiSourceCode.isDirty() || this._uiSourceCode.hasUnsavedCommittedChanges()))
+ titleText = "*" + titleText;
+ this._treeElement.titleText = titleText;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ hasChildren: function()
+ {
+ return false;
+ },
+
+ dispose: function()
+ {
+ if (!this._treeElement)
+ return;
+ this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.TitleChanged, this._titleChanged, this);
+ this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
+ this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);
+ },
+
+ _titleChanged: function(event)
+ {
+ this.updateTitle();
+ },
+
+ _workingCopyChanged: function(event)
+ {
+ this.updateTitle();
+ },
+
+ _workingCopyCommitted: function(event)
+ {
+ this.updateTitle();
+ },
+
+ /**
+ * @param {boolean=} select
+ */
+ reveal: function(select)
+ {
+ this.parent.populate();
+ this.parent.treeElement().expand();
+ this._treeElement.reveal();
+ if (select)
+ this._treeElement.select(true);
+ },
+
+ /**
+ * @param {function(boolean)=} callback
+ */
+ rename: function(callback)
+ {
+ if (!this._treeElement)
+ return;
+
+ // Tree outline should be marked as edited as well as the tree element to prevent search from starting.
+ var treeOutlineElement = this._treeElement.treeOutline.element;
+ WebInspector.markBeingEdited(treeOutlineElement, true);
+
+ /**
+ * @param {!Element} element
+ * @param {string} newTitle
+ * @param {string} oldTitle
+ * @this {WebInspector.NavigatorUISourceCodeTreeNode}
+ */
+ function commitHandler(element, newTitle, oldTitle)
+ {
+ if (newTitle !== oldTitle) {
+ this._treeElement.titleText = newTitle;
+ this._uiSourceCode.rename(newTitle, renameCallback.bind(this));
+ return;
+ }
+ afterEditing.call(this, true);
+ }
+
+ /**
+ * @param {boolean} success
+ * @this {WebInspector.NavigatorUISourceCodeTreeNode}
+ */
+ function renameCallback(success)
+ {
+ if (!success) {
+ WebInspector.markBeingEdited(treeOutlineElement, false);
+ this.updateTitle();
+ this.rename(callback);
+ return;
+ }
+ afterEditing.call(this, true);
+ }
+
+ /**
+ * @this {WebInspector.NavigatorUISourceCodeTreeNode}
+ */
+ function cancelHandler()
+ {
+ afterEditing.call(this, false);
+ }
+
+ /**
+ * @param {boolean} committed
+ * @this {WebInspector.NavigatorUISourceCodeTreeNode}
+ */
+ function afterEditing(committed)
+ {
+ WebInspector.markBeingEdited(treeOutlineElement, false);
+ this.updateTitle();
+ this._treeElement.treeOutline.childrenListElement.focus();
+ if (callback)
+ callback(committed);
+ }
+
+ var editingConfig = new WebInspector.InplaceEditor.Config(commitHandler.bind(this), cancelHandler.bind(this));
+ this.updateTitle(true);
+ WebInspector.InplaceEditor.startEditing(this._treeElement.titleElement, editingConfig);
+ window.getSelection().setBaseAndExtent(this._treeElement.titleElement, 0, this._treeElement.titleElement, 1);
+ },
+
+ __proto__: WebInspector.NavigatorTreeNode.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.NavigatorTreeNode}
+ * @param {!WebInspector.NavigatorView} navigatorView
+ * @param {?WebInspector.Project} project
+ * @param {string} id
+ * @param {string} type
+ * @param {string} folderPath
+ * @param {string} title
+ */
+WebInspector.NavigatorFolderTreeNode = function(navigatorView, project, id, type, folderPath, title)
+{
+ WebInspector.NavigatorTreeNode.call(this, id);
+ this._navigatorView = navigatorView;
+ this._project = project;
+ this._type = type;
+ this._folderPath = folderPath;
+ this._title = title;
+}
+
+WebInspector.NavigatorFolderTreeNode.prototype = {
+ /**
+ * @return {!TreeElement}
+ */
+ treeElement: function()
+ {
+ if (this._treeElement)
+ return this._treeElement;
+ this._treeElement = this._createTreeElement(this._title, this);
+ return this._treeElement;
+ },
+
+ /**
+ * @return {!TreeElement}
+ */
+ _createTreeElement: function(title, node)
+ {
+ var treeElement = new WebInspector.NavigatorFolderTreeElement(this._navigatorView, this._type, title);
+ treeElement.setNode(node);
+ return treeElement;
+ },
+
+ wasPopulated: function()
+ {
+ if (!this._treeElement || this._treeElement._node !== this)
+ return;
+ this._addChildrenRecursive();
+ },
+
+ _addChildrenRecursive: function()
+ {
+ var children = this.children();
+ for (var i = 0; i < children.length; ++i) {
+ var child = children[i];
+ this.didAddChild(child);
+ if (child instanceof WebInspector.NavigatorFolderTreeNode)
+ child._addChildrenRecursive();
+ }
+ },
+
+ _shouldMerge: function(node)
+ {
+ return this._type !== WebInspector.NavigatorTreeOutline.Types.Domain && node instanceof WebInspector.NavigatorFolderTreeNode;
+ },
+
+ didAddChild: function(node)
+ {
+ function titleForNode(node)
+ {
+ return node._title;
+ }
+
+ if (!this._treeElement)
+ return;
+
+ var children = this.children();
+
+ if (children.length === 1 && this._shouldMerge(node)) {
+ node._isMerged = true;
+ this._treeElement.titleText = this._treeElement.titleText + "/" + node._title;
+ node._treeElement = this._treeElement;
+ this._treeElement.setNode(node);
+ return;
+ }
+
+ var oldNode;
+ if (children.length === 2)
+ oldNode = children[0] !== node ? children[0] : children[1];
+ if (oldNode && oldNode._isMerged) {
+ delete oldNode._isMerged;
+ var mergedToNodes = [];
+ mergedToNodes.push(this);
+ var treeNode = this;
+ while (treeNode._isMerged) {
+ treeNode = treeNode.parent;
+ mergedToNodes.push(treeNode);
+ }
+ mergedToNodes.reverse();
+ var titleText = mergedToNodes.map(titleForNode).join("/");
+
+ var nodes = [];
+ treeNode = oldNode;
+ do {
+ nodes.push(treeNode);
+ children = treeNode.children();
+ treeNode = children.length === 1 ? children[0] : null;
+ } while (treeNode && treeNode._isMerged);
+
+ if (!this.isPopulated()) {
+ this._treeElement.titleText = titleText;
+ this._treeElement.setNode(this);
+ for (var i = 0; i < nodes.length; ++i) {
+ delete nodes[i]._treeElement;
+ delete nodes[i]._isMerged;
+ }
+ return;
+ }
+ var oldTreeElement = this._treeElement;
+ var treeElement = this._createTreeElement(titleText, this);
+ for (var i = 0; i < mergedToNodes.length; ++i)
+ mergedToNodes[i]._treeElement = treeElement;
+ oldTreeElement.parent.appendChild(treeElement);
+
+ oldTreeElement.setNode(nodes[nodes.length - 1]);
+ oldTreeElement.titleText = nodes.map(titleForNode).join("/");
+ oldTreeElement.parent.removeChild(oldTreeElement);
+ this._treeElement.appendChild(oldTreeElement);
+ if (oldTreeElement.expanded)
+ treeElement.expand();
+ }
+ if (this.isPopulated())
+ this._treeElement.appendChild(node.treeElement());
+ },
+
+ willRemoveChild: function(node)
+ {
+ if (node._isMerged || !this.isPopulated())
+ return;
+ this._treeElement.removeChild(node._treeElement);
+ },
+
+ __proto__: WebInspector.NavigatorTreeNode.prototype
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/Placard.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/Placard.js
new file mode 100644
index 00000000000..bb233d2b6c7
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/Placard.js
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @param {string} title
+ * @param {string} subtitle
+ */
+WebInspector.Placard = function(title, subtitle)
+{
+ this.element = document.createElementWithClass("div", "placard");
+ this.element.placard = this;
+
+ this.subtitleElement = this.element.createChild("div", "subtitle");
+ this.titleElement = this.element.createChild("div", "title");
+
+ this._hidden = false;
+ this.title = title;
+ this.subtitle = subtitle;
+ this.selected = false;
+}
+
+WebInspector.Placard.prototype = {
+ /** @return {string} */
+ get title()
+ {
+ return this._title;
+ },
+
+ set title(x)
+ {
+ if (this._title === x)
+ return;
+ this._title = x;
+ this.titleElement.textContent = x;
+ },
+
+ /** @return {string} */
+ get subtitle()
+ {
+ return this._subtitle;
+ },
+
+ set subtitle(x)
+ {
+ if (this._subtitle === x)
+ return;
+ this._subtitle = x;
+ this.subtitleElement.textContent = x;
+ },
+
+ /** @return {boolean} */
+ get selected()
+ {
+ return this._selected;
+ },
+
+ set selected(x)
+ {
+ if (x)
+ this.select();
+ else
+ this.deselect();
+ },
+
+ select: function()
+ {
+ if (this._selected)
+ return;
+ this._selected = true;
+ this.element.classList.add("selected");
+ },
+
+ deselect: function()
+ {
+ if (!this._selected)
+ return;
+ this._selected = false;
+ this.element.classList.remove("selected");
+ },
+
+ toggleSelected: function()
+ {
+ this.selected = !this.selected;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ isHidden: function()
+ {
+ return this._hidden;
+ },
+
+ /**
+ * @param {boolean} x
+ */
+ setHidden: function(x)
+ {
+ if (this._hidden === x)
+ return;
+ this._hidden = x;
+ this.element.classList.toggle("hidden", x);
+ },
+
+ discard: function()
+ {
+ }
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/RevisionHistoryView.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/RevisionHistoryView.js
new file mode 100644
index 00000000000..e7a64c1fd03
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/RevisionHistoryView.js
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.VBox}
+ */
+WebInspector.RevisionHistoryView = function()
+{
+ WebInspector.VBox.call(this);
+ this.registerRequiredCSS("revisionHistory.css");
+ this.element.classList.add("revision-history-drawer");
+ this.element.classList.add("outline-disclosure");
+ this._uiSourceCodeItems = new Map();
+
+ var olElement = this.element.createChild("ol");
+ this._treeOutline = new TreeOutline(olElement);
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @this {WebInspector.RevisionHistoryView}
+ */
+ function populateRevisions(uiSourceCode)
+ {
+ if (uiSourceCode.history.length)
+ this._createUISourceCodeItem(uiSourceCode);
+ }
+
+ WebInspector.workspace.uiSourceCodes().forEach(populateRevisions.bind(this));
+ WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeContentCommitted, this._revisionAdded, this);
+ WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this);
+ WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
+}
+
+/**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+WebInspector.RevisionHistoryView.showHistory = function(uiSourceCode)
+{
+ if (!WebInspector.RevisionHistoryView._view)
+ WebInspector.RevisionHistoryView._view = new WebInspector.RevisionHistoryView();
+ var view = WebInspector.RevisionHistoryView._view;
+ WebInspector.inspectorView.showCloseableViewInDrawer("history", WebInspector.UIString("History"), view);
+ view._revealUISourceCode(uiSourceCode);
+}
+
+WebInspector.RevisionHistoryView.prototype = {
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _createUISourceCodeItem: function(uiSourceCode)
+ {
+ var uiSourceCodeItem = new TreeElement(uiSourceCode.displayName(), null, true);
+ uiSourceCodeItem.selectable = false;
+
+ // Insert in sorted order
+ for (var i = 0; i < this._treeOutline.children.length; ++i) {
+ if (this._treeOutline.children[i].title.localeCompare(uiSourceCode.displayName()) > 0) {
+ this._treeOutline.insertChild(uiSourceCodeItem, i);
+ break;
+ }
+ }
+ if (i === this._treeOutline.children.length)
+ this._treeOutline.appendChild(uiSourceCodeItem);
+
+ this._uiSourceCodeItems.put(uiSourceCode, uiSourceCodeItem);
+
+ var revisionCount = uiSourceCode.history.length;
+ for (var i = revisionCount - 1; i >= 0; --i) {
+ var revision = uiSourceCode.history[i];
+ var historyItem = new WebInspector.RevisionHistoryTreeElement(revision, uiSourceCode.history[i - 1], i !== revisionCount - 1);
+ uiSourceCodeItem.appendChild(historyItem);
+ }
+
+ var linkItem = new TreeElement("", null, false);
+ linkItem.selectable = false;
+ uiSourceCodeItem.appendChild(linkItem);
+
+ var revertToOriginal = linkItem.listItemElement.createChild("span", "revision-history-link revision-history-link-row");
+ revertToOriginal.textContent = WebInspector.UIString("apply original content");
+ revertToOriginal.addEventListener("click", uiSourceCode.revertToOriginal.bind(uiSourceCode));
+
+ var clearHistoryElement = uiSourceCodeItem.listItemElement.createChild("span", "revision-history-link");
+ clearHistoryElement.textContent = WebInspector.UIString("revert");
+ clearHistoryElement.addEventListener("click", this._clearHistory.bind(this, uiSourceCode));
+ return uiSourceCodeItem;
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _clearHistory: function(uiSourceCode)
+ {
+ uiSourceCode.revertAndClearHistory(this._removeUISourceCode.bind(this));
+ },
+
+ _revisionAdded: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.uiSourceCode);
+ var uiSourceCodeItem = this._uiSourceCodeItems.get(uiSourceCode);
+ if (!uiSourceCodeItem) {
+ uiSourceCodeItem = this._createUISourceCodeItem(uiSourceCode);
+ return;
+ }
+
+ var historyLength = uiSourceCode.history.length;
+ var historyItem = new WebInspector.RevisionHistoryTreeElement(uiSourceCode.history[historyLength - 1], uiSourceCode.history[historyLength - 2], false);
+ if (uiSourceCodeItem.children.length)
+ uiSourceCodeItem.children[0].allowRevert();
+ uiSourceCodeItem.insertChild(historyItem, 0);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _revealUISourceCode: function(uiSourceCode)
+ {
+ var uiSourceCodeItem = this._uiSourceCodeItems.get(uiSourceCode);
+ if (uiSourceCodeItem) {
+ uiSourceCodeItem.reveal();
+ uiSourceCodeItem.expand();
+ }
+ },
+
+ _uiSourceCodeRemoved: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
+ this._removeUISourceCode(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _removeUISourceCode: function(uiSourceCode)
+ {
+ var uiSourceCodeItem = this._uiSourceCodeItems.get(uiSourceCode);
+ if (!uiSourceCodeItem)
+ return;
+ this._treeOutline.removeChild(uiSourceCodeItem);
+ this._uiSourceCodeItems.remove(uiSourceCode);
+ },
+
+ _projectRemoved: function(event)
+ {
+ var project = event.data;
+ project.uiSourceCodes().forEach(this._removeUISourceCode.bind(this));
+ },
+
+ __proto__: WebInspector.VBox.prototype
+}
+
+/**
+ * @constructor
+ * @extends {TreeElement}
+ * @param {!WebInspector.Revision} revision
+ * @param {!WebInspector.Revision} baseRevision
+ * @param {boolean} allowRevert
+ */
+WebInspector.RevisionHistoryTreeElement = function(revision, baseRevision, allowRevert)
+{
+ TreeElement.call(this, revision.timestamp.toLocaleTimeString(), null, true);
+ this.selectable = false;
+
+ this._revision = revision;
+ this._baseRevision = baseRevision;
+
+ this._revertElement = document.createElement("span");
+ this._revertElement.className = "revision-history-link";
+ this._revertElement.textContent = WebInspector.UIString("apply revision content");
+ this._revertElement.addEventListener("click", this._revision.revertToThis.bind(this._revision), false);
+ if (!allowRevert)
+ this._revertElement.classList.add("hidden");
+}
+
+WebInspector.RevisionHistoryTreeElement.prototype = {
+ onattach: function()
+ {
+ this.listItemElement.classList.add("revision-history-revision");
+ },
+
+ onexpand: function()
+ {
+ this.listItemElement.appendChild(this._revertElement);
+
+ if (this._wasExpandedOnce)
+ return;
+ this._wasExpandedOnce = true;
+
+ this.childrenListElement.classList.add("source-code");
+ if (this._baseRevision)
+ this._baseRevision.requestContent(step1.bind(this));
+ else
+ this._revision.uiSourceCode.requestOriginalContent(step1.bind(this));
+
+ /**
+ * @param {?string} baseContent
+ * @this {WebInspector.RevisionHistoryTreeElement}
+ */
+ function step1(baseContent)
+ {
+ this._revision.requestContent(step2.bind(this, baseContent));
+ }
+
+ /**
+ * @param {?string} baseContent
+ * @param {?string} newContent
+ * @this {WebInspector.RevisionHistoryTreeElement}
+ */
+ function step2(baseContent, newContent)
+ {
+ var baseLines = difflib.stringAsLines(baseContent);
+ var newLines = difflib.stringAsLines(newContent);
+ var sm = new difflib.SequenceMatcher(baseLines, newLines);
+ var opcodes = sm.get_opcodes();
+ var lastWasSeparator = false;
+
+ for (var idx = 0; idx < opcodes.length; idx++) {
+ var code = opcodes[idx];
+ var change = code[0];
+ var b = code[1];
+ var be = code[2];
+ var n = code[3];
+ var ne = code[4];
+ var rowCount = Math.max(be - b, ne - n);
+ var topRows = [];
+ var bottomRows = [];
+ for (var i = 0; i < rowCount; i++) {
+ if (change === "delete" || (change === "replace" && b < be)) {
+ var lineNumber = b++;
+ this._createLine(lineNumber, null, baseLines[lineNumber], "removed");
+ lastWasSeparator = false;
+ }
+
+ if (change === "insert" || (change === "replace" && n < ne)) {
+ var lineNumber = n++;
+ this._createLine(null, lineNumber, newLines[lineNumber], "added");
+ lastWasSeparator = false;
+ }
+
+ if (change === "equal") {
+ b++;
+ n++;
+ if (!lastWasSeparator)
+ this._createLine(null, null, " \u2026", "separator");
+ lastWasSeparator = true;
+ }
+ }
+ }
+ }
+ },
+
+ oncollapse: function()
+ {
+ this._revertElement.remove();
+ },
+
+ /**
+ * @param {?number} baseLineNumber
+ * @param {?number} newLineNumber
+ * @param {string} lineContent
+ * @param {string} changeType
+ */
+ _createLine: function(baseLineNumber, newLineNumber, lineContent, changeType)
+ {
+ var child = new TreeElement("", null, false);
+ child.selectable = false;
+ this.appendChild(child);
+ var lineElement = document.createElement("span");
+
+ function appendLineNumber(lineNumber)
+ {
+ var numberString = lineNumber !== null ? numberToStringWithSpacesPadding(lineNumber + 1, 4) : " ";
+ var lineNumberSpan = document.createElement("span");
+ lineNumberSpan.classList.add("webkit-line-number");
+ lineNumberSpan.textContent = numberString;
+ child.listItemElement.appendChild(lineNumberSpan);
+ }
+
+ appendLineNumber(baseLineNumber);
+ appendLineNumber(newLineNumber);
+
+ var contentSpan = document.createElement("span");
+ contentSpan.textContent = lineContent;
+ child.listItemElement.appendChild(contentSpan);
+ child.listItemElement.classList.add("revision-history-line");
+ child.listItemElement.classList.add("revision-history-line-" + changeType);
+ },
+
+ allowRevert: function()
+ {
+ this._revertElement.classList.remove("hidden");
+ },
+
+ __proto__: TreeElement.prototype
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js
new file mode 100644
index 00000000000..affe79cb8f8
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.SidebarPane}
+ */
+WebInspector.ScopeChainSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Scope Variables"));
+ this._sections = [];
+ this._expandedSections = {};
+ this._expandedProperties = [];
+}
+
+WebInspector.ScopeChainSidebarPane.prototype = {
+ /**
+ * @param {?WebInspector.DebuggerModel.CallFrame} callFrame
+ */
+ update: function(callFrame)
+ {
+ this.bodyElement.removeChildren();
+
+ if (!callFrame) {
+ var infoElement = document.createElement("div");
+ infoElement.className = "info";
+ infoElement.textContent = WebInspector.UIString("Not Paused");
+ this.bodyElement.appendChild(infoElement);
+ return;
+ }
+
+ for (var i = 0; i < this._sections.length; ++i) {
+ var section = this._sections[i];
+ if (!section.title)
+ continue;
+ if (section.expanded)
+ this._expandedSections[section.title] = true;
+ else
+ delete this._expandedSections[section.title];
+ }
+
+ this._sections = [];
+
+ var foundLocalScope = false;
+ var scopeChain = callFrame.scopeChain;
+ for (var i = 0; i < scopeChain.length; ++i) {
+ var scope = scopeChain[i];
+ var title = null;
+ var subtitle = scope.object.description;
+ var emptyPlaceholder = null;
+ var extraProperties = [];
+ var declarativeScope;
+
+ switch (scope.type) {
+ case DebuggerAgent.ScopeType.Local:
+ foundLocalScope = true;
+ title = WebInspector.UIString("Local");
+ emptyPlaceholder = WebInspector.UIString("No Variables");
+ subtitle = undefined;
+ var thisObject = callFrame.thisObject();
+ if (thisObject)
+ extraProperties.push(new WebInspector.RemoteObjectProperty("this", thisObject));
+ if (i == 0) {
+ var details = callFrame.target().debuggerModel.debuggerPausedDetails();
+ if (!callFrame.isAsync()) {
+ var exception = details.exception();
+ if (exception)
+ extraProperties.push(new WebInspector.RemoteObjectProperty("<exception>", exception));
+ }
+ var returnValue = callFrame.returnValue();
+ if (returnValue)
+ extraProperties.push(new WebInspector.RemoteObjectProperty("<return>", returnValue));
+ }
+ declarativeScope = true;
+ break;
+ case DebuggerAgent.ScopeType.Closure:
+ title = WebInspector.UIString("Closure");
+ emptyPlaceholder = WebInspector.UIString("No Variables");
+ subtitle = undefined;
+ declarativeScope = true;
+ break;
+ case DebuggerAgent.ScopeType.Catch:
+ title = WebInspector.UIString("Catch");
+ subtitle = undefined;
+ declarativeScope = true;
+ break;
+ case DebuggerAgent.ScopeType.With:
+ title = WebInspector.UIString("With Block");
+ declarativeScope = false;
+ break;
+ case DebuggerAgent.ScopeType.Global:
+ title = WebInspector.UIString("Global");
+ declarativeScope = false;
+ break;
+ }
+
+ if (!title || title === subtitle)
+ subtitle = undefined;
+
+ var runtimeModel = callFrame.target().runtimeModel;
+ if (declarativeScope)
+ var scopeObject = runtimeModel.createScopeRemoteObject(scope.object, new WebInspector.ScopeRef(i, callFrame.id, undefined));
+ else
+ var scopeObject = runtimeModel.createRemoteObject(scope.object);
+
+ var section = new WebInspector.ObjectPropertiesSection(scopeObject, title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement);
+ section.editInSelectedCallFrameWhenPaused = true;
+ section.pane = this;
+
+ if (scope.type === DebuggerAgent.ScopeType.Global)
+ section.expanded = false;
+ else if (!foundLocalScope || scope.type === DebuggerAgent.ScopeType.Local || title in this._expandedSections)
+ section.expanded = true;
+
+ this._sections.push(section);
+ this.bodyElement.appendChild(section.element);
+ }
+ },
+
+ __proto__: WebInspector.SidebarPane.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.ObjectPropertyTreeElement}
+ * @param {!WebInspector.RemoteObjectProperty} property
+ */
+WebInspector.ScopeVariableTreeElement = function(property)
+{
+ WebInspector.ObjectPropertyTreeElement.call(this, property);
+}
+
+WebInspector.ScopeVariableTreeElement.prototype = {
+ onattach: function()
+ {
+ WebInspector.ObjectPropertyTreeElement.prototype.onattach.call(this);
+ if (this.hasChildren && this.propertyIdentifier in this.treeOutline.section.pane._expandedProperties)
+ this.expand();
+ },
+
+ onexpand: function()
+ {
+ this.treeOutline.section.pane._expandedProperties[this.propertyIdentifier] = true;
+ },
+
+ oncollapse: function()
+ {
+ delete this.treeOutline.section.pane._expandedProperties[this.propertyIdentifier];
+ },
+
+ get propertyIdentifier()
+ {
+ if ("_propertyIdentifier" in this)
+ return this._propertyIdentifier;
+ var section = this.treeOutline.section;
+ this._propertyIdentifier = section.title + ":" + (section.subtitle ? section.subtitle + ":" : "") + this.propertyPath();
+ return this._propertyIdentifier;
+ },
+
+ __proto__: WebInspector.ObjectPropertyTreeElement.prototype
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatter.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatter.js
new file mode 100644
index 00000000000..b980bc67aa2
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatter.js
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @interface
+ */
+WebInspector.Formatter = function()
+{
+}
+
+/**
+ * @param {!WebInspector.ResourceType} contentType
+ * @return {!WebInspector.Formatter}
+ */
+WebInspector.Formatter.createFormatter = function(contentType)
+{
+ if (contentType === WebInspector.resourceTypes.Script || contentType === WebInspector.resourceTypes.Document || contentType === WebInspector.resourceTypes.Stylesheet)
+ return new WebInspector.ScriptFormatter();
+ return new WebInspector.IdentityFormatter();
+}
+
+/**
+ * @param {!Array.<number>} lineEndings
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {number}
+ */
+WebInspector.Formatter.locationToPosition = function(lineEndings, lineNumber, columnNumber)
+{
+ var position = lineNumber ? lineEndings[lineNumber - 1] + 1 : 0;
+ return position + columnNumber;
+}
+
+/**
+ * @param {!Array.<number>} lineEndings
+ * @param {number} position
+ * @return {!Array.<number>}
+ */
+WebInspector.Formatter.positionToLocation = function(lineEndings, position)
+{
+ var lineNumber = lineEndings.upperBound(position - 1);
+ if (!lineNumber)
+ var columnNumber = position;
+ else
+ var columnNumber = position - lineEndings[lineNumber - 1] - 1;
+ return [lineNumber, columnNumber];
+}
+
+WebInspector.Formatter.prototype = {
+ /**
+ * @param {string} mimeType
+ * @param {string} content
+ * @param {function(string, !WebInspector.FormatterSourceMapping)} callback
+ */
+ formatContent: function(mimeType, content, callback)
+ {
+ }
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.Formatter}
+ */
+WebInspector.ScriptFormatter = function()
+{
+ this._tasks = [];
+}
+
+WebInspector.ScriptFormatter.prototype = {
+ /**
+ * @param {string} mimeType
+ * @param {string} content
+ * @param {function(string, !WebInspector.FormatterSourceMapping)} callback
+ */
+ formatContent: function(mimeType, content, callback)
+ {
+ content = content.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '');
+ const method = "format";
+ var parameters = { mimeType: mimeType, content: content, indentString: WebInspector.settings.textEditorIndent.get() };
+ this._tasks.push({ data: parameters, callback: callback });
+ this._worker.postMessage({ method: method, params: parameters });
+ },
+
+ _didFormatContent: function(event)
+ {
+ var task = this._tasks.shift();
+ var originalContent = task.data.content;
+ var formattedContent = event.data.content;
+ var mapping = event.data["mapping"];
+ var sourceMapping = new WebInspector.FormatterSourceMappingImpl(originalContent.lineEndings(), formattedContent.lineEndings(), mapping);
+ task.callback(formattedContent, sourceMapping);
+ },
+
+ /**
+ * @return {!Worker}
+ */
+ get _worker()
+ {
+ if (!this._cachedWorker) {
+ this._cachedWorker = new Worker("script_formatter_worker/ScriptFormatterWorker.js");
+ this._cachedWorker.onmessage = /** @type {function(this:Worker)} */ (this._didFormatContent.bind(this));
+ }
+ return this._cachedWorker;
+ }
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.Formatter}
+ */
+WebInspector.IdentityFormatter = function()
+{
+ this._tasks = [];
+}
+
+WebInspector.IdentityFormatter.prototype = {
+ /**
+ * @param {string} mimeType
+ * @param {string} content
+ * @param {function(string, !WebInspector.FormatterSourceMapping)} callback
+ */
+ formatContent: function(mimeType, content, callback)
+ {
+ callback(content, new WebInspector.IdentityFormatterSourceMapping());
+ }
+}
+
+/**
+ * @constructor
+ */
+WebInspector.FormatterMappingPayload = function()
+{
+ this.original = [];
+ this.formatted = [];
+}
+
+/**
+ * @interface
+ */
+WebInspector.FormatterSourceMapping = function()
+{
+}
+
+WebInspector.FormatterSourceMapping.prototype = {
+ /**
+ * @param {number} lineNumber
+ * @param {number=} columnNumber
+ * @return {!Array.<number>}
+ */
+ originalToFormatted: function(lineNumber, columnNumber) { },
+
+ /**
+ * @param {number} lineNumber
+ * @param {number=} columnNumber
+ * @return {!Array.<number>}
+ */
+ formattedToOriginal: function(lineNumber, columnNumber) { }
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.FormatterSourceMapping}
+ */
+WebInspector.IdentityFormatterSourceMapping = function()
+{
+}
+
+WebInspector.IdentityFormatterSourceMapping.prototype = {
+ /**
+ * @param {number} lineNumber
+ * @param {number=} columnNumber
+ * @return {!Array.<number>}
+ */
+ originalToFormatted: function(lineNumber, columnNumber)
+ {
+ return [lineNumber, columnNumber || 0];
+ },
+
+ /**
+ * @param {number} lineNumber
+ * @param {number=} columnNumber
+ * @return {!Array.<number>}
+ */
+ formattedToOriginal: function(lineNumber, columnNumber)
+ {
+ return [lineNumber, columnNumber || 0];
+ }
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.FormatterSourceMapping}
+ * @param {!Array.<number>} originalLineEndings
+ * @param {!Array.<number>} formattedLineEndings
+ * @param {!WebInspector.FormatterMappingPayload} mapping
+ */
+WebInspector.FormatterSourceMappingImpl = function(originalLineEndings, formattedLineEndings, mapping)
+{
+ this._originalLineEndings = originalLineEndings;
+ this._formattedLineEndings = formattedLineEndings;
+ this._mapping = mapping;
+}
+
+WebInspector.FormatterSourceMappingImpl.prototype = {
+ /**
+ * @param {number} lineNumber
+ * @param {number=} columnNumber
+ * @return {!Array.<number>}
+ */
+ originalToFormatted: function(lineNumber, columnNumber)
+ {
+ var originalPosition = WebInspector.Formatter.locationToPosition(this._originalLineEndings, lineNumber, columnNumber || 0);
+ var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, originalPosition || 0);
+ return WebInspector.Formatter.positionToLocation(this._formattedLineEndings, formattedPosition);
+ },
+
+ /**
+ * @param {number} lineNumber
+ * @param {number=} columnNumber
+ * @return {!Array.<number>}
+ */
+ formattedToOriginal: function(lineNumber, columnNumber)
+ {
+ var formattedPosition = WebInspector.Formatter.locationToPosition(this._formattedLineEndings, lineNumber, columnNumber || 0);
+ var originalPosition = this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition);
+ return WebInspector.Formatter.positionToLocation(this._originalLineEndings, originalPosition || 0);
+ },
+
+ /**
+ * @param {!Array.<number>} positions1
+ * @param {!Array.<number>} positions2
+ * @param {number} position
+ * @return {number}
+ */
+ _convertPosition: function(positions1, positions2, position)
+ {
+ var index = positions1.upperBound(position) - 1;
+ var convertedPosition = positions2[index] + position - positions1[index];
+ if (index < positions2.length - 1 && convertedPosition > positions2[index + 1])
+ convertedPosition = positions2[index + 1];
+ return convertedPosition;
+ }
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatterEditorAction.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatterEditorAction.js
new file mode 100644
index 00000000000..b87af340451
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatterEditorAction.js
@@ -0,0 +1,379 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @constructor
+ * @implements {WebInspector.SourceMapping}
+ * @param {!WebInspector.Workspace} workspace
+ * @param {!WebInspector.DebuggerModel} debuggerModel
+ */
+WebInspector.FormatterScriptMapping = function(workspace, debuggerModel)
+{
+ this._workspace = workspace;
+ this._debuggerModel = debuggerModel;
+
+ this._init();
+
+ this._projectId = "formatter:";
+ this._projectDelegate = new WebInspector.FormatterProjectDelegate(workspace, this._projectId);
+ this._debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
+}
+
+WebInspector.FormatterScriptMapping.prototype = {
+ /**
+ * @param {!WebInspector.RawLocation} rawLocation
+ * @return {?WebInspector.UILocation}
+ */
+ rawLocationToUILocation: function(rawLocation)
+ {
+ var debuggerModelLocation = /** @type {!WebInspector.DebuggerModel.Location} */ (rawLocation);
+ var script = debuggerModelLocation.script();
+ var uiSourceCode = this._uiSourceCodes.get(script);
+ if (!uiSourceCode)
+ return null;
+
+ var formatData = this._formatData.get(uiSourceCode);
+ if (!formatData)
+ return null;
+ var mapping = formatData.mapping;
+ var lineNumber = debuggerModelLocation.lineNumber;
+ var columnNumber = debuggerModelLocation.columnNumber || 0;
+ var formattedLocation = mapping.originalToFormatted(lineNumber, columnNumber);
+ return uiSourceCode.uiLocation(formattedLocation[0], formattedLocation[1]);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {?WebInspector.DebuggerModel.Location}
+ */
+ uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
+ {
+ var formatData = this._formatData.get(uiSourceCode);
+ if (!formatData)
+ return null;
+ var originalLocation = formatData.mapping.formattedToOriginal(lineNumber, columnNumber)
+ return this._debuggerModel.createRawLocation(formatData.scripts[0], originalLocation[0], originalLocation[1]);
+ },
+
+ /**
+ * @return {boolean}
+ */
+ isIdentity: function()
+ {
+ return false;
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {!Array.<!WebInspector.Script>}
+ */
+ _scriptsForUISourceCode: function(uiSourceCode)
+ {
+ /**
+ * @param {!WebInspector.Script} script
+ * @return {boolean}
+ */
+ function isInlineScript(script)
+ {
+ return script.isInlineScript();
+ }
+
+ if (uiSourceCode.contentType() === WebInspector.resourceTypes.Document)
+ return this._debuggerModel.scriptsForSourceURL(uiSourceCode.url).filter(isInlineScript);
+ if (uiSourceCode.contentType() === WebInspector.resourceTypes.Script) {
+ var rawLocation = /** @type {!WebInspector.DebuggerModel.Location} */ (uiSourceCode.uiLocationToRawLocation(this._debuggerModel.target(), 0, 0));
+ return rawLocation ? [rawLocation.script()] : [];
+ }
+ return [];
+ },
+
+ _init: function()
+ {
+ /** @type {!Map.<!WebInspector.Script, !WebInspector.UISourceCode>} */
+ this._uiSourceCodes = new Map();
+ /** @type {!StringMap.<string>} */
+ this._formattedPaths = new StringMap();
+ /** @type {!Map.<!WebInspector.UISourceCode, !WebInspector.FormatterScriptMapping.FormatData>} */
+ this._formatData = new Map();
+ },
+
+ _debuggerReset: function()
+ {
+ var formattedPaths = this._formattedPaths.values();
+ for (var i = 0; i < formattedPaths.length; ++i)
+ this._projectDelegate._removeFormatted(formattedPaths[i]);
+ this._init();
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {function(?WebInspector.UISourceCode, !WebInspector.FormatterSourceMapping=)} callback
+ */
+ _performUISourceCodeScriptFormatting: function(uiSourceCode, callback)
+ {
+ var path = this._formattedPaths.get(uiSourceCode.project().id() + ":" + uiSourceCode.path());
+ if (path) {
+ var uiSourceCodePath = path;
+ var formattedUISourceCode = this._workspace.uiSourceCode(this._projectId, uiSourceCodePath);
+ var formatData = formattedUISourceCode ? this._formatData.get(formattedUISourceCode) : null;
+ if (!formatData)
+ callback(null);
+ else
+ callback(formattedUISourceCode, formatData.mapping);
+ return;
+ }
+
+ uiSourceCode.requestContent(contentLoaded.bind(this));
+
+ /**
+ * @this {WebInspector.FormatterScriptMapping}
+ * @param {?string} content
+ */
+ function contentLoaded(content)
+ {
+ var formatter = WebInspector.Formatter.createFormatter(uiSourceCode.contentType());
+ formatter.formatContent(uiSourceCode.highlighterType(), content || "", innerCallback.bind(this));
+ }
+
+ /**
+ * @this {WebInspector.FormatterScriptMapping}
+ * @param {string} formattedContent
+ * @param {!WebInspector.FormatterSourceMapping} formatterMapping
+ */
+ function innerCallback(formattedContent, formatterMapping)
+ {
+ var scripts = this._scriptsForUISourceCode(uiSourceCode);
+ if (!scripts.length) {
+ callback(null);
+ return;
+ }
+ var name;
+ if (uiSourceCode.contentType() === WebInspector.resourceTypes.Document)
+ name = uiSourceCode.displayName();
+ else
+ name = uiSourceCode.name() || scripts[0].scriptId;
+ path = this._projectDelegate._addFormatted(name, uiSourceCode.url, uiSourceCode.contentType(), formattedContent);
+ var formattedUISourceCode = /** @type {!WebInspector.UISourceCode} */ (this._workspace.uiSourceCode(this._projectId, path));
+
+ var formatData = new WebInspector.FormatterScriptMapping.FormatData(uiSourceCode.project().id(), uiSourceCode.path(), formatterMapping, scripts);
+ this._formatData.put(formattedUISourceCode, formatData);
+ this._formattedPaths.put(uiSourceCode.project().id() + ":" + uiSourceCode.path(), path);
+ for (var i = 0; i < scripts.length; ++i) {
+ this._uiSourceCodes.put(scripts[i], formattedUISourceCode);
+ scripts[i].pushSourceMapping(this);
+ }
+ formattedUISourceCode.setSourceMappingForTarget(this._debuggerModel.target(), this);
+ callback(formattedUISourceCode, formatterMapping);
+ }
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} formattedUISourceCode
+ * @return {?WebInspector.FormatterSourceMapping}
+ */
+ _discardFormattedUISourceCodeScript: function(formattedUISourceCode)
+ {
+ var formatData = this._formatData.get(formattedUISourceCode);
+ if (!formatData)
+ return null;
+
+ this._formatData.remove(formattedUISourceCode);
+ this._formattedPaths.remove(formatData.projectId + ":" + formatData.path);
+ for (var i = 0; i < formatData.scripts.length; ++i) {
+ this._uiSourceCodes.remove(formatData.scripts[i]);
+ formatData.scripts[i].popSourceMapping();
+ }
+ this._projectDelegate._removeFormatted(formattedUISourceCode.path());
+ return formatData.mapping;
+ }
+}
+
+/**
+ * @constructor
+ * @param {string} projectId
+ * @param {string} path
+ * @param {!WebInspector.FormatterSourceMapping} mapping
+ * @param {!Array.<!WebInspector.Script>} scripts
+ */
+WebInspector.FormatterScriptMapping.FormatData = function(projectId, path, mapping, scripts)
+{
+ this.projectId = projectId;
+ this.path = path;
+ this.mapping = mapping;
+ this.scripts = scripts;
+}
+
+/**
+ * @constructor
+ * @param {!WebInspector.Workspace} workspace
+ * @param {string} id
+ * @extends {WebInspector.ContentProviderBasedProjectDelegate}
+ */
+WebInspector.FormatterProjectDelegate = function(workspace, id)
+{
+ WebInspector.ContentProviderBasedProjectDelegate.call(this, workspace, id, WebInspector.projectTypes.Formatter);
+}
+
+WebInspector.FormatterProjectDelegate.prototype = {
+ /**
+ * @return {string}
+ */
+ displayName: function()
+ {
+ return "formatter";
+ },
+
+ /**
+ * @param {string} name
+ * @param {string} sourceURL
+ * @param {!WebInspector.ResourceType} contentType
+ * @param {string} content
+ * @return {string}
+ */
+ _addFormatted: function(name, sourceURL, contentType, content)
+ {
+ var contentProvider = new WebInspector.StaticContentProvider(contentType, content);
+ return this.addContentProvider(sourceURL, name + ":formatted", "deobfuscated:" + sourceURL, contentProvider);
+ },
+
+ /**
+ * @param {string} path
+ */
+ _removeFormatted: function(path)
+ {
+ this.removeFile(path);
+ },
+
+ __proto__: WebInspector.ContentProviderBasedProjectDelegate.prototype
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.SourcesView.EditorAction}
+ */
+WebInspector.ScriptFormatterEditorAction = function()
+{
+ this._scriptMapping = new WebInspector.FormatterScriptMapping(WebInspector.workspace, WebInspector.debuggerModel);
+}
+
+WebInspector.ScriptFormatterEditorAction.prototype = {
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _editorSelected: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
+ this._updateButton(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _editorClosed: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.uiSourceCode);
+ var wasSelected = /** @type {boolean} */ (event.data.wasSelected);
+
+ if (wasSelected)
+ this._updateButton(null);
+ this._discardFormattedUISourceCodeScript(uiSourceCode);
+ },
+
+ /**
+ * @param {?WebInspector.UISourceCode} uiSourceCode
+ */
+ _updateButton: function(uiSourceCode)
+ {
+ this._button.element.classList.toggle("hidden", !this._isFormatableScript(uiSourceCode));
+ },
+
+ /**
+ * @param {!WebInspector.SourcesView} sourcesView
+ * @return {!Element}
+ */
+ button: function(sourcesView)
+ {
+ if (this._button)
+ return this._button.element;
+
+ this._sourcesView = sourcesView;
+ this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorSelected, this._editorSelected.bind(this));
+ this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorClosed, this._editorClosed.bind(this));
+
+ this._button = new WebInspector.StatusBarButton(WebInspector.UIString("Pretty print"), "sources-toggle-pretty-print-status-bar-item");
+ this._button.toggled = false;
+ this._button.addEventListener("click", this._toggleFormatScriptSource, this);
+ this._updateButton(null);
+
+ return this._button.element;
+ },
+
+ /**
+ * @param {?WebInspector.UISourceCode} uiSourceCode
+ * @return {boolean}
+ */
+ _isFormatableScript: function(uiSourceCode)
+ {
+ if (!uiSourceCode)
+ return false;
+ var supportedProjectTypes = [WebInspector.projectTypes.Network, WebInspector.projectTypes.Debugger, WebInspector.projectTypes.ContentScripts];
+ if (supportedProjectTypes.indexOf(uiSourceCode.project().type()) === -1)
+ return false;
+ var contentType = uiSourceCode.contentType();
+ return contentType === WebInspector.resourceTypes.Script || contentType === WebInspector.resourceTypes.Document;
+ },
+
+ _toggleFormatScriptSource: function()
+ {
+ var uiSourceCode = this._sourcesView.currentUISourceCode();
+ if (!this._isFormatableScript(uiSourceCode))
+ return;
+ this._formatUISourceCodeScript(uiSourceCode);
+
+ WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
+ action: WebInspector.UserMetrics.UserActionNames.TogglePrettyPrint,
+ enabled: true,
+ url: uiSourceCode.originURL()
+ });
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _formatUISourceCodeScript: function(uiSourceCode)
+ {
+ this._scriptMapping._performUISourceCodeScriptFormatting(uiSourceCode, innerCallback.bind(this));
+
+ /**
+ * @this {WebInspector.ScriptFormatterEditorAction}
+ * @param {?WebInspector.UISourceCode} formattedUISourceCode
+ * @param {!WebInspector.FormatterSourceMapping=} mapping
+ */
+ function innerCallback(formattedUISourceCode, mapping)
+ {
+ if (!formattedUISourceCode)
+ return;
+ if (uiSourceCode !== this._sourcesView.currentUISourceCode())
+ return;
+ var sourceFrame = this._sourcesView.viewForFile(uiSourceCode);
+ var start = [0, 0];
+ if (sourceFrame) {
+ var selection = sourceFrame.selection();
+ start = mapping.originalToFormatted(selection.startLine, selection.startColumn);
+ }
+ this._sourcesView.showSourceLocation(formattedUISourceCode, start[0], start[1]);
+ this._updateButton(formattedUISourceCode);
+ }
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _discardFormattedUISourceCodeScript: function(uiSourceCode)
+ {
+ this._scriptMapping._discardFormattedUISourceCodeScript(uiSourceCode);
+ }
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/SimpleHistoryManager.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/SimpleHistoryManager.js
new file mode 100644
index 00000000000..5771e7a0e97
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/SimpleHistoryManager.js
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @interface
+ */
+WebInspector.HistoryEntry = function() { }
+
+WebInspector.HistoryEntry.prototype = {
+ /**
+ * @return {boolean}
+ */
+ valid: function() { },
+
+ reveal: function() { }
+};
+
+/**
+ * @constructor
+ * @param {number} historyDepth
+ */
+WebInspector.SimpleHistoryManager = function(historyDepth)
+{
+ this._entries = [];
+ this._activeEntryIndex = -1;
+ this._coalescingReadonly = 0;
+ this._historyDepth = historyDepth;
+}
+
+WebInspector.SimpleHistoryManager.prototype = {
+ readOnlyLock: function()
+ {
+ ++this._coalescingReadonly;
+ },
+
+ releaseReadOnlyLock: function()
+ {
+ --this._coalescingReadonly;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ readOnly: function()
+ {
+ return !!this._coalescingReadonly;
+ },
+
+ /**
+ * @param {!function(!WebInspector.HistoryEntry):boolean} filterOutCallback
+ */
+ filterOut: function(filterOutCallback)
+ {
+ if (this.readOnly())
+ return;
+ var filteredEntries = [];
+ var removedBeforeActiveEntry = 0;
+ for (var i = 0; i < this._entries.length; ++i) {
+ if (!filterOutCallback(this._entries[i])) {
+ filteredEntries.push(this._entries[i]);
+ } else if (i <= this._activeEntryIndex)
+ ++removedBeforeActiveEntry;
+ }
+ this._entries = filteredEntries;
+ this._activeEntryIndex = Math.max(0, this._activeEntryIndex - removedBeforeActiveEntry);
+ },
+
+ /**
+ * @return {boolean}
+ */
+ empty: function()
+ {
+ return !this._entries.length;
+ },
+
+ /**
+ * @return {?WebInspector.HistoryEntry}
+ */
+ active: function()
+ {
+ return this.empty() ? null : this._entries[this._activeEntryIndex];
+ },
+
+ /**
+ * @param {!WebInspector.HistoryEntry} entry
+ */
+ push: function(entry)
+ {
+ if (this.readOnly())
+ return;
+ if (!this.empty())
+ this._entries.splice(this._activeEntryIndex + 1);
+ this._entries.push(entry);
+ if (this._entries.length > this._historyDepth)
+ this._entries.shift();
+ this._activeEntryIndex = this._entries.length - 1;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ rollback: function()
+ {
+ if (this.empty())
+ return false;
+
+ var revealIndex = this._activeEntryIndex - 1;
+ while (revealIndex >= 0 && !this._entries[revealIndex].valid())
+ --revealIndex;
+ if (revealIndex < 0)
+ return false;
+
+ this.readOnlyLock();
+ this._entries[revealIndex].reveal();
+ this.releaseReadOnlyLock();
+
+ this._activeEntryIndex = revealIndex;
+ return true;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ rollover: function()
+ {
+ var revealIndex = this._activeEntryIndex + 1;
+
+ while (revealIndex < this._entries.length && !this._entries[revealIndex].valid())
+ ++revealIndex;
+ if (revealIndex >= this._entries.length)
+ return false;
+
+ this.readOnlyLock();
+ this._entries[revealIndex].reveal();
+ this.releaseReadOnlyLock();
+
+ this._activeEntryIndex = revealIndex;
+ return true;
+ },
+};
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js
new file mode 100644
index 00000000000..ce6a897c9f8
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
+ * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.Object}
+ * @param {!WebInspector.Workspace} workspace
+ */
+WebInspector.SourcesNavigator = function(workspace)
+{
+ WebInspector.Object.call(this);
+ this._workspace = workspace;
+
+ this._tabbedPane = new WebInspector.TabbedPane();
+ this._tabbedPane.shrinkableTabs = true;
+ this._tabbedPane.element.classList.add("navigator-tabbed-pane");
+ new WebInspector.ExtensibleTabbedPaneController(this._tabbedPane, "navigator-view", this._navigatorViewCreated.bind(this));
+ /** @type {!StringMap.<?WebInspector.NavigatorView>} */
+ this._navigatorViews = new StringMap();
+}
+
+WebInspector.SourcesNavigator.Events = {
+ SourceSelected: "SourceSelected",
+ SourceRenamed: "SourceRenamed"
+}
+
+WebInspector.SourcesNavigator.prototype = {
+ /**
+ * @param {string} id
+ * @param {!WebInspector.View} view
+ */
+ _navigatorViewCreated: function(id, view)
+ {
+ var navigatorView = /** @type {!WebInspector.NavigatorView} */ (view);
+ navigatorView.addEventListener(WebInspector.NavigatorView.Events.ItemSelected, this._sourceSelected, this);
+ navigatorView.addEventListener(WebInspector.NavigatorView.Events.ItemRenamed, this._sourceRenamed, this);
+ this._navigatorViews.put(id, navigatorView);
+ navigatorView.setWorkspace(this._workspace);
+ },
+
+ /**
+ * @return {!WebInspector.View}
+ */
+ get view()
+ {
+ return this._tabbedPane;
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {string|null}
+ */
+ _navigatorViewIdForUISourceCode: function(uiSourceCode)
+ {
+ var ids = this._navigatorViews.keys();
+ for (var i = 0; i < ids.length; ++i) {
+ var id = ids[i]
+ var navigatorView = this._navigatorViews.get(id);
+ if (navigatorView.accept(uiSourceCode))
+ return id;
+ }
+ return null;
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ revealUISourceCode: function(uiSourceCode)
+ {
+ var id = this._navigatorViewIdForUISourceCode(uiSourceCode);
+ if (!id)
+ return;
+ var navigatorView = this._navigatorViews.get(id);
+ console.assert(navigatorView);
+ navigatorView.revealUISourceCode(uiSourceCode, true);
+ this._tabbedPane.selectTab(id);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _sourceSelected: function(event)
+ {
+ this.dispatchEventToListeners(WebInspector.SourcesNavigator.Events.SourceSelected, event.data);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _sourceRenamed: function(event)
+ {
+ this.dispatchEventToListeners(WebInspector.SourcesNavigator.Events.SourceRenamed, event.data);
+ },
+
+ __proto__: WebInspector.Object.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.NavigatorView}
+ */
+WebInspector.SnippetsNavigatorView = function()
+{
+ WebInspector.NavigatorView.call(this);
+}
+
+WebInspector.SnippetsNavigatorView.prototype = {
+ /**
+ * @override
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {boolean}
+ */
+ accept: function(uiSourceCode)
+ {
+ if (!WebInspector.NavigatorView.prototype.accept(uiSourceCode))
+ return false;
+ return uiSourceCode.project().type() === WebInspector.projectTypes.Snippets;
+ },
+
+ /**
+ * @param {!Event} event
+ */
+ handleContextMenu: function(event)
+ {
+ var contextMenu = new WebInspector.ContextMenu(event);
+ contextMenu.appendItem(WebInspector.UIString("New"), this._handleCreateSnippet.bind(this));
+ contextMenu.show();
+ },
+
+ /**
+ * @param {!Event} event
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ handleFileContextMenu: function(event, uiSourceCode)
+ {
+ var contextMenu = new WebInspector.ContextMenu(event);
+ contextMenu.appendItem(WebInspector.UIString("Run"), this._handleEvaluateSnippet.bind(this, uiSourceCode));
+ contextMenu.appendItem(WebInspector.UIString("Rename"), this.rename.bind(this, uiSourceCode));
+ contextMenu.appendItem(WebInspector.UIString("Remove"), this._handleRemoveSnippet.bind(this, uiSourceCode));
+ contextMenu.appendSeparator();
+ contextMenu.appendItem(WebInspector.UIString("New"), this._handleCreateSnippet.bind(this));
+ contextMenu.show();
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _handleEvaluateSnippet: function(uiSourceCode)
+ {
+ var executionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
+ if (uiSourceCode.project().type() !== WebInspector.projectTypes.Snippets || !executionContext)
+ return;
+ WebInspector.scriptSnippetModel.evaluateScriptSnippet(executionContext, uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _handleRemoveSnippet: function(uiSourceCode)
+ {
+ if (uiSourceCode.project().type() !== WebInspector.projectTypes.Snippets)
+ return;
+ uiSourceCode.remove();
+ },
+
+ _handleCreateSnippet: function()
+ {
+ this.create(WebInspector.scriptSnippetModel.project(), "")
+ },
+
+ /**
+ * @override
+ */
+ sourceDeleted: function(uiSourceCode)
+ {
+ this._handleRemoveSnippet(uiSourceCode);
+ },
+
+ __proto__: WebInspector.NavigatorView.prototype
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
new file mode 100644
index 00000000000..bf570c2b982
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -0,0 +1,1479 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+importScript("Placard.js");
+importScript("BreakpointsSidebarPane.js");
+importScript("CallStackSidebarPane.js");
+importScript("SimpleHistoryManager.js");
+importScript("EditingLocationHistoryManager.js");
+importScript("FilePathScoreFunction.js");
+importScript("FilteredItemSelectionDialog.js");
+importScript("UISourceCodeFrame.js");
+importScript("JavaScriptSourceFrame.js");
+importScript("CSSSourceFrame.js");
+importScript("NavigatorView.js");
+importScript("RevisionHistoryView.js");
+importScript("ScopeChainSidebarPane.js");
+importScript("SourcesNavigator.js");
+importScript("StyleSheetOutlineDialog.js");
+importScript("TabbedEditorContainer.js");
+importScript("WatchExpressionsSidebarPane.js");
+importScript("WorkersSidebarPane.js");
+importScript("TargetsToolbar.js");
+importScript("ScriptFormatterEditorAction.js");
+importScript("InplaceFormatterEditorAction.js");
+importScript("ScriptFormatter.js");
+importScript("SourcesView.js");
+
+/**
+ * @constructor
+ * @implements {WebInspector.ContextMenu.Provider}
+ * @implements {WebInspector.TargetManager.Observer}
+ * @extends {WebInspector.Panel}
+ * @param {!WebInspector.Workspace=} workspaceForTest
+ */
+WebInspector.SourcesPanel = function(workspaceForTest)
+{
+ WebInspector.Panel.call(this, "sources");
+ this.registerRequiredCSS("sourcesPanel.css");
+ this.registerRequiredCSS("suggestBox.css");
+ new WebInspector.UpgradeFileSystemDropTarget(this.element);
+
+ WebInspector.settings.showEditorInDrawer = WebInspector.settings.createSetting("showEditorInDrawer", true);
+
+ this._workspace = workspaceForTest || WebInspector.workspace;
+
+ var helpSection = WebInspector.shortcutsScreen.section(WebInspector.UIString("Sources Panel"));
+ this.debugToolbar = this._createDebugToolbar();
+ this._debugToolbarDrawer = this._createDebugToolbarDrawer();
+ this._targetsToolbar = new WebInspector.TargetsToolbar();
+
+ const initialDebugSidebarWidth = 225;
+ this._splitView = new WebInspector.SplitView(true, true, "sourcesPanelSplitViewState", initialDebugSidebarWidth);
+ this._splitView.enableShowModeSaving();
+ this._splitView.show(this.element);
+
+ // Create scripts navigator
+ const initialNavigatorWidth = 225;
+ this.editorView = new WebInspector.SplitView(true, false, "sourcesPanelNavigatorSplitViewState", initialNavigatorWidth);
+ this.editorView.enableShowModeSaving();
+ this.editorView.element.id = "scripts-editor-split-view";
+ this.editorView.element.tabIndex = 0;
+ this.editorView.show(this._splitView.mainElement());
+
+ this._navigator = new WebInspector.SourcesNavigator(this._workspace);
+ this._navigator.view.setMinimumSize(100, 25);
+ this._navigator.view.show(this.editorView.sidebarElement());
+ this._navigator.addEventListener(WebInspector.SourcesNavigator.Events.SourceSelected, this._sourceSelected, this);
+ this._navigator.addEventListener(WebInspector.SourcesNavigator.Events.SourceRenamed, this._sourceRenamed, this);
+
+ this._sourcesView = new WebInspector.SourcesView(this._workspace, this);
+ this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorSelected, this._editorSelected.bind(this));
+ this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorClosed, this._editorClosed.bind(this));
+ this._sourcesView.registerShortcuts(this.registerShortcuts.bind(this));
+
+ if (WebInspector.experimentsSettings.editorInDrawer.isEnabled()) {
+ this._drawerEditorView = new WebInspector.SourcesPanel.DrawerEditorView();
+ this._sourcesView.show(this._drawerEditorView.element);
+ } else {
+ this._sourcesView.show(this.editorView.mainElement());
+ }
+
+ this._debugSidebarResizeWidgetElement = document.createElementWithClass("div", "resizer-widget");
+ this._debugSidebarResizeWidgetElement.id = "scripts-debug-sidebar-resizer-widget";
+ this._splitView.addEventListener(WebInspector.SplitView.Events.ShowModeChanged, this._updateDebugSidebarResizeWidget, this);
+ this._updateDebugSidebarResizeWidget();
+ this._splitView.installResizer(this._debugSidebarResizeWidgetElement);
+
+ this.sidebarPanes = {};
+ this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
+ this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
+ this.sidebarPanes.callstack.addEventListener(WebInspector.CallStackSidebarPane.Events.CallFrameSelected, this._callFrameSelectedInSidebar.bind(this));
+ this.sidebarPanes.callstack.addEventListener(WebInspector.CallStackSidebarPane.Events.CallFrameRestarted, this._callFrameRestartedInSidebar.bind(this));
+ this.sidebarPanes.callstack.registerShortcuts(this.registerShortcuts.bind(this));
+
+ this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
+ this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(WebInspector.debuggerModel, WebInspector.breakpointManager, this.showUISourceCode.bind(this));
+ this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane.createProxy(this);
+ this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane();
+ this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
+
+ if (Capabilities.isMainFrontend)
+ this.sidebarPanes.workerList = new WebInspector.WorkersSidebarPane();
+
+ this._extensionSidebarPanes = [];
+ this._installDebuggerSidebarController();
+
+ WebInspector.dockController.addEventListener(WebInspector.DockController.Events.DockSideChanged, this._dockSideChanged.bind(this));
+ WebInspector.settings.splitVerticallyWhenDockedToRight.addChangeListener(this._dockSideChanged.bind(this));
+ this._dockSideChanged();
+
+ this._updateDebuggerButtons();
+ this._pauseOnExceptionEnabledChanged();
+ WebInspector.settings.pauseOnExceptionEnabled.addChangeListener(this._pauseOnExceptionEnabledChanged, this);
+ WebInspector.targetManager.observeTargets(this);
+ this._setTarget(WebInspector.context.flavor(WebInspector.Target));
+ WebInspector.context.addFlavorChangeListener(WebInspector.Target, this._onCurrentTargetChanged, this);
+}
+
+WebInspector.SourcesPanel.minToolbarWidth = 215;
+
+WebInspector.SourcesPanel.prototype = {
+ /**
+ * @param {!WebInspector.Target} target
+ */
+ targetAdded: function(target)
+ {
+ target.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
+ target.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerReset, this);
+ target.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
+ target.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
+ target.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.CallFrameSelected, this._callFrameSelected, this);
+ target.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this);
+ target.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this);
+ target.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
+ },
+
+ /**
+ * @param {!WebInspector.Target} target
+ */
+ targetRemoved: function(target)
+ {
+ target.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
+ target.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerReset, this);
+ target.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
+ target.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
+ target.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.CallFrameSelected, this._callFrameSelected, this);
+ target.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this);
+ target.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this);
+ target.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
+ },
+
+ /**
+ * @param {?WebInspector.Target} target
+ */
+ _setTarget: function(target)
+ {
+ if (!target)
+ return;
+
+ if (target.debuggerModel.isPaused()) {
+ this._showDebuggerPausedDetails(/** @type {!WebInspector.DebuggerPausedDetails} */ (target.debuggerModel.debuggerPausedDetails()));
+ var callFrame = target.debuggerModel.selectedCallFrame();
+ if (callFrame)
+ this._selectCallFrame(callFrame);
+ } else {
+ this._paused = false;
+ this._clearInterface();
+ this._toggleDebuggerSidebarButton.setEnabled(true);
+ }
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _onCurrentTargetChanged: function(event)
+ {
+ var target = /** @type {?WebInspector.Target} */ (event.data);
+ this._setTarget(target);
+ },
+
+ /**
+ * @return {!Element}
+ */
+ defaultFocusedElement: function()
+ {
+ return this._sourcesView.defaultFocusedElement() || this._navigator.view.defaultFocusedElement();
+ },
+
+ /**
+ * @return {boolean}
+ */
+ paused: function()
+ {
+ return this._paused;
+ },
+
+ /**
+ * @return {!WebInspector.SourcesPanel.DrawerEditor}
+ */
+ _drawerEditor: function()
+ {
+ var drawerEditorInstance = WebInspector.moduleManager.instance(WebInspector.DrawerEditor);
+ console.assert(drawerEditorInstance instanceof WebInspector.SourcesPanel.DrawerEditor, "WebInspector.DrawerEditor module instance does not use WebInspector.SourcesPanel.DrawerEditor as an implementation. ");
+ return /** @type {!WebInspector.SourcesPanel.DrawerEditor} */ (drawerEditorInstance);
+ },
+
+ wasShown: function()
+ {
+ WebInspector.context.setFlavor(WebInspector.SourcesPanel, this);
+ if (WebInspector.experimentsSettings.editorInDrawer.isEnabled()) {
+ this._drawerEditor()._panelWasShown();
+ this._sourcesView.show(this.editorView.mainElement());
+ }
+ WebInspector.Panel.prototype.wasShown.call(this);
+ },
+
+ willHide: function()
+ {
+ WebInspector.Panel.prototype.willHide.call(this);
+ if (WebInspector.experimentsSettings.editorInDrawer.isEnabled()) {
+ this._drawerEditor()._panelWillHide();
+ this._sourcesView.show(this._drawerEditorView.element);
+ }
+ WebInspector.context.setFlavor(WebInspector.SourcesPanel, null);
+ },
+
+ /**
+ * @return {!WebInspector.SearchableView}
+ */
+ searchableView: function()
+ {
+ return this._sourcesView.searchableView();
+ },
+
+ _consoleCommandEvaluatedInSelectedCallFrame: function(event)
+ {
+ this.sidebarPanes.scopechain.update(WebInspector.debuggerModel.selectedCallFrame());
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _debuggerPaused: function(event)
+ {
+ var details = /** @type {!WebInspector.DebuggerPausedDetails} */ (event.data);
+ if (!this._paused)
+ WebInspector.inspectorView.setCurrentPanel(this);
+
+ if (WebInspector.context.flavor(WebInspector.Target) === details.target())
+ this._showDebuggerPausedDetails(details);
+ else if (!this._paused)
+ WebInspector.context.setFlavor(WebInspector.Target, details.target());
+ },
+
+ /**
+ * @param {!WebInspector.DebuggerPausedDetails} details
+ */
+ _showDebuggerPausedDetails: function(details)
+ {
+ this._paused = true;
+ this._updateDebuggerButtons();
+
+ this.sidebarPanes.callstack.update(details);
+
+ /**
+ * @param {!Element} element
+ * @this {WebInspector.SourcesPanel}
+ */
+ function didCreateBreakpointHitStatusMessage(element)
+ {
+ this.sidebarPanes.callstack.setStatus(element);
+ }
+
+ /**
+ * @param {!WebInspector.UILocation} uiLocation
+ * @this {WebInspector.SourcesPanel}
+ */
+ function didGetUILocation(uiLocation)
+ {
+ var breakpoint = WebInspector.breakpointManager.findBreakpointOnLine(uiLocation.uiSourceCode, uiLocation.lineNumber);
+ if (!breakpoint)
+ return;
+ this.sidebarPanes.jsBreakpoints.highlightBreakpoint(breakpoint);
+ this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
+ }
+
+ if (details.reason === WebInspector.DebuggerModel.BreakReason.DOM) {
+ WebInspector.domBreakpointsSidebarPane.highlightBreakpoint(details.auxData);
+ WebInspector.domBreakpointsSidebarPane.createBreakpointHitStatusMessage(details, didCreateBreakpointHitStatusMessage.bind(this));
+ } else if (details.reason === WebInspector.DebuggerModel.BreakReason.EventListener) {
+ var eventName = details.auxData["eventName"];
+ var targetName = details.auxData["targetName"];
+ this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(eventName, targetName);
+ var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName, details.auxData);
+ this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI));
+ } else if (details.reason === WebInspector.DebuggerModel.BreakReason.XHR) {
+ this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.auxData["breakpointURL"]);
+ this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest."));
+ } else if (details.reason === WebInspector.DebuggerModel.BreakReason.Exception)
+ this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData["description"]));
+ else if (details.reason === WebInspector.DebuggerModel.BreakReason.Assert)
+ this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on assertion."));
+ else if (details.reason === WebInspector.DebuggerModel.BreakReason.CSPViolation)
+ this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a script blocked due to Content Security Policy directive: \"%s\".", details.auxData["directiveText"]));
+ else if (details.reason === WebInspector.DebuggerModel.BreakReason.DebugCommand)
+ this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a debugged function"));
+ else {
+ if (details.callFrames.length)
+ details.callFrames[0].createLiveLocation(didGetUILocation.bind(this));
+ else
+ console.warn("ScriptsPanel paused, but callFrames.length is zero."); // TODO remove this once we understand this case better
+ }
+
+ this._splitView.showBoth(true);
+ this._toggleDebuggerSidebarButton.setEnabled(false);
+ window.focus();
+ InspectorFrontendHost.bringToFront();
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _debuggerResumed: function(event)
+ {
+ var target = /** @type {!WebInspector.Target} */ (event.target.target());
+ if (WebInspector.context.flavor(WebInspector.Target) !== target)
+ return;
+ this._paused = false;
+ this._clearInterface();
+ this._toggleDebuggerSidebarButton.setEnabled(true);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _debuggerWasEnabled: function(event)
+ {
+ var target = /** @type {!WebInspector.Target} */ (event.target.target());
+ if (WebInspector.context.flavor(WebInspector.Target) !== target)
+ return;
+
+ this._updateDebuggerButtons();
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _debuggerReset: function(event)
+ {
+ this._debuggerResumed(event);
+ delete this._skipExecutionLineRevealing;
+ },
+
+ /**
+ * @return {!WebInspector.View}
+ */
+ get visibleView()
+ {
+ return this._sourcesView.visibleView();
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {number=} lineNumber
+ * @param {number=} columnNumber
+ * @param {boolean=} forceShowInPanel
+ */
+ showUISourceCode: function(uiSourceCode, lineNumber, columnNumber, forceShowInPanel)
+ {
+ this._showEditor(forceShowInPanel);
+ this._sourcesView.showSourceLocation(uiSourceCode, lineNumber, columnNumber);
+ },
+
+ _showEditor: function(forceShowInPanel)
+ {
+ if (this._sourcesView.isShowing())
+ return;
+
+ if (this._shouldShowEditorInDrawer() && !forceShowInPanel)
+ this._drawerEditor()._show();
+ else
+ WebInspector.inspectorView.showPanel("sources");
+ },
+
+ /**
+ * @param {!WebInspector.UILocation} uiLocation
+ * @param {boolean=} forceShowInPanel
+ */
+ showUILocation: function(uiLocation, forceShowInPanel)
+ {
+ this.showUISourceCode(uiLocation.uiSourceCode, uiLocation.lineNumber, uiLocation.columnNumber, forceShowInPanel);
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _shouldShowEditorInDrawer: function()
+ {
+ return WebInspector.experimentsSettings.editorInDrawer.isEnabled() && WebInspector.settings.showEditorInDrawer.get() && WebInspector.inspectorView.isDrawerEditorShown();
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _revealInNavigator: function(uiSourceCode)
+ {
+ this._navigator.revealUISourceCode(uiSourceCode);
+ },
+
+ _executionLineChanged: function(uiLocation)
+ {
+ this._sourcesView.clearCurrentExecutionLine();
+ this._sourcesView.setExecutionLine(uiLocation);
+ if (this._skipExecutionLineRevealing)
+ return;
+ this._skipExecutionLineRevealing = true;
+ this._sourcesView.showSourceLocation(uiLocation.uiSourceCode, uiLocation.lineNumber, 0, undefined, true);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _callFrameSelected: function(event)
+ {
+ var callFrame = /** @type {?WebInspector.DebuggerModel.CallFrame} */ (event.data);
+
+ if (!callFrame || callFrame.target() !== WebInspector.context.flavor(WebInspector.Target))
+ return;
+
+ this._selectCallFrame(callFrame);
+ },
+
+ /**
+ * @param {!WebInspector.DebuggerModel.CallFrame} callFrame
+ */
+ _selectCallFrame: function(callFrame)
+ {
+ this.sidebarPanes.scopechain.update(callFrame);
+ this.sidebarPanes.watchExpressions.refreshExpressions();
+ this.sidebarPanes.callstack.setSelectedCallFrame(callFrame);
+ callFrame.createLiveLocation(this._executionLineChanged.bind(this));
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _sourceSelected: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.uiSourceCode);
+ this._sourcesView.showSourceLocation(uiSourceCode, undefined, undefined, !event.data.focusSource)
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _sourceRenamed: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
+ this._sourcesView.sourceRenamed(uiSourceCode);
+ },
+
+ _pauseOnExceptionEnabledChanged: function()
+ {
+ var enabled = WebInspector.settings.pauseOnExceptionEnabled.get();
+ this._pauseOnExceptionButton.toggled = enabled;
+ this._pauseOnExceptionButton.title = WebInspector.UIString(enabled ? "Don't pause on exceptions." : "Pause on exceptions.");
+ this._debugToolbarDrawer.classList.toggle("expanded", enabled);
+ },
+
+ _updateDebuggerButtons: function()
+ {
+ var currentTarget = WebInspector.context.flavor(WebInspector.Target);
+ if (!currentTarget)
+ return;
+
+ if (this._paused) {
+ this._updateButtonTitle(this._pauseButton, WebInspector.UIString("Resume script execution (%s)."))
+ this._pauseButton.state = true;
+ this._pauseButton.setLongClickOptionsEnabled((function() { return [ this._longResumeButton ] }).bind(this));
+
+ this._pauseButton.setEnabled(true);
+ this._stepOverButton.setEnabled(true);
+ this._stepIntoButton.setEnabled(true);
+ this._stepOutButton.setEnabled(true);
+ } else {
+ this._updateButtonTitle(this._pauseButton, WebInspector.UIString("Pause script execution (%s)."))
+ this._pauseButton.state = false;
+ this._pauseButton.setLongClickOptionsEnabled(null);
+
+ this._pauseButton.setEnabled(!currentTarget.debuggerModel.isPausing());
+ this._stepOverButton.setEnabled(false);
+ this._stepIntoButton.setEnabled(false);
+ this._stepOutButton.setEnabled(false);
+ }
+ },
+
+ _clearInterface: function()
+ {
+ this.sidebarPanes.callstack.update(null);
+ this.sidebarPanes.scopechain.update(null);
+ this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight();
+ WebInspector.domBreakpointsSidebarPane.clearBreakpointHighlight();
+ this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight();
+ this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight();
+
+ this._sourcesView.clearCurrentExecutionLine();
+ this._updateDebuggerButtons();
+ },
+
+ _togglePauseOnExceptions: function()
+ {
+ WebInspector.settings.pauseOnExceptionEnabled.set(!this._pauseOnExceptionButton.toggled);
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _runSnippet: function()
+ {
+ var uiSourceCode = this._sourcesView.currentUISourceCode();
+ if (uiSourceCode.project().type() !== WebInspector.projectTypes.Snippets)
+ return false;
+
+ var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
+ if (!currentExecutionContext)
+ return false;
+
+ WebInspector.scriptSnippetModel.evaluateScriptSnippet(currentExecutionContext, uiSourceCode);
+ return true;
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _editorSelected: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
+ this._editorChanged(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _editorClosed: function(event)
+ {
+ var wasSelected = /** @type {boolean} */ (event.data.wasSelected);
+ if (wasSelected)
+ this._editorChanged(null);
+ },
+
+ /**
+ * @param {?WebInspector.UISourceCode} uiSourceCode
+ */
+ _editorChanged: function(uiSourceCode)
+ {
+ var isSnippet = uiSourceCode && uiSourceCode.project().type() === WebInspector.projectTypes.Snippets;
+ this._runSnippetButton.element.classList.toggle("hidden", !isSnippet);
+ },
+
+ /**
+ * @return {boolean}
+ */
+ togglePause: function()
+ {
+ var target = WebInspector.context.flavor(WebInspector.Target);
+ if (!target)
+ return true;
+
+ if (this._paused) {
+ delete this._skipExecutionLineRevealing;
+ this._paused = false;
+ target.debuggerModel.resume();
+ } else {
+ // Make sure pauses didn't stick skipped.
+ target.debuggerModel.pause();
+ }
+
+ this._clearInterface();
+ return true;
+ },
+
+ /**
+ * @return {?WebInspector.DebuggerModel}
+ */
+ _prepareToResume: function()
+ {
+ if (!this._paused)
+ return null;
+
+ delete this._skipExecutionLineRevealing;
+ this._paused = false;
+
+ this._clearInterface();
+ var target = WebInspector.context.flavor(WebInspector.Target);
+ return target ? target.debuggerModel : null;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _longResume: function()
+ {
+ var debuggerModel = this._prepareToResume();
+ if (!debuggerModel)
+ return true;
+
+ debuggerModel.skipAllPausesUntilReloadOrTimeout(500);
+ debuggerModel.resume();
+ return true;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _stepOverClicked: function()
+ {
+ var debuggerModel = this._prepareToResume();
+ if (!debuggerModel)
+ return true;
+
+ debuggerModel.stepOver();
+ return true;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _stepIntoClicked: function()
+ {
+ var debuggerModel = this._prepareToResume();
+ if (!debuggerModel)
+ return true;
+
+ debuggerModel.stepInto();
+ return true;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _stepOutClicked: function()
+ {
+ var debuggerModel = this._prepareToResume();
+ if (!debuggerModel)
+ return true;
+
+ debuggerModel.stepOut();
+ return true;
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _callFrameSelectedInSidebar: function(event)
+ {
+ var callFrame = /** @type {!WebInspector.DebuggerModel.CallFrame} */ (event.data);
+ delete this._skipExecutionLineRevealing;
+ callFrame.target().debuggerModel.setSelectedCallFrame(callFrame);
+ },
+
+ _callFrameRestartedInSidebar: function()
+ {
+ delete this._skipExecutionLineRevealing;
+ },
+
+ /**
+ * @param {!WebInspector.DebuggerModel.Location} rawLocation
+ */
+ continueToLocation: function(rawLocation)
+ {
+ if (!this._prepareToResume())
+ return;
+
+ rawLocation.continueToLocation();
+ },
+
+ _toggleBreakpointsClicked: function(event)
+ {
+ WebInspector.debuggerModel.setBreakpointsActive(!WebInspector.debuggerModel.breakpointsActive());
+ },
+
+ _breakpointsActiveStateChanged: function(event)
+ {
+ var active = event.data;
+ this._toggleBreakpointsButton.toggled = !active;
+ this.sidebarPanes.jsBreakpoints.listElement.classList.toggle("breakpoints-list-deactivated", !active);
+ this._sourcesView.toggleBreakpointsActiveState(active);
+ if (active)
+ this._toggleBreakpointsButton.title = WebInspector.UIString("Deactivate breakpoints.");
+ else
+ this._toggleBreakpointsButton.title = WebInspector.UIString("Activate breakpoints.");
+ },
+
+ _createDebugToolbar: function()
+ {
+ var debugToolbar = document.createElement("div");
+ debugToolbar.className = "scripts-debug-toolbar";
+
+ var title, handler;
+ var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta;
+
+ // Run snippet.
+ title = WebInspector.UIString("Run snippet (%s).");
+ handler = this._runSnippet.bind(this);
+ this._runSnippetButton = this._createButtonAndRegisterShortcuts("scripts-run-snippet", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.RunSnippet);
+ debugToolbar.appendChild(this._runSnippetButton.element);
+ this._runSnippetButton.element.classList.add("hidden");
+
+ // Continue.
+ handler = function() { return WebInspector.actionRegistry.execute("debugger.toggle-pause"); };
+ this._pauseButton = this._createButtonAndRegisterShortcuts("scripts-pause", "", handler, []);
+ debugToolbar.appendChild(this._pauseButton.element);
+
+ // Long resume.
+ title = WebInspector.UIString("Resume with all pauses blocked for 500 ms");
+ this._longResumeButton = new WebInspector.StatusBarButton(title, "scripts-long-resume");
+ this._longResumeButton.addEventListener("click", this._longResume.bind(this), this);
+
+ // Step over.
+ title = WebInspector.UIString("Step over next function call (%s).");
+ handler = this._stepOverClicked.bind(this);
+ this._stepOverButton = this._createButtonAndRegisterShortcuts("scripts-step-over", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepOver);
+ debugToolbar.appendChild(this._stepOverButton.element);
+
+ // Step into.
+ title = WebInspector.UIString("Step into next function call (%s).");
+ handler = this._stepIntoClicked.bind(this);
+ this._stepIntoButton = this._createButtonAndRegisterShortcuts("scripts-step-into", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepInto);
+ debugToolbar.appendChild(this._stepIntoButton.element);
+
+ // Step out.
+ title = WebInspector.UIString("Step out of current function (%s).");
+ handler = this._stepOutClicked.bind(this);
+ this._stepOutButton = this._createButtonAndRegisterShortcuts("scripts-step-out", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepOut);
+ debugToolbar.appendChild(this._stepOutButton.element);
+
+ // Toggle Breakpoints
+ this._toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate breakpoints."), "scripts-toggle-breakpoints");
+ this._toggleBreakpointsButton.toggled = false;
+ this._toggleBreakpointsButton.addEventListener("click", this._toggleBreakpointsClicked, this);
+ debugToolbar.appendChild(this._toggleBreakpointsButton.element);
+
+ // Pause on Exception
+ this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item");
+ this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions, this);
+ debugToolbar.appendChild(this._pauseOnExceptionButton.element);
+
+ return debugToolbar;
+ },
+
+ _createDebugToolbarDrawer: function()
+ {
+ var debugToolbarDrawer = document.createElement("div");
+ debugToolbarDrawer.className = "scripts-debug-toolbar-drawer";
+
+ var label = WebInspector.UIString("Pause On Caught Exceptions");
+ var setting = WebInspector.settings.pauseOnCaughtException;
+ debugToolbarDrawer.appendChild(WebInspector.SettingsUI.createSettingCheckbox(label, setting, true));
+
+ return debugToolbarDrawer;
+ },
+
+ /**
+ * @param {!WebInspector.StatusBarButton} button
+ * @param {string} buttonTitle
+ */
+ _updateButtonTitle: function(button, buttonTitle)
+ {
+ var hasShortcuts = button.shortcuts && button.shortcuts.length;
+ if (hasShortcuts)
+ button.title = String.vsprintf(buttonTitle, [button.shortcuts[0].name]);
+ else
+ button.title = buttonTitle;
+ },
+
+ /**
+ * @param {string} buttonId
+ * @param {string} buttonTitle
+ * @param {function(?Event=):boolean} handler
+ * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} shortcuts
+ * @return {!WebInspector.StatusBarButton}
+ */
+ _createButtonAndRegisterShortcuts: function(buttonId, buttonTitle, handler, shortcuts)
+ {
+ var button = new WebInspector.StatusBarButton(buttonTitle, buttonId);
+ button.element.addEventListener("click", handler, false);
+ button.shortcuts = shortcuts;
+ this._updateButtonTitle(button, buttonTitle);
+ this.registerShortcuts(shortcuts, handler);
+ return button;
+ },
+
+ addToWatch: function(expression)
+ {
+ this.sidebarPanes.watchExpressions.addExpression(expression);
+ },
+
+ _installDebuggerSidebarController: function()
+ {
+ this._toggleNavigatorSidebarButton = this.editorView.createShowHideSidebarButton("navigator", "scripts-navigator-show-hide-button");
+ this.editorView.mainElement().appendChild(this._toggleNavigatorSidebarButton.element);
+
+ this._toggleDebuggerSidebarButton = this._splitView.createShowHideSidebarButton("debugger", "scripts-debugger-show-hide-button");
+
+ this._splitView.mainElement().appendChild(this._toggleDebuggerSidebarButton.element);
+ this._splitView.mainElement().appendChild(this._debugSidebarResizeWidgetElement);
+ },
+
+ _updateDebugSidebarResizeWidget: function()
+ {
+ this._debugSidebarResizeWidgetElement.classList.toggle("hidden", this._splitView.showMode() !== WebInspector.SplitView.ShowMode.Both);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _showLocalHistory: function(uiSourceCode)
+ {
+ WebInspector.RevisionHistoryView.showHistory(uiSourceCode);
+ },
+
+ /**
+ * @param {!Event} event
+ * @param {!WebInspector.ContextMenu} contextMenu
+ * @param {!Object} target
+ */
+ appendApplicableItems: function(event, contextMenu, target)
+ {
+ this._appendUISourceCodeItems(event, contextMenu, target);
+ this._appendRemoteObjectItems(contextMenu, target);
+ },
+
+ _suggestReload: function()
+ {
+ if (window.confirm(WebInspector.UIString("It is recommended to restart inspector after making these changes. Would you like to restart it?")))
+ WebInspector.reload();
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _mapFileSystemToNetwork: function(uiSourceCode)
+ {
+ WebInspector.SelectUISourceCodeForProjectTypesDialog.show(uiSourceCode.name(), [WebInspector.projectTypes.Network, WebInspector.projectTypes.ContentScripts], mapFileSystemToNetwork.bind(this), this.editorView.mainElement())
+
+ /**
+ * @param {!WebInspector.UISourceCode} networkUISourceCode
+ * @this {WebInspector.SourcesPanel}
+ */
+ function mapFileSystemToNetwork(networkUISourceCode)
+ {
+ this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceBinding);
+ this._suggestReload();
+ }
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _removeNetworkMapping: function(uiSourceCode)
+ {
+ if (confirm(WebInspector.UIString("Are you sure you want to remove network mapping?"))) {
+ this._workspace.removeMapping(uiSourceCode);
+ this._suggestReload();
+ }
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} networkUISourceCode
+ */
+ _mapNetworkToFileSystem: function(networkUISourceCode)
+ {
+ WebInspector.SelectUISourceCodeForProjectTypesDialog.show(networkUISourceCode.name(), [WebInspector.projectTypes.FileSystem], mapNetworkToFileSystem.bind(this), this.editorView.mainElement())
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @this {WebInspector.SourcesPanel}
+ */
+ function mapNetworkToFileSystem(uiSourceCode)
+ {
+ this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceBinding);
+ this._suggestReload();
+ }
+ },
+
+ /**
+ * @param {!WebInspector.ContextMenu} contextMenu
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _appendUISourceCodeMappingItems: function(contextMenu, uiSourceCode)
+ {
+ if (uiSourceCode.project().type() === WebInspector.projectTypes.FileSystem) {
+ var hasMappings = !!uiSourceCode.url;
+ if (!hasMappings)
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Map to network resource\u2026" : "Map to Network Resource\u2026"), this._mapFileSystemToNetwork.bind(this, uiSourceCode));
+ else
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove network mapping" : "Remove Network Mapping"), this._removeNetworkMapping.bind(this, uiSourceCode));
+ }
+
+ /**
+ * @param {!WebInspector.Project} project
+ */
+ function filterProject(project)
+ {
+ return project.type() === WebInspector.projectTypes.FileSystem;
+ }
+
+ if (uiSourceCode.project().type() === WebInspector.projectTypes.Network || uiSourceCode.project().type() === WebInspector.projectTypes.ContentScripts) {
+ if (!this._workspace.projects().filter(filterProject).length)
+ return;
+ if (this._workspace.uiSourceCodeForURL(uiSourceCode.url) === uiSourceCode)
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Map to file system resource\u2026" : "Map to File System Resource\u2026"), this._mapNetworkToFileSystem.bind(this, uiSourceCode));
+ }
+ },
+
+ /**
+ * @param {?Event} event
+ * @param {!WebInspector.ContextMenu} contextMenu
+ * @param {!Object} target
+ */
+ _appendUISourceCodeItems: function(event, contextMenu, target)
+ {
+ if (!(target instanceof WebInspector.UISourceCode))
+ return;
+
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (target);
+ var project = uiSourceCode.project();
+ if (project.type() !== WebInspector.projectTypes.FileSystem)
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Local modifications\u2026" : "Local Modifications\u2026"), this._showLocalHistory.bind(this, uiSourceCode));
+ this._appendUISourceCodeMappingItems(contextMenu, uiSourceCode);
+
+ if (!event.target.isSelfOrDescendant(this.editorView.sidebarElement())) {
+ contextMenu.appendSeparator();
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Reveal in navigator" : "Reveal in Navigator"), this._handleContextMenuReveal.bind(this, uiSourceCode));
+ }
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _handleContextMenuReveal: function(uiSourceCode)
+ {
+ this.editorView.showBoth();
+ this._revealInNavigator(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.ContextMenu} contextMenu
+ * @param {!Object} target
+ */
+ _appendRemoteObjectItems: function(contextMenu, target)
+ {
+ if (!(target instanceof WebInspector.RemoteObject))
+ return;
+ var remoteObject = /** @type {!WebInspector.RemoteObject} */ (target);
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Store as global variable" : "Store as Global Variable"), this._saveToTempVariable.bind(this, remoteObject));
+ if (remoteObject.type === "function")
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Show function definition" : "Show Function Definition"), this._showFunctionDefinition.bind(this, remoteObject));
+ },
+
+ /**
+ * @param {!WebInspector.RemoteObject} remoteObject
+ */
+ _saveToTempVariable: function(remoteObject)
+ {
+ var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
+ if (!currentExecutionContext)
+ return;
+
+ currentExecutionContext.evaluate("window", "", false, true, false, false, didGetGlobalObject.bind(null, currentExecutionContext.target()));
+ /**
+ * @param {!WebInspector.Target} target
+ * @param {?WebInspector.RemoteObject} global
+ * @param {boolean=} wasThrown
+ */
+ function didGetGlobalObject(target, global, wasThrown)
+ {
+ /**
+ * @suppressReceiverCheck
+ * @this {Window}
+ */
+ function remoteFunction(value)
+ {
+ var prefix = "temp";
+ var index = 1;
+ while ((prefix + index) in this)
+ ++index;
+ var name = prefix + index;
+ this[name] = value;
+ return name;
+ }
+
+ if (wasThrown || !global)
+ failedToSave(target, global);
+ else
+ global.callFunction(remoteFunction, [WebInspector.RemoteObject.toCallArgument(remoteObject)], didSave.bind(null, global));
+ }
+
+ /**
+ * @param {!WebInspector.RemoteObject} global
+ * @param {?WebInspector.RemoteObject} result
+ * @param {boolean=} wasThrown
+ */
+ function didSave(global, result, wasThrown)
+ {
+ var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
+ global.release();
+ if (!currentExecutionContext || wasThrown || !result || result.type !== "string")
+ failedToSave(global.target(), result);
+ else
+ WebInspector.ConsoleModel.evaluateCommandInConsole(currentExecutionContext, result.value);
+ }
+
+ /**
+ * @param {!WebInspector.Target} target
+ * @param {?WebInspector.RemoteObject} result
+ */
+ function failedToSave(target, result)
+ {
+ var message = WebInspector.UIString("Failed to save to temp variable.");
+ if (result) {
+ message += " " + result.description;
+ result.release();
+ }
+ target.consoleModel.showErrorMessage(message);
+ }
+ },
+
+ /**
+ * @param {!WebInspector.RemoteObject} remoteObject
+ */
+ _showFunctionDefinition: function(remoteObject)
+ {
+ var target = remoteObject.target();
+
+ /**
+ * @param {?Protocol.Error} error
+ * @param {!DebuggerAgent.FunctionDetails} response
+ * @this {WebInspector.SourcesPanel}
+ */
+ function didGetFunctionDetails(error, response)
+ {
+ if (error) {
+ console.error(error);
+ return;
+ }
+
+ var uiLocation = target.debuggerModel.rawLocationToUILocation(response.location);
+ if (!uiLocation)
+ return;
+
+ this.showUILocation(uiLocation, true);
+ }
+ target.debuggerAgent().getFunctionDetails(remoteObject.objectId, didGetFunctionDetails.bind(this));
+ },
+
+ showGoToSourceDialog: function()
+ {
+ this._sourcesView.showOpenResourceDialog();
+ },
+
+ _dockSideChanged: function()
+ {
+ var vertically = WebInspector.dockController.isVertical() && WebInspector.settings.splitVerticallyWhenDockedToRight.get();
+ this._splitVertically(vertically);
+ },
+
+ /**
+ * @param {boolean} vertically
+ */
+ _splitVertically: function(vertically)
+ {
+ if (this.sidebarPaneView && vertically === !this._splitView.isVertical())
+ return;
+
+ if (this.sidebarPaneView)
+ this.sidebarPaneView.detach();
+
+ this._splitView.setVertical(!vertically);
+
+ if (!vertically)
+ this._splitView.uninstallResizer(this._sourcesView.statusBarContainerElement());
+ else
+ this._splitView.installResizer(this._sourcesView.statusBarContainerElement());
+
+ // Create vertical box with stack.
+ var vbox = new WebInspector.VBox();
+ vbox.element.appendChild(this._debugToolbarDrawer);
+ vbox.element.appendChild(this.debugToolbar);
+ vbox.element.appendChild(this._targetsToolbar.element);
+ vbox.setMinimumAndPreferredSizes(25, 25, WebInspector.SourcesPanel.minToolbarWidth, 100);
+ var sidebarPaneStack = new WebInspector.SidebarPaneStack();
+ sidebarPaneStack.element.classList.add("flex-auto");
+ sidebarPaneStack.show(vbox.element);
+
+ if (!vertically) {
+ // Populate the only stack.
+ for (var pane in this.sidebarPanes)
+ sidebarPaneStack.addPane(this.sidebarPanes[pane]);
+ this._extensionSidebarPanesContainer = sidebarPaneStack;
+
+ this.sidebarPaneView = vbox;
+ } else {
+ var splitView = new WebInspector.SplitView(true, true, "sourcesPanelDebuggerSidebarSplitViewState", 0.5);
+ vbox.show(splitView.mainElement());
+
+ // Populate the left stack.
+ sidebarPaneStack.addPane(this.sidebarPanes.callstack);
+ sidebarPaneStack.addPane(this.sidebarPanes.jsBreakpoints);
+ sidebarPaneStack.addPane(this.sidebarPanes.domBreakpoints);
+ sidebarPaneStack.addPane(this.sidebarPanes.xhrBreakpoints);
+ sidebarPaneStack.addPane(this.sidebarPanes.eventListenerBreakpoints);
+ if (this.sidebarPanes.workerList)
+ sidebarPaneStack.addPane(this.sidebarPanes.workerList);
+
+ var tabbedPane = new WebInspector.SidebarTabbedPane();
+ tabbedPane.show(splitView.sidebarElement());
+ tabbedPane.addPane(this.sidebarPanes.scopechain);
+ tabbedPane.addPane(this.sidebarPanes.watchExpressions);
+ this._extensionSidebarPanesContainer = tabbedPane;
+
+ this.sidebarPaneView = splitView;
+ }
+ for (var i = 0; i < this._extensionSidebarPanes.length; ++i)
+ this._extensionSidebarPanesContainer.addPane(this._extensionSidebarPanes[i]);
+
+ this.sidebarPaneView.show(this._splitView.sidebarElement());
+
+ this.sidebarPanes.scopechain.expand();
+ this.sidebarPanes.jsBreakpoints.expand();
+ this.sidebarPanes.callstack.expand();
+
+ if (WebInspector.settings.watchExpressions.get().length > 0)
+ this.sidebarPanes.watchExpressions.expand();
+ },
+
+ /**
+ * @param {string} id
+ * @param {!WebInspector.SidebarPane} pane
+ */
+ addExtensionSidebarPane: function(id, pane)
+ {
+ this._extensionSidebarPanes.push(pane);
+ this._extensionSidebarPanesContainer.addPane(pane);
+ this.setHideOnDetach();
+ },
+
+ /**
+ * @return {!WebInspector.SourcesView}
+ */
+ sourcesView: function()
+ {
+ return this._sourcesView;
+ },
+
+ __proto__: WebInspector.Panel.prototype
+}
+
+/**
+ * @constructor
+ * @param {!Element} element
+ */
+WebInspector.UpgradeFileSystemDropTarget = function(element)
+{
+ element.addEventListener("dragenter", this._onDragEnter.bind(this), true);
+ element.addEventListener("dragover", this._onDragOver.bind(this), true);
+ this._element = element;
+}
+
+WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType = "Files";
+
+WebInspector.UpgradeFileSystemDropTarget.prototype = {
+ _onDragEnter: function (event)
+ {
+ if (event.dataTransfer.types.indexOf(WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType) === -1)
+ return;
+ event.consume(true);
+ },
+
+ _onDragOver: function (event)
+ {
+ if (event.dataTransfer.types.indexOf(WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType) === -1)
+ return;
+ event.dataTransfer.dropEffect = "copy";
+ event.consume(true);
+ if (this._dragMaskElement)
+ return;
+ this._dragMaskElement = this._element.createChild("div", "fill drag-mask");
+ this._dragMaskElement.createChild("div", "fill drag-mask-inner").textContent = WebInspector.UIString("Drop workspace folder here");
+ this._dragMaskElement.addEventListener("drop", this._onDrop.bind(this), true);
+ this._dragMaskElement.addEventListener("dragleave", this._onDragLeave.bind(this), true);
+ },
+
+ _onDrop: function (event)
+ {
+ event.consume(true);
+ this._removeMask();
+ var items = /** @type {!Array.<!DataTransferItem>} */ (event.dataTransfer.items);
+ if (!items.length)
+ return;
+ var entry = items[0].webkitGetAsEntry();
+ if (!entry.isDirectory)
+ return;
+ InspectorFrontendHost.upgradeDraggedFileSystemPermissions(entry.filesystem);
+ },
+
+ _onDragLeave: function (event)
+ {
+ event.consume(true);
+ this._removeMask();
+ },
+
+ _removeMask: function ()
+ {
+ this._dragMaskElement.remove();
+ delete this._dragMaskElement;
+ }
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.DrawerEditor}
+ */
+WebInspector.SourcesPanel.DrawerEditor = function()
+{
+ this._panel = WebInspector.inspectorView.panel("sources");
+}
+
+WebInspector.SourcesPanel.DrawerEditor.prototype = {
+ /**
+ * @return {!WebInspector.View}
+ */
+ view: function()
+ {
+ return this._panel._drawerEditorView;
+ },
+
+ installedIntoDrawer: function()
+ {
+ if (this._panel.isShowing())
+ this._panelWasShown();
+ else
+ this._panelWillHide();
+ },
+
+ _panelWasShown: function()
+ {
+ WebInspector.inspectorView.setDrawerEditorAvailable(false);
+ WebInspector.inspectorView.hideDrawerEditor();
+ },
+
+ _panelWillHide: function()
+ {
+ WebInspector.inspectorView.setDrawerEditorAvailable(true);
+ if (WebInspector.inspectorView.isDrawerEditorShown())
+ WebInspector.inspectorView.showDrawerEditor();
+ },
+
+ _show: function()
+ {
+ WebInspector.inspectorView.showDrawerEditor();
+ },
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.VBox}
+ */
+WebInspector.SourcesPanel.DrawerEditorView = function()
+{
+ WebInspector.VBox.call(this);
+ this.element.id = "drawer-editor-view";
+}
+
+WebInspector.SourcesPanel.DrawerEditorView.prototype = {
+ __proto__: WebInspector.VBox.prototype
+}
+
+
+/**
+ * @constructor
+ * @implements {WebInspector.ContextMenu.Provider}
+ */
+WebInspector.SourcesPanel.ContextMenuProvider = function()
+{
+}
+
+WebInspector.SourcesPanel.ContextMenuProvider.prototype = {
+ /**
+ * @param {!Event} event
+ * @param {!WebInspector.ContextMenu} contextMenu
+ * @param {!Object} target
+ */
+ appendApplicableItems: function(event, contextMenu, target)
+ {
+ WebInspector.inspectorView.panel("sources").appendApplicableItems(event, contextMenu, target);
+ }
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.Revealer}
+ */
+WebInspector.SourcesPanel.UILocationRevealer = function()
+{
+}
+
+WebInspector.SourcesPanel.UILocationRevealer.prototype = {
+ /**
+ * @param {!Object} uiLocation
+ */
+ reveal: function(uiLocation)
+ {
+ if (uiLocation instanceof WebInspector.UILocation)
+ /** @type {!WebInspector.SourcesPanel} */ (WebInspector.inspectorView.panel("sources")).showUILocation(uiLocation);
+ }
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.Revealer}
+ */
+WebInspector.SourcesPanel.UISourceCodeRevealer = function()
+{
+}
+
+WebInspector.SourcesPanel.UISourceCodeRevealer.prototype = {
+ /**
+ * @param {!Object} uiSourceCode
+ */
+ reveal: function(uiSourceCode)
+ {
+ if (uiSourceCode instanceof WebInspector.UISourceCode)
+ /** @type {!WebInspector.SourcesPanel} */ (WebInspector.inspectorView.panel("sources")).showUISourceCode(uiSourceCode);
+ }
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.ActionDelegate}
+ */
+WebInspector.SourcesPanel.ShowGoToSourceDialogActionDelegate = function() {}
+
+WebInspector.SourcesPanel.ShowGoToSourceDialogActionDelegate.prototype = {
+ /**
+ * @return {boolean}
+ */
+ handleAction: function()
+ {
+ /** @type {!WebInspector.SourcesPanel} */ (WebInspector.inspectorView.showPanel("sources")).showGoToSourceDialog();
+ return true;
+ }
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.UISettingDelegate}
+ */
+WebInspector.SourcesPanel.SkipStackFramePatternSettingDelegate = function()
+{
+ WebInspector.UISettingDelegate.call(this);
+}
+
+WebInspector.SourcesPanel.SkipStackFramePatternSettingDelegate.prototype = {
+ /**
+ * @override
+ * @return {!Element}
+ */
+ settingElement: function()
+ {
+ return WebInspector.SettingsUI.createSettingInputField(WebInspector.UIString("Pattern"), WebInspector.settings.skipStackFramesPattern, false, 1000, "100px", WebInspector.SettingsUI.regexValidator);
+ },
+
+ __proto__: WebInspector.UISettingDelegate.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.UISettingDelegate}
+ */
+WebInspector.SourcesPanel.DisableJavaScriptSettingDelegate = function()
+{
+ WebInspector.UISettingDelegate.call(this);
+}
+
+WebInspector.SourcesPanel.DisableJavaScriptSettingDelegate.prototype = {
+ /**
+ * @override
+ * @return {!Element}
+ */
+ settingElement: function()
+ {
+ var disableJSElement = WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Disable JavaScript"), WebInspector.settings.javaScriptDisabled);
+ this._disableJSCheckbox = disableJSElement.getElementsByTagName("input")[0];
+ WebInspector.settings.javaScriptDisabled.addChangeListener(this._settingChanged, this);
+ var disableJSInfoParent = this._disableJSCheckbox.parentElement.createChild("span", "monospace");
+ this._disableJSInfo = disableJSInfoParent.createChild("span", "object-info-state-note hidden");
+ this._disableJSInfo.title = WebInspector.UIString("JavaScript is blocked on the inspected page (may be disabled in browser settings).");
+
+ WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._updateScriptDisabledCheckbox, this);
+ this._updateScriptDisabledCheckbox();
+ return disableJSElement;
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _settingChanged: function(event)
+ {
+ PageAgent.setScriptExecutionDisabled(event.data, this._updateScriptDisabledCheckbox.bind(this));
+ },
+
+ _updateScriptDisabledCheckbox: function()
+ {
+ PageAgent.getScriptExecutionStatus(executionStatusCallback.bind(this));
+
+ /**
+ * @param {?Protocol.Error} error
+ * @param {string} status
+ * @this {WebInspector.SourcesPanel.DisableJavaScriptSettingDelegate}
+ */
+ function executionStatusCallback(error, status)
+ {
+ if (error || !status)
+ return;
+
+ var forbidden = (status === "forbidden");
+ var disabled = forbidden || (status === "disabled");
+
+ this._disableJSInfo.classList.toggle("hidden", !forbidden);
+ this._disableJSCheckbox.checked = disabled;
+ this._disableJSCheckbox.disabled = forbidden;
+ }
+ },
+
+ __proto__: WebInspector.UISettingDelegate.prototype
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.ActionDelegate}
+ */
+WebInspector.SourcesPanel.TogglePauseActionDelegate = function()
+{
+}
+
+WebInspector.SourcesPanel.TogglePauseActionDelegate.prototype = {
+ /**
+ * @return {boolean}
+ */
+ handleAction: function()
+ {
+ /** @type {!WebInspector.SourcesPanel} */ (WebInspector.inspectorView.showPanel("sources")).togglePause();
+ return true;
+ }
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js
new file mode 100644
index 00000000000..12257d2b3d0
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js
@@ -0,0 +1,708 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @constructor
+ * @implements {WebInspector.TabbedEditorContainerDelegate}
+ * @implements {WebInspector.Searchable}
+ * @implements {WebInspector.Replaceable}
+ * @extends {WebInspector.VBox}
+ * @param {!WebInspector.Workspace} workspace
+ * @param {!WebInspector.SourcesPanel} sourcesPanel
+ */
+WebInspector.SourcesView = function(workspace, sourcesPanel)
+{
+ WebInspector.VBox.call(this);
+ this.registerRequiredCSS("sourcesView.css");
+ this.element.id = "sources-panel-sources-view";
+ this.setMinimumAndPreferredSizes(50, 25, 150, 100);
+
+ this._workspace = workspace;
+ this._sourcesPanel = sourcesPanel;
+
+ this._searchableView = new WebInspector.SearchableView(this);
+ this._searchableView.setMinimalSearchQuerySize(0);
+ this._searchableView.show(this.element);
+
+ /** @type {!Map.<!WebInspector.UISourceCode, !WebInspector.UISourceCodeFrame>} */
+ this._sourceFramesByUISourceCode = new Map();
+
+ var tabbedEditorPlaceholderText = WebInspector.isMac() ? WebInspector.UIString("Hit Cmd+P to open a file") : WebInspector.UIString("Hit Ctrl+P to open a file");
+ this._editorContainer = new WebInspector.TabbedEditorContainer(this, "previouslyViewedFiles", tabbedEditorPlaceholderText);
+ this._editorContainer.show(this._searchableView.element);
+ this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorSelected, this._editorSelected, this);
+ this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorClosed, this._editorClosed, this);
+
+ this._historyManager = new WebInspector.EditingLocationHistoryManager(this, this.currentSourceFrame.bind(this));
+
+ this._scriptViewStatusBarItemsContainer = document.createElement("div");
+ this._scriptViewStatusBarItemsContainer.className = "inline-block";
+
+ this._scriptViewStatusBarTextContainer = document.createElement("div");
+ this._scriptViewStatusBarTextContainer.className = "hbox";
+
+ this._statusBarContainerElement = this.element.createChild("div", "sources-status-bar");
+
+ /**
+ * @this {WebInspector.SourcesView}
+ * @param {!WebInspector.SourcesView.EditorAction} EditorAction
+ */
+ function appendButtonForExtension(EditorAction)
+ {
+ this._statusBarContainerElement.appendChild(EditorAction.button(this));
+ }
+ var editorActions = /** @type {!Array.<!WebInspector.SourcesView.EditorAction>} */ (WebInspector.moduleManager.instances(WebInspector.SourcesView.EditorAction));
+ editorActions.forEach(appendButtonForExtension.bind(this));
+
+ this._statusBarContainerElement.appendChild(this._scriptViewStatusBarItemsContainer);
+ this._statusBarContainerElement.appendChild(this._scriptViewStatusBarTextContainer);
+
+ WebInspector.startBatchUpdate();
+ this._workspace.uiSourceCodes().forEach(this._addUISourceCode.bind(this));
+ WebInspector.endBatchUpdate();
+
+ this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
+ this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this);
+ this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectRemoved, this._projectRemoved.bind(this), this);
+
+ function handleBeforeUnload(event)
+ {
+ if (event.returnValue)
+ return;
+ var unsavedSourceCodes = WebInspector.workspace.unsavedSourceCodes();
+ if (!unsavedSourceCodes.length)
+ return;
+
+ event.returnValue = WebInspector.UIString("DevTools have unsaved changes that will be permanently lost.");
+ WebInspector.inspectorView.showPanel("sources");
+ for (var i = 0; i < unsavedSourceCodes.length; ++i)
+ WebInspector.Revealer.reveal(unsavedSourceCodes[i]);
+ }
+ window.addEventListener("beforeunload", handleBeforeUnload, true);
+
+ this._shortcuts = {};
+ this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false);
+}
+
+WebInspector.SourcesView.Events = {
+ EditorClosed: "EditorClosed",
+ EditorSelected: "EditorSelected",
+}
+
+WebInspector.SourcesView.prototype = {
+ /**
+ * @param {function(!Array.<!WebInspector.KeyboardShortcut.Descriptor>, function(?Event=):boolean)} registerShortcutDelegate
+ */
+ registerShortcuts: function(registerShortcutDelegate)
+ {
+ /**
+ * @this {WebInspector.SourcesView}
+ * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} shortcuts
+ * @param {function(?Event=):boolean} handler
+ */
+ function registerShortcut(shortcuts, handler)
+ {
+ registerShortcutDelegate(shortcuts, handler);
+ this._registerShortcuts(shortcuts, handler);
+ }
+
+ registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.JumpToPreviousLocation, this._onJumpToPreviousLocation.bind(this));
+ registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.JumpToNextLocation, this._onJumpToNextLocation.bind(this));
+ registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.CloseEditorTab, this._onCloseEditorTab.bind(this));
+ registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.GoToLine, this._showGoToLineDialog.bind(this));
+ registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.GoToMember, this._showOutlineDialog.bind(this));
+ registerShortcut.call(this, [WebInspector.KeyboardShortcut.makeDescriptor("o", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta | WebInspector.KeyboardShortcut.Modifiers.Shift)], this._showOutlineDialog.bind(this));
+ registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.ToggleBreakpoint, this._toggleBreakpoint.bind(this));
+ registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.Save, this._save.bind(this));
+ registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.SaveAll, this._saveAll.bind(this));
+ },
+
+ /**
+ * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} keys
+ * @param {function(?Event=):boolean} handler
+ */
+ _registerShortcuts: function(keys, handler)
+ {
+ for (var i = 0; i < keys.length; ++i)
+ this._shortcuts[keys[i].key] = handler;
+ },
+
+ _handleKeyDown: function(event)
+ {
+ var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
+ var handler = this._shortcuts[shortcutKey];
+ if (handler && handler())
+ event.consume(true);
+ },
+
+ /**
+ * @return {!Element}
+ */
+ statusBarContainerElement: function()
+ {
+ return this._statusBarContainerElement;
+ },
+
+ /**
+ * @return {!Element}
+ */
+ defaultFocusedElement: function()
+ {
+ return this._editorContainer.view.defaultFocusedElement();
+ },
+
+ /**
+ * @return {!WebInspector.SearchableView}
+ */
+ searchableView: function()
+ {
+ return this._searchableView;
+ },
+
+ /**
+ * @return {!WebInspector.View}
+ */
+ visibleView: function()
+ {
+ return this._editorContainer.visibleView;
+ },
+
+ /**
+ * @return {?WebInspector.SourceFrame}
+ */
+ currentSourceFrame: function()
+ {
+ var view = this.visibleView();
+ if (!(view instanceof WebInspector.SourceFrame))
+ return null;
+ return /** @type {!WebInspector.SourceFrame} */ (view);
+ },
+
+ /**
+ * @return {?WebInspector.UISourceCode}
+ */
+ currentUISourceCode: function()
+ {
+ return this._currentUISourceCode;
+ },
+
+ /**
+ * @param {?Event=} event
+ */
+ _onCloseEditorTab: function(event)
+ {
+ var uiSourceCode = this.currentUISourceCode();
+ if (!uiSourceCode)
+ return false;
+ this._editorContainer.closeFile(uiSourceCode);
+ return true;
+ },
+
+ /**
+ * @param {?Event=} event
+ */
+ _onJumpToPreviousLocation: function(event)
+ {
+ this._historyManager.rollback();
+ return true;
+ },
+
+ /**
+ * @param {?Event=} event
+ */
+ _onJumpToNextLocation: function(event)
+ {
+ this._historyManager.rollover();
+ return true;
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _uiSourceCodeAdded: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
+ this._addUISourceCode(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _addUISourceCode: function(uiSourceCode)
+ {
+ if (uiSourceCode.project().isServiceProject())
+ return;
+ this._editorContainer.addUISourceCode(uiSourceCode);
+ // Replace debugger script-based uiSourceCode with a network-based one.
+ var currentUISourceCode = this._currentUISourceCode;
+ if (currentUISourceCode && currentUISourceCode.project().isServiceProject() && currentUISourceCode !== uiSourceCode && currentUISourceCode.url === uiSourceCode.url) {
+ this._showFile(uiSourceCode);
+ this._editorContainer.removeUISourceCode(currentUISourceCode);
+ }
+ },
+
+ _uiSourceCodeRemoved: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
+ this._removeUISourceCodes([uiSourceCode]);
+ },
+
+ /**
+ * @param {!Array.<!WebInspector.UISourceCode>} uiSourceCodes
+ */
+ _removeUISourceCodes: function(uiSourceCodes)
+ {
+ this._editorContainer.removeUISourceCodes(uiSourceCodes);
+ for (var i = 0; i < uiSourceCodes.length; ++i) {
+ this._removeSourceFrame(uiSourceCodes[i]);
+ this._historyManager.removeHistoryForSourceCode(uiSourceCodes[i]);
+ }
+ },
+
+ _projectRemoved: function(event)
+ {
+ var project = event.data;
+ var uiSourceCodes = project.uiSourceCodes();
+ this._removeUISourceCodes(uiSourceCodes);
+ if (project.type() === WebInspector.projectTypes.Network)
+ this._editorContainer.reset();
+ },
+
+ _updateScriptViewStatusBarItems: function()
+ {
+ this._scriptViewStatusBarItemsContainer.removeChildren();
+ this._scriptViewStatusBarTextContainer.removeChildren();
+ var sourceFrame = this.currentSourceFrame();
+ if (!sourceFrame)
+ return;
+
+ var statusBarItems = sourceFrame.statusBarItems() || [];
+ for (var i = 0; i < statusBarItems.length; ++i)
+ this._scriptViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
+ var statusBarText = sourceFrame.statusBarText();
+ if (statusBarText)
+ this._scriptViewStatusBarTextContainer.appendChild(statusBarText);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {number=} lineNumber
+ * @param {number=} columnNumber
+ * @param {boolean=} omitFocus
+ * @param {boolean=} omitHighlight
+ */
+ showSourceLocation: function(uiSourceCode, lineNumber, columnNumber, omitFocus, omitHighlight)
+ {
+ this._historyManager.updateCurrentState();
+ var sourceFrame = this._showFile(uiSourceCode);
+ if (typeof lineNumber === "number")
+ sourceFrame.revealPosition(lineNumber, columnNumber, !omitHighlight);
+ this._historyManager.pushNewState();
+ if (!omitFocus)
+ sourceFrame.focus();
+ WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
+ action: WebInspector.UserMetrics.UserActionNames.OpenSourceLink,
+ url: uiSourceCode.originURL(),
+ lineNumber: lineNumber
+ });
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {!WebInspector.SourceFrame}
+ */
+ _showFile: function(uiSourceCode)
+ {
+ var sourceFrame = this._getOrCreateSourceFrame(uiSourceCode);
+ if (this._currentUISourceCode === uiSourceCode)
+ return sourceFrame;
+
+ this._currentUISourceCode = uiSourceCode;
+ this._editorContainer.showFile(uiSourceCode);
+ this._updateScriptViewStatusBarItems();
+ return sourceFrame;
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {!WebInspector.UISourceCodeFrame}
+ */
+ _createSourceFrame: function(uiSourceCode)
+ {
+ var sourceFrame;
+ switch (uiSourceCode.contentType()) {
+ case WebInspector.resourceTypes.Script:
+ sourceFrame = new WebInspector.JavaScriptSourceFrame(this._sourcesPanel, uiSourceCode);
+ break;
+ case WebInspector.resourceTypes.Document:
+ sourceFrame = new WebInspector.JavaScriptSourceFrame(this._sourcesPanel, uiSourceCode);
+ break;
+ case WebInspector.resourceTypes.Stylesheet:
+ sourceFrame = new WebInspector.CSSSourceFrame(uiSourceCode);
+ break;
+ default:
+ sourceFrame = new WebInspector.UISourceCodeFrame(uiSourceCode);
+ break;
+ }
+ sourceFrame.setHighlighterType(uiSourceCode.highlighterType());
+ this._sourceFramesByUISourceCode.put(uiSourceCode, sourceFrame);
+ this._historyManager.trackSourceFrameCursorJumps(sourceFrame);
+ return sourceFrame;
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {!WebInspector.UISourceCodeFrame}
+ */
+ _getOrCreateSourceFrame: function(uiSourceCode)
+ {
+ return this._sourceFramesByUISourceCode.get(uiSourceCode) || this._createSourceFrame(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.SourceFrame} sourceFrame
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {boolean}
+ */
+ _sourceFrameMatchesUISourceCode: function(sourceFrame, uiSourceCode)
+ {
+ switch (uiSourceCode.contentType()) {
+ case WebInspector.resourceTypes.Script:
+ case WebInspector.resourceTypes.Document:
+ return sourceFrame instanceof WebInspector.JavaScriptSourceFrame;
+ case WebInspector.resourceTypes.Stylesheet:
+ return sourceFrame instanceof WebInspector.CSSSourceFrame;
+ default:
+ return !(sourceFrame instanceof WebInspector.JavaScriptSourceFrame);
+ }
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _recreateSourceFrameIfNeeded: function(uiSourceCode)
+ {
+ var oldSourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode);
+ if (!oldSourceFrame)
+ return;
+ if (this._sourceFrameMatchesUISourceCode(oldSourceFrame, uiSourceCode)) {
+ oldSourceFrame.setHighlighterType(uiSourceCode.highlighterType());
+ } else {
+ this._editorContainer.removeUISourceCode(uiSourceCode);
+ this._removeSourceFrame(uiSourceCode);
+ }
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {!WebInspector.SourceFrame}
+ */
+ viewForFile: function(uiSourceCode)
+ {
+ return this._getOrCreateSourceFrame(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _removeSourceFrame: function(uiSourceCode)
+ {
+ var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode);
+ if (!sourceFrame)
+ return;
+ this._sourceFramesByUISourceCode.remove(uiSourceCode);
+ sourceFrame.dispose();
+ },
+
+ clearCurrentExecutionLine: function()
+ {
+ if (this._executionSourceFrame)
+ this._executionSourceFrame.clearExecutionLine();
+ delete this._executionSourceFrame;
+ },
+
+ setExecutionLine: function(uiLocation)
+ {
+ var sourceFrame = this._getOrCreateSourceFrame(uiLocation.uiSourceCode);
+ sourceFrame.setExecutionLine(uiLocation.lineNumber);
+ this._executionSourceFrame = sourceFrame;
+ },
+
+ _editorClosed: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
+ this._historyManager.removeHistoryForSourceCode(uiSourceCode);
+
+ var wasSelected = false;
+ if (this._currentUISourceCode === uiSourceCode) {
+ delete this._currentUISourceCode;
+ wasSelected = true;
+ }
+
+ // SourcesNavigator does not need to update on EditorClosed.
+ this._updateScriptViewStatusBarItems();
+ this._searchableView.resetSearch();
+
+ var data = {};
+ data.uiSourceCode = uiSourceCode;
+ data.wasSelected = wasSelected;
+ this.dispatchEventToListeners(WebInspector.SourcesView.Events.EditorClosed, data);
+ },
+
+ _editorSelected: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.currentFile);
+ var shouldUseHistoryManager = uiSourceCode !== this._currentUISourceCode && event.data.userGesture;
+ if (shouldUseHistoryManager)
+ this._historyManager.updateCurrentState();
+ var sourceFrame = this._showFile(uiSourceCode);
+ if (shouldUseHistoryManager)
+ this._historyManager.pushNewState();
+
+ this._searchableView.setReplaceable(!!sourceFrame && sourceFrame.canEditSource());
+ this._searchableView.resetSearch();
+
+ this.dispatchEventToListeners(WebInspector.SourcesView.Events.EditorSelected, uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ sourceRenamed: function(uiSourceCode)
+ {
+ this._recreateSourceFrameIfNeeded(uiSourceCode);
+ },
+
+ searchCanceled: function()
+ {
+ if (this._searchView)
+ this._searchView.searchCanceled();
+
+ delete this._searchView;
+ delete this._searchQuery;
+ },
+
+ /**
+ * @param {string} query
+ * @param {boolean} shouldJump
+ * @param {boolean=} jumpBackwards
+ */
+ performSearch: function(query, shouldJump, jumpBackwards)
+ {
+ this._searchableView.updateSearchMatchesCount(0);
+
+ var sourceFrame = this.currentSourceFrame();
+ if (!sourceFrame)
+ return;
+
+ this._searchView = sourceFrame;
+ this._searchQuery = query;
+
+ /**
+ * @param {!WebInspector.View} view
+ * @param {number} searchMatches
+ * @this {WebInspector.SourcesView}
+ */
+ function finishedCallback(view, searchMatches)
+ {
+ if (!searchMatches)
+ return;
+
+ this._searchableView.updateSearchMatchesCount(searchMatches);
+ }
+
+ /**
+ * @param {number} currentMatchIndex
+ * @this {WebInspector.SourcesView}
+ */
+ function currentMatchChanged(currentMatchIndex)
+ {
+ this._searchableView.updateCurrentMatchIndex(currentMatchIndex);
+ }
+
+ /**
+ * @this {WebInspector.SourcesView}
+ */
+ function searchResultsChanged()
+ {
+ this._searchableView.cancelSearch();
+ }
+
+ this._searchView.performSearch(query, shouldJump, !!jumpBackwards, finishedCallback.bind(this), currentMatchChanged.bind(this), searchResultsChanged.bind(this));
+ },
+
+ jumpToNextSearchResult: function()
+ {
+ if (!this._searchView)
+ return;
+
+ if (this._searchView !== this.currentSourceFrame()) {
+ this.performSearch(this._searchQuery, true);
+ return;
+ }
+
+ this._searchView.jumpToNextSearchResult();
+ },
+
+ jumpToPreviousSearchResult: function()
+ {
+ if (!this._searchView)
+ return;
+
+ if (this._searchView !== this.currentSourceFrame()) {
+ this.performSearch(this._searchQuery, true);
+ if (this._searchView)
+ this._searchView.jumpToLastSearchResult();
+ return;
+ }
+
+ this._searchView.jumpToPreviousSearchResult();
+ },
+
+ /**
+ * @param {string} text
+ */
+ replaceSelectionWith: function(text)
+ {
+ var sourceFrame = this.currentSourceFrame();
+ if (!sourceFrame) {
+ console.assert(sourceFrame);
+ return;
+ }
+ sourceFrame.replaceSelectionWith(text);
+ },
+
+ /**
+ * @param {string} query
+ * @param {string} text
+ */
+ replaceAllWith: function(query, text)
+ {
+ var sourceFrame = this.currentSourceFrame();
+ if (!sourceFrame) {
+ console.assert(sourceFrame);
+ return;
+ }
+ sourceFrame.replaceAllWith(query, text);
+ },
+
+ /**
+ * @param {?Event=} event
+ * @return {boolean}
+ */
+ _showOutlineDialog: function(event)
+ {
+ var uiSourceCode = this._editorContainer.currentFile();
+ if (!uiSourceCode)
+ return false;
+
+ switch (uiSourceCode.contentType()) {
+ case WebInspector.resourceTypes.Document:
+ case WebInspector.resourceTypes.Script:
+ WebInspector.JavaScriptOutlineDialog.show(this, uiSourceCode, this.showSourceLocation.bind(this, uiSourceCode));
+ return true;
+ case WebInspector.resourceTypes.Stylesheet:
+ WebInspector.StyleSheetOutlineDialog.show(this, uiSourceCode, this.showSourceLocation.bind(this, uiSourceCode));
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * @param {string=} query
+ */
+ showOpenResourceDialog: function(query)
+ {
+ var uiSourceCodes = this._editorContainer.historyUISourceCodes();
+ /** @type {!Map.<!WebInspector.UISourceCode, number>} */
+ var defaultScores = new Map();
+ for (var i = 1; i < uiSourceCodes.length; ++i) // Skip current element
+ defaultScores.put(uiSourceCodes[i], uiSourceCodes.length - i);
+ WebInspector.OpenResourceDialog.show(this, this.element, query, defaultScores);
+ },
+
+ /**
+ * @param {?Event=} event
+ * @return {boolean}
+ */
+ _showGoToLineDialog: function(event)
+ {
+ if (this._currentUISourceCode)
+ this.showOpenResourceDialog(":");
+ return true;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _save: function()
+ {
+ this._saveSourceFrame(this.currentSourceFrame());
+ return true;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ _saveAll: function()
+ {
+ var sourceFrames = this._editorContainer.fileViews();
+ sourceFrames.forEach(this._saveSourceFrame.bind(this));
+ return true;
+ },
+
+ /**
+ * @param {?WebInspector.SourceFrame} sourceFrame
+ */
+ _saveSourceFrame: function(sourceFrame)
+ {
+ if (!sourceFrame)
+ return;
+ if (!(sourceFrame instanceof WebInspector.UISourceCodeFrame))
+ return;
+ var uiSourceCodeFrame = /** @type {!WebInspector.UISourceCodeFrame} */ (sourceFrame);
+ uiSourceCodeFrame.commitEditing();
+ },
+ /**
+ * @return {boolean}
+ */
+ _toggleBreakpoint: function()
+ {
+ var sourceFrame = this.currentSourceFrame();
+ if (!sourceFrame)
+ return false;
+
+ if (sourceFrame instanceof WebInspector.JavaScriptSourceFrame) {
+ var javaScriptSourceFrame = /** @type {!WebInspector.JavaScriptSourceFrame} */ (sourceFrame);
+ javaScriptSourceFrame.toggleBreakpointOnCurrentLine();
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * @param {boolean} active
+ */
+ toggleBreakpointsActiveState: function(active)
+ {
+ this._editorContainer.view.element.classList.toggle("breakpoints-deactivated", !active);
+ },
+
+ __proto__: WebInspector.VBox.prototype
+}
+
+/**
+ * @interface
+ */
+WebInspector.SourcesView.EditorAction = function()
+{
+}
+
+WebInspector.SourcesView.EditorAction.prototype = {
+ /**
+ * @param {!WebInspector.SourcesView} sourcesView
+ * @return {!Element}
+ */
+ button: function(sourcesView) { }
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/StyleSheetOutlineDialog.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/StyleSheetOutlineDialog.js
new file mode 100644
index 00000000000..05b5f9a6ea0
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/StyleSheetOutlineDialog.js
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
+ * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.SelectionDialogContentProvider}
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {function(number, number)} selectItemCallback
+ */
+WebInspector.StyleSheetOutlineDialog = function(uiSourceCode, selectItemCallback)
+{
+ WebInspector.SelectionDialogContentProvider.call(this);
+ this._selectItemCallback = selectItemCallback;
+ this._cssParser = new WebInspector.CSSParser();
+ this._cssParser.addEventListener(WebInspector.CSSParser.Events.RulesParsed, this.refresh.bind(this));
+ this._cssParser.parse(uiSourceCode.workingCopy());
+}
+
+/**
+ * @param {!WebInspector.View} view
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {function(number, number)} selectItemCallback
+ */
+WebInspector.StyleSheetOutlineDialog.show = function(view, uiSourceCode, selectItemCallback)
+{
+ if (WebInspector.Dialog.currentInstance())
+ return;
+ var delegate = new WebInspector.StyleSheetOutlineDialog(uiSourceCode, selectItemCallback);
+ var filteredItemSelectionDialog = new WebInspector.FilteredItemSelectionDialog(delegate);
+ WebInspector.Dialog.show(view.element, filteredItemSelectionDialog);
+}
+
+WebInspector.StyleSheetOutlineDialog.prototype = {
+ /**
+ * @return {number}
+ */
+ itemCount: function()
+ {
+ return this._cssParser.rules().length;
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @return {string}
+ */
+ itemKeyAt: function(itemIndex)
+ {
+ var rule = this._cssParser.rules()[itemIndex];
+ return rule.selectorText || rule.atRule;
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @param {string} query
+ * @return {number}
+ */
+ itemScoreAt: function(itemIndex, query)
+ {
+ var rule = this._cssParser.rules()[itemIndex];
+ return -rule.lineNumber;
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @param {string} query
+ * @param {!Element} titleElement
+ * @param {!Element} subtitleElement
+ */
+ renderItem: function(itemIndex, query, titleElement, subtitleElement)
+ {
+ var rule = this._cssParser.rules()[itemIndex];
+ titleElement.textContent = rule.selectorText || rule.atRule;
+ this.highlightRanges(titleElement, query);
+ subtitleElement.textContent = ":" + (rule.lineNumber + 1);
+ },
+
+ /**
+ * @param {number} itemIndex
+ * @param {string} promptValue
+ */
+ selectItem: function(itemIndex, promptValue)
+ {
+ var rule = this._cssParser.rules()[itemIndex];
+ var lineNumber = rule.lineNumber;
+ if (!isNaN(lineNumber) && lineNumber >= 0)
+ this._selectItemCallback(lineNumber, rule.columnNumber);
+ },
+
+ dispose: function()
+ {
+ this._cssParser.dispose();
+ },
+
+ __proto__: WebInspector.SelectionDialogContentProvider.prototype
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/TabbedEditorContainer.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/TabbedEditorContainer.js
new file mode 100644
index 00000000000..b7de95086c4
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/TabbedEditorContainer.js
@@ -0,0 +1,739 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
+ * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @interface
+ */
+WebInspector.TabbedEditorContainerDelegate = function() { }
+
+WebInspector.TabbedEditorContainerDelegate.prototype = {
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {!WebInspector.SourceFrame}
+ */
+ viewForFile: function(uiSourceCode) { },
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.Object}
+ * @param {!WebInspector.TabbedEditorContainerDelegate} delegate
+ * @param {string} settingName
+ * @param {string} placeholderText
+ */
+WebInspector.TabbedEditorContainer = function(delegate, settingName, placeholderText)
+{
+ WebInspector.Object.call(this);
+ this._delegate = delegate;
+
+ this._tabbedPane = new WebInspector.TabbedPane();
+ this._tabbedPane.setPlaceholderText(placeholderText);
+ this._tabbedPane.setTabDelegate(new WebInspector.EditorContainerTabDelegate(this));
+
+ this._tabbedPane.closeableTabs = true;
+ this._tabbedPane.element.id = "sources-editor-container-tabbed-pane";
+
+ this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabClosed, this._tabClosed, this);
+ this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this);
+
+ this._tabIds = new Map();
+ this._files = {};
+
+ this._previouslyViewedFilesSetting = WebInspector.settings.createSetting(settingName, []);
+ this._history = WebInspector.TabbedEditorContainer.History.fromObject(this._previouslyViewedFilesSetting.get());
+}
+
+WebInspector.TabbedEditorContainer.Events = {
+ EditorSelected: "EditorSelected",
+ EditorClosed: "EditorClosed"
+}
+
+WebInspector.TabbedEditorContainer._tabId = 0;
+
+WebInspector.TabbedEditorContainer.maximalPreviouslyViewedFilesCount = 30;
+
+WebInspector.TabbedEditorContainer.prototype = {
+ /**
+ * @return {!WebInspector.View}
+ */
+ get view()
+ {
+ return this._tabbedPane;
+ },
+
+ /**
+ * @type {!WebInspector.SourceFrame}
+ */
+ get visibleView()
+ {
+ return this._tabbedPane.visibleView;
+ },
+
+ /**
+ * @return {!Array.<!WebInspector.SourceFrame>}
+ */
+ fileViews: function()
+ {
+ return /** @type {!Array.<!WebInspector.SourceFrame>} */ (this._tabbedPane.tabViews());
+ },
+
+ /**
+ * @param {!Element} parentElement
+ */
+ show: function(parentElement)
+ {
+ this._tabbedPane.show(parentElement);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ showFile: function(uiSourceCode)
+ {
+ this._innerShowFile(uiSourceCode, true);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ closeFile: function(uiSourceCode)
+ {
+ var tabId = this._tabIds.get(uiSourceCode);
+ if (!tabId)
+ return;
+ this._closeTabs([tabId]);
+ },
+
+ /**
+ * @return {!Array.<!WebInspector.UISourceCode>}
+ */
+ historyUISourceCodes: function()
+ {
+ // FIXME: there should be a way to fetch UISourceCode for its uri.
+ var uriToUISourceCode = {};
+ for (var id in this._files) {
+ var uiSourceCode = this._files[id];
+ uriToUISourceCode[uiSourceCode.uri()] = uiSourceCode;
+ }
+
+ var result = [];
+ var uris = this._history._urls();
+ for (var i = 0; i < uris.length; ++i) {
+ var uiSourceCode = uriToUISourceCode[uris[i]];
+ if (uiSourceCode)
+ result.push(uiSourceCode);
+ }
+ return result;
+ },
+
+ _addViewListeners: function()
+ {
+ if (!this._currentView)
+ return;
+ this._currentView.addEventListener(WebInspector.SourceFrame.Events.ScrollChanged, this._scrollChanged, this);
+ this._currentView.addEventListener(WebInspector.SourceFrame.Events.SelectionChanged, this._selectionChanged, this);
+ },
+
+ _removeViewListeners: function()
+ {
+ if (!this._currentView)
+ return;
+ this._currentView.removeEventListener(WebInspector.SourceFrame.Events.ScrollChanged, this._scrollChanged, this);
+ this._currentView.removeEventListener(WebInspector.SourceFrame.Events.SelectionChanged, this._selectionChanged, this);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _scrollChanged: function(event)
+ {
+ var lineNumber = /** @type {number} */ (event.data);
+ this._history.updateScrollLineNumber(this._currentFile.uri(), lineNumber);
+ this._history.save(this._previouslyViewedFilesSetting);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _selectionChanged: function(event)
+ {
+ var range = /** @type {!WebInspector.TextRange} */ (event.data);
+ this._history.updateSelectionRange(this._currentFile.uri(), range);
+ this._history.save(this._previouslyViewedFilesSetting);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {boolean=} userGesture
+ */
+ _innerShowFile: function(uiSourceCode, userGesture)
+ {
+ if (this._currentFile === uiSourceCode)
+ return;
+
+ this._removeViewListeners();
+ this._currentFile = uiSourceCode;
+
+ var tabId = this._tabIds.get(uiSourceCode) || this._appendFileTab(uiSourceCode, userGesture);
+
+ this._tabbedPane.selectTab(tabId, userGesture);
+ if (userGesture)
+ this._editorSelectedByUserAction();
+
+ this._currentView = this.visibleView;
+ this._addViewListeners();
+
+ var eventData = { currentFile: this._currentFile, userGesture: userGesture };
+ this.dispatchEventToListeners(WebInspector.TabbedEditorContainer.Events.EditorSelected, eventData);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {string}
+ */
+ _titleForFile: function(uiSourceCode)
+ {
+ var maxDisplayNameLength = 30;
+ var title = uiSourceCode.displayName(true).trimMiddle(maxDisplayNameLength);
+ if (uiSourceCode.isDirty() || uiSourceCode.hasUnsavedCommittedChanges())
+ title += "*";
+ return title;
+ },
+
+ /**
+ * @param {string} id
+ * @param {string} nextTabId
+ */
+ _maybeCloseTab: function(id, nextTabId)
+ {
+ var uiSourceCode = this._files[id];
+ var shouldPrompt = uiSourceCode.isDirty() && uiSourceCode.project().canSetFileContent();
+ // FIXME: this should be replaced with common Save/Discard/Cancel dialog.
+ if (!shouldPrompt || confirm(WebInspector.UIString("Are you sure you want to close unsaved file: %s?", uiSourceCode.name()))) {
+ uiSourceCode.resetWorkingCopy();
+ if (nextTabId)
+ this._tabbedPane.selectTab(nextTabId, true);
+ this._tabbedPane.closeTab(id, true);
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * @param {!Array.<string>} ids
+ */
+ _closeTabs: function(ids)
+ {
+ var dirtyTabs = [];
+ var cleanTabs = [];
+ for (var i = 0; i < ids.length; ++i) {
+ var id = ids[i];
+ var uiSourceCode = this._files[id];
+ if (uiSourceCode.isDirty())
+ dirtyTabs.push(id);
+ else
+ cleanTabs.push(id);
+ }
+ if (dirtyTabs.length)
+ this._tabbedPane.selectTab(dirtyTabs[0], true);
+ this._tabbedPane.closeTabs(cleanTabs, true);
+ for (var i = 0; i < dirtyTabs.length; ++i) {
+ var nextTabId = i + 1 < dirtyTabs.length ? dirtyTabs[i + 1] : null;
+ if (!this._maybeCloseTab(dirtyTabs[i], nextTabId))
+ break;
+ }
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ addUISourceCode: function(uiSourceCode)
+ {
+ var uri = uiSourceCode.uri();
+ if (this._userSelectedFiles)
+ return;
+
+ var index = this._history.index(uri)
+ if (index === -1)
+ return;
+
+ var tabId = this._tabIds.get(uiSourceCode) || this._appendFileTab(uiSourceCode, false);
+
+ if (!this._currentFile)
+ return;
+
+ // Select tab if this file was the last to be shown.
+ if (!index) {
+ this._innerShowFile(uiSourceCode, false);
+ return;
+ }
+
+ var currentProjectType = this._currentFile.project().type();
+ var addedProjectType = uiSourceCode.project().type();
+ var snippetsProjectType = WebInspector.projectTypes.Snippets;
+ if (this._history.index(this._currentFile.uri()) && currentProjectType === snippetsProjectType && addedProjectType !== snippetsProjectType)
+ this._innerShowFile(uiSourceCode, false);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ removeUISourceCode: function(uiSourceCode)
+ {
+ this.removeUISourceCodes([uiSourceCode]);
+ },
+
+ /**
+ * @param {!Array.<!WebInspector.UISourceCode>} uiSourceCodes
+ */
+ removeUISourceCodes: function(uiSourceCodes)
+ {
+ var tabIds = [];
+ for (var i = 0; i < uiSourceCodes.length; ++i) {
+ var uiSourceCode = uiSourceCodes[i];
+ var tabId = this._tabIds.get(uiSourceCode);
+ if (tabId)
+ tabIds.push(tabId);
+ }
+ this._tabbedPane.closeTabs(tabIds);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _editorClosedByUserAction: function(uiSourceCode)
+ {
+ this._userSelectedFiles = true;
+ this._history.remove(uiSourceCode.uri());
+ this._updateHistory();
+ },
+
+ _editorSelectedByUserAction: function()
+ {
+ this._userSelectedFiles = true;
+ this._updateHistory();
+ },
+
+ _updateHistory: function()
+ {
+ var tabIds = this._tabbedPane.lastOpenedTabIds(WebInspector.TabbedEditorContainer.maximalPreviouslyViewedFilesCount);
+
+ /**
+ * @param {string} tabId
+ * @this {WebInspector.TabbedEditorContainer}
+ */
+ function tabIdToURI(tabId)
+ {
+ return this._files[tabId].uri();
+ }
+
+ this._history.update(tabIds.map(tabIdToURI.bind(this)));
+ this._history.save(this._previouslyViewedFilesSetting);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {string}
+ */
+ _tooltipForFile: function(uiSourceCode)
+ {
+ return uiSourceCode.originURL();
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @param {boolean=} userGesture
+ * @return {string}
+ */
+ _appendFileTab: function(uiSourceCode, userGesture)
+ {
+ var view = this._delegate.viewForFile(uiSourceCode);
+ var title = this._titleForFile(uiSourceCode);
+ var tooltip = this._tooltipForFile(uiSourceCode);
+
+ var tabId = this._generateTabId();
+ this._tabIds.put(uiSourceCode, tabId);
+ this._files[tabId] = uiSourceCode;
+
+ var savedSelectionRange = this._history.selectionRange(uiSourceCode.uri());
+ if (savedSelectionRange)
+ view.setSelection(savedSelectionRange);
+ var savedScrollLineNumber = this._history.scrollLineNumber(uiSourceCode.uri());
+ if (savedScrollLineNumber)
+ view.scrollToLine(savedScrollLineNumber);
+
+ this._tabbedPane.appendTab(tabId, title, view, tooltip, userGesture);
+
+ this._updateFileTitle(uiSourceCode);
+ this._addUISourceCodeListeners(uiSourceCode);
+ return tabId;
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _tabClosed: function(event)
+ {
+ var tabId = /** @type {string} */ (event.data.tabId);
+ var userGesture = /** @type {boolean} */ (event.data.isUserGesture);
+
+ var uiSourceCode = this._files[tabId];
+ if (this._currentFile === uiSourceCode) {
+ this._removeViewListeners();
+ delete this._currentView;
+ delete this._currentFile;
+ }
+ this._tabIds.remove(uiSourceCode);
+ delete this._files[tabId];
+
+ this._removeUISourceCodeListeners(uiSourceCode);
+
+ this.dispatchEventToListeners(WebInspector.TabbedEditorContainer.Events.EditorClosed, uiSourceCode);
+
+ if (userGesture)
+ this._editorClosedByUserAction(uiSourceCode);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _tabSelected: function(event)
+ {
+ var tabId = /** @type {string} */ (event.data.tabId);
+ var userGesture = /** @type {boolean} */ (event.data.isUserGesture);
+
+ var uiSourceCode = this._files[tabId];
+ this._innerShowFile(uiSourceCode, userGesture);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _addUISourceCodeListeners: function(uiSourceCode)
+ {
+ uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.TitleChanged, this._uiSourceCodeTitleChanged, this);
+ uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._uiSourceCodeWorkingCopyChanged, this);
+ uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._uiSourceCodeWorkingCopyCommitted, this);
+ uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.SavedStateUpdated, this._uiSourceCodeSavedStateUpdated, this);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _removeUISourceCodeListeners: function(uiSourceCode)
+ {
+ uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.TitleChanged, this._uiSourceCodeTitleChanged, this);
+ uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._uiSourceCodeWorkingCopyChanged, this);
+ uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._uiSourceCodeWorkingCopyCommitted, this);
+ uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.SavedStateUpdated, this._uiSourceCodeSavedStateUpdated, this);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+ _updateFileTitle: function(uiSourceCode)
+ {
+ var tabId = this._tabIds.get(uiSourceCode);
+ if (tabId) {
+ var title = this._titleForFile(uiSourceCode);
+ this._tabbedPane.changeTabTitle(tabId, title);
+ if (uiSourceCode.hasUnsavedCommittedChanges())
+ this._tabbedPane.setTabIcon(tabId, "editor-container-unsaved-committed-changes-icon", WebInspector.UIString("Changes to this file were not saved to file system."));
+ else
+ this._tabbedPane.setTabIcon(tabId, "");
+ }
+ },
+
+ _uiSourceCodeTitleChanged: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.target);
+ this._updateFileTitle(uiSourceCode);
+ this._updateHistory();
+ },
+
+ _uiSourceCodeWorkingCopyChanged: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.target);
+ this._updateFileTitle(uiSourceCode);
+ },
+
+ _uiSourceCodeWorkingCopyCommitted: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.target);
+ this._updateFileTitle(uiSourceCode);
+ },
+
+ _uiSourceCodeSavedStateUpdated: function(event)
+ {
+ var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.target);
+ this._updateFileTitle(uiSourceCode);
+ },
+
+ reset: function()
+ {
+ delete this._userSelectedFiles;
+ },
+
+ /**
+ * @return {string}
+ */
+ _generateTabId: function()
+ {
+ return "tab_" + (WebInspector.TabbedEditorContainer._tabId++);
+ },
+
+ /**
+ * @return {!WebInspector.UISourceCode} uiSourceCode
+ */
+ currentFile: function()
+ {
+ return this._currentFile;
+ },
+
+ __proto__: WebInspector.Object.prototype
+}
+
+/**
+ * @constructor
+ * @param {string} url
+ * @param {!WebInspector.TextRange=} selectionRange
+ * @param {number=} scrollLineNumber
+ */
+WebInspector.TabbedEditorContainer.HistoryItem = function(url, selectionRange, scrollLineNumber)
+{
+ /** @const */ this.url = url;
+ /** @const */ this._isSerializable = url.length < WebInspector.TabbedEditorContainer.HistoryItem.serializableUrlLengthLimit;
+ this.selectionRange = selectionRange;
+ this.scrollLineNumber = scrollLineNumber;
+}
+
+WebInspector.TabbedEditorContainer.HistoryItem.serializableUrlLengthLimit = 4096;
+
+/**
+ * @param {!Object} serializedHistoryItem
+ * @return {!WebInspector.TabbedEditorContainer.HistoryItem}
+ */
+WebInspector.TabbedEditorContainer.HistoryItem.fromObject = function (serializedHistoryItem)
+{
+ var selectionRange = serializedHistoryItem.selectionRange ? WebInspector.TextRange.fromObject(serializedHistoryItem.selectionRange) : undefined;
+ return new WebInspector.TabbedEditorContainer.HistoryItem(serializedHistoryItem.url, selectionRange, serializedHistoryItem.scrollLineNumber);
+}
+
+WebInspector.TabbedEditorContainer.HistoryItem.prototype = {
+ /**
+ * @return {?Object}
+ */
+ serializeToObject: function()
+ {
+ if (!this._isSerializable)
+ return null;
+ var serializedHistoryItem = {};
+ serializedHistoryItem.url = this.url;
+ serializedHistoryItem.selectionRange = this.selectionRange;
+ serializedHistoryItem.scrollLineNumber = this.scrollLineNumber;
+ return serializedHistoryItem;
+ }
+}
+
+/**
+ * @constructor
+ * @param {!Array.<!WebInspector.TabbedEditorContainer.HistoryItem>} items
+ */
+WebInspector.TabbedEditorContainer.History = function(items)
+{
+ this._items = items;
+ this._rebuildItemIndex();
+}
+
+/**
+ * @param {!Array.<!Object>} serializedHistory
+ * @return {!WebInspector.TabbedEditorContainer.History}
+ */
+WebInspector.TabbedEditorContainer.History.fromObject = function(serializedHistory)
+{
+ var items = [];
+ for (var i = 0; i < serializedHistory.length; ++i)
+ items.push(WebInspector.TabbedEditorContainer.HistoryItem.fromObject(serializedHistory[i]));
+ return new WebInspector.TabbedEditorContainer.History(items);
+}
+
+WebInspector.TabbedEditorContainer.History.prototype = {
+ /**
+ * @param {string} url
+ * @return {number}
+ */
+ index: function(url)
+ {
+ var index = this._itemsIndex[url];
+ if (typeof index === "number")
+ return index;
+ return -1;
+ },
+
+ _rebuildItemIndex: function()
+ {
+ this._itemsIndex = {};
+ for (var i = 0; i < this._items.length; ++i) {
+ console.assert(!this._itemsIndex.hasOwnProperty(this._items[i].url));
+ this._itemsIndex[this._items[i].url] = i;
+ }
+ },
+
+ /**
+ * @param {string} url
+ * @return {!WebInspector.TextRange|undefined}
+ */
+ selectionRange: function(url)
+ {
+ var index = this.index(url);
+ return index !== -1 ? this._items[index].selectionRange : undefined;
+ },
+
+ /**
+ * @param {string} url
+ * @param {!WebInspector.TextRange=} selectionRange
+ */
+ updateSelectionRange: function(url, selectionRange)
+ {
+ if (!selectionRange)
+ return;
+ var index = this.index(url);
+ if (index === -1)
+ return;
+ this._items[index].selectionRange = selectionRange;
+ },
+
+ /**
+ * @param {string} url
+ * @return {number|undefined}
+ */
+ scrollLineNumber: function(url)
+ {
+ var index = this.index(url);
+ return index !== -1 ? this._items[index].scrollLineNumber : undefined;
+ },
+
+ /**
+ * @param {string} url
+ * @param {number} scrollLineNumber
+ */
+ updateScrollLineNumber: function(url, scrollLineNumber)
+ {
+ var index = this.index(url);
+ if (index === -1)
+ return;
+ this._items[index].scrollLineNumber = scrollLineNumber;
+ },
+
+ /**
+ * @param {!Array.<string>} urls
+ */
+ update: function(urls)
+ {
+ for (var i = urls.length - 1; i >= 0; --i) {
+ var index = this.index(urls[i]);
+ var item;
+ if (index !== -1) {
+ item = this._items[index];
+ this._items.splice(index, 1);
+ } else
+ item = new WebInspector.TabbedEditorContainer.HistoryItem(urls[i]);
+ this._items.unshift(item);
+ this._rebuildItemIndex();
+ }
+ },
+
+ /**
+ * @param {string} url
+ */
+ remove: function(url)
+ {
+ var index = this.index(url);
+ if (index !== -1) {
+ this._items.splice(index, 1);
+ this._rebuildItemIndex();
+ }
+ },
+
+ /**
+ * @param {!WebInspector.Setting} setting
+ */
+ save: function(setting)
+ {
+ setting.set(this._serializeToObject());
+ },
+
+ /**
+ * @return {!Array.<!Object>}
+ */
+ _serializeToObject: function()
+ {
+ var serializedHistory = [];
+ for (var i = 0; i < this._items.length; ++i) {
+ var serializedItem = this._items[i].serializeToObject();
+ if (serializedItem)
+ serializedHistory.push(serializedItem);
+ if (serializedHistory.length === WebInspector.TabbedEditorContainer.maximalPreviouslyViewedFilesCount)
+ break;
+ }
+ return serializedHistory;
+ },
+
+
+ /**
+ * @return {!Array.<string>}
+ */
+ _urls: function()
+ {
+ var result = [];
+ for (var i = 0; i < this._items.length; ++i)
+ result.push(this._items[i].url);
+ return result;
+ }
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.TabbedPaneTabDelegate}
+ * @param {!WebInspector.TabbedEditorContainer} editorContainer
+ */
+WebInspector.EditorContainerTabDelegate = function(editorContainer)
+{
+ this._editorContainer = editorContainer;
+}
+
+WebInspector.EditorContainerTabDelegate.prototype = {
+ /**
+ * @param {!WebInspector.TabbedPane} tabbedPane
+ * @param {!Array.<string>} ids
+ */
+ closeTabs: function(tabbedPane, ids)
+ {
+ this._editorContainer._closeTabs(ids);
+ }
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/TargetsToolbar.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/TargetsToolbar.js
new file mode 100644
index 00000000000..5b0a4a9db1f
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/TargetsToolbar.js
@@ -0,0 +1,78 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @constructor
+ * @implements {WebInspector.TargetManager.Observer}
+ */
+WebInspector.TargetsToolbar = function()
+{
+ this.element = document.createElement("div");
+ this.element.className = "status-bar scripts-debug-toolbar targets-toolbar hidden";
+ this._comboBox = new WebInspector.StatusBarComboBox(this._onComboBoxSelectionChange.bind(this));
+ this.element.appendChild(this._comboBox.element);
+
+ /** @type {!Map.<!WebInspector.Target, !Element>} */
+ this._targetToOption = new Map();
+ if (!WebInspector.experimentsSettings.workersInMainWindow.isEnabled())
+ return;
+
+ WebInspector.context.addFlavorChangeListener(WebInspector.Target, this._targetChangedExternally, this);
+ WebInspector.targetManager.observeTargets(this);
+}
+
+WebInspector.TargetsToolbar.prototype = {
+
+ /**
+ * @param {!WebInspector.Target} target
+ */
+ targetAdded: function(target)
+ {
+ var option = this._comboBox.createOption(target.name());
+ option.__target = target;
+ this._targetToOption.put(target, option);
+ if (WebInspector.context.flavor(WebInspector.Target) === target)
+ this._comboBox.select(option);
+
+ this._updateVisibility();
+ },
+
+ /**
+ * @param {!WebInspector.Target} target
+ */
+ targetRemoved: function(target)
+ {
+ var option = this._targetToOption.remove(target);
+ this._comboBox.removeOption(option);
+ this._updateVisibility();
+ },
+
+ _onComboBoxSelectionChange: function()
+ {
+ var selectedOption = this._comboBox.selectedOption();
+ if (!selectedOption)
+ return;
+
+ WebInspector.context.setFlavor(WebInspector.Target, selectedOption.__target);
+ },
+
+ _updateVisibility: function()
+ {
+ var hidden = this._comboBox.size() === 1;
+ this.element.classList.toggle("hidden", hidden);
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _targetChangedExternally: function(event)
+ {
+ var target = /** @type {?WebInspector.Target} */ (event.data);
+ if (target) {
+ var option = /** @type {!Element} */ (this._targetToOption.get(target));
+ this._comboBox.select(option);
+ }
+ }
+
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js
new file mode 100644
index 00000000000..782325215ac
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
+ * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.SourceFrame}
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ */
+WebInspector.UISourceCodeFrame = function(uiSourceCode)
+{
+ this._uiSourceCode = uiSourceCode;
+ WebInspector.SourceFrame.call(this, this._uiSourceCode);
+ WebInspector.settings.textEditorAutocompletion.addChangeListener(this._enableAutocompletionIfNeeded, this);
+ this._enableAutocompletionIfNeeded();
+
+ this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._onWorkingCopyChanged, this);
+ this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._onWorkingCopyCommitted, this);
+ this._updateStyle();
+}
+
+WebInspector.UISourceCodeFrame.prototype = {
+ /**
+ * @return {!WebInspector.UISourceCode}
+ */
+ uiSourceCode: function()
+ {
+ return this._uiSourceCode;
+ },
+
+ _enableAutocompletionIfNeeded: function()
+ {
+ this.textEditor.setCompletionDictionary(WebInspector.settings.textEditorAutocompletion.get() ? new WebInspector.SampleCompletionDictionary() : null);
+ },
+
+ wasShown: function()
+ {
+ WebInspector.SourceFrame.prototype.wasShown.call(this);
+ this._boundWindowFocused = this._windowFocused.bind(this);
+ window.addEventListener("focus", this._boundWindowFocused, false);
+ this._checkContentUpdated();
+ },
+
+ willHide: function()
+ {
+ WebInspector.SourceFrame.prototype.willHide.call(this);
+ window.removeEventListener("focus", this._boundWindowFocused, false);
+ delete this._boundWindowFocused;
+ this._uiSourceCode.removeWorkingCopyGetter();
+ },
+
+ /**
+ * @return {boolean}
+ */
+ canEditSource: function()
+ {
+ var projectType = this._uiSourceCode.project().type();
+ if (projectType === WebInspector.projectTypes.Debugger || projectType === WebInspector.projectTypes.Formatter)
+ return false;
+ if (projectType === WebInspector.projectTypes.Network && this._uiSourceCode.contentType() === WebInspector.resourceTypes.Document)
+ return false;
+ return true;
+ },
+
+ _windowFocused: function(event)
+ {
+ this._checkContentUpdated();
+ },
+
+ _checkContentUpdated: function()
+ {
+ if (!this.loaded || !this.isShowing())
+ return;
+ this._uiSourceCode.checkContentUpdated();
+ },
+
+ commitEditing: function()
+ {
+ if (!this._uiSourceCode.isDirty())
+ return;
+
+ this._muteSourceCodeEvents = true;
+ this._uiSourceCode.commitWorkingCopy(this._didEditContent.bind(this));
+ delete this._muteSourceCodeEvents;
+ },
+
+ onTextChanged: function(oldRange, newRange)
+ {
+ WebInspector.SourceFrame.prototype.onTextChanged.call(this, oldRange, newRange);
+ if (this._isSettingContent)
+ return;
+ this._muteSourceCodeEvents = true;
+ if (this._textEditor.isClean())
+ this._uiSourceCode.resetWorkingCopy();
+ else
+ this._uiSourceCode.setWorkingCopyGetter(this._textEditor.text.bind(this._textEditor));
+ delete this._muteSourceCodeEvents;
+ },
+
+ _didEditContent: function(error)
+ {
+ if (error) {
+ WebInspector.messageSink.addErrorMessage(error, true);
+ return;
+ }
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _onWorkingCopyChanged: function(event)
+ {
+ if (this._muteSourceCodeEvents)
+ return;
+ this._innerSetContent(this._uiSourceCode.workingCopy());
+ this.onUISourceCodeContentChanged();
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _onWorkingCopyCommitted: function(event)
+ {
+ if (!this._muteSourceCodeEvents) {
+ this._innerSetContent(this._uiSourceCode.workingCopy());
+ this.onUISourceCodeContentChanged();
+ }
+ this._textEditor.markClean();
+ this._updateStyle();
+ },
+
+ _updateStyle: function()
+ {
+ this.element.classList.toggle("source-frame-unsaved-committed-changes", this._uiSourceCode.hasUnsavedCommittedChanges());
+ },
+
+ onUISourceCodeContentChanged: function()
+ {
+ },
+
+ /**
+ * @param {string} content
+ */
+ _innerSetContent: function(content)
+ {
+ this._isSettingContent = true;
+ this.setContent(content);
+ delete this._isSettingContent;
+ },
+
+ populateTextAreaContextMenu: function(contextMenu, lineNumber)
+ {
+ WebInspector.SourceFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber);
+ contextMenu.appendApplicableItems(this._uiSourceCode);
+ contextMenu.appendSeparator();
+ },
+
+ dispose: function()
+ {
+ WebInspector.settings.textEditorAutocompletion.removeChangeListener(this._enableAutocompletionIfNeeded, this);
+ this._textEditor.dispose();
+ this.detach();
+ },
+
+ __proto__: WebInspector.SourceFrame.prototype
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
new file mode 100644
index 00000000000..80b97689bed
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) IBM Corp. 2009 All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of IBM Corp. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.SidebarPane}
+ */
+WebInspector.WatchExpressionsSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Watch Expressions"));
+
+ this.section = new WebInspector.WatchExpressionsSection();
+ this.bodyElement.appendChild(this.section.element);
+
+ var refreshButton = document.createElement("button");
+ refreshButton.className = "pane-title-button refresh";
+ refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
+ refreshButton.title = WebInspector.UIString("Refresh");
+ this.titleElement.appendChild(refreshButton);
+
+ var addButton = document.createElement("button");
+ addButton.className = "pane-title-button add";
+ addButton.addEventListener("click", this._addButtonClicked.bind(this), false);
+ this.titleElement.appendChild(addButton);
+ addButton.title = WebInspector.UIString("Add watch expression");
+
+ this._requiresUpdate = true;
+ WebInspector.context.addFlavorChangeListener(WebInspector.ExecutionContext ,this.refreshExpressions, this);
+}
+
+WebInspector.WatchExpressionsSidebarPane.prototype = {
+ wasShown: function()
+ {
+ this._refreshExpressionsIfNeeded();
+ },
+
+ refreshExpressions: function()
+ {
+ this._requiresUpdate = true;
+ this._refreshExpressionsIfNeeded();
+ },
+
+ addExpression: function(expression)
+ {
+ this.section.addExpression(expression);
+ this.expand();
+ },
+
+ _refreshExpressionsIfNeeded: function()
+ {
+ if (this._requiresUpdate && this.isShowing()) {
+ this.section.update();
+ delete this._requiresUpdate;
+ } else
+ this._requiresUpdate = true;
+ },
+
+ _addButtonClicked: function(event)
+ {
+ event.consume();
+ this.expand();
+ this.section.addNewExpressionAndEdit();
+ },
+
+ _refreshButtonClicked: function(event)
+ {
+ event.consume();
+ this.refreshExpressions();
+ },
+
+ __proto__: WebInspector.SidebarPane.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.ObjectPropertiesSection}
+ */
+WebInspector.WatchExpressionsSection = function()
+{
+ this._watchObjectGroupId = "watch-group";
+
+ WebInspector.ObjectPropertiesSection.call(this, WebInspector.runtimeModel.createRemoteObjectFromPrimitiveValue(""));
+
+ this.treeElementConstructor = WebInspector.WatchedPropertyTreeElement;
+ this._expandedExpressions = {};
+ this._expandedProperties = {};
+
+ this.emptyElement = document.createElement("div");
+ this.emptyElement.className = "info";
+ this.emptyElement.textContent = WebInspector.UIString("No Watch Expressions");
+
+ this.watchExpressions = WebInspector.settings.watchExpressions.get();
+
+ this.headerElement.className = "hidden";
+ this.editable = true;
+ this.expanded = true;
+ this.propertiesElement.classList.add("watch-expressions");
+
+ this.element.addEventListener("mousemove", this._mouseMove.bind(this), true);
+ this.element.addEventListener("mouseout", this._mouseOut.bind(this), true);
+ this.element.addEventListener("dblclick", this._sectionDoubleClick.bind(this), false);
+ this.emptyElement.addEventListener("contextmenu", this._emptyElementContextMenu.bind(this), false);
+}
+
+WebInspector.WatchExpressionsSection.NewWatchExpression = "\xA0";
+
+WebInspector.WatchExpressionsSection.prototype = {
+ /**
+ * @param {?Event=} e
+ */
+ update: function(e)
+ {
+ if (e)
+ e.consume();
+
+ /***
+ * @param {string} expression
+ * @param {number} watchIndex
+ * @param {?WebInspector.RemoteObject} result
+ * @param {boolean} wasThrown
+ * @this {WebInspector.WatchExpressionsSection}
+ */
+ function appendResult(expression, watchIndex, result, wasThrown)
+ {
+ if (!result)
+ return;
+
+ var property = new WebInspector.RemoteObjectProperty(expression, result);
+ property.watchIndex = watchIndex;
+ property.wasThrown = wasThrown;
+
+ // To clarify what's going on here:
+ // In the outer function, we calculate the number of properties
+ // that we're going to be updating, and set that in the
+ // propertyCount variable.
+ // In this function, we test to see when we are processing the
+ // last property, and then call the superclass's updateProperties()
+ // method to get all the properties refreshed at once.
+ properties.push(property);
+
+ if (properties.length == propertyCount) {
+ this.updateProperties(properties, [], WebInspector.WatchExpressionTreeElement, WebInspector.WatchExpressionsSection.CompareProperties);
+
+ // check to see if we just added a new watch expression,
+ // which will always be the last property
+ if (this._newExpressionAdded) {
+ delete this._newExpressionAdded;
+
+ var treeElement = this.findAddedTreeElement();
+ if (treeElement)
+ treeElement.startEditing();
+ }
+
+ // Force displaying delete button for hovered element.
+ if (this._lastMouseMovePageY)
+ this._updateHoveredElement(this._lastMouseMovePageY);
+ }
+ }
+
+ // TODO: pass exact injected script id.
+ WebInspector.targetManager.targets().forEach(function(target) {target.runtimeAgent().releaseObjectGroup(this._watchObjectGroupId)}, this);
+ var properties = [];
+
+ // Count the properties, so we known when to call this.updateProperties()
+ // in appendResult()
+ var propertyCount = 0;
+ for (var i = 0; i < this.watchExpressions.length; ++i) {
+ if (!this.watchExpressions[i])
+ continue;
+ ++propertyCount;
+ }
+
+ // Now process all the expressions, since we have the actual count,
+ // which is checked in the appendResult inner function.
+ var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
+ if (currentExecutionContext) {
+ for (var i = 0; i < this.watchExpressions.length; ++i) {
+ var expression = this.watchExpressions[i];
+ if (!expression)
+ continue;
+
+ currentExecutionContext.evaluate(expression, this._watchObjectGroupId, false, true, false, false, appendResult.bind(this, expression, i));
+ }
+ }
+
+ if (!propertyCount) {
+ if (!this.emptyElement.parentNode)
+ this.element.appendChild(this.emptyElement);
+ } else {
+ if (this.emptyElement.parentNode)
+ this.element.removeChild(this.emptyElement);
+ }
+
+ // note this is setting the expansion of the tree, not the section;
+ // with no expressions, and expanded tree, we get some extra vertical
+ // white space
+ this.expanded = (propertyCount != 0);
+ },
+
+ addExpression: function(expression)
+ {
+ this.watchExpressions.push(expression);
+ this.saveExpressions();
+ this.update();
+ },
+
+ addNewExpressionAndEdit: function()
+ {
+ this._newExpressionAdded = true;
+ this.watchExpressions.push(WebInspector.WatchExpressionsSection.NewWatchExpression);
+ this.update();
+ },
+
+ _sectionDoubleClick: function(event)
+ {
+ if (event.target !== this.element && event.target !== this.propertiesElement && event.target !== this.emptyElement)
+ return;
+ event.consume();
+ this.addNewExpressionAndEdit();
+ },
+
+ updateExpression: function(element, value)
+ {
+ if (value === null) {
+ var index = element.property.watchIndex;
+ this.watchExpressions.splice(index, 1);
+ }
+ else
+ this.watchExpressions[element.property.watchIndex] = value;
+ this.saveExpressions();
+ this.update();
+ },
+
+ _deleteAllExpressions: function()
+ {
+ this.watchExpressions = [];
+ this.saveExpressions();
+ this.update();
+ },
+
+ /**
+ * @return {?TreeElement}
+ */
+ findAddedTreeElement: function()
+ {
+ var children = this.propertiesTreeOutline.children;
+ for (var i = 0; i < children.length; ++i) {
+ if (children[i].property.name === WebInspector.WatchExpressionsSection.NewWatchExpression)
+ return children[i];
+ }
+ return null;
+ },
+
+ /**
+ * @return {number}
+ */
+ saveExpressions: function()
+ {
+ var toSave = [];
+ for (var i = 0; i < this.watchExpressions.length; i++)
+ if (this.watchExpressions[i])
+ toSave.push(this.watchExpressions[i]);
+
+ WebInspector.settings.watchExpressions.set(toSave);
+ return toSave.length;
+ },
+
+ _mouseMove: function(e)
+ {
+ if (this.propertiesElement.firstChild)
+ this._updateHoveredElement(e.pageY);
+ },
+
+ _mouseOut: function()
+ {
+ if (this._hoveredElement) {
+ this._hoveredElement.classList.remove("hovered");
+ delete this._hoveredElement;
+ }
+ delete this._lastMouseMovePageY;
+ },
+
+ _updateHoveredElement: function(pageY)
+ {
+ var candidateElement = this.propertiesElement.firstChild;
+ while (true) {
+ var next = candidateElement.nextSibling;
+ while (next && !next.clientHeight)
+ next = next.nextSibling;
+ if (!next || next.totalOffsetTop() > pageY)
+ break;
+ candidateElement = next;
+ }
+
+ if (this._hoveredElement !== candidateElement) {
+ if (this._hoveredElement)
+ this._hoveredElement.classList.remove("hovered");
+ if (candidateElement)
+ candidateElement.classList.add("hovered");
+ this._hoveredElement = candidateElement;
+ }
+
+ this._lastMouseMovePageY = pageY;
+ },
+
+ _emptyElementContextMenu: function(event)
+ {
+ var contextMenu = new WebInspector.ContextMenu(event);
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add watch expression" : "Add Watch Expression"), this.addNewExpressionAndEdit.bind(this));
+ contextMenu.show();
+ },
+
+ __proto__: WebInspector.ObjectPropertiesSection.prototype
+}
+
+/**
+ * @param {!WebInspector.RemoteObjectProperty} propertyA
+ * @param {!WebInspector.RemoteObjectProperty} propertyB
+ * @return {number}
+ */
+WebInspector.WatchExpressionsSection.CompareProperties = function(propertyA, propertyB)
+{
+ if (propertyA.watchIndex == propertyB.watchIndex)
+ return 0;
+ else if (propertyA.watchIndex < propertyB.watchIndex)
+ return -1;
+ else
+ return 1;
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.ObjectPropertyTreeElement}
+ * @param {!WebInspector.RemoteObjectProperty} property
+ */
+WebInspector.WatchExpressionTreeElement = function(property)
+{
+ WebInspector.ObjectPropertyTreeElement.call(this, property);
+}
+
+WebInspector.WatchExpressionTreeElement.prototype = {
+ onexpand: function()
+ {
+ WebInspector.ObjectPropertyTreeElement.prototype.onexpand.call(this);
+ this.treeOutline.section._expandedExpressions[this._expression()] = true;
+ },
+
+ oncollapse: function()
+ {
+ WebInspector.ObjectPropertyTreeElement.prototype.oncollapse.call(this);
+ delete this.treeOutline.section._expandedExpressions[this._expression()];
+ },
+
+ onattach: function()
+ {
+ WebInspector.ObjectPropertyTreeElement.prototype.onattach.call(this);
+ if (this.treeOutline.section._expandedExpressions[this._expression()])
+ this.expanded = true;
+ },
+
+ _expression: function()
+ {
+ return this.property.name;
+ },
+
+ update: function()
+ {
+ WebInspector.ObjectPropertyTreeElement.prototype.update.call(this);
+
+ if (this.property.wasThrown) {
+ this.valueElement.textContent = WebInspector.UIString("<not available>");
+ this.listItemElement.classList.add("dimmed");
+ } else
+ this.listItemElement.classList.remove("dimmed");
+
+ var deleteButton = document.createElement("input");
+ deleteButton.type = "button";
+ deleteButton.title = WebInspector.UIString("Delete watch expression.");
+ deleteButton.classList.add("enabled-button");
+ deleteButton.classList.add("delete-button");
+ deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
+ this.listItemElement.addEventListener("contextmenu", this._contextMenu.bind(this), false);
+ this.listItemElement.insertBefore(deleteButton, this.listItemElement.firstChild);
+ },
+
+ /**
+ * @param {!WebInspector.ContextMenu} contextMenu
+ * @override
+ */
+ populateContextMenu: function(contextMenu)
+ {
+ if (!this.isEditing()) {
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add watch expression" : "Add Watch Expression"), this.treeOutline.section.addNewExpressionAndEdit.bind(this.treeOutline.section));
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Delete watch expression" : "Delete Watch Expression"), this._deleteButtonClicked.bind(this));
+ }
+ if (this.treeOutline.section.watchExpressions.length > 1)
+ contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Delete all watch expressions" : "Delete All Watch Expressions"), this._deleteAllButtonClicked.bind(this));
+ },
+
+ _contextMenu: function(event)
+ {
+ var contextMenu = new WebInspector.ContextMenu(event);
+ this.populateContextMenu(contextMenu);
+ contextMenu.show();
+ },
+
+ _deleteAllButtonClicked: function()
+ {
+ this.treeOutline.section._deleteAllExpressions();
+ },
+
+ _deleteButtonClicked: function()
+ {
+ this.treeOutline.section.updateExpression(this, null);
+ },
+
+ /**
+ * @return {boolean}
+ */
+ renderPromptAsBlock: function()
+ {
+ return true;
+ },
+
+ /**
+ * @override
+ * @return {{element: !Element, value: (string|undefined)}}
+ */
+ elementAndValueToEdit: function()
+ {
+ return { element: this.nameElement, value: this.property.name.trim() };
+ },
+
+ /**
+ * @override
+ */
+ editingCancelled: function(element, context)
+ {
+ if (!context.elementToEdit.textContent)
+ this.treeOutline.section.updateExpression(this, null);
+
+ WebInspector.ObjectPropertyTreeElement.prototype.editingCancelled.call(this, element, context);
+ },
+
+ /**
+ * @override
+ * @param {string} expression
+ */
+ applyExpression: function(expression)
+ {
+ expression = expression.trim();
+ this.property.name = expression || null;
+ this.treeOutline.section.updateExpression(this, expression);
+ },
+
+ __proto__: WebInspector.ObjectPropertyTreeElement.prototype
+}
+
+
+/**
+ * @constructor
+ * @extends {WebInspector.ObjectPropertyTreeElement}
+ * @param {!WebInspector.RemoteObjectProperty} property
+ */
+WebInspector.WatchedPropertyTreeElement = function(property)
+{
+ WebInspector.ObjectPropertyTreeElement.call(this, property);
+}
+
+WebInspector.WatchedPropertyTreeElement.prototype = {
+ onattach: function()
+ {
+ WebInspector.ObjectPropertyTreeElement.prototype.onattach.call(this);
+ if (this.hasChildren && this.propertyPath() in this.treeOutline.section._expandedProperties)
+ this.expand();
+ },
+
+ onexpand: function()
+ {
+ WebInspector.ObjectPropertyTreeElement.prototype.onexpand.call(this);
+ this.treeOutline.section._expandedProperties[this.propertyPath()] = true;
+ },
+
+ oncollapse: function()
+ {
+ WebInspector.ObjectPropertyTreeElement.prototype.oncollapse.call(this);
+ delete this.treeOutline.section._expandedProperties[this.propertyPath()];
+ },
+
+ __proto__: WebInspector.ObjectPropertyTreeElement.prototype
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/WorkersSidebarPane.js b/chromium/third_party/WebKit/Source/devtools/front_end/sources/WorkersSidebarPane.js
new file mode 100644
index 00000000000..73eb9b30df7
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/WorkersSidebarPane.js
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ * @extends {WebInspector.SidebarPane}
+ */
+WebInspector.WorkersSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Workers"));
+
+ this._enableWorkersCheckbox = new WebInspector.Checkbox(
+ WebInspector.UIString("Pause on start"),
+ "sidebar-label",
+ WebInspector.UIString("Automatically attach to new workers and pause them. Enabling this option will force opening inspector for all new workers."));
+ this._enableWorkersCheckbox.element.id = "pause-workers-checkbox";
+ this.bodyElement.appendChild(this._enableWorkersCheckbox.element);
+ this._enableWorkersCheckbox.addEventListener(this._autoattachToWorkersClicked.bind(this));
+ this._enableWorkersCheckbox.checked = false;
+
+ var note = this.bodyElement.createChild("div");
+ note.id = "shared-workers-list";
+ note.classList.add("sidebar-label")
+ note.textContent = WebInspector.UIString("Shared workers can be inspected in the Task Manager");
+
+ var separator = this.bodyElement.createChild("div", "sidebar-separator");
+ separator.textContent = WebInspector.UIString("Dedicated worker inspectors");
+
+ this._workerListElement = document.createElement("ol");
+ this._workerListElement.tabIndex = 0;
+ this._workerListElement.classList.add("properties-tree");
+ this._workerListElement.classList.add("sidebar-label");
+ this.bodyElement.appendChild(this._workerListElement);
+
+ this._idToWorkerItem = {};
+
+ var threadList = WebInspector.workerManager.threadsList();
+ for (var i = 0; i < threadList.length; ++i) {
+ var threadId = threadList[i];
+ if (threadId === WebInspector.WorkerManager.MainThreadId)
+ continue;
+
+ this._addWorker(threadId, WebInspector.workerManager.threadUrl(threadId));
+ }
+
+ WebInspector.workerManager.addEventListener(WebInspector.WorkerManager.Events.WorkerAdded, this._workerAdded, this);
+ WebInspector.workerManager.addEventListener(WebInspector.WorkerManager.Events.WorkerRemoved, this._workerRemoved, this);
+ WebInspector.workerManager.addEventListener(WebInspector.WorkerManager.Events.WorkersCleared, this._workersCleared, this);
+}
+
+WebInspector.WorkersSidebarPane.prototype = {
+ _workerAdded: function(event)
+ {
+ this._addWorker(event.data.workerId, event.data.url);
+ },
+
+ _workerRemoved: function(event)
+ {
+ this._idToWorkerItem[event.data].remove();
+ delete this._idToWorkerItem[event.data];
+ },
+
+ _workersCleared: function(event)
+ {
+ this._idToWorkerItem = {};
+ this._workerListElement.removeChildren();
+ },
+
+ _addWorker: function(workerId, url)
+ {
+ var item = this._workerListElement.createChild("div", "dedicated-worker-item");
+ var link = item.createChild("a");
+ link.textContent = url;
+ link.href = "#";
+ link.target = "_blank";
+ link.addEventListener("click", this._workerItemClicked.bind(this, workerId), true);
+ this._idToWorkerItem[workerId] = item;
+ },
+
+ _workerItemClicked: function(workerId, event)
+ {
+ event.consume(true);
+ WebInspector.workerFrontendManager.openWorkerInspector(workerId);
+ },
+
+ _autoattachToWorkersClicked: function(event)
+ {
+ WorkerAgent.setAutoconnectToWorkers(this._enableWorkersCheckbox.checked);
+ },
+
+ __proto__: WebInspector.SidebarPane.prototype
+}
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sources/module.json b/chromium/third_party/WebKit/Source/devtools/front_end/sources/module.json
new file mode 100644
index 00000000000..81fd9276f85
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sources/module.json
@@ -0,0 +1,173 @@
+{
+ "extensions": [
+ {
+ "type": "@WebInspector.Panel",
+ "name": "sources",
+ "title": "Sources",
+ "order": 2,
+ "className": "WebInspector.SourcesPanel"
+ },
+ {
+ "type": "@WebInspector.ContextMenu.Provider",
+ "contextTypes": ["WebInspector.UISourceCode", "WebInspector.RemoteObject"],
+ "className": "WebInspector.SourcesPanel.ContextMenuProvider"
+ },
+ {
+ "type": "@WebInspector.ActionDelegate",
+ "actionId": "debugger.toggle-pause",
+ "className": "WebInspector.SourcesPanel.TogglePauseActionDelegate",
+ "contextTypes": ["WebInspector.SourcesPanel", "WebInspector.ShortcutRegistry.ForwardedShortcut"],
+ "bindings": [
+ {
+ "platform": "windows,linux",
+ "shortcut": "F8 Ctrl+\\"
+ },
+ {
+ "platform": "mac",
+ "shortcut": "F8 Meta+\\"
+ }
+ ]
+ },
+ {
+ "type": "@WebInspector.SearchScope",
+ "className": "WebInspector.SourcesSearchScope"
+ },
+ {
+ "type": "@WebInspector.DrawerEditor",
+ "className": "WebInspector.SourcesPanel.DrawerEditor"
+ },
+ {
+ "type": "@WebInspector.Revealer",
+ "contextTypes": ["WebInspector.UILocation"],
+ "className": "WebInspector.SourcesPanel.UILocationRevealer"
+ },
+ {
+ "type": "@WebInspector.Revealer",
+ "contextTypes": ["WebInspector.UISourceCode"],
+ "className": "WebInspector.SourcesPanel.UISourceCodeRevealer"
+ },
+ {
+ "type": "@WebInspector.SourcesView.EditorAction",
+ "className": "WebInspector.InplaceFormatterEditorAction"
+ },
+ {
+ "type": "@WebInspector.SourcesView.EditorAction",
+ "className": "WebInspector.ScriptFormatterEditorAction"
+ },
+ {
+ "type": "navigator-view",
+ "name": "sources",
+ "title": "Sources",
+ "order": 1,
+ "className": "WebInspector.SourcesNavigatorView"
+ },
+ {
+ "type": "navigator-view",
+ "name": "contentScripts",
+ "title": "Content scripts",
+ "order": 2,
+ "className": "WebInspector.ContentScriptsNavigatorView"
+ },
+ {
+ "type": "navigator-view",
+ "name": "snippets",
+ "title": "Snippets",
+ "order": 3,
+ "className": "WebInspector.SnippetsNavigatorView"
+ },
+ {
+ "type": "@WebInspector.ActionDelegate",
+ "actionId": "sources.go-to-source",
+ "className": "WebInspector.SourcesPanel.ShowGoToSourceDialogActionDelegate",
+ "bindings": [
+ {
+ "platform": "mac",
+ "shortcut": "Meta+O Meta+P"
+ },
+ {
+ "platform": "windows,linux",
+ "shortcut": "Ctrl+O Ctrl+P"
+ }
+ ]
+ },
+ {
+ "type": "ui-setting",
+ "settingName": "javaScriptDisabled",
+ "settingType": "custom",
+ "className": "WebInspector.SourcesPanel.DisableJavaScriptSettingDelegate"
+ },
+ {
+ "type": "ui-setting",
+ "section": "Sources",
+ "title": "Search in content scripts",
+ "settingName": "searchInContentScripts",
+ "settingType": "checkbox"
+ },
+ {
+ "type": "ui-setting",
+ "section": "Sources",
+ "title": "Enable JavaScript source maps",
+ "settingName": "jsSourceMapsEnabled",
+ "settingType": "checkbox"
+ },
+ {
+ "type": "ui-setting",
+ "section": "Sources",
+ "title": "Detect indentation",
+ "settingName": "textEditorAutoDetectIndent",
+ "settingType": "checkbox"
+ },
+ {
+ "type": "ui-setting",
+ "section": "Sources",
+ "title": "Autocompletion",
+ "settingName": "textEditorAutocompletion",
+ "settingType": "checkbox"
+ },
+ {
+ "type": "ui-setting",
+ "section": "Sources",
+ "title": "Bracket matching",
+ "settingName": "textEditorBracketMatching",
+ "settingType": "checkbox"
+ },
+ {
+ "type": "ui-setting",
+ "section": "Sources",
+ "title": "Show whitespace characters",
+ "settingName": "showWhitespacesInEditor",
+ "settingType": "checkbox"
+ },
+ {
+ "type": "ui-setting",
+ "section": "Sources",
+ "title": "Enable CSS source maps",
+ "settingName": "cssSourceMapsEnabled",
+ "settingType": "checkbox"
+ },
+ {
+ "type": "ui-setting",
+ "title": "Auto-reload generated CSS",
+ "parentSettingName": "cssSourceMapsEnabled",
+ "settingName": "cssReloadEnabled",
+ "settingType": "checkbox"
+ },
+ {
+ "type": "ui-setting",
+ "section": "Sources",
+ "experiment": "frameworksDebuggingSupport",
+ "title": "Skip stepping through sources with particular names",
+ "settingName": "skipStackFramesSwitch",
+ "settingType": "checkbox"
+ },
+ {
+ "type": "ui-setting",
+ "experiment": "frameworksDebuggingSupport",
+ "parentSettingName": "skipStackFramesSwitch",
+ "settingType": "custom",
+ "className": "WebInspector.SourcesPanel.SkipStackFramePatternSettingDelegate"
+ }
+ ],
+ "dependencies": [ "source_frame" ],
+ "scripts": [ "SourcesPanel.js" ]
+}