问题
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!
回答1:
You need to set up the pref change handler in the onAttach handler, as it is the only place in the code where you have access to the prefSet global and a given page's worker instance. This pattern works for me:
const pageMod = require("page-mod");
const data = require("self").data;
const prefSet = require("simple-prefs");
// Listen for changes
exports.main = function() {
pageMod.PageMod({
include: ["*"],
contentScriptWhen: 'end',
contentScript: 'self.port.on("prefchange", function(data) { console.log(JSON.stringify(data,null," ")); })',
onAttach: function(worker) {
function onPrefChange(prefName) {
worker.port.emit('prefchange', [prefName, prefSet.prefs[prefName]]);
}
prefSet.on("option1", onPrefChange);
prefSet.on("option2", onPrefChange);
}
});
}
See this github repo for a working example: https://github.com/canuckistani/Pref-changes
回答2:
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
});
});
})();
来源:https://stackoverflow.com/questions/10163154/use-of-simple-prefs-sdk-api-with-external-script-and-postmessage