Skip to content
This repository has been archived by the owner on Feb 26, 2022. It is now read-only.

Privileged object export

ZER0 edited this page Feb 13, 2013 · 11 revisions

COW and createObjectIn

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.

Where do we need this?

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

The new and shiny API

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);

The options object:

  • clientGlobal: the global object of the target compartment (content window usually)
  • 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.

Do ask questions and tell me about your ideas!

https://etherpad.mozilla.org/cvbBmdFNXX