Bug 850145 - Use SideMenuWidget in the Profiler; r=vporof

This commit is contained in:
Anton Kovalyov 2013-06-18 14:42:36 -07:00
Родитель f68b453f7a
Коммит 3cfd9dc53d
12 изменённых файлов: 223 добавлений и 178 удалений

Просмотреть файл

@ -10,6 +10,8 @@ Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource:///modules/devtools/ProfilerController.jsm"); Cu.import("resource:///modules/devtools/ProfilerController.jsm");
Cu.import("resource:///modules/devtools/ProfilerHelpers.jsm"); Cu.import("resource:///modules/devtools/ProfilerHelpers.jsm");
Cu.import("resource:///modules/devtools/shared/event-emitter.js"); Cu.import("resource:///modules/devtools/shared/event-emitter.js");
Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/devtools/Console.jsm"); Cu.import("resource://gre/modules/devtools/Console.jsm");
@ -24,6 +26,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
XPCOMUtils.defineLazyModuleGetter(this, "Services", XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm"); "resource://gre/modules/Services.jsm");
const PROFILE_IDLE = 0;
const PROFILE_RUNNING = 1;
const PROFILE_COMPLETED = 2;
/** /**
* An instance of a profile UI. Profile UI consists of * An instance of a profile UI. Profile UI consists of
* an iframe with Cleopatra loaded in it and some * an iframe with Cleopatra loaded in it and some
@ -159,18 +165,6 @@ ProfileUI.prototype = {
}); });
}, },
/**
* Update profile's label in the sidebar.
*
* @param string text
* New text for the label.
*/
updateLabel: function PUI_udpateLabel(text) {
let doc = this.panel.document;
let label = doc.querySelector("li#profile-" + this.uid + "> h1");
label.textContent = text;
},
/** /**
* Start profiling and, once started, notify the underlying page * Start profiling and, once started, notify the underlying page
* so that it could update the UI. Also, once started, we add a * so that it could update the UI. Also, once started, we add a
@ -192,7 +186,7 @@ ProfileUI.prototype = {
startFn = startFn || this.panel.startProfiling.bind(this.panel); startFn = startFn || this.panel.startProfiling.bind(this.panel);
startFn(this.name, () => { startFn(this.name, () => {
this.isStarted = true; this.isStarted = true;
this.updateLabel(this.name + " *"); this.panel.sidebar.setProfileState(this, PROFILE_RUNNING);
this.panel.broadcast(this.uid, {task: "onStarted"}); // Do we really need this? this.panel.broadcast(this.uid, {task: "onStarted"}); // Do we really need this?
this.emit("started"); this.emit("started");
}); });
@ -219,7 +213,7 @@ ProfileUI.prototype = {
stopFn(this.name, () => { stopFn(this.name, () => {
this.isStarted = false; this.isStarted = false;
this.isFinished = true; this.isFinished = true;
this.updateLabel(this.name); this.panel.sidebar.setProfileState(this, PROFILE_COMPLETED);
this.panel.broadcast(this.uid, {task: "onStopped"}); this.panel.broadcast(this.uid, {task: "onStopped"});
this.emit("stopped"); this.emit("stopped");
}); });
@ -274,6 +268,39 @@ ProfileUI.prototype = {
} }
}; };
function SidebarView(el) {
EventEmitter.decorate(this);
this.node = new SideMenuWidget(el);
}
ViewHelpers.create({ constructor: SidebarView, proto: MenuContainer.prototype }, {
getItemByProfile: function (profile) {
return this.orderedItems.filter((item) => item.attachment.uid === profile.uid)[0];
},
setProfileState: function (profile, state) {
let item = this.getItemByProfile(profile);
let label = item.target.querySelector(".profiler-sidebar-item > span");
switch (state) {
case PROFILE_IDLE:
label.textContent = L10N.getStr("profiler.stateIdle");
break;
case PROFILE_RUNNING:
label.textContent = L10N.getStr("profiler.stateRunning");
break;
case PROFILE_COMPLETED:
label.textContent = L10N.getStr("profiler.stateCompleted");
break;
default: // Wrong state, do nothing.
return;
}
item.attachment.state = state;
this.emit("stateChanged", item);
}
});
/** /**
* Profiler panel. It is responsible for creating and managing * Profiler panel. It is responsible for creating and managing
* different profile instances (see ProfileUI). * different profile instances (see ProfileUI).
@ -320,6 +347,7 @@ ProfilerPanel.prototype = {
target: null, target: null,
controller: null, controller: null,
profiles: null, profiles: null,
sidebar: null,
_uid: null, _uid: null,
_activeUid: null, _activeUid: null,
@ -332,7 +360,14 @@ ProfilerPanel.prototype = {
}, },
set activeProfile(profile) { set activeProfile(profile) {
if (this._activeUid === profile.uid)
return;
if (this.activeProfile)
this.activeProfile.hide();
this._activeUid = profile.uid; this._activeUid = profile.uid;
profile.show();
}, },
get browserWindow() { get browserWindow() {
@ -357,42 +392,59 @@ ProfilerPanel.prototype = {
* @return Promise * @return Promise
*/ */
open: function PP_open() { open: function PP_open() {
let promise;
// Local profiling needs to make the target remote. // Local profiling needs to make the target remote.
if (!this.target.isRemote) { let target = this.target;
promise = this.target.makeRemote(); let promise = !target.isRemote ? target.makeRemote() : Promise.resolve(target);
} else {
promise = Promise.resolve(this.target);
}
return promise return promise
.then(function(target) { .then((target) => {
let deferred = Promise.defer(); let deferred = Promise.defer();
this.controller = new ProfilerController(this.target);
this.controller.connect(function onConnect() { this.controller = new ProfilerController(this.target);
this.sidebar = new SidebarView(this.document.querySelector("#profiles-list"));
this.sidebar.node.addEventListener("select", (ev) => {
if (!ev.detail)
return;
let profile = this.profiles.get(ev.detail.attachment.uid);
this.activeProfile = profile;
if (profile.isReady) {
profile.flushMessages();
return void this.emit("profileSwitched", profile.uid);
}
profile.once("ready", () => {
profile.flushMessages();
this.emit("profileSwitched", profile.uid);
});
});
this.controller.connect(() => {
let create = this.document.getElementById("profiler-create"); let create = this.document.getElementById("profiler-create");
create.addEventListener("click", function (ev) { create.addEventListener("click", () => this.createProfile(), false);
this.createProfile()
}.bind(this), false);
create.removeAttribute("disabled"); create.removeAttribute("disabled");
let profile = this.createProfile(); let profile = this.createProfile();
this.switchToProfile(profile, function () { let onSwitch = (_, uid) => {
if (profile.uid !== uid)
return;
this.off("profileSwitched", onSwitch);
this.isReady = true; this.isReady = true;
this.emit("ready"); this.emit("ready");
deferred.resolve(this); deferred.resolve(this);
}.bind(this)) };
}.bind(this));
this.on("profileSwitched", onSwitch);
this.sidebar.selectedItem = this.sidebar.getItemByProfile(profile);
});
return deferred.promise; return deferred.promise;
}.bind(this)) })
.then(null, function onError(reason) { .then(null, (reason) =>
Cu.reportError("ProfilerPanel open failed. " + Cu.reportError("ProfilePanel open failed: " + reason.message));
reason.error + ": " + reason.message);
});
}, },
/** /**
@ -427,22 +479,17 @@ ProfilerPanel.prototype = {
} }
} }
let list = this.document.getElementById("profiles-list"); let box = this.document.createElement("vbox");
let item = this.document.createElement("li"); box.className = "profiler-sidebar-item";
let wrap = this.document.createElement("h1"); box.id = "profile-" + uid;
name = name || L10N.getFormatStr("profiler.profileName", [uid]); let h3 = this.document.createElement("h3");
h3.textContent = name;
let span = this.document.createElement("span");
span.textContent = L10N.getStr("profiler.stateIdle");
box.appendChild(h3);
box.appendChild(span);
item.setAttribute("id", "profile-" + uid); this.sidebar.push(box, { attachment: { uid: uid, name: name, state: PROFILE_IDLE } });
item.setAttribute("data-uid", uid);
item.addEventListener("click", function (ev) {
this.switchToProfile(this.profiles.get(uid));
}.bind(this), false);
wrap.className = "profile-name";
wrap.textContent = name;
item.appendChild(wrap);
list.appendChild(item);
let profile = new ProfileUI(uid, name, this); let profile = new ProfileUI(uid, name, this);
this.profiles.set(uid, profile); this.profiles.set(uid, profile);
@ -451,47 +498,6 @@ ProfilerPanel.prototype = {
return profile; return profile;
}, },
/**
* Switches to a different profile by making its instance an
* active one.
*
* @param ProfileUI profile
* A profile instance to switch to.
* @param function onLoad
* A function to call when profile instance is ready.
* If the instance is already loaded, onLoad will be
* called synchronously.
*/
switchToProfile: function PP_switchToProfile(profile, onLoad=function() {}) {
let doc = this.document;
if (this.activeProfile) {
this.activeProfile.hide();
}
let active = doc.querySelector("#profiles-list > li.splitview-active");
if (active) {
active.className = "";
}
doc.getElementById("profile-" + profile.uid).className = "splitview-active";
profile.show();
this.activeProfile = profile;
if (profile.isReady) {
profile.flushMessages();
this.emit("profileSwitched", profile.uid);
onLoad();
return;
}
profile.once("ready", () => {
profile.flushMessages();
this.emit("profileSwitched", profile.uid);
onLoad();
});
},
/** /**
* Start collecting profile data. * Start collecting profile data.
* *

Просмотреть файл

@ -83,7 +83,15 @@ gcli.addCommand({
throw gcli.lookup("profilerAlreadyFinished"); throw gcli.lookup("profilerAlreadyFinished");
} }
panel.switchToProfile(profile, function () profile.start()); let item = panel.sidebar.getItemByProfile(profile);
if (panel.sidebar.selectedItem === item) {
profile.start();
} else {
panel.on("profileSwitched", () => profile.start());
panel.sidebar.selectedItem = item;
}
return gcli.lookup("profilerStarting2"); return gcli.lookup("profilerStarting2");
} }
@ -124,7 +132,15 @@ gcli.addCommand({
throw gcli.lookup("profilerNotStarted2"); throw gcli.lookup("profilerNotStarted2");
} }
panel.switchToProfile(profile, function () profile.stop()); let item = panel.sidebar.getItemByProfile(profile);
if (panel.sidebar.selectedItem === item) {
profile.stop();
} else {
panel.on("profileSwitched", () => profile.stop());
panel.sidebar.selectedItem = item;
}
return gcli.lookup("profilerStopping2"); return gcli.lookup("profilerStopping2");
} }
@ -193,7 +209,7 @@ gcli.addCommand({
throw gcli.lookup("profilerNotFound"); throw gcli.lookup("profilerNotFound");
} }
panel.switchToProfile(profile); panel.sidebar.selectedItem = panel.sidebar.getItemByProfile(profile);
} }
}); });

Просмотреть файл

@ -6,9 +6,9 @@
<?xml-stylesheet href="chrome://global/skin/global.css"?> <?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css"?> <?xml-stylesheet href="chrome://browser/skin/devtools/common.css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/splitview.css"?> <?xml-stylesheet href="chrome://browser/skin/devtools/widgets.css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/profiler.css"?> <?xml-stylesheet href="chrome://browser/skin/devtools/profiler.css"?>
<?xml-stylesheet href="chrome://browser/content/devtools/splitview.css"?> <?xml-stylesheet href="chrome://browser/content/devtools/widgets.css"?>
<!DOCTYPE window [ <!DOCTYPE window [
<!ENTITY % profilerDTD SYSTEM "chrome://browser/locale/devtools/profiler.dtd"> <!ENTITY % profilerDTD SYSTEM "chrome://browser/locale/devtools/profiler.dtd">
@ -16,37 +16,31 @@
]> ]>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<box flex="1" id="profiler-chrome" class="splitview-root"> <box flex="1" id="profiler-chrome" class="devtools-responsive-container">
<box class="splitview-controller" width="180px"> <vbox class="profiler-sidebar">
<box class="splitview-main"></box> <toolbar class="devtools-toolbar">
<toolbarbutton id="profiler-create"
class="devtools-toolbarbutton"
label="&profilerNew.label;"
disabled="true"/>
</toolbar>
<box class="splitview-nav-container"> <vbox id="profiles-list" flex="1">
<ol class="splitview-nav" id="profiles-list"> </vbox>
<!-- Example: </vbox>
<li class="splitview-active" id="profile-1" data-uid="1">
<h1 class="profile-name">Profile 1</h1>
</li>
-->
</ol>
<spacer flex="1"/> <splitter class="devtools-side-splitter"/>
<toolbar class="devtools-toolbar" mode="full"> <vbox flex="1">
<toolbarbutton id="profiler-create" <toolbar class="devtools-toolbar">
class="devtools-toolbarbutton" </toolbar>
label="&profilerNew.label;"
disabled="true"/>
</toolbar>
</box> <!-- splitview-nav-container -->
</box> <!-- splitview-controller -->
<box flex="1">
<vbox flex="1" id="profiler-report"> <vbox flex="1" id="profiler-report">
<!-- Example: <!-- Example:
<iframe id="profiler-cleo-1" <iframe id="profiler-cleo-1"
src="devtools/cleopatra.html" flex="1"></iframe> src="devtools/cleopatra.html" flex="1"></iframe>
--> -->
</vbox> </vbox>
</box> </vbox>
</box> </box>
</window> </window>

Просмотреть файл

@ -26,13 +26,6 @@ function test() {
}); });
} }
function getCleoControls(doc) {
return [
doc.querySelector("#startWrapper button"),
doc.querySelector("#profilerMessage")
];
}
function startProfiling() { function startProfiling() {
gPanel.profiles.get(gPanel.activeProfile.uid).once("started", function () { gPanel.profiles.get(gPanel.activeProfile.uid).once("started", function () {
setTimeout(function () { setTimeout(function () {
@ -40,36 +33,27 @@ function startProfiling() {
gPanel.profiles.get(2).once("started", function () setTimeout(stopProfiling, 50)); gPanel.profiles.get(2).once("started", function () setTimeout(stopProfiling, 50));
}, 50); }, 50);
}); });
sendFromProfile(gPanel.activeProfile.uid, "start"); sendFromProfile(gPanel.activeProfile.uid, "start");
} }
function stopProfiling() { function stopProfiling() {
let [win, doc] = getProfileInternals(gUid); is(getSidebarItem(1).attachment.state, PROFILE_RUNNING);
let [btn, msg] = getCleoControls(doc); is(getSidebarItem(2).attachment.state, PROFILE_RUNNING);
is(gPanel.document.querySelector("li#profile-1 > h1").textContent,
"Profile 1 *", "Profile 1 has a star next to it.");
is(gPanel.document.querySelector("li#profile-2 > h1").textContent,
"Profile 2 *", "Profile 2 has a star next to it.");
gPanel.profiles.get(gPanel.activeProfile.uid).once("stopped", function () { gPanel.profiles.get(gPanel.activeProfile.uid).once("stopped", function () {
is(gPanel.document.querySelector("li#profile-1 > h1").textContent, is(getSidebarItem(1).attachment.state, PROFILE_COMPLETED);
"Profile 1", "Profile 1 doesn't have a star next to it anymore.");
sendFromProfile(2, "stop"); sendFromProfile(2, "stop");
gPanel.profiles.get(2).once("stopped", confirmAndFinish); gPanel.profiles.get(2).once("stopped", confirmAndFinish);
}); });
sendFromProfile(gPanel.activeProfile.uid, "stop"); sendFromProfile(gPanel.activeProfile.uid, "stop");
} }
function confirmAndFinish(ev, data) { function confirmAndFinish(ev, data) {
let [win, doc] = getProfileInternals(gUid); is(getSidebarItem(1).attachment.state, PROFILE_COMPLETED);
let [btn, msg] = getCleoControls(doc); is(getSidebarItem(2).attachment.state, PROFILE_COMPLETED);
is(gPanel.document.querySelector("li#profile-1 > h1").textContent,
"Profile 1", "Profile 1 doesn't have a star next to it.");
is(gPanel.document.querySelector("li#profile-2 > h1").textContent,
"Profile 2", "Profile 2 doesn't have a star next to it.");
tearDown(gTab, function onTearDown() { tearDown(gTab, function onTearDown() {
gPanel = null; gPanel = null;

Просмотреть файл

@ -48,17 +48,15 @@ function testConsoleProfile(hud) {
function checkProfiles(toolbox) { function checkProfiles(toolbox) {
let panel = toolbox.getPanel("jsprofiler"); let panel = toolbox.getPanel("jsprofiler");
let getTitle = (uid) =>
panel.document.querySelector("li#profile-" + uid + " > h1").textContent;
is(getTitle(1), "Profile 1", "Profile 1 doesn't have a star next to it."); is(getSidebarItem(1, panel).attachment.state, PROFILE_IDLE);
is(getTitle(2), "Profile 2 *", "Profile 2 doesn't have a star next to it."); is(getSidebarItem(2, panel).attachment.state, PROFILE_RUNNING);
is(getTitle(3), "Profile 3", "Profile 3 doesn't have a star next to it."); is(getSidebarItem(3, panel).attachment.state, PROFILE_COMPLETED);
// Make sure we can still stop profiles via the UI. // Make sure we can still stop profiles via the UI.
gPanel.profiles.get(2).once("stopped", () => { gPanel.profiles.get(2).once("stopped", () => {
is(getTitle(2), "Profile 2", "Profile 2 doesn't have a star next to it."); is(getSidebarItem(2, panel).attachment.state, PROFILE_COMPLETED);
tearDown(gTab, () => gTab = gPanel = null); tearDown(gTab, () => gTab = gPanel = null);
}); });

Просмотреть файл

@ -17,18 +17,20 @@ function test() {
openProfiler(tab, (toolbox) => { openProfiler(tab, (toolbox) => {
gToolbox = toolbox; gToolbox = toolbox;
loadUrl(PAGE, tab, () => { loadUrl(PAGE, tab, () => {
gPanel.on("profileCreated", runTests); gPanel.sidebar.on("stateChanged", (_, item) => {
if (item.attachment.state !== PROFILE_COMPLETED)
return;
runTests();
});
}); });
}); });
}); });
} }
function runTests() { function runTests() {
let getTitle = (uid) => is(getSidebarItem(1).attachment.state, PROFILE_IDLE);
gPanel.document.querySelector("li#profile-" + uid + " > h1").textContent; is(getSidebarItem(2).attachment.state, PROFILE_COMPLETED);
is(getTitle(1), "Profile 1", "Profile 1 doesn't have a star next to it.");
is(getTitle(2), "Profile 2", "Profile 2 doesn't have a star next to it.");
gPanel.once("parsed", () => { gPanel.once("parsed", () => {
function assertSampleAndFinish() { function assertSampleAndFinish() {
@ -49,5 +51,6 @@ function runTests() {
assertSampleAndFinish(); assertSampleAndFinish();
}); });
gPanel.switchToProfile(gPanel.profiles.get(2)); let profile = gPanel.profiles.get(2);
gPanel.sidebar.selectedItem = gPanel.sidebar.getItemByProfile(profile);
} }

Просмотреть файл

@ -18,15 +18,13 @@ function test() {
function runTests(toolbox) { function runTests(toolbox) {
let panel = toolbox.getPanel("jsprofiler"); let panel = toolbox.getPanel("jsprofiler");
let getTitle = (uid) =>
panel.document.querySelector("li#profile-" + uid + " > h1").textContent;
panel.profiles.get(1).once("started", () => { panel.profiles.get(1).once("started", () => {
is(getTitle(1), "Profile 1 *", "Profile 1 has a start next to it."); is(getSidebarItem(1, panel).attachment.state, PROFILE_RUNNING);
openConsole(gTab, (hud) => { openConsole(gTab, (hud) => {
panel.profiles.get(1).once("stopped", () => { panel.profiles.get(1).once("stopped", () => {
is(getTitle(1), "Profile 1", "Profile 1 doesn't have a star next to it."); is(getSidebarItem(1, panel).attachment.state, PROFILE_COMPLETED);
tearDown(gTab, () => gTab = gPanel = null); tearDown(gTab, () => gTab = gPanel = null);
}); });

Просмотреть файл

@ -46,18 +46,18 @@ function testConsoleProfile(hud) {
function checkProfiles(toolbox) { function checkProfiles(toolbox) {
let panel = toolbox.getPanel("jsprofiler"); let panel = toolbox.getPanel("jsprofiler");
let getTitle = (uid) =>
panel.document.querySelector("li#profile-" + uid + " > h1").textContent;
is(getTitle(1), "Profile 1", "Profile 1 doesn't have a star next to it."); is(getSidebarItem(1, panel).attachment.state, PROFILE_IDLE);
is(getTitle(2), "Second", "Second doesn't have a star next to it."); is(getSidebarItem(2, panel).attachment.name, "Second");
is(getTitle(3), "Third *", "Third does have a star next to it."); is(getSidebarItem(2, panel).attachment.state, PROFILE_COMPLETED);
is(getSidebarItem(3, panel).attachment.name, "Third");
is(getSidebarItem(3, panel).attachment.state, PROFILE_RUNNING);
// Make sure we can still stop profiles via the queue pop. // Make sure we can still stop profiles via the queue pop.
gPanel.profiles.get(3).once("stopped", () => { gPanel.profiles.get(3).once("stopped", () => {
openProfiler(gTab, () => { openProfiler(gTab, () => {
is(getTitle(3), "Third", "Third doesn't have a star next to it."); is(getSidebarItem(3, panel).attachment.state, PROFILE_COMPLETED);
tearDown(gTab, () => gTab = gPanel = null); tearDown(gTab, () => gTab = gPanel = null);
}); });
}); });

Просмотреть файл

@ -48,8 +48,11 @@ function onNamedProfileCreated(name, uid) {
is(gPanel.profiles.size, 3, "There are three profiles now"); is(gPanel.profiles.size, 3, "There are three profiles now");
is(gPanel.getProfileByUID(uid).name, "Custom Profile", "Name is correct"); is(gPanel.getProfileByUID(uid).name, "Custom Profile", "Name is correct");
let label = gPanel.document.querySelector("li#profile-" + uid + "> h1"); let profile = gPanel.profiles.get(uid);
is(label.textContent, "Custom Profile", "Name is correct on the label"); let data = gPanel.sidebar.getItemByProfile(profile).attachment;
is(data.uid, uid, "UID is correct");
is(data.name, "Custom Profile", "Name is correct on the label");
let btn = gPanel.document.getElementById("profile-" + uid); let btn = gPanel.document.getElementById("profile-" + uid);
ok(btn, "Profile item has been added to the sidebar"); ok(btn, "Profile item has been added to the sidebar");

Просмотреть файл

@ -2,8 +2,12 @@
http://creativecommons.org/publicdomain/zero/1.0/ */ http://creativecommons.org/publicdomain/zero/1.0/ */
let temp = {}; let temp = {};
const PROFILER_ENABLED = "devtools.profiler.enabled"; const PROFILER_ENABLED = "devtools.profiler.enabled";
const REMOTE_ENABLED = "devtools.debugger.remote-enabled"; const REMOTE_ENABLED = "devtools.debugger.remote-enabled";
const PROFILE_IDLE = 0;
const PROFILE_RUNNING = 1;
const PROFILE_COMPLETED = 2;
Cu.import("resource:///modules/devtools/gDevTools.jsm", temp); Cu.import("resource:///modules/devtools/gDevTools.jsm", temp);
let gDevTools = temp.gDevTools; let gDevTools = temp.gDevTools;
@ -36,6 +40,11 @@ function getProfileInternals(uid) {
return [win, doc]; return [win, doc];
} }
function getSidebarItem(uid, panel=gPanel) {
let profile = panel.profiles.get(uid);
return panel.sidebar.getItemByProfile(profile);
}
function sendFromProfile(uid, msg) { function sendFromProfile(uid, msg) {
let [win, doc] = getProfileInternals(uid); let [win, doc] = getProfileInternals(uid);
win.parent.postMessage({ uid: uid, status: msg }, "*"); win.parent.postMessage({ uid: uid, status: msg }, "*");

Просмотреть файл

@ -82,3 +82,18 @@ profiler.loading=Loading profile…
# This string is displayed in the profiler whenever there is already # This string is displayed in the profiler whenever there is already
# another running profile. Users can run only one profile at a time. # another running profile. Users can run only one profile at a time.
profiler.alreadyRunning=Profiler is already running. If you want to run this profile stop Profile %S first. profiler.alreadyRunning=Profiler is already running. If you want to run this profile stop Profile %S first.
# LOCALIZATION NOTE (profiler.stateIdle)
# This string is used to show that the profile in question is in IDLE
# state meaning that it hasn't been started yet.
profiler.stateIdle=Idle
# LOCALIZATION NOTE (profiler.stateRunning)
# This string is used to show that the profile in question is in RUNNING
# state meaning that it has been started and currently gathering profile data.
profiler.stateRunning=Running
# LOCALIZATION NOTE (profiler.stateCompleted)
# This string is used to show that the profile in question is in COMPLETED
# state meaning that it has been started and stopped already.
profiler.stateCompleted=Completed

Просмотреть файл

@ -4,21 +4,40 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
%endif %endif
.profile-name { .profiler-sidebar {
min-width: 196px;
}
.profiler-sidebar + .devtools-side-splitter {
-moz-border-start-color: transparent;
}
.profiler-sidebar-item {
padding: 3px 5px;
}
.profiler-sidebar-item > h3 {
font-size: 13px; font-size: 13px;
padding: 8px; display: block;
} }
#profiles-list > li { .profiler-sidebar-item > span {
width: 180px; margin-top: 2px;
cursor: pointer; color: rgb(140, 152, 165);
} }
.splitview-nav-container button { .selected .profiler-sidebar-item > span {
color: white; color: rgb(128, 195, 228);
background-clip: padding-box; }
border-bottom: 1px solid hsla(210,16%,76%,.1);
box-shadow: inset 0 -1px 0 hsla(210,8%,5%,.25); .devtools-toolbar {
-moz-padding-end: 8px; height: 26px;
-moz-box-align: center; padding: 3px;
}
.devtools-toolbar .devtools-toolbarbutton {
min-width: 48px;
min-height: 0;
font-size: 11px;
padding: 0px 8px;
} }