Search code examples
firefox-addonfirefox-addon-sdk

Use of simple-prefs (SDK API) with external script and postMessage


I'm developing a new version of my add-on (targeting Gmail) using the SDK and would need to store a few boolean preferences for my users. To do so, I would like to play with the new "simple-prefs" API. Based on the Mozilla documentation and this Stackoverflow question, I got something but I face the following issues:

1) I cannot get the change of my preferences to be properly passed to my external script in data. I need to disable and re-enable the add-on to get the changes applied.

2) How to ensure that the preferences are directly applied to the tab in which Gmail is opened.

Here is my package.json:

{
"name": "Demo", 
"license": "MPL 1.1/GPL 2.0/LGPL 2.1", 
"author": "me", 
...

"preferences": [{
    "type": "bool",
    "name": "option1",
    "value": true,
    "title": "Description Option1"
},
    {
    "type": "bool",
    "name": "option2",
    "value": true,
    "title": "Description Option2"
  }]
}

My main.js:

const pageMod = require("page-mod");
const data    = require("self").data;
const prefSet = require("simple-prefs");

// Get the values for options
var option1 = prefSet.prefs.option1;
var option2 = prefSet.prefs.option2;

// Listen for changes
function onPrefChange(prefName) {  prefSet.prefs[prefName];  }

prefSet.on("option1", onPrefChange);
prefSet.on("option2", onPrefChange);

exports.main = function() {
  pageMod.PageMod({ 
  include: ["https://mail.google.com/*","http://mail.google.com/*"],
  contentScriptWhen: 'ready',
  contentScriptFile: [data.url("jquery.js"),data.url("script.js")],
  onAttach: function(worker)
    {
      worker.postMessage(option1);
      worker.postMessage(option2);
     }
 });
}

My script.js (in data):

(function(){

// Option 1
self.on("message", function(option1)    { 
  if( option1 == true ) {  
           // Do this
                          }});

// Option 2
self.on("message", function(option2)    { 
  if( option2 == true ) {  
           // Do this
                          }});
})();

There is certainly a neater way to use the postMessage protocol in my main.js file and to call it in my script.js file... Feel free to suggest your ideas and suggestions!


Solution

  • OK, here is a working version of what I wanted, quite ugly though. So if you have a prettier way of achieving it, please feel free to share it!

    My package.json:

    {
    "name": "Demo", 
    "license": "MPL 1.1/GPL 2.0/LGPL 2.1", 
    "author": "me", 
    ...
    
    "preferences": [{
        "type": "bool",
        "name": "option1",
        "value": true,
        "title": "Description Option1"
    },
        {
        "type": "bool",
        "name": "option2",
        "value": true,
        "title": "Description Option2"
      }]
    }
    

    My main.js:

    const pageMod = require("page-mod");
    const data    = require("self").data;
    const prefSet = require("simple-prefs");
    
    exports.main = function() {
        pageMod.PageMod({ 
        include: ["*//example.com/*"],
        contentScriptWhen: 'end',
        contentScriptFile: [data.url("jquery.js"),data.url("script.js")],
            onAttach: function(worker) {
    
                // Persistent values
                var option1 = prefSet.prefs.option1;
                var option2 = prefSet.prefs.option2;
    
                worker.port.emit('get-prefs', [ option1, option2 ]); // sender1
    
                // Listen for changes
                function onPrefChange(prefName) {
                    let payload = [prefName, prefSet.prefs[prefName]];
                    worker.port.emit('prefchange', payload); // sender2
                }
    
                prefSet.on("option1", onPrefChange);
                prefSet.on("option2", onPrefChange);
    
    
            }
        });
    }
    

    and my script.js (in data):

    (function(){
    
    // Persistent Values
    self.port.on("get-prefs", function(prefs) {
    
    // onPrefchange Values
    self.port.on("prefchange", function(data) { 
    
        $(document).ready(function() {
    
        var option1     = prefs[0];
        var option2     = prefs[1];
        var option      = data[0];
        var value       = data[1];
    
        var css;
    
            if(option1 == true || option == "option1" && value == true){
                css = "body {background-color:red !important}";
                    }
    
    
            if(option2 == true || option == "option2" && value == true){
                css = "body {background-color:blue !important}";
    
                    }
    
    
    ///////////////////////////////// CSS Activation
    $('head').append('<style type="text/css">' + css + '</style>');
    //////////////////////////////// #CSS Activation
    
        });//end jQuery ready
     });
     });
    
    })();