-
Notifications
You must be signed in to change notification settings - Fork 263
Privileged object export
When a pure JavaScript object needed to be exposed from privileged scope to content, because of the flexibility of the language it is really difficult to do it in a safe way. There were two API so far for this, one is COW, which is a filtering wrapper, with the clumsy exposedProps property and with various hacks in it's implementation around it's prototype chain.
And the createObjectIn / makeObjectPropsNormal function pair. This later API enabled one to create an object in the content compartment and then add safe privileged methods bound to the (privileged) object to be exposed.
COWs turned out to have a lot of problems, the old version with security the newer one with the prototype chain trick fixed that issue but had some other problems with the js engine in some edge cases. So it will be deprecated. The other API is quite difficult to use really, and has it's own issues. Since for jetpack a well designed API that is reliable is needed we came up with a 3rd version that is somewhat closer to the createObjectIn / makeObjectPropsNormal version.
This API is going to be needed for:
- every content-script that wants to expose JS Object to content
- modules want to expose JS object to content or content-script
Before I define the API I try to explain the concept in a nutshell. The API creates two constructor. One is accessible from privileged code, and one optional that is accessible from content side. Calling each will execute both, and will create two objects that are linked under the hood. One on privileged side and one on content side. I will call these objects privileged view and content view for now. By linked I mean if we access it from privileged scope we will get the privileged view of the object if we access it from content scope we will get the content view. There will be an array of privileged methods which will be installed on the content view, but will be executed in privileged scope (which means the this object will be the privileged view).
The API could use some name changes...
Cu.defineClientAPI(options); Options object: (required) clientGlobal: hostConstructor: constructor code for host-side objects clientConstructor: toSourced()/eval-ed constructor code for client-side objects clientConstructorName: optional name. If given, client-side constructor will be defined on client global. hostPrototype: prototype for host-side objects clientPrototype: structured cloned into content, used as prototype for client-side objects clientAPI: {prop: { getter: foo, setter: bar}, prop: {value: func; }} * Privileged functions that get defined on client-side prototype. * When invoked, run in host, with host-side object as |this| * These functions in their client-side form require a bonafide client object to operate.
Finally there is a simplified version for cloning object into the other compartment: Cu.cloneInto(global, object); This version only does a structured cloning into the other compartment, without any privileged methods, or tricks. It's almost like passing by JSON. Personally I don't find this one very interesting.