Reputation: 705
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.
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.
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.
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
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
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