You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pm...@apache.org on 2012/02/15 18:42:37 UTC

[18/51] [partial] Apache-ization, port to node.js

http://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre/blob/c4fbd3d0/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkPanel.js
----------------------------------------------------------------------
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkPanel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkPanel.js
new file mode 100644
index 0000000..085f468
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkPanel.js
@@ -0,0 +1,1742 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2008, 2009 Anthony Ricaud <ri...@webkit.org>
+ * 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 APPLE 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.
+ */
+
+WebInspector.NetworkPanel = function()
+{
+    WebInspector.Panel.call(this, "network");
+
+    this.createSidebar();
+    this.sidebarElement.className = "network-sidebar";
+
+    this._resources = [];
+    this._resourcesById = {};
+    this._resourcesByURL = {};
+    this._staleResources = [];
+    this._resourceGridNodes = {};
+    this._mainResourceLoadTime = -1;
+    this._mainResourceDOMContentTime = -1;
+    this._hiddenCategories = {};
+
+    this._categories = WebInspector.resourceCategories;
+
+    this.containerElement = document.createElement("div");
+    this.containerElement.id = "network-container";
+    this.sidebarElement.appendChild(this.containerElement);
+
+    this._viewsContainerElement = document.createElement("div");
+    this._viewsContainerElement.id = "network-views";
+    this._viewsContainerElement.className = "hidden";
+    this.element.appendChild(this._viewsContainerElement);
+
+    this._closeButtonElement = document.createElement("button");
+    this._closeButtonElement.id = "network-close-button";
+    this._closeButtonElement.addEventListener("click", this._toggleGridMode.bind(this), false);
+    this._viewsContainerElement.appendChild(this._closeButtonElement);
+
+    this._createSortingFunctions();
+    this._createTable();
+    this._createTimelineGrid();
+    this._createStatusbarButtons();
+    this._createFilterStatusBarItems();
+    this._createSummaryBar();
+
+    if (!WebInspector.settings.resourcesLargeRows)
+        this._setLargerResources(WebInspector.settings.resourcesLargeRows);
+
+    this._popoverHelper = new WebInspector.PopoverHelper(this.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this), true);
+    // Enable faster hint.
+    this._popoverHelper.setTimeout(100);
+
+    this.calculator = new WebInspector.NetworkTransferTimeCalculator();
+    this._filter(this._filterAllElement, false);
+
+    this._toggleGridMode();
+
+    WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this);
+    WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdated, this._onResourceUpdated, this);
+    WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceUpdated, this);
+    WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.MainResourceCommitLoad, this._onMainResourceCommitLoad, this);
+}
+
+WebInspector.NetworkPanel.prototype = {
+    get toolbarItemLabel()
+    {
+        return WebInspector.UIString("Network");
+    },
+
+    get statusBarItems()
+    {
+        return [this._largerResourcesButton.element, this._preserveLogToggle.element, this._clearButton.element, this._filterBarElement];
+    },
+
+    isCategoryVisible: function(categoryName)
+    {
+        return true;
+    },
+
+    elementsToRestoreScrollPositionsFor: function()
+    {
+        return [this.containerElement, this._dataGrid.scrollContainer];
+    },
+
+    resize: function()
+    {
+        WebInspector.Panel.prototype.resize.call(this);
+        this._dataGrid.updateWidths();
+        this._positionSummaryBar();
+    },
+
+    updateSidebarWidth: function(width)
+    {
+        if (!this._viewingResourceMode)
+            return;
+        WebInspector.Panel.prototype.updateSidebarWidth.call(this, width);
+    },
+
+    updateMainViewWidth: function(width)
+    {
+        this._viewsContainerElement.style.left = width + "px";
+    },
+
+    handleShortcut: function(event)
+    {
+        if (this._viewingResourceMode && event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
+            this._toggleGridMode();
+            event.handled = true;
+        }
+    },
+
+    _positionSummaryBar: function()
+    {
+        // Position the total bar.
+
+        var fillerRow = this._dataGrid.dataTableBody.lastChild;
+        if (this._summaryBarElement.parentElement !== this.element && fillerRow.offsetHeight > 0) {
+            // Glue status to bottom.
+            if (this._summaryBarRowNode) {
+                this._dataGrid.removeChild(this._summaryBarRowNode);
+                delete this._summaryBarRowNode;
+            }
+            this._summaryBarElement.addStyleClass("network-summary-bar-bottom");
+            this.element.appendChild(this._summaryBarElement);
+            this._dataGrid.element.style.bottom = "20px";
+            return;
+        }
+
+        if (!this._summaryBarRowNode && !fillerRow.offsetHeight) {
+            // Glue status to table.
+            this._summaryBarRowNode = new WebInspector.NetworkTotalGridNode(this._summaryBarElement);
+            this._summaryBarElement.removeStyleClass("network-summary-bar-bottom");
+            this._dataGrid.appendChild(this._summaryBarRowNode);
+            this._dataGrid.element.style.bottom = 0;
+            this._sortItems();
+        }
+        this._updateOffscreenRows();
+    },
+
+    _resetSummaryBar: function()
+    {
+        delete this._summaryBarRowNode;
+        this._summaryBarElement.parentElement.removeChild(this._summaryBarElement);
+        this._updateSummaryBar();
+    },
+
+    _createTimelineGrid: function()
+    {
+        this._timelineGrid = new WebInspector.TimelineGrid();
+        this._timelineGrid.element.addStyleClass("network-timeline-grid");
+        this._dataGrid.element.appendChild(this._timelineGrid.element);
+    },
+
+    _createTable: function()
+    {
+        var columns = {name: {}, method: {}, status: {}, type: {}, size: {}, time: {}, timeline: {}};
+        columns.name.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Name"), WebInspector.UIString("Path"));
+        columns.name.sortable = true;
+        columns.name.width = "20%";
+        columns.name.disclosure = true;
+
+        columns.method.title = WebInspector.UIString("Method");
+        columns.method.sortable = true;
+        columns.method.width = "7%";
+
+        columns.status.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Status"), WebInspector.UIString("Text"));
+        columns.status.sortable = true;
+        columns.status.width = "8%";
+
+        columns.type.title = WebInspector.UIString("Type");
+        columns.type.sortable = true;
+        columns.type.width = "10%";
+
+        columns.size.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Size"), WebInspector.UIString("Transfer"));
+        columns.size.sortable = true;
+        columns.size.width = "10%";
+        columns.size.aligned = "right";
+
+        columns.time.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Time"), WebInspector.UIString("Latency"));
+        columns.time.sortable = true;
+        columns.time.width = "10%";
+        columns.time.aligned = "right";
+
+        columns.timeline.title = "";
+        columns.timeline.sortable = false;
+        columns.timeline.width = "37%";
+        columns.timeline.sort = "ascending";
+
+        this._dataGrid = new WebInspector.DataGrid(columns);
+        this._dataGrid.element.addEventListener("contextmenu", this._contextMenu.bind(this), true);
+        this.containerElement.appendChild(this._dataGrid.element);
+        this._dataGrid.addEventListener("sorting changed", this._sortItems, this);
+        this._dataGrid.addEventListener("width changed", this._updateDividersIfNeeded, this);
+        this._dataGrid.scrollContainer.addEventListener("scroll", this._updateOffscreenRows.bind(this));
+
+        this._patchTimelineHeader();
+    },
+
+    _makeHeaderFragment: function(title, subtitle)
+    {
+        var fragment = document.createDocumentFragment();
+        fragment.appendChild(document.createTextNode(title));
+        var subtitleDiv = document.createElement("div");
+        subtitleDiv.className = "network-header-subtitle";
+        subtitleDiv.textContent = subtitle;
+        fragment.appendChild(subtitleDiv);
+        return fragment;
+    },
+
+    _patchTimelineHeader: function()
+    {
+        var timelineSorting = document.createElement("select");
+
+        var option = document.createElement("option");
+        option.value = "startTime";
+        option.label = WebInspector.UIString("Timeline");
+        timelineSorting.appendChild(option);
+
+        option = document.createElement("option");
+        option.value = "startTime";
+        option.label = WebInspector.UIString("Start Time");
+        timelineSorting.appendChild(option);
+
+        option = document.createElement("option");
+        option.value = "responseTime";
+        option.label = WebInspector.UIString("Response Time");
+        timelineSorting.appendChild(option);
+
+        option = document.createElement("option");
+        option.value = "endTime";
+        option.label = WebInspector.UIString("End Time");
+        timelineSorting.appendChild(option);
+
+        option = document.createElement("option");
+        option.value = "duration";
+        option.label = WebInspector.UIString("Duration");
+        timelineSorting.appendChild(option);
+
+        option = document.createElement("option");
+        option.value = "latency";
+        option.label = WebInspector.UIString("Latency");
+        timelineSorting.appendChild(option);
+
+        var header = this._dataGrid.headerTableHeader("timeline");
+        header.replaceChild(timelineSorting, header.firstChild);
+
+        timelineSorting.addEventListener("click", function(event) { event.stopPropagation() }, false);
+        timelineSorting.addEventListener("change", this._sortByTimeline.bind(this), false);
+        this._timelineSortSelector = timelineSorting;
+    },
+
+    _createSortingFunctions: function()
+    {
+        this._sortingFunctions = {};
+        this._sortingFunctions.name = WebInspector.NetworkDataGridNode.NameComparator;
+        this._sortingFunctions.method = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "method", false);
+        this._sortingFunctions.status = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "statusCode", false);
+        this._sortingFunctions.type = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "mimeType", false);
+        this._sortingFunctions.size = WebInspector.NetworkDataGridNode.SizeComparator;
+        this._sortingFunctions.time = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "duration", false);
+        this._sortingFunctions.timeline = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "startTime", false);
+        this._sortingFunctions.startTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "startTime", false);
+        this._sortingFunctions.endTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "endTime", false);
+        this._sortingFunctions.responseTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "responseReceivedTime", false);
+        this._sortingFunctions.duration = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "duration", true);
+        this._sortingFunctions.latency = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "latency", true);
+
+        var timeCalculator = new WebInspector.NetworkTransferTimeCalculator();
+        var durationCalculator = new WebInspector.NetworkTransferDurationCalculator();
+
+        this._calculators = {};
+        this._calculators.timeline = timeCalculator;
+        this._calculators.startTime = timeCalculator;
+        this._calculators.endTime = timeCalculator;
+        this._calculators.responseTime = timeCalculator;
+        this._calculators.duration = durationCalculator;
+        this._calculators.latency = durationCalculator;
+    },
+
+    _sortItems: function()
+    {
+        var columnIdentifier = this._dataGrid.sortColumnIdentifier;
+        if (columnIdentifier === "timeline") {
+            this._sortByTimeline();
+            return;
+        }
+        var sortingFunction = this._sortingFunctions[columnIdentifier];
+        if (!sortingFunction)
+            return;
+
+        this._dataGrid.sortNodes(sortingFunction, this._dataGrid.sortOrder === "descending");
+        this._timelineSortSelector.selectedIndex = 0;
+        this._updateOffscreenRows();
+    },
+
+    _sortByTimeline: function()
+    {
+        var selectedIndex = this._timelineSortSelector.selectedIndex;
+        if (!selectedIndex)
+            selectedIndex = 1; // Sort by start time by default.
+        var selectedOption = this._timelineSortSelector[selectedIndex];
+        var value = selectedOption.value;
+
+        var sortingFunction = this._sortingFunctions[value];
+        this._dataGrid.sortNodes(sortingFunction);
+        this.calculator = this._calculators[value];
+        if (this.calculator.startAtZero)
+            this._timelineGrid.hideEventDividers();
+        else
+            this._timelineGrid.showEventDividers();
+        this._dataGrid.markColumnAsSortedBy("timeline", "ascending");
+        this._updateOffscreenRows();
+    },
+
+    _createFilterStatusBarItems: function()
+    {
+        var filterBarElement = document.createElement("div");
+        filterBarElement.className = "scope-bar status-bar-item";
+        filterBarElement.id = "network-filter";
+
+        function createFilterElement(category, label)
+        {
+            var categoryElement = document.createElement("li");
+            categoryElement.category = category;
+            categoryElement.className = category;
+            categoryElement.appendChild(document.createTextNode(label));
+            categoryElement.addEventListener("click", this._updateFilter.bind(this), false);
+            filterBarElement.appendChild(categoryElement);
+
+            return categoryElement;
+        }
+
+        this._filterAllElement = createFilterElement.call(this, "all", WebInspector.UIString("All"));
+
+        // Add a divider
+        var dividerElement = document.createElement("div");
+        dividerElement.addStyleClass("scope-bar-divider");
+        filterBarElement.appendChild(dividerElement);
+
+        for (var category in this._categories)
+            createFilterElement.call(this, category, this._categories[category].title);
+        this._filterBarElement = filterBarElement;
+    },
+
+    _createSummaryBar: function()
+    {
+        this._summaryBarElement = document.createElement("div");
+        this._summaryBarElement.className = "network-summary-bar";
+        this.containerElement.appendChild(this._summaryBarElement);
+    },
+
+    _updateSummaryBar: function()
+    {
+        this._positionSummaryBar(); // Grid is growing.
+        var numRequests = this._resources.length;
+
+        if (!numRequests) {
+            if (this._summaryBarElement._isDisplayingWarning)
+                return;
+            this._summaryBarElement._isDisplayingWarning = true;
+
+            var img = document.createElement("img");
+            img.src = "Images/warningIcon.png";
+            this._summaryBarElement.removeChildren();
+            this._summaryBarElement.appendChild(img);
+            this._summaryBarElement.appendChild(document.createTextNode(" "));
+            this._summaryBarElement.appendChild(document.createTextNode(
+                WebInspector.UIString("No requests captured. Reload the page to see detailed information on the network activity.")));
+            return;
+        }
+        delete this._summaryBarElement._isDisplayingWarning;
+
+        var transferSize = 0;
+        var baseTime = -1;
+        var maxTime = -1;
+        for (var i = 0; i < this._resources.length; ++i) {
+            var resource = this._resources[i];
+            transferSize += (resource.cached || !resource.transferSize) ? 0 : resource.transferSize;
+            if (resource.isMainResource)
+                baseTime = resource.startTime;
+            if (resource.endTime > maxTime)
+                maxTime = resource.endTime;
+        }
+        var text = String.sprintf(WebInspector.UIString("%d requests"), numRequests);
+        text += "  \u2758  " + String.sprintf(WebInspector.UIString("%s transferred"), Number.bytesToString(transferSize));
+        if (baseTime !== -1 && this._mainResourceLoadTime !== -1 && this._mainResourceDOMContentTime !== -1 && this._mainResourceDOMContentTime > baseTime) {
+            text += "  \u2758  " + String.sprintf(WebInspector.UIString("%s (onload: %s, DOMContentLoaded: %s)"),
+                        Number.secondsToString(maxTime - baseTime),
+                        Number.secondsToString(this._mainResourceLoadTime - baseTime),
+                        Number.secondsToString(this._mainResourceDOMContentTime - baseTime));
+        }
+        this._summaryBarElement.textContent = text;
+    },
+
+    _showCategory: function(category)
+    {
+        this._dataGrid.element.addStyleClass("filter-" + category);
+        delete this._hiddenCategories[category];
+    },
+
+    _hideCategory: function(category)
+    {
+        this._dataGrid.element.removeStyleClass("filter-" + category);
+        this._hiddenCategories[category] = true;
+    },
+
+    _updateFilter: function(e)
+    {
+        var isMac = WebInspector.isMac();
+        var selectMultiple = false;
+        if (isMac && e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey)
+            selectMultiple = true;
+        if (!isMac && e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey)
+            selectMultiple = true;
+
+        this._filter(e.target, selectMultiple);
+        this._positionSummaryBar();
+    },
+
+    _filter: function(target, selectMultiple)
+    {
+        function unselectAll()
+        {
+            for (var i = 0; i < this._filterBarElement.childNodes.length; ++i) {
+                var child = this._filterBarElement.childNodes[i];
+                if (!child.category)
+                    continue;
+
+                child.removeStyleClass("selected");
+                this._hideCategory(child.category);
+            }
+        }
+
+        if (target.category === this._filterAllElement) {
+            if (target.hasStyleClass("selected")) {
+                // We can't unselect All, so we break early here
+                return;
+            }
+
+            // If All wasn't selected, and now is, unselect everything else.
+            unselectAll.call(this);
+        } else {
+            // Something other than All is being selected, so we want to unselect All.
+            if (this._filterAllElement.hasStyleClass("selected")) {
+                this._filterAllElement.removeStyleClass("selected");
+                this._hideCategory("all");
+            }
+        }
+
+        if (!selectMultiple) {
+            // If multiple selection is off, we want to unselect everything else
+            // and just select ourselves.
+            unselectAll.call(this);
+
+            target.addStyleClass("selected");
+            this._showCategory(target.category);
+            return;
+        }
+
+        if (target.hasStyleClass("selected")) {
+            // If selectMultiple is turned on, and we were selected, we just
+            // want to unselect ourselves.
+            target.removeStyleClass("selected");
+            this._hideCategory(target.category);
+        } else {
+            // If selectMultiple is turned on, and we weren't selected, we just
+            // want to select ourselves.
+            target.addStyleClass("selected");
+            this._showCategory(target.category);
+        }
+        this._updateOffscreenRows();
+    },
+
+    _scheduleRefresh: function()
+    {
+        if (this._needsRefresh)
+            return;
+
+        this._needsRefresh = true;
+
+        if (this.visible && !("_refreshTimeout" in this))
+            this._refreshTimeout = setTimeout(this.refresh.bind(this), 500);
+    },
+
+    _updateDividersIfNeeded: function(force)
+    {
+        var timelineColumn = this._dataGrid.columns.timeline;
+        for (var i = 0; i < this._dataGrid.resizers.length; ++i) {
+            if (timelineColumn.ordinal === this._dataGrid.resizers[i].rightNeighboringColumnID) {
+                // Position timline grid location.
+                this._timelineGrid.element.style.left = this._dataGrid.resizers[i].style.left;
+                this._timelineGrid.element.style.right = "18px";
+            }
+        }
+
+        var proceed = true;
+        if (!this.visible) {
+            this._scheduleRefresh();
+            proceed = false;
+        } else
+            proceed = this._timelineGrid.updateDividers(force, this.calculator);
+
+        if (!proceed)
+            return;
+
+        if (this.calculator.startAtZero || !this.calculator.computePercentageFromEventTime) {
+            // If our current sorting method starts at zero, that means it shows all
+            // resources starting at the same point, and so onLoad event and DOMContent
+            // event lines really wouldn't make much sense here, so don't render them.
+            // Additionally, if the calculator doesn't have the computePercentageFromEventTime
+            // function defined, we are probably sorting by size, and event times aren't relevant
+            // in this case.
+            return;
+        }
+
+        this._timelineGrid.removeEventDividers();
+        if (this._mainResourceLoadTime !== -1) {
+            var percent = this.calculator.computePercentageFromEventTime(this._mainResourceLoadTime);
+
+            var loadDivider = document.createElement("div");
+            loadDivider.className = "network-event-divider network-red-divider";
+
+            var loadDividerPadding = document.createElement("div");
+            loadDividerPadding.className = "network-event-divider-padding";
+            loadDividerPadding.title = WebInspector.UIString("Load event fired");
+            loadDividerPadding.appendChild(loadDivider);
+            loadDividerPadding.style.left = percent + "%";
+            this._timelineGrid.addEventDivider(loadDividerPadding);
+        }
+
+        if (this._mainResourceDOMContentTime !== -1) {
+            var percent = this.calculator.computePercentageFromEventTime(this._mainResourceDOMContentTime);
+
+            var domContentDivider = document.createElement("div");
+            domContentDivider.className = "network-event-divider network-blue-divider";
+
+            var domContentDividerPadding = document.createElement("div");
+            domContentDividerPadding.className = "network-event-divider-padding";
+            domContentDividerPadding.title = WebInspector.UIString("DOMContent event fired");
+            domContentDividerPadding.appendChild(domContentDivider);
+            domContentDividerPadding.style.left = percent + "%";
+            this._timelineGrid.addEventDivider(domContentDividerPadding);
+        }
+    },
+
+    _refreshIfNeeded: function()
+    {
+        if (this._needsRefresh)
+            this.refresh();
+    },
+
+    _invalidateAllItems: function()
+    {
+        this._staleResources = this._resources.slice();
+    },
+
+    get calculator()
+    {
+        return this._calculator;
+    },
+
+    set calculator(x)
+    {
+        if (!x || this._calculator === x)
+            return;
+
+        this._calculator = x;
+        this._calculator.reset();
+
+        this._invalidateAllItems();
+        this.refresh();
+    },
+
+    _resourceGridNode: function(resource)
+    {
+        return this._resourceGridNodes[resource.identifier];
+    },
+
+    revealAndSelectItem: function(resource)
+    {
+        var node = this._resourceGridNode(resource);
+        if (node) {
+            node.reveal();
+            node.select(true);
+        }
+    },
+
+    addEventDivider: function(divider)
+    {
+        this._timelineGrid.addEventDivider(divider);
+    },
+
+    _createStatusbarButtons: function()
+    {
+        this._preserveLogToggle = new WebInspector.StatusBarButton(WebInspector.UIString("Preserve Log upon Navigation"), "record-profile-status-bar-item");
+        this._preserveLogToggle.addEventListener("click", this._onPreserveLogClicked.bind(this), false);
+
+        this._clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear"), "clear-status-bar-item");
+        this._clearButton.addEventListener("click", this._reset.bind(this), false);
+
+        this._largerResourcesButton = new WebInspector.StatusBarButton(WebInspector.UIString("Use small resource rows."), "network-larger-resources-status-bar-item");
+        this._largerResourcesButton.toggled = WebInspector.settings.resourcesLargeRows;
+        this._largerResourcesButton.addEventListener("click", this._toggleLargerResources.bind(this), false);
+    },
+
+    set mainResourceLoadTime(x)
+    {
+        if (this._mainResourceLoadTime === x)
+            return;
+
+        this._mainResourceLoadTime = x || -1;
+        // Update the dividers to draw the new line
+        this._updateDividersIfNeeded(true);
+    },
+
+    set mainResourceDOMContentTime(x)
+    {
+        if (this._mainResourceDOMContentTime === x)
+            return;
+
+        this._mainResourceDOMContentTime = x || -1;
+        this._updateDividersIfNeeded(true);
+    },
+
+    show: function()
+    {
+        WebInspector.Panel.prototype.show.call(this);
+        this._refreshIfNeeded();
+
+        if (this.visibleView)
+            this.visibleView.show(this._viewsContainerElement);
+
+        this._dataGrid.updateWidths();
+        this._positionSummaryBar();
+    },
+
+    hide: function()
+    {
+        WebInspector.Panel.prototype.hide.call(this);
+        this._popoverHelper.hidePopup();
+    },
+
+    get searchableViews()
+    {
+        var views = [];
+        return views;
+    },
+
+    searchMatchFound: function(view, matches)
+    {
+        this._resourceGridNode(view.resource).searchMatches = matches;
+    },
+
+    searchCanceled: function(startingNewSearch)
+    {
+        WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch);
+
+        if (startingNewSearch || !this._resources)
+            return;
+    },
+
+    performSearch: function(query)
+    {
+        WebInspector.Panel.prototype.performSearch.call(this, query);
+    },
+
+    refresh: function()
+    {
+        this._needsRefresh = false;
+        if ("_refreshTimeout" in this) {
+            clearTimeout(this._refreshTimeout);
+            delete this._refreshTimeout;
+        }
+
+        var wasScrolledToLastRow = this._dataGrid.isScrolledToLastRow();
+        var staleItemsLength = this._staleResources.length;
+        var boundariesChanged = false;
+
+        for (var i = 0; i < staleItemsLength; ++i) {
+            var resource = this._staleResources[i];
+            var node = this._resourceGridNode(resource);
+            if (!node) {
+                // Create the timeline tree element and graph.
+                node = new WebInspector.NetworkDataGridNode(this, resource);
+                this._resourceGridNodes[resource.identifier] = node;
+                this._dataGrid.appendChild(node);
+            }
+            node.refreshResource();
+
+            if (this.calculator.updateBoundaries(resource))
+                boundariesChanged = true;
+        }
+
+        if (boundariesChanged) {
+            // The boundaries changed, so all item graphs are stale.
+            this._invalidateAllItems();
+            staleItemsLength = this._staleResources.length;
+        }
+
+        for (var i = 0; i < staleItemsLength; ++i)
+            this._resourceGridNode(this._staleResources[i]).refreshGraph(this.calculator);
+
+        this._staleResources = [];
+        this._sortItems();
+        this._updateSummaryBar();
+        this._dataGrid.updateWidths();
+
+        if (wasScrolledToLastRow)
+            this._dataGrid.scrollToLastRow();
+    },
+
+    _onPreserveLogClicked: function(e)
+    {
+        this._preserveLogToggle.toggled = !this._preserveLogToggle.toggled;
+    },
+
+    _reset: function()
+    {
+        this._popoverHelper.hidePopup();
+        this._closeVisibleResource();
+
+        this._toggleGridMode();
+
+        // Begin reset timeline
+        if (this._calculator)
+            this._calculator.reset();
+
+        this._resources = [];
+        this._resourcesById = {};
+        this._resourcesByURL = {};
+        this._staleResources = [];
+        this._resourceGridNodes = {};
+
+        this._dataGrid.removeChildren();
+        delete this._summaryBarRowNode;
+        this._updateDividersIfNeeded(true);
+        // End reset timeline.
+
+        this._mainResourceLoadTime = -1;
+        this._mainResourceDOMContentTime = -1;
+
+        this._viewsContainerElement.removeChildren();
+        this._viewsContainerElement.appendChild(this._closeButtonElement);
+        this._resetSummaryBar();
+    },
+
+    get resources()
+    {
+        return this._resources;
+    },
+
+    resourceById: function(id)
+    {
+        return this._resourcesById[id];
+    },
+
+    _onResourceStarted: function(event)
+    {
+        this._appendResource(event.data);
+    },
+
+    _appendResource: function(resource)
+    {
+        this._resources.push(resource);
+        this._resourcesById[resource.identifier] = resource;
+        this._resourcesByURL[resource.url] = resource;
+
+        // Pull all the redirects of the main resource upon commit load.
+        if (resource.redirects) {
+            for (var i = 0; i < resource.redirects.length; ++i)
+                this._refreshResource(resource.redirects[i]);
+        }
+
+        this._refreshResource(resource);
+    },
+
+    _onResourceUpdated: function(event)
+    {
+        this._refreshResource(event.data);
+    },
+
+    _refreshResource: function(resource)
+    {
+        this._staleResources.push(resource);
+        this._scheduleRefresh();
+
+        var oldView = WebInspector.ResourceView.existingResourceViewForResource(resource);
+        if (!oldView)
+            return;
+
+        if (WebInspector.ResourceView.resourceViewTypeMatchesResource(resource))
+            return;
+
+        var newView = WebInspector.ResourceView.recreateResourceView(resource);
+        if (this.visibleView === oldView)
+            this.visibleView = newView;
+    },
+
+    clear: function()
+    {
+        if (this._preserveLogToggle.toggled)
+            return;
+        this._reset();
+    },
+
+    _onMainResourceCommitLoad: function()
+    {
+        if (this._preserveLogToggle.toggled)
+            return;
+
+        this._reset();
+        // Now resurrect the main resource along with all redirects that lead to it.
+        var resourcesToAppend = (WebInspector.mainResource.redirects || []).concat(WebInspector.mainResource);
+        resourcesToAppend.forEach(this._appendResource, this);
+    },
+
+    canShowSourceLine: function(url, line)
+    {
+        return !!this._resourcesByURL[url];
+    },
+
+    showSourceLine: function(url, line)
+    {
+        this._showResource(this._resourcesByURL[url], line);
+    },
+
+    _showResource: function(resource, line)
+    {
+        if (!resource)
+            return;
+
+        this._popoverHelper.hidePopup();
+
+        this._toggleViewingResourceMode();
+
+        if (this.visibleView) {
+            this.visibleView.detach();
+            delete this.visibleView;
+        }
+
+        var view = new WebInspector.NetworkItemView(resource);
+        view.show(this._viewsContainerElement);
+        this.visibleView = view;
+
+        this.updateSidebarWidth();
+    },
+
+    _closeVisibleResource: function()
+    {
+        this.element.removeStyleClass("viewing-resource");
+
+        if (this.visibleView) {
+            this.visibleView.detach();
+            delete this.visibleView;
+        }
+
+        if (this._lastSelectedGraphTreeElement)
+            this._lastSelectedGraphTreeElement.select(true);
+
+        this.updateSidebarWidth();
+    },
+
+    _toggleLargerResources: function()
+    {
+        WebInspector.settings.resourcesLargeRows = !WebInspector.settings.resourcesLargeRows;
+        this._setLargerResources(WebInspector.settings.resourcesLargeRows);
+    },
+
+    _setLargerResources: function(enabled)
+    {
+        this._largerResourcesButton.toggled = enabled;
+        if (!enabled) {
+            this._largerResourcesButton.title = WebInspector.UIString("Use large resource rows.");
+            this._dataGrid.element.addStyleClass("small");
+            this._timelineGrid.element.addStyleClass("small");
+            this._viewsContainerElement.addStyleClass("small");
+        } else {
+            this._largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
+            this._dataGrid.element.removeStyleClass("small");
+            this._timelineGrid.element.removeStyleClass("small");
+            this._viewsContainerElement.removeStyleClass("small");
+        }
+        this._positionSummaryBar();
+    },
+
+    _getPopoverAnchor: function(element)
+    {
+        var anchor = element.enclosingNodeOrSelfWithClass("network-graph-bar") || element.enclosingNodeOrSelfWithClass("network-graph-label");
+        if (!anchor)
+            return null;
+        var resource = anchor.parentElement.resource;
+        return resource && resource.timing ? anchor : null;
+    },
+
+    _showPopover: function(anchor)
+    {
+        var resource = anchor.parentElement.resource;
+        var tableElement = WebInspector.ResourceTimingView.createTimingTable(resource);
+        var popover = new WebInspector.Popover(tableElement);
+        popover.show(anchor);
+        return popover;
+    },
+
+    _toggleGridMode: function()
+    {
+        if (this._viewingResourceMode) {
+            this._viewingResourceMode = false;
+            this.element.removeStyleClass("viewing-resource");
+            this._dataGrid.element.removeStyleClass("viewing-resource-mode");
+            this._viewsContainerElement.addStyleClass("hidden");
+            this.sidebarElement.style.right = 0;
+            this.sidebarElement.style.removeProperty("width");
+            if (this._dataGrid.selectedNode)
+                this._dataGrid.selectedNode.selected = false;
+        }
+
+        if (this._briefGrid) {
+            this._dataGrid.element.removeStyleClass("full-grid-mode");
+            this._dataGrid.element.addStyleClass("brief-grid-mode");
+
+            this._dataGrid.hideColumn("method");
+            this._dataGrid.hideColumn("status");
+            this._dataGrid.hideColumn("type");
+            this._dataGrid.hideColumn("size");
+            this._dataGrid.hideColumn("time");
+
+            var widths = {};
+            widths.name = 20;
+            widths.timeline = 80;
+        } else {
+            this._dataGrid.element.addStyleClass("full-grid-mode");
+            this._dataGrid.element.removeStyleClass("brief-grid-mode");
+
+            this._dataGrid.showColumn("method");
+            this._dataGrid.showColumn("status");
+            this._dataGrid.showColumn("type");
+            this._dataGrid.showColumn("size");
+            this._dataGrid.showColumn("time");
+
+            var widths = {};
+            widths.name = 20;
+            widths.method = 7;
+            widths.status = 8;
+            widths.type = 10;
+            widths.size = 10;
+            widths.time = 10;
+            widths.timeline = 37;
+        }
+
+        this._dataGrid.showColumn("timeline");
+        this._dataGrid.applyColumnWidthsMap(widths);
+
+    },
+
+    _toggleViewingResourceMode: function()
+    {
+        if (this._viewingResourceMode)
+            return;
+        this._viewingResourceMode = true;
+        this._preservedColumnWidths = this._dataGrid.columnWidthsMap();
+
+        this.element.addStyleClass("viewing-resource");
+        this._dataGrid.element.addStyleClass("viewing-resource-mode");
+        this._dataGrid.element.removeStyleClass("full-grid-mode");
+        this._dataGrid.element.removeStyleClass("brief-grid-mode");
+
+        this._dataGrid.hideColumn("method");
+        this._dataGrid.hideColumn("status");
+        this._dataGrid.hideColumn("type");
+        this._dataGrid.hideColumn("size");
+        this._dataGrid.hideColumn("time");
+        this._dataGrid.hideColumn("timeline");
+
+        this._viewsContainerElement.removeStyleClass("hidden");
+        this.updateSidebarWidth(200);
+
+        var widths = {};
+        widths.name = 100;
+        this._dataGrid.applyColumnWidthsMap(widths);
+    },
+
+    _contextMenu: function(event)
+    {
+        // createBlobURL is enabled conditionally, do not expose resource export if it's not available.
+        if (typeof window.webkitURL.createObjectURL !== "function" || !Preferences.resourceExportEnabled)
+            return;
+
+        var contextMenu = new WebInspector.ContextMenu();
+        var gridNode = this._dataGrid.dataGridNodeFromNode(event.target);
+        var resource = gridNode && gridNode._resource;
+        if (resource)
+            contextMenu.appendItem(WebInspector.UIString("Export to HAR"), this._exportResource.bind(this, resource));
+        contextMenu.appendItem(WebInspector.UIString("Export all to HAR"), this._exportAll.bind(this));
+        contextMenu.show(event);
+    },
+
+    _exportAll: function()
+    {
+        var harArchive = {
+            log: (new WebInspector.HARLog()).build()
+        }
+        InspectorFrontendHost.copyText(JSON.stringify(harArchive));
+    },
+
+    _exportResource: function(resource)
+    {
+        var har = (new WebInspector.HAREntry(resource)).build();
+        InspectorFrontendHost.copyText(JSON.stringify(har));
+    },
+
+    _updateOffscreenRows: function(e)
+    {
+        var dataTableBody = this._dataGrid.dataTableBody;
+        var rows = dataTableBody.children;
+        var recordsCount = rows.length;
+        if (recordsCount < 2)
+            return;  // Filler row only.
+
+        var visibleTop = this._dataGrid.scrollContainer.scrollTop;
+        var visibleBottom = visibleTop + this._dataGrid.scrollContainer.offsetHeight;
+
+        var rowHeight = 0;
+
+        // Filler is at recordsCount - 1.
+        var unfilteredRowIndex = 0;
+        for (var i = 0; i < recordsCount - 1; ++i) {
+            var row = rows[i];
+            // Don't touch summaty - quit instead.
+            if (this._summaryBarRowNode && row === this._summaryBarRowNode.element)
+                break;
+
+            var dataGridNode = this._dataGrid.dataGridNodeFromNode(row);
+            if (dataGridNode.isFilteredOut()) {
+                row.removeStyleClass("offscreen");
+                continue;
+            }
+
+            if (!rowHeight)
+                rowHeight = row.offsetHeight;
+
+            var rowIsVisible = unfilteredRowIndex * rowHeight < visibleBottom && (unfilteredRowIndex + 1) * rowHeight > visibleTop;
+            if (rowIsVisible !== row.rowIsVisible) {
+                if (rowIsVisible)
+                    row.removeStyleClass("offscreen");
+                else
+                    row.addStyleClass("offscreen");
+                row.rowIsVisible = rowIsVisible;
+            }
+            unfilteredRowIndex++;
+        }
+    }
+}
+
+WebInspector.NetworkPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+WebInspector.NetworkBaseCalculator = function()
+{
+}
+
+WebInspector.NetworkBaseCalculator.prototype = {
+    computeSummaryValues: function(items)
+    {
+        var total = 0;
+        var categoryValues = {};
+
+        var itemsLength = items.length;
+        for (var i = 0; i < itemsLength; ++i) {
+            var item = items[i];
+            var value = this._value(item);
+            if (typeof value === "undefined")
+                continue;
+            if (!(item.category.name in categoryValues))
+                categoryValues[item.category.name] = 0;
+            categoryValues[item.category.name] += value;
+            total += value;
+        }
+
+        return {categoryValues: categoryValues, total: total};
+    },
+
+    computeBarGraphPercentages: function(item)
+    {
+        return {start: 0, middle: 0, end: (this._value(item) / this.boundarySpan) * 100};
+    },
+
+    computeBarGraphLabels: function(item)
+    {
+        const label = this.formatValue(this._value(item));
+        return {left: label, right: label, tooltip: label};
+    },
+
+    get boundarySpan()
+    {
+        return this.maximumBoundary - this.minimumBoundary;
+    },
+
+    updateBoundaries: function(item)
+    {
+        this.minimumBoundary = 0;
+
+        var value = this._value(item);
+        if (typeof this.maximumBoundary === "undefined" || value > this.maximumBoundary) {
+            this.maximumBoundary = value;
+            return true;
+        }
+        return false;
+    },
+
+    reset: function()
+    {
+        delete this.minimumBoundary;
+        delete this.maximumBoundary;
+    },
+
+    _value: function(item)
+    {
+        return 0;
+    },
+
+    formatValue: function(value)
+    {
+        return value.toString();
+    }
+}
+
+WebInspector.NetworkTimeCalculator = function(startAtZero)
+{
+    WebInspector.NetworkBaseCalculator.call(this);
+    this.startAtZero = startAtZero;
+}
+
+WebInspector.NetworkTimeCalculator.prototype = {
+    computeSummaryValues: function(resources)
+    {
+        var resourcesByCategory = {};
+        var resourcesLength = resources.length;
+        for (var i = 0; i < resourcesLength; ++i) {
+            var resource = resources[i];
+            if (!(resource.category.name in resourcesByCategory))
+                resourcesByCategory[resource.category.name] = [];
+            resourcesByCategory[resource.category.name].push(resource);
+        }
+
+        var earliestStart;
+        var latestEnd;
+        var categoryValues = {};
+        for (var category in resourcesByCategory) {
+            resourcesByCategory[category].sort(WebInspector.Resource.CompareByTime);
+            categoryValues[category] = 0;
+
+            var segment = {start: -1, end: -1};
+
+            var categoryResources = resourcesByCategory[category];
+            var resourcesLength = categoryResources.length;
+            for (var i = 0; i < resourcesLength; ++i) {
+                var resource = categoryResources[i];
+                if (resource.startTime === -1 || resource.endTime === -1)
+                    continue;
+
+                if (typeof earliestStart === "undefined")
+                    earliestStart = resource.startTime;
+                else
+                    earliestStart = Math.min(earliestStart, resource.startTime);
+
+                if (typeof latestEnd === "undefined")
+                    latestEnd = resource.endTime;
+                else
+                    latestEnd = Math.max(latestEnd, resource.endTime);
+
+                if (resource.startTime <= segment.end) {
+                    segment.end = Math.max(segment.end, resource.endTime);
+                    continue;
+                }
+
+                categoryValues[category] += segment.end - segment.start;
+
+                segment.start = resource.startTime;
+                segment.end = resource.endTime;
+            }
+
+            // Add the last segment
+            categoryValues[category] += segment.end - segment.start;
+        }
+
+        return {categoryValues: categoryValues, total: latestEnd - earliestStart};
+    },
+
+    computeBarGraphPercentages: function(resource)
+    {
+        if (resource.startTime !== -1)
+            var start = ((resource.startTime - this.minimumBoundary) / this.boundarySpan) * 100;
+        else
+            var start = 0;
+
+        if (resource.responseReceivedTime !== -1)
+            var middle = ((resource.responseReceivedTime - this.minimumBoundary) / this.boundarySpan) * 100;
+        else
+            var middle = (this.startAtZero ? start : 100);
+
+        if (resource.endTime !== -1)
+            var end = ((resource.endTime - this.minimumBoundary) / this.boundarySpan) * 100;
+        else
+            var end = (this.startAtZero ? middle : 100);
+
+        if (this.startAtZero) {
+            end -= start;
+            middle -= start;
+            start = 0;
+        }
+
+        return {start: start, middle: middle, end: end};
+    },
+
+    computePercentageFromEventTime: function(eventTime)
+    {
+        // This function computes a percentage in terms of the total loading time
+        // of a specific event. If startAtZero is set, then this is useless, and we
+        // want to return 0.
+        if (eventTime !== -1 && !this.startAtZero)
+            return ((eventTime - this.minimumBoundary) / this.boundarySpan) * 100;
+
+        return 0;
+    },
+
+    computeBarGraphLabels: function(resource)
+    {
+        var rightLabel = "";
+        if (resource.responseReceivedTime !== -1 && resource.endTime !== -1)
+            rightLabel = this.formatValue(resource.endTime - resource.responseReceivedTime);
+
+        var hasLatency = resource.latency > 0;
+        if (hasLatency)
+            var leftLabel = this.formatValue(resource.latency);
+        else
+            var leftLabel = rightLabel;
+
+        if (resource.timing)
+            return {left: leftLabel, right: rightLabel};
+
+        if (hasLatency && rightLabel) {
+            var total = this.formatValue(resource.duration);
+            var tooltip = WebInspector.UIString("%s latency, %s download (%s total)", leftLabel, rightLabel, total);
+        } else if (hasLatency)
+            var tooltip = WebInspector.UIString("%s latency", leftLabel);
+        else if (rightLabel)
+            var tooltip = WebInspector.UIString("%s download", rightLabel);
+
+        if (resource.cached)
+            tooltip = WebInspector.UIString("%s (from cache)", tooltip);
+        return {left: leftLabel, right: rightLabel, tooltip: tooltip};
+    },
+
+    updateBoundaries: function(resource)
+    {
+        var didChange = false;
+
+        var lowerBound;
+        if (this.startAtZero)
+            lowerBound = 0;
+        else
+            lowerBound = this._lowerBound(resource);
+
+        if (lowerBound !== -1 && (typeof this.minimumBoundary === "undefined" || lowerBound < this.minimumBoundary)) {
+            this.minimumBoundary = lowerBound;
+            didChange = true;
+        }
+
+        var upperBound = this._upperBound(resource);
+        if (upperBound !== -1 && (typeof this.maximumBoundary === "undefined" || upperBound > this.maximumBoundary)) {
+            this.maximumBoundary = upperBound;
+            didChange = true;
+        }
+
+        return didChange;
+    },
+
+    formatValue: function(value)
+    {
+        return Number.secondsToString(value);
+    },
+
+    _lowerBound: function(resource)
+    {
+        return 0;
+    },
+
+    _upperBound: function(resource)
+    {
+        return 0;
+    }
+}
+
+WebInspector.NetworkTimeCalculator.prototype.__proto__ = WebInspector.NetworkBaseCalculator.prototype;
+
+WebInspector.NetworkTransferTimeCalculator = function()
+{
+    WebInspector.NetworkTimeCalculator.call(this, false);
+}
+
+WebInspector.NetworkTransferTimeCalculator.prototype = {
+    formatValue: function(value)
+    {
+        return Number.secondsToString(value);
+    },
+
+    _lowerBound: function(resource)
+    {
+        return resource.startTime;
+    },
+
+    _upperBound: function(resource)
+    {
+        return resource.endTime;
+    }
+}
+
+WebInspector.NetworkTransferTimeCalculator.prototype.__proto__ = WebInspector.NetworkTimeCalculator.prototype;
+
+WebInspector.NetworkTransferDurationCalculator = function()
+{
+    WebInspector.NetworkTimeCalculator.call(this, true);
+}
+
+WebInspector.NetworkTransferDurationCalculator.prototype = {
+    formatValue: function(value)
+    {
+        return Number.secondsToString(value);
+    },
+
+    _upperBound: function(resource)
+    {
+        return resource.duration;
+    }
+}
+
+WebInspector.NetworkTransferDurationCalculator.prototype.__proto__ = WebInspector.NetworkTimeCalculator.prototype;
+
+WebInspector.NetworkDataGridNode = function(panel, resource)
+{
+    WebInspector.DataGridNode.call(this, {});
+    this._panel = panel;
+    this._resource = resource;
+}
+
+WebInspector.NetworkDataGridNode.prototype = {
+    createCells: function()
+    {
+        this._nameCell = this._createDivInTD("name");
+        this._methodCell = this._createDivInTD("method");
+        this._statusCell = this._createDivInTD("status");
+        this._typeCell = this._createDivInTD("type");
+        this._sizeCell = this._createDivInTD("size");
+        this._timeCell = this._createDivInTD("time");
+        this._createTimelineCell();
+        this._nameCell.addEventListener("click", this.select.bind(this), false);
+        this._nameCell.addEventListener("dblclick", this._openInNewTab.bind(this), false);
+    },
+
+    isFilteredOut: function()
+    {
+        if (!this._panel._hiddenCategories.all)
+            return false;
+        return this._resource.category.name in this._panel._hiddenCategories;
+    },
+
+    select: function()
+    {
+        this._panel._showResource(this._resource);
+        WebInspector.DataGridNode.prototype.select.apply(this, arguments);
+    },
+
+    _openInNewTab: function()
+    {
+        InspectorBackend.openInInspectedWindow(this._resource.url);
+    },
+
+    get selectable()
+    {
+        if (!this._panel._viewingResourceMode)
+            return false;
+        return !this.isFilteredOut();
+    },
+
+    _createDivInTD: function(columnIdentifier)
+    {
+        var td = document.createElement("td");
+        td.className = columnIdentifier + "-column";
+        var div = document.createElement("div");
+        td.appendChild(div);
+        this._element.appendChild(td);
+        return div;
+    },
+
+    _createTimelineCell: function()
+    {
+        this._graphElement = document.createElement("div");
+        this._graphElement.className = "network-graph-side";
+
+        this._barAreaElement = document.createElement("div");
+        //    this._barAreaElement.className = "network-graph-bar-area hidden";
+        this._barAreaElement.className = "network-graph-bar-area";
+        this._barAreaElement.resource = this._resource;
+        this._graphElement.appendChild(this._barAreaElement);
+
+        this._barLeftElement = document.createElement("div");
+        this._barLeftElement.className = "network-graph-bar waiting";
+        this._barAreaElement.appendChild(this._barLeftElement);
+
+        this._barRightElement = document.createElement("div");
+        this._barRightElement.className = "network-graph-bar";
+        this._barAreaElement.appendChild(this._barRightElement);
+
+
+        this._labelLeftElement = document.createElement("div");
+        this._labelLeftElement.className = "network-graph-label waiting";
+        this._barAreaElement.appendChild(this._labelLeftElement);
+
+        this._labelRightElement = document.createElement("div");
+        this._labelRightElement.className = "network-graph-label";
+        this._barAreaElement.appendChild(this._labelRightElement);
+
+        this._graphElement.addEventListener("mouseover", this._refreshLabelPositions.bind(this), false);
+
+        this._timelineCell = document.createElement("td");
+        this._timelineCell.className = "timeline-column";
+        this._element.appendChild(this._timelineCell);
+        this._timelineCell.appendChild(this._graphElement);
+    },
+
+    refreshResource: function()
+    {
+        this._refreshNameCell();
+
+        this._methodCell.textContent = this._resource.requestMethod;
+
+        this._refreshStatusCell();
+
+        if (this._resource.mimeType) {
+            this._typeCell.removeStyleClass("network-dim-cell");
+            this._typeCell.textContent = this._resource.mimeType;
+        } else {
+            this._typeCell.addStyleClass("network-dim-cell");
+            this._typeCell.textContent = WebInspector.UIString("Pending");
+        }
+
+        this._refreshSizeCell();
+        this._refreshTimeCell();
+
+        if (this._resource.cached)
+            this._graphElement.addStyleClass("resource-cached");
+
+        this._element.addStyleClass("network-item");
+        if (!this._element.hasStyleClass("network-category-" + this._resource.category.name)) {
+            this._element.removeMatchingStyleClasses("network-category-\\w+");
+            this._element.addStyleClass("network-category-" + this._resource.category.name);
+        }
+    },
+
+    _refreshNameCell: function()
+    {
+        this._nameCell.removeChildren();
+
+        if (this._resource.category === WebInspector.resourceCategories.images) {
+            var previewImage = document.createElement("img");
+            previewImage.className = "image-network-icon-preview";
+            this._resource.populateImageSource(previewImage);
+
+            var iconElement = document.createElement("div");
+            iconElement.className = "icon";
+            iconElement.appendChild(previewImage);
+        } else {
+            var iconElement = document.createElement("img");
+            iconElement.className = "icon";
+        }
+        this._nameCell.appendChild(iconElement);
+        this._nameCell.appendChild(document.createTextNode(this._fileName()));
+
+
+        var subtitle = this._resource.displayDomain;
+
+        if (this._resource.path && this._resource.lastPathComponent) {
+            var lastPathComponentIndex = this._resource.path.lastIndexOf("/" + this._resource.lastPathComponent);
+            if (lastPathComponentIndex != -1)
+                subtitle += this._resource.path.substring(0, lastPathComponentIndex);
+        }
+
+        this._appendSubtitle(this._nameCell, subtitle);
+        this._nameCell.title = this._resource.url;
+    },
+
+    _fileName: function()
+    {
+        var fileName = this._resource.displayName;
+        if (this._resource.queryString)
+            fileName += "?" + this._resource.queryString;
+        return fileName;
+    },
+
+    _refreshStatusCell: function()
+    {
+        this._statusCell.removeChildren();
+
+        var fromCache = this._resource.cached;
+        if (fromCache) {
+            this._statusCell.textContent = WebInspector.UIString("(from cache)");
+            this._statusCell.addStyleClass("network-dim-cell");
+            return;
+        }
+
+        this._statusCell.removeStyleClass("network-dim-cell");
+        if (this._resource.statusCode) {
+            this._statusCell.appendChild(document.createTextNode(this._resource.statusCode));
+            this._statusCell.removeStyleClass("network-dim-cell");
+            this._appendSubtitle(this._statusCell, this._resource.statusText);
+            this._statusCell.title = this._resource.statusCode + " " + this._resource.statusText;
+        } else {
+            this._statusCell.addStyleClass("network-dim-cell");
+            this._statusCell.textContent = WebInspector.UIString("Pending");
+        }
+    },
+
+    _refreshSizeCell: function()
+    {
+        var resourceSize = typeof this._resource.resourceSize === "number" ? Number.bytesToString(this._resource.resourceSize) : "?";
+        var transferSize = typeof this._resource.transferSize === "number" ? Number.bytesToString(this._resource.transferSize) : "?";
+        var fromCache = this._resource.cached;
+        this._sizeCell.textContent = !fromCache ? resourceSize : WebInspector.UIString("(from cache)");
+        if (fromCache)
+            this._sizeCell.addStyleClass("network-dim-cell");
+        else
+            this._sizeCell.removeStyleClass("network-dim-cell");
+        if (!fromCache)
+            this._appendSubtitle(this._sizeCell, transferSize);
+    },
+
+    _refreshTimeCell: function()
+    {
+        if (this._resource.duration > 0) {
+            this._timeCell.removeStyleClass("network-dim-cell");
+            this._timeCell.textContent = Number.secondsToString(this._resource.duration);
+            this._appendSubtitle(this._timeCell, Number.secondsToString(this._resource.latency));
+        } else {
+            this._timeCell.addStyleClass("network-dim-cell");
+            this._timeCell.textContent = WebInspector.UIString("Pending");
+        }
+    },
+
+    _appendSubtitle: function(cellElement, subtitleText)
+    {
+        var subtitleElement = document.createElement("div");
+        subtitleElement.className = "network-cell-subtitle";
+        subtitleElement.textContent = subtitleText;
+        cellElement.appendChild(subtitleElement);
+    },
+
+    refreshGraph: function(calculator)
+    {
+        var percentages = calculator.computeBarGraphPercentages(this._resource);
+        this._percentages = percentages;
+
+        this._barAreaElement.removeStyleClass("hidden");
+
+        if (!this._graphElement.hasStyleClass("network-category-" + this._resource.category.name)) {
+            this._graphElement.removeMatchingStyleClasses("network-category-\\w+");
+            this._graphElement.addStyleClass("network-category-" + this._resource.category.name);
+        }
+
+        this._barLeftElement.style.setProperty("left", percentages.start + "%");
+        this._barRightElement.style.setProperty("right", (100 - percentages.end) + "%");
+
+        this._barLeftElement.style.setProperty("right", (100 - percentages.end) + "%");
+        this._barRightElement.style.setProperty("left", percentages.middle + "%");
+
+        var labels = calculator.computeBarGraphLabels(this._resource);
+        this._labelLeftElement.textContent = labels.left;
+        this._labelRightElement.textContent = labels.right;
+
+        var tooltip = (labels.tooltip || "");
+        this._barLeftElement.title = tooltip;
+        this._labelLeftElement.title = tooltip;
+        this._labelRightElement.title = tooltip;
+        this._barRightElement.title = tooltip;
+    },
+
+    _refreshLabelPositions: function()
+    {
+        if (!this._percentages)
+            return;
+        this._labelLeftElement.style.removeProperty("left");
+        this._labelLeftElement.style.removeProperty("right");
+        this._labelLeftElement.removeStyleClass("before");
+        this._labelLeftElement.removeStyleClass("hidden");
+
+        this._labelRightElement.style.removeProperty("left");
+        this._labelRightElement.style.removeProperty("right");
+        this._labelRightElement.removeStyleClass("after");
+        this._labelRightElement.removeStyleClass("hidden");
+
+        const labelPadding = 10;
+        const barRightElementOffsetWidth = this._barRightElement.offsetWidth;
+        const barLeftElementOffsetWidth = this._barLeftElement.offsetWidth;
+
+        if (this._barLeftElement) {
+            var leftBarWidth = barLeftElementOffsetWidth - labelPadding;
+            var rightBarWidth = (barRightElementOffsetWidth - barLeftElementOffsetWidth) - labelPadding;
+        } else {
+            var leftBarWidth = (barLeftElementOffsetWidth - barRightElementOffsetWidth) - labelPadding;
+            var rightBarWidth = barRightElementOffsetWidth - labelPadding;
+        }
+
+        const labelLeftElementOffsetWidth = this._labelLeftElement.offsetWidth;
+        const labelRightElementOffsetWidth = this._labelRightElement.offsetWidth;
+
+        const labelBefore = (labelLeftElementOffsetWidth > leftBarWidth);
+        const labelAfter = (labelRightElementOffsetWidth > rightBarWidth);
+        const graphElementOffsetWidth = this._graphElement.offsetWidth;
+
+        if (labelBefore && (graphElementOffsetWidth * (this._percentages.start / 100)) < (labelLeftElementOffsetWidth + 10))
+            var leftHidden = true;
+
+        if (labelAfter && (graphElementOffsetWidth * ((100 - this._percentages.end) / 100)) < (labelRightElementOffsetWidth + 10))
+            var rightHidden = true;
+
+        if (barLeftElementOffsetWidth == barRightElementOffsetWidth) {
+            // The left/right label data are the same, so a before/after label can be replaced by an on-bar label.
+            if (labelBefore && !labelAfter)
+                leftHidden = true;
+            else if (labelAfter && !labelBefore)
+                rightHidden = true;
+        }
+
+        if (labelBefore) {
+            if (leftHidden)
+                this._labelLeftElement.addStyleClass("hidden");
+            this._labelLeftElement.style.setProperty("right", (100 - this._percentages.start) + "%");
+            this._labelLeftElement.addStyleClass("before");
+        } else {
+            this._labelLeftElement.style.setProperty("left", this._percentages.start + "%");
+            this._labelLeftElement.style.setProperty("right", (100 - this._percentages.middle) + "%");
+        }
+
+        if (labelAfter) {
+            if (rightHidden)
+                this._labelRightElement.addStyleClass("hidden");
+            this._labelRightElement.style.setProperty("left", this._percentages.end + "%");
+            this._labelRightElement.addStyleClass("after");
+        } else {
+            this._labelRightElement.style.setProperty("left", this._percentages.middle + "%");
+            this._labelRightElement.style.setProperty("right", (100 - this._percentages.end) + "%");
+        }
+    }
+}
+
+WebInspector.NetworkDataGridNode.NameComparator = function(a, b)
+{
+    var aFileName = a._resource.displayName + (a._resource.queryString ? a._resource.queryString : "");
+    var bFileName = b._resource.displayName + (b._resource.queryString ? b._resource.queryString : "");
+    if (aFileName > bFileName)
+        return 1;
+    if (bFileName > aFileName)
+        return -1;
+    return 0;
+}
+
+WebInspector.NetworkDataGridNode.SizeComparator = function(a, b)
+{
+    if (b._resource.cached && !a._resource.cached)
+        return 1;
+    if (a._resource.cached && !b._resource.cached)
+        return -1;
+
+    if (a._resource.resourceSize === b._resource.resourceSize)
+        return 0;
+
+    return a._resource.resourceSize - b._resource.resourceSize;
+}
+
+WebInspector.NetworkDataGridNode.ResourcePropertyComparator = function(propertyName, revert, a, b)
+{
+    var aValue = a._resource[propertyName];
+    var bValue = b._resource[propertyName];
+    if (aValue > bValue)
+        return revert ? -1 : 1;
+    if (bValue > aValue)
+        return revert ? 1 : -1;
+    return 0;
+}
+
+WebInspector.NetworkDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
+
+WebInspector.NetworkTotalGridNode = function(element)
+{
+    this._summaryBarElement = element;
+    WebInspector.DataGridNode.call(this, {summaryRow: true});
+}
+
+WebInspector.NetworkTotalGridNode.prototype = {
+    isFilteredOut: function()
+    {
+        return false;
+    },
+
+    get selectable()
+    {
+        return false;
+    },
+
+    createCells: function()
+    {
+        var td = document.createElement("td");
+        td.setAttribute("colspan", 7);
+        td.className = "network-summary";
+        td.appendChild(this._summaryBarElement);
+        this._element.appendChild(td);
+    }
+}
+
+WebInspector.NetworkTotalGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre/blob/c4fbd3d0/weinre.build/vendor/webkit/WebCore/inspector/front-end/Object.js
----------------------------------------------------------------------
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Object.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Object.js
new file mode 100644
index 0000000..5872b8b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Object.js
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+WebInspector.Object = function() {
+}
+
+WebInspector.Object.prototype = {
+    addEventListener: function(eventType, listener, thisObject)
+    {
+        if (!("_listeners" in this))
+            this._listeners = {};
+        if (!(eventType in this._listeners))
+            this._listeners[eventType] = [];
+        this._listeners[eventType].push({ thisObject: thisObject, listener: listener });
+    },
+
+    removeEventListener: function(eventType, listener, thisObject)
+    {
+        if (!("_listeners" in this) || !(eventType in this._listeners))
+            return;
+        var listeners = this._listeners[eventType];
+        for (var i = 0; i < listeners.length; ++i) {
+            if (listener && listeners[i].listener === listener && listeners[i].thisObject === thisObject)
+                listeners.splice(i, 1);
+            else if (!listener && thisObject && listeners[i].thisObject === thisObject)
+                listeners.splice(i, 1);
+        }
+
+        if (!listeners.length)
+            delete this._listeners[eventType];
+    },
+
+    removeAllListeners: function()
+    {
+        delete this._listeners;
+    },
+
+    dispatchEventToListeners: function(eventType, eventData)
+    {
+        if (!("_listeners" in this) || !(eventType in this._listeners))
+            return;
+
+        var stoppedPropagation = false;
+
+        function stopPropagation()
+        {
+            stoppedPropagation = true;
+        }
+
+        function preventDefault()
+        {
+            this.defaultPrevented = true;
+        }
+
+        var event = {target: this, type: eventType, data: eventData, defaultPrevented: false};
+        event.stopPropagation = stopPropagation;
+        event.preventDefault = preventDefault;
+
+        var listeners = this._listeners[eventType].slice(0);
+        for (var i = 0; i < listeners.length; ++i) {
+            listeners[i].listener.call(listeners[i].thisObject, event);
+            if (stoppedPropagation)
+                break;
+        }
+
+        return event.defaultPrevented;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre/blob/c4fbd3d0/weinre.build/vendor/webkit/WebCore/inspector/front-end/ObjectPropertiesSection.js
----------------------------------------------------------------------
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ObjectPropertiesSection.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ObjectPropertiesSection.js
new file mode 100644
index 0000000..88fddd6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ObjectPropertiesSection.js
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * 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.
+ */
+
+WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, treeElementConstructor)
+{
+    this.emptyPlaceholder = (emptyPlaceholder || WebInspector.UIString("No Properties"));
+    this.object = object;
+    this.ignoreHasOwnProperty = ignoreHasOwnProperty;
+    this.extraProperties = extraProperties;
+    this.treeElementConstructor = treeElementConstructor || WebInspector.ObjectPropertyTreeElement;
+    this.editable = true;
+
+    WebInspector.PropertiesSection.call(this, title, subtitle);
+}
+
+WebInspector.ObjectPropertiesSection.prototype = {
+    onpopulate: function()
+    {
+        this.update();
+    },
+
+    update: function()
+    {
+        var self = this;
+        var callback = function(properties) {
+            if (!properties)
+                return;
+            self.updateProperties(properties);
+        };
+        this.object.getProperties(this.ignoreHasOwnProperty, true, callback);
+    },
+
+    updateProperties: function(properties, rootTreeElementConstructor, rootPropertyComparer)
+    {
+        if (!rootTreeElementConstructor)
+            rootTreeElementConstructor = this.treeElementConstructor;
+            
+        if (!rootPropertyComparer)
+            rootPropertyComparer = WebInspector.ObjectPropertiesSection.CompareProperties;
+            
+        if (this.extraProperties)
+            for (var i = 0; i < this.extraProperties.length; ++i)
+                properties.push(this.extraProperties[i]);
+                
+        properties.sort(rootPropertyComparer);
+
+        this.propertiesTreeOutline.removeChildren();
+
+        for (var i = 0; i < properties.length; ++i) {
+            properties[i].parentObject = this.object;
+            this.propertiesTreeOutline.appendChild(new rootTreeElementConstructor(properties[i]));
+        }
+
+        if (!this.propertiesTreeOutline.children.length) {
+            var title = "<div class=\"info\">" + this.emptyPlaceholder + "</div>";
+            var infoElement = new TreeElement(null, null, false);
+            infoElement.titleHTML = title;
+            this.propertiesTreeOutline.appendChild(infoElement);
+        }
+        this.propertiesForTest = properties;
+    }
+}
+
+WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
+
+WebInspector.ObjectPropertiesSection.CompareProperties = function(propertyA, propertyB) 
+{
+    var a = propertyA.name;
+    var b = propertyB.name;
+    if (a === "__proto__")
+        return 1;
+    if (b === "__proto__")
+        return -1;
+
+    // if used elsewhere make sure to
+    //  - convert a and b to strings (not needed here, properties are all strings)
+    //  - check if a == b (not needed here, no two properties can be the same)
+
+    var diff = 0;
+    var chunk = /^\d+|^\D+/;
+    var chunka, chunkb, anum, bnum;
+    while (diff === 0) {
+        if (!a && b)
+            return -1;
+        if (!b && a)
+            return 1;
+        chunka = a.match(chunk)[0];
+        chunkb = b.match(chunk)[0];
+        anum = !isNaN(chunka);
+        bnum = !isNaN(chunkb);
+        if (anum && !bnum)
+            return -1;
+        if (bnum && !anum)
+            return 1;
+        if (anum && bnum) {
+            diff = chunka - chunkb;
+            if (diff === 0 && chunka.length !== chunkb.length) {
+                if (!+chunka && !+chunkb) // chunks are strings of all 0s (special case)
+                    return chunka.length - chunkb.length;
+                else
+                    return chunkb.length - chunka.length;
+            }
+        } else if (chunka !== chunkb)
+            return (chunka < chunkb) ? -1 : 1;
+        a = a.substring(chunka.length);
+        b = b.substring(chunkb.length);
+    }
+    return diff;
+}
+
+WebInspector.ObjectPropertyTreeElement = function(property)
+{
+    this.property = property;
+
+    // Pass an empty title, the title gets made later in onattach.
+    TreeElement.call(this, "", null, false);
+}
+
+WebInspector.ObjectPropertyTreeElement.prototype = {
+    onpopulate: function()
+    {
+        if (this.children.length && !this.shouldRefreshChildren)
+            return;
+
+        var callback = function(properties) {
+            this.removeChildren();
+            if (!properties)
+                return;
+
+            properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties);
+            for (var i = 0; i < properties.length; ++i) {
+                this.appendChild(new this.treeOutline.section.treeElementConstructor(properties[i]));
+            }
+        };
+        this.property.value.getOwnProperties(true, callback.bind(this));
+    },
+
+    ondblclick: function(event)
+    {
+        this.startEditing();
+    },
+
+    onattach: function()
+    {
+        this.update();
+    },
+
+    update: function()
+    {
+        this.nameElement = document.createElement("span");
+        this.nameElement.className = "name";
+        this.nameElement.textContent = this.property.name;
+
+        var separatorElement = document.createElement("span");
+        separatorElement.className = "separator";
+        separatorElement.textContent = ": ";
+        
+        this.valueElement = document.createElement("span");
+        this.valueElement.className = "value";
+
+        var description = this.property.value.description;
+        // Render \n as a nice unicode cr symbol.
+        if (this.property.value.type === "string" && typeof description === "string")
+            description = description.replace(/\n/g, "\u21B5");
+        this.valueElement.textContent = description;
+
+        if (this.property.isGetter)
+            this.valueElement.addStyleClass("dimmed");
+        if (this.property.value.isError())
+            this.valueElement.addStyleClass("error");
+        if (this.property.value.type)
+            this.valueElement.addStyleClass("console-formatted-" + this.property.value.type);
+        if (this.property.value.type === "node")
+            this.valueElement.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), false);
+
+        this.listItemElement.removeChildren();
+
+        this.listItemElement.appendChild(this.nameElement);
+        this.listItemElement.appendChild(separatorElement);
+        this.listItemElement.appendChild(this.valueElement);
+        this.hasChildren = this.property.value.hasChildren;
+    },
+
+    _contextMenuEventFired: function()
+    {
+        function selectNode(nodeId)
+        {
+            if (nodeId) {
+                WebInspector.panels.elements.switchToAndFocus(WebInspector.domAgent.nodeForId(nodeId));
+            }
+        }
+
+        function revealElement()
+        {
+            this.property.value.pushNodeToFrontend(selectNode);
+        }
+
+        var contextMenu = new WebInspector.ContextMenu();
+        contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), revealElement.bind(this));
+        contextMenu.show(event);
+    },
+
+    updateSiblings: function()
+    {
+        if (this.parent.root)
+            this.treeOutline.section.update();
+        else
+            this.parent.shouldRefreshChildren = true;
+    },
+
+    startEditing: function()
+    {
+        if (WebInspector.isBeingEdited(this.valueElement) || !this.treeOutline.section.editable)
+            return;
+
+        var context = { expanded: this.expanded };
+
+        // Lie about our children to prevent expanding on double click and to collapse subproperties.
+        this.hasChildren = false;
+
+        this.listItemElement.addStyleClass("editing-sub-part");
+
+        WebInspector.startEditing(this.valueElement, {
+            context: context,
+            commitHandler: this.editingCommitted.bind(this),
+            cancelHandler: this.editingCancelled.bind(this)
+        });
+    },
+
+    editingEnded: function(context)
+    {
+        this.listItemElement.scrollLeft = 0;
+        this.listItemElement.removeStyleClass("editing-sub-part");
+        if (context.expanded)
+            this.expand();
+    },
+
+    editingCancelled: function(element, context)
+    {
+        this.update();
+        this.editingEnded(context);
+    },
+
+    editingCommitted: function(element, userInput, previousContent, context)
+    {
+        if (userInput === previousContent)
+            return this.editingCancelled(element, context); // nothing changed, so cancel
+
+        this.applyExpression(userInput, true);
+
+        this.editingEnded(context);
+    },
+
+    applyExpression: function(expression, updateInterface)
+    {
+        expression = expression.trim();
+        var expressionLength = expression.length;
+        var self = this;
+        var callback = function(success) {
+            if (!updateInterface)
+                return;
+
+            if (!success)
+                self.update();
+
+            if (!expressionLength) {
+                // The property was deleted, so remove this tree element.
+                self.parent.removeChild(this);
+            } else {
+                // Call updateSiblings since their value might be based on the value that just changed.
+                self.updateSiblings();
+            }
+        };
+        this.property.parentObject.setPropertyValue(this.property.name, expression.trim(), callback);
+    }
+}
+
+WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype;