browser/devtools/profiler/cleopatra/js/devtools.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:da45550aa69b
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 "use strict";
6
7 var gInstanceUID;
8 var gParsedQS;
9 var gHideSourceLinks;
10
11 function getParam(key) {
12 if (gParsedQS)
13 return gParsedQS[key];
14
15 var query = window.location.search.substring(1);
16 gParsedQS = {};
17
18 query.split("&").forEach(function (pair) {
19 pair = pair.split("=");
20 gParsedQS[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
21 });
22
23 return gParsedQS[key];
24 }
25
26 /**
27 * Sends a message to the parent window with a status
28 * update.
29 *
30 * @param string status
31 * Status to send to the parent page:
32 * - loaded, when page is loaded.
33 * - displaysource, when user wants to display source
34 * @param object data (optional)
35 * Additional data to send to the parent page.
36 */
37 function notifyParent(status, data={}) {
38 if (!gInstanceUID) {
39 gInstanceUID = getParam("uid");
40 }
41
42 window.parent.postMessage({
43 uid: gInstanceUID,
44 status: status,
45 data: data
46 }, "*");
47 }
48
49 /**
50 * A listener for incoming messages from the parent
51 * page. All incoming messages must be stringified
52 * JSON objects to be compatible with Cleopatra's
53 * format:
54 *
55 * {
56 * task: string,
57 * ...
58 * }
59 *
60 * This listener recognizes two tasks: onStarted and
61 * onStopped.
62 *
63 * @param object event
64 * PostMessage event object.
65 */
66 function onParentMessage(event) {
67 var start = document.getElementById("startWrapper");
68 var stop = document.getElementById("stopWrapper");
69 var profilerMessage = document.getElementById("profilerMessage");
70 var msg = JSON.parse(event.data);
71
72 if (msg.task !== "receiveProfileData" && !msg.isCurrent) {
73 return;
74 }
75
76 switch (msg.task) {
77 case "onStarted":
78 start.style.display = "none";
79 start.querySelector("button").removeAttribute("disabled");
80 stop.style.display = "inline";
81 break;
82 case "onStopped":
83 stop.style.display = "none";
84 stop.querySelector("button").removeAttribute("disabled");
85 start.style.display = "inline";
86 break;
87 case "receiveProfileData":
88 loadProfile(JSON.stringify(msg.rawProfile));
89 }
90 }
91
92 window.addEventListener("message", onParentMessage);
93
94 /**
95 * Main entry point. This function initializes Cleopatra
96 * in the light mode and creates all the UI we need.
97 */
98 function initUI() {
99 gHideSourceLinks = getParam("ext") === "true";
100 gFileList = { profileParsingFinished: function () {} };
101 gInfoBar = { display: function () {} };
102
103 var container = document.createElement("div");
104 container.id = "ui";
105
106 gMainArea = document.createElement("div");
107 gMainArea.id = "mainarea";
108
109 container.appendChild(gMainArea);
110 document.body.appendChild(container);
111 }
112
113 /**
114 * Modified copy of Cleopatra's enterFinishedProfileUI.
115 * By overriding the function we don't need to modify ui.js which helps
116 * with updating from upstream.
117 */
118 function enterFinishedProfileUI() {
119 var cover = document.createElement("div");
120 cover.className = "finishedProfilePaneBackgroundCover";
121
122 var pane = document.createElement("table");
123 var rowIndex = 0;
124 var currRow;
125
126 pane.style.width = "100%";
127 pane.style.height = "100%";
128 pane.border = "0";
129 pane.cellPadding = "0";
130 pane.cellSpacing = "0";
131 pane.borderCollapse = "collapse";
132 pane.className = "finishedProfilePane";
133
134 gBreadcrumbTrail = new BreadcrumbTrail();
135 currRow = pane.insertRow(rowIndex++);
136 currRow.insertCell(0).appendChild(gBreadcrumbTrail.getContainer());
137
138 gHistogramView = new HistogramView();
139 currRow = pane.insertRow(rowIndex++);
140 currRow.insertCell(0).appendChild(gHistogramView.getContainer());
141
142 if (gMeta && gMeta.videoCapture) {
143 gVideoPane = new VideoPane(gMeta.videoCapture);
144 gVideoPane.onTimeChange(videoPaneTimeChange);
145 currRow = pane.insertRow(rowIndex++);
146 currRow.insertCell(0).appendChild(gVideoPane.getContainer());
147 }
148
149 var tree = document.createElement("div");
150 tree.className = "treeContainer";
151 tree.style.width = "100%";
152 tree.style.height = "100%";
153
154 gTreeManager = new ProfileTreeManager();
155 gTreeManager.treeView.setColumns([
156 { name: "sampleCount", title: gStrings["Running Time"] },
157 { name: "selfSampleCount", title: gStrings["Self"] },
158 { name: "resource", title: "" }
159 ]);
160
161 currRow = pane.insertRow(rowIndex++);
162 currRow.style.height = "100%";
163
164 var cell = currRow.insertCell(0);
165 cell.appendChild(tree);
166 tree.appendChild(gTreeManager.getContainer());
167
168 gPluginView = new PluginView();
169 tree.appendChild(gPluginView.getContainer());
170
171 gMainArea.appendChild(cover);
172 gMainArea.appendChild(pane);
173
174 var currentBreadcrumb = gSampleFilters;
175 gBreadcrumbTrail.add({
176 title: gStrings["Complete Profile"],
177 enterCallback: function () {
178 gSampleFilters = [];
179 filtersChanged();
180 }
181 });
182
183 if (currentBreadcrumb == null || currentBreadcrumb.length == 0) {
184 gTreeManager.restoreSerializedSelectionSnapshot(gRestoreSelection);
185 viewOptionsChanged();
186 }
187
188 for (var i = 0; i < currentBreadcrumb.length; i++) {
189 var filter = currentBreadcrumb[i];
190 var forceSelection = null;
191 if (gRestoreSelection != null && i == currentBreadcrumb.length - 1) {
192 forceSelection = gRestoreSelection;
193 }
194 switch (filter.type) {
195 case "FocusedFrameSampleFilter":
196 focusOnSymbol(filter.name, filter.symbolName);
197 gBreadcrumbTrail.enterLastItem(forceSelection);
198 case "FocusedCallstackPrefixSampleFilter":
199 focusOnCallstack(filter.focusedCallstack, filter.name, false);
200 gBreadcrumbTrail.enterLastItem(forceSelection);
201 case "FocusedCallstackPostfixSampleFilter":
202 focusOnCallstack(filter.focusedCallstack, filter.name, true);
203 gBreadcrumbTrail.enterLastItem(forceSelection);
204 case "RangeSampleFilter":
205 gHistogramView.selectRange(filter.start, filter.end);
206 gBreadcrumbTrail.enterLastItem(forceSelection);
207 }
208 }
209
210 // Show platform data?
211 if (getParam("spd") !== "true")
212 toggleJavascriptOnly();
213 }
214
215 function enterProgressUI() {
216 var pane = document.createElement("div");
217 var label = document.createElement("a");
218 var bar = document.createElement("progress");
219 var string = gStrings.getStr("profiler.loading");
220
221 pane.className = "profileProgressPane";
222 pane.appendChild(label);
223 pane.appendChild(bar);
224
225 var reporter = new ProgressReporter();
226 reporter.addListener(function (rep) {
227 var progress = rep.getProgress();
228
229 if (label.textContent !== string) {
230 label.textContent = string;
231 }
232
233 if (isNaN(progress)) {
234 bar.removeAttribute("value");
235 } else {
236 bar.value = progress;
237 }
238 });
239
240 gMainArea.appendChild(pane);
241 Parser.updateLogSetting();
242
243 return reporter;
244 }

mercurial