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

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

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

Powered by Google App Engine
This is Rietveld 408576698