简体   繁体   中英

ContentScript in Firefox extension without using the Add-On SDK

Is there an easy way to create a Firefox extension for a simple content script WITHOUT having to use the Add-On SDK and PageMod? It really seems overkill to go through the hassle of installing Python and the SDK, learning how to use the SDK and API, and adding unnecessary bloat and abstraction layers, just to execute a simple content script.

I already tried using a XUL browser overlay and injecting the scripts there, but having everything injected in the browser.xul context instead of document.body is also adding a lot of complexity...

So what's the easiest, lightweight way to inject a few scripts and css files in the html document instead of the XUL document?

Your guestion is border-line too broad, so I won't be discussing everything in detail but give a general overview.

Easy might be an overstatement, but SDK content scripts (and actually modules too), Greasemonkey/Scriptish and everything else that resembles a content script uses Sandbox internally. Even bootstrap.js in restartless add-ons are executed in a sandbox.

The basic idea is the following:

  1. Get a reference to the content window you want to attach too.
  2. Choose a "principal" the script should run under. The principal is essentially the security context/policy that also defines the same origin. An unprivileged content script would usually use the content window itself (which is a principal too), while a privileged script (chrome access to Components ) script would use the system principal.
  3. Choose if you want XRay wrappers. The docs tell you more about it.
  4. Choose the Sandbox prototype (the "global" or top-level this). Usually for content script stuff you'll choose the content window.
  5. Create the Sandbox .
  6. Add any stuff your content script may need to the Sandbox.
  7. Execute a script by either evalInSandbox or the subscript loader .

Here is a limited example adding an unprivileged content script to a window:

// 1. get the content window, e.g. the currently selected tab window
var contentWindow = gBrowser.contentWindow;
// 2. Choose the principal, e.g. just use the content window again
var principal = contentWindow;
// 3. We want XRay wrappers, to keep our content script and the actual
// page scripts in their own corners.
var wantXrays = true;
// 4. Our prototype will be the window
var sbProto = contentWindow;
// 5. Putting it all together to create a sandbox
var sandbox = Cu.Sandbox(principal, {
  sandboxPrototype: sbProto,
  wantXrays: wantXrays
});
// 6. Adding a random helper function (e.g.)
sandbox.getRandomInt = function (min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
};
// 7. Execute some content script, aka. the stupid example.
try {
  var execute = function() {
    var demo1 = document.querySelector('title').textContent;
    var demo2 = getRandomInt(1, 1000);
    alert(demo1 + " " + demo2);
  }
  Cu.evalInSandbox(
    "(" + execute.toSource() + ")()",
    sandbox
  );
} catch(ex) {
  console.error(ex);
}

PS: This example will run verbatim in a Scratchpad with Environment/Browser .

Regarding styles:

Do what the SDK does, I guess, which is simplified:

var wu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).
         getInterface(Ci.nsIDOMWindowUtils);
var uri = Services.io.newURI(
  "chrome://myaddon/style/content-style.css",
  null,
  null);
wu.loadSheet(uri, wu.USER_SHEET);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM