diff -r 000000000000 -r 6474c204b198 browser/devtools/profiler/cleopatra/js/devtools.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/browser/devtools/profiler/cleopatra/js/devtools.js Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,244 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +var gInstanceUID; +var gParsedQS; +var gHideSourceLinks; + +function getParam(key) { + if (gParsedQS) + return gParsedQS[key]; + + var query = window.location.search.substring(1); + gParsedQS = {}; + + query.split("&").forEach(function (pair) { + pair = pair.split("="); + gParsedQS[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); + }); + + return gParsedQS[key]; +} + +/** + * Sends a message to the parent window with a status + * update. + * + * @param string status + * Status to send to the parent page: + * - loaded, when page is loaded. + * - displaysource, when user wants to display source + * @param object data (optional) + * Additional data to send to the parent page. + */ +function notifyParent(status, data={}) { + if (!gInstanceUID) { + gInstanceUID = getParam("uid"); + } + + window.parent.postMessage({ + uid: gInstanceUID, + status: status, + data: data + }, "*"); +} + +/** + * A listener for incoming messages from the parent + * page. All incoming messages must be stringified + * JSON objects to be compatible with Cleopatra's + * format: + * + * { + * task: string, + * ... + * } + * + * This listener recognizes two tasks: onStarted and + * onStopped. + * + * @param object event + * PostMessage event object. + */ +function onParentMessage(event) { + var start = document.getElementById("startWrapper"); + var stop = document.getElementById("stopWrapper"); + var profilerMessage = document.getElementById("profilerMessage"); + var msg = JSON.parse(event.data); + + if (msg.task !== "receiveProfileData" && !msg.isCurrent) { + return; + } + + switch (msg.task) { + case "onStarted": + start.style.display = "none"; + start.querySelector("button").removeAttribute("disabled"); + stop.style.display = "inline"; + break; + case "onStopped": + stop.style.display = "none"; + stop.querySelector("button").removeAttribute("disabled"); + start.style.display = "inline"; + break; + case "receiveProfileData": + loadProfile(JSON.stringify(msg.rawProfile)); + } +} + +window.addEventListener("message", onParentMessage); + +/** + * Main entry point. This function initializes Cleopatra + * in the light mode and creates all the UI we need. + */ +function initUI() { + gHideSourceLinks = getParam("ext") === "true"; + gFileList = { profileParsingFinished: function () {} }; + gInfoBar = { display: function () {} }; + + var container = document.createElement("div"); + container.id = "ui"; + + gMainArea = document.createElement("div"); + gMainArea.id = "mainarea"; + + container.appendChild(gMainArea); + document.body.appendChild(container); +} + +/** + * Modified copy of Cleopatra's enterFinishedProfileUI. + * By overriding the function we don't need to modify ui.js which helps + * with updating from upstream. + */ +function enterFinishedProfileUI() { + var cover = document.createElement("div"); + cover.className = "finishedProfilePaneBackgroundCover"; + + var pane = document.createElement("table"); + var rowIndex = 0; + var currRow; + + pane.style.width = "100%"; + pane.style.height = "100%"; + pane.border = "0"; + pane.cellPadding = "0"; + pane.cellSpacing = "0"; + pane.borderCollapse = "collapse"; + pane.className = "finishedProfilePane"; + + gBreadcrumbTrail = new BreadcrumbTrail(); + currRow = pane.insertRow(rowIndex++); + currRow.insertCell(0).appendChild(gBreadcrumbTrail.getContainer()); + + gHistogramView = new HistogramView(); + currRow = pane.insertRow(rowIndex++); + currRow.insertCell(0).appendChild(gHistogramView.getContainer()); + + if (gMeta && gMeta.videoCapture) { + gVideoPane = new VideoPane(gMeta.videoCapture); + gVideoPane.onTimeChange(videoPaneTimeChange); + currRow = pane.insertRow(rowIndex++); + currRow.insertCell(0).appendChild(gVideoPane.getContainer()); + } + + var tree = document.createElement("div"); + tree.className = "treeContainer"; + tree.style.width = "100%"; + tree.style.height = "100%"; + + gTreeManager = new ProfileTreeManager(); + gTreeManager.treeView.setColumns([ + { name: "sampleCount", title: gStrings["Running Time"] }, + { name: "selfSampleCount", title: gStrings["Self"] }, + { name: "resource", title: "" } + ]); + + currRow = pane.insertRow(rowIndex++); + currRow.style.height = "100%"; + + var cell = currRow.insertCell(0); + cell.appendChild(tree); + tree.appendChild(gTreeManager.getContainer()); + + gPluginView = new PluginView(); + tree.appendChild(gPluginView.getContainer()); + + gMainArea.appendChild(cover); + gMainArea.appendChild(pane); + + var currentBreadcrumb = gSampleFilters; + gBreadcrumbTrail.add({ + title: gStrings["Complete Profile"], + enterCallback: function () { + gSampleFilters = []; + filtersChanged(); + } + }); + + if (currentBreadcrumb == null || currentBreadcrumb.length == 0) { + gTreeManager.restoreSerializedSelectionSnapshot(gRestoreSelection); + viewOptionsChanged(); + } + + for (var i = 0; i < currentBreadcrumb.length; i++) { + var filter = currentBreadcrumb[i]; + var forceSelection = null; + if (gRestoreSelection != null && i == currentBreadcrumb.length - 1) { + forceSelection = gRestoreSelection; + } + switch (filter.type) { + case "FocusedFrameSampleFilter": + focusOnSymbol(filter.name, filter.symbolName); + gBreadcrumbTrail.enterLastItem(forceSelection); + case "FocusedCallstackPrefixSampleFilter": + focusOnCallstack(filter.focusedCallstack, filter.name, false); + gBreadcrumbTrail.enterLastItem(forceSelection); + case "FocusedCallstackPostfixSampleFilter": + focusOnCallstack(filter.focusedCallstack, filter.name, true); + gBreadcrumbTrail.enterLastItem(forceSelection); + case "RangeSampleFilter": + gHistogramView.selectRange(filter.start, filter.end); + gBreadcrumbTrail.enterLastItem(forceSelection); + } + } + + // Show platform data? + if (getParam("spd") !== "true") + toggleJavascriptOnly(); +} + +function enterProgressUI() { + var pane = document.createElement("div"); + var label = document.createElement("a"); + var bar = document.createElement("progress"); + var string = gStrings.getStr("profiler.loading"); + + pane.className = "profileProgressPane"; + pane.appendChild(label); + pane.appendChild(bar); + + var reporter = new ProgressReporter(); + reporter.addListener(function (rep) { + var progress = rep.getProgress(); + + if (label.textContent !== string) { + label.textContent = string; + } + + if (isNaN(progress)) { + bar.removeAttribute("value"); + } else { + bar.value = progress; + } + }); + + gMainArea.appendChild(pane); + Parser.updateLogSetting(); + + return reporter; +}