By default, content scripts don't have any cross-domain privileges. In particular, they can't:
- access content hosted in an
iframe
, if that content is served from a different domain - make cross-domain XMLHttpRequests
However, you can enable these features for specific domains by adding them to your add-on's package.json under the "cross-domain-content"
key, which itself lives under the "permissions"
key:
"permissions": {
"cross-domain-content": ["http://example.org/", "http://example.com/"]
}
- The domains listed must include the scheme and fully qualified domain name, and these must exactly match the domains serving the content - so in the example above, the content script will not be allowed to access content served from
https://example.com/
. - Wildcards are not allowed.
- This feature is currently only available for content scripts, not for page scripts included in HTML files shipped with your add-on.
Cross-domain iframes
The following "main.js" creates a page-worker which loads a local HTML file called "page.html", attaches a content script called "page.js" to the page, waits for messages from the script, and logs the payload.
//main.js
var data = require("sdk/self").data;
var pageWorker = require("sdk/page-worker").Page({
contentURL: data.url("page.html"),
contentScriptFile: data.url("page-script.js")
});
pageWorker.on("message", function(message) {
console.log(message);
});
The "page.html" file embeds an iframe whose content is served from "http://en.m.wikipedia.org/":
<!DOCTYPE html>
<!-- page.html -->
<html>
<head></head>
<body>
<iframe id="wikipedia" src="http://en.m.wikipedia.org/"></iframe>
</body>
</html>
The "page-script.js" file locates "Today's Featured Article" and sends its content to "main.js":
// page-script.js
var iframe = window.document.getElementById("wikipedia");
var todaysFeaturedArticle = iframe.contentWindow.document.getElementById("mp-tfa");
self.postMessage(todaysFeaturedArticle.textContent);
For this to work, we need to add the "cross-domain-content"
key to "package.json":
"permissions": {
"cross-domain-content": ["http://en.m.wikipedia.org/"]
}
The add-on should successfully retrieve the iframe's content.
Cross-domain XMLHttpRequest
The following add-on creates a panel whose content is the summary weather forecast for Shetland. If you want to try it out, you'll need to register and get an API key.
The "main.js":
- creates a panel whose content is supplied by "panel.html" and adds a content script "panel-script.js" to it
- sends the panel a "show" message when it is shown
- adds a button which shows the panel when it is clicked
// main.js
var data = require("sdk/self").data;
var forecast_panel = require("sdk/panel").Panel({
height: 50,
contentURL: data.url("panel.html"),
contentScriptFile: data.url("panel-script.js")
});
forecast_panel.on("show", function(){
forecast_panel.port.emit("show");
});
require("sdk/ui/button/action").ActionButton({
id: "get-forecast",
label: "Get the forecast",
icon: "./icon-16.png",
onClick: function() {
forecast_panel.show();
}
});
The "panel.html" just includes a <div>
block for the forecast:
<!DOCTYPE html>
<!-- panel.html -->
<html>
<head></head>
<body>
<div id="forecast_summary"></div>
</body>
</html>
The "panel-script.js" uses XMLHttpRequest to fetch the latest forecast:
// panel-script.js
var url = "http://datapoint.metoffice.gov.uk/public/data/txt/wxfcs/regionalforecast/json/500?key=YOUR-API-KEY";
self.port.on("show", function () {
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.onload = function () {
var jsonResponse = JSON.parse(request.responseText);
var summary = getSummary(jsonResponse);
var element = document.getElementById("forecast_summary");
element.textContent = summary;
};
request.send();
});
function getSummary(forecast) {
return forecast.RegionalFcst.FcstPeriods.Period[0].Paragraph[0].$;
}
Finally, we need to add the "cross-domain-content"
key to "package.json":
"permissions": {
"cross-domain-content": ["http://datapoint.metoffice.gov.uk"]
}
Content Permissions and unsafeWindow
If you use "cross-domain-content"
, then JavaScript values in content scripts will not be available from pages. Suppose your content script includes a line like:
// content-script.js:
unsafeWindow.myCustomAPI = function () {};
If you have included the "cross-domain-content"
key, when the page script tries to access myCustomAPI
this will result in a "permission denied" exception.