Search code examples
javascriptfirefoxfirefox-addonfirefox-addon-sdk

Receive message from main.js in Firefox add-on content script


I'm trying to communicate between main.js and a content script. Here is my main.js:

var pageMod = require('sdk/page-mod');
var self = require('sdk/self');
var ss = require('sdk/simple-storage');

pageMod.PageMod({
    include: 'example.com',
    contentScriptFile: self.data.url('content-script.js'),
    onAttach: function(worker) {
        worker.port.on('getSetting', function(request) {
            // var settingValue = ss.storage[request]
            var settingValue = 'test value'; // for testing, return an 
                                             // arbitrary string
            worker.port.emit('settingRetrieved', settingValue);
        });
    }
});

And content-script.js:

alert('getting setting...');
self.port.emit('getSetting', 'test setting name');
alert('asked for setting...');
self.port.on('settingRetrieved', function(results) {
    alert('retrieved setting: "' + results + '"');
});

It appears that self.port.on() in content-script.js is not receiving the message from main.js. What am I doing wrong?


Solution

  • Facepalm. The code from content-script.js was wrapped in a jQuery event handler, so self.port.on() couldn't listen properly.

    Here is the working code--first, main.js:

    var pageMod = require('sdk/page-mod');
    var self = require('sdk/self');
    var ss = require('sdk/simple-storage');
    
    pageMod.PageMod({
        include: 'example.com',
        contentScriptFile: self.data.url('content-script.js'),
        onAttach: function(worker) {
            worker.port.on('getSetting', function(request) {
                var settingValue = ss.storage[request];
                worker.port.emit('settingRetrieved',
                    {
                        'settingName': request,
                        'settingValue': settingValue,
                    }
                );
            });
        }
    });
    

    And content-script.js:

    // Store the setting value
    var mySetting = '';
    
    // Listen for retrieval the setting value
    self.port.on('settingRetrieved', function(results) {
        mySetting = results['settingValue'];
    });
    
    // Generic function to retrieve a setting value
    function getSetting(setting) {
        self.port.emit('getSetting', setting);
    }
    
    // Retrieve the value of 'mySetting' and do something with it
    $(document).ready(function() {
        $('#my-element').click(function() {
            getSetting('mySetting');
            /*
            ...
            Value of mySetting has been updated; do something with it here
            ...
            */
        });
    });