[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.21-584-g1e41756
apavlov at chromium.org
apavlov at chromium.org
Fri Feb 26 22:16:41 UTC 2010
The following commit has been merged in the webkit-1.1 branch:
commit ad4087a4bfa2e274020bf017333b1b036910e2af
Author: apavlov at chromium.org <apavlov at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Wed Feb 10 09:56:01 2010 +0000
2010-02-09 Alexander Pavlov <apavlov at chromium.org>
Reviewed by Pavel Feldman.
Web Inspector: Add two basic categories for the Audits panel
https://bugs.webkit.org/show_bug.cgi?id=32930
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* inspector/front-end/AuditCategories.js: Added.
(WebInspector.AuditCategories.PagePerformance):
(WebInspector.AuditCategories.PagePerformance.prototype.initialize):
(WebInspector.AuditCategories.NetworkUtilization):
(WebInspector.AuditCategories.NetworkUtilization.prototype.initialize):
* inspector/front-end/AuditLauncherView.js:
(WebInspector.AuditLauncherView.prototype.updateResourceTrackingState):
(WebInspector.AuditLauncherView.prototype._createLauncherUI):
(WebInspector.AuditLauncherView.prototype.show):
* inspector/front-end/AuditRules.js: Added.
(WebInspector.AuditRules.arrayAsUL):
(WebInspector.AuditRules.getDomainToResourcesMap):
(WebInspector.AuditRules.evaluateInTargetWindow):
(WebInspector.AuditRules.GzipRule):
(WebInspector.AuditRules.GzipRule.prototype.doRun):
(WebInspector.AuditRules.GzipRule.prototype._isCompressed):
(WebInspector.AuditRules.GzipRule.prototype._shouldCompress):
(WebInspector.AuditRules.CombineExternalResourcesRule):
(WebInspector.AuditRules.CombineExternalResourcesRule.prototype.doRun):
(WebInspector.AuditRules.CombineJsResourcesRule):
(WebInspector.AuditRules.CombineCssResourcesRule):
(WebInspector.AuditRules.MinimizeDnsLookupsRule):
(WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype.doRun):
(WebInspector.AuditRules.ParallelizeDownloadRule):
(WebInspector.AuditRules.ParallelizeDownloadRule.prototype.doRun):
(WebInspector.AuditRules.UnusedCssRule):
(WebInspector.AuditRules.UnusedCssRule.prototype._getUnusedStylesheetRatioMessage):
(WebInspector.AuditRules.UnusedCssRule.prototype._getUnusedTotalRatioMessage):
(WebInspector.AuditRules.UnusedCssRule.prototype.doRun.evalCallback):
(WebInspector.AuditRules.UnusedCssRule.prototype.doRun.routine):
(WebInspector.AuditRules.UnusedCssRule.prototype.doRun):
(WebInspector.AuditRules.CacheControlRule):
(WebInspector.AuditRules.CacheControlRule.prototype.InfoCheck.1.FailCheck.0.WarningCheck.1.SevereCheck.2.doRun):
(WebInspector.AuditRules.CacheControlRule.prototype.handleNonCacheableResources):
(WebInspector.AuditRules.CacheControlRule.prototype._cacheableAndNonCacheableResources):
(WebInspector.AuditRules.CacheControlRule.prototype.execCheck):
(WebInspector.AuditRules.CacheControlRule.prototype.freshnessLifetimeGreaterThan):
(WebInspector.AuditRules.CacheControlRule.prototype.responseHeader):
(WebInspector.AuditRules.CacheControlRule.prototype.hasResponseHeader):
(WebInspector.AuditRules.CacheControlRule.prototype.isCompressible):
(WebInspector.AuditRules.CacheControlRule.prototype.isPubliclyCacheable):
(WebInspector.AuditRules.CacheControlRule.prototype.responseHeaderMatch):
(WebInspector.AuditRules.CacheControlRule.prototype.hasExplicitExpiration):
(WebInspector.AuditRules.CacheControlRule.prototype._isExplicitlyNonCacheable):
(WebInspector.AuditRules.CacheControlRule.prototype.isCacheableResource):
(WebInspector.AuditRules.BrowserCacheControlRule):
(WebInspector.AuditRules.BrowserCacheControlRule.prototype.handleNonCacheableResources):
(WebInspector.AuditRules.BrowserCacheControlRule.prototype.runChecks):
(WebInspector.AuditRules.BrowserCacheControlRule.prototype._missingExpirationCheck):
(WebInspector.AuditRules.BrowserCacheControlRule.prototype._varyCheck):
(WebInspector.AuditRules.BrowserCacheControlRule.prototype._oneMonthExpirationCheck):
(WebInspector.AuditRules.BrowserCacheControlRule.prototype._oneYearExpirationCheck):
(WebInspector.AuditRules.ProxyCacheControlRule):
(WebInspector.AuditRules.ProxyCacheControlRule.prototype.runChecks):
(WebInspector.AuditRules.ProxyCacheControlRule.prototype._questionMarkCheck):
(WebInspector.AuditRules.ProxyCacheControlRule.prototype._publicCachingCheck):
(WebInspector.AuditRules.ProxyCacheControlRule.prototype._setCookieCacheableCheck):
(WebInspector.AuditRules.ImageDimensionsRule):
(WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun):
(WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun.routine.hasDimension):
(WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun.routine.hasWidth):
(WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun.routine.hasHeight):
(WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun.routine):
(WebInspector.AuditRules.CssInHeadRule):
(WebInspector.AuditRules.CssInHeadRule.prototype.doRun):
(WebInspector.AuditRules.CssInHeadRule.prototype.doRun.routine.allViews):
(WebInspector.AuditRules.CssInHeadRule.prototype.doRun.routine):
(WebInspector.AuditRules.StylesScriptsOrderRule):
(WebInspector.AuditRules.StylesScriptsOrderRule.prototype.doRun):
(WebInspector.AuditRules.StylesScriptsOrderRule.prototype.doRun.routine):
(WebInspector.AuditRules.CookieRuleBase):
(WebInspector.AuditRules.CookieRuleBase.prototype.doRun.resultCallback):
(WebInspector.AuditRules.CookieRuleBase.prototype.doRun):
(WebInspector.AuditRules.CookieRuleBase.prototype.mapResourceCookies):
(WebInspector.AuditRules.CookieRuleBase.prototype._callbackForResourceCookiePairs):
(WebInspector.AuditRules.CookieSizeRule):
(WebInspector.AuditRules.CookieSizeRule.prototype._average):
(WebInspector.AuditRules.CookieSizeRule.prototype._max):
(WebInspector.AuditRules.CookieSizeRule.prototype.processCookies):
(WebInspector.AuditRules.CookieSizeRule.prototype.processCookies.avgSizeSorter):
(WebInspector.AuditRules.StaticCookielessRule):
(WebInspector.AuditRules.StaticCookielessRule.prototype.processCookies):
(WebInspector.AuditRules.StaticCookielessRule.prototype._collectorCallback):
* inspector/front-end/AuditsPanel.js:
(WebInspector.AuditsPanel.prototype._constructCategories):
(WebInspector.AuditsPanel.prototype._reloadResources):
(WebInspector.AuditsPanel.prototype.show):
(WebInspector.AuditsPanel.prototype._updateLauncherViewControls):
(WebInspector.AuditCategory):
(WebInspector.AuditCategory.prototype.get id):
(WebInspector.AuditCategory.prototype.get ruleCount):
(WebInspector.AuditCategory.prototype.runRules):
(WebInspector.AuditCategory.prototype._ensureInitialized):
(WebInspector.AuditCategoryResult):
* inspector/front-end/WebKit.qrc:
* inspector/front-end/audits.css:
* inspector/front-end/inspector.html:
* inspector/front-end/inspector.js:
(WebInspector.loaded):
(WebInspector.addPanelToolbarIcon):
(WebInspector.documentKeyDown):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@54591 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 6376914..b55baf6 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,114 @@
+2010-02-09 Alexander Pavlov <apavlov at chromium.org>
+
+ Reviewed by Pavel Feldman.
+
+ Web Inspector: Add two basic categories for the Audits panel
+ https://bugs.webkit.org/show_bug.cgi?id=32930
+
+ * WebCore.gypi:
+ * WebCore.vcproj/WebCore.vcproj:
+ * inspector/front-end/AuditCategories.js: Added.
+ (WebInspector.AuditCategories.PagePerformance):
+ (WebInspector.AuditCategories.PagePerformance.prototype.initialize):
+ (WebInspector.AuditCategories.NetworkUtilization):
+ (WebInspector.AuditCategories.NetworkUtilization.prototype.initialize):
+ * inspector/front-end/AuditLauncherView.js:
+ (WebInspector.AuditLauncherView.prototype.updateResourceTrackingState):
+ (WebInspector.AuditLauncherView.prototype._createLauncherUI):
+ (WebInspector.AuditLauncherView.prototype.show):
+ * inspector/front-end/AuditRules.js: Added.
+ (WebInspector.AuditRules.arrayAsUL):
+ (WebInspector.AuditRules.getDomainToResourcesMap):
+ (WebInspector.AuditRules.evaluateInTargetWindow):
+ (WebInspector.AuditRules.GzipRule):
+ (WebInspector.AuditRules.GzipRule.prototype.doRun):
+ (WebInspector.AuditRules.GzipRule.prototype._isCompressed):
+ (WebInspector.AuditRules.GzipRule.prototype._shouldCompress):
+ (WebInspector.AuditRules.CombineExternalResourcesRule):
+ (WebInspector.AuditRules.CombineExternalResourcesRule.prototype.doRun):
+ (WebInspector.AuditRules.CombineJsResourcesRule):
+ (WebInspector.AuditRules.CombineCssResourcesRule):
+ (WebInspector.AuditRules.MinimizeDnsLookupsRule):
+ (WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype.doRun):
+ (WebInspector.AuditRules.ParallelizeDownloadRule):
+ (WebInspector.AuditRules.ParallelizeDownloadRule.prototype.doRun):
+ (WebInspector.AuditRules.UnusedCssRule):
+ (WebInspector.AuditRules.UnusedCssRule.prototype._getUnusedStylesheetRatioMessage):
+ (WebInspector.AuditRules.UnusedCssRule.prototype._getUnusedTotalRatioMessage):
+ (WebInspector.AuditRules.UnusedCssRule.prototype.doRun.evalCallback):
+ (WebInspector.AuditRules.UnusedCssRule.prototype.doRun.routine):
+ (WebInspector.AuditRules.UnusedCssRule.prototype.doRun):
+ (WebInspector.AuditRules.CacheControlRule):
+ (WebInspector.AuditRules.CacheControlRule.prototype.InfoCheck.1.FailCheck.0.WarningCheck.1.SevereCheck.2.doRun):
+ (WebInspector.AuditRules.CacheControlRule.prototype.handleNonCacheableResources):
+ (WebInspector.AuditRules.CacheControlRule.prototype._cacheableAndNonCacheableResources):
+ (WebInspector.AuditRules.CacheControlRule.prototype.execCheck):
+ (WebInspector.AuditRules.CacheControlRule.prototype.freshnessLifetimeGreaterThan):
+ (WebInspector.AuditRules.CacheControlRule.prototype.responseHeader):
+ (WebInspector.AuditRules.CacheControlRule.prototype.hasResponseHeader):
+ (WebInspector.AuditRules.CacheControlRule.prototype.isCompressible):
+ (WebInspector.AuditRules.CacheControlRule.prototype.isPubliclyCacheable):
+ (WebInspector.AuditRules.CacheControlRule.prototype.responseHeaderMatch):
+ (WebInspector.AuditRules.CacheControlRule.prototype.hasExplicitExpiration):
+ (WebInspector.AuditRules.CacheControlRule.prototype._isExplicitlyNonCacheable):
+ (WebInspector.AuditRules.CacheControlRule.prototype.isCacheableResource):
+ (WebInspector.AuditRules.BrowserCacheControlRule):
+ (WebInspector.AuditRules.BrowserCacheControlRule.prototype.handleNonCacheableResources):
+ (WebInspector.AuditRules.BrowserCacheControlRule.prototype.runChecks):
+ (WebInspector.AuditRules.BrowserCacheControlRule.prototype._missingExpirationCheck):
+ (WebInspector.AuditRules.BrowserCacheControlRule.prototype._varyCheck):
+ (WebInspector.AuditRules.BrowserCacheControlRule.prototype._oneMonthExpirationCheck):
+ (WebInspector.AuditRules.BrowserCacheControlRule.prototype._oneYearExpirationCheck):
+ (WebInspector.AuditRules.ProxyCacheControlRule):
+ (WebInspector.AuditRules.ProxyCacheControlRule.prototype.runChecks):
+ (WebInspector.AuditRules.ProxyCacheControlRule.prototype._questionMarkCheck):
+ (WebInspector.AuditRules.ProxyCacheControlRule.prototype._publicCachingCheck):
+ (WebInspector.AuditRules.ProxyCacheControlRule.prototype._setCookieCacheableCheck):
+ (WebInspector.AuditRules.ImageDimensionsRule):
+ (WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun):
+ (WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun.routine.hasDimension):
+ (WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun.routine.hasWidth):
+ (WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun.routine.hasHeight):
+ (WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun.routine):
+ (WebInspector.AuditRules.CssInHeadRule):
+ (WebInspector.AuditRules.CssInHeadRule.prototype.doRun):
+ (WebInspector.AuditRules.CssInHeadRule.prototype.doRun.routine.allViews):
+ (WebInspector.AuditRules.CssInHeadRule.prototype.doRun.routine):
+ (WebInspector.AuditRules.StylesScriptsOrderRule):
+ (WebInspector.AuditRules.StylesScriptsOrderRule.prototype.doRun):
+ (WebInspector.AuditRules.StylesScriptsOrderRule.prototype.doRun.routine):
+ (WebInspector.AuditRules.CookieRuleBase):
+ (WebInspector.AuditRules.CookieRuleBase.prototype.doRun.resultCallback):
+ (WebInspector.AuditRules.CookieRuleBase.prototype.doRun):
+ (WebInspector.AuditRules.CookieRuleBase.prototype.mapResourceCookies):
+ (WebInspector.AuditRules.CookieRuleBase.prototype._callbackForResourceCookiePairs):
+ (WebInspector.AuditRules.CookieSizeRule):
+ (WebInspector.AuditRules.CookieSizeRule.prototype._average):
+ (WebInspector.AuditRules.CookieSizeRule.prototype._max):
+ (WebInspector.AuditRules.CookieSizeRule.prototype.processCookies):
+ (WebInspector.AuditRules.CookieSizeRule.prototype.processCookies.avgSizeSorter):
+ (WebInspector.AuditRules.StaticCookielessRule):
+ (WebInspector.AuditRules.StaticCookielessRule.prototype.processCookies):
+ (WebInspector.AuditRules.StaticCookielessRule.prototype._collectorCallback):
+ * inspector/front-end/AuditsPanel.js:
+ (WebInspector.AuditsPanel.prototype._constructCategories):
+ (WebInspector.AuditsPanel.prototype._reloadResources):
+ (WebInspector.AuditsPanel.prototype.show):
+ (WebInspector.AuditsPanel.prototype._updateLauncherViewControls):
+ (WebInspector.AuditCategory):
+ (WebInspector.AuditCategory.prototype.get id):
+ (WebInspector.AuditCategory.prototype.get ruleCount):
+ (WebInspector.AuditCategory.prototype.runRules):
+ (WebInspector.AuditCategory.prototype._ensureInitialized):
+ (WebInspector.AuditCategoryResult):
+ * inspector/front-end/WebKit.qrc:
+ * inspector/front-end/audits.css:
+ * inspector/front-end/inspector.html:
+ * inspector/front-end/inspector.js:
+ (WebInspector.loaded):
+ (WebInspector.addPanelToolbarIcon):
+ (WebInspector.documentKeyDown):
+
2010-02-10 Adam Barth <abarth at webkit.org>
Reviewed by Darin Adler.
diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi
index b5499d4..92ebf49 100644
--- a/WebCore/WebCore.gypi
+++ b/WebCore/WebCore.gypi
@@ -3700,8 +3700,10 @@
'inspector/front-end/inspector.html',
'inspector/front-end/AbstractTimelinePanel.js',
+ 'inspector/front-end/AuditCategories.js',
'inspector/front-end/AuditLauncherView.js',
'inspector/front-end/AuditResultView.js',
+ 'inspector/front-end/AuditRules.js',
'inspector/front-end/AuditsPanel.js',
'inspector/front-end/BottomUpProfileDataGridTree.js',
'inspector/front-end/Breakpoint.js',
diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj
index 8bcca83..2b04c0c 100644
--- a/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -42700,6 +42700,10 @@
>
</File>
<File
+ RelativePath="..\inspector\front-end\AuditCategories.js"
+ >
+ </File>
+ <File
RelativePath="..\inspector\front-end\AuditLauncherView.js"
>
</File>
@@ -42708,6 +42712,10 @@
>
</File>
<File
+ RelativePath="..\inspector\front-end\AuditRules.js"
+ >
+ </File>
+ <File
RelativePath="..\inspector\front-end\audits.css"
>
</File>
diff --git a/WebCore/inspector/front-end/AuditCategories.js b/WebCore/inspector/front-end/AuditCategories.js
new file mode 100644
index 0000000..6931b5f
--- /dev/null
+++ b/WebCore/inspector/front-end/AuditCategories.js
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.AuditCategories.PagePerformance = function() {
+ WebInspector.AuditCategory.call(this, WebInspector.AuditCategories.PagePerformance.AuditCategoryName);
+}
+
+WebInspector.AuditCategories.PagePerformance.AuditCategoryName = "Web Page Performance";
+
+WebInspector.AuditCategories.PagePerformance.prototype = {
+ initialize: function()
+ {
+ this.addRule(new WebInspector.AuditRules.UnusedCssRule());
+ this.addRule(new WebInspector.AuditRules.CssInHeadRule({InlineURLScore: 6, InlineStylesheetScore: 21}));
+ this.addRule(new WebInspector.AuditRules.StylesScriptsOrderRule({CSSAfterJSURLScore: 11, InlineBetweenResourcesScore: 21}));
+ }
+}
+
+WebInspector.AuditCategories.PagePerformance.prototype.__proto__ = WebInspector.AuditCategory.prototype;
+
+WebInspector.AuditCategories.NetworkUtilization = function() {
+ WebInspector.AuditCategory.call(this, WebInspector.AuditCategories.NetworkUtilization.AuditCategoryName);
+}
+
+WebInspector.AuditCategories.NetworkUtilization.AuditCategoryName = "Network Utilization";
+
+WebInspector.AuditCategories.NetworkUtilization.prototype = {
+ initialize: function()
+ {
+ this.addRule(new WebInspector.AuditRules.GzipRule());
+ this.addRule(new WebInspector.AuditRules.ImageDimensionsRule({ScorePerImageUse: 5}));
+ this.addRule(new WebInspector.AuditRules.CookieSizeRule({MinBytesThreshold: 400, MaxBytesThreshold: 1000}));
+ this.addRule(new WebInspector.AuditRules.StaticCookielessRule({MinResources: 5}));
+ this.addRule(new WebInspector.AuditRules.CombineJsResourcesRule({AllowedPerDomain: 2, ScorePerResource: 11}));
+ this.addRule(new WebInspector.AuditRules.CombineCssResourcesRule({AllowedPerDomain: 2, ScorePerResource: 11}));
+ this.addRule(new WebInspector.AuditRules.MinimizeDnsLookupsRule({HostCountThreshold: 4, ViolationDomainScore: 6}));
+ this.addRule(new WebInspector.AuditRules.ParallelizeDownloadRule({OptimalHostnameCount: 4, MinRequestThreshold: 10, MinBalanceThreshold: 0.5}));
+ this.addRule(new WebInspector.AuditRules.BrowserCacheControlRule());
+ this.addRule(new WebInspector.AuditRules.ProxyCacheControlRule());
+ }
+}
+
+WebInspector.AuditCategories.NetworkUtilization.prototype.__proto__ = WebInspector.AuditCategory.prototype;
diff --git a/WebCore/inspector/front-end/AuditLauncherView.js b/WebCore/inspector/front-end/AuditLauncherView.js
index 79fbb92..f2a2fd2 100644
--- a/WebCore/inspector/front-end/AuditLauncherView.js
+++ b/WebCore/inspector/front-end/AuditLauncherView.js
@@ -63,11 +63,11 @@ WebInspector.AuditLauncherView = function(categoriesById, runnerCallback)
}
WebInspector.AuditLauncherView.prototype = {
- updateResourceTrackingState: function()
+ updateResourceTrackingState: function(isTracking)
{
if (!this._auditPresentStateLabelElement)
return;
- if (InspectorBackend.resourceTrackingEnabled()) {
+ if (isTracking) {
this._auditPresentStateLabelElement.nodeValue = WebInspector.UIString("Audit Present State");
this._auditPresentStateElement.disabled = false;
this._auditPresentStateElement.parentElement.removeStyleClass("disabled");
@@ -197,7 +197,6 @@ WebInspector.AuditLauncherView.prototype = {
this._selectAllClicked(this._selectAllCheckboxElement.checked);
this.updateResourceTrackingState();
this._updateButton();
- this.resize();
},
_updateButton: function()
@@ -209,6 +208,12 @@ WebInspector.AuditLauncherView.prototype = {
this._launchButton.textContent = WebInspector.UIString("Run");
},
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+ setTimeout(this.resize(), 0);
+ },
+
resize: function()
{
if (this._categoriesElement)
diff --git a/WebCore/inspector/front-end/AuditRules.js b/WebCore/inspector/front-end/AuditRules.js
new file mode 100644
index 0000000..210b8a9
--- /dev/null
+++ b/WebCore/inspector/front-end/AuditRules.js
@@ -0,0 +1,1213 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.AuditRules.IPAddressRegexp = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
+
+WebInspector.AuditRules.CacheableResponseCodes =
+{
+ 200: true,
+ 203: true,
+ 206: true,
+ 300: true,
+ 301: true,
+ 410: true,
+
+ 304: true // Underlying resource is cacheable
+}
+
+/**
+ * @param {Array} array Array of Elements (outerHTML is used) or strings (plain value is used as innerHTML)
+ */
+WebInspector.AuditRules.arrayAsUL = function(array, shouldLinkify)
+{
+ if (!array.length)
+ return "";
+ var ulElement = document.createElement("ul");
+ for (var i = 0; i < array.length; ++i) {
+ var liElement = document.createElement("li");
+ if (array[i] instanceof Element)
+ liElement.appendChild(array[i]);
+ else if (shouldLinkify)
+ liElement.appendChild(WebInspector.linkifyURLAsNode(array[i]));
+ else
+ liElement.innerHTML = array[i];
+ ulElement.appendChild(liElement);
+ }
+ return ulElement.outerHTML;
+}
+
+WebInspector.AuditRules.getDomainToResourcesMap = function(resources, types, regexp, needFullResources)
+{
+ var domainToResourcesMap = {};
+ for (var i = 0, size = resources.length; i < size; ++i) {
+ var resource = resources[i];
+ if (types && types.indexOf(resource.type) === -1)
+ continue;
+ var match = resource.url.match(regexp);
+ if (!match)
+ continue;
+ var domain = match[2];
+ var domainResources = domainToResourcesMap[domain];
+ if (domainResources === undefined) {
+ domainResources = [];
+ domainToResourcesMap[domain] = domainResources;
+ }
+ domainResources.push(needFullResources ? resource : resource.url);
+ }
+ return domainToResourcesMap;
+}
+
+WebInspector.AuditRules.evaluateInTargetWindow = function(func, callback)
+{
+ InjectedScriptAccess.getDefault().evaluateOnSelf(func.toString(), callback);
+}
+
+
+WebInspector.AuditRules.GzipRule = function()
+{
+ WebInspector.AuditRule.call(this, "network-gzip", "Enable gzip compression");
+}
+
+WebInspector.AuditRules.GzipRule.prototype = {
+ doRun: function(resources, result, callback)
+ {
+ try {
+ var commonMessage = undefined;
+ var totalSavings = 0;
+ var compressedSize = 0
+ var candidateSize = 0
+ var outputResources = [];
+ for (var i = 0, length = resources.length; i < length; ++i) {
+ var resource = resources[i];
+ if (this._shouldCompress(resource)) {
+ var size = resource.contentLength;
+ candidateSize += size;
+ if (this._isCompressed(resource)) {
+ compressedSize += size;
+ continue;
+ }
+ if (!commonMessage)
+ commonMessage = result.appendChild("");
+ var savings = 2 * size / 3;
+ totalSavings += savings;
+ outputResources.push(
+ String.sprintf("Compressing %s could save ~%s",
+ WebInspector.linkifyURL(resource.url), Number.bytesToString(savings)));
+ }
+ }
+ if (commonMessage) {
+ commonMessage.value =
+ String.sprintf("Compressing the following resources with gzip could reduce their " +
+ "transfer size by about two thirds (~%s):", Number.bytesToString(totalSavings));
+ commonMessage.appendChild(WebInspector.AuditRules.arrayAsUL(outputResources));
+ result.score = 100 * compressedSize / candidateSize;
+ result.type = WebInspector.AuditRuleResult.Type.Violation;
+ }
+ } catch(e) {
+ console.log(e);
+ } finally {
+ callback(result);
+ }
+ },
+
+ _isCompressed: function(resource)
+ {
+ var encoding = resource.responseHeaders["Content-Encoding"];
+ return encoding === "gzip" || encoding === "deflate";
+ },
+
+ _shouldCompress: function(resource)
+ {
+ return WebInspector.Resource.Type.isTextType(resource.type) && resource.domain && resource.contentLength !== undefined && resource.contentLength > 150;
+ }
+}
+
+WebInspector.AuditRules.GzipRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CombineExternalResourcesRule = function(id, name, type, resourceTypeName, parametersObject)
+{
+ WebInspector.AuditRule.call(this, id, name, parametersObject);
+ this._type = type;
+ this._resourceTypeName = resourceTypeName;
+}
+
+WebInspector.AuditRules.CombineExternalResourcesRule.prototype = {
+ doRun: function(resources, result, callback)
+ {
+ try {
+ var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, [this._type], WebInspector.URLRegExp);
+ var penalizedResourceCount = 0;
+ // TODO: refactor according to the chosen i18n approach
+ for (var domain in domainToResourcesMap) {
+ var domainResources = domainToResourcesMap[domain];
+ var extraResourceCount = domainResources.length - this.getValue("AllowedPerDomain");
+ if (extraResourceCount <= 0)
+ continue;
+ penalizedResourceCount += extraResourceCount - 1;
+ result.appendChild(
+ String.sprintf("There are %d %s files served from %s. Consider combining them into as few files as possible.",
+ domainResources.length, this._resourceTypeName, domain));
+ }
+ result.score = 100 - (penalizedResourceCount * this.getValue("ScorePerResource"));
+ result.type = WebInspector.AuditRuleResult.Type.Hint;
+ } catch(e) {
+ console.log(e);
+ } finally {
+ callback(result);
+ }
+ }
+};
+
+WebInspector.AuditRules.CombineExternalResourcesRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CombineJsResourcesRule = function(parametersObject) {
+ WebInspector.AuditRules.CombineExternalResourcesRule.call(this, "page-externaljs", "Combine external JavaScript", WebInspector.Resource.Type.Script, "JS", parametersObject);
+}
+
+WebInspector.AuditRules.CombineJsResourcesRule.prototype.__proto__ = WebInspector.AuditRules.CombineExternalResourcesRule.prototype;
+
+
+WebInspector.AuditRules.CombineCssResourcesRule = function(parametersObject) {
+ WebInspector.AuditRules.CombineExternalResourcesRule.call(this, "page-externalcss", "Combine external CSS", WebInspector.Resource.Type.Stylesheet, "CSS", parametersObject);
+}
+
+WebInspector.AuditRules.CombineCssResourcesRule.prototype.__proto__ = WebInspector.AuditRules.CombineExternalResourcesRule.prototype;
+
+
+WebInspector.AuditRules.MinimizeDnsLookupsRule = function(parametersObject) {
+ WebInspector.AuditRule.call(this, "network-minimizelookups", "Minimize DNS lookups", parametersObject);
+}
+
+WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype = {
+ doRun: function(resources, result, callback)
+ {
+ try {
+ var violationDomains = [];
+ var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, undefined, WebInspector.URLRegExp);
+ for (var domain in domainToResourcesMap) {
+ if (domainToResourcesMap[domain].length > 1)
+ continue;
+ var match = domain.match(WebInspector.URLRegExp);
+ if (!match)
+ continue;
+ if (!match[2].search(WebInspector.AuditRules.IPAddressRegexp))
+ continue; // an IP address
+ violationDomains.push(match[2]);
+ }
+ if (violationDomains.length <= this.getValue("HostCountThreshold"))
+ return;
+ var commonMessage = result.appendChild(
+ "The following domains only serve one resource each. If possible, avoid the extra DNS " +
+ "lookups by serving these resources from existing domains.");
+ commonMessage.appendChild(WebInspector.AuditRules.arrayAsUL(violationDomains));
+ result.score = 100 - violationDomains.length * this.getValue("ViolationDomainScore");
+ } catch(e) {
+ console.log(e);
+ } finally {
+ callback(result);
+ }
+ }
+}
+
+WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.ParallelizeDownloadRule = function(parametersObject)
+{
+ WebInspector.AuditRule.call(this, "network-parallelizehosts", "Parallelize downloads across hostnames", parametersObject);
+}
+
+
+WebInspector.AuditRules.ParallelizeDownloadRule.prototype = {
+ doRun: function(resources, result, callback)
+ {
+ function hostSorter(a, b)
+ {
+ var aCount = domainToResourcesMap[a].length;
+ var bCount = domainToResourcesMap[b].length;
+ return (aCount < bCount) ? 1 : (aCount == bCount) ? 0 : -1;
+ }
+
+ try {
+ var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(
+ resources,
+ [WebInspector.Resource.Type.Stylesheet, WebInspector.Resource.Type.Image],
+ WebInspector.URLRegExp,
+ true);
+
+ var hosts = [];
+ for (var url in domainToResourcesMap)
+ hosts.push(url);
+
+ if (!hosts.length)
+ return; // no hosts (local file or something)
+
+ hosts.sort(hostSorter);
+
+ var optimalHostnameCount = this.getValue("OptimalHostnameCount");
+ if (hosts.length > optimalHostnameCount)
+ hosts.splice(optimalHostnameCount);
+
+ var busiestHostResourceCount = domainToResourcesMap[hosts[0]].length;
+ var resourceCountAboveThreshold = busiestHostResourceCount - this.getValue("MinRequestThreshold");
+ if (resourceCountAboveThreshold <= 0)
+ return;
+
+ var avgResourcesPerHost = 0;
+ for (var i = 0, size = hosts.length; i < size; ++i)
+ avgResourcesPerHost += domainToResourcesMap[hosts[i]].length;
+
+ // Assume optimal parallelization.
+ avgResourcesPerHost /= optimalHostnameCount;
+
+ avgResourcesPerHost = Math.max(avgResourcesPerHost, 1);
+
+ var pctAboveAvg = (resourceCountAboveThreshold / avgResourcesPerHost) - 1.0;
+
+ var minBalanceThreshold = this.getValue("MinBalanceThreshold");
+ if (pctAboveAvg < minBalanceThreshold) {
+ result.score = 100;
+ return;
+ }
+
+ result.score = (1 - (pctAboveAvg - minBalanceThreshold)) * 100;
+ result.type = WebInspector.AuditRuleResult.Type.Hint;
+
+ var resourcesOnBusiestHost = domainToResourcesMap[hosts[0]];
+ var commonMessage = result.appendChild(
+ String.sprintf("This page makes %d parallelizable requests to %s" +
+ ". Increase download parallelization by distributing the following" +
+ " requests across multiple hostnames.", busiestHostResourceCount, hosts[0]));
+ var outputResources = [];
+ for (var i = 0, size = resourcesOnBusiestHost.length; i < size; ++i)
+ outputResources.push(resourcesOnBusiestHost[i].url);
+ commonMessage.appendChild(WebInspector.AuditRules.arrayAsUL(outputResources, true));
+ } catch(e) {
+ console.log(e);
+ } finally {
+ callback(result);
+ }
+ }
+}
+
+WebInspector.AuditRules.ParallelizeDownloadRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+// The reported CSS rule size is incorrect (parsed != original in WebKit),
+// so use percentages instead, which gives a better approximation.
+WebInspector.AuditRules.UnusedCssRule = function(parametersObject)
+{
+ WebInspector.AuditRule.call(this, "page-unusedcss", "Remove unused CSS", parametersObject);
+}
+
+WebInspector.AuditRules.UnusedCssRule.prototype = {
+ _getUnusedStylesheetRatioMessage: function(unusedLength, type, location, styleSheetLength)
+ {
+ var url = type === "href"
+ ? WebInspector.linkifyURL(location)
+ : String.sprintf("Inline block #%s", location);
+ var pctUnused = Math.round(unusedLength / styleSheetLength * 100);
+ return String.sprintf("%s: %f%% (estimated) is not used by the current page.", url, pctUnused);
+ },
+
+ _getUnusedTotalRatioMessage: function(unusedLength, totalLength)
+ {
+ var pctUnused = Math.round(unusedLength / totalLength * 100);
+ return String.sprintf("%d%% of CSS (estimated) is not used by the current page.", pctUnused);
+ },
+
+ doRun: function(resources, result, callback)
+ {
+ var self = this;
+ function evalCallback(evalResult, isException) {
+ try {
+ if (isException)
+ return;
+
+ var totalLength = 0;
+ var totalUnusedLength = 0;
+ var topMessage;
+ var styleSheetMessage;
+ for (var i = 0; i < evalResult.length; ) {
+ var type = evalResult[i++];
+ if (type === "totalLength") {
+ totalLength = evalResult[i++];
+ continue;
+ }
+
+ var styleSheetLength = evalResult[i++];
+ var location = evalResult[i++];
+ var unusedRules = evalResult[i++];
+ styleSheetMessage = undefined;
+ if (!topMessage)
+ topMessage = result.appendChild("");
+
+ var totalUnusedRuleLength = 0;
+ var ruleSelectors = [];
+ for (var j = 0; j < unusedRules.length; ++j) {
+ var rule = unusedRules[j];
+ totalUnusedRuleLength += parseInt(rule[1]);
+ if (!styleSheetMessage)
+ styleSheetMessage = result.appendChild("");
+ ruleSelectors.push(rule[0]);
+ }
+ styleSheetMessage.appendChild(WebInspector.AuditRules.arrayAsUL(ruleSelectors));
+
+ styleSheetMessage.value = self._getUnusedStylesheetRatioMessage(totalUnusedRuleLength, type, location, styleSheetLength);
+ totalUnusedLength += totalUnusedRuleLength;
+ }
+ if (totalUnusedLength) {
+ var totalUnusedPercent = totalUnusedLength / totalLength;
+ topMessage.value = self._getUnusedTotalRatioMessage(totalUnusedLength, totalLength);
+ var pctMultiplier = Math.log(Math.max(200, totalUnusedLength - 800)) / 7 - 0.6;
+ result.score = (1 - totalUnusedPercent * pctMultiplier) * 100;
+ result.type = WebInspector.AuditRuleResult.Type.Hint;
+ } else
+ result.score = 100;
+ } catch(e) {
+ console.log(e);
+ } finally {
+ callback(result);
+ }
+ }
+
+ function routine()
+ {
+ var styleSheets = document.styleSheets;
+ if (!styleSheets)
+ return {};
+ var styleSheetToUnusedRules = [];
+ var inlineBlockOrdinal = 0;
+ var totalCSSLength = 0;
+ var pseudoSelectorRegexp = /:hover|:link|:active|:visited|:focus/;
+ for (var i = 0; i < styleSheets.length; ++i) {
+ var styleSheet = styleSheets[i];
+ if (!styleSheet.cssRules)
+ continue;
+ var currentStyleSheetSize = 0;
+ var unusedRules = [];
+ for (var curRule = 0; curRule < styleSheet.cssRules.length; ++curRule) {
+ var rule = styleSheet.cssRules[curRule];
+ var textLength = rule.cssText ? rule.cssText.length : 0;
+ currentStyleSheetSize += textLength;
+ totalCSSLength += textLength;
+ if (rule.type !== 1 || rule.selectorText.match(pseudoSelectorRegexp))
+ continue;
+ var nodes = document.querySelectorAll(rule.selectorText);
+ if (nodes && nodes.length)
+ continue;
+ unusedRules.push([rule.selectorText, textLength]);
+ }
+ if (unusedRules.length) {
+ styleSheetToUnusedRules.push(styleSheet.href ? "href" : "inline");
+ styleSheetToUnusedRules.push(currentStyleSheetSize);
+ styleSheetToUnusedRules.push(styleSheet.href ? styleSheet.href : ++inlineBlockOrdinal);
+ styleSheetToUnusedRules.push(unusedRules);
+ }
+ }
+ styleSheetToUnusedRules.push("totalLength");
+ styleSheetToUnusedRules.push(totalCSSLength);
+ return styleSheetToUnusedRules;
+ }
+
+ WebInspector.AuditRules.evaluateInTargetWindow(routine, evalCallback);
+ }
+}
+
+WebInspector.AuditRules.UnusedCssRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CacheControlRule = function(id, name, parametersObject)
+{
+ WebInspector.AuditRule.call(this, id, name, parametersObject);
+}
+
+WebInspector.AuditRules.CacheControlRule.MillisPerMonth = 1000 * 60 * 60 * 24 * 30;
+
+WebInspector.AuditRules.CacheControlRule.prototype = {
+
+ InfoCheck: -1,
+ FailCheck: 0,
+ WarningCheck: 1,
+ SevereCheck: 2,
+
+ doRun: function(resources, result, callback)
+ {
+ try {
+ var cacheableAndNonCacheableResources = this._cacheableAndNonCacheableResources(resources);
+ if (cacheableAndNonCacheableResources[0].length) {
+ result.score = 100;
+ this.runChecks(cacheableAndNonCacheableResources[0], result);
+ }
+ this.handleNonCacheableResources(cacheableAndNonCacheableResources[1], result);
+ } catch(e) {
+ console.log(e);
+ } finally {
+ callback(result);
+ }
+ },
+
+ handleNonCacheableResources: function()
+ {
+ },
+
+ _cacheableAndNonCacheableResources: function(resources)
+ {
+ var processedResources = [[], []];
+ for (var i = 0; i < resources.length; ++i) {
+ var resource = resources[i];
+ if (!this.isCacheableResource(resource))
+ continue;
+ if (this._isExplicitlyNonCacheable(resource))
+ processedResources[1].push(resource);
+ else
+ processedResources[0].push(resource);
+ }
+ return processedResources;
+ },
+
+ execCheck: function(messageText, resourceCheckFunction, resources, severity, result)
+ {
+ var topMessage;
+ var failingResources = 0;
+ var resourceCount = resources.length;
+ var outputResources = [];
+ for (var i = 0; i < resourceCount; ++i) {
+ if (resourceCheckFunction.call(this, resources[i])) {
+ ++failingResources;
+ if (!topMessage)
+ topMessage = result.appendChild(messageText);
+ outputResources.push(resources[i].url);
+ }
+ }
+ if (topMessage)
+ topMessage.appendChild(WebInspector.AuditRules.arrayAsUL(outputResources, true));
+ if (failingResources) {
+ switch (severity) {
+ case this.FailCheck:
+ result.score = 0;
+ result.type = WebInspector.AuditRuleResult.Type.Violation;
+ break;
+ case this.SevereCheck:
+ case this.WarningCheck:
+ result.score -= 50 * severity * failingResources / resourceCount;
+ result.type = WebInspector.AuditRuleResult.Type.Hint;
+ break;
+ }
+ }
+ return topMessage;
+ },
+
+ freshnessLifetimeGreaterThan: function(resource, timeMs)
+ {
+ var dateHeader = this.responseHeader(resource, "Date");
+ if (!dateHeader)
+ return false;
+
+ var dateHeaderMs = Date.parse(dateHeader);
+ if (isNaN(dateHeaderMs))
+ return false;
+
+ var freshnessLifetimeMs;
+ var maxAgeMatch = this.responseHeaderMatch(resource, "Cache-Control", "max-age=(\\d+)");
+
+ if (maxAgeMatch)
+ freshnessLifetimeMs = (maxAgeMatch[1]) ? 1000 * maxAgeMatch[1] : 0;
+ else {
+ var expiresHeader = this.responseHeader(resource, "Expires");
+ if (expiresHeader) {
+ var expDate = Date.parse(expiresHeader);
+ if (!isNaN(expDate))
+ freshnessLifetimeMs = expDate - dateHeaderMs;
+ }
+ }
+
+ return (isNaN(freshnessLifetimeMs)) ? false : freshnessLifetimeMs > timeMs;
+ },
+
+ responseHeader: function(resource, header)
+ {
+ return resource.responseHeaders[header];
+ },
+
+ hasResponseHeader: function(resource, header)
+ {
+ return resource.responseHeaders[header] !== undefined;
+ },
+
+ isCompressible: function(resource)
+ {
+ return WebInspector.Resource.Type.isTextType(resource.type);
+ },
+
+ isPubliclyCacheable: function(resource)
+ {
+ if (this._isExplicitlyNonCacheable(resource))
+ return false;
+
+ if (this.responseHeaderMatch(resource, "Cache-Control", "public"))
+ return true;
+
+ return resource.url.indexOf("?") == -1 && !this.responseHeaderMatch(resource, "Cache-Control", "private");
+ },
+
+ responseHeaderMatch: function(resource, header, regexp)
+ {
+ return resource.responseHeaders[header]
+ ? resource.responseHeaders[header].match(new RegExp(regexp, "im"))
+ : undefined;
+ },
+
+ hasExplicitExpiration: function(resource)
+ {
+ return this.hasResponseHeader(resource, "Date") &&
+ (this.hasResponseHeader(resource, "Expires") || this.responseHeaderMatch(resource, "Cache-Control", "max-age"));
+ },
+
+ _isExplicitlyNonCacheable: function(resource)
+ {
+ var hasExplicitExp = this.hasExplicitExpiration(resource);
+ return this.responseHeaderMatch(resource, "Cache-Control", "(no-cache|no-store|must-revalidate)") ||
+ this.responseHeaderMatch(resource, "Pragma", "no-cache") ||
+ (hasExplicitExp && !this.freshnessLifetimeGreaterThan(resource, 0)) ||
+ (!hasExplicitExp && resource.url && resource.url.indexOf("?") >= 0) ||
+ (!hasExplicitExp && !this.isCacheableResource(resource));
+ },
+
+ isCacheableResource: function(resource)
+ {
+ return resource.statusCode !== undefined && WebInspector.AuditRules.CacheableResponseCodes[resource.statusCode];
+ }
+}
+
+WebInspector.AuditRules.CacheControlRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.BrowserCacheControlRule = function(parametersObject)
+{
+ WebInspector.AuditRules.CacheControlRule.call(this, "http-browsercache", "Leverage browser caching", parametersObject);
+}
+
+WebInspector.AuditRules.BrowserCacheControlRule.prototype = {
+ handleNonCacheableResources: function(resources, result)
+ {
+ if (resources.length) {
+ var message = result.appendChild(
+ "The following resources are explicitly non-cacheable. Consider making them cacheable if possible:");
+ var resourceOutput = [];
+ for (var i = 0; i < resources.length; ++i)
+ resourceOutput.push(resources[i].url);
+ message.appendChild(WebInspector.AuditRules.arrayAsUL(resourceOutput, true));
+ }
+ },
+
+ runChecks: function(resources, result, callback)
+ {
+ this.execCheck(
+ "The following resources are missing a cache expiration." +
+ " Resources that do not specify an expiration may not be" +
+ " cached by browsers:",
+ this._missingExpirationCheck, resources, this.SevereCheck, result);
+ this.execCheck(
+ "The following resources specify a \"Vary\" header that" +
+ " disables caching in most versions of Internet Explorer:",
+ this._varyCheck, resources, this.SevereCheck, result);
+ this.execCheck(
+ "The following cacheable resources have a short" +
+ " freshness lifetime:",
+ this._oneMonthExpirationCheck, resources, this.WarningCheck, result);
+
+ // Unable to implement the favicon check due to the WebKit limitations.
+
+ this.execCheck(
+ "To further improve cache hit rate, specify an expiration" +
+ " one year in the future for the following cacheable" +
+ " resources:",
+ this._oneYearExpirationCheck, resources, this.InfoCheck, result);
+ },
+
+ _missingExpirationCheck: function(resource)
+ {
+ return this.isCacheableResource(resource) && !this.hasResponseHeader(resource, "Set-Cookie") && !this.hasExplicitExpiration(resource);
+ },
+
+ _varyCheck: function(resource)
+ {
+ var varyHeader = this.responseHeader(resource, "Vary");
+ if (varyHeader) {
+ varyHeader = varyHeader.replace(/User-Agent/gi, "");
+ varyHeader = varyHeader.replace(/Accept-Encoding/gi, "");
+ varyHeader = varyHeader.replace(/[, ]*/g, "");
+ }
+ return varyHeader && varyHeader.length && this.isCacheableResource(resource) && this.freshnessLifetimeGreaterThan(resource, 0);
+ },
+
+ _oneMonthExpirationCheck: function(resource)
+ {
+ return this.isCacheableResource(resource) &&
+ !this.hasResponseHeader(resource, "Set-Cookie") &&
+ !this.freshnessLifetimeGreaterThan(resource, WebInspector.AuditRules.CacheControlRule.MillisPerMonth) &&
+ this.freshnessLifetimeGreaterThan(resource, 0);
+ },
+
+ _oneYearExpirationCheck: function(resource)
+ {
+ return this.isCacheableResource(resource) &&
+ !this.hasResponseHeader(resource, "Set-Cookie") &&
+ !this.freshnessLifetimeGreaterThan(resource, 11 * WebInspector.AuditRules.CacheControlRule.MillisPerMonth) &&
+ this.freshnessLifetimeGreaterThan(resource, WebInspector.AuditRules.CacheControlRule.MillisPerMonth);
+ }
+}
+
+WebInspector.AuditRules.BrowserCacheControlRule.prototype.__proto__ = WebInspector.AuditRules.CacheControlRule.prototype;
+
+
+WebInspector.AuditRules.ProxyCacheControlRule = function(parametersObject) {
+ WebInspector.AuditRules.CacheControlRule.call(this, "http-proxycache", "Leverage proxy caching", parametersObject);
+}
+
+WebInspector.AuditRules.ProxyCacheControlRule.prototype = {
+ runChecks: function(resources, result, callback)
+ {
+ this.execCheck(
+ "Resources with a \"?\" in the URL are not cached by most" +
+ " proxy caching servers:",
+ this._questionMarkCheck, resources, this.WarningCheck, result);
+ this.execCheck(
+ "Consider adding a \"Cache-Control: public\" header to the" +
+ " following resources:",
+ this._publicCachingCheck, resources, this.InfoCheck, result);
+ this.execCheck(
+ "The following publicly cacheable resources contain" +
+ " a Set-Cookie header. This security vulnerability" +
+ " can cause cookies to be shared by multiple users.",
+ this._setCookieCacheableCheck, resources, this.FailCheck, result);
+ },
+
+ _questionMarkCheck: function(resource)
+ {
+ return resource.url.indexOf("?") >= 0 && !this.hasResponseHeader(resource, "Set-Cookie") && this.isPubliclyCacheable(resource);
+ },
+
+ _publicCachingCheck: function(resource)
+ {
+ return this.isCacheableResource(resource) &&
+ !this.isCompressible(resource) &&
+ !this.responseHeaderMatch(resource, "Cache-Control", "public") &&
+ !this.hasResponseHeader(resource, "Set-Cookie");
+ },
+
+ _setCookieCacheableCheck: function(resource)
+ {
+ return this.hasResponseHeader(resource, "Set-Cookie") && this.isPubliclyCacheable(resource);
+ }
+}
+
+WebInspector.AuditRules.ProxyCacheControlRule.prototype.__proto__ = WebInspector.AuditRules.CacheControlRule.prototype;
+
+
+WebInspector.AuditRules.ImageDimensionsRule = function(parametersObject)
+{
+ WebInspector.AuditRule.call(this, "page-imagedims", "Specify image dimensions", parametersObject);
+}
+
+WebInspector.AuditRules.ImageDimensionsRule.prototype = {
+ doRun: function(resources, result, callback)
+ {
+ function evalCallback(evalResult, isException)
+ {
+ try {
+ if (isException)
+ return;
+ if (!evalResult || !evalResult.totalImages)
+ return;
+ result.score = 100;
+ var topMessage = result.appendChild(
+ "A width and height should be specified for all images in order to " +
+ "speed up page display. The following image(s) are missing a width and/or height:");
+ var map = evalResult.map;
+ var outputResources = [];
+ for (var url in map) {
+ var value = WebInspector.linkifyURL(url);
+ if (map[url] > 1)
+ value += " (" + map[url] + " uses)";
+ outputResources.push(value);
+ result.score -= this.getValue("ScorePerImageUse") * map[url];
+ result.type = WebInspector.AuditRuleResult.Type.Hint;
+ }
+ topMessage.appendChild(WebInspector.AuditRules.arrayAsUL(outputResources));
+ } catch(e) {
+ console.log(e);
+ } finally {
+ callback(result);
+ }
+ }
+
+ function routine()
+ {
+ var images = document.getElementsByTagName("img");
+ const widthRegExp = /width[^:;]*:/gim;
+ const heightRegExp = /height[^:;]*:/gim;
+
+ function hasDimension(element, cssText, rules, regexp, attributeName) {
+ if (element.attributes.getNamedItem(attributeName) != null || (cssText && cssText.match(regexp)))
+ return true;
+
+ if (!rules)
+ return false;
+ for (var i = 0; i < rules.length; ++i) {
+ if (rules.item(i).style.cssText.match(regexp))
+ return true;
+ }
+ return false;
+ }
+
+ function hasWidth(element, cssText, rules) {
+ return hasDimension(element, cssText, rules, widthRegExp, "width");
+ }
+
+ function hasHeight(element, cssText, rules) {
+ return hasDimension(element, cssText, rules, heightRegExp, "height");
+ }
+
+ var urlToNoDimensionCount = {};
+ var found = false;
+ for (var i = 0; i < images.length; ++i) {
+ var image = images[i];
+ if (!image.src)
+ continue;
+ var position = document.defaultView.getComputedStyle(image).getPropertyValue("position");
+ if (position === "absolute")
+ continue;
+ var cssText = (image.style && image.style.cssText) ? image.style.cssText : "";
+ var rules = document.defaultView.getMatchedCSSRules(image, "", true);
+ if (!hasWidth(image, cssText, rules) || !hasHeight(image, cssText, rules)) {
+ found = true;
+ if (urlToNoDimensionCount.hasOwnProperty(image.src))
+ ++urlToNoDimensionCount[image.src];
+ else
+ urlToNoDimensionCount[image.src] = 1;
+ }
+ }
+ return found ? {totalImages: images.length, map: urlToNoDimensionCount} : null;
+ }
+
+ WebInspector.AuditRules.evaluateInTargetWindow(routine, evalCallback.bind(this));
+ }
+}
+
+WebInspector.AuditRules.ImageDimensionsRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CssInHeadRule = function(parametersObject)
+{
+ WebInspector.AuditRule.call(this, "page-cssinhead", "Put CSS in the document head", parametersObject);
+}
+
+WebInspector.AuditRules.CssInHeadRule.prototype = {
+ doRun: function(resources, result, callback)
+ {
+ function evalCallback(evalResult, isException)
+ {
+ try {
+ if (isException)
+ return;
+ if (!evalResult)
+ return;
+ result.score = 100;
+ var outputMessages = [];
+ for (var url in evalResult) {
+ var urlViolations = evalResult[url];
+ var topMessage = result.appendChild(
+ String.sprintf("CSS in the %s document body adversely impacts rendering performance.",
+ WebInspector.linkifyURL(url)));
+ if (urlViolations[0]) {
+ outputMessages.push(
+ String.sprintf("%s style block(s) in the body should be moved to the document head.", urlViolations[0]));
+ result.score -= this.getValue("InlineURLScore") * urlViolations[0];
+ }
+ for (var i = 0; i < urlViolations[1].length; ++i) {
+ outputMessages.push(
+ String.sprintf("Link node %s should be moved to the document head", WebInspector.linkifyURL(urlViolations[1])));
+ }
+ result.score -= this.getValue("InlineStylesheetScore") * urlViolations[1];
+ result.type = WebInspector.AuditRuleResult.Type.Hint;
+ }
+ topMessage.appendChild(WebInspector.AuditRules.arrayAsUL(outputMessages));
+ } catch(e) {
+ console.log(e);
+ } finally {
+ callback(result);
+ }
+ }
+
+ function routine()
+ {
+ function allViews() {
+ var views = [document.defaultView];
+ var curView = 0;
+ while (curView < views.length) {
+ var view = views[curView];
+ var frames = view.frames;
+ for (var i = 0; i < frames.length; ++i) {
+ if (frames[i] !== view)
+ views.push(frames[i]);
+ }
+ ++curView;
+ }
+ return views;
+ }
+
+ var views = allViews();
+ var urlToViolationsArray = {};
+ var found = false;
+ for (var i = 0; i < views.length; ++i) {
+ var view = views[i];
+ if (!view.document)
+ continue;
+
+ var inlineStyles = view.document.querySelectorAll("body style");
+ var inlineStylesheets = view.document.querySelectorAll(
+ "body link[rel~='stylesheet'][href]");
+ if (!inlineStyles.length && !inlineStylesheets.length)
+ continue;
+
+ found = true;
+ var inlineStylesheetHrefs = [];
+ for (var j = 0; j < inlineStylesheets.length; ++j)
+ inlineStylesheetHrefs.push(inlineStylesheets[j].href);
+
+ urlToViolationsArray[view.location.href] =
+ [inlineStyles.length, inlineStylesheetHrefs];
+ }
+ return found ? urlToViolationsArray : null;
+ }
+
+ WebInspector.AuditRules.evaluateInTargetWindow(routine, evalCallback);
+ }
+}
+
+WebInspector.AuditRules.CssInHeadRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.StylesScriptsOrderRule = function(parametersObject)
+{
+ WebInspector.AuditRule.call(this, "page-stylescriptorder", "Optimize the order of styles and scripts", parametersObject);
+}
+
+WebInspector.AuditRules.StylesScriptsOrderRule.prototype = {
+ doRun: function(resources, result, callback)
+ {
+ function evalCallback(evalResult, isException)
+ {
+ try {
+ if (isException)
+ return;
+ if (!evalResult)
+ return;
+
+ result.score = 100;
+ var lateCssUrls = evalResult['late'];
+ if (lateCssUrls) {
+ var lateMessage = result.appendChild(
+ 'The following external CSS files were included after ' +
+ 'an external JavaScript file in the document head. To ' +
+ 'ensure CSS files are downloaded in parallel, always ' +
+ 'include external CSS before external JavaScript.');
+ lateMessage.appendChild(WebInspector.AuditRules.arrayAsUL(lateCssUrls, true));
+ result.score -= this.getValue("InlineBetweenResourcesScore") * lateCssUrls.length;
+ result.type = WebInspector.AuditRuleResult.Type.Violation;
+ }
+ if (evalResult['cssBeforeInlineCount']) {
+ var count = evalResult['cssBeforeInlineCount'];
+ result.appendChild(count + ' inline script block' +
+ (count > 1 ? 's were' : ' was') + ' found in the head between an ' +
+ 'external CSS file and another resource. To allow parallel ' +
+ 'downloading, move the inline script before the external CSS ' +
+ 'file, or after the next resource.');
+ result.score -= this.getValue("CSSAfterJSURLScore") * count;
+ result.type = WebInspector.AuditRuleResult.Type.Violation;
+ }
+ } catch(e) {
+ console.log(e);
+ } finally {
+ callback(result);
+ }
+ }
+
+ function routine()
+ {
+ var lateStyles = document.querySelectorAll(
+ "head script[src] ~ link[rel~='stylesheet'][href]");
+ var stylesBeforeInlineScript = document.querySelectorAll(
+ "head link[rel~='stylesheet'][href] ~ script:not([src])");
+
+ var resultObject;
+ if (!lateStyles.length && !stylesBeforeInlineScript.length)
+ resultObject = null;
+ else {
+ resultObject = {};
+ if (lateStyles.length) {
+ lateStyleUrls = [];
+ for (var i = 0; i < lateStyles.length; ++i)
+ lateStyleUrls.push(lateStyles[i].href);
+ resultObject["late"] = lateStyleUrls;
+ }
+ resultObject["cssBeforeInlineCount"] = stylesBeforeInlineScript.length;
+ }
+ return resultObject;
+ }
+
+ WebInspector.AuditRules.evaluateInTargetWindow(routine, evalCallback.bind(this));
+ }
+}
+
+WebInspector.AuditRules.StylesScriptsOrderRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CookieRuleBase = function(id, name, parametersObject)
+{
+ WebInspector.AuditRule.call(this, id, name, parametersObject);
+}
+
+WebInspector.AuditRules.CookieRuleBase.prototype = {
+ doRun: function(resources, result, callback)
+ {
+ var self = this;
+ function resultCallback(receivedCookies, isAdvanced) {
+ try {
+ self.processCookies(isAdvanced ? receivedCookies : [], resources, result);
+ } catch(e) {
+ console.log(e);
+ } finally {
+ callback(result);
+ }
+ }
+ WebInspector.Cookies.getCookiesAsync(resultCallback);
+ },
+
+ mapResourceCookies: function(resourcesByDomain, allCookies, callback)
+ {
+ for (var i = 0; i < allCookies.length; ++i) {
+ for (var resourceDomain in resourcesByDomain) {
+ if (WebInspector.Cookies.cookieDomainMatchesResourceDomain(allCookies[i].domain, resourceDomain))
+ this._callbackForResourceCookiePairs(resourcesByDomain[resourceDomain], allCookies[i], callback);
+ }
+ }
+ },
+
+ _callbackForResourceCookiePairs: function(resources, cookie, callback)
+ {
+ if (!resources)
+ return;
+ for (var i = 0; i < resources.length; ++i) {
+ if (WebInspector.Cookies.cookieMatchesResourceURL(cookie, resources[i].url))
+ callback(resources[i], cookie);
+ }
+ }
+}
+
+WebInspector.AuditRules.CookieRuleBase.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CookieSizeRule = function(parametersObject)
+{
+ WebInspector.AuditRules.CookieRuleBase.call(this, "http-cookiesize", "Minimize cookie size", parametersObject);
+}
+
+WebInspector.AuditRules.CookieSizeRule.prototype = {
+ _average: function(cookieArray)
+ {
+ var total = 0;
+ for (var i = 0; i < cookieArray.length; ++i)
+ total += cookieArray[i].size;
+ return cookieArray.length ? Math.round(total / cookieArray.length) : 0;
+ },
+
+ _max: function(cookieArray)
+ {
+ var result = 0;
+ for (var i = 0; i < cookieArray.length; ++i)
+ result = Math.max(cookieArray[i].size, result);
+ return result;
+ },
+
+ processCookies: function(allCookies, resources, result)
+ {
+ function maxSizeSorter(a, b)
+ {
+ return b.maxCookieSize - a.maxCookieSize;
+ }
+
+ function avgSizeSorter(a, b)
+ {
+ return b.avgCookieSize - a.avgCookieSize;
+ }
+
+ var cookiesPerResourceDomain = {};
+
+ function collectorCallback(resource, cookie)
+ {
+ var cookies = cookiesPerResourceDomain[resource.domain];
+ if (!cookies) {
+ cookies = [];
+ cookiesPerResourceDomain[resource.domain] = cookies;
+ }
+ cookies.push(cookie);
+ }
+
+ if (!allCookies.length)
+ return;
+
+ var sortedCookieSizes = [];
+
+ var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources,
+ null,
+ WebInspector.URLRegExp,
+ true);
+ var matchingResourceData = {};
+ this.mapResourceCookies(domainToResourcesMap, allCookies, collectorCallback.bind(this));
+
+ result.score = 100;
+ for (var resourceDomain in cookiesPerResourceDomain) {
+ var cookies = cookiesPerResourceDomain[resourceDomain];
+ sortedCookieSizes.push({
+ domain: resourceDomain,
+ avgCookieSize: this._average(cookies),
+ maxCookieSize: this._max(cookies)
+ });
+ }
+ var avgAllCookiesSize = this._average(allCookies);
+
+ var hugeCookieDomains = [];
+ sortedCookieSizes.sort(maxSizeSorter);
+
+ var maxBytesThreshold = this.getValue("MaxBytesThreshold");
+ var minBytesThreshold = this.getValue("MinBytesThreshold");
+
+ for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) {
+ var maxCookieSize = sortedCookieSizes[i].maxCookieSize;
+ if (maxCookieSize > maxBytesThreshold)
+ hugeCookieDomains.push(sortedCookieSizes[i].domain + ": " + Number.bytesToString(maxCookieSize));
+ }
+
+ var bigAvgCookieDomains = [];
+ sortedCookieSizes.sort(avgSizeSorter);
+ for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) {
+ var domain = sortedCookieSizes[i].domain;
+ var avgCookieSize = sortedCookieSizes[i].avgCookieSize;
+ if (avgCookieSize > minBytesThreshold && avgCookieSize < maxBytesThreshold)
+ bigAvgCookieDomains.push(domain + ": " + Number.bytesToString(avgCookieSize));
+ }
+ result.appendChild("The average cookie size for all requests on this page is " + Number.bytesToString(avgAllCookiesSize));
+
+ var message;
+ if (hugeCookieDomains.length) {
+ result.score = 75;
+ result.type = WebInspector.AuditRuleResult.Type.Violation;
+ message = result.appendChild(
+ String.sprintf("The following domains have a cookie size in excess of %d " +
+ " bytes. This is harmful because requests with cookies larger than 1KB" +
+ " typically cannot fit into a single network packet.", maxBytesThreshold));
+ message.appendChild(WebInspector.AuditRules.arrayAsUL(hugeCookieDomains));
+ }
+
+ if (bigAvgCookieDomains.length) {
+ this.score -= Math.max(0, avgAllCookiesSize - minBytesThreshold) /
+ (minBytesThreshold - minBytesThreshold) / this.getValue("TotalPoints");
+ if (!result.type)
+ result.type = WebInspector.AuditRuleResult.Type.Hint;
+ message = result.appendChild(
+ String.sprintf("The following domains have an average cookie size in excess of %d" +
+ " bytes. Reducing the size of cookies" +
+ " for these domains can reduce the time it takes to send requests.", minBytesThreshold));
+ message.appendChild(WebInspector.AuditRules.arrayAsUL(bigAvgCookieDomains));
+ }
+
+ if (!bigAvgCookieDomains.length && !hugeCookieDomains.length)
+ result.score = WebInspector.AuditCategoryResult.ScoreNA;
+ }
+}
+
+WebInspector.AuditRules.CookieSizeRule.prototype.__proto__ = WebInspector.AuditRules.CookieRuleBase.prototype;
+
+
+WebInspector.AuditRules.StaticCookielessRule = function(parametersObject)
+{
+ WebInspector.AuditRules.CookieRuleBase.call(this, "http-staticcookieless", "Serve static content from a cookieless domain", parametersObject);
+}
+
+WebInspector.AuditRules.StaticCookielessRule.prototype = {
+ processCookies: function(allCookies, resources, result)
+ {
+ var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources,
+ [WebInspector.Resource.Type.Stylesheet,
+ WebInspector.Resource.Type.Image],
+ WebInspector.URLRegExp,
+ true);
+ var totalStaticResources = 0;
+ var minResources = this.getValue("MinResources");
+ for (var domain in domainToResourcesMap)
+ totalStaticResources += domainToResourcesMap[domain].length;
+ if (totalStaticResources < minResources)
+ return;
+ var matchingResourceData = {};
+ this.mapResourceCookies(domainToResourcesMap, allCookies, this._collectorCallback.bind(this, matchingResourceData));
+
+ var badUrls = [];
+ var cookieBytes = 0;
+ for (var url in matchingResourceData) {
+ badUrls.push(url);
+ cookieBytes += matchingResourceData[url]
+ }
+ if (badUrls.length < minResources)
+ return;
+
+ result.score = 100;
+ var badPoints = cookieBytes / 75;
+ var violationPct = Math.max(badUrls.length / totalStaticResources, 0.6);
+ badPoints *= violationPct;
+ result.score -= badPoints;
+ result.score = Math.max(result.score, 0);
+ result.type = WebInspector.AuditRuleResult.Type.Violation;
+ result.appendChild(String.sprintf("%s of cookies were sent with the following static resources.", Number.bytesToString(cookieBytes)));
+ var message = result.appendChild("Serve these static resources from a domain that does not set cookies:");
+ message.appendChild(WebInspector.AuditRules.arrayAsUL(badUrls, true));
+ },
+
+ _collectorCallback: function(matchingResourceData, resource, cookie)
+ {
+ matchingResourceData[resource.url] = (matchingResourceData[resource.url] || 0) + cookie.size;
+ }
+}
+
+WebInspector.AuditRules.StaticCookielessRule.prototype.__proto__ = WebInspector.AuditRules.CookieRuleBase.prototype;
diff --git a/WebCore/inspector/front-end/AuditsPanel.js b/WebCore/inspector/front-end/AuditsPanel.js
index 696d132..fcadb82 100644
--- a/WebCore/inspector/front-end/AuditsPanel.js
+++ b/WebCore/inspector/front-end/AuditsPanel.js
@@ -105,7 +105,8 @@ WebInspector.AuditsPanel.prototype = {
this._auditCategoriesById = {};
for (var categoryCtorID in WebInspector.AuditCategories) {
var auditCategory = new WebInspector.AuditCategories[categoryCtorID]();
- this.categoriesById[auditCategory.id] = auditCategory;
+ auditCategory._id = categoryCtorID;
+ this.categoriesById[categoryCtorID] = auditCategory;
}
},
@@ -185,15 +186,13 @@ WebInspector.AuditsPanel.prototype = {
_reloadResources: function(callback)
{
- function nullCallback()
- {
- }
this._resourceTrackingCallback = callback;
+
if (!InspectorBackend.resourceTrackingEnabled()) {
InspectorBackend.enableResourceTracking(false);
- this._updateLauncherViewControls();
+ this._updateLauncherViewControls(true);
} else
- InjectedScriptAccess.getDefault().evaluate("window.location.reload()", nullCallback);
+ InjectedScriptAccess.getDefault().evaluate("window.location.reload()", switchCallback);
},
_didMainResourceLoad: function()
@@ -239,7 +238,7 @@ WebInspector.AuditsPanel.prototype = {
WebInspector.Panel.prototype.show.call(this);
this.showView();
- this._updateLauncherViewControls();
+ this._updateLauncherViewControls(InspectorBackend.resourceTrackingEnabled());
},
attach: function()
@@ -254,10 +253,10 @@ WebInspector.AuditsPanel.prototype = {
this.viewsContainerElement.style.left = width + "px";
},
- _updateLauncherViewControls: function()
+ _updateLauncherViewControls: function(isTracking)
{
if (this._launcherView)
- this._launcherView.updateResourceTrackingState();
+ this._launcherView.updateResourceTrackingState(isTracking);
},
_clearButtonClicked: function()
@@ -278,9 +277,8 @@ WebInspector.AuditsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
-WebInspector.AuditCategory = function(id, displayName)
+WebInspector.AuditCategory = function(displayName)
{
- this._id = id;
this._displayName = displayName;
this._rules = [];
}
@@ -288,6 +286,7 @@ WebInspector.AuditCategory = function(id, displayName)
WebInspector.AuditCategory.prototype = {
get id()
{
+ // this._id value is injected at construction time.
return this._id;
},
@@ -298,6 +297,7 @@ WebInspector.AuditCategory.prototype = {
get ruleCount()
{
+ this._ensureInitialized();
return this._rules.length;
},
@@ -308,8 +308,18 @@ WebInspector.AuditCategory.prototype = {
runRules: function(resources, callback)
{
+ this._ensureInitialized();
for (var i = 0; i < this._rules.length; ++i)
this._rules[i].run(resources, callback);
+ },
+
+ _ensureInitialized: function()
+ {
+ if (!this._initialized) {
+ if ("initialize" in this)
+ this.initialize();
+ this._initialized = true;
+ }
}
}
@@ -354,7 +364,6 @@ WebInspector.AuditRule.prototype = {
WebInspector.AuditCategoryResult = function(category)
{
- this.categoryId = category.id;
this.title = category.displayName;
this.entries = [];
}
@@ -378,8 +387,13 @@ WebInspector.AuditRuleResult = function(value)
}
WebInspector.AuditRuleResult.Type = {
+ // Does not denote a discovered flaw but rather represents an informational message.
NA: 0,
+
+ // Denotes a minor impact on the checked metric.
Hint: 1,
+
+ // Denotes a major impact on the checked metric.
Violation: 2
}
diff --git a/WebCore/inspector/front-end/WebKit.qrc b/WebCore/inspector/front-end/WebKit.qrc
index 20e9aa2..765f9b4 100644
--- a/WebCore/inspector/front-end/WebKit.qrc
+++ b/WebCore/inspector/front-end/WebKit.qrc
@@ -2,8 +2,10 @@
<qresource prefix="/webkit/inspector">
<file>inspector.html</file>
<file>AbstractTimelinePanel.js</file>
+ <file>AuditCategories.js</file>
<file>AuditLauncherView.js</file>
<file>AuditResultView.js</file>
+ <file>AuditRules.js</file>
<file>AuditsPanel.js</file>
<file>BottomUpProfileDataGridTree.js</file>
<file>Breakpoint.js</file>
diff --git a/WebCore/inspector/front-end/audits.css b/WebCore/inspector/front-end/audits.css
index 35db76b..9d02c80 100644
--- a/WebCore/inspector/front-end/audits.css
+++ b/WebCore/inspector/front-end/audits.css
@@ -262,11 +262,11 @@ body.inactive .audit-launcher-view button, .audit-launcher-view button:disabled
margin: 0 5px 5px 0;
}
-.audit-launcher-view input[type="radio"]:active {
+.audit-launcher-view input[type="radio"]:active:not(:disabled) {
background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239)));
}
-.audit-launcher-view input[type="radio"]:checked {
+.audit-launcher-view input[type="radio"]:checked:not(:disabled), .audit-launcher-view input[type="radio"]:checked:disabled {
background: url(Images/radioDot.png) center no-repeat,
-webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
}
diff --git a/WebCore/inspector/front-end/inspector.html b/WebCore/inspector/front-end/inspector.html
index 26264dc..0dee8f2 100644
--- a/WebCore/inspector/front-end/inspector.html
+++ b/WebCore/inspector/front-end/inspector.html
@@ -91,6 +91,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="AuditsPanel.js"></script>
<script type="text/javascript" src="AuditResultView.js"></script>
<script type="text/javascript" src="AuditLauncherView.js"></script>
+ <script type="text/javascript" src="AuditRules.js"></script>
+ <script type="text/javascript" src="AuditCategories.js"></script>
<script type="text/javascript" src="ResourceView.js"></script>
<script type="text/javascript" src="SourceFrame.js"></script>
<script type="text/javascript" src="DOMSyntaxHighlighter.js"></script>
diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js
index e44ee3c..77d3f42 100644
--- a/WebCore/inspector/front-end/inspector.js
+++ b/WebCore/inspector/front-end/inspector.js
@@ -468,17 +468,8 @@ WebInspector.loaded = function()
var previousToolbarItem = toolbarElement.children[0];
this.panelOrder = [];
- for (var panelName in this.panels) {
- var panel = this.panels[panelName];
- var panelToolbarItem = panel.toolbarItem;
- this.panelOrder.push(panel);
- panelToolbarItem.addEventListener("click", this._toolbarItemClicked.bind(this));
- if (previousToolbarItem)
- toolbarElement.insertBefore(panelToolbarItem, previousToolbarItem.nextSibling);
- else
- toolbarElement.insertBefore(panelToolbarItem, toolbarElement.firstChild);
- previousToolbarItem = panelToolbarItem;
- }
+ for (var panelName in this.panels)
+ previousToolbarItem = WebInspector.addPanelToolbarIcon(toolbarElement, this.panels[panelName], previousToolbarItem);
this.Tips = {
ResourceNotCompressed: {id: 0, message: WebInspector.UIString("You could save bandwidth by having your web server compress this transfer with gzip or zlib.")}
@@ -529,6 +520,18 @@ WebInspector.loaded = function()
InspectorFrontendHost.loaded();
}
+WebInspector.addPanelToolbarIcon = function(toolbarElement, panel, previousToolbarItem)
+{
+ var panelToolbarItem = panel.toolbarItem;
+ this.panelOrder.push(panel);
+ panelToolbarItem.addEventListener("click", this._toolbarItemClicked.bind(this));
+ if (previousToolbarItem)
+ toolbarElement.insertBefore(panelToolbarItem, previousToolbarItem.nextSibling);
+ else
+ toolbarElement.insertBefore(panelToolbarItem, toolbarElement.firstChild);
+ return panelToolbarItem;
+}
+
var windowLoaded = function()
{
var localizedStringsURL = InspectorFrontendHost.localizedStringsURL();
@@ -749,8 +752,11 @@ WebInspector.documentKeyDown = function(event)
var shouldShowAuditsPanel = event.ctrlKey && !event.shiftKey && !event.metaKey && event.altKey;
if (shouldShowAuditsPanel) {
- if (!this.panels.audits)
+ if (!this.panels.audits) {
this.panels.audits = new WebInspector.AuditsPanel();
+ var toolbarElement = document.getElementById("toolbar");
+ WebInspector.addPanelToolbarIcon(toolbarElement, this.panels.audits, this.panels.console.toolbarItem);
+ }
this.currentPanel = this.panels.audits;
}
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list