1/* 2 * Copyright (C) 2011 Apple 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26var LeaksViewer = { 27 loaded: function() { 28 this._loader = new LeaksLoader(this._didCountLeaksFiles.bind(this), this._didLoadLeaksFile.bind(this)); 29 this._parser = new LeaksParser(this._didParseLeaksFile.bind(this)); 30 31 this._loadingIndicator = document.getElementById("loading-indicator"); 32 this._loadingIndicatorLabel = document.getElementById("loading-indicator-label"); 33 34 this._profileView = new WebInspector.CPUProfileView({}); 35 document.getElementById("main-panels").appendChild(this._profileView.element); 36 this._profileView.show(); 37 38 // From WebInspector.Panel.prototype.show 39 var statusBarItems = this._profileView.statusBarItems; 40 if (statusBarItems) { 41 this._statusBarItemContainer = document.createElement("div"); 42 for (var i = 0; i < statusBarItems.length; ++i) 43 this._statusBarItemContainer.appendChild(statusBarItems[i]); 44 document.getElementById("main-status-bar").appendChild(this._statusBarItemContainer); 45 } 46 47 var url; 48 var match = /url=([^&]+)/.exec(location.search); 49 if (match) 50 url = decodeURIComponent(match[1]); 51 52 if (url) 53 this._loadLeaksFromURL(url) 54 else 55 this._displayURLPrompt(); 56 }, 57 58 get filesLeftToParse() { 59 if (!('_filesLeftToParse' in this)) 60 this._filesLeftToParse = 0; 61 return this._filesLeftToParse; 62 }, 63 64 set filesLeftToParse(x) { 65 if (this._filesLeftToParse === x) 66 return; 67 this._filesLeftToParse = x; 68 this._loadingStatusChanged(); 69 }, 70 71 get loading() { 72 return this._isLoading; 73 }, 74 75 set loading(x) { 76 if (this._isLoading === x) 77 return; 78 this._isLoading = x; 79 this._loadingStatusChanged(); 80 }, 81 82 get url() { 83 return this._url; 84 }, 85 86 set url(x) { 87 if (this._url === x) 88 return; 89 90 this._url = x; 91 this._updateTitle(); 92 }, 93 94 urlPromptButtonClicked: function(e) { 95 this._urlChosenFromPrompt(document.getElementById("url").value); 96 }, 97 98 _didCountLeaksFiles: function(fileCount) { 99 this._fileCount = fileCount; 100 this.filesLeftToParse = fileCount; 101 }, 102 103 _didLoadLeaksFile: function(leaksText) { 104 this._parser.addLeaksFile(leaksText); 105 }, 106 107 _didLoadRecentBuilds: function(builds) { 108 this._recentBuilds = builds; 109 this._updateURLPrompt(); 110 }, 111 112 _didParseLeaksFile: function(profile) { 113 if (--this.filesLeftToParse) 114 return; 115 ProfilerAgent.profileReady(profile); 116 this.loading = false; 117 }, 118 119 _displayURLPrompt: function() { 120 document.getElementById("url-prompt-container").removeStyleClass("hidden"); 121 document.getElementById("url").focus(); 122 var loader = new RecentBuildsLoader(this._didLoadRecentBuilds.bind(this)); 123 loader.start("SnowLeopard Intel Leaks", this._numberOfRecentBuildsToLoad); 124 }, 125 126 _loadLeaksFromURL: function(url) { 127 this.url = url; 128 this.loading = true; 129 130 this._loader.start(this.url); 131 }, 132 133 _loadingIndicatorText: function() { 134 var text = "Loading"; 135 if (this.filesLeftToParse) 136 text += " " + (this._fileCount - this.filesLeftToParse + 1) + "/" + this._fileCount + " files"; 137 text += "\u2026"; 138 return text; 139 }, 140 141 _loadingStatusChanged: function() { 142 this._setLoadingIndicatorHidden(!this.loading); 143 this._updateLoadingIndicatorLabel(); 144 this._updateTitle(); 145 }, 146 147 _numberOfRecentBuildsToLoad: 10, 148 149 _setLoadingIndicatorHidden: function(hidden) { 150 if (hidden) 151 this._loadingIndicator.addStyleClass("hidden"); 152 else 153 this._loadingIndicator.removeStyleClass("hidden"); 154 }, 155 156 _updateLoadingIndicatorLabel: function() { 157 this._loadingIndicatorLabel.innerText = this._loadingIndicatorText(); 158 }, 159 160 _updateTitle: function() { 161 var title = "Leaks Viewer \u2014 "; 162 if (this.loading) 163 title += "(" + this._loadingIndicatorText() + ") "; 164 title += this.url; 165 document.title = title; 166 }, 167 168 _updateURLPrompt: function() { 169 var recentBuildsContainer = document.getElementById("recent-builds-container"); 170 recentBuildsContainer.removeChildren(); 171 if (this._recentBuilds && this._recentBuilds.length) { 172 var list = document.createElement("ol"); 173 list.id = "recent-builds-list"; 174 175 var self = this; 176 this._recentBuilds.forEach(function(build) { 177 var link = document.createElement("a"); 178 link.href = document.location.href + "?url=" + encodeURIComponent(build.url); 179 link.addEventListener("click", function(e) { 180 self._urlChosenFromPrompt(build.url); 181 e.preventDefault(); 182 }); 183 link.appendChild(document.createTextNode("r" + build.revision + ": " + build.leakCount + " leaks")); 184 var item = document.createElement("li"); 185 item.appendChild(link); 186 187 list.appendChild(item); 188 }); 189 190 recentBuildsContainer.appendChild(list); 191 } else 192 recentBuildsContainer.appendChild(document.createTextNode("No recent leaky builds found.")); 193 }, 194 195 _urlChosenFromPrompt: function(url) { 196 this._loadLeaksFromURL(url); 197 document.getElementById("url-prompt-container").addStyleClass("hidden"); 198 }, 199 200}; 201 202addEventListener("load", LeaksViewer.loaded.bind(LeaksViewer)); 203