User:Mrbkap

  • Revision slug: User:Mrbkap
  • Revision title: User:Mrbkap
  • Revision id: 180555
  • Created:
  • Creator: Jst
  • Is current revision? No
  • Comment /* XPCNativeWrapper */

Revision Content

Status of wrappers in XPConnect.

Purpose of this document

Developers in the know understand that wrappers play a large role in XPConnect, and that we have a lot of them. Less informed developers understand that wrappers exist and are somehow important, but they don't know when they should use what wrappers, or if they should be seeing a wrapper. This document will serve as a high level overview to wrappers.

Types of Wrappers

Base Wrappers

XPCWrappedNative

These wrappers are created when any natively implemented object (that is, any object implemented in C++) needs to be reflected into JavaScript. This includes all DOM objects (including Window) and chrome elements that are reflected into JavaScript. This wrapper is responsible for mapping calls from JavaScript into C++. This means that when you say window.focus(), you're calling into XPCWrappedNative code. They are implicitly created by XPConnect and you should not have to worry about how that happens. There are several types of wrapped natives, but I won't cover those here.

XPCWrappedJS

These wrappers are the exact opposite of XPCWrappedNative. They exist to reflect an object from JavaScript into C++. This means that whenever you pass your JavaScript object into a C++ function, we create one of these wrappers. For example, if you've implemented some component with an interface nsIFoo and you pass your JavaScript object into a C++ function taking an nsIFoo, an XPCWrappedJS is created around your object. C++ calls are routed through XPCWrappedJS code into your JavaScript implementation. These wrappers are created by XPConnect, so you should not have to worry about how to construct them or whether to construct them.

Wrapper Wrappers

Here is where things start to get hairy. The previous two wrappers only wrap a single object, the C++ or JavaScript object that they are reflecting (Note: this isn't quite true, see the section below on double-wrapping). The following wrappers all wrap other JavaScript objects and do various things with them.

XPCNativeWrapper

This was the first wrapper wrapper. It will only wrap XPCWrappedNatives, and will throw an exception if it is asked to wrap any other type of JavaScript object (see the section about double wrapping for more information about this statement). XPCNativeWrappers are designed to protect the user from the dynamicism that JavaScript provides. For example, given the code someAnchor.href = "http://www.mozilla.com" some evil code might run during the someAnchor call to prevent it from working correctly. If someAnchor is wrapped by an XPCNativeWrapper, this will not happen. The wrapper will always perform the original action, as defined by idl (or convention in the case of DOM0 behavior). XPCNativeWrappers are implicitly created by XPConnect for chrome JavaScript or JavaScript components, whenever they access content (less privileged) objects. They can also be created by using new XPCNativeWrapper(wrappedNative). "Expando" properties, not defined in idl, but created by the wrapped object are not visible through this wrapper.

XPCSafeJSObjectWrapper

This wrapper was created to address some problems with XPCNativeWrapper. In particular, some extensions want to be able to safely access non-natively-implemented content defined objects (and to access the underlying under an XPCNativeWrapper without its strong behavior guarantees). XPCSJOW act as a buffer between the chrome code. Note: Because any type of object can be wrapped here, there is no predefined behavior. The only guarantee here is that untrusted code will run in an untrusted context. In particular, the underlying object might act entirely differently from what is expected. Safe JSObject wrappers are implicitly created in some circumstances. All properties are visible through this wrapper.

XPCCrossOriginWrapper

The cross origin wrapper, or XOW, was recently implemented in order to broker access between web sites. This wrapper is implicitly created by XPConnect. All access checks happen in XOW code. If a XOW wrapper happens to wrap an object that is from the same origin as the running code, it acts like the Safe JSObject wrapper and it is possible to do anything to the XOW that you would do with any JS object. If the underlying object is not accessible, then it acts like an XPCNativeWrapper, meaning that it allows access to all APIs and behaviors provided by idl, overriding whatever the other site might have done.

What Wrappers Should I Use

Alright, you've skimmed the above and now you want to write some code! What wrappers should you use?

Chrome Code (extensions, etc)

As mentioned above, XPCWrappedNative and XPCWrappedJS wrappers are created implicitly, you should never have to worry about them. Likewise, if you are writing an extension or chrome code that never touches content code, you don't have to worry about wrappers.

However, most extensions do touch content in some way. If you do touch content (via its window, for example) you should always get an XPCNativeWrapper. If you don't, then you have found a bug. See the documentation on XPCNativeWrapper for more information about its use.

If you need more access to an object or need to access a content defined object that is implemented in JS or otherwise not available through an idl interface, then you should be using XPCSafeJSObjectWrappers. At the moment, you can either get one through XPCNativeWrapper.wrappedJSObject or by explictly writing new XPCSafeJSObjectWrapper(object). Note, however, that I'm looking into implicitly creating these wrappers in all relevant cases and removing the visible constructor.

Content Code (a webpage)

As has always been the case, content code should not have to worry about wrappers or wrapping. Especially with the advent of XOWs, if you write code that conforms to the security restrictions imposed by the browser, you should not have to worry about wrappers. This does not mean that you can ignore security, think of XOWs like a safety belt, they will try to protect you, but you can still get in an accident.

Details

I mentioned double wrapping before, and I want to mention it again before I go. Double wrapping is the one case where an XPCWrappedNative wraps another object -- this case is where a JS object was passed in via some IDL-declared interface, creating an XPCWrappedJS, and is now being returned to JavaScript via some other interface. In order to preserve API compatibility, an XPCWrappedNative is created around the XPCWrappedJS.

Revision Source

<p>Status of wrappers in XPConnect.
</p>
<h2 name="Purpose_of_this_document"> Purpose of this document </h2>
<p>Developers in the know understand that wrappers play a large role in XPConnect, and that we have a lot of them.  Less informed developers understand that wrappers exist and are somehow important, but they don't know when they should use what wrappers, or if they should be seeing a wrapper. This document will serve as a high level overview to wrappers.
</p>
<h2 name="Types_of_Wrappers"> Types of Wrappers </h2>
<h3 name="Base_Wrappers"> Base Wrappers </h3>
<h4 name="XPCWrappedNative"> XPCWrappedNative </h4>
<p>These wrappers are created when any natively implemented object (that is, any object implemented in C++) needs to be reflected into JavaScript. This includes all DOM objects (including Window) and chrome elements that are reflected into JavaScript. This wrapper is responsible for mapping calls <i>from</i> JavaScript <i>into</i> C++. This means that when you say <code>window.focus()</code>, you're calling into XPCWrappedNative code. They are implicitly created by XPConnect and you should not have to worry about how that happens. There are several types of wrapped natives, but I won't cover those here.
</p>
<h4 name="XPCWrappedJS"> XPCWrappedJS </h4>
<p>These wrappers are the exact opposite of XPCWrappedNative. They exist to reflect an object <i>from</i> JavaScript <i>into</i> C++. This means that whenever you pass your JavaScript object into a C++ function, we create one of these wrappers. For example, if you've implemented some component with an interface nsIFoo and you pass your JavaScript object into a C++ function taking an nsIFoo, an XPCWrappedJS is created around your object. C++ calls are routed through XPCWrappedJS code into your JavaScript implementation. These wrappers are created by XPConnect, so you should not have to worry about how to construct them or whether to construct them.
</p>
<h3 name="Wrapper_Wrappers"> Wrapper Wrappers </h3>
<p>Here is where things start to get hairy. The previous two wrappers only wrap a single object, the C++ or JavaScript object that they are reflecting (Note: this isn't quite true, see the section below on double-wrapping). The following wrappers all wrap other JavaScript objects and do various things with them.
</p>
<h4 name="XPCNativeWrapper"> XPCNativeWrapper </h4>
<p>This was the first wrapper wrapper. It will only wrap XPCWrappedNatives, and will throw an exception if it is asked to wrap any other type of JavaScript object (see the section about double wrapping for more information about this statement). XPCNativeWrappers are designed to protect the user from the dynamicism that JavaScript provides. For example, given the code <code>someAnchor.href = "http://www.mozilla.com"</code> some evil code might run during the someAnchor call to prevent it from working correctly. If someAnchor is wrapped by an XPCNativeWrapper, this will not happen.  The wrapper will always perform the original action, as defined by idl (or convention in the case of DOM0 behavior).  XPCNativeWrappers are implicitly created by XPConnect for chrome JavaScript or JavaScript components, whenever they access content (less privileged) objects. They can also be created by using <code>new XPCNativeWrapper(wrappedNative)</code>.  "Expando" properties, not defined in idl, but created by the <i>wrapped</i> object are not visible through this wrapper.
</p>
<h4 name="XPCSafeJSObjectWrapper"> XPCSafeJSObjectWrapper </h4>
<p>This wrapper was created to address some problems with XPCNativeWrapper.  In particular, some extensions want to be able to safely access non-natively-implemented content defined objects (and to access the underlying under an XPCNativeWrapper without its strong behavior guarantees).  XPCSJOW act as a buffer between the chrome code. <b>Note: Because any type of object can be wrapped here, there is no predefined behavior.  The only guarantee here is that untrusted code will run in an untrusted context. In particular, the underlying object might act entirely differently from what is expected.</b> Safe JSObject wrappers are implicitly created in some circumstances. All properties are visible through this wrapper.
</p>
<h4 name="XPCCrossOriginWrapper"> XPCCrossOriginWrapper </h4>
<p>The cross origin wrapper, or XOW, was recently implemented in order to broker access between web sites. This wrapper is implicitly created by XPConnect. All access checks happen in XOW code. If a XOW wrapper happens to wrap an object that is from the same origin as the running code, it acts like the Safe JSObject wrapper and it is possible to do anything to the XOW that you would do with any JS object. If the underlying object is <i>not</i> accessible, then it acts like an XPCNativeWrapper, meaning that it allows access to all APIs and behaviors provided by idl, overriding whatever the other site might have done.
</p>
<h2 name="What_Wrappers_Should_I_Use"> What Wrappers Should I Use </h2>
<p>Alright, you've skimmed the above and now you want to write some code! What wrappers should you use?
</p>
<h3 name="Chrome_Code_.28extensions.2C_etc.29"> Chrome Code (extensions, etc) </h3>
<p>As mentioned above, XPCWrappedNative and XPCWrappedJS wrappers are created implicitly, you should never have to worry about them. Likewise, if you are writing an extension or chrome code that <b>never</b> touches content code, you don't have to worry about wrappers.
</p><p>However, most extensions do touch content in some way. If you do touch content (via its window, for example) you should <b>always</b> get an XPCNativeWrapper. If you don't, then you have found a bug. See the documentation on XPCNativeWrapper for more information about its use.
</p><p>If you need more access to an object or need to access a content defined object that is implemented in JS or otherwise not available through an idl interface, then you should be using XPCSafeJSObjectWrappers. At the moment, you can either get one through <code>XPCNativeWrapper.wrappedJSObject</code> or by explictly writing <code>new XPCSafeJSObjectWrapper(object)</code>. Note, however, that I'm looking into implicitly creating these wrappers in all relevant cases and removing the visible constructor.
</p>
<h3 name="Content_Code_.28a_webpage.29"> Content Code (a webpage) </h3>
<p>As has always been the case, content code should not have to worry about wrappers or wrapping. Especially with the advent of XOWs, if you write code that conforms to the security restrictions imposed by the browser, you should not have to worry about wrappers. This does <b>not</b> mean that you can ignore security, think of XOWs like a safety belt, they will try to protect you, but you can still get in an accident.
</p>
<h2 name="Details"> Details </h2>
<p>I mentioned double wrapping before, and I want to mention it again before I go. Double wrapping is the one case where an XPCWrappedNative wraps another object -- this case is where a JS object was passed in via some IDL-declared interface, creating an XPCWrappedJS, and is now being returned to JavaScript via some other interface. In order to preserve API compatibility, an XPCWrappedNative is created around the XPCWrappedJS.
</p>
Revert to this revision