blob: 35ef76433bd986824302982251e6e5a0e31ddb60 [file] [log] [blame]
/*
* Copyright (C) 2011 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.
*/
/**
* @unrestricted
*/
Audits.AuditLauncherView = class extends UI.VBox {
/**
* @param {!Audits.AuditController} auditController
*/
constructor(auditController) {
super();
this.setMinimumSize(100, 25);
this._auditController = auditController;
this._categoryIdPrefix = 'audit-category-item-';
this._auditRunning = false;
this.element.classList.add('audit-launcher-view');
this.element.classList.add('panel-enabler-view');
this._contentElement = createElement('div');
this._contentElement.className = 'audit-launcher-view-content';
this.element.appendChild(this._contentElement);
this._boundCategoryClickListener = this._categoryClicked.bind(this);
this._resetResourceCount();
this._sortedCategories = [];
this._headerElement = createElement('h1');
this._headerElement.className = 'no-audits';
this._headerElement.textContent = Common.UIString('No audits to run');
this._contentElement.appendChild(this._headerElement);
SDK.targetManager.addModelListener(
SDK.NetworkManager, SDK.NetworkManager.Events.RequestStarted, this._onRequestStarted, this);
SDK.targetManager.addModelListener(
SDK.NetworkManager, SDK.NetworkManager.Events.RequestFinished, this._onRequestFinished, this);
var defaultSelectedAuditCategory = {};
defaultSelectedAuditCategory[Audits.AuditLauncherView.AllCategoriesKey] = true;
this._selectedCategoriesSetting =
Common.settings.createSetting('selectedAuditCategories', defaultSelectedAuditCategory);
}
_resetResourceCount() {
this._loadedResources = 0;
this._totalResources = 0;
}
_onRequestStarted(event) {
var request = /** @type {!SDK.NetworkRequest} */ (event.data);
// Ignore long-living WebSockets for the sake of progress indicator, as we won't be waiting them anyway.
if (request.resourceType() === Common.resourceTypes.WebSocket)
return;
++this._totalResources;
this._updateResourceProgress();
}
_onRequestFinished(event) {
var request = /** @type {!SDK.NetworkRequest} */ (event.data);
// See resorceStarted for details.
if (request.resourceType() === Common.resourceTypes.WebSocket)
return;
++this._loadedResources;
this._updateResourceProgress();
}
/**
* @param {!Audits.AuditCategory} category
*/
addCategory(category) {
if (!this._sortedCategories.length)
this._createLauncherUI();
var selectedCategories = this._selectedCategoriesSetting.get();
var categoryElement = this._createCategoryElement(category.displayName, category.id);
category._checkboxElement = categoryElement.checkboxElement;
if (this._selectAllCheckboxElement.checked || selectedCategories[category.displayName]) {
category._checkboxElement.checked = true;
++this._currentCategoriesCount;
}
/**
* @param {!Audits.AuditCategory} a
* @param {!Audits.AuditCategory} b
* @return {number}
*/
function compareCategories(a, b) {
var aTitle = a.displayName || '';
var bTitle = b.displayName || '';
return aTitle.localeCompare(bTitle);
}
var insertBefore = this._sortedCategories.lowerBound(category, compareCategories);
this._categoriesElement.insertBefore(categoryElement, this._categoriesElement.children[insertBefore]);
this._sortedCategories.splice(insertBefore, 0, category);
this._selectedCategoriesUpdated();
}
_startAudit() {
this._auditRunning = true;
this._updateButton();
this._toggleUIComponents(this._auditRunning);
var catIds = [];
for (var category = 0; category < this._sortedCategories.length; ++category) {
if (this._sortedCategories[category]._checkboxElement.checked)
catIds.push(this._sortedCategories[category].id);
}
this._resetResourceCount();
this._progressIndicator = new UI.ProgressIndicator();
this._buttonContainerElement.appendChild(this._progressIndicator.element);
this._displayResourceLoadingProgress = true;
/**
* @this {Audits.AuditLauncherView}
*/
function onAuditStarted() {
this._displayResourceLoadingProgress = false;
}
this._auditController.initiateAudit(
catIds, new Common.ProgressProxy(this._progressIndicator, this._auditsDone.bind(this)),
this._auditPresentStateElement.checked, onAuditStarted.bind(this));
}
_auditsDone() {
this._displayResourceLoadingProgress = false;
delete this._progressIndicator;
this._launchButton.disabled = false;
this._auditRunning = false;
this._updateButton();
this._toggleUIComponents(this._auditRunning);
}
/**
* @param {boolean} disable
*/
_toggleUIComponents(disable) {
this._selectAllCheckboxElement.disabled = disable;
for (var child = this._categoriesElement.firstChild; child; child = child.nextSibling)
child.checkboxElement.disabled = disable;
this._auditPresentStateElement.disabled = disable;
this._auditReloadedStateElement.disabled = disable;
}
_launchButtonClicked(event) {
if (this._auditRunning) {
this._launchButton.disabled = true;
this._progressIndicator.cancel();
return;
}
this._startAudit();
}
_clearButtonClicked() {
this._auditController.clearResults();
}
/**
* @param {boolean} checkCategories
* @param {boolean=} userGesture
*/
_selectAllClicked(checkCategories, userGesture) {
var childNodes = this._categoriesElement.childNodes;
for (var i = 0, length = childNodes.length; i < length; ++i)
childNodes[i].checkboxElement.checked = checkCategories;
this._currentCategoriesCount = checkCategories ? this._sortedCategories.length : 0;
this._selectedCategoriesUpdated(userGesture);
}
_categoryClicked(event) {
this._currentCategoriesCount += event.target.checked ? 1 : -1;
this._selectAllCheckboxElement.checked = this._currentCategoriesCount === this._sortedCategories.length;
this._selectedCategoriesUpdated(true);
}
/**
* @param {string} title
* @param {string=} id
*/
_createCategoryElement(title, id) {
var labelElement = createCheckboxLabel(title);
if (id) {
labelElement.id = this._categoryIdPrefix + id;
labelElement.checkboxElement.addEventListener('click', this._boundCategoryClickListener, false);
}
labelElement.__displayName = title;
return labelElement;
}
_createLauncherUI() {
this._headerElement = createElement('h1');
this._headerElement.textContent = Common.UIString('Select audits to run');
this._contentElement.removeChildren();
this._contentElement.appendChild(this._headerElement);
/**
* @param {!Event} event
* @this {Audits.AuditLauncherView}
*/
function handleSelectAllClick(event) {
this._selectAllClicked(event.target.checked, true);
}
var categoryElement = this._createCategoryElement(Common.UIString('Select All'), '');
categoryElement.id = 'audit-launcher-selectall';
this._selectAllCheckboxElement = categoryElement.checkboxElement;
this._selectAllCheckboxElement.checked =
this._selectedCategoriesSetting.get()[Audits.AuditLauncherView.AllCategoriesKey];
this._selectAllCheckboxElement.addEventListener('click', handleSelectAllClick.bind(this), false);
this._contentElement.appendChild(categoryElement);
this._categoriesElement = this._contentElement.createChild('fieldset', 'audit-categories-container');
this._currentCategoriesCount = 0;
this._contentElement.createChild('div', 'flexible-space');
this._buttonContainerElement = this._contentElement.createChild('div', 'button-container');
var radio = createRadioLabel('audit-mode', Common.UIString('Audit Present State'), true);
this._buttonContainerElement.appendChild(radio);
this._auditPresentStateElement = radio.radioElement;
radio = createRadioLabel('audit-mode', Common.UIString('Reload Page and Audit on Load'));
this._buttonContainerElement.appendChild(radio);
this._auditReloadedStateElement = radio.radioElement;
this._launchButton = createTextButton(Common.UIString('Run'), this._launchButtonClicked.bind(this));
this._buttonContainerElement.appendChild(this._launchButton);
this._clearButton = createTextButton(Common.UIString('Clear'), this._clearButtonClicked.bind(this));
this._buttonContainerElement.appendChild(this._clearButton);
this._selectAllClicked(this._selectAllCheckboxElement.checked);
}
_updateResourceProgress() {
if (this._displayResourceLoadingProgress) {
this._progressIndicator.setTitle(
Common.UIString('Loading (%d of %d)', this._loadedResources, this._totalResources));
}
}
/**
* @param {boolean=} userGesture
*/
_selectedCategoriesUpdated(userGesture) {
// Save present categories only upon user gesture to clean up junk from past versions and removed extensions.
// Do not remove old categories if not handling a user gesture, as there's chance categories will be added
// later during start-up.
var selectedCategories = userGesture ? {} : this._selectedCategoriesSetting.get();
var childNodes = this._categoriesElement.childNodes;
for (var i = 0, length = childNodes.length; i < length; ++i)
selectedCategories[childNodes[i].__displayName] = childNodes[i].checkboxElement.checked;
selectedCategories[Audits.AuditLauncherView.AllCategoriesKey] = this._selectAllCheckboxElement.checked;
this._selectedCategoriesSetting.set(selectedCategories);
this._updateButton();
}
_updateButton() {
this._launchButton.textContent = this._auditRunning ? Common.UIString('Stop') : Common.UIString('Run');
this._launchButton.disabled = !this._currentCategoriesCount;
}
};
Audits.AuditLauncherView.AllCategoriesKey = '__AllCategories';