Firefox Addon : Event on a specific command line

I’m trying that when the user enters a command in the Web console, I get this command in the script of my addon before to be executed?

For example, when the user enters the command line “screenshot --fullpage” this command to be sent to a function of the script of my addon before being executed.

I did some research but I only found an event on the opening of the web console.

You need an observer for the “commandline-args-changed” notification:
Services.obs.addObserver(this, "commandline-args-changed", false);

Thanks, but would you have an example of using?

I tried with this example, but it does not work

My code:

function myObserver()
{
this.register();
}
myObserver.prototype = {
observe: function(subject, topic, data) {
console.log(‘incoming observe commandline-args-changed - subject: "’ + subject + ‘" | topic: "’ + topic + ‘" | data: "’ + data + ‘"’);
},
register: function() {
var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
observerService.addObserver(this, “commandline-args-changed”, false);
},
unregister: function() {
var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
observerService.removeObserver(this, “commandline-args-changed”);
}
}

var observer = new myObserver();

I think you’re right. You may have to register a full command line handler in an XPCOM component.

If you don’t have a component, you should be able to do the same thing from a javascript code module, or even a bootstrap script. Instead of a manifest you would have to register the code from javascript, something like this (use your handler instead of mine):

Cm.QueryInterface(Ci.nsIComponentRegistrar).registerFactory(proto.classID, “Torrent Status magnet protocol handler”, “@mozilla.org/network/protocol;1?name=magnet”, proto.factory);`

I’m not sure you’re understood my question. I want when the user enters the command “screenshot” in the console.

One of my functions is executed before executing the command “screenshot”. For information I use the SDK with JPM.

Best regards.

Oh. In the web console? That’s just javascript. Create a function called screenshot and away you go. Unfortunately that might not go down too well with the addon reviewers. It would have to be a global called screenshot and the convention is that addons shouldn’t go around creating globals. The SDK is particular is not intended for that purpose. If you want to extend the user interface, it is more normal to add a button or a menu item, perhaps even a hotkey although they’re pretty much all used up now with Firefox junk.

Ok, so it’s impossible to put a trigger on the screenshot action. In that case, is it possible to take a screenshot from the code of my addon (SDK)?

No its very possible. Search dxr, it shows you how they set it up, so you can do the same :smile:

https://dxr.mozilla.org/mozilla-central/source/devtools/shared/gcli/commands/index.js#71

Ok I was curious to dig a little bit to see if i could add one. I found this nice article on dxr - https://dxr.mozilla.org/mozilla-central/source/devtools/shared/gcli/source/docs/writing-commands.md

I tried some stuff quickly but it’s not working on my first try, try digging around here:

var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
const { createSystem, connectFront, disconnectFront } = require("gcli/system");
const { GcliFront } = require("devtools/server/actors/gcli");
require('gcli/index')
var mySystem = createSystem({location:'client'})

mySystem.addItems([{
  name: 'greet',
  description: 'Show a greeting',
  params: [
    {
      name: 'name',
      type: 'string',
      description: 'The name to greet'
    }
  ],
  returnType: 'string',
  exec: function(args, context) {
    return 'Hello, ' + args.name;
  }
}]);

But that fails saying “type string” is invalid. And also I’m not sure if this affects the commands inputable to the developer toolbar. I think I might be making a new “system” and adding commands to that. Not sure.

I found a getSystem function here - https://dxr.mozilla.org/mozilla-central/source/devtools/shared/gcli/commands/index.js#110

So called it in like this:

require(‘devtools/shared/gcli/commands/index’)

But couldn’t figure out how to give it a target.

I found that this

var tmp = {};
Cu.import("resource://devtools/client/shared/DeveloperToolbar.jsm", tmp);
var a = new tmp.DeveloperToolbar(window, document.getElementById("developer-toolbar"));

That gives you a like the current dev toolbar but then I cant figure out how to run getSystem on it.

Alrighty here we go, this works:

var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});

var gcliInit = require('devtools/shared/gcli/commands/index');
var { TargetFactory } = require("devtools/client/framework/target");

var sysTarget= TargetFactory.forTab(Services.wm.getMostRecentWindow('navigator:browser').gBrowser.selectedTab);

gcliInit.getSystem(sysTarget).then(
    system => {
        console.log('system:',system);
        system.addItems([{
            name: 'greet',
            description: 'Show a greeting',
            params: [{
                name: 'name',
                type: 'string',
                description: 'The name to greet'
            }],
            returnType: 'string',
            exec: function(args, context) {
                return 'Hello, ' + args.name;
            }
        }]);
    },
    y => console.error('y:',y)
);

Note, the path changes in Firefox 45. So this code is for Fx45+ prior to this you would use resource://gre/modules/devtools/Loader.jsm instead of resource://devtools/shared/Loader.jsm.

TargetFactor was the key component I was missing, it’s important, it’s got these methods:

 Object { forTab: function (), forRemoteTab: function (), forWorker: function (), isKnownTab: function () }

Thank you very much for taking time for my problem.

I’m sorry but your code does not compile for me. I have several errors like:
“require is not function"
or
"Module ‘gcli/system’ is not found at ressource://gre/modules/commonjs/gcli/system.js”

Yet I have used Firefox 44.0 and Firefox Developer Edition 46.0a2 for my tests.

Can you post the complete project where you have tested your code that I can try on my computer?

You have to copy paste that to scratchpad with environment browser and then hit “Run”, it works in Fx45+.

As mentioned in previous post, if you want to use in Firefox less than 45 change the Loader.jsm path to resource://gre/modules/devtools/Loader.jsm.

If you are copying and pasting this code into an addon sdk main.js or something, then you need to first put at the top:

var {Cu, Cc, Ci} = require('chrome');
Cu.import('resource://gre/modules/Services.jsm');

Remember though this is a per tab thing, so you have to run this script on each new tab that opens.

Really the thanks goes to you, for being so persistent, I hope you make a very nice addon out of this. :slight_smile:

Sorry but I just initialize a new project with JPM (jpm init). I delete all files except index.js (hand) and package.json. And I pasted this code in index.js :

//Firefox 44

var {Cu, Cc, Ci} = require(‘chrome’);
Cu.import(‘resource://gre/modules/Services.jsm’);

var { requiree } = Cu.import(“resource://gre/modules/devtools/Loader.jsm”, {});

var gcliInit = require(‘devtools/shared/gcli/commands/index’);
var { TargetFactory } = require(“devtools/client/framework/target”);

var sysTarget= TargetFactory.forTab(Services.wm.getMostRecentWindow(‘navigator:browser’).gBrowser.selectedTab);

gcliInit.getSystem(sysTarget).then(
system => {
console.log(‘system:’,system);
system.addItems([{
name: ‘greet’,
description: ‘Show a greeting’,
params: [{
name: ‘name’,
type: ‘string’,
description: ‘The name to greet’
}],
returnType: ‘string’,
exec: function(args, context) {
return 'Hello, ’ + args.name;
}
}]);
},
y => console.error(‘y:’,y)
);

And the result is the same. Always the same errors.

If you have JPM installed, the link to download my project : https://mega.nz/#!lMIySRRT!95nqO0uTxnBcP-Y9hEbYCUsGLhumOAZTWIWkounZJRs

You have a typo:

var { requiree } = Cu.import(“resource://gre/modules/devtools/Loader.jsm”, {});

Notice that you typed requiree instead of require

I rather not download from Mega. Do you have a github account you can upload to?

Yes I changed “require” in “requiree” because JPM returned me an error (require is not defined).

I uploaded my project on Github : https://github.com/ValentinG08/Test

You can’t change require spelling. What you have to do is load it into a scope.

So do this:

var my = {};
Cu.import("resource://gre/modules/devtools/Loader.jsm", my);

Then you can use my.require

Sorry for my absence but I lacked the time to devote to my project.

Thank you for your help it works perfectly.

But I try to overwrite the screenshot function. So I tried to include “resource: //gre/modules/Screenshot.jsm” to use Screenshot.get (). But this resource is not found.