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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/audits/AuditRules.js

Issue 2627073003: [Devtools] Fixed url in Audits and added doctypes (Closed)
Patch Set: Created 3 years, 11 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 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
(...skipping 11 matching lines...) Expand all
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 Audits.AuditRules.IPAddressRegexp = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; 30 Audits.AuditRules.IPAddressRegexp = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
31 31
32 /** @type {!Object<number, boolean>} */
32 Audits.AuditRules.CacheableResponseCodes = { 33 Audits.AuditRules.CacheableResponseCodes = {
33 200: true, 34 200: true,
34 203: true, 35 203: true,
35 206: true, 36 206: true,
36 300: true, 37 300: true,
37 301: true, 38 301: true,
38 410: true, 39 410: true,
39 40
40 304: true // Underlying request is cacheable 41 304: true // Underlying request is cacheable
41 }; 42 };
42 43
43 /** 44 /**
44 * @param {!Array.<!SDK.NetworkRequest>} requests 45 * @param {!Array<!SDK.NetworkRequest>} requests
45 * @param {?Array.<!Common.ResourceType>} types 46 * @param {?Array<!Common.ResourceType>} types
46 * @param {boolean} needFullResources 47 * @return {!Object<string, !Array<!SDK.NetworkRequest>>}
47 * @return {!Object.<string, !Array.<!SDK.NetworkRequest|string>>}
48 */ 48 */
49 Audits.AuditRules.getDomainToResourcesMap = function(requests, types, needFullRe sources) { 49 Audits.AuditRules.getDomainToResourcesMap = function(requests, types) {
50 /** @type {!Object<string, !Array<!SDK.NetworkRequest|string>>} */ 50 /** @type {!Object<string, !Array<!SDK.NetworkRequest>>} */
51 var domainToResourcesMap = {}; 51 var domainToResourcesMap = {};
52 for (var i = 0, size = requests.length; i < size; ++i) { 52 for (var i = 0, size = requests.length; i < size; ++i) {
53 var request = requests[i]; 53 var request = requests[i];
54 if (types && types.indexOf(request.resourceType()) === -1) 54 if (types && types.indexOf(request.resourceType()) === -1)
55 continue; 55 continue;
56 var parsedURL = request.url().asParsedURL(); 56 var parsedURL = request.url().asParsedURL();
57 if (!parsedURL) 57 if (!parsedURL)
58 continue; 58 continue;
59 var domain = parsedURL.host; 59 var domain = parsedURL.host;
60 var domainResources = domainToResourcesMap[domain]; 60 var domainResources = domainToResourcesMap[domain];
61 if (domainResources === undefined) { 61 if (domainResources === undefined) {
62 domainResources = /** @type {!Array<!SDK.NetworkRequest|string>} */ ([]); 62 domainResources = /** @type {!Array<!SDK.NetworkRequest>} */ ([]);
63 domainToResourcesMap[domain] = domainResources; 63 domainToResourcesMap[domain] = domainResources;
64 } 64 }
65 domainResources.push(needFullResources ? request : request.url()); 65 domainResources.push(request);
66 } 66 }
67 return domainToResourcesMap; 67 return domainToResourcesMap;
68 }; 68 };
69 69
70 /** 70 /**
71 * @param {!Array<!SDK.NetworkRequest>} requests
72 * @param {?Array<!Common.ResourceType>} types
73 * @return {!Object<string, !Array<string>>}
74 */
75 Audits.AuditRules.getDomainToResourceUrlMap = function(requests, types) {
luoe 2017/01/13 08:05:22 I don't think this new function is needed. The pl
allada 2017/01/17 19:16:25 line: 245 does.
luoe 2017/01/17 19:40:16 Line 245 is using "domain", the keys of the map, n
allada 2017/01/17 19:50:11 Done.
76 var requestMap = Audits.AuditRules.getDomainToResourcesMap(requests, types);
77 /** @type {!Object<string, !Array<string>>} */
78 var output = {};
alph 2017/01/12 07:54:42 nit: can you plz use Map as assigning arbitrary ke
allada 2017/01/12 23:49:31 I don't want to do this because this patch is not
79 for (var domain of Object.keys(requestMap))
80 output[domain] = requestMap[domain].map(request => request.url());
81 return output;
82 };
83
84 /**
71 * @unrestricted 85 * @unrestricted
72 */ 86 */
73 Audits.AuditRules.GzipRule = class extends Audits.AuditRule { 87 Audits.AuditRules.GzipRule = class extends Audits.AuditRule {
74 constructor() { 88 constructor() {
75 super('network-gzip', Common.UIString('Enable gzip compression')); 89 super('network-gzip', Common.UIString('Enable gzip compression'));
76 } 90 }
77 91
78 /** 92 /**
79 * @override 93 * @override
80 * @param {!SDK.Target} target 94 * @param {!SDK.Target} target
81 * @param {!Array.<!SDK.NetworkRequest>} requests 95 * @param {!Array.<!SDK.NetworkRequest>} requests
luoe 2017/01/13 08:05:22 Remove period here and in all the places where the
allada 2017/01/17 19:16:25 This patch isn't here to fix legacy doctypes.
82 * @param {!Audits.AuditRuleResult} result 96 * @param {!Audits.AuditRuleResult} result
83 * @param {function(?Audits.AuditRuleResult)} callback 97 * @param {function(?Audits.AuditRuleResult)} callback
84 * @param {!Common.Progress} progress 98 * @param {!Common.Progress} progress
85 */ 99 */
86 doRun(target, requests, result, callback, progress) { 100 doRun(target, requests, result, callback, progress) {
87 var totalSavings = 0; 101 var totalSavings = 0;
88 var summary = result.addChild('', true); 102 var summary = result.addChild('', true);
89 for (var i = 0, length = requests.length; i < length; ++i) { 103 for (var i = 0, length = requests.length; i < length; ++i) {
90 var request = requests[i]; 104 var request = requests[i];
91 if (request.cached() || request.statusCode === 304) 105 if (request.cached() || request.statusCode === 304)
(...skipping 12 matching lines...) Expand all
104 callback(null); 118 callback(null);
105 return; 119 return;
106 } 120 }
107 summary.value = Common.UIString( 121 summary.value = Common.UIString(
108 'Compressing the following resources with gzip could reduce their transf er size by about two thirds (~%s):', 122 'Compressing the following resources with gzip could reduce their transf er size by about two thirds (~%s):',
109 Number.bytesToString(totalSavings)); 123 Number.bytesToString(totalSavings));
110 callback(result); 124 callback(result);
111 } 125 }
112 126
113 /** 127 /**
114 * @param {!SDK.NetworkRequest} request 128 * @param {!SDK.NetworkRequest} request
luoe 2017/01/13 08:05:22 Missing @return here and in many other functions
allada 2017/01/17 19:16:25 This patch isn't here to fix legacy doctypes.
115 */ 129 */
116 _isCompressed(request) { 130 _isCompressed(request) {
117 var encodingHeader = request.responseHeaderValue('Content-Encoding'); 131 var encodingHeader = request.responseHeaderValue('Content-Encoding');
118 if (!encodingHeader) 132 if (!encodingHeader)
119 return false; 133 return false;
120 134
121 return /\b(?:gzip|deflate)\b/.test(encodingHeader); 135 return /\b(?:gzip|deflate)\b/.test(encodingHeader);
122 } 136 }
123 137
124 /** 138 /**
(...skipping 25 matching lines...) Expand all
150 164
151 /** 165 /**
152 * @override 166 * @override
153 * @param {!SDK.Target} target 167 * @param {!SDK.Target} target
154 * @param {!Array.<!SDK.NetworkRequest>} requests 168 * @param {!Array.<!SDK.NetworkRequest>} requests
155 * @param {!Audits.AuditRuleResult} result 169 * @param {!Audits.AuditRuleResult} result
156 * @param {function(?Audits.AuditRuleResult)} callback 170 * @param {function(?Audits.AuditRuleResult)} callback
157 * @param {!Common.Progress} progress 171 * @param {!Common.Progress} progress
158 */ 172 */
159 doRun(target, requests, result, callback, progress) { 173 doRun(target, requests, result, callback, progress) {
160 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap(request s, [this._type], false); 174 var domainToResourcesMap = Audits.AuditRules.getDomainToResourceUrlMap(reque sts, [this._type]);
161 var penalizedResourceCount = 0; 175 var penalizedResourceCount = 0;
162 // TODO: refactor according to the chosen i18n approach 176 // TODO: refactor according to the chosen i18n approach
163 var summary = result.addChild('', true); 177 var summary = result.addChild('', true);
164 for (var domain in domainToResourcesMap) { 178 for (var domain in domainToResourcesMap) {
165 var domainResources = domainToResourcesMap[domain]; 179 var domainResources = domainToResourcesMap[domain];
166 var extraResourceCount = domainResources.length - this._allowedPerDomain; 180 var extraResourceCount = domainResources.length - this._allowedPerDomain;
167 if (extraResourceCount <= 0) 181 if (extraResourceCount <= 0)
168 continue; 182 continue;
169 penalizedResourceCount += extraResourceCount - 1; 183 penalizedResourceCount += extraResourceCount - 1;
170 summary.addChild(Common.UIString( 184 summary.addChild(Common.UIString(
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 /** 231 /**
218 * @override 232 * @override
219 * @param {!SDK.Target} target 233 * @param {!SDK.Target} target
220 * @param {!Array.<!SDK.NetworkRequest>} requests 234 * @param {!Array.<!SDK.NetworkRequest>} requests
221 * @param {!Audits.AuditRuleResult} result 235 * @param {!Audits.AuditRuleResult} result
222 * @param {function(?Audits.AuditRuleResult)} callback 236 * @param {function(?Audits.AuditRuleResult)} callback
223 * @param {!Common.Progress} progress 237 * @param {!Common.Progress} progress
224 */ 238 */
225 doRun(target, requests, result, callback, progress) { 239 doRun(target, requests, result, callback, progress) {
226 var summary = result.addChild(''); 240 var summary = result.addChild('');
227 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap(request s, null, false); 241 var domainToResourcesMap = Audits.AuditRules.getDomainToResourceUrlMap(reque sts, null);
228 for (var domain in domainToResourcesMap) { 242 for (var domain in domainToResourcesMap) {
229 if (domainToResourcesMap[domain].length > 1) 243 if (domainToResourcesMap[domain].length > 1)
230 continue; 244 continue;
231 var parsedURL = domain.asParsedURL(); 245 var parsedURL = domain.asParsedURL();
232 if (!parsedURL) 246 if (!parsedURL)
233 continue; 247 continue;
234 if (!parsedURL.host.search(Audits.AuditRules.IPAddressRegexp)) 248 if (!parsedURL.host.search(Audits.AuditRules.IPAddressRegexp))
235 continue; // an IP address 249 continue; // an IP address
236 summary.addSnippet(domain); 250 summary.addSnippet(domain);
237 result.violationCount++; 251 result.violationCount++;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 * @param {string} a 285 * @param {string} a
272 * @param {string} b 286 * @param {string} b
273 */ 287 */
274 function hostSorter(a, b) { 288 function hostSorter(a, b) {
275 var aCount = domainToResourcesMap[a].length; 289 var aCount = domainToResourcesMap[a].length;
276 var bCount = domainToResourcesMap[b].length; 290 var bCount = domainToResourcesMap[b].length;
277 return (aCount < bCount) ? 1 : (aCount === bCount) ? 0 : -1; 291 return (aCount < bCount) ? 1 : (aCount === bCount) ? 0 : -1;
278 } 292 }
279 293
280 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap( 294 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap(
281 requests, [Common.resourceTypes.Stylesheet, Common.resourceTypes.Image], true); 295 requests, [Common.resourceTypes.Stylesheet, Common.resourceTypes.Image]) ;
282 296
297 /** @type {!Array<string>} */
283 var hosts = []; 298 var hosts = [];
284 for (var url in domainToResourcesMap) 299 for (var url in domainToResourcesMap)
285 hosts.push(url); 300 hosts.push(url);
286 301
287 if (!hosts.length) { 302 if (!hosts.length) {
288 callback(null); // no hosts (local file or something) 303 callback(null); // no hosts (local file or something)
289 return; 304 return;
290 } 305 }
291 306
292 hosts.sort(hostSorter); 307 hosts.sort(hostSorter);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 return; 374 return;
360 } 375 }
361 376
362 /** 377 /**
363 * @param {!Array.<!Audits.AuditRules.ParsedStyleSheet>} styleSheets 378 * @param {!Array.<!Audits.AuditRules.ParsedStyleSheet>} styleSheets
364 */ 379 */
365 function evalCallback(styleSheets) { 380 function evalCallback(styleSheets) {
366 if (!styleSheets.length) 381 if (!styleSheets.length)
367 return callback(null); 382 return callback(null);
368 383
384 /** @type {!Array<string>} */
369 var selectors = []; 385 var selectors = [];
386 /** @type {!Object<string, number>} */
370 var testedSelectors = {}; 387 var testedSelectors = {};
371 for (var i = 0; i < styleSheets.length; ++i) { 388 for (var i = 0; i < styleSheets.length; ++i) {
372 var styleSheet = styleSheets[i]; 389 var styleSheet = styleSheets[i];
373 for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) { 390 for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) {
374 var selectorText = styleSheet.rules[curRule].selectorText; 391 var selectorText = styleSheet.rules[curRule].selectorText;
375 if (testedSelectors[selectorText]) 392 if (testedSelectors[selectorText])
376 continue; 393 continue;
377 selectors.push(selectorText); 394 selectors.push(selectorText);
378 testedSelectors[selectorText] = 1; 395 testedSelectors[selectorText] = 1;
379 } 396 }
380 } 397 }
381 398
399 /** @type {!Object<string, boolean>} */
382 var foundSelectors = {}; 400 var foundSelectors = {};
383 401
384 /** 402 /**
385 * @param {!Array.<!Audits.AuditRules.ParsedStyleSheet>} styleSheets 403 * @param {!Array.<!Audits.AuditRules.ParsedStyleSheet>} styleSheets
386 */ 404 */
387 function selectorsCallback(styleSheets) { 405 function selectorsCallback(styleSheets) {
388 if (progress.isCanceled()) { 406 if (progress.isCanceled()) {
389 callback(null); 407 callback(null);
390 return; 408 return;
391 } 409 }
392 410
393 var inlineBlockOrdinal = 0; 411 var inlineBlockOrdinal = 0;
394 var totalStylesheetSize = 0; 412 var totalStylesheetSize = 0;
395 var totalUnusedStylesheetSize = 0; 413 var totalUnusedStylesheetSize = 0;
396 var summary; 414 var summary;
397 415
398 for (var i = 0; i < styleSheets.length; ++i) { 416 for (var i = 0; i < styleSheets.length; ++i) {
399 var styleSheet = styleSheets[i]; 417 var styleSheet = styleSheets[i];
418 /** @type {!Array<string>} */
400 var unusedRules = []; 419 var unusedRules = [];
401 for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) { 420 for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) {
402 var rule = styleSheet.rules[curRule]; 421 var rule = styleSheet.rules[curRule];
403 if (!testedSelectors[rule.selectorText] || foundSelectors[rule.selec torText]) 422 if (!testedSelectors[rule.selectorText] || foundSelectors[rule.selec torText])
404 continue; 423 continue;
405 unusedRules.push(rule.selectorText); 424 unusedRules.push(rule.selectorText);
406 } 425 }
407 totalStylesheetSize += styleSheet.rules.length; 426 totalStylesheetSize += styleSheet.rules.length;
408 totalUnusedStylesheetSize += unusedRules.length; 427 totalUnusedStylesheetSize += unusedRules.length;
409 428
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 */ 513 */
495 Audits.AuditRules.StyleSheetProcessor = class { 514 Audits.AuditRules.StyleSheetProcessor = class {
496 /** 515 /**
497 * @param {!Array.<!SDK.CSSStyleSheetHeader>} styleSheetHeaders 516 * @param {!Array.<!SDK.CSSStyleSheetHeader>} styleSheetHeaders
498 * @param {!Common.Progress} progress 517 * @param {!Common.Progress} progress
499 * @param {function(!Array.<!Audits.AuditRules.ParsedStyleSheet>)} styleSheets ParsedCallback 518 * @param {function(!Array.<!Audits.AuditRules.ParsedStyleSheet>)} styleSheets ParsedCallback
500 */ 519 */
501 constructor(styleSheetHeaders, progress, styleSheetsParsedCallback) { 520 constructor(styleSheetHeaders, progress, styleSheetsParsedCallback) {
502 this._styleSheetHeaders = styleSheetHeaders; 521 this._styleSheetHeaders = styleSheetHeaders;
503 this._progress = progress; 522 this._progress = progress;
523 /** @type {!Array<!Audits.AuditRules.ParsedStyleSheet>} */
504 this._styleSheets = []; 524 this._styleSheets = [];
505 this._styleSheetsParsedCallback = styleSheetsParsedCallback; 525 this._styleSheetsParsedCallback = styleSheetsParsedCallback;
506 } 526 }
507 527
508 run() { 528 run() {
509 this._processNextStyleSheet(); 529 this._processNextStyleSheet();
510 } 530 }
511 531
512 _processNextStyleSheet() { 532 _processNextStyleSheet() {
513 if (!this._styleSheetHeaders.length) { 533 if (!this._styleSheetHeaders.length) {
514 this._styleSheetsParsedCallback(this._styleSheets); 534 this._styleSheetsParsedCallback(this._styleSheets);
515 return; 535 return;
516 } 536 }
517 this._currentStyleSheetHeader = this._styleSheetHeaders.shift(); 537 this._currentStyleSheetHeader = this._styleSheetHeaders.shift();
518 538
539 /** @type {!Array<!Common.FormatterWorkerPool.CSSRule>} */
519 var allRules = []; 540 var allRules = [];
520 this._currentStyleSheetHeader.requestContent().then( 541 this._currentStyleSheetHeader.requestContent().then(
521 content => Common.formatterWorkerPool.parseCSS(content || '', onRulesPar sed.bind(this))); 542 content => Common.formatterWorkerPool.parseCSS(content || '', onRulesPar sed.bind(this)));
522 543
523 /** 544 /**
524 * @param {boolean} isLastChunk 545 * @param {boolean} isLastChunk
525 * @param {!Array<!Common.FormatterWorkerPool.CSSRule>} rules 546 * @param {!Array<!Common.FormatterWorkerPool.CSSRule>} rules
526 * @this {Audits.AuditRules.StyleSheetProcessor} 547 * @this {Audits.AuditRules.StyleSheetProcessor}
527 */ 548 */
528 function onRulesParsed(isLastChunk, rules) { 549 function onRulesParsed(isLastChunk, rules) {
529 allRules.push(...rules); 550 allRules.push.apply(allRules, rules);
luoe 2017/01/13 08:05:21 I'm not sure how large the "rules" array gets, but
allada 2017/01/17 19:16:25 Apply is better per kozyatinskiy@
530 if (isLastChunk) 551 if (isLastChunk)
531 this._onStyleSheetParsed(allRules); 552 this._onStyleSheetParsed(allRules);
532 } 553 }
533 } 554 }
534 555
535 /** 556 /**
536 * @param {!Array.<!Common.FormatterWorkerPool.CSSRule>} rules 557 * @param {!Array.<!Common.FormatterWorkerPool.CSSRule>} rules
537 */ 558 */
538 _onStyleSheetParsed(rules) { 559 _onStyleSheetParsed(rules) {
539 if (this._progress.isCanceled()) { 560 if (this._progress.isCanceled()) {
540 this._styleSheetsParsedCallback(this._styleSheets); 561 this._styleSheetsParsedCallback(this._styleSheets);
541 return; 562 return;
542 } 563 }
543 564
565 /** @type {!Array<!Common.FormatterWorkerPool.CSSRule>} */
544 var styleRules = []; 566 var styleRules = [];
545 for (var i = 0; i < rules.length; ++i) { 567 for (var i = 0; i < rules.length; ++i) {
546 var rule = rules[i]; 568 var rule = rules[i];
547 if (rule.selectorText) 569 if (rule.selectorText)
548 styleRules.push(rule); 570 styleRules.push(rule);
549 } 571 }
550 this._styleSheets.push({sourceURL: this._currentStyleSheetHeader.sourceURL, rules: styleRules}); 572 this._styleSheets.push({sourceURL: this._currentStyleSheetHeader.sourceURL, rules: styleRules});
551 this._processNextStyleSheet(); 573 this._processNextStyleSheet();
552 } 574 }
553 }; 575 };
(...skipping 16 matching lines...) Expand all
570 */ 592 */
571 doRun(target, requests, result, callback, progress) { 593 doRun(target, requests, result, callback, progress) {
572 var cacheableAndNonCacheableResources = this._cacheableAndNonCacheableResour ces(requests); 594 var cacheableAndNonCacheableResources = this._cacheableAndNonCacheableResour ces(requests);
573 if (cacheableAndNonCacheableResources[0].length) 595 if (cacheableAndNonCacheableResources[0].length)
574 this.runChecks(cacheableAndNonCacheableResources[0], result); 596 this.runChecks(cacheableAndNonCacheableResources[0], result);
575 this.handleNonCacheableResources(cacheableAndNonCacheableResources[1], resul t); 597 this.handleNonCacheableResources(cacheableAndNonCacheableResources[1], resul t);
576 598
577 callback(result); 599 callback(result);
578 } 600 }
579 601
602 /**
603 * @param {!Array<!SDK.NetworkRequest>} requests
604 * @param {!Audits.AuditRuleResult} result
605 */
580 handleNonCacheableResources(requests, result) { 606 handleNonCacheableResources(requests, result) {
581 } 607 }
582 608
609 /**
610 * @param {!Array<!SDK.NetworkRequest>} requests
611 * @return {!Array<!Array<!SDK.NetworkRequest>>}
612 */
583 _cacheableAndNonCacheableResources(requests) { 613 _cacheableAndNonCacheableResources(requests) {
614 /** @type {!Array<!Array<!SDK.NetworkRequest>>} */
584 var processedResources = [[], []]; 615 var processedResources = [[], []];
585 for (var i = 0; i < requests.length; ++i) { 616 for (var i = 0; i < requests.length; ++i) {
586 var request = requests[i]; 617 var request = requests[i];
587 if (!this.isCacheableResource(request)) 618 if (!this.isCacheableResource(request))
588 continue; 619 continue;
589 if (this._isExplicitlyNonCacheable(request)) 620 if (this._isExplicitlyNonCacheable(request))
590 processedResources[1].push(request); 621 processedResources[1].push(request);
591 else 622 else
592 processedResources[0].push(request); 623 processedResources[0].push(request);
593 } 624 }
594 return processedResources; 625 return processedResources;
595 } 626 }
596 627
628 /**
629 * @param {string} messageText
630 * @param {function(!SDK.NetworkRequest):boolean} requestCheckFunction
631 * @param {!Array<!SDK.NetworkRequest>} requests
632 * @param {!Audits.AuditRuleResult} result
633 */
597 execCheck(messageText, requestCheckFunction, requests, result) { 634 execCheck(messageText, requestCheckFunction, requests, result) {
598 var requestCount = requests.length; 635 var requestCount = requests.length;
636 /** @type {!Array<string>} */
599 var urls = []; 637 var urls = [];
600 for (var i = 0; i < requestCount; ++i) { 638 for (var i = 0; i < requestCount; ++i) {
601 if (requestCheckFunction.call(this, requests[i])) 639 if (requestCheckFunction.call(this, requests[i]))
602 urls.push(requests[i].url); 640 urls.push(requests[i].url());
603 } 641 }
604 if (urls.length) { 642 if (urls.length) {
605 var entry = result.addChild(messageText, true); 643 var entry = result.addChild(messageText, true);
606 entry.addURLs(urls); 644 entry.addURLs(urls);
607 result.violationCount += urls.length; 645 result.violationCount += urls.length;
608 } 646 }
609 } 647 }
610 648
611 /** 649 /**
612 * @param {!SDK.NetworkRequest} request 650 * @param {!SDK.NetworkRequest} request
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 /** 765 /**
728 * @unrestricted 766 * @unrestricted
729 */ 767 */
730 Audits.AuditRules.BrowserCacheControlRule = class extends Audits.AuditRules.Cach eControlRule { 768 Audits.AuditRules.BrowserCacheControlRule = class extends Audits.AuditRules.Cach eControlRule {
731 constructor() { 769 constructor() {
732 super('http-browsercache', Common.UIString('Leverage browser caching')); 770 super('http-browsercache', Common.UIString('Leverage browser caching'));
733 } 771 }
734 772
735 /** 773 /**
736 * @override 774 * @override
775 * @param {!Array<!SDK.NetworkRequest>} requests
776 * @param {!Audits.AuditRuleResult} result
737 */ 777 */
738 handleNonCacheableResources(requests, result) { 778 handleNonCacheableResources(requests, result) {
739 if (requests.length) { 779 if (requests.length) {
740 var entry = result.addChild( 780 var entry = result.addChild(
741 Common.UIString( 781 Common.UIString(
742 'The following resources are explicitly non-cacheable. Consider ma king them cacheable if possible:'), 782 'The following resources are explicitly non-cacheable. Consider ma king them cacheable if possible:'),
743 true); 783 true);
744 result.violationCount += requests.length; 784 result.violationCount += requests.length;
745 for (var i = 0; i < requests.length; ++i) 785 for (var i = 0; i < requests.length; ++i)
746 entry.addURL(requests[i].url); 786 entry.addURL(requests[i].url());
747 } 787 }
748 } 788 }
749 789
750 runChecks(requests, result, callback) { 790 /**
791 * @param {!Array<!SDK.NetworkRequest>} requests
792 * @param {!Audits.AuditRuleResult} result
793 */
794 runChecks(requests, result) {
751 this.execCheck( 795 this.execCheck(
752 Common.UIString( 796 Common.UIString(
753 'The following resources are missing a cache expiration. Resources t hat do not specify an expiration may not be cached by browsers:'), 797 'The following resources are missing a cache expiration. Resources t hat do not specify an expiration may not be cached by browsers:'),
754 this._missingExpirationCheck, requests, result); 798 this._missingExpirationCheck, requests, result);
755 this.execCheck( 799 this.execCheck(
756 Common.UIString( 800 Common.UIString(
757 'The following resources specify a "Vary" header that disables cachi ng in most versions of Internet Explorer:'), 801 'The following resources specify a "Vary" header that disables cachi ng in most versions of Internet Explorer:'),
758 this._varyCheck, requests, result); 802 this._varyCheck, requests, result);
759 this.execCheck( 803 this.execCheck(
760 Common.UIString('The following cacheable resources have a short freshnes s lifetime:'), 804 Common.UIString('The following cacheable resources have a short freshnes s lifetime:'),
761 this._oneMonthExpirationCheck, requests, result); 805 this._oneMonthExpirationCheck, requests, result);
762 806
763 // Unable to implement the favicon check due to the WebKit limitations. 807 // Unable to implement the favicon check due to the WebKit limitations.
764 this.execCheck( 808 this.execCheck(
765 Common.UIString( 809 Common.UIString(
766 'To further improve cache hit rate, specify an expiration one year i n the future for the following cacheable resources:'), 810 'To further improve cache hit rate, specify an expiration one year i n the future for the following cacheable resources:'),
767 this._oneYearExpirationCheck, requests, result); 811 this._oneYearExpirationCheck, requests, result);
768 } 812 }
769 813
814 /**
815 * @param {!SDK.NetworkRequest} request
816 * @return {boolean}
817 */
770 _missingExpirationCheck(request) { 818 _missingExpirationCheck(request) {
771 return this.isCacheableResource(request) && !this.hasResponseHeader(request, 'Set-Cookie') && 819 return this.isCacheableResource(request) && !this.hasResponseHeader(request, 'Set-Cookie') &&
772 !this.hasExplicitExpiration(request); 820 !this.hasExplicitExpiration(request);
773 } 821 }
774 822
823 /**
824 * @param {!SDK.NetworkRequest} request
825 * @return {boolean}
826 */
775 _varyCheck(request) { 827 _varyCheck(request) {
776 var varyHeader = this.responseHeader(request, 'Vary'); 828 var varyHeader = this.responseHeader(request, 'Vary');
777 if (varyHeader) { 829 if (varyHeader) {
778 varyHeader = varyHeader.replace(/User-Agent/gi, ''); 830 varyHeader = varyHeader.replace(/User-Agent/gi, '');
779 varyHeader = varyHeader.replace(/Accept-Encoding/gi, ''); 831 varyHeader = varyHeader.replace(/Accept-Encoding/gi, '');
780 varyHeader = varyHeader.replace(/[, ]*/g, ''); 832 varyHeader = varyHeader.replace(/[, ]*/g, '');
781 } 833 }
782 return varyHeader && varyHeader.length && this.isCacheableResource(request) && 834 return !!(
783 this.freshnessLifetimeGreaterThan(request, 0); 835 varyHeader && varyHeader.length && this.isCacheableResource(request) &&
836 this.freshnessLifetimeGreaterThan(request, 0));
784 } 837 }
785 838
839 /**
840 * @param {!SDK.NetworkRequest} request
841 * @return {boolean}
842 */
786 _oneMonthExpirationCheck(request) { 843 _oneMonthExpirationCheck(request) {
787 return this.isCacheableResource(request) && !this.hasResponseHeader(request, 'Set-Cookie') && 844 return this.isCacheableResource(request) && !this.hasResponseHeader(request, 'Set-Cookie') &&
788 !this.freshnessLifetimeGreaterThan(request, Audits.AuditRules.CacheContr olRule.MillisPerMonth) && 845 !this.freshnessLifetimeGreaterThan(request, Audits.AuditRules.CacheContr olRule.MillisPerMonth) &&
789 this.freshnessLifetimeGreaterThan(request, 0); 846 this.freshnessLifetimeGreaterThan(request, 0);
790 } 847 }
791 848
849 /**
850 * @param {!SDK.NetworkRequest} request
851 * @return {boolean}
852 */
792 _oneYearExpirationCheck(request) { 853 _oneYearExpirationCheck(request) {
793 return this.isCacheableResource(request) && !this.hasResponseHeader(request, 'Set-Cookie') && 854 return this.isCacheableResource(request) && !this.hasResponseHeader(request, 'Set-Cookie') &&
794 !this.freshnessLifetimeGreaterThan(request, 11 * Audits.AuditRules.Cache ControlRule.MillisPerMonth) && 855 !this.freshnessLifetimeGreaterThan(request, 11 * Audits.AuditRules.Cache ControlRule.MillisPerMonth) &&
795 this.freshnessLifetimeGreaterThan(request, Audits.AuditRules.CacheContro lRule.MillisPerMonth); 856 this.freshnessLifetimeGreaterThan(request, Audits.AuditRules.CacheContro lRule.MillisPerMonth);
796 } 857 }
797 }; 858 };
798 859
799 /** 860 /**
800 * @unrestricted 861 * @unrestricted
801 */ 862 */
(...skipping 11 matching lines...) Expand all
813 * @param {!Common.Progress} progress 874 * @param {!Common.Progress} progress
814 */ 875 */
815 doRun(target, requests, result, callback, progress) { 876 doRun(target, requests, result, callback, progress) {
816 var domModel = SDK.DOMModel.fromTarget(target); 877 var domModel = SDK.DOMModel.fromTarget(target);
817 var cssModel = SDK.CSSModel.fromTarget(target); 878 var cssModel = SDK.CSSModel.fromTarget(target);
818 if (!domModel || !cssModel) { 879 if (!domModel || !cssModel) {
819 callback(null); 880 callback(null);
820 return; 881 return;
821 } 882 }
822 883
884 /** @type {!Object<string,number>} */
luoe 2017/01/13 08:05:22 Nit: space after comma
allada 2017/01/17 19:16:25 Done.
823 var urlToNoDimensionCount = {}; 885 var urlToNoDimensionCount = {};
824 886
825 function doneCallback() { 887 function doneCallback() {
826 for (var url in urlToNoDimensionCount) { 888 for (var url in urlToNoDimensionCount) {
827 var entry = entry || 889 var entry = entry ||
828 result.addChild( 890 result.addChild(
829 Common.UIString( 891 Common.UIString(
830 'A width and height should be specified for all images in or der to speed up page display. The following image(s) are missing a width and/or height:'), 892 'A width and height should be specified for all images in or der to speed up page display. The following image(s) are missing a width and/or height:'),
831 true); 893 true);
832 var format = '%r'; 894 var format = '%r';
833 if (urlToNoDimensionCount[url] > 1) 895 if (urlToNoDimensionCount[url] > 1)
834 format += ' (%d uses)'; 896 format += ' (%d uses)';
835 entry.addFormatted(format, url, urlToNoDimensionCount[url]); 897 entry.addFormatted(format, url, urlToNoDimensionCount[url]);
836 result.violationCount++; 898 result.violationCount++;
837 } 899 }
838 callback(entry ? result : null); 900 callback(entry ? result : null);
839 } 901 }
840 902
903 /**
904 * @param {number} imageId
905 * @param {!{nodeStyles: (!Array<!SDK.CSSStyleDeclaration>|undefined), compu tedStyle: (?Map<string, string>|undefined)}} styles
906 */
841 function imageStylesReady(imageId, styles) { 907 function imageStylesReady(imageId, styles) {
842 if (progress.isCanceled()) { 908 if (progress.isCanceled()) {
843 callback(null); 909 callback(null);
844 return; 910 return;
845 } 911 }
846 912
847 const node = domModel.nodeForId(imageId); 913 const node = domModel.nodeForId(imageId);
848 var src = node.getAttribute('src'); 914 var src = node.getAttribute('src');
849 if (!src.asParsedURL()) { 915 if (!src.asParsedURL()) {
850 for (var frameOwnerCandidate = node; frameOwnerCandidate; 916 for (var frameOwnerCandidate = node; frameOwnerCandidate;
(...skipping 29 matching lines...) Expand all
880 } 946 }
881 947
882 /** 948 /**
883 * @param {!Array.<!Protocol.DOM.NodeId>=} nodeIds 949 * @param {!Array.<!Protocol.DOM.NodeId>=} nodeIds
884 */ 950 */
885 function getStyles(nodeIds) { 951 function getStyles(nodeIds) {
886 if (progress.isCanceled()) { 952 if (progress.isCanceled()) {
887 callback(null); 953 callback(null);
888 return; 954 return;
889 } 955 }
956 /** @type {!{nodeStyles: (!Array<!SDK.CSSStyleDeclaration>|undefined), com putedStyle: (?Map<string, string>|undefined)}} */
890 var targetResult = {}; 957 var targetResult = {};
891 958
892 /** 959 /**
893 * @param {?SDK.CSSMatchedStyles} matchedStyleResult 960 * @param {?SDK.CSSMatchedStyles} matchedStyleResult
894 */ 961 */
895 function matchedCallback(matchedStyleResult) { 962 function matchedCallback(matchedStyleResult) {
896 if (!matchedStyleResult) 963 if (!matchedStyleResult)
897 return; 964 return;
898 targetResult.nodeStyles = matchedStyleResult.nodeStyles(); 965 targetResult.nodeStyles = matchedStyleResult.nodeStyles();
899 } 966 }
900 967
901 /** 968 /**
902 * @param {?Map.<string, string>} computedStyle 969 * @param {?Map.<string, string>} computedStyle
903 */ 970 */
904 function computedCallback(computedStyle) { 971 function computedCallback(computedStyle) {
905 targetResult.computedStyle = computedStyle; 972 targetResult.computedStyle = computedStyle;
906 } 973 }
907 974
908 if (!nodeIds || !nodeIds.length) 975 if (!nodeIds || !nodeIds.length)
909 doneCallback(); 976 doneCallback();
910 977
978 /** @type {!Array<!Promise>} */
911 var nodePromises = []; 979 var nodePromises = [];
912 for (var i = 0; nodeIds && i < nodeIds.length; ++i) { 980 for (var i = 0; nodeIds && i < nodeIds.length; ++i) {
981 /** @type {!Array<!Promise>} */
913 var stylePromises = [ 982 var stylePromises = [
914 cssModel.matchedStylesPromise(nodeIds[i]).then(matchedCallback), 983 cssModel.matchedStylesPromise(nodeIds[i]).then(matchedCallback),
915 cssModel.computedStylePromise(nodeIds[i]).then(computedCallback) 984 cssModel.computedStylePromise(nodeIds[i]).then(computedCallback)
916 ]; 985 ];
917 var nodePromise = Promise.all(stylePromises).then(imageStylesReady.bind( null, nodeIds[i], targetResult)); 986 var nodePromise = Promise.all(stylePromises).then(imageStylesReady.bind( null, nodeIds[i], targetResult));
918 nodePromises.push(nodePromise); 987 nodePromises.push(nodePromise);
919 } 988 }
920 Promise.all(nodePromises).catchException(null).then(doneCallback); 989 Promise.all(nodePromises).catchException(null).then(doneCallback);
921 } 990 }
922 991
992 /**
993 * @param {!SDK.DOMDocument} root
994 */
923 function onDocumentAvailable(root) { 995 function onDocumentAvailable(root) {
924 if (progress.isCanceled()) { 996 if (progress.isCanceled()) {
925 callback(null); 997 callback(null);
926 return; 998 return;
927 } 999 }
928 domModel.querySelectorAll(root.id, 'img[src]', getStyles); 1000 domModel.querySelectorAll(root.id, 'img[src]', getStyles);
929 } 1001 }
930 1002
931 if (progress.isCanceled()) { 1003 if (progress.isCanceled()) {
932 callback(null); 1004 callback(null);
(...skipping 19 matching lines...) Expand all
952 * @param {function(?Audits.AuditRuleResult)} callback 1024 * @param {function(?Audits.AuditRuleResult)} callback
953 * @param {!Common.Progress} progress 1025 * @param {!Common.Progress} progress
954 */ 1026 */
955 doRun(target, requests, result, callback, progress) { 1027 doRun(target, requests, result, callback, progress) {
956 var domModel = SDK.DOMModel.fromTarget(target); 1028 var domModel = SDK.DOMModel.fromTarget(target);
957 if (!domModel) { 1029 if (!domModel) {
958 callback(null); 1030 callback(null);
959 return; 1031 return;
960 } 1032 }
961 1033
1034 /**
1035 * @param {?Object<string, !Array<(number|!Array<string>)>>} evalResult
1036 */
962 function evalCallback(evalResult) { 1037 function evalCallback(evalResult) {
963 if (progress.isCanceled()) { 1038 if (progress.isCanceled()) {
964 callback(null); 1039 callback(null);
965 return; 1040 return;
966 } 1041 }
967 1042
968 if (!evalResult) 1043 if (!evalResult)
969 return callback(null); 1044 return callback(null);
970 1045
971 var summary = result.addChild(''); 1046 var summary = result.addChild('');
(...skipping 20 matching lines...) Expand all
992 */ 1067 */
993 function externalStylesheetsReceived(root, inlineStyleNodeIds, nodeIds) { 1068 function externalStylesheetsReceived(root, inlineStyleNodeIds, nodeIds) {
994 if (progress.isCanceled()) { 1069 if (progress.isCanceled()) {
995 callback(null); 1070 callback(null);
996 return; 1071 return;
997 } 1072 }
998 1073
999 if (!nodeIds) 1074 if (!nodeIds)
1000 return; 1075 return;
1001 var externalStylesheetNodeIds = nodeIds; 1076 var externalStylesheetNodeIds = nodeIds;
1077 /** @type {?Object<string, !Array<(number|!Array<string>)>>} */
1002 var result = null; 1078 var result = null;
1003 if (inlineStyleNodeIds.length || externalStylesheetNodeIds.length) { 1079 if (inlineStyleNodeIds.length || externalStylesheetNodeIds.length) {
1080 /** @type {!Object<string, !Array<(number|!Array<string>)>>} */
1004 var urlToViolationsArray = {}; 1081 var urlToViolationsArray = {};
1082 /** @type {!Array<string>} */
1005 var externalStylesheetHrefs = []; 1083 var externalStylesheetHrefs = [];
1006 for (var j = 0; j < externalStylesheetNodeIds.length; ++j) { 1084 for (var j = 0; j < externalStylesheetNodeIds.length; ++j) {
1007 var linkNode = domModel.nodeForId(externalStylesheetNodeIds[j]); 1085 var linkNode = domModel.nodeForId(externalStylesheetNodeIds[j]);
1008 var completeHref = 1086 var completeHref =
1009 Common.ParsedURL.completeURL(linkNode.ownerDocument.baseURL, linkN ode.getAttribute('href')); 1087 Common.ParsedURL.completeURL(linkNode.ownerDocument.baseURL, linkN ode.getAttribute('href'));
1010 externalStylesheetHrefs.push(completeHref || '<empty>'); 1088 externalStylesheetHrefs.push(completeHref || '<empty>');
1011 } 1089 }
1012 urlToViolationsArray[root.documentURL] = [inlineStyleNodeIds.length, ext ernalStylesheetHrefs]; 1090 urlToViolationsArray[root.documentURL] = [inlineStyleNodeIds.length, ext ernalStylesheetHrefs];
1013 result = urlToViolationsArray; 1091 result = urlToViolationsArray;
1014 } 1092 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 * @param {function(?Audits.AuditRuleResult)} callback 1141 * @param {function(?Audits.AuditRuleResult)} callback
1064 * @param {!Common.Progress} progress 1142 * @param {!Common.Progress} progress
1065 */ 1143 */
1066 doRun(target, requests, result, callback, progress) { 1144 doRun(target, requests, result, callback, progress) {
1067 var domModel = SDK.DOMModel.fromTarget(target); 1145 var domModel = SDK.DOMModel.fromTarget(target);
1068 if (!domModel) { 1146 if (!domModel) {
1069 callback(null); 1147 callback(null);
1070 return; 1148 return;
1071 } 1149 }
1072 1150
1151 /**
1152 * @param {?Array<!Array<string>|number>} resultValue
1153 */
1073 function evalCallback(resultValue) { 1154 function evalCallback(resultValue) {
1074 if (progress.isCanceled()) { 1155 if (progress.isCanceled()) {
1075 callback(null); 1156 callback(null);
1076 return; 1157 return;
1077 } 1158 }
1078 1159
1079 if (!resultValue) 1160 if (!resultValue)
1080 return callback(null); 1161 return callback(null);
1081 1162
1082 var lateCssUrls = resultValue[0]; 1163 var lateCssUrls = resultValue[0];
1083 var cssBeforeInlineCount = resultValue[1]; 1164 var cssBeforeInlineCount = resultValue[1];
1084 1165
1085 if (lateCssUrls.length) { 1166 if (lateCssUrls.length) {
1086 var entry = result.addChild( 1167 var entry = result.addChild(
1087 Common.UIString( 1168 Common.UIString(
1088 'The following external CSS files were included after an externa l JavaScript file in the document head. To ensure CSS files are downloaded in pa rallel, always include external CSS before external JavaScript.'), 1169 'The following external CSS files were included after an externa l JavaScript file in the document head. To ensure CSS files are downloaded in pa rallel, always include external CSS before external JavaScript.'),
1089 true); 1170 true);
1090 entry.addURLs(lateCssUrls); 1171 entry.addURLs(/** @type {!Array<string>} */ (lateCssUrls));
1091 result.violationCount += lateCssUrls.length; 1172 result.violationCount += lateCssUrls.length;
1092 } 1173 }
1093 1174
1094 if (cssBeforeInlineCount) { 1175 if (cssBeforeInlineCount) {
1095 result.addChild(Common.UIString( 1176 result.addChild(Common.UIString(
1096 ' %d inline script block%s found in the head between an external CSS file and another resource. To allow parallel downloading, move the inline scrip t before the external CSS file, or after the next resource.', 1177 ' %d inline script block%s found in the head between an external CSS file and another resource. To allow parallel downloading, move the inline scrip t before the external CSS file, or after the next resource.',
1097 cssBeforeInlineCount, cssBeforeInlineCount > 1 ? 's were' : ' was')) ; 1178 cssBeforeInlineCount, cssBeforeInlineCount > 1 ? 's were' : ' was')) ;
1098 result.violationCount += cssBeforeInlineCount; 1179 result.violationCount += cssBeforeInlineCount;
1099 } 1180 }
1100 callback(result); 1181 callback(result);
1101 } 1182 }
1102 1183
1103 /** 1184 /**
1104 * @param {!Array.<!Protocol.DOM.NodeId>} lateStyleIds 1185 * @param {!Array.<!Protocol.DOM.NodeId>} lateStyleIds
1105 * @param {!Array.<!Protocol.DOM.NodeId>=} nodeIds 1186 * @param {!Array.<!Protocol.DOM.NodeId>=} nodeIds
1106 */ 1187 */
1107 function cssBeforeInlineReceived(lateStyleIds, nodeIds) { 1188 function cssBeforeInlineReceived(lateStyleIds, nodeIds) {
1108 if (progress.isCanceled()) { 1189 if (progress.isCanceled()) {
1109 callback(null); 1190 callback(null);
1110 return; 1191 return;
1111 } 1192 }
1112 1193
1113 if (!nodeIds) 1194 if (!nodeIds)
1114 return; 1195 return;
1115 1196
1116 var cssBeforeInlineCount = nodeIds.length; 1197 var cssBeforeInlineCount = nodeIds.length;
1198 /** @type {?Array<!Array<string>|number>} */
1117 var result = null; 1199 var result = null;
1118 if (lateStyleIds.length || cssBeforeInlineCount) { 1200 if (lateStyleIds.length || cssBeforeInlineCount) {
1201 /** @type {!Array<string>} */
1119 var lateStyleUrls = []; 1202 var lateStyleUrls = [];
1120 for (var i = 0; i < lateStyleIds.length; ++i) { 1203 for (var i = 0; i < lateStyleIds.length; ++i) {
1121 var lateStyleNode = domModel.nodeForId(lateStyleIds[i]); 1204 var lateStyleNode = domModel.nodeForId(lateStyleIds[i]);
1122 var completeHref = 1205 var completeHref =
1123 Common.ParsedURL.completeURL(lateStyleNode.ownerDocument.baseURL, lateStyleNode.getAttribute('href')); 1206 Common.ParsedURL.completeURL(lateStyleNode.ownerDocument.baseURL, lateStyleNode.getAttribute('href'));
1124 lateStyleUrls.push(completeHref || '<empty>'); 1207 lateStyleUrls.push(completeHref || '<empty>');
1125 } 1208 }
1126 result = [lateStyleUrls, cssBeforeInlineCount]; 1209 result = [lateStyleUrls, cssBeforeInlineCount];
1127 } 1210 }
1128 1211
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 root.id, 'head script[src] ~ link[rel~=\'stylesheet\'][href]', lateSty lesReceived.bind(null, root)); 1243 root.id, 'head script[src] ~ link[rel~=\'stylesheet\'][href]', lateSty lesReceived.bind(null, root));
1161 } 1244 }
1162 1245
1163 domModel.requestDocument(onDocumentAvailable); 1246 domModel.requestDocument(onDocumentAvailable);
1164 } 1247 }
1165 }; 1248 };
1166 1249
1167 /** 1250 /**
1168 * @unrestricted 1251 * @unrestricted
1169 */ 1252 */
1170 Audits.AuditRules.CSSRuleBase = class extends Audits.AuditRule { 1253 Audits.AuditRules.CSSRuleBase = class extends Audits.AuditRule {
luoe 2017/01/13 08:05:22 Not related to typing, but it looks like this clas
allada 2017/01/17 19:16:25 I would rather not in this cl, I only want to prot
1254 /**
1255 * @param {string} id
1256 * @param {string} name
1257 */
1171 constructor(id, name) { 1258 constructor(id, name) {
1172 super(id, name); 1259 super(id, name);
1173 } 1260 }
1174 1261
1175 /** 1262 /**
1176 * @override 1263 * @override
1177 * @param {!SDK.Target} target 1264 * @param {!SDK.Target} target
1178 * @param {!Array.<!SDK.NetworkRequest>} requests 1265 * @param {!Array.<!SDK.NetworkRequest>} requests
1179 * @param {!Audits.AuditRuleResult} result 1266 * @param {!Audits.AuditRuleResult} result
1180 * @param {function(?Audits.AuditRuleResult)} callback 1267 * @param {function(?Audits.AuditRuleResult)} callback
1181 * @param {!Common.Progress} progress 1268 * @param {!Common.Progress} progress
1182 */ 1269 */
1183 doRun(target, requests, result, callback, progress) { 1270 doRun(target, requests, result, callback, progress) {
1184 var cssModel = SDK.CSSModel.fromTarget(target); 1271 var cssModel = SDK.CSSModel.fromTarget(target);
1185 if (!cssModel) { 1272 if (!cssModel) {
1186 callback(null); 1273 callback(null);
1187 return; 1274 return;
1188 } 1275 }
1189 1276
1190 var headers = cssModel.allStyleSheets(); 1277 var headers = cssModel.allStyleSheets();
1191 if (!headers.length) { 1278 if (!headers.length) {
1192 callback(null); 1279 callback(null);
1193 return; 1280 return;
1194 } 1281 }
1282 /** @type {!Array<!SDK.CSSStyleSheetHeader>} */
1195 var activeHeaders = []; 1283 var activeHeaders = [];
1196 for (var i = 0; i < headers.length; ++i) { 1284 for (var i = 0; i < headers.length; ++i) {
1197 if (!headers[i].disabled) 1285 if (!headers[i].disabled)
1198 activeHeaders.push(headers[i]); 1286 activeHeaders.push(headers[i]);
1199 } 1287 }
1200 1288
1201 var styleSheetProcessor = new Audits.AuditRules.StyleSheetProcessor( 1289 var styleSheetProcessor = new Audits.AuditRules.StyleSheetProcessor(
1202 activeHeaders, progress, this._styleSheetsLoaded.bind(this, result, call back, progress)); 1290 activeHeaders, progress, this._styleSheetsLoaded.bind(this, result, call back, progress));
1203 styleSheetProcessor.run(); 1291 styleSheetProcessor.run();
1204 } 1292 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1283 */ 1371 */
1284 visitProperty(styleSheet, rule, property, result) { 1372 visitProperty(styleSheet, rule, property, result) {
1285 // Subclasses can implement. 1373 // Subclasses can implement.
1286 } 1374 }
1287 }; 1375 };
1288 1376
1289 /** 1377 /**
1290 * @unrestricted 1378 * @unrestricted
1291 */ 1379 */
1292 Audits.AuditRules.CookieRuleBase = class extends Audits.AuditRule { 1380 Audits.AuditRules.CookieRuleBase = class extends Audits.AuditRule {
1381 /**
1382 * @param {string} id
1383 * @param {string} name
1384 */
1293 constructor(id, name) { 1385 constructor(id, name) {
1294 super(id, name); 1386 super(id, name);
1295 } 1387 }
1296 1388
1297 /** 1389 /**
1298 * @override 1390 * @override
1299 * @param {!SDK.Target} target 1391 * @param {!SDK.Target} target
1300 * @param {!Array.<!SDK.NetworkRequest>} requests 1392 * @param {!Array.<!SDK.NetworkRequest>} requests
1301 * @param {!Audits.AuditRuleResult} result 1393 * @param {!Audits.AuditRuleResult} result
1302 * @param {function(!Audits.AuditRuleResult)} callback 1394 * @param {function(!Audits.AuditRuleResult)} callback
1303 * @param {!Common.Progress} progress 1395 * @param {!Common.Progress} progress
1304 */ 1396 */
1305 doRun(target, requests, result, callback, progress) { 1397 doRun(target, requests, result, callback, progress) {
1306 var self = this; 1398 var self = this;
1399 /**
1400 * @param {!Array<!SDK.Cookie>} receivedCookies
1401 */
1307 function resultCallback(receivedCookies) { 1402 function resultCallback(receivedCookies) {
1308 if (progress.isCanceled()) { 1403 if (progress.isCanceled()) {
1309 callback(result); 1404 callback(result);
1310 return; 1405 return;
1311 } 1406 }
1312 1407
1313 self.processCookies(receivedCookies, requests, result); 1408 self.processCookies(receivedCookies, requests, result);
1314 callback(result); 1409 callback(result);
1315 } 1410 }
1316 1411
1317 SDK.Cookies.getCookiesAsync(resultCallback); 1412 SDK.Cookies.getCookiesAsync(resultCallback);
1318 } 1413 }
1319 1414
1415 /**
1416 * @param {!Object<string, !Array<!SDK.NetworkRequest>>} requestsByDomain
1417 * @param {!Array<!SDK.Cookie>} allCookies
1418 * @param {function(!SDK.NetworkRequest, !SDK.Cookie)} callback
1419 */
1320 mapResourceCookies(requestsByDomain, allCookies, callback) { 1420 mapResourceCookies(requestsByDomain, allCookies, callback) {
1321 for (var i = 0; i < allCookies.length; ++i) { 1421 for (var i = 0; i < allCookies.length; ++i) {
1322 for (var requestDomain in requestsByDomain) { 1422 for (var requestDomain in requestsByDomain) {
1323 if (SDK.Cookies.cookieDomainMatchesResourceDomain(allCookies[i].domain() , requestDomain)) 1423 if (SDK.Cookies.cookieDomainMatchesResourceDomain(allCookies[i].domain() , requestDomain))
1324 this._callbackForResourceCookiePairs(requestsByDomain[requestDomain], allCookies[i], callback); 1424 this._callbackForResourceCookiePairs(requestsByDomain[requestDomain], allCookies[i], callback);
1325 } 1425 }
1326 } 1426 }
1327 } 1427 }
1328 1428
1429 /**
1430 * @param {!Array<!SDK.NetworkRequest>} requests
1431 * @param {!SDK.Cookie} cookie
1432 * @param {function(!SDK.NetworkRequest, !SDK.Cookie)} callback
1433 */
1329 _callbackForResourceCookiePairs(requests, cookie, callback) { 1434 _callbackForResourceCookiePairs(requests, cookie, callback) {
1330 if (!requests) 1435 if (!requests)
1331 return; 1436 return;
1332 for (var i = 0; i < requests.length; ++i) { 1437 for (var i = 0; i < requests.length; ++i) {
1333 if (SDK.Cookies.cookieMatchesResourceURL(cookie, requests[i].url)) 1438 if (SDK.Cookies.cookieMatchesResourceURL(cookie, requests[i].url()))
1334 callback(requests[i], cookie); 1439 callback(requests[i], cookie);
1335 } 1440 }
1336 } 1441 }
1337 }; 1442 };
1338 1443
1339 /** 1444 /**
1340 * @unrestricted 1445 * @unrestricted
1341 */ 1446 */
1342 Audits.AuditRules.CookieSizeRule = class extends Audits.AuditRules.CookieRuleBas e { 1447 Audits.AuditRules.CookieSizeRule = class extends Audits.AuditRules.CookieRuleBas e {
1448 /**
1449 * @param {number} avgBytesThreshold
1450 */
1343 constructor(avgBytesThreshold) { 1451 constructor(avgBytesThreshold) {
1344 super('http-cookiesize', Common.UIString('Minimize cookie size')); 1452 super('http-cookiesize', Common.UIString('Minimize cookie size'));
1345 this._avgBytesThreshold = avgBytesThreshold; 1453 this._avgBytesThreshold = avgBytesThreshold;
1346 this._maxBytesThreshold = 1000; 1454 this._maxBytesThreshold = 1000;
1347 } 1455 }
1348 1456
1457 /**
1458 * @param {!Array<!SDK.Cookie>} cookieArray
luoe 2017/01/13 08:05:22 @return {number}
allada 2017/01/17 19:16:25 Done.
1459 */
1349 _average(cookieArray) { 1460 _average(cookieArray) {
1350 var total = 0; 1461 var total = 0;
1351 for (var i = 0; i < cookieArray.length; ++i) 1462 for (var i = 0; i < cookieArray.length; ++i)
1352 total += cookieArray[i].size(); 1463 total += cookieArray[i].size();
1353 return cookieArray.length ? Math.round(total / cookieArray.length) : 0; 1464 return cookieArray.length ? Math.round(total / cookieArray.length) : 0;
1354 } 1465 }
1355 1466
1467 /**
1468 * @param {!Array<!SDK.Cookie>} cookieArray
luoe 2017/01/13 08:05:22 ditto
allada 2017/01/17 19:16:25 Done.
1469 */
1356 _max(cookieArray) { 1470 _max(cookieArray) {
1357 var result = 0; 1471 var result = 0;
1358 for (var i = 0; i < cookieArray.length; ++i) 1472 for (var i = 0; i < cookieArray.length; ++i)
1359 result = Math.max(cookieArray[i].size(), result); 1473 result = Math.max(cookieArray[i].size(), result);
1360 return result; 1474 return result;
1361 } 1475 }
1362 1476
1477 /**
1478 * @param {!Array<!SDK.Cookie>} allCookies
1479 * @param {!Array<!SDK.NetworkRequest>} requests
1480 * @param {!Audits.AuditRuleResult} result
1481 */
1363 processCookies(allCookies, requests, result) { 1482 processCookies(allCookies, requests, result) {
1483 /**
1484 * @param {!{domain: string, avgCookieSize: number, maxCookieSize: number}} a
luoe 2017/01/13 08:05:23 typedef CookieStats? @return number
allada 2017/01/17 19:16:25 Done.
1485 * @param {!{domain: string, avgCookieSize: number, maxCookieSize: number}} b
1486 */
1364 function maxSizeSorter(a, b) { 1487 function maxSizeSorter(a, b) {
1365 return b.maxCookieSize - a.maxCookieSize; 1488 return b.maxCookieSize - a.maxCookieSize;
1366 } 1489 }
1367 1490
1491 /**
1492 * @param {!{domain: string, avgCookieSize: number, maxCookieSize: number}} a
luoe 2017/01/13 08:05:22 ditto
1493 * @param {!{domain: string, avgCookieSize: number, maxCookieSize: number}} b
1494 */
1368 function avgSizeSorter(a, b) { 1495 function avgSizeSorter(a, b) {
1369 return b.avgCookieSize - a.avgCookieSize; 1496 return b.avgCookieSize - a.avgCookieSize;
1370 } 1497 }
1371 1498
1499 /** @type {!Object<string, !Array<!SDK.Cookie>>} */
1372 var cookiesPerResourceDomain = {}; 1500 var cookiesPerResourceDomain = {};
1373 1501
1502 /**
1503 * @param {!SDK.NetworkRequest} request
1504 * @param {!SDK.Cookie} cookie
1505 */
1374 function collectorCallback(request, cookie) { 1506 function collectorCallback(request, cookie) {
1375 var cookies = cookiesPerResourceDomain[request.parsedURL.host]; 1507 var cookies = cookiesPerResourceDomain[request.parsedURL.host];
1376 if (!cookies) { 1508 if (!cookies) {
1377 cookies = []; 1509 cookies = [];
luoe 2017/01/13 08:05:22 I guess closure doesn't complain about this?
allada 2017/01/17 19:16:25 It can infer it from line 1500
luoe 2017/01/17 19:40:16 I changed it to "cookies = [123]" and ran closure
allada 2017/01/17 19:50:11 What dgozman@ and I agreed on is that we should do
1378 cookiesPerResourceDomain[request.parsedURL.host] = cookies; 1510 cookiesPerResourceDomain[request.parsedURL.host] = cookies;
1379 } 1511 }
1380 cookies.push(cookie); 1512 cookies.push(cookie);
1381 } 1513 }
1382 1514
1383 if (!allCookies.length) 1515 if (!allCookies.length)
1384 return; 1516 return;
1385 1517
1518 /** @type {!Array<!{domain: string, avgCookieSize: number, maxCookieSize: nu mber}>} */
1386 var sortedCookieSizes = []; 1519 var sortedCookieSizes = [];
1387 1520
1388 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap(request s, null, true); 1521 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap(request s, null);
1389 this.mapResourceCookies(domainToResourcesMap, allCookies, collectorCallback) ; 1522 this.mapResourceCookies(domainToResourcesMap, allCookies, collectorCallback) ;
1390 1523
1391 for (var requestDomain in cookiesPerResourceDomain) { 1524 for (var requestDomain in cookiesPerResourceDomain) {
1392 var cookies = cookiesPerResourceDomain[requestDomain]; 1525 var cookies = cookiesPerResourceDomain[requestDomain];
1393 sortedCookieSizes.push( 1526 sortedCookieSizes.push(
1394 {domain: requestDomain, avgCookieSize: this._average(cookies), maxCook ieSize: this._max(cookies)}); 1527 {domain: requestDomain, avgCookieSize: this._average(cookies), maxCook ieSize: this._max(cookies)});
1395 } 1528 }
1396 var avgAllCookiesSize = this._average(allCookies); 1529 var avgAllCookiesSize = this._average(allCookies);
1397 1530
1531 /** @type {!Array<string>} */
1398 var hugeCookieDomains = []; 1532 var hugeCookieDomains = [];
1399 sortedCookieSizes.sort(maxSizeSorter); 1533 sortedCookieSizes.sort(maxSizeSorter);
1400 1534
1401 for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) { 1535 for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) {
1402 var maxCookieSize = sortedCookieSizes[i].maxCookieSize; 1536 var maxCookieSize = sortedCookieSizes[i].maxCookieSize;
1403 if (maxCookieSize > this._maxBytesThreshold) { 1537 if (maxCookieSize > this._maxBytesThreshold) {
1404 hugeCookieDomains.push( 1538 hugeCookieDomains.push(
1405 Audits.AuditRuleResult.resourceDomain(sortedCookieSizes[i].domain) + ': ' + 1539 Audits.AuditRuleResult.resourceDomain(sortedCookieSizes[i].domain) + ': ' +
1406 Number.bytesToString(maxCookieSize)); 1540 Number.bytesToString(maxCookieSize));
1407 } 1541 }
1408 } 1542 }
1409 1543
1544 /** @type {!Array<string>} */
1410 var bigAvgCookieDomains = []; 1545 var bigAvgCookieDomains = [];
1411 sortedCookieSizes.sort(avgSizeSorter); 1546 sortedCookieSizes.sort(avgSizeSorter);
1412 for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) { 1547 for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) {
1413 var domain = sortedCookieSizes[i].domain; 1548 var domain = sortedCookieSizes[i].domain;
1414 var avgCookieSize = sortedCookieSizes[i].avgCookieSize; 1549 var avgCookieSize = sortedCookieSizes[i].avgCookieSize;
1415 if (avgCookieSize > this._avgBytesThreshold && avgCookieSize < this._maxBy tesThreshold) { 1550 if (avgCookieSize > this._avgBytesThreshold && avgCookieSize < this._maxBy tesThreshold) {
1416 bigAvgCookieDomains.push( 1551 bigAvgCookieDomains.push(
1417 Audits.AuditRuleResult.resourceDomain(domain) + ': ' + Number.bytesT oString(avgCookieSize)); 1552 Audits.AuditRuleResult.resourceDomain(domain) + ': ' + Number.bytesT oString(avgCookieSize));
1418 } 1553 }
1419 } 1554 }
(...skipping 18 matching lines...) Expand all
1438 entry.addURLs(bigAvgCookieDomains); 1573 entry.addURLs(bigAvgCookieDomains);
1439 result.violationCount += bigAvgCookieDomains.length; 1574 result.violationCount += bigAvgCookieDomains.length;
1440 } 1575 }
1441 } 1576 }
1442 }; 1577 };
1443 1578
1444 /** 1579 /**
1445 * @unrestricted 1580 * @unrestricted
1446 */ 1581 */
1447 Audits.AuditRules.StaticCookielessRule = class extends Audits.AuditRules.CookieR uleBase { 1582 Audits.AuditRules.StaticCookielessRule = class extends Audits.AuditRules.CookieR uleBase {
1583 /**
1584 * @param {number} minResources
1585 */
1448 constructor(minResources) { 1586 constructor(minResources) {
1449 super('http-staticcookieless', Common.UIString('Serve static content from a cookieless domain')); 1587 super('http-staticcookieless', Common.UIString('Serve static content from a cookieless domain'));
1450 this._minResources = minResources; 1588 this._minResources = minResources;
1451 } 1589 }
1452 1590
1591 /**
1592 * @param {!Array<!SDK.Cookie>} allCookies
1593 * @param {!Array<!SDK.NetworkRequest>} requests
1594 * @param {!Audits.AuditRuleResult} result
1595 */
1453 processCookies(allCookies, requests, result) { 1596 processCookies(allCookies, requests, result) {
1454 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap( 1597 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap(
1455 requests, [Common.resourceTypes.Stylesheet, Common.resourceTypes.Image], true); 1598 requests, [Common.resourceTypes.Stylesheet, Common.resourceTypes.Image]) ;
1456 var totalStaticResources = 0; 1599 var totalStaticResources = 0;
1457 for (var domain in domainToResourcesMap) 1600 for (var domain in domainToResourcesMap)
1458 totalStaticResources += domainToResourcesMap[domain].length; 1601 totalStaticResources += domainToResourcesMap[domain].length;
1459 if (totalStaticResources < this._minResources) 1602 if (totalStaticResources < this._minResources)
1460 return; 1603 return;
1461 /** @type {!Object<string, number>} */ 1604 /** @type {!Object<string, number>} */
1462 var matchingResourceData = {}; 1605 var matchingResourceData = {};
1463 this.mapResourceCookies(domainToResourcesMap, allCookies, this._collectorCal lback.bind(this, matchingResourceData)); 1606 this.mapResourceCookies(domainToResourcesMap, allCookies, this._collectorCal lback.bind(this, matchingResourceData));
1464 1607
1608 /** @type {!Array<string>} */
1465 var badUrls = []; 1609 var badUrls = [];
1466 var cookieBytes = 0; 1610 var cookieBytes = 0;
1467 for (var url in matchingResourceData) { 1611 for (var url in matchingResourceData) {
1468 badUrls.push(url); 1612 badUrls.push(url);
1469 cookieBytes += matchingResourceData[url]; 1613 cookieBytes += matchingResourceData[url];
1470 } 1614 }
1471 if (badUrls.length < this._minResources) 1615 if (badUrls.length < this._minResources)
1472 return; 1616 return;
1473 1617
1474 var entry = result.addChild( 1618 var entry = result.addChild(
1475 Common.UIString( 1619 Common.UIString(
1476 '%s of cookies were sent with the following static resources. Serve these static resources from a domain that does not set cookies:', 1620 '%s of cookies were sent with the following static resources. Serve these static resources from a domain that does not set cookies:',
1477 Number.bytesToString(cookieBytes)), 1621 Number.bytesToString(cookieBytes)),
1478 true); 1622 true);
1479 entry.addURLs(badUrls); 1623 entry.addURLs(badUrls);
1480 result.violationCount = badUrls.length; 1624 result.violationCount = badUrls.length;
1481 } 1625 }
1482 1626
1483 /** 1627 /**
1484 * @param {!Object<string, number>} matchingResourceData 1628 * @param {!Object<string, number>} matchingResourceData
1485 * @param {!SDK.NetworkRequest} request 1629 * @param {!SDK.NetworkRequest} request
1486 * @param {!SDK.Cookie} cookie 1630 * @param {!SDK.Cookie} cookie
1487 */ 1631 */
1488 _collectorCallback(matchingResourceData, request, cookie) { 1632 _collectorCallback(matchingResourceData, request, cookie) {
1489 matchingResourceData[request.url()] = (matchingResourceData[request.url()] | | 0) + cookie.size(); 1633 matchingResourceData[request.url()] = (matchingResourceData[request.url()] | | 0) + cookie.size();
1490 } 1634 }
1491 }; 1635 };
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698