Bug 1245029 - aboutdebugging full react refactor part1;r=janx,ochameau

React refactor part1 : refactor addons and workers panels as react components

MozReview-Commit-ID: GYabZqMyX4L

--HG--
extra : rebase_source : 8fbb99705f99d1a58c81161811006cb6cee17a7e
This commit is contained in:
Julian Descottes 2016-02-04 21:58:02 +01:00
parent 99f799e4c7
commit ed31367b39
12 changed files with 193 additions and 139 deletions

View File

@ -82,11 +82,11 @@ label {
flex: 1;
}
.addon-controls {
.addons-controls {
display: flex;
flex-direction: row;
}
.addon-options {
.addons-options {
flex: 1;
}

View File

@ -8,7 +8,6 @@
"use strict";
const { classes: Cc, interfaces: Ci } = Components;
const { loader } = Components.utils.import(
"resource://devtools/shared/Loader.jsm", {});
@ -22,20 +21,8 @@ loader.lazyRequireGetter(this, "Telemetry",
"devtools/client/shared/telemetry");
loader.lazyRequireGetter(this, "WorkersComponent",
"devtools/client/aboutdebugging/components/workers", true);
loader.lazyRequireGetter(this, "Services");
loader.lazyImporter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
var AboutDebugging = {
_prefListeners: [],
// Pointer to the current React component.
_component: null,
_categories: null,
get categories() {
// If needed, initialize the list of available categories.
@ -68,12 +55,13 @@ var AboutDebugging = {
.setAttribute("selected", "true");
location.hash = "#" + category;
let client = this.client;
if (category == "addons") {
this._component = React.render(React.createElement(AddonsComponent,
{client: this.client}), document.querySelector("#addons"));
React.render(React.createElement(AddonsComponent, { client }),
document.querySelector("#tab-addons"));
} else if (category == "workers") {
this._component = React.render(React.createElement(WorkersComponent,
{client: this.client}), document.querySelector("#workers"));
React.render(React.createElement(WorkersComponent, { client }),
document.querySelector("#tab-workers"));
}
},
@ -81,32 +69,6 @@ var AboutDebugging = {
let telemetry = this._telemetry = new Telemetry();
telemetry.toolOpened("aboutdebugging");
// Link checkboxes to prefs.
let elements = document.querySelectorAll("input[type=checkbox][data-pref]");
Array.map(elements, element => {
let pref = element.dataset.pref;
let updatePref = () => {
Services.prefs.setBoolPref(pref, element.checked);
};
element.addEventListener("change", updatePref, false);
let onPreferenceChanged = () => {
element.checked = Services.prefs.getBoolPref(pref);
this.update();
};
Services.prefs.addObserver(pref, onPreferenceChanged, false);
this._prefListeners.push([pref, onPreferenceChanged]);
// Initialize the current checkbox element.
element.checked = Services.prefs.getBoolPref(pref);
});
// Link buttons to their associated actions.
let loadAddonButton = document.getElementById("load-addon-from-file");
loadAddonButton.addEventListener("click", this.loadAddonFromFile);
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
@ -121,47 +83,13 @@ var AboutDebugging = {
});
},
update() {
if (this._component) {
this._component.setState({});
}
},
loadAddonFromFile() {
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(window,
Strings.GetStringFromName("selectAddonFromFile"),
Ci.nsIFilePicker.modeOpen);
let res = fp.show();
if (res == Ci.nsIFilePicker.returnCancel || !fp.file) {
return;
}
let file = fp.file;
// AddonManager.installTemporaryAddon accepts either
// addon directory or final xpi file.
if (!file.isDirectory() && !file.leafName.endsWith(".xpi")) {
file = file.parent;
}
try {
AddonManager.installTemporaryAddon(file);
} catch (e) {
alert("Error while installing the addon:\n" + e.message + "\n");
throw e;
}
},
destroy() {
let telemetry = this._telemetry;
telemetry.toolClosed("aboutdebugging");
telemetry.destroy();
this._prefListeners.forEach(([pref, listener]) => {
Services.prefs.removeObserver(pref, listener);
});
this._prefListeners = [];
React.unmountComponentAtNode(document.querySelector("#addons"));
React.unmountComponentAtNode(document.querySelector("#workers"));
React.unmountComponentAtNode(document.querySelector("#tab-addons"));
React.unmountComponentAtNode(document.querySelector("#tab-workers"));
this.client.close();
this.client = null;

View File

@ -30,25 +30,8 @@
</div>
</div>
<div class="main-content">
<div id="tab-addons" class="tab active">
<div class="header">
<h1 class="header-name">&aboutDebugging.addons;</h1>
</div>
<div class="addon-controls">
<div class="addon-options">
<input id="enable-addon-debugging" type="checkbox" data-pref="devtools.chrome.enabled"/>
<label for="enable-addon-debugging" title="&aboutDebugging.addonDebugging.tooltip;">&aboutDebugging.addonDebugging.label;</label>
</div>
<button id="load-addon-from-file">&aboutDebugging.loadTemporaryAddon;</button>
</div>
<div id="addons"></div>
</div>
<div id="tab-workers" class="tab">
<div class="header">
<h1 class="header-name">&aboutDebugging.workers;</h1>
</div>
<div id="workers"></div>
</div>
<div id="tab-addons" class="tab active" role="tabpanel" aria-labelledby="addons-header"></div>
<div id="tab-workers" class="tab" role="tabpanel" aria-labelledby="workers-header"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,76 @@
/* 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/. */
/* global React */
"use strict";
loader.lazyRequireGetter(this, "Ci", "chrome", true);
loader.lazyRequireGetter(this, "Cc", "chrome", true);
loader.lazyRequireGetter(this, "React", "devtools/client/shared/vendor/react");
loader.lazyRequireGetter(this, "Services");
loader.lazyImporter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
exports.AddonsControlsComponent = React.createClass({
displayName: "AddonsControlsComponent",
render() {
let { debugDisabled } = this.props;
return React.createElement(
"div", { className: "addons-controls" }, React.createElement(
"div", { className: "addons-options" },
React.createElement("input", {
id: "enable-addon-debugging",
type: "checkbox",
checked: !debugDisabled,
onChange: this.onEnableAddonDebuggingChange,
}),
React.createElement("label", {
htmlFor: "enable-addon-debugging",
title: Strings.GetStringFromName("addonDebugging.tooltip")
}, Strings.GetStringFromName("addonDebugging.label"))
),
React.createElement("button", {
id: "load-addon-from-file",
onClick: this.loadAddonFromFile,
}, Strings.GetStringFromName("loadTemporaryAddon"))
);
},
onEnableAddonDebuggingChange(event) {
let enabled = event.target.checked;
Services.prefs.setBoolPref("devtools.chrome.enabled", enabled);
},
loadAddonFromFile(event) {
let win = event.target.ownerDocument.defaultView;
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(win,
Strings.GetStringFromName("selectAddonFromFile"),
Ci.nsIFilePicker.modeOpen);
let res = fp.show();
if (res == Ci.nsIFilePicker.returnCancel || !fp.file) {
return;
}
let file = fp.file;
// AddonManager.installTemporaryAddon accepts either
// addon directory or final xpi file.
if (!file.isDirectory() && !file.leafName.endsWith(".xpi")) {
file = file.parent;
}
try {
AddonManager.installTemporaryAddon(file);
} catch (e) {
win.alert("Error while installing the addon:\n" + e.message + "\n");
throw e;
}
},
});

View File

@ -10,6 +10,10 @@ loader.lazyRequireGetter(this, "React",
"devtools/client/shared/vendor/react");
loader.lazyRequireGetter(this, "TargetListComponent",
"devtools/client/aboutdebugging/components/target-list", true);
loader.lazyRequireGetter(this, "TabHeaderComponent",
"devtools/client/aboutdebugging/components/tab-header", true);
loader.lazyRequireGetter(this, "AddonsControlsComponent",
"devtools/client/aboutdebugging/components/addons-controls", true);
loader.lazyRequireGetter(this, "Services");
loader.lazyImporter(this, "AddonManager",
@ -24,31 +28,50 @@ exports.AddonsComponent = React.createClass({
getInitialState() {
return {
extensions: []
extensions: [],
debugDisabled: false,
};
},
componentDidMount() {
AddonManager.addAddonListener(this);
this.update();
Services.prefs.addObserver("devtools.chrome.enabled",
this.updateDebugStatus, false);
this.updateDebugStatus();
this.updateAddonsList();
},
componentWillUnmount() {
AddonManager.removeAddonListener(this);
Services.prefs.removeObserver("devtools.chrome.enabled",
this.updateDebugStatus);
},
render() {
let client = this.props.client;
let targets = this.state.extensions;
let { client } = this.props;
let { debugDisabled, extensions: targets } = this.state;
let name = Strings.GetStringFromName("extensions");
let debugDisabled = !Services.prefs.getBoolPref("devtools.chrome.enabled");
return React.createElement("div", null,
React.createElement(TargetListComponent,
{ name, targets, client, debugDisabled })
return React.createElement(
"div", null,
React.createElement(TabHeaderComponent, {
id: "addons-header", name: Strings.GetStringFromName("addons")}),
React.createElement(AddonsControlsComponent, { debugDisabled }),
React.createElement(
"div", { id: "addons", className: "inverted-icons" },
React.createElement(TargetListComponent,
{ name, targets, client, debugDisabled })
)
);
},
update() {
updateDebugStatus() {
this.setState({
debugDisabled: !Services.prefs.getBoolPref("devtools.chrome.enabled")
});
},
updateAddonsList() {
AddonManager.getAllAddons(addons => {
let extensions = addons.filter(addon => addon.isDebuggable).map(addon => {
return {
@ -62,19 +85,31 @@ exports.AddonsComponent = React.createClass({
});
},
/**
* Mandatory callback as AddonManager listener.
*/
onInstalled() {
this.update();
this.updateAddonsList();
},
/**
* Mandatory callback as AddonManager listener.
*/
onUninstalled() {
this.update();
this.updateAddonsList();
},
/**
* Mandatory callback as AddonManager listener.
*/
onEnabled() {
this.update();
this.updateAddonsList();
},
/**
* Mandatory callback as AddonManager listener.
*/
onDisabled() {
this.update();
this.updateAddonsList();
},
});

View File

@ -3,7 +3,9 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'addons-controls.js',
'addons.js',
'tab-header.js',
'target-list.js',
'target.js',
'workers.js',

View File

@ -0,0 +1,22 @@
/* 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/. */
/* global React */
"use strict";
loader.lazyRequireGetter(this, "React",
"devtools/client/shared/vendor/react");
exports.TabHeaderComponent = React.createClass({
displayName: "TabHeaderComponent",
render() {
let { name, id } = this.props;
return React.createElement(
"div", { className: "header" }, React.createElement(
"h1", { id, className: "header-name" }, name));
},
});

View File

@ -22,8 +22,7 @@ exports.TargetListComponent = React.createClass({
displayName: "TargetListComponent",
render() {
let client = this.props.client;
let debugDisabled = this.props.debugDisabled;
let { client, debugDisabled } = this.props;
let targets = this.props.targets.sort(LocaleCompare).map(target => {
return React.createElement(TargetComponent,
{ client, target, debugDisabled });

View File

@ -27,8 +27,7 @@ exports.TargetComponent = React.createClass({
displayName: "TargetComponent",
debug() {
let client = this.props.client;
let target = this.props.target;
let { client, target } = this.props;
switch (target.type) {
case "extension":
BrowserToolboxProcess.init({ addonID: target.addonID });
@ -53,9 +52,7 @@ exports.TargetComponent = React.createClass({
},
render() {
let target = this.props.target;
let debugDisabled = this.props.debugDisabled;
let { target, debugDisabled } = this.props;
return React.createElement("div", { className: "target" },
React.createElement("img", {
className: "target-icon",

View File

@ -12,6 +12,8 @@ loader.lazyRequireGetter(this, "React",
"devtools/client/shared/vendor/react");
loader.lazyRequireGetter(this, "TargetListComponent",
"devtools/client/aboutdebugging/components/target-list", true);
loader.lazyRequireGetter(this, "TabHeaderComponent",
"devtools/client/aboutdebugging/components/tab-header", true);
loader.lazyRequireGetter(this, "Services");
loader.lazyImporter(this, "Task", "resource://gre/modules/Task.jsm");
@ -47,22 +49,28 @@ exports.WorkersComponent = React.createClass({
},
render() {
let client = this.props.client;
let workers = this.state.workers;
return React.createElement("div", { className: "inverted-icons" },
React.createElement(TargetListComponent, {
id: "service-workers",
name: Strings.GetStringFromName("serviceWorkers"),
targets: workers.service, client }),
React.createElement(TargetListComponent, {
id: "shared-workers",
name: Strings.GetStringFromName("sharedWorkers"),
targets: workers.shared, client }),
React.createElement(TargetListComponent, {
id: "other-workers",
name: Strings.GetStringFromName("otherWorkers"),
targets: workers.other, client })
);
let { client } = this.props;
let { workers } = this.state;
return React.createElement(
"div", null,
React.createElement(TabHeaderComponent, {
id: "workers-header", name: Strings.GetStringFromName("workers")}),
React.createElement(
"div", { id: "workers", className: "inverted-icons" },
React.createElement(TargetListComponent, {
id: "service-workers",
name: Strings.GetStringFromName("serviceWorkers"),
targets: workers.service, client }),
React.createElement(TargetListComponent, {
id: "shared-workers",
name: Strings.GetStringFromName("sharedWorkers"),
targets: workers.shared, client }),
React.createElement(TargetListComponent, {
id: "other-workers",
name: Strings.GetStringFromName("otherWorkers"),
targets: workers.other, client }))
);
},
update() {

View File

@ -4,7 +4,4 @@
<!ENTITY aboutDebugging.title "about:debugging">
<!ENTITY aboutDebugging.addons "Add-ons">
<!ENTITY aboutDebugging.addonDebugging.label "Enable add-on debugging">
<!ENTITY aboutDebugging.addonDebugging.tooltip "Turning this on will allow you to debug add-ons and various other parts of the browser chrome">
<!ENTITY aboutDebugging.loadTemporaryAddon "Load Temporary Add-on">
<!ENTITY aboutDebugging.workers "Workers">

View File

@ -4,10 +4,17 @@
debug = Debug
addons = Add-ons
addonDebugging.label = Enable add-on debugging
addonDebugging.tooltip = Turning this on will allow you to debug add-ons and various other parts of the browser chrome
loadTemporaryAddon = Load Temporary Add-on
extensions = Extensions
selectAddonFromFile = Select Add-on Directory or XPI File
workers = Workers
serviceWorkers = Service Workers
sharedWorkers = Shared Workers
otherWorkers = Other Workers
nothing = Nothing yet.