Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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) { | |
| 76 var requestMap = Audits.AuditRules.getDomainToResourcesMap(requests, types); | |
| 77 /** @type {!Object<string, !Array<string>>} */ | |
| 78 var output = {}; | |
| 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 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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>} */ | |
|
pfeldman
2017/01/17 19:33:55
Let's not enforce annotating inline objects and ar
allada
2017/01/17 19:38:27
Acknowledged.
| |
| 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 Loading... | |
| 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 Loading... | |
| 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(...rules); |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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>} */ | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 { |
| 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 Loading... | |
| 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 | |
| 1459 * @return {number} | |
| 1460 */ | |
| 1349 _average(cookieArray) { | 1461 _average(cookieArray) { |
| 1350 var total = 0; | 1462 var total = 0; |
| 1351 for (var i = 0; i < cookieArray.length; ++i) | 1463 for (var i = 0; i < cookieArray.length; ++i) |
| 1352 total += cookieArray[i].size(); | 1464 total += cookieArray[i].size(); |
| 1353 return cookieArray.length ? Math.round(total / cookieArray.length) : 0; | 1465 return cookieArray.length ? Math.round(total / cookieArray.length) : 0; |
| 1354 } | 1466 } |
| 1355 | 1467 |
| 1468 /** | |
| 1469 * @param {!Array<!SDK.Cookie>} cookieArray | |
| 1470 * @return {number} | |
| 1471 */ | |
| 1356 _max(cookieArray) { | 1472 _max(cookieArray) { |
| 1357 var result = 0; | 1473 var result = 0; |
| 1358 for (var i = 0; i < cookieArray.length; ++i) | 1474 for (var i = 0; i < cookieArray.length; ++i) |
| 1359 result = Math.max(cookieArray[i].size(), result); | 1475 result = Math.max(cookieArray[i].size(), result); |
| 1360 return result; | 1476 return result; |
| 1361 } | 1477 } |
| 1362 | 1478 |
| 1479 /** | |
| 1480 * @param {!Array<!SDK.Cookie>} allCookies | |
| 1481 * @param {!Array<!SDK.NetworkRequest>} requests | |
| 1482 * @param {!Audits.AuditRuleResult} result | |
| 1483 */ | |
| 1363 processCookies(allCookies, requests, result) { | 1484 processCookies(allCookies, requests, result) { |
| 1485 /** | |
| 1486 * @param {!Audits.AuditRules._CookieStats} a | |
| 1487 * @param {!Audits.AuditRules._CookieStats} b | |
| 1488 * @return {number} | |
| 1489 */ | |
| 1364 function maxSizeSorter(a, b) { | 1490 function maxSizeSorter(a, b) { |
| 1365 return b.maxCookieSize - a.maxCookieSize; | 1491 return b.maxCookieSize - a.maxCookieSize; |
| 1366 } | 1492 } |
| 1367 | 1493 |
| 1494 /** | |
| 1495 * @param {!Audits.AuditRules._CookieStats} a | |
| 1496 * @param {!Audits.AuditRules._CookieStats} b | |
| 1497 * @return {number} | |
| 1498 */ | |
| 1368 function avgSizeSorter(a, b) { | 1499 function avgSizeSorter(a, b) { |
| 1369 return b.avgCookieSize - a.avgCookieSize; | 1500 return b.avgCookieSize - a.avgCookieSize; |
| 1370 } | 1501 } |
| 1371 | 1502 |
| 1503 /** @type {!Object<string, !Array<!SDK.Cookie>>} */ | |
| 1372 var cookiesPerResourceDomain = {}; | 1504 var cookiesPerResourceDomain = {}; |
| 1373 | 1505 |
| 1506 /** | |
| 1507 * @param {!SDK.NetworkRequest} request | |
| 1508 * @param {!SDK.Cookie} cookie | |
| 1509 */ | |
| 1374 function collectorCallback(request, cookie) { | 1510 function collectorCallback(request, cookie) { |
| 1375 var cookies = cookiesPerResourceDomain[request.parsedURL.host]; | 1511 var cookies = cookiesPerResourceDomain[request.parsedURL.host]; |
| 1376 if (!cookies) { | 1512 if (!cookies) { |
| 1377 cookies = []; | 1513 cookies = []; |
| 1378 cookiesPerResourceDomain[request.parsedURL.host] = cookies; | 1514 cookiesPerResourceDomain[request.parsedURL.host] = cookies; |
| 1379 } | 1515 } |
| 1380 cookies.push(cookie); | 1516 cookies.push(cookie); |
| 1381 } | 1517 } |
| 1382 | 1518 |
| 1383 if (!allCookies.length) | 1519 if (!allCookies.length) |
| 1384 return; | 1520 return; |
| 1385 | 1521 |
| 1522 /** @type {!Array<!Audits.AuditRules._CookieStats>} */ | |
| 1386 var sortedCookieSizes = []; | 1523 var sortedCookieSizes = []; |
| 1387 | 1524 |
| 1388 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap(request s, null, true); | 1525 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap(request s, null); |
| 1389 this.mapResourceCookies(domainToResourcesMap, allCookies, collectorCallback) ; | 1526 this.mapResourceCookies(domainToResourcesMap, allCookies, collectorCallback) ; |
| 1390 | 1527 |
| 1391 for (var requestDomain in cookiesPerResourceDomain) { | 1528 for (var requestDomain in cookiesPerResourceDomain) { |
| 1392 var cookies = cookiesPerResourceDomain[requestDomain]; | 1529 var cookies = cookiesPerResourceDomain[requestDomain]; |
| 1393 sortedCookieSizes.push( | 1530 sortedCookieSizes.push( |
| 1394 {domain: requestDomain, avgCookieSize: this._average(cookies), maxCook ieSize: this._max(cookies)}); | 1531 {domain: requestDomain, avgCookieSize: this._average(cookies), maxCook ieSize: this._max(cookies)}); |
| 1395 } | 1532 } |
| 1396 var avgAllCookiesSize = this._average(allCookies); | 1533 var avgAllCookiesSize = this._average(allCookies); |
| 1397 | 1534 |
| 1535 /** @type {!Array<string>} */ | |
| 1398 var hugeCookieDomains = []; | 1536 var hugeCookieDomains = []; |
| 1399 sortedCookieSizes.sort(maxSizeSorter); | 1537 sortedCookieSizes.sort(maxSizeSorter); |
| 1400 | 1538 |
| 1401 for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) { | 1539 for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) { |
| 1402 var maxCookieSize = sortedCookieSizes[i].maxCookieSize; | 1540 var maxCookieSize = sortedCookieSizes[i].maxCookieSize; |
| 1403 if (maxCookieSize > this._maxBytesThreshold) { | 1541 if (maxCookieSize > this._maxBytesThreshold) { |
| 1404 hugeCookieDomains.push( | 1542 hugeCookieDomains.push( |
| 1405 Audits.AuditRuleResult.resourceDomain(sortedCookieSizes[i].domain) + ': ' + | 1543 Audits.AuditRuleResult.resourceDomain(sortedCookieSizes[i].domain) + ': ' + |
| 1406 Number.bytesToString(maxCookieSize)); | 1544 Number.bytesToString(maxCookieSize)); |
| 1407 } | 1545 } |
| 1408 } | 1546 } |
| 1409 | 1547 |
| 1548 /** @type {!Array<string>} */ | |
| 1410 var bigAvgCookieDomains = []; | 1549 var bigAvgCookieDomains = []; |
| 1411 sortedCookieSizes.sort(avgSizeSorter); | 1550 sortedCookieSizes.sort(avgSizeSorter); |
| 1412 for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) { | 1551 for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) { |
| 1413 var domain = sortedCookieSizes[i].domain; | 1552 var domain = sortedCookieSizes[i].domain; |
| 1414 var avgCookieSize = sortedCookieSizes[i].avgCookieSize; | 1553 var avgCookieSize = sortedCookieSizes[i].avgCookieSize; |
| 1415 if (avgCookieSize > this._avgBytesThreshold && avgCookieSize < this._maxBy tesThreshold) { | 1554 if (avgCookieSize > this._avgBytesThreshold && avgCookieSize < this._maxBy tesThreshold) { |
| 1416 bigAvgCookieDomains.push( | 1555 bigAvgCookieDomains.push( |
| 1417 Audits.AuditRuleResult.resourceDomain(domain) + ': ' + Number.bytesT oString(avgCookieSize)); | 1556 Audits.AuditRuleResult.resourceDomain(domain) + ': ' + Number.bytesT oString(avgCookieSize)); |
| 1418 } | 1557 } |
| 1419 } | 1558 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1438 entry.addURLs(bigAvgCookieDomains); | 1577 entry.addURLs(bigAvgCookieDomains); |
| 1439 result.violationCount += bigAvgCookieDomains.length; | 1578 result.violationCount += bigAvgCookieDomains.length; |
| 1440 } | 1579 } |
| 1441 } | 1580 } |
| 1442 }; | 1581 }; |
| 1443 | 1582 |
| 1444 /** | 1583 /** |
| 1445 * @unrestricted | 1584 * @unrestricted |
| 1446 */ | 1585 */ |
| 1447 Audits.AuditRules.StaticCookielessRule = class extends Audits.AuditRules.CookieR uleBase { | 1586 Audits.AuditRules.StaticCookielessRule = class extends Audits.AuditRules.CookieR uleBase { |
| 1587 /** | |
| 1588 * @param {number} minResources | |
| 1589 */ | |
| 1448 constructor(minResources) { | 1590 constructor(minResources) { |
| 1449 super('http-staticcookieless', Common.UIString('Serve static content from a cookieless domain')); | 1591 super('http-staticcookieless', Common.UIString('Serve static content from a cookieless domain')); |
| 1450 this._minResources = minResources; | 1592 this._minResources = minResources; |
| 1451 } | 1593 } |
| 1452 | 1594 |
| 1595 /** | |
| 1596 * @param {!Array<!SDK.Cookie>} allCookies | |
| 1597 * @param {!Array<!SDK.NetworkRequest>} requests | |
| 1598 * @param {!Audits.AuditRuleResult} result | |
| 1599 */ | |
| 1453 processCookies(allCookies, requests, result) { | 1600 processCookies(allCookies, requests, result) { |
| 1454 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap( | 1601 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap( |
| 1455 requests, [Common.resourceTypes.Stylesheet, Common.resourceTypes.Image], true); | 1602 requests, [Common.resourceTypes.Stylesheet, Common.resourceTypes.Image]) ; |
| 1456 var totalStaticResources = 0; | 1603 var totalStaticResources = 0; |
| 1457 for (var domain in domainToResourcesMap) | 1604 for (var domain in domainToResourcesMap) |
| 1458 totalStaticResources += domainToResourcesMap[domain].length; | 1605 totalStaticResources += domainToResourcesMap[domain].length; |
| 1459 if (totalStaticResources < this._minResources) | 1606 if (totalStaticResources < this._minResources) |
| 1460 return; | 1607 return; |
| 1461 /** @type {!Object<string, number>} */ | 1608 /** @type {!Object<string, number>} */ |
| 1462 var matchingResourceData = {}; | 1609 var matchingResourceData = {}; |
| 1463 this.mapResourceCookies(domainToResourcesMap, allCookies, this._collectorCal lback.bind(this, matchingResourceData)); | 1610 this.mapResourceCookies(domainToResourcesMap, allCookies, this._collectorCal lback.bind(this, matchingResourceData)); |
| 1464 | 1611 |
| 1612 /** @type {!Array<string>} */ | |
| 1465 var badUrls = []; | 1613 var badUrls = []; |
| 1466 var cookieBytes = 0; | 1614 var cookieBytes = 0; |
| 1467 for (var url in matchingResourceData) { | 1615 for (var url in matchingResourceData) { |
| 1468 badUrls.push(url); | 1616 badUrls.push(url); |
| 1469 cookieBytes += matchingResourceData[url]; | 1617 cookieBytes += matchingResourceData[url]; |
| 1470 } | 1618 } |
| 1471 if (badUrls.length < this._minResources) | 1619 if (badUrls.length < this._minResources) |
| 1472 return; | 1620 return; |
| 1473 | 1621 |
| 1474 var entry = result.addChild( | 1622 var entry = result.addChild( |
| 1475 Common.UIString( | 1623 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:', | 1624 '%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)), | 1625 Number.bytesToString(cookieBytes)), |
| 1478 true); | 1626 true); |
| 1479 entry.addURLs(badUrls); | 1627 entry.addURLs(badUrls); |
| 1480 result.violationCount = badUrls.length; | 1628 result.violationCount = badUrls.length; |
| 1481 } | 1629 } |
| 1482 | 1630 |
| 1483 /** | 1631 /** |
| 1484 * @param {!Object<string, number>} matchingResourceData | 1632 * @param {!Object<string, number>} matchingResourceData |
| 1485 * @param {!SDK.NetworkRequest} request | 1633 * @param {!SDK.NetworkRequest} request |
| 1486 * @param {!SDK.Cookie} cookie | 1634 * @param {!SDK.Cookie} cookie |
| 1487 */ | 1635 */ |
| 1488 _collectorCallback(matchingResourceData, request, cookie) { | 1636 _collectorCallback(matchingResourceData, request, cookie) { |
| 1489 matchingResourceData[request.url()] = (matchingResourceData[request.url()] | | 0) + cookie.size(); | 1637 matchingResourceData[request.url()] = (matchingResourceData[request.url()] | | 0) + cookie.size(); |
| 1490 } | 1638 } |
| 1491 }; | 1639 }; |
| 1640 | |
| 1641 /** @typedef {!{domain: string, avgCookieSize: number, maxCookieSize: number}} * / | |
| 1642 Audits.AuditRules._CookieStats; | |
| OLD | NEW |