Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(326)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/sdk/HAREntry.js

Issue 2758673002: [DevTools] Extract NetworkLog and HAREntry to a separate network_log module (Closed)
Patch Set: rebased Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2012 Google 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 are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 // See http://www.softwareishard.com/blog/har-12-spec/
31 // for HAR specification.
32
33 // FIXME: Some fields are not yet supported due to back-end limitations.
34 // See https://bugs.webkit.org/show_bug.cgi?id=58127 for details.
35
36 /**
37 * @unrestricted
38 */
39 SDK.HAREntry = class {
40 /**
41 * @param {!SDK.NetworkRequest} request
42 */
43 constructor(request) {
44 this._request = request;
45 }
46
47 /**
48 * @param {number} time
49 * @return {number}
50 */
51 static _toMilliseconds(time) {
52 return time === -1 ? -1 : time * 1000;
53 }
54
55 /**
56 * @return {!Object}
57 */
58 build() {
59 var ipAddress = this._request.remoteAddress();
60 var portPositionInString = ipAddress.lastIndexOf(':');
61 if (portPositionInString !== -1)
62 ipAddress = ipAddress.substr(0, portPositionInString);
63
64 var entry = {
65 startedDateTime: SDK.HARLog.pseudoWallTime(this._request, this._request.st artTime),
66 time: this._request.timing ? SDK.HAREntry._toMilliseconds(this._request.du ration) : 0,
67 request: this._buildRequest(),
68 response: this._buildResponse(),
69 cache: {}, // Not supported yet.
70 timings: this._buildTimings(),
71 serverIPAddress: ipAddress
72 };
73
74 if (this._request.connectionId !== '0')
75 entry.connection = this._request.connectionId;
76 var page = SDK.networkLog.pageLoadForRequest(this._request);
77 if (page)
78 entry.pageref = 'page_' + page.id;
79 return entry;
80 }
81
82 /**
83 * @return {!Object}
84 */
85 _buildRequest() {
86 var headersText = this._request.requestHeadersText();
87 var res = {
88 method: this._request.requestMethod,
89 url: this._buildRequestURL(this._request.url()),
90 httpVersion: this._request.requestHttpVersion(),
91 headers: this._request.requestHeaders(),
92 queryString: this._buildParameters(this._request.queryParameters || []),
93 cookies: this._buildCookies(this._request.requestCookies || []),
94 headersSize: headersText ? headersText.length : -1,
95 bodySize: this.requestBodySize
96 };
97 if (this._request.requestFormData)
98 res.postData = this._buildPostData();
99
100 return res;
101 }
102
103 /**
104 * @return {!Object}
105 */
106 _buildResponse() {
107 var headersText = this._request.responseHeadersText;
108 return {
109 status: this._request.statusCode,
110 statusText: this._request.statusText,
111 httpVersion: this._request.responseHttpVersion(),
112 headers: this._request.responseHeaders,
113 cookies: this._buildCookies(this._request.responseCookies || []),
114 content: this._buildContent(),
115 redirectURL: this._request.responseHeaderValue('Location') || '',
116 headersSize: headersText ? headersText.length : -1,
117 bodySize: this.responseBodySize,
118 _transferSize: this._request.transferSize,
119 _error: this._request.localizedFailDescription
120 };
121 }
122
123 /**
124 * @return {!Object}
125 */
126 _buildContent() {
127 var content = {
128 size: this._request.resourceSize,
129 mimeType: this._request.mimeType || 'x-unknown',
130 // text: this._request.content // TODO: pull out into a boolean flag, as c ontent can be huge (and needs to be requested with an async call)
131 };
132 var compression = this.responseCompression;
133 if (typeof compression === 'number')
134 content.compression = compression;
135 return content;
136 }
137
138 /**
139 * @return {!Object}
140 */
141 _buildTimings() {
142 // Order of events: request_start = 0, [proxy], [dns], [connect [ssl]], [sen d], receive_headers_end
143 // HAR 'blocked' time is time before first network activity.
144
145 var timing = this._request.timing;
146 if (!timing)
147 return {blocked: -1, dns: -1, connect: -1, send: 0, wait: 0, receive: 0, s sl: -1};
148
149 function firstNonNegative(values) {
150 for (var i = 0; i < values.length; ++i) {
151 if (values[i] >= 0)
152 return values[i];
153 }
154 console.assert(false, 'Incomplete request timing information.');
155 }
156
157 var blocked = firstNonNegative([timing.dnsStart, timing.connectStart, timing .sendStart]);
158
159 var dns = -1;
160 if (timing.dnsStart >= 0)
161 dns = firstNonNegative([timing.connectStart, timing.sendStart]) - timing.d nsStart;
162
163 var connect = -1;
164 if (timing.connectStart >= 0)
165 connect = timing.sendStart - timing.connectStart;
166
167 var send = timing.sendEnd - timing.sendStart;
168 var wait = timing.receiveHeadersEnd - timing.sendEnd;
169 var receive = SDK.HAREntry._toMilliseconds(this._request.duration) - timing. receiveHeadersEnd;
170
171 var ssl = -1;
172 if (timing.sslStart >= 0 && timing.sslEnd >= 0)
173 ssl = timing.sslEnd - timing.sslStart;
174
175 return {blocked: blocked, dns: dns, connect: connect, send: send, wait: wait , receive: receive, ssl: ssl};
176 }
177
178 /**
179 * @return {!Object}
180 */
181 _buildPostData() {
182 var res = {mimeType: this._request.requestContentType(), text: this._request .requestFormData};
183 if (this._request.formParameters)
184 res.params = this._buildParameters(this._request.formParameters);
185 return res;
186 }
187
188 /**
189 * @param {!Array.<!Object>} parameters
190 * @return {!Array.<!Object>}
191 */
192 _buildParameters(parameters) {
193 return parameters.slice();
194 }
195
196 /**
197 * @param {string} url
198 * @return {string}
199 */
200 _buildRequestURL(url) {
201 return url.split('#', 2)[0];
202 }
203
204 /**
205 * @param {!Array.<!SDK.Cookie>} cookies
206 * @return {!Array.<!Object>}
207 */
208 _buildCookies(cookies) {
209 return cookies.map(this._buildCookie.bind(this));
210 }
211
212 /**
213 * @param {!SDK.Cookie} cookie
214 * @return {!Object}
215 */
216 _buildCookie(cookie) {
217 var c = {
218 name: cookie.name(),
219 value: cookie.value(),
220 path: cookie.path(),
221 domain: cookie.domain(),
222 expires: cookie.expiresDate(SDK.HARLog.pseudoWallTime(this._request, this. _request.startTime)),
223 httpOnly: cookie.httpOnly(),
224 secure: cookie.secure()
225 };
226 if (cookie.sameSite())
227 c.sameSite = cookie.sameSite();
228 return c;
229 }
230
231 /**
232 * @return {number}
233 */
234 get requestBodySize() {
235 return !this._request.requestFormData ? 0 : this._request.requestFormData.le ngth;
236 }
237
238 /**
239 * @return {number}
240 */
241 get responseBodySize() {
242 if (this._request.cached() || this._request.statusCode === 304)
243 return 0;
244 if (!this._request.responseHeadersText)
245 return -1;
246 return this._request.transferSize - this._request.responseHeadersText.length ;
247 }
248
249 /**
250 * @return {number|undefined}
251 */
252 get responseCompression() {
253 if (this._request.cached() || this._request.statusCode === 304 || this._requ est.statusCode === 206)
254 return;
255 if (!this._request.responseHeadersText)
256 return;
257 return this._request.resourceSize - this.responseBodySize;
258 }
259 };
260
261
262 /**
263 * @unrestricted
264 */
265 SDK.HARLog = class {
266 /**
267 * @param {!Array.<!SDK.NetworkRequest>} requests
268 */
269 constructor(requests) {
270 this._requests = requests;
271 }
272
273 /**
274 * @param {!SDK.NetworkRequest} request
275 * @param {number} monotonicTime
276 * @return {!Date}
277 */
278 static pseudoWallTime(request, monotonicTime) {
279 return new Date(request.pseudoWallTime(monotonicTime) * 1000);
280 }
281
282 /**
283 * @return {!Object}
284 */
285 build() {
286 return {
287 version: '1.2',
288 creator: this._creator(),
289 pages: this._buildPages(),
290 entries: this._requests.map(this._convertResource.bind(this))
291 };
292 }
293
294 _creator() {
295 var webKitVersion = /AppleWebKit\/([^ ]+)/.exec(window.navigator.userAgent);
296
297 return {name: 'WebInspector', version: webKitVersion ? webKitVersion[1] : 'n /a'};
298 }
299
300 /**
301 * @return {!Array.<!Object>}
302 */
303 _buildPages() {
304 var seenIdentifiers = {};
305 var pages = [];
306 for (var i = 0; i < this._requests.length; ++i) {
307 var request = this._requests[i];
308 var page = SDK.networkLog.pageLoadForRequest(request);
309 if (!page || seenIdentifiers[page.id])
310 continue;
311 seenIdentifiers[page.id] = true;
312 pages.push(this._convertPage(page, request));
313 }
314 return pages;
315 }
316
317 /**
318 * @param {!SDK.PageLoad} page
319 * @param {!SDK.NetworkRequest} request
320 * @return {!Object}
321 */
322 _convertPage(page, request) {
323 return {
324 startedDateTime: SDK.HARLog.pseudoWallTime(request, page.startTime),
325 id: 'page_' + page.id,
326 title: page.url, // We don't have actual page title here. URL is probably better than nothing.
327 pageTimings: {
328 onContentLoad: this._pageEventTime(page, page.contentLoadTime),
329 onLoad: this._pageEventTime(page, page.loadTime)
330 }
331 };
332 }
333
334 /**
335 * @param {!SDK.NetworkRequest} request
336 * @return {!Object}
337 */
338 _convertResource(request) {
339 return (new SDK.HAREntry(request)).build();
340 }
341
342 /**
343 * @param {!SDK.PageLoad} page
344 * @param {number} time
345 * @return {number}
346 */
347 _pageEventTime(page, time) {
348 var startTime = page.startTime;
349 if (time === -1 || startTime === -1)
350 return -1;
351 return SDK.HAREntry._toMilliseconds(time - startTime);
352 }
353 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698