Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / audits / AuditLauncherView.js
1 /*
2  * Copyright (C) 2011 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 /**
32  * @constructor
33  * @param {!WebInspector.AuditController} auditController
34  * @extends {WebInspector.VBox}
35  */
36 WebInspector.AuditLauncherView = function(auditController)
37 {
38     WebInspector.VBox.call(this);
39     this.setMinimumSize(100, 25);
40
41     this._auditController = auditController;
42
43     this._categoryIdPrefix = "audit-category-item-";
44     this._auditRunning = false;
45
46     this.element.classList.add("audit-launcher-view");
47     this.element.classList.add("panel-enabler-view");
48
49     this._contentElement = document.createElement("div");
50     this._contentElement.className = "audit-launcher-view-content";
51     this.element.appendChild(this._contentElement);
52     this._boundCategoryClickListener = this._categoryClicked.bind(this);
53
54     this._resetResourceCount();
55
56     this._sortedCategories = [];
57
58     this._headerElement = document.createElement("h1");
59     this._headerElement.className = "no-audits";
60     this._headerElement.textContent = WebInspector.UIString("No audits to run");
61     this._contentElement.appendChild(this._headerElement);
62
63     WebInspector.targetManager.addModelListener(WebInspector.NetworkManager, WebInspector.NetworkManager.EventTypes.RequestStarted, this._onRequestStarted, this);
64     WebInspector.targetManager.addModelListener(WebInspector.NetworkManager, WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestFinished, this);
65     WebInspector.profilingLock().addEventListener(WebInspector.Lock.Events.StateChanged, this._updateButton, this);
66
67     var defaultSelectedAuditCategory = {};
68     defaultSelectedAuditCategory[WebInspector.AuditLauncherView.AllCategoriesKey] = true;
69     this._selectedCategoriesSetting = WebInspector.settings.createSetting("selectedAuditCategories", defaultSelectedAuditCategory);
70 }
71
72 WebInspector.AuditLauncherView.AllCategoriesKey = "__AllCategories";
73
74 WebInspector.AuditLauncherView.prototype = {
75     _resetResourceCount: function()
76     {
77         this._loadedResources = 0;
78         this._totalResources = 0;
79     },
80
81     _onRequestStarted: function(event)
82     {
83         var request = /** @type {!WebInspector.NetworkRequest} */ (event.data);
84         // Ignore long-living WebSockets for the sake of progress indicator, as we won't be waiting them anyway.
85         if (request.type === WebInspector.resourceTypes.WebSocket)
86             return;
87         ++this._totalResources;
88         this._updateResourceProgress();
89     },
90
91     _onRequestFinished: function(event)
92     {
93         var request = /** @type {!WebInspector.NetworkRequest} */ (event.data);
94         // See resorceStarted for details.
95         if (request.type === WebInspector.resourceTypes.WebSocket)
96             return;
97         ++this._loadedResources;
98         this._updateResourceProgress();
99     },
100
101     /**
102      * @param {!WebInspector.AuditCategory} category
103      */
104     addCategory: function(category)
105     {
106         if (!this._sortedCategories.length)
107             this._createLauncherUI();
108
109         var selectedCategories = this._selectedCategoriesSetting.get();
110         var categoryElement = this._createCategoryElement(category.displayName, category.id);
111         category._checkboxElement = categoryElement.firstChild;
112         if (this._selectAllCheckboxElement.checked || selectedCategories[category.displayName]) {
113             category._checkboxElement.checked = true;
114             ++this._currentCategoriesCount;
115         }
116
117         /**
118          * @param {!WebInspector.AuditCategory} a
119          * @param {!WebInspector.AuditCategory} b
120          * @return {number}
121          */
122         function compareCategories(a, b)
123         {
124             var aTitle = a.displayName || "";
125             var bTitle = b.displayName || "";
126             return aTitle.localeCompare(bTitle);
127         }
128         var insertBefore = insertionIndexForObjectInListSortedByFunction(category, this._sortedCategories, compareCategories);
129         this._categoriesElement.insertBefore(categoryElement, this._categoriesElement.children[insertBefore]);
130         this._sortedCategories.splice(insertBefore, 0, category);
131         this._selectedCategoriesUpdated();
132     },
133
134     /**
135      * @param {boolean} auditRunning
136      */
137     _setAuditRunning: function(auditRunning)
138     {
139         if (this._auditRunning === auditRunning)
140             return;
141         this._auditRunning = auditRunning;
142         this._updateButton();
143         this._toggleUIComponents(this._auditRunning);
144         if (this._auditRunning) {
145             WebInspector.profilingLock().acquire();
146             this._startAudit();
147         } else {
148             this._stopAudit();
149             WebInspector.profilingLock().release();
150         }
151     },
152
153     _startAudit: function()
154     {
155         var catIds = [];
156         for (var category = 0; category < this._sortedCategories.length; ++category) {
157             if (this._sortedCategories[category]._checkboxElement.checked)
158                 catIds.push(this._sortedCategories[category].id);
159         }
160
161         this._resetResourceCount();
162         this._progressIndicator = new WebInspector.ProgressIndicator();
163         this._buttonContainerElement.appendChild(this._progressIndicator.element);
164         this._displayResourceLoadingProgress = true;
165
166         /**
167          * @this {WebInspector.AuditLauncherView}
168          */
169         function onAuditStarted()
170         {
171             this._displayResourceLoadingProgress = false;
172         }
173         this._auditController.initiateAudit(catIds, this._progressIndicator, this._auditPresentStateElement.checked, onAuditStarted.bind(this), this._setAuditRunning.bind(this, false));
174     },
175
176     _stopAudit: function()
177     {
178         this._displayResourceLoadingProgress = false;
179         this._progressIndicator.cancel();
180         this._progressIndicator.done();
181         delete this._progressIndicator;
182     },
183
184     /**
185      * @param {boolean} disable
186      */
187     _toggleUIComponents: function(disable)
188     {
189         this._selectAllCheckboxElement.disabled = disable;
190         this._categoriesElement.disabled = disable;
191         this._auditPresentStateElement.disabled = disable;
192         this._auditReloadedStateElement.disabled = disable;
193     },
194
195     _launchButtonClicked: function(event)
196     {
197         this._setAuditRunning(!this._auditRunning);
198     },
199
200     _clearButtonClicked: function()
201     {
202         this._auditController.clearResults();
203     },
204
205     /**
206      * @param {boolean} checkCategories
207      * @param {boolean=} userGesture
208      */
209     _selectAllClicked: function(checkCategories, userGesture)
210     {
211         var childNodes = this._categoriesElement.childNodes;
212         for (var i = 0, length = childNodes.length; i < length; ++i)
213             childNodes[i].firstChild.checked = checkCategories;
214         this._currentCategoriesCount = checkCategories ? this._sortedCategories.length : 0;
215         this._selectedCategoriesUpdated(userGesture);
216     },
217
218     _categoryClicked: function(event)
219     {
220         this._currentCategoriesCount += event.target.checked ? 1 : -1;
221         this._selectAllCheckboxElement.checked = this._currentCategoriesCount === this._sortedCategories.length;
222         this._selectedCategoriesUpdated(true);
223     },
224
225     /**
226      * @param {string} title
227      * @param {string} id
228      */
229     _createCategoryElement: function(title, id)
230     {
231         var labelElement = document.createElement("label");
232         labelElement.id = this._categoryIdPrefix + id;
233
234         var element = document.createElement("input");
235         element.type = "checkbox";
236         if (id !== "")
237             element.addEventListener("click", this._boundCategoryClickListener, false);
238         labelElement.appendChild(element);
239         labelElement.createTextChild(title);
240         labelElement.__displayName = title;
241
242         return labelElement;
243     },
244
245     _createLauncherUI: function()
246     {
247         this._headerElement = document.createElement("h1");
248         this._headerElement.textContent = WebInspector.UIString("Select audits to run");
249
250         for (var child = 0; child < this._contentElement.children.length; ++child)
251             this._contentElement.removeChild(this._contentElement.children[child]);
252
253         this._contentElement.appendChild(this._headerElement);
254
255         /**
256          * @param {!Event} event
257          * @this {WebInspector.AuditLauncherView}
258          */
259         function handleSelectAllClick(event)
260         {
261             this._selectAllClicked(event.target.checked, true);
262         }
263         var categoryElement = this._createCategoryElement(WebInspector.UIString("Select All"), "");
264         categoryElement.id = "audit-launcher-selectall";
265         this._selectAllCheckboxElement = categoryElement.firstChild;
266         this._selectAllCheckboxElement.checked = this._selectedCategoriesSetting.get()[WebInspector.AuditLauncherView.AllCategoriesKey];
267         this._selectAllCheckboxElement.addEventListener("click", handleSelectAllClick.bind(this), false);
268         this._contentElement.appendChild(categoryElement);
269
270         this._categoriesElement = this._contentElement.createChild("fieldset", "audit-categories-container");
271         this._currentCategoriesCount = 0;
272
273         this._contentElement.createChild("div", "flexible-space");
274
275         this._buttonContainerElement = this._contentElement.createChild("div", "button-container");
276
277         var labelElement = this._buttonContainerElement.createChild("label");
278         this._auditPresentStateElement = labelElement.createChild("input");
279         this._auditPresentStateElement.name = "audit-mode";
280         this._auditPresentStateElement.type = "radio";
281         this._auditPresentStateElement.checked = true;
282         this._auditPresentStateLabelElement = document.createTextNode(WebInspector.UIString("Audit Present State"));
283         labelElement.appendChild(this._auditPresentStateLabelElement);
284
285         labelElement = this._buttonContainerElement.createChild("label");
286         this._auditReloadedStateElement = labelElement.createChild("input");
287         this._auditReloadedStateElement.name = "audit-mode";
288         this._auditReloadedStateElement.type = "radio";
289         labelElement.createTextChild("Reload Page and Audit on Load");
290
291         this._launchButton = this._buttonContainerElement.createChild("button", "text-button");
292         this._launchButton.textContent = WebInspector.UIString("Run");
293         this._launchButton.addEventListener("click", this._launchButtonClicked.bind(this), false);
294
295         this._clearButton = this._buttonContainerElement.createChild("button", "text-button");
296         this._clearButton.textContent = WebInspector.UIString("Clear");
297         this._clearButton.addEventListener("click", this._clearButtonClicked.bind(this), false);
298
299         this._selectAllClicked(this._selectAllCheckboxElement.checked);
300     },
301
302     _updateResourceProgress: function()
303     {
304         if (this._displayResourceLoadingProgress)
305             this._progressIndicator.setTitle(WebInspector.UIString("Loading (%d of %d)", this._loadedResources, this._totalResources));
306     },
307
308     /**
309      * @param {boolean=} userGesture
310      */
311     _selectedCategoriesUpdated: function(userGesture)
312     {
313         // Save present categories only upon user gesture to clean up junk from past versions and removed extensions.
314         // Do not remove old categories if not handling a user gesture, as there's chance categories will be added
315         // later during start-up.
316         var selectedCategories = userGesture ? {} : this._selectedCategoriesSetting.get();
317         var childNodes = this._categoriesElement.childNodes;
318         for (var i = 0, length = childNodes.length; i < length; ++i)
319             selectedCategories[childNodes[i].__displayName] = childNodes[i].firstChild.checked;
320         selectedCategories[WebInspector.AuditLauncherView.AllCategoriesKey] = this._selectAllCheckboxElement.checked;
321         this._selectedCategoriesSetting.set(selectedCategories);
322         this._updateButton();
323     },
324
325     _updateButton: function()
326     {
327         var enable = this._auditRunning || (this._currentCategoriesCount && !WebInspector.profilingLock().isAcquired());
328         this._launchButton.textContent = this._auditRunning ? WebInspector.UIString("Stop") : WebInspector.UIString("Run");
329         this._launchButton.disabled = !enable;
330         this._launchButton.title = enable ? "" : WebInspector.anotherProfilerActiveLabel();
331     },
332
333     __proto__: WebInspector.VBox.prototype
334 }