Reputation: 705
I have encountered undocumented behaviour in an SDK extension I am currently working on and would appreciate help from the community to find either a fix or a way around it.
The problem only occurs when an HTML page embedded in the extension is opened in a tab, like so:
tabs.open(data.url("html/test.html"));
Note that test.html
above would reside in data/html
from the extension's root directory.
I'm injecting a content script and listening for messages emitted as given below:
tabs.once("open", function (tab) {
var w = tab.attach({ contentScriptFile: [ data.url("js/embed.js") ]});
w.port.once("init", function () {
console.log("content script initialised");
});
});
The content script, data/js/embed.js
, contains the following:
console.log("attaching embedded script");
self.port.emit("init");
The problem is that if the content script is attached to a data HTML page (a page embedded in the extension), messages sent by the content script are suppressed.
It is absolutely crucial that my extension opens an embedded HTML page and is able to both receive from and send messages to the extension. How can I overcome this limitation?
I've created a tiny extension that reproduces the problem clearly. You can find it here.
Upvotes: 1
Views: 71
Reputation: 705
The answer, as pointed out here, is to emit the message in the ready
event (and not open
).
Upvotes: 1
Reputation: 705
Found a way of circumventing the limitation but it's rather hacky. It consists of grabbing the content window object of the tab and then relying on the Window's postMessage
API. Like so:
var tabs = require("sdk/tabs"),
self = require("sdk/self"),
data = self.data,
utils = require("sdk/tabs/utils"),
{viewFor} = require("sdk/view/core");
tabs.once("ready", function (tab) {
var window = utils.getTabContentWindow(viewFor(tab));
window.addEventListener("message", function (ev) {
console.log("message received: ", ev.data);
});
});
tabs.open(data.url("html/test.html"));
Then in a script loaded by the HTML page, one would do something similar to:
window.postMessage({ method: "init", state: true }, origin);
I would still like to know why one can't use the native self.port.emit
API though? Or why it quietly suppresses attempts at emitting messages.
Upvotes: 0