| 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 29 matching lines...) Expand all Loading... |
| 40 304: true // Underlying request is cacheable | 40 304: true // Underlying request is cacheable |
| 41 }; | 41 }; |
| 42 | 42 |
| 43 /** | 43 /** |
| 44 * @param {!Array.<!SDK.NetworkRequest>} requests | 44 * @param {!Array.<!SDK.NetworkRequest>} requests |
| 45 * @param {?Array.<!Common.ResourceType>} types | 45 * @param {?Array.<!Common.ResourceType>} types |
| 46 * @param {boolean} needFullResources | 46 * @param {boolean} needFullResources |
| 47 * @return {!Object.<string, !Array.<!SDK.NetworkRequest|string>>} | 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, needFullRe
sources) { |
| 50 /** @type {!Object<string, !Array<!SDK.NetworkRequest|string>>} */ |
| 50 var domainToResourcesMap = {}; | 51 var domainToResourcesMap = {}; |
| 51 for (var i = 0, size = requests.length; i < size; ++i) { | 52 for (var i = 0, size = requests.length; i < size; ++i) { |
| 52 var request = requests[i]; | 53 var request = requests[i]; |
| 53 if (types && types.indexOf(request.resourceType()) === -1) | 54 if (types && types.indexOf(request.resourceType()) === -1) |
| 54 continue; | 55 continue; |
| 55 var parsedURL = request.url.asParsedURL(); | 56 var parsedURL = request.url().asParsedURL(); |
| 56 if (!parsedURL) | 57 if (!parsedURL) |
| 57 continue; | 58 continue; |
| 58 var domain = parsedURL.host; | 59 var domain = parsedURL.host; |
| 59 var domainResources = domainToResourcesMap[domain]; | 60 var domainResources = domainToResourcesMap[domain]; |
| 60 if (domainResources === undefined) { | 61 if (domainResources === undefined) { |
| 61 domainResources = []; | 62 domainResources = /** @type {!Array<!SDK.NetworkRequest|string>} */ ([]); |
| 62 domainToResourcesMap[domain] = domainResources; | 63 domainToResourcesMap[domain] = domainResources; |
| 63 } | 64 } |
| 64 domainResources.push(needFullResources ? request : request.url); | 65 domainResources.push(needFullResources ? request : request.url()); |
| 65 } | 66 } |
| 66 return domainToResourcesMap; | 67 return domainToResourcesMap; |
| 67 }; | 68 }; |
| 68 | 69 |
| 69 /** | 70 /** |
| 70 * @unrestricted | 71 * @unrestricted |
| 71 */ | 72 */ |
| 72 Audits.AuditRules.GzipRule = class extends Audits.AuditRule { | 73 Audits.AuditRules.GzipRule = class extends Audits.AuditRule { |
| 73 constructor() { | 74 constructor() { |
| 74 super('network-gzip', Common.UIString('Enable gzip compression')); | 75 super('network-gzip', Common.UIString('Enable gzip compression')); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 88 for (var i = 0, length = requests.length; i < length; ++i) { | 89 for (var i = 0, length = requests.length; i < length; ++i) { |
| 89 var request = requests[i]; | 90 var request = requests[i]; |
| 90 if (request.cached() || request.statusCode === 304) | 91 if (request.cached() || request.statusCode === 304) |
| 91 continue; // Do not test cached resources. | 92 continue; // Do not test cached resources. |
| 92 if (this._shouldCompress(request)) { | 93 if (this._shouldCompress(request)) { |
| 93 var size = request.resourceSize; | 94 var size = request.resourceSize; |
| 94 if (this._isCompressed(request)) | 95 if (this._isCompressed(request)) |
| 95 continue; | 96 continue; |
| 96 var savings = 2 * size / 3; | 97 var savings = 2 * size / 3; |
| 97 totalSavings += savings; | 98 totalSavings += savings; |
| 98 summary.addFormatted('%r could save ~%s', request.url, Number.bytesToStr
ing(savings)); | 99 summary.addFormatted('%r could save ~%s', request.url(), Number.bytesToS
tring(savings)); |
| 99 result.violationCount++; | 100 result.violationCount++; |
| 100 } | 101 } |
| 101 } | 102 } |
| 102 if (!totalSavings) { | 103 if (!totalSavings) { |
| 103 callback(null); | 104 callback(null); |
| 104 return; | 105 return; |
| 105 } | 106 } |
| 106 summary.value = Common.UIString( | 107 summary.value = Common.UIString( |
| 107 'Compressing the following resources with gzip could reduce their transf
er size by about two thirds (~%s):', | 108 'Compressing the following resources with gzip could reduce their transf
er size by about two thirds (~%s):', |
| 108 Number.bytesToString(totalSavings)); | 109 Number.bytesToString(totalSavings)); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 return; | 317 return; |
| 317 } | 318 } |
| 318 | 319 |
| 319 var requestsOnBusiestHost = domainToResourcesMap[hosts[0]]; | 320 var requestsOnBusiestHost = domainToResourcesMap[hosts[0]]; |
| 320 var entry = result.addChild( | 321 var entry = result.addChild( |
| 321 Common.UIString( | 322 Common.UIString( |
| 322 'This page makes %d parallelizable requests to %s. Increase download
parallelization by distributing the following requests across multiple hostname
s.', | 323 'This page makes %d parallelizable requests to %s. Increase download
parallelization by distributing the following requests across multiple hostname
s.', |
| 323 busiestHostResourceCount, hosts[0]), | 324 busiestHostResourceCount, hosts[0]), |
| 324 true); | 325 true); |
| 325 for (var i = 0; i < requestsOnBusiestHost.length; ++i) | 326 for (var i = 0; i < requestsOnBusiestHost.length; ++i) |
| 326 entry.addURL(requestsOnBusiestHost[i].url); | 327 entry.addURL(requestsOnBusiestHost[i].url()); |
| 327 | 328 |
| 328 result.violationCount = requestsOnBusiestHost.length; | 329 result.violationCount = requestsOnBusiestHost.length; |
| 329 callback(result); | 330 callback(result); |
| 330 } | 331 } |
| 331 }; | 332 }; |
| 332 | 333 |
| 333 /** | 334 /** |
| 334 * @unrestricted | 335 * @unrestricted |
| 335 */ | 336 */ |
| 336 Audits.AuditRules.UnusedCssRule = class extends Audits.AuditRule { | 337 Audits.AuditRules.UnusedCssRule = class extends Audits.AuditRule { |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 * @param {!SDK.NetworkRequest} request | 669 * @param {!SDK.NetworkRequest} request |
| 669 * @return {boolean} | 670 * @return {boolean} |
| 670 */ | 671 */ |
| 671 isPubliclyCacheable(request) { | 672 isPubliclyCacheable(request) { |
| 672 if (this._isExplicitlyNonCacheable(request)) | 673 if (this._isExplicitlyNonCacheable(request)) |
| 673 return false; | 674 return false; |
| 674 | 675 |
| 675 if (this.responseHeaderMatch(request, 'Cache-Control', 'public')) | 676 if (this.responseHeaderMatch(request, 'Cache-Control', 'public')) |
| 676 return true; | 677 return true; |
| 677 | 678 |
| 678 return request.url.indexOf('?') === -1 && !this.responseHeaderMatch(request,
'Cache-Control', 'private'); | 679 return request.url().indexOf('?') === -1 && !this.responseHeaderMatch(reques
t, 'Cache-Control', 'private'); |
| 679 } | 680 } |
| 680 | 681 |
| 681 /** | 682 /** |
| 682 * @param {!SDK.NetworkRequest} request | 683 * @param {!SDK.NetworkRequest} request |
| 683 * @param {string} header | 684 * @param {string} header |
| 684 * @param {string} regexp | 685 * @param {string} regexp |
| 685 * @return {?Array.<string>} | 686 * @return {?Array.<string>} |
| 686 */ | 687 */ |
| 687 responseHeaderMatch(request, header, regexp) { | 688 responseHeaderMatch(request, header, regexp) { |
| 688 return request.responseHeaderValue(header) ? request.responseHeaderValue(hea
der).match(new RegExp(regexp, 'im')) : | 689 return request.responseHeaderValue(header) ? request.responseHeaderValue(hea
der).match(new RegExp(regexp, 'im')) : |
| 689 null; | 690 null; |
| 690 } | 691 } |
| 691 | 692 |
| 692 /** | 693 /** |
| 693 * @param {!SDK.NetworkRequest} request | 694 * @param {!SDK.NetworkRequest} request |
| 694 * @return {boolean} | 695 * @return {boolean} |
| 695 */ | 696 */ |
| 696 hasExplicitExpiration(request) { | 697 hasExplicitExpiration(request) { |
| 697 return this.hasResponseHeader(request, 'Date') && | 698 return this.hasResponseHeader(request, 'Date') && |
| 698 (this.hasResponseHeader(request, 'Expires') || !!this.responseHeaderMatc
h(request, 'Cache-Control', 'max-age')); | 699 (this.hasResponseHeader(request, 'Expires') || !!this.responseHeaderMatc
h(request, 'Cache-Control', 'max-age')); |
| 699 } | 700 } |
| 700 | 701 |
| 701 /** | 702 /** |
| 702 * @param {!SDK.NetworkRequest} request | 703 * @param {!SDK.NetworkRequest} request |
| 703 * @return {boolean} | 704 * @return {boolean} |
| 704 */ | 705 */ |
| 705 _isExplicitlyNonCacheable(request) { | 706 _isExplicitlyNonCacheable(request) { |
| 706 var hasExplicitExp = this.hasExplicitExpiration(request); | 707 var hasExplicitExp = this.hasExplicitExpiration(request); |
| 707 return !!this.responseHeaderMatch(request, 'Cache-Control', '(no-cache|no-st
ore)') || | 708 return !!( |
| 709 !!this.responseHeaderMatch(request, 'Cache-Control', '(no-cache|no-store
)') || |
| 708 !!this.responseHeaderMatch(request, 'Pragma', 'no-cache') || | 710 !!this.responseHeaderMatch(request, 'Pragma', 'no-cache') || |
| 709 (hasExplicitExp && !this.freshnessLifetimeGreaterThan(request, 0)) || | 711 (hasExplicitExp && !this.freshnessLifetimeGreaterThan(request, 0)) || |
| 710 (!hasExplicitExp && !!request.url && request.url.indexOf('?') >= 0) || | 712 (!hasExplicitExp && request.url() && request.url().indexOf('?') >= 0) || |
| 711 (!hasExplicitExp && !this.isCacheableResource(request)); | 713 (!hasExplicitExp && !this.isCacheableResource(request))); |
| 712 } | 714 } |
| 713 | 715 |
| 714 /** | 716 /** |
| 715 * @param {!SDK.NetworkRequest} request | 717 * @param {!SDK.NetworkRequest} request |
| 716 * @return {boolean} | 718 * @return {boolean} |
| 717 */ | 719 */ |
| 718 isCacheableResource(request) { | 720 isCacheableResource(request) { |
| 719 return request.statusCode !== undefined && Audits.AuditRules.CacheableRespon
seCodes[request.statusCode]; | 721 return request.statusCode !== undefined && Audits.AuditRules.CacheableRespon
seCodes[request.statusCode]; |
| 720 } | 722 } |
| 721 }; | 723 }; |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1449 } | 1451 } |
| 1450 | 1452 |
| 1451 processCookies(allCookies, requests, result) { | 1453 processCookies(allCookies, requests, result) { |
| 1452 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap( | 1454 var domainToResourcesMap = Audits.AuditRules.getDomainToResourcesMap( |
| 1453 requests, [Common.resourceTypes.Stylesheet, Common.resourceTypes.Image],
true); | 1455 requests, [Common.resourceTypes.Stylesheet, Common.resourceTypes.Image],
true); |
| 1454 var totalStaticResources = 0; | 1456 var totalStaticResources = 0; |
| 1455 for (var domain in domainToResourcesMap) | 1457 for (var domain in domainToResourcesMap) |
| 1456 totalStaticResources += domainToResourcesMap[domain].length; | 1458 totalStaticResources += domainToResourcesMap[domain].length; |
| 1457 if (totalStaticResources < this._minResources) | 1459 if (totalStaticResources < this._minResources) |
| 1458 return; | 1460 return; |
| 1461 /** @type {!Object<string, number>} */ |
| 1459 var matchingResourceData = {}; | 1462 var matchingResourceData = {}; |
| 1460 this.mapResourceCookies(domainToResourcesMap, allCookies, this._collectorCal
lback.bind(this, matchingResourceData)); | 1463 this.mapResourceCookies(domainToResourcesMap, allCookies, this._collectorCal
lback.bind(this, matchingResourceData)); |
| 1461 | 1464 |
| 1462 var badUrls = []; | 1465 var badUrls = []; |
| 1463 var cookieBytes = 0; | 1466 var cookieBytes = 0; |
| 1464 for (var url in matchingResourceData) { | 1467 for (var url in matchingResourceData) { |
| 1465 badUrls.push(url); | 1468 badUrls.push(url); |
| 1466 cookieBytes += matchingResourceData[url]; | 1469 cookieBytes += matchingResourceData[url]; |
| 1467 } | 1470 } |
| 1468 if (badUrls.length < this._minResources) | 1471 if (badUrls.length < this._minResources) |
| 1469 return; | 1472 return; |
| 1470 | 1473 |
| 1471 var entry = result.addChild( | 1474 var entry = result.addChild( |
| 1472 Common.UIString( | 1475 Common.UIString( |
| 1473 '%s of cookies were sent with the following static resources. Serve
these static resources from a domain that does not set cookies:', | 1476 '%s of cookies were sent with the following static resources. Serve
these static resources from a domain that does not set cookies:', |
| 1474 Number.bytesToString(cookieBytes)), | 1477 Number.bytesToString(cookieBytes)), |
| 1475 true); | 1478 true); |
| 1476 entry.addURLs(badUrls); | 1479 entry.addURLs(badUrls); |
| 1477 result.violationCount = badUrls.length; | 1480 result.violationCount = badUrls.length; |
| 1478 } | 1481 } |
| 1479 | 1482 |
| 1483 /** |
| 1484 * @param {!Object<string, number>} matchingResourceData |
| 1485 * @param {!SDK.NetworkRequest} request |
| 1486 * @param {!SDK.Cookie} cookie |
| 1487 */ |
| 1480 _collectorCallback(matchingResourceData, request, cookie) { | 1488 _collectorCallback(matchingResourceData, request, cookie) { |
| 1481 matchingResourceData[request.url] = (matchingResourceData[request.url] || 0)
+ cookie.size(); | 1489 matchingResourceData[request.url()] = (matchingResourceData[request.url()] |
| 0) + cookie.size(); |
| 1482 } | 1490 } |
| 1483 }; | 1491 }; |
| OLD | NEW |