migdsb
migdsb

Reputation: 705

How to open an addon page in Firefox?

I'm developing a Firefox (SDK) addon that, at some point, needs to open an internal page (so resource://<addon_id>/data/path/to/some_page.html) and still be able to retain the ability to communicate with the addon.

Here are the strategies I've employed so far but which have all failed.

  1. Open a new tab using sdk/tabs.open and hope that, since it's an internal page, self.port is available in the page's context to the scripts and they can both listen and emit messages. Didn't work -- self isn't available at all.

  2. Open a new tab using sdk/tabs.open and inject a content script. self this time is available, however no messages are sent to or received from the addon. This seems to be some sort of security measure. Interestingly the failure to send or receive messages is silent and thus there are no messages dumped to the console.

  3. Open a new tab using sdk/tabs.open, gain direct access to the tab's (DOM) window object and send/receive messages via the window.postMessage API. This seems to require invoking getBrowserForTab and then accessing contentWindow.wrappedJSObject. However, invoking getBrowserForTab in the onOpened handler of the sdk/tabs.open call returns undefined.

I'm stuck.

It seems I'd have a much easier time implementing this with a panel but alas this strategy isn't available to me as the page needs to be modeless. How can this be achieved?

Upvotes: 2

Views: 211

Answers (2)

ZER0
ZER0

Reputation: 25332

Open a new tab using sdk/tabs.open and inject a content script. self this time is available, however no messages are sent to or received from the addon. This seems to be some sort of security measure. Interestingly the failure to send or receive messages is silent and thus there are no messages dumped to the console.

This method should works, could you provide some code and Firefox version / jpm version etc? Your code should looks like:

require("sdk/tabs").open({
  url: "./page.html",
  onReady(tab) {
    let worker = tab.attach({
      contentScriptFile: "./content.js"
    });
    // send and received stuff using `worker.port`
  }
});

You could also use page-mod for that:

const { data: { url } } = require("sdk/self");

require("sdk/page-mod").PageMod({
  include: url("./page.html"),
  contentScriptFile: "./content.js",
  onAttach(worker) {
    // send and received stuff using `worker.port`
  }
});

// if you want to open the page in a tab immediately
require("sdk/tabs").open("./page.html");

The main advantage using page-mod, is that it works even if the page is not opened by the add-on (so, if the user bookmark the URL or enter the URL manually in a tab, etc).

I tried both version, and with a content.js with both self.port.on and self.port.emit it works as expected – just bouncing a text message.

Upvotes: 3

Noitidart
Noitidart

Reputation: 37318

Just load type that resource url to the browser and it loads. To communicate you can do contentWindow.wrappedJSObject but try to use messages, its better. I personally use observer service. You can even have your addon page tap into your addon scope with this method: https://gist.github.com/yajd/17ee5b1b98cb717c8429 Don't go the panel way, html pages are the best thats how i do it. https://github.com/Noitidart/l10n/tree/xhtml-xul actually use xhtml so you can localize it

Upvotes: 0

Related Questions