Skip to content

Instantly share code, notes, and snippets.

@rpl
Last active August 29, 2015 14:07
Show Gist options
  • Save rpl/4a1348b18287bb9ebe08 to your computer and use it in GitHub Desktop.
Save rpl/4a1348b18287bb9ebe08 to your computer and use it in GitHub Desktop.
Extending the Firefox Developer Tools
// import base Devtools SDK Panel constructor
const { Panel } = require("dev/panel");
// import Devtools SDK Toolbox manager constructor
const { Tool } = require("dev/toolbox");
// import Class helper from the Addon SDK
const { Class } = require("sdk/core/heritage");
// import self module needed to result data resources urls
var self = require('sdk/self');
// define a new Devtools SDK Panel constructor
const GruntDevToolPanel = Class({
extends: Panel,
label: "Grunt",
tooltip: "Grunt Task Runner Extension for Chrome Developer Tools",
// resolve data resources urls
icon: self.data.url("./img/icon48.png"),
url: self.data.url("./panel.html")
});
// register the new Panel to the Developer Toolbox
var gruntDevTool = new Tool({
panels: { grunt: GruntDevToolPanel }
});
// import the jpm/npm dependency
var devtools = require("firefox-devtools");
// register the devtools addon panels defined in the package.json
devtools.registerAddonsFromManifest();
{
"name": "dev-addon",
"version": "0.1.0",
"title": "dev-addon",
"description": "a basic add-on",
"main": "main.js",
"firefox-devtools": {
"panels": {
"repl": {
"label": "MYADDON",
"url": "panel.html",
"icon": "icon.png",
"tooltip": "My Addon Panel"
}
}
},
"dependencies": {
"firefox-devtools": "git://github.com/rpl/firefox-devtools"
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<pre id="response"></pre>
<textarea name="request" id="request" rows="10" cols="40"></textarea>
</body>
<script>
window.addEventListener("message", function(evt) {
if (evt.data === "RDP") {
window.debuggee = evt.ports[0];
// register a message handler on the RDP port
window.debuggee.onmessage = receive;
}
});
document.querySelector("#request").addEventListener("keyup", send, false);
function send(evt) {
if ((evt.keyCode == 13) && (evt.getModifierState("Control") == true)) {
// send a JSON object to the Debugger Server over the RDP port
window.debuggee.postMessage(JSON.parse(request.value));
}
}
function receive(evt) {
document.querySelector("#response").textContent = JSON.stringify(evt.data, null, 2);
}
</script>
</html>
const { Panel } = require("dev/panel");
const { Tool } = require("dev/toolbox");
const { Class } = require("sdk/core/heritage");
var self = require('sdk/self');
const RDPPanel = Class({
extends: Panel,
label: "RDP REPL",
tooltip: "Simple RemoteDebuggingProtocol Panel",
icon: self.data.url("./icon.png"),
url: self.data.url("./panel.html"),
// overload the setup method to get the debuggee message port
setup: function({debuggee}) {
this.debuggee = debuggee;
},
dispose: function() {
delete this.debuggee;
},
onReady: function() {
// when the panel is ready start the mesage port
this.debuggee.start();
// and send it to the panel
this.postMessage("RDP", [this.debuggee]);
}
});
// register the new Panel to the Developer Toolbox
var rdpPanelTool = new Tool({
panels: { rdp: RDPPanel }
});
const protocol = require("devtools/server/protocol");
const SimpleActor = exports.SimpleActor = protocol.ActorClass({
typeName: "simple",
initialize: function (conn, tabActor) {
protocol.Actor.prototype.initialize.call(this, conn);
...
},
destroy: function (conn) {
protocol.Actor.prototype.initialize.call(this, conn);
},
echo: method(function(msg) {
return "reply to: " + msg;
}, {
request: {
msg: protocol.Arg(0, "string")
},
response: {
msg: protocol.RetVal("string")
}
})
});
{
"to": "root",
"type": "protocolDescription"
}
{
"to": "root",
"type": "requestTypes"
}
<!DOCTYPE html>
<html>
<head>
<script src="resource://sdk/dev/volcan.js"></script>
</head>
<body>
</body>
<script>
window.addEventListener("message", function(evt) {
if (evt.data === "RDP") {
// connect volcan to the debugger server
volcan.connect(port).then(function(root) {
// get the list tabs from the root actor
root.listTabs().then(function(list) {
// get the activeTab
var activeTab = list.tabs[list.selected];
// get the tab url
document.body.innerHTML = "Connected to tab: " + activeTab.url;
});
});
}
});
</script>
</html>
window.addEventListener("message", function(evt) {
if (evt.data === "RDP") {
spawn(runEvaluateJS, evt.ports[0]);
}
});
// use the volcan promised API with ES6 generators
function* runEvaluateJS(port) {
// connect volcan to the debugger server
var root = yield volcan.connect(port);
// get the list tabs from the root actor
var list = yield root.listTabs();
// get the activeTab
var activeTab = list.tabs[list.selected];
// get the tab url
document.body.innerHTML = "Connected to tab: " + activeTab.url;
}
// minimal spawn generator helper
function spawn(task, ...args) {
return new Promise(function(resolve, reject) {
try {
var routine = task(...args);
var raise = function(error) { routine.throw(error); };
var step = function(data) {
var { done, value } = routine.next(data);
if (done) {
resolve(value);
} else {
Promise.resolve(value).then(step, raise);
}
};
step();
} catch(error) {
reject(error);
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment