Home | History | Annotate | Download | only in audits
      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