XPConnect Chrome Object Wrappers: Difference between revisions

m
__exposedProps__ should use colon, not equal sign
(added section on compliance tests)
m (__exposedProps__ should use colon, not equal sign)
 
(15 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{draft}}
== Current Status ==
COWs landed on mozilla-central at the end of September 2009. They were also approved for Gecko 1.9.2 (Firefox 3.6) and landed on its trunk on October 6, 2009.
As of October 16, 2009, however, it is still not possible for chrome-privileged script to create COWs—that is, COWs still need to be automatically created when passing through a trust boundary.  Furthermore, there are a number of TODOs in this specification that are still in the process of being resolved. All of these are currently considered bugs in the implementation, and any fixes to them will automatically propagate to Firefox 3.6.
== Introduction ==
== Introduction ==


Line 21: Line 29:
   /* Do something here that requires chrome privileges. */
   /* Do something here that requires chrome privileges. */
}
}
foo.__callableByContent__ = true;


var sandbox = Cu.Sandbox("http://www.mozilla.org");
var sandbox = Cu.Sandbox("http://www.mozilla.org");
sandbox.foo = foo;
sandbox.foo = foo;
var result = Cu.evalInSandbox("foo({bar: 5});");
var result = Cu.evalInSandbox("foo({bar: 5});", sandbox);
</pre>
</pre>


In the above example, <tt>foo()</tt> is wrapped by a COW when accessed by sandboxed code executed via <tt>Components.utils.evalInSandbox()</tt>.  The object <tt>{bar: 5}</tt> is wrapped in an <tt>XPCSafeJSObjectWrapper</tt> before being passed into <tt>foo()</tt>.
In the above example, <tt>foo()</tt> is wrapped by a COW when accessed by sandboxed code executed via <tt>Components.utils.evalInSandbox()</tt>.  The object <tt>{bar: 5}</tt> is wrapped in an <tt>XPCSafeJSObjectWrapper</tt> before being passed into <tt>foo()</tt>.
The metadata attached to <tt>foo()</tt>, <tt>__callableByContent__</tt>, is used to explicitly declare that the function its attached to can be called from content.  This is necessary for security purposes; if a function that's only ever intended to be called from trusted code ever accidentally "falls into the wrong hands", we don't want untrusted code to be able to exploit it.
'''TODO:''' What kind of exception should be raised when a function without <tt>__callableByContent__</tt> is called from content?  Or should it be a null-op and thus fail silently?


=== COWing Objects ===
=== COWing Objects ===


By default, Chrome objects passed into content space are completely opaque: no information can be accessed from them, and no properties can be defined on them.
By default, non-function Chrome objects passed into content space are completely opaque: no information can be accessed from them, and no properties can be defined on them.


'''TODO:''' What happens on read/write of properties on such objects? Is an exception raised, or do all reads simply return <tt>undefined</tt> and are all writes null-ops?
When a non-writable property is written to, a security exception will be raised. However, when a non-readable property is accessed, its value is <tt>undefined</tt>: a security exception isn't thrown because we don't want to break code that relies on [http://en.wikipedia.org/wiki/Duck_typing duck typing].


Individual properties can be exposed by defining a <tt>__exposedProps__</tt> property on the object, like so:
To bypass this default behavior, individual properties can be exposed by defining a <tt>__exposedProps__</tt> property on the object, like so:


<pre class="brush:js;">
<pre class="brush:js;">
Line 46: Line 49:


var MyObj = {
var MyObj = {
   __exposedProps__ = {foo: "r", bar: "rw"},
   __exposedProps__: {foo: "r", bar: "rw"},


   foo: function foo(obj) {
   foo: function foo(obj) {
Line 56: Line 59:
   baz: "I am protected information"
   baz: "I am protected information"
}
}
</pre>
In the above example, <tt>MyObj.foo()</tt> can be accessed but not assigned to, <tt>foo()</tt> itself is callable from content, and <tt>MyObj.bar</tt> is both readable and writable, while <tt>MyObj.baz</tt> can't be accessed at all.


MyObj.foo.__callableByContent__ = true;
All properties that are exposed to content are enumerable by content as well.
</pre>
 
Getters and setters on exposed properties are automatically called as necessary.


In the above example, <tt>MyObj.foo()</tt> can be accessed but not assigned to&mdash;and <tt>foo()</tt> itself is callable from content, since <tt>__callableByContent__</tt> is set&mdash;and <tt>MyObj.bar</tt> is both readable and writable, while <tt>MyObj.baz</tt> can't be accessed at all.
If an exposed property is writable by content, it is deletable by content as well.


'''TODO:''' What should the default <tt>toString()</tt> method of a COW'ed object with no metadata yield?
'''TODO:''' What should the default <tt>toString()</tt> method of a COW'ed object with no metadata yield?


'''TODO:''' Does this work okay with getters and setters?
'''TODO:''' Discuss what to do with native objects that get exposed (like the Sidebar object).


== Compliance Tests ==
== Compliance Tests ==


'''TODO:''' Write a compliance test suite. It should allow us to implement COWs in C++ as well as in JS (via [[Labs/Jetpack/Binary_Components#Flexible_Membrane_Functionality|Flexible Membranes]]) using test-driven development.
A suite of compliance tests for the metadata functionality of COWs can be found at:
 
  http://hg.mozilla.org/users/avarma_mozilla.com/cow-exposed-info/
 
This suite uses the JSAPI, and is independent of XPCOM and XPConnect.
 
== Related Patches ==
 
A Mercurial patch queue containing an in-progress COW test suite that patches against mozilla-central can be found here:
 
  http://hg.mozilla.org/users/avarma_mozilla.com/cow-patches/
 
== Related Bugzilla Bugs ==
 
* [https://bugzilla.mozilla.org/show_bug.cgi?id=518991 518991 - COWs should only expose certain properties]
* [https://bugzilla.mozilla.org/show_bug.cgi?id=522764 522764 - COWs need tests]
1

edit