1

I am learning how to create a Firefox add-on. I want to do a simple add-on that will inject a script in a page. I have read the documentation but I can't solve this problem.

in the cfx run logs, I can see that it runs the script various times in the same page when it should do it only once.

main.js

 
var pageMod = require('sdk/page-mod')
var data = require('sdk/self').data

pageMod.PageMod({
  include:  ['*'],
  contentScriptWhen: 'end',
  contentScriptFile: data.url('starter.js')
})
 

starter.js

 
var script = document.createElement('script');

script.id = 'i-inject';
script.type = 'text/javascript';
script.src = 'http://localhost:8888/injectme.js';
document.getElementsByTagName('head')[0].appendChild(script);
console.log('injected');
 

Do you see this console.log('injected') ? I can see that it's printed 5 times in the console when I do cfx run and each time I reload the page. I don't understand that behaviour.

Any help greatly appreciated :)

Kev
  • 5,049
  • 5
  • 32
  • 53
  • 1
    Are you sure it runs in 5 times in the same page, or maybe just once and then once for each of the four iframes the page may contain? – nmaier May 11 '14 at 19:59
  • 1
    Hello, I didn't think about iframes. Your comments lead me to this question: http://stackoverflow.com/questions/12002542/firefox-addon-ignore-iframes and I guess I have to try to solve it this way. If you want you can put an answer and I'll vote it. Chrome extensions don't do that, I thought it would be the same, thank you :) – Kev May 12 '14 at 07:19

1 Answers1

2

I just finished asking the same question, for some reason multiple searches didn't lead me to this question until now.

The link you posted concerning iFrames lead me to this solution, which seems to be working well.

In Firefox, iFrames are still Pages, and by default the SDK doesn't discriminate between iFrames and top Pages, causing content scripts to attach to ANY loaded page ( or iFrame ) that meets your pageMod 'match' requirements. Rather than use page-mod, you can use tabs to inject the scripts and data you need.

var data = require("sdk/self").data;
var tabs = require('sdk/tabs');

tabs.on('ready', function(tab) {
     var worker = tab.attach({
          contentScriptOptions: {},
          contentScriptFile: [data.url('myScript.js')]
     });

     // now set up your hooks:        
     worker.port.on('someKey', function(data) {
          //do whatever with your data
     });

});

Alternatively, you can modify the behavior of PageMod to only apply to the top page, which will prevent it from running in any iFrames on the page.

var data = require("sdk/self").data;
var pageMod = require('sdk/page-mod');

pageMod.PageMod({
    match: [*],
    attachTo: ["top"],
    contentScriptOptions: {},
    contentScriptFile: [data.url('myScript.js')],
    onAttach: function(worker) {
        //function body
    }
});

More details on how to further control page-mod behavior can be found in their API docs

BrMcMullin
  • 1,261
  • 2
  • 12
  • 28
  • Hi. Thanks for the answer. I also did this. But the question was **why** it would run multiple times. If you can complete your answer with the reason (what @nmaier said actually), I'll accept it. – Kev Oct 20 '14 at 13:11