This function provides a safe way to take an object defined in a privileged scope and create a structured clone of it in a less-privileged scope. It returns a reference to the clone:
var clonedObject = cloneInto(myObject, targetWindow);
You can then assign the clone to an object in the target scope as an expando property, and scripts running in that scope can access it:
targetWindow.foo = clonedObject;
In this way privileged code, such as an add-on, can share an object with less-privileged code like a normal web page script.
Components.utils.cloneInto(obj, targetScope[, options]);
obj : object
targetScope : object
options : object
cloneFunctions
: a Boolean value that determines if functions should be cloned. If omitted the default value is false
. Cloned functions have the same semantics as functions exported using Components.utils.exportFunction
. See Cloning objects that have functions below.wrapReflectors
: a Boolean value that determines if objects reflected from C++, such as DOM objects, should be cloned. If omitted the default value is false
. See Cloning objects that contain DOM elements below.A reference to the cloned object.
This add-on script creates an object, clones it into the content window and makes it a property of the content window global:
// add-on script var addonScriptObject = {"greeting" : "hello from add-on"}; contentWindow.addonScriptObject = cloneInto(addonScriptObject, contentWindow);
Scripts running in the page can now access the object:
// page script button.addEventListener("click", function() { console.log(window.addonScriptObject.greeting); // "hello from add-on" }, false);
Of course, you don't have to assign the clone to the window itself: you can assign it to some other object in the target scope:
contentWindow.foo.addonScriptObject = cloneInto(addonScriptObject, contentWindow);
You can also pass it into a function defined in the page script. Suppose the page script defines a function like this:
// page script function foo(greeting) { console.log("they said: " + greeting.message); }
The add-on script can define an object, clone it, and pass it into this function:
// add-on script var addonScriptObject = {"message" : "hello from add-on"}; contentWindow.foo(cloneInto(addonScriptObject, contentWindow)); // "they said: hello from add-on"
If the object to be cloned contains functions, you must pass the {cloneFunctions:true}
flag or you'll get an error. If you do pass this flag, then functions in the object are cloned using the same mechanism as that used in Components.utils.exportFunction
:
// add-on script var addonScriptObject = { greetme: function() { alert("hello from add-on"); } }; contentWindow.addonScriptObject = cloneInto(addonScriptObject, contentWindow, {cloneFunctions: true});
// page script var test = document.getElementById("test"); test.addEventListener("click", function() { window.addonScriptObject.greetme(); }, false);
By default, if the object you clone contains objects that are reflected from C++, such as DOM elements, the cloning operation will fail with an error. If you pass the {wrapReflectors:true}
flag, then the object you clone is allowed to contain these objects:
// add-on script var addonScriptObject = { body: contentWindow.document.body }; contentWindow.addonScriptObject = cloneInto(addonScriptObject, contentWindow, {wrapReflectors: true});
// page script var test = document.getElementById("test"); test.addEventListener("click", function() { console.log(window.addonScriptObject.body.innerHTML); }, false);
Access to these objects in the target scope is subject to the normal security checks.