Join MDN and developers like you at Mozilla's View Source conference, 12-14 September in Berlin, Germany. Learn more at https://viewsourceconf.org

Cross-domain Content Scripts

By default, content scripts don't have any cross-domain privileges. In particular, they can't:

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.

Document Tags and Contributors

 Contributors to this page: wbamberg, Brettz9, erxin, evold
 Last updated by: wbamberg,