2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
26 WebInspector.ResourceTreeElement = class ResourceTreeElement extends WebInspector.SourceCodeTreeElement
28 constructor(resource, representedObject)
30 console.assert(resource instanceof WebInspector.Resource);
32 super(resource, ["resource", WebInspector.ResourceTreeElement.ResourceIconStyleClassName, resource.type], "", "", representedObject || resource, false);
34 this._updateResource(resource);
39 static compareResourceTreeElements(a, b)
41 // Compare by type first to keep resources grouped by type when not sorted into folders.
42 var comparisonResult = a.resource.type.localeCompare(b.resource.type);
43 if (comparisonResult !== 0)
44 return comparisonResult;
46 // Compare async resource types by their first timestamp so they are in chronological order.
47 if (a.resource.type === WebInspector.Resource.Type.XHR || a.resource.type === WebInspector.Resource.Type.WebSocket)
48 return a.resource.firstTimestamp - b.resource.firstTimestamp || 0;
50 // Compare by subtitle when the types are the same. The subtitle is used to show the
51 // domain of the resource. This causes resources to group by domain. If the resource
52 // is on the same domain as the frame it will have an empty subtitle. This is good
53 // because empty string sorts first, so those will appear before external resources.
54 comparisonResult = a.subtitle.localeCompare(b.subtitle);
55 if (comparisonResult !== 0)
56 return comparisonResult;
58 // Compare by title when the subtitles are the same.
59 return a.mainTitle.localeCompare(b.mainTitle);
62 static compareFolderAndResourceTreeElements(a, b)
64 var aIsFolder = a instanceof WebInspector.FolderTreeElement;
65 var bIsFolder = b instanceof WebInspector.FolderTreeElement;
67 if (aIsFolder && !bIsFolder)
69 if (!aIsFolder && bIsFolder)
71 if (aIsFolder && bIsFolder)
72 return a.mainTitle.localeCompare(b.mainTitle);
74 return WebInspector.ResourceTreeElement.compareResourceTreeElements(a, b);
81 return this._resource;
86 return {text: this._resource.url};
91 InspectorFrontendHost.openInNewTab(this._resource.url);
94 // Protected (Used by FrameTreeElement)
96 _updateResource(resource)
98 console.assert(resource instanceof WebInspector.Resource);
100 // This method is for subclasses like FrameTreeElement who don't use a resource as the representedObject.
101 // This method should only be called once if the representedObject is a resource, since changing the resource
102 // without changing the representedObject is bad. If you need to change the resource, make a new ResourceTreeElement.
103 console.assert(!this._resource || !(this.representedObject instanceof WebInspector.Resource));
105 if (this._resource) {
106 this._resource.removeEventListener(WebInspector.Resource.Event.URLDidChange, this._urlDidChange, this);
107 this._resource.removeEventListener(WebInspector.Resource.Event.TypeDidChange, this._typeDidChange, this);
108 this._resource.removeEventListener(WebInspector.Resource.Event.LoadingDidFinish, this._updateStatus, this);
109 this._resource.removeEventListener(WebInspector.Resource.Event.LoadingDidFail, this._updateStatus, this);
112 this._updateSourceCode(resource);
114 this._resource = resource;
116 resource.addEventListener(WebInspector.Resource.Event.URLDidChange, this._urlDidChange, this);
117 resource.addEventListener(WebInspector.Resource.Event.TypeDidChange, this._typeDidChange, this);
118 resource.addEventListener(WebInspector.Resource.Event.LoadingDidFinish, this._updateStatus, this);
119 resource.addEventListener(WebInspector.Resource.Event.LoadingDidFail, this._updateStatus, this);
121 this._updateTitles();
122 this._updateStatus();
123 this._updateToolTip();
130 var frame = this._resource.parentFrame;
131 var isMainResource = this._resource.isMainResource();
132 if (isMainResource && frame) {
133 // When the resource is a main resource, get the host from the current frame's parent frame instead of the current frame.
134 var parentResourceHost = frame.parentFrame ? frame.parentFrame.mainResource.urlComponents.host : null;
136 // When the resource is a normal sub-resource, get the host from the current frame's main resource.
137 var parentResourceHost = frame.mainResource.urlComponents.host;
140 var urlComponents = this._resource.urlComponents;
142 var oldMainTitle = this.mainTitle;
143 this.mainTitle = WebInspector.displayNameForURL(this._resource.url, urlComponents);
145 // Show the host as the subtitle if it is different from the main resource or if this is the main frame's main resource.
146 var subtitle = parentResourceHost !== urlComponents.host || frame.isMainFrame() && isMainResource ? WebInspector.displayNameForHost(urlComponents.host) : null;
147 this.subtitle = this.mainTitle !== subtitle ? subtitle : null;
149 if (oldMainTitle !== this.mainTitle)
150 this.callFirstAncestorFunction("descendantResourceTreeElementMainTitleDidChange", [this, oldMainTitle]);
157 if (this._resource.failed)
158 this.addClassName(WebInspector.ResourceTreeElement.FailedStyleClassName);
160 this.removeClassName(WebInspector.ResourceTreeElement.FailedStyleClassName);
162 if (this._resource.finished || this._resource.failed) {
163 // Remove the spinner and replace with a reload button in case it's the main frame's main resource.
164 var frame = this._resource.parentFrame;
165 if (this._resource.isMainResource() && frame && frame.isMainFrame() && this instanceof WebInspector.FrameTreeElement)
166 this.updateStatusForMainFrame();
170 var spinner = new WebInspector.IndeterminateProgressSpinner;
171 this.status = spinner.element;
177 this.tooltip = this._resource.url;
182 this._updateTitles();
183 this._updateToolTip();
186 _typeDidChange(event)
188 this.removeClassName(event.data.oldType);
189 this.addClassName(this._resource.type);
191 this.callFirstAncestorFunction("descendantResourceTreeElementTypeDidChange", [this, event.data.oldType]);
195 WebInspector.ResourceTreeElement.ResourceIconStyleClassName = "resource-icon";
196 WebInspector.ResourceTreeElement.FailedStyleClassName = "failed";