Web Inspector: Include Beacon and Ping requests in Network tab
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / ResourceContentView.js
1 /*
2  * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 WI.ResourceContentView = class ResourceContentView extends WI.ContentView
27 {
28     constructor(resource, styleClassName)
29     {
30         console.assert(resource instanceof WI.Resource || resource instanceof WI.CSSStyleSheet, resource);
31         console.assert(typeof styleClassName === "string");
32
33         super(resource);
34
35         this._resource = resource;
36
37         this.element.classList.add(styleClassName, "resource");
38
39         this._spinnerTimeout = setTimeout(() => {
40             // Append a spinner while waiting for contentAvailable. Subclasses are responsible for
41             // removing the spinner before showing the resource content by calling removeLoadingIndicator.
42             let spinner = new WI.IndeterminateProgressSpinner;
43             this.element.appendChild(spinner.element);
44
45             this._spinnerTimeout = undefined;
46         }, 100);
47
48         this.element.addEventListener("click", this._mouseWasClicked.bind(this), false);
49
50         // Request content last so the spinner will always be removed in case the content is immediately available.
51         resource.requestContent().then(this._contentAvailable.bind(this)).catch(this.showGenericErrorMessage.bind(this));
52
53         if (!this.managesOwnIssues) {
54             WI.issueManager.addEventListener(WI.IssueManager.Event.IssueWasAdded, this._issueWasAdded, this);
55
56             var issues = WI.issueManager.issuesForSourceCode(resource);
57             for (var i = 0; i < issues.length; ++i)
58                 this.addIssue(issues[i]);
59         }
60     }
61
62     // Public
63
64     get resource()
65     {
66         return this._resource;
67     }
68
69     get supportsSave()
70     {
71         return this._resource.finished;
72     }
73
74     get saveData()
75     {
76         return {url: this._resource.url, content: this._resource.content};
77     }
78
79     contentAvailable(content, base64Encoded)
80     {
81         // Implemented by subclasses.
82     }
83
84     showGenericErrorMessage()
85     {
86         this._contentError(WI.UIString("An error occurred trying to load the resource."));
87     }
88
89     showMessage(message)
90     {
91         this.element.removeChildren();
92         this.element.appendChild(WI.createMessageTextView(message));
93     }
94
95     addIssue(issue)
96     {
97         // This generically shows only the last issue, subclasses can override for better handling.
98         this.element.removeChildren();
99         this.element.appendChild(WI.createMessageTextView(issue.text, issue.level === WI.IssueMessage.Level.Error));
100     }
101
102     closed()
103     {
104         super.closed();
105
106         if (!this.managesOwnIssues)
107             WI.issueManager.removeEventListener(null, null, this);
108     }
109
110     // Protected
111
112     removeLoadingIndicator()
113     {
114         if (this._spinnerTimeout) {
115             clearTimeout(this._spinnerTimeout);
116             this._spinnerTimeout = undefined;
117         }
118
119         this.element.removeChildren();
120     }
121
122     // Private
123
124     _contentAvailable(parameters)
125     {
126         if (parameters.error) {
127             this._contentError(parameters.error);
128             return;
129         }
130
131         // Content is ready to show, call the public method now.
132         console.assert(!this._hasContent());
133         console.assert(parameters.sourceCode === this._resource);
134         this.contentAvailable(parameters.sourceCode.content, parameters.base64Encoded);
135     }
136
137     _contentError(error)
138     {
139         if (this._hasContent())
140             return;
141
142         this.removeLoadingIndicator();
143
144         this.element.appendChild(WI.createMessageTextView(error, true));
145
146         this.dispatchEventToListeners(WI.ResourceContentView.Event.ContentError);
147     }
148
149     _hasContent()
150     {
151         return this.element.hasChildNodes() && !this.element.querySelector(".indeterminate-progress-spinner");
152     }
153
154     _issueWasAdded(event)
155     {
156         console.assert(!this.managesOwnIssues);
157
158         var issue = event.data.issue;
159         if (!WI.IssueManager.issueMatchSourceCode(issue, this.resource))
160             return;
161
162         this.addIssue(issue);
163     }
164
165     _mouseWasClicked(event)
166     {
167         WI.handlePossibleLinkClick(event, this.resource.parentFrame);
168     }
169 };
170
171 WI.ResourceContentView.Event = {
172     ContentError: "resource-content-view-content-error",
173 };