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": ["https://example.org/", "https://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 "https://en.m.wikipedia.org/":
<!DOCTYPE html> <!-- page.html --> <html> <head></head> <body> <iframe id="wikipedia" src="https://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": ["https://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 = "https://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": ["https://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.