home *** CD-ROM | disk | FTP | other *** search
/ Computer Active Guide 2009 July / CAG7.ISO / Internetas / SafariSetup.exe / AppleApplicationSupport.msi / WebKit.resources_inspector_AuditsPanel.js < prev    next >
Encoding:
Text File  |  2010-06-03  |  13.5 KB  |  500 lines

  1. /*
  2.  * Copyright (C) 2009 Google Inc. All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions are
  6.  * met:
  7.  *
  8.  *     * Redistributions of source code must retain the above copyright
  9.  * notice, this list of conditions and the following disclaimer.
  10.  *     * Redistributions in binary form must reproduce the above
  11.  * copyright notice, this list of conditions and the following disclaimer
  12.  * in the documentation and/or other materials provided with the
  13.  * distribution.
  14.  *     * Neither the name of Google Inc. nor the names of its
  15.  * contributors may be used to endorse or promote products derived from
  16.  * this software without specific prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22.  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  */
  30.  
  31. WebInspector.AuditsPanel = function()
  32. {
  33.     WebInspector.Panel.call(this);
  34.  
  35.     this._constructCategories();
  36.  
  37.     this.createSidebar();
  38.     this.auditsTreeElement = new WebInspector.SidebarSectionTreeElement("", {}, true);
  39.     this.sidebarTree.appendChild(this.auditsTreeElement);
  40.     this.auditsTreeElement.listItemElement.addStyleClass("hidden");
  41.     this.auditsTreeElement.expand();
  42.  
  43.     this.auditsItemTreeElement = new WebInspector.AuditsSidebarTreeElement();
  44.     this.auditsTreeElement.appendChild(this.auditsItemTreeElement);
  45.  
  46.     this.auditResultsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RESULTS"), {}, true);
  47.     this.sidebarTree.appendChild(this.auditResultsTreeElement);
  48.     this.auditResultsTreeElement.expand();
  49.  
  50.     this.element.addStyleClass("audits");
  51.  
  52.     this.clearResultsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear audit results."), "clear-audit-results-status-bar-item");
  53.     this.clearResultsButton.addEventListener("click", this._clearButtonClicked.bind(this), false);
  54.  
  55.     this.viewsContainerElement = document.createElement("div");
  56.     this.viewsContainerElement.id = "audit-views";
  57.     this.element.appendChild(this.viewsContainerElement);
  58.  
  59.     this._launcherView = new WebInspector.AuditLauncherView(this.categoriesById, this.initiateAudit.bind(this));
  60. }
  61.  
  62. WebInspector.AuditsPanel.prototype = {
  63.     toolbarItemClass: "audits",
  64.  
  65.     get toolbarItemLabel()
  66.     {
  67.         return WebInspector.UIString("Audits");
  68.     },
  69.  
  70.     get statusBarItems()
  71.     {
  72.         return [this.clearResultsButton.element];
  73.     },
  74.  
  75.     get mainResourceLoadTime()
  76.     {
  77.         return this._mainResourceLoadTime;
  78.     },
  79.  
  80.     set mainResourceLoadTime(x)
  81.     {
  82.         this._mainResourceLoadTime = x;
  83.         this._didMainResourceLoad();
  84.     },
  85.  
  86.     get mainResourceDOMContentTime()
  87.     {
  88.         return this._mainResourceDOMContentTime;
  89.     },
  90.  
  91.     set mainResourceDOMContentTime(x)
  92.     {
  93.         this._mainResourceDOMContentTime = x;
  94.     },
  95.  
  96.     get categoriesById()
  97.     {
  98.         return this._auditCategoriesById;
  99.     },
  100.  
  101.     resourceStarted: function(resource)
  102.     {
  103.         this._launcherView.resourceStarted(resource);
  104.     },
  105.  
  106.     resourceFinished: function(resource)
  107.     {
  108.         this._launcherView.resourceFinished(resource);
  109.     },
  110.  
  111.     _constructCategories: function()
  112.     {
  113.         this._auditCategoriesById = {};
  114.         for (var categoryCtorID in WebInspector.AuditCategories) {
  115.             var auditCategory = new WebInspector.AuditCategories[categoryCtorID]();
  116.             auditCategory._id = categoryCtorID;
  117.             this.categoriesById[categoryCtorID] = auditCategory;
  118.         }
  119.     },
  120.  
  121.     _executeAudit: function(categories, resultCallback)
  122.     {
  123.         var resources = [];
  124.         for (var id in WebInspector.resources)
  125.             resources.push(WebInspector.resources[id]);
  126.  
  127.         var rulesRemaining = 0;
  128.         for (var i = 0; i < categories.length; ++i)
  129.             rulesRemaining += categories[i].ruleCount;
  130.  
  131.         var results = [];
  132.         var mainResourceURL = WebInspector.mainResource.url;
  133.  
  134.         function ruleResultReadyCallback(categoryResult, ruleResult)
  135.         {
  136.             if (ruleResult && ruleResult.children)
  137.                 categoryResult.addRuleResult(ruleResult);
  138.  
  139.             --rulesRemaining;
  140.  
  141.             if (!rulesRemaining && resultCallback)
  142.                 resultCallback(mainResourceURL, results);
  143.         }
  144.  
  145.         if (!rulesRemaining) {
  146.             resultCallback(mainResourceURL, results);
  147.             return;
  148.         }
  149.  
  150.         for (var i = 0; i < categories.length; ++i) {
  151.             var category = categories[i];
  152.             var result = new WebInspector.AuditCategoryResult(category);
  153.             results.push(result);
  154.             category.runRules(resources, ruleResultReadyCallback.bind(null, result));
  155.         }
  156.     },
  157.  
  158.     _auditFinishedCallback: function(launcherCallback, mainResourceURL, results)
  159.     {
  160.         var children = this.auditResultsTreeElement.children;
  161.         var ordinal = 1;
  162.         for (var i = 0; i < children.length; ++i) {
  163.             if (children[i].mainResourceURL === mainResourceURL)
  164.                 ordinal++;
  165.         }
  166.  
  167.         var resultTreeElement = new WebInspector.AuditResultSidebarTreeElement(results, mainResourceURL, ordinal);
  168.         this.auditResultsTreeElement.appendChild(resultTreeElement);
  169.         resultTreeElement.reveal();
  170.         resultTreeElement.select();
  171.         if (launcherCallback)
  172.             launcherCallback();
  173.     },
  174.  
  175.     initiateAudit: function(categoryIds, runImmediately, launcherCallback)
  176.     {
  177.         if (!categoryIds || !categoryIds.length)
  178.             return;
  179.  
  180.         var categories = [];
  181.         for (var i = 0; i < categoryIds.length; ++i)
  182.             categories.push(this.categoriesById[categoryIds[i]]);
  183.  
  184.         function initiateAuditCallback(categories, launcherCallback)
  185.         {
  186.             this._executeAudit(categories, this._auditFinishedCallback.bind(this, launcherCallback));
  187.         }
  188.  
  189.         if (runImmediately)
  190.             initiateAuditCallback.call(this, categories, launcherCallback);
  191.         else
  192.             this._reloadResources(initiateAuditCallback.bind(this, categories, launcherCallback));
  193.     },
  194.  
  195.     _reloadResources: function(callback)
  196.     {
  197.         this._resourceTrackingCallback = callback;
  198.  
  199.         if (!WebInspector.panels.resources.resourceTrackingEnabled) {
  200.             InspectorBackend.enableResourceTracking(false);
  201.             this._updateLauncherViewControls(true);
  202.         } else
  203.             InspectorBackend.reloadPage();
  204.     },
  205.  
  206.     _didMainResourceLoad: function()
  207.     {
  208.         if (this._resourceTrackingCallback) {
  209.             var callback = this._resourceTrackingCallback;
  210.             delete this._resourceTrackingCallback;
  211.             callback();
  212.         }
  213.     },
  214.  
  215.     showResults: function(categoryResults)
  216.     {
  217.         if (!categoryResults._resultView)
  218.             categoryResults._resultView = new WebInspector.AuditResultView(categoryResults);
  219.  
  220.         this.visibleView = categoryResults._resultView;
  221.     },
  222.  
  223.     showLauncherView: function()
  224.     {
  225.         this.visibleView = this._launcherView;
  226.     },
  227.     
  228.     get visibleView()
  229.     {
  230.         return this._visibleView;
  231.     },
  232.  
  233.     set visibleView(x)
  234.     {
  235.         if (this._visibleView === x)
  236.             return;
  237.  
  238.         if (this._visibleView)
  239.             this._visibleView.hide();
  240.  
  241.         this._visibleView = x;
  242.  
  243.         if (x)
  244.             x.show(this.viewsContainerElement);
  245.     },
  246.  
  247.     show: function()
  248.     {
  249.         WebInspector.Panel.prototype.show.call(this);
  250.         this._updateLauncherViewControls(WebInspector.panels.resources.resourceTrackingEnabled);
  251.     },
  252.  
  253.     reset: function()
  254.     {
  255.         this._launcherView.reset();
  256.     },
  257.  
  258.     attach: function()
  259.     {
  260.         WebInspector.Panel.prototype.attach.call(this);
  261.  
  262.         this.auditsItemTreeElement.select();
  263.     },
  264.  
  265.     updateMainViewWidth: function(width)
  266.     {
  267.         this.viewsContainerElement.style.left = width + "px";
  268.     },
  269.  
  270.     _updateLauncherViewControls: function(isTracking)
  271.     {
  272.         if (this._launcherView)
  273.             this._launcherView.updateResourceTrackingState(isTracking);
  274.     },
  275.  
  276.     _clearButtonClicked: function()
  277.     {
  278.         this.auditsItemTreeElement.reveal();
  279.         this.auditsItemTreeElement.select();
  280.         this.auditResultsTreeElement.removeChildren();
  281.     }
  282. }
  283.  
  284. WebInspector.AuditsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
  285.  
  286.  
  287.  
  288. WebInspector.AuditCategory = function(displayName)
  289. {
  290.     this._displayName = displayName;
  291.     this._rules = [];
  292. }
  293.  
  294. WebInspector.AuditCategory.prototype = {
  295.     get id()
  296.     {
  297.         // this._id value is injected at construction time.
  298.         return this._id;
  299.     },
  300.  
  301.     get displayName()
  302.     {
  303.         return this._displayName;
  304.     },
  305.  
  306.     get ruleCount()
  307.     {
  308.         this._ensureInitialized();
  309.         return this._rules.length;
  310.     },
  311.  
  312.     addRule: function(rule, severity)
  313.     {
  314.         rule.severity = severity;
  315.         this._rules.push(rule);
  316.     },
  317.  
  318.     runRules: function(resources, callback)
  319.     {
  320.         this._ensureInitialized();
  321.         for (var i = 0; i < this._rules.length; ++i)
  322.             this._rules[i].run(resources, callback);
  323.     },
  324.  
  325.     _ensureInitialized: function()
  326.     {
  327.         if (!this._initialized) {
  328.             if ("initialize" in this)
  329.                 this.initialize();
  330.             this._initialized = true;
  331.         }
  332.     }
  333. }
  334.  
  335.  
  336. WebInspector.AuditRule = function(id, displayName)
  337. {
  338.     this._id = id;
  339.     this._displayName = displayName;
  340. }
  341.  
  342. WebInspector.AuditRule.Severity = {
  343.     Info: "info",
  344.     Warning: "warning",
  345.     Severe: "severe"
  346. }
  347.  
  348. WebInspector.AuditRule.SeverityOrder = {
  349.     "info": 3,
  350.     "warning": 2,
  351.     "severe": 1
  352. }
  353.  
  354. WebInspector.AuditRule.prototype = {
  355.     get id()
  356.     {
  357.         return this._id;
  358.     },
  359.  
  360.     get displayName()
  361.     {
  362.         return this._displayName;
  363.     },
  364.  
  365.     set severity(severity)
  366.     {
  367.         this._severity = severity;
  368.     },
  369.  
  370.     run: function(resources, callback)
  371.     {
  372.         var result = new WebInspector.AuditRuleResult(this.displayName);
  373.         result.severity = this._severity;
  374.         this.doRun(resources, result, callback);
  375.     },
  376.  
  377.     doRun: function(resources, result, callback)
  378.     {
  379.         throw new Error("doRun() not implemented");
  380.     }
  381. }
  382.  
  383. WebInspector.AuditCategoryResult = function(category)
  384. {
  385.     this.title = category.displayName;
  386.     this.ruleResults = [];
  387. }
  388.  
  389. WebInspector.AuditCategoryResult.prototype = {
  390.     addRuleResult: function(ruleResult)
  391.     {
  392.         this.ruleResults.push(ruleResult);
  393.     }
  394. }
  395.  
  396. WebInspector.AuditRuleResult = function(value, expanded, className)
  397. {
  398.     this.value = value;
  399.     this.className = className;
  400.     this.expanded = expanded;
  401.     this.violationCount = 0;
  402. }
  403.  
  404. WebInspector.AuditRuleResult.linkifyDisplayName = function(url)
  405. {
  406.     return WebInspector.linkifyURL(url, WebInspector.displayNameForURL(url));
  407. }
  408.  
  409. WebInspector.AuditRuleResult.resourceDomain = function(domain)
  410. {
  411.     return domain || WebInspector.UIString("[empty domain]");
  412. }
  413.  
  414. WebInspector.AuditRuleResult.prototype = {
  415.     addChild: function(value, expanded, className)
  416.     {
  417.         if (!this.children)
  418.             this.children = [];
  419.         var entry = new WebInspector.AuditRuleResult(value, expanded, className);
  420.         this.children.push(entry);
  421.         return entry;
  422.     },
  423.  
  424.     addURL: function(url)
  425.     {
  426.         return this.addChild(WebInspector.AuditRuleResult.linkifyDisplayName(url));
  427.     },
  428.  
  429.     addURLs: function(urls)
  430.     {
  431.         for (var i = 0; i < urls.length; ++i)
  432.             this.addURL(urls[i]);
  433.     },
  434.  
  435.     addSnippet: function(snippet)
  436.     {
  437.         return this.addChild(snippet, false, "source-code");
  438.     }
  439. }
  440.  
  441. WebInspector.AuditsSidebarTreeElement = function()
  442. {
  443.     this.small = false;
  444.  
  445.     WebInspector.SidebarTreeElement.call(this, "audits-sidebar-tree-item", WebInspector.UIString("Audits"), "", null, false);
  446. }
  447.  
  448. WebInspector.AuditsSidebarTreeElement.prototype = {
  449.     onattach: function()
  450.     {
  451.         WebInspector.SidebarTreeElement.prototype.onattach.call(this);
  452.     },
  453.  
  454.     onselect: function()
  455.     {
  456.         WebInspector.panels.audits.showLauncherView();
  457.     },
  458.  
  459.     get selectable()
  460.     {
  461.         return true;
  462.     },
  463.  
  464.     refresh: function()
  465.     {
  466.         this.refreshTitles();
  467.     }
  468. }
  469.  
  470. WebInspector.AuditsSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
  471.  
  472.  
  473. WebInspector.AuditResultSidebarTreeElement = function(results, mainResourceURL, ordinal)
  474. {
  475.     this.results = results;
  476.     this.mainResourceURL = mainResourceURL;
  477.  
  478.     WebInspector.SidebarTreeElement.call(this, "audit-result-sidebar-tree-item", String.sprintf("%s (%d)", mainResourceURL, ordinal), "", {}, false);
  479. }
  480.  
  481. WebInspector.AuditResultSidebarTreeElement.prototype = {
  482.     onselect: function()
  483.     {
  484.         WebInspector.panels.audits.showResults(this.results);
  485.     },
  486.  
  487.     get selectable()
  488.     {
  489.         return true;
  490.     }
  491. }
  492.  
  493. WebInspector.AuditResultSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
  494.  
  495. // Contributed audit rules should go into this namespace.
  496. WebInspector.AuditRules = {};
  497.  
  498. // Contributed audit categories should go into this namespace.
  499. WebInspector.AuditCategories = {};
  500.