Components.utils.exportFunction 编辑
This function provides a safe way to expose a function from a privileged scope to a less-privileged scope. In this way privileged code, such as an extension, can share code with less-privileged code like a normal web page script. A function exported from privileged to less-privileged code can be called from the less privileged code's context.
The function has access to its surrounding closure just as if it were being called in the privileged context.
The exported function does not have to be added to the less privileged code's global window object: it can be exported to any object in the target scope.
exportFunction()
is made available as a global in sandboxes which have the wantExportHelpers
option set in the Sandbox()
constructor. This includes Add-on SDK content scripts.
To understand what happens if the functions you export accept arguments, see Exporting functions that take arguments below.
Syntax
Components.utils.exportFunction(func, targetScope[, options]);
Parameters
func : function
- The function to export.
targetScope : object
- The object to attach the function to. This does not have to be the global window object: it could be any other object in the target window, or an object created by the caller.
options : object
- Optional parameter that supplies additional options. The following options are currently defined:
defineAs
: determines the name of the function intargetScope
. If this is omitted, you need to assign the return value ofexportFunction()
to an object in the target scope.allowCallbacks
: deprecated/redundant from Firefox 34. This option allows the exported function to accept callbacks as arguments. Boolean, defaulting tofalse
. This option is new in Firefox 33. From Firefox 34 onwards this option has no effect: the exported function is always able to accept callbacks as arguments.allowCrossOriginArguments
: do not check that arguments to the exported function are subsumed by the caller: this allows the caller to pass objects with a different origin into the exported function, which can then use its privileged status to make cross-origin requests with them. Boolean, defaulting tofalse
. This option is new in Firefox 34.
Returns
The placeholder function which has been created in the target context.
Exporting functions that take arguments
Until Firefox 34, any arguments that the function takes are structured-cloned across the security boundary unless they are native objects such as DOM nodes. Because structured cloning does not clone functions, this meant that the function may not return a function, and by default, may not take any functions as arguments. However, in Firefox 33, you could use the allowCallbacks
option to enable the function to accept callbacks.
From Firefox 34 onwards, any arguments passed into the function are not cloned. Instead, they are passed through to the privileged scope as Xrays.
Modifying the argument
While cloning creates a copy of an object, an Xray for an object refers to the original, so any changes to the argument that are made in the exported function will affect the original object that was passed in:
// privileged scope: for example, a content script
function changeMyName(user) {
user.name = "Bill";
}
exportFunction(changeMyName, contentWindow, {
defineAs: "changeMyName"
});
// less-privileged scope: for example, a page script
var user = {name: "Jim"};
var test = document.getElementById("test");
test.addEventListener("click", function() {
console.log(user.name); // "Jim"
window.changeMyName(user);
console.log(user.name); // "Bill"
}, false);
Note that this is subject to the normal rules of Xrays: for example, an expando property added to a DOM node will not be visible in the original object.
Xray filtering and waiving
Xrays provide a filtered view of the original object. For the full details refer to the documentation for Xray vision, but for example: functions are not visible in the Xrays of JavaScript Object
types. If you need unfiltered access to the original, you can waive Xrays:
// privileged scope: for example, a content script
function logUser(user) {
// console.log(user.getUser()); // error
console.log(user.wrappedJSObject.getUser()); // "Bill"
}
exportFunction(logUser, contentWindow, {
defineAs: "logUser"
});
// less-privileged scope: for example, a page script
var user = {getUser: function() {return "Bill";}}
var test = document.getElementById("test");
test.addEventListener("click", function() {
window.logUser(user);
}, false);
Passing functions as arguments
If functions are given as arguments, these are also passed as Xrays. Because you can call Function
Xrays just like normal functions, this means that passing callbacks into the exported function just works, making the allowCallbacks
option redundant:
// privileged scope: for example, a content script
function logUser(getUser) {
console.log(getUser()); // "Bill"
}
exportFunction(logUser, unsafeWindow, {
defineAs: "logUser"
});
// less-privileged scope: for example, a page script
function getUser() {
return "Bill";
}
var test = document.getElementById("test");
test.addEventListener("click", function() {
window.logUser(getUser);
}, false);
Cross-origin checking
When the exported function is called each argument, including this
, is checked to make sure that the caller subsumes that argument. This prevents passing cross-origin objects (like Window
or Location
) to privileged functions, since the privileged code will have full access to those objects and might unintentionally do something dangerous. This provision can be overridden by passing { allowCrossOriginArguments: true }
to exportFunction
.
Example
Export to global scope
This add-on script defines a function, then exports it to a content window:
// addon-script.js
var salutation = "hello ";
function greetme(user) {
return salutation + user;
}
Components.utils.exportFunction(greetme, contentWindow, {defineAs: "foo"});
Instead of using defineAs
, the script can assign the result of exportFunction
to an object in the target scope:
// addon-script.js
var salutation = "hello ";
function greetme(user) {
return salutation + user;
}
contentWindow.foo = Components.utils.exportFunction(greetme, contentWindow);
Either way, code running in the content window's scope can now call the function:
// page-script.js
var greeting = foo("alice");
console.log(greeting);
// "hello alice"
Export to an existing local object
Instead of attaching the function to the target's global window
object, the caller can attach it to any other object in the target context. Suppose the content window defines a local variable bar
:
// page-script.js
var bar = {};
Now the add-on script can attach the function to bar
:
// addon-script.js
Components.utils.exportFunction(greetme, contentWindow.bar, {defineAs: "greetme"});
// page-script.js
var value = bar.greetme("bob");
console.log(value);
// "hello bob"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论