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:
- Get a reference to the content window you want to attach too.
- 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.
- Choose if you want XRay wrappers. The docs tell you more about it.
- Choose the Sandbox prototype (the "global" or top-level this). Usually for content script stuff you'll choose the content window.
- Create the
Sandbox.
- Add any stuff your content script may need to the Sandbox.
- 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);