1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * Copyright (C) 2013 Samsung Electronics. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /** 33 * @constructor 34 * @extends {WebInspector.TargetAware} 35 * @param {!WebInspector.Target} target 36 * @param {!WebInspector.AuditsPanel} auditsPanel 37 */ 38 WebInspector.AuditController = function(target, auditsPanel) 39 { 40 WebInspector.TargetAware.call(this, target); 41 this._auditsPanel = auditsPanel; 42 this.target().resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.Load, this._didMainResourceLoad, this); 43 } 44 45 WebInspector.AuditController.prototype = { 46 /** 47 * @param {!Array.<!WebInspector.AuditCategory>} categories 48 * @param {function(string, !Array.<!WebInspector.AuditCategoryResult>)} resultCallback 49 */ 50 _executeAudit: function(categories, resultCallback) 51 { 52 this._progress.setTitle(WebInspector.UIString("Running audit")); 53 54 /** 55 * @param {!WebInspector.AuditCategoryResult} categoryResult 56 * @param {!WebInspector.AuditRuleResult} ruleResult 57 * @this {WebInspector.AuditController} 58 */ 59 function ruleResultReadyCallback(categoryResult, ruleResult) 60 { 61 if (ruleResult && ruleResult.children) 62 categoryResult.addRuleResult(ruleResult); 63 64 if (this._progress.isCanceled()) 65 this._progress.done(); 66 } 67 68 var results = []; 69 var mainResourceURL = this.target().resourceTreeModel.inspectedPageURL(); 70 var categoriesDone = 0; 71 72 /** 73 * @this {WebInspector.AuditController} 74 */ 75 function categoryDoneCallback() 76 { 77 if (++categoriesDone !== categories.length) 78 return; 79 this._progress.done(); 80 resultCallback(mainResourceURL, results) 81 } 82 83 var requests = this.target().networkLog.requests.slice(); 84 var compositeProgress = new WebInspector.CompositeProgress(this._progress); 85 var subprogresses = []; 86 for (var i = 0; i < categories.length; ++i) 87 subprogresses.push(compositeProgress.createSubProgress()); 88 for (var i = 0; i < categories.length; ++i) { 89 var category = categories[i]; 90 var result = new WebInspector.AuditCategoryResult(category); 91 results.push(result); 92 category.run(this.target(), requests, ruleResultReadyCallback.bind(this, result), categoryDoneCallback.bind(this), subprogresses[i]); 93 } 94 }, 95 96 /** 97 * @param {function()} launcherCallback 98 * @param {string} mainResourceURL 99 * @param {!Array.<!WebInspector.AuditCategoryResult>} results 100 */ 101 _auditFinishedCallback: function(launcherCallback, mainResourceURL, results) 102 { 103 this._auditsPanel.auditFinishedCallback(mainResourceURL, results); 104 if (!this._progress.isCanceled()) 105 launcherCallback(); 106 }, 107 108 /** 109 * @param {!Array.<string>} categoryIds 110 * @param {!WebInspector.Progress} progress 111 * @param {boolean} runImmediately 112 * @param {function()} startedCallback 113 * @param {function()} finishedCallback 114 */ 115 initiateAudit: function(categoryIds, progress, runImmediately, startedCallback, finishedCallback) 116 { 117 if (!categoryIds || !categoryIds.length) 118 return; 119 120 this._progress = progress; 121 122 var categories = []; 123 for (var i = 0; i < categoryIds.length; ++i) 124 categories.push(this._auditsPanel.categoriesById[categoryIds[i]]); 125 126 /** 127 * @this {WebInspector.AuditController} 128 */ 129 function startAuditWhenResourcesReady() 130 { 131 startedCallback(); 132 this._executeAudit(categories, this._auditFinishedCallback.bind(this, finishedCallback)); 133 } 134 135 if (runImmediately) 136 startAuditWhenResourcesReady.call(this); 137 else 138 this._reloadResources(startAuditWhenResourcesReady.bind(this)); 139 140 WebInspector.userMetrics.AuditsStarted.record(); 141 }, 142 143 /** 144 * @param {function()=} callback 145 */ 146 _reloadResources: function(callback) 147 { 148 this._pageReloadCallback = callback; 149 this.target().resourceTreeModel.reloadPage(); 150 }, 151 152 _didMainResourceLoad: function() 153 { 154 if (this._pageReloadCallback) { 155 var callback = this._pageReloadCallback; 156 delete this._pageReloadCallback; 157 callback(); 158 } 159 }, 160 161 clearResults: function() 162 { 163 this._auditsPanel.clearResults(); 164 }, 165 166 __proto__: WebInspector.TargetAware.prototype 167 } 168