XPCNativeWrapper

  • Revision slug: XPCNativeWrapper
  • Revision title: XPCNativeWrapper
  • Revision id: 93108
  • Created:
  • Creator: Sevenspade
  • Is current revision? No
  • Comment Update based on comment from Boris.; 26 words added, 8 words removed

Revision Content

XPCNativeWrapper is a way to wrap up an object so that it's safe to access from privileged code. It can be used in all Firefox versions, though the behavior changed somewhat starting with Firefox 1.5 (Gecko 1.8). See the entry for XPCNativeWrapper at the MozillaZine KnowledgeBase for the behavior of XPCNativeWrapper in Firefox versions prior to 1.5. This document addresses XPCNativeWrapper in Firefox 1.5 and later.

What XPCNativeWrapper does

An XPCNativeWrapper limits access to the properties and methods of the object it wraps. The only properties and methods accessible through an XPCNativeWrapper are those that are defined in IDL or defined by DOM Level 0 (though some DOM Level 0 properties and methods do not work on an XPCNativeWrapper). In particular, properties added to an object via JavaScript (including getters and setters) are not exposed by an XPCNativeWrapper for this object. The intent is to allow safe access to the IDL-defined methods of the object.

Please make sure to read the known bugs section, especially when writing code targeted at a range of 1.5.0.x Firefox releases.

Types of XPCNativeWrapper

There are three different types of XPCNativeWrapper in Firefox 1.5. All three types wrap a possibly-unsafe object and provide safe access to its properties and methods.

The differences in behavior between the three types of XPCNativeWrapper are determined by two characteristics an XPCNativeWrapper wrapper can have. An XPCNativeWrapper can be explicit (or the opposite, implicit) and can be deep (or the opposite, shallow). The type of wrapper created is determined by the way it was created as follows:

Created by Explicit/Implicit Deep/Shallow
Protected script accessing an untrusted object Implicit Deep
Constructor called with string arguments Explicit Shallow
Constructor called with no string arguments Explicit Deep

Explicit vs. Implicit

The difference in behavior between explicit and implicit XPCNativeWrapper is that a property access on an implicit XPCNativeWrapper from script that is not protected is NOT safe. The property access will be forwarded through to the wrappedJSObject of the XPCNativeWrapper.

This means that scripts that are not protected don't need to worry about bugs arising because other code hands them an implicit XPCNativeWrapper. On the other hand, such scripts do need to watch out for unsafe object access.

Property access on an explicit XPCNativeWrapper is safe no matter whether the caller is protected.

Deep vs. Shallow

The difference in behavior between deep and shallow XPCNativeWrapper is that when a property is accessed or a function is called on a deep wrapper the return value will be wrapped in a XPCNativeWrapper of its own. The new XPCNativeWrapper will also be deep and it will be explicit if and only if the XPCNativeWrapper whose property is accessed was explicit. By contrast, when a property is accessed or a function is called on a shallow wrapper, the return value may be an unsafe object.

For example, say we are given three instances of XPCNativeWrapper for the same window object. Let us call them deepExplicitWindow, deepImplicitWindow and shallowWindow. Then we have:

var doc1 = deepExplicitWindow.document;
// doc1 is now a deep explicit XPCNativeWrapper for
// the document object.  Accessing doc1.open(), say, is safe.
var doc2 = deepImplicitWindow.document;
// If the caller has xpcnativewrappers=yes set, doc2 is now a deep
// implicit XPCNativeWrapper for the document object.
// Otherwise doc2 is now the unsafe document object, since the
// property access was simply passed along to the unsafe window object.
var doc3 = shallowWindow.document;
// doc3 is now the unsafe document object.

Creating XPCNativeWrapper objects

There are three different ways of creating an XPCNativeWrapper object; one way for each of the three types.

Protected script accessing an untrusted object

Any time a protected script accesses an untrusted object it will get back an implicit deep XPCNativeWrapper. Accessing properties of this XPCNativeWrapper is safe from protected scripts.

A wrapper created in this way will stick around as long as the object being wrapped does and accessing an object twice in a row will give the same XPCNativeWrapper.

What is a protected script?

In Firefox versions 1.5 through 1.5.0.5, a script is protected or not protected based solely on its URI. A script is protected only if its URI starts with a known protected prefix; scripts not loaded by URI (e.g. JavaScript-implemented components) are not protected. The protected prefixes in Firefox 1.5 are determined by the Chrome Registry.

By default, all content packages are protected. This means that all URIs that start "chrome://<package name>/content/" (for any package) are protected. Individual packages can override this using a flag in their chrome manifest file.

Starting with Firefox 1.5.0.6, JavaScript-implemented components are protected scripts. So a script is protected if it's either loaded from a URI which starts with a protected prefix or is a JavaScript-implemented component.

What is an untrusted object?

All objects are either trusted or untrusted. An object is trusted if any of the following hold:

  1. The object's scope chain is a trusted object.
  2. It is the root scope object for a JavaScript component.
  3. It is the window object for a trusted window.

Since all DOM objects in a window have the window on their scope chain, they will be trusted if and only if their window is trusted.

What is a trusted window?

Whether a window is trusted depends on its container. A window is trusted if any of the following holds:

  1. It is a top-level window (e.g. <xul:window>, <xul:dialog>, or some URI passed to the -chrome command-line flag).
  2. Its parent is trusted, and one of the following three options holds:
    1. It is not loaded in a <xul:iframe> or <xul:browser>.
    2. The <xul:iframe> or <xul:browser> loading it doesn't have a "type" attribute.
    3. The value of the "type" attribute of the <xul:iframe> or <xul:browser> loading it is not "content" and does not start with "content-".

Note that whether a window is trusted does not depend on the URI loaded in the window. So for example, the following would create trusted windows when used inside a document whose window is already trusted:

  • <xul:browser>
  • <xul:browser type="chrome">
  • <xul:browser type="rabid_dog">
  • <xul:iframe type="foofy">
  • <html:iframe>
  • <html:iframe type="content">

The following would not create trusted windows:

  • <xul:browser type="content">
  • <xul:iframe type="content-primary">

Further note that any child window of an untrusted window is automatically untrusted.

What happens when a script accesses an object?

The table below describes what happens when a script accesses an object, and how the wrapper is involved.

Script Object Effects
Protected Trusted No wrapper is created and therefore the script gets full access to the object.
Protected Untrusted An implicit deep XPCNativeWrapper is created.
Unprotected Trusted No wrapper is created, just as in the protected/trusted case.
Unprotected Untrusted No wrapper is created, just as in the protected/trusted case.

Using the XPCNativeWrapper constructor

As described above, by default in newer Firefox versions XPCNativeWrappers are created automatically. You don't need to use the XPCNativeWrapper constructor, unless you intend your code to work in older versions of the browser or you disabled XPCNativeWrappers.
XPCNativeWrapper constructor call with string arguments

For example:

var contentWinWrapper = new XPCNativeWrapper(content,
                                             "document");

This creates an explicit shallow XPCNativeWrapper. This syntax has been kept for compatibility with versions prior to Firefox 1.5. While all properties of the contentWinWrapper object can now be safely accessed, the return values of these properties are NOT safe to access (just like in versions prior to Firefox 1.5), since the XPCNativeWrapper is shallow. So to compare the content document title to the current content selection, one must do:

var winWrapper = new XPCNativeWrapper(content, "document",
                                      "getSelection()");
var docWrapper = new XPCNativeWrapper(winWrapper.document,
                                      "title");
return docWrapper.title == winWrapper.getSelection();

just like in versions before Firefox 1.5. Note that the "getSelection()" argument is not strictly needed here; if the code is not intended for use with Firefox versions before 1.5 it can be removed. A single string argument after the object being wrapped is all that is required for Firefox 1.5 to create this type of XPCNativeWrapper.

XPCNativeWrapper constructor call with no string arguments

For example:

var contentWinWrapper = new XPCNativeWrapper(content);

This creates an explicit deep XPCNativeWrapper. Accessing properties of this XPCNativeWrapper is safe, and the return values will also be wrapped in explicit deep XPCNativeWrapper objects.

Unwrapping an object

{{ gecko_minversion_header("1.9.2.2") }}

Given an object that's previously been wrapped, you may wish to be able to unwrap it. This can be done using the unwrap() method, which was added in Gecko 1.9.2.2 (Firefox 3.6.2).

Given a wrapped object, obj, you can unwrap it thusly:

obj = XPCNativeWrapper.unwrap(obj);

{{ note("XPCNativeWrapper.unwrap has been backed out on trunk (bug 533596). Continue using wrappedJSObject for now.") }}

XPCNativeWrapper lifetime

Explicit XPCNativeWrapper objects exist while they are referenced. Creating a new explicit XPCNativeWrapper for the same possibly-unsafe object will create a new wrapper object; something to watch out for when setting "expando" properties

Implicit XPCNativeWrapper objects have the same lifetime as the object they're wrapping.

Setting "expando" properties on XPCNativeWrapper

It is possible to set "expando" properties (properties with names that don't correspond to IDL-defined properties) on XPCNativeWrapper objects. If this is done, then chrome will be able to see these expando properties, but content will not be able to. There is no safe way to set an expando property from chrome and have it be readable from content.

There's a workaround using evalInSandbox: discussion, another example.

Accessing unsafe properties

If unsafe access to a property is required for some reason, this can be accomplished via the wrappedJSObject property of the wrapper. For example, if docWrapper is a wrapper for doc, then

docWrapper.wrappedJSObject.prop

is the same as

doc.prop

As the name of this section implies, doing so is unsafe. You shouldn't use wrappedJSObject to bypass XPCNativeWrapper in production code. More details can be found in this newsgroup discussion.

{{ Fx_minversion_inline("3") }} In Firefox 3 wrappedJSObject returns yet another wrapper around the content JS object (XPCSafeJSObjectWrapper), which allows you to safely inspect the content object. See XPCSafeJSObjectWrapper.

See Interaction between privileged and non-privileged pages for the better alternatives.

Known bugs

There are two known bugs in XPCNativeWrapper in the 1.5.0.x versions:

  1. Firefox versions 1.5 through 1.5.0.4 have {{ Bug("337095") }}, which causes wrappers to not be created for protected scripts in some cases. Specifically, if a protected script makes a property access or function call that returns an untrusted object, a wrapper will be created. However, if a function in a protected script is called from C++ and an untrusted object is passed as an argument to this function, a wrapper will not be created. Functions that expect to be called in this way need to do their own wrapping. This bug is fixed in Firefox 1.5.0.5 and later.
  2. Firefox versions 1.5 through 1.5.0.5 have {{ Bug("345991") }}, which causes components written in JavaScript to not be protected scripts. This bug is fixed in Firefox 1.5.0.6 and later.

Limitations of XPCNativeWrapper

There are some commonly used properties and coding styles that cannot be used with XPCNativeWrapper. Specifically:

  1. Assigning to or reading an on* property on an XPCNativeWrapper of a DOM node or Window object will throw an exception. (Use addEventListener instead, and use "event.preventDefault();" in your handler if you used "return false;" before.)
  2. Access to frames by window name (e.g. window.frameName) does not work on an XPCNativeWrapper
  3. document.all does not work on an XPCNativeWrapper for a document.
  4. Access to named items by name does not work on an XPCNativeWrapper for an HTML document. For example, if you have a <form name="foo"> and docWrapper is a wrapper for the HTML document doc then doc.foo is an HTMLFormElement while docWrapper.foo is undefined. Code that wishes to do this could use docWrapper.forms.namedItem("foo") instead.
  5. Access to nodes by id doesn't work on an XPCNativeWrapper for an HTML document. getElementById should be used instead.
  6. Access to inputs by name doesn't work on an XPCNativeWrapper for an HTML form. Code that wishes to do this should use form.elements.namedItem("inputname").
  7. Access to elements by name doesn't work on an XPCNativeWrapper for an HTMLCollection. Code that wishes to do this should use the namedItem() method. Note that namedItem only returns the first input element with the name, even if there are multiple elements (e.g. radio buttons) with the same name in the form.
  8. Similarly, access to items by name does not work on an XPCNativeWrapper for a Plugin, a PluginArray, or a MimeTypeArray. You should use namedItem() here as well.
  9. Calling methods implemented by NPAPI plugins through the XPCNativeWrapper for the corresponding node does not work.
  10. Getting or setting properties implemented by NPAPI plugins though the XPCNativeWrapper for the corresponding node does not work.
  11. Calling methods implemented via XBL bindings attached to a node through an XPCNativeWrapper for that node does not work.
  12. Getting or setting properties implemented via XBL bindings attached to a node through an XPCNativeWrapper for that node does not work.
  13. Object.prototype is not on the prototype chain of an XPCNativeWrapper. As a result, various Object.prototype properties are undefined on an XPCNativeWrapper (to be precise, these are __proto__, toSource, toLocaleString, valueOf, watch, unwatch, hasOwnProperty, isPrototypeOf, propertyIsEnumerable, __defineGetter__, __defineSetter__, __lookupGetter__, and __lookupSetter__).
  14. There is no support for the importXPCNative method the old XPCNativeWrapper implementation used to have.
  15. Accessing standard classes (such as Function) through an XPCNativeWrapper will not work. To create functions and objects with a particular window's parent, use the evalInSandbox function.
  16. Prior to Gecko 2.0 {{ geckoRelease("2.0") }}, using the delete operator on "expando" properties of an XPCNativeWrapper threw a security exception; this limitation was removed in Gecko 2.0.

{{ fx_minversion_note("3") }}

Avoid Common Pitfalls in Greasemonkey has an elaborate explanation for some of these limitations (in context of Greasemonkey scripts).

{{ languages( { "es": "es/XPCNativeWrapper", "fr": "fr/XPCNativeWrapper", "it": "it/XPCNativeWrapper", "ja": "ja/XPCNativeWrapper", "pl": "pl/XPCNativeWrapper" } ) }}

Revision Source

<p><code>XPCNativeWrapper</code> is a way to <a href="/en/XPConnect_wrappers" title="en/XPConnect_wrappers">wrap up</a> an object so that it's <a href="/en/Safely_accessing_content_DOM_from_chrome" title="en/Safely_accessing_content_DOM_from_chrome">safe to access from privileged code</a>. It can be used in all Firefox versions, though the behavior changed somewhat starting with Firefox 1.5 (Gecko 1.8). See <a class="external" href="http://kb.mozillazine.org/XPCNativeWrapper">the entry for <code>XPCNativeWrapper</code> at the MozillaZine KnowledgeBase</a> for the behavior of <code>XPCNativeWrapper</code> in Firefox versions prior to 1.5. This document addresses <code>XPCNativeWrapper</code> in Firefox 1.5 and later.</p>
<h3 name="What_XPCNativeWrapper_does">What <code>XPCNativeWrapper</code> does</h3>
<p>An <code>XPCNativeWrapper</code> limits access to the properties and methods of the object it wraps. The only properties and methods accessible through an <code>XPCNativeWrapper</code> are those that are defined in IDL or defined by DOM Level 0 (though some DOM Level 0 properties and methods <a href="#Limitations_of_XPCNativeWrapper">do not work on an <code>XPCNativeWrapper</code></a>). In particular, properties added to an object via JavaScript (including getters and setters) are not exposed by an <code>XPCNativeWrapper</code> for this object. The intent is to allow safe access to the IDL-defined methods of the object.</p>
<p>Please make sure to read the <a href="#Known_bugs">known bugs</a> section, especially when writing code targeted at a range of 1.5.0.x Firefox releases.</p>
<h3 name="Types_of_XPCNativeWrapper">Types of <code>XPCNativeWrapper</code></h3>
<p>There are three different types of <code>XPCNativeWrapper</code> in Firefox 1.5. All three types wrap a possibly-unsafe object and <a href="#What_XPCNativeWrapper_does">provide safe access to its properties and methods</a>.</p>
<p>The differences in behavior between the three types of <code>XPCNativeWrapper</code> are determined by two characteristics an <code>XPCNativeWrapper</code> wrapper can have. An <code>XPCNativeWrapper</code> can be <a href="#Explicit_vs._Implicit"><em>explicit</em></a> (or the opposite, <em>implicit</em>) and can be <a href="#Deep_vs._Shallow"><em>deep</em></a> (or the opposite, <em>shallow</em>). The type of wrapper created is determined by <a href="#Creating_XPCNativeWrapper_objects">the way it was created</a> as follows:</p>
<table class="standard-table"> <tbody> <tr> <th>Created by</th> <th>Explicit/Implicit</th> <th>Deep/Shallow</th> </tr> <tr> <th><a href="#Protected_script_accessing_an_untrusted_object">Protected script accessing an untrusted object</a></th> <td>Implicit</td> <td>Deep</td> </tr> <tr> <th><a href="#XPCNativeWrapper_constructor_call_with_string_arguments">Constructor called with string arguments</a></th> <td>Explicit</td> <td>Shallow</td> </tr> <tr> <th><a href="#XPCNativeWrapper_constructor_call_with_no_string_arguments">Constructor called with no string arguments</a></th> <td>Explicit</td> <td>Deep</td> </tr> </tbody>
</table>
<h4 name="Explicit_vs._Implicit">Explicit vs. Implicit</h4>
<p>The difference in behavior between explicit and implicit <code>XPCNativeWrapper</code> is that a property access on an implicit <code>XPCNativeWrapper</code> from script that is not <a href="#What_is_a_protected_script.3F">protected</a> is NOT safe. The property access will be forwarded through to the <code>wrappedJSObject</code> of the <code>XPCNativeWrapper</code>.</p>
<p>This means that scripts that are not <a href="#What_is_a_protected_script.3F">protected</a> don't need to worry about bugs arising because other code hands them an implicit <code>XPCNativeWrapper</code>. On the other hand, such scripts do need to watch out for unsafe object access.</p>
<p>Property access on an explicit <code>XPCNativeWrapper</code> is safe no matter whether the caller is <a href="#What_is_a_protected_script.3F">protected</a>.</p>
<h4 name="Deep_vs._Shallow">Deep vs. Shallow</h4>
<p>The difference in behavior between deep and shallow <code>XPCNativeWrapper</code> is that when a property is accessed or a function is called on a deep wrapper the return value will be wrapped in a <code>XPCNativeWrapper</code> of its own. The new <code>XPCNativeWrapper</code> will also be deep and it will be <a href="#Explicit_vs._Implicit">explicit</a> if and only if the <code>XPCNativeWrapper</code> whose property is accessed was explicit. By contrast, when a property is accessed or a function is called on a shallow wrapper, the return value may be an unsafe object.</p>
<p>For example, say we are given three instances of <code>XPCNativeWrapper</code> for the same window object. Let us call them <code>deepExplicitWindow</code>, <code>deepImplicitWindow</code> and <code>shallowWindow</code>. Then we have:</p>
<pre class="brush: js">var doc1 = deepExplicitWindow.document;
// doc1 is now a deep explicit <code>XPCNativeWrapper</code> for
// the document object.  Accessing doc1.open(), say, is safe.
</pre>
<pre class="brush: js">var doc2 = deepImplicitWindow.document;
// If the caller has xpcnativewrappers=yes set, doc2 is now a deep
// implicit <code>XPCNativeWrapper</code> for the document object.
// Otherwise doc2 is now the unsafe document object, since the
// property access was simply passed along to the unsafe window object.
</pre>
<pre class="brush: js">var doc3 = shallowWindow.document;
// doc3 is now the unsafe document object.
</pre>
<h3 name="Creating_XPCNativeWrapper_objects">Creating <code>XPCNativeWrapper</code> objects</h3>
<p>There are three different ways of creating an <code>XPCNativeWrapper</code> object; one way for each of the three types.</p>
<h4 name="Protected_script_accessing_an_untrusted_object">Protected script accessing an untrusted object</h4>
<p>Any time a <a href="#What_is_a_protected_script.3F">protected script</a> accesses an <a href="#What_is_an_untrusted_object.3F">untrusted object</a> it will get back an <a href="#Explicit_vs._Implicit">implicit</a> <a href="#Deep_vs._Shallow">deep</a> <code>XPCNativeWrapper</code>. Accessing properties of this <code>XPCNativeWrapper</code> is safe from <a href="#What_is_a_protected_script.3F">protected scripts</a>.</p>
<p>A wrapper created in this way will stick around as long as the object being wrapped does and accessing an object twice in a row will give the same <code>XPCNativeWrapper</code>.</p>
<h5 name="What_is_a_protected_script.3F">What is a protected script?</h5>
<p>In Firefox versions 1.5 through 1.5.0.5, a script is protected or not protected based solely on its URI. A script is protected only if its URI starts with a known protected prefix; scripts not loaded by URI (e.g. JavaScript-implemented components) are not protected. The protected prefixes in Firefox 1.5 are determined by the Chrome Registry.</p>
<p>By default, <strong>all content packages are protected</strong>. This means that all URIs that start "<code>chrome://&lt;package name&gt;/content/</code>" (for any package) are protected. Individual packages can <a href="/en/Chrome_Registration#xpcnativewrappers" title="en/Chrome_Registration#xpcnativewrappers">override this using a flag</a> in their chrome manifest file.</p>
<p>Starting with Firefox 1.5.0.6, JavaScript-implemented components are protected scripts. So a script is protected if it's either loaded from a URI which starts with a protected prefix or is a JavaScript-implemented component.</p>
<h5 name="What_is_an_untrusted_object.3F">What is an untrusted object?</h5>
<p>All objects are either trusted or untrusted. An object is trusted if any of the following hold:</p>
<ol> <li>The object's scope chain is a trusted object.</li> <li>It is the root scope object for a JavaScript component.</li> <li>It is the window object for a <a href="#What_is_a_trusted_window.3F">trusted window</a>.</li>
</ol>
<p>Since all DOM objects in a window have the window on their <code><span style="font-family: Verdana,Tahoma,sans-serif;">scope</span></code> chain, they will be trusted if and only if their window is trusted.</p>
<h5 name="What_is_a_trusted_window.3F">What is a trusted window?</h5>
<p>Whether a window is trusted depends on its container. A window is trusted if any of the following holds:</p>
<ol> <li>It is a top-level window (e.g. <code>&lt;xul:window&gt;</code>, <code>&lt;xul:dialog&gt;</code>, or some URI passed to the <code>-chrome</code> command-line flag).</li> <li>Its parent is trusted, and one of the following three options holds: <ol> <li>It is not loaded in a <code>&lt;xul:iframe&gt;</code> or <code>&lt;xul:browser&gt;</code>.</li> <li>The <code>&lt;xul:iframe&gt;</code> or <code>&lt;xul:browser&gt;</code> loading it doesn't have a "type" attribute.</li> <li>The value of the "type" attribute of the <code>&lt;xul:iframe&gt;</code> or <code>&lt;xul:browser&gt;</code> loading it is not "content" and does not start with "content-".</li> </ol> </li>
</ol>
<p>Note that whether a window is trusted does <strong>not</strong> depend on the URI loaded in the window. So for example, the following would create trusted windows when used inside a document whose window is already trusted:</p>
<ul> <li><code>&lt;xul:browser&gt;</code></li> <li><code>&lt;xul:browser type="chrome"&gt;</code></li> <li><code>&lt;xul:browser type="rabid_dog"&gt;</code></li> <li><code>&lt;xul:iframe type="foofy"&gt;</code></li> <li><code>&lt;html:iframe&gt;</code></li> <li><code>&lt;html:iframe type="content"&gt;</code></li>
</ul>
<p>The following would not create trusted windows:</p>
<ul> <li><code>&lt;xul:browser type="content"&gt;</code></li> <li><code>&lt;xul:iframe type="content-primary"&gt;</code></li>
</ul>
<p>Further note that any child window of an untrusted window is automatically untrusted.</p>
<h5 name="What_happens_when_a_script_accesses_an_object.3F">What happens when a script accesses an object?</h5>
<p>The table below describes what happens when a script accesses an object, and how the wrapper is involved.</p>
<table class="standard-table"> <tbody> <tr> <th>Script</th> <th>Object</th> <th>Effects</th> </tr> <tr> <td>Protected</td> <td>Trusted</td> <td>No wrapper is created and therefore the script gets full access to the object.</td> </tr> <tr> <td>Protected</td> <td>Untrusted</td> <td>An <a href="#Explicit_vs._Implicit">implicit</a> <a href="#Deep_vs._Shallow">deep</a> <code>XPCNativeWrapper</code> is created.</td> </tr> <tr> <td>Unprotected</td> <td>Trusted</td> <td>No wrapper is created, just as in the protected/trusted case.</td> </tr> <tr> <td>Unprotected</td> <td>Untrusted</td> <td>No wrapper is created, just as in the protected/trusted case.</td> </tr> </tbody>
</table>
<h4 name="Using_the_XPCNativeWrapper_constructor">Using the <code>XPCNativeWrapper</code> constructor</h4>
<div class="note">As described above, by default in newer Firefox versions <code>XPCNativeWrapper</code>s are created automatically. <strong>You don't need to use the <code>XPCNativeWrapper</code> constructor</strong>, unless you intend your code to work in older versions of the browser or you disabled <code>XPCNativeWrapper</code>s.</div>
<h5 name="XPCNativeWrapper_constructor_call_with_string_arguments"><code>XPCNativeWrapper</code> constructor call with string arguments</h5>
<p>For example:</p>
<pre class="brush: js">var contentWinWrapper = new XPCNativeWrapper(content,
                                             "document");
</pre>
<p>This creates an <a href="#Explicit_vs._Implicit">explicit</a> <a href="#Deep_vs._Shallow">shallow</a> <code>XPCNativeWrapper</code>. This syntax has been kept for compatibility with versions prior to Firefox 1.5. While all properties of the <code>contentWinWrapper</code> object can now be safely accessed, the return values of these properties are NOT safe to access (just like in versions prior to Firefox 1.5), since the <code>XPCNativeWrapper</code> is <a href="#Deep_vs._Shallow">shallow</a>. So to compare the content document title to the current content selection, one must do:</p>
<pre class="brush: js">var winWrapper = new XPCNativeWrapper(content, "document",
                                      "getSelection()");
var docWrapper = new XPCNativeWrapper(winWrapper.document,
                                      "title");
return docWrapper.title == winWrapper.getSelection();
</pre>
<p>just like in versions before Firefox 1.5. Note that the <code>"getSelection()"</code> argument is not strictly needed here; if the code is not intended for use with Firefox versions before 1.5 it can be removed. A single string argument after the object being wrapped is all that is required for Firefox 1.5 to create this type of <code>XPCNativeWrapper</code>.</p>
<h5 name="XPCNativeWrapper_constructor_call_with_no_string_arguments"><code>XPCNativeWrapper</code> constructor call with no string arguments</h5>
<p>For example:</p>
<pre class="brush: js">var contentWinWrapper = new XPCNativeWrapper(content);
</pre>
<p>This creates an <a href="#Explicit_vs._Implicit">explicit</a> <a href="#Deep_vs._Shallow">deep</a> <code>XPCNativeWrapper</code>. Accessing properties of this <code>XPCNativeWrapper</code> is safe, and the return values will also be wrapped in <a href="#Explicit_vs._Implicit">explicit</a> <a href="#Deep_vs._Shallow">deep</a> <code>XPCNativeWrapper</code> objects.</p>
<h3>Unwrapping an object</h3>
<p>{{ gecko_minversion_header("1.9.2.2") }}</p>
<p>Given an object that's previously been wrapped, you may wish to be able to unwrap it. This can be done using the <code>unwrap()</code> method, which was added in Gecko 1.9.2.2 (Firefox 3.6.2).</p>
<p>Given a wrapped object, <code>obj</code>, you can unwrap it thusly:</p>
<pre>obj = XPCNativeWrapper.unwrap(obj);
</pre>
<p>{{ note("XPCNativeWrapper.unwrap has been backed out on trunk (bug 533596). Continue using wrappedJSObject for now.") }}</p><h3 name="XPCNativeWrapper_lifetime"><code>XPCNativeWrapper</code> lifetime</h3>
<p>Explicit <code>XPCNativeWrapper</code> objects exist while they are referenced. Creating a new explicit <code>XPCNativeWrapper</code> for the same possibly-unsafe object will create a new wrapper object; something to watch out for when <a href="#Setting_.22expando.22_properties_on_XPCNativeWrapper">setting "expando" properties</a></p>
<p>Implicit <code>XPCNativeWrapper</code> objects have the same lifetime as the object they're wrapping.</p>
<h3 name="Setting_.22expando.22_properties_on_XPCNativeWrapper">Setting "expando" properties on <code>XPCNativeWrapper</code></h3>
<p>It is possible to set "expando" properties (properties with names that don't correspond to IDL-defined properties) on <code>XPCNativeWrapper</code> objects. If this is done, then chrome will be able to see these expando properties, but content will not be able to. <strong>There is no safe way to set an expando property from chrome and have it be readable from content.</strong></p>
<p>There's a workaround using evalInSandbox: <a class="external" href="http://groups.google.com/group/mozilla.dev.extensions/browse_thread/thread/492396807b37892f/3ba40f23b0bf2253#3ba40f23b0bf2253" title="http://groups.google.com/group/mozilla.dev.extensions/browse_thread/thread/492396807b37892f/3ba40f23b0bf2253#3ba40f23b0bf2253">discussion</a>, <a class="external" href="http://groups.google.com/group/mozilla.dev.extensions/msg/bdf1de5fb305d365" title="http://groups.google.com/group/mozilla.dev.extensions/msg/bdf1de5fb305d365">another example</a>.</p>
<h3 name="Accessing_unsafe_properties">Accessing unsafe properties</h3>
<p>If unsafe access to a property is required for some reason, this can be accomplished via the <code>wrappedJSObject</code> property of the wrapper. For example, if <code>docWrapper</code> is a wrapper for <code>doc</code>, then</p>
<pre class="brush: js">docWrapper.wrappedJSObject.prop
</pre>
<p>is the same as</p>
<pre class="brush: js">doc.prop
</pre>
<p>As the name of this section implies, doing so is <strong>unsafe</strong>. You shouldn't use <code>wrappedJSObject</code> to bypass XPCNativeWrapper in production code. More details can be found in <a class=" external" href="http://groups.google.com/group/mozilla.dev.platform/tree/browse_frm/thread/8d8470bce0d5b80f/210e9c62533e6090?hl=en&amp;rnum=11#doc_8e9010527b290b9b" title="http://groups.google.com/group/mozilla.dev.platform/tree/browse_frm/thread/8d8470bce0d5b80f/210e9c62533e6090?hl=en&amp;rnum=11#doc_8e9010527b290b9b">this newsgroup discussion</a>.</p>
<p>{{ Fx_minversion_inline("3") }} In Firefox 3 <code>wrappedJSObject</code> returns yet another wrapper around the content JS object (XPCSafeJSObjectWrapper), which allows you to safely inspect the content object. See <a href="/en/XPConnect_wrappers#XPCSafeJSObjectWrapper" title="en/XPConnect_wrappers#XPCSafeJSObjectWrapper">XPCSafeJSObjectWrapper</a>.</p>
<p>See <a href="/en/Code_snippets/Interaction_between_privileged_and_non-privileged_pages" title="en/Code_snippets/Interaction_between_privileged_and_non-privileged_pages">Interaction between privileged and non-privileged pages</a> for the better alternatives.</p><h3 name="Known_bugs">Known bugs</h3>
<p>There are two known bugs in <code>XPCNativeWrapper</code> in the 1.5.0.x versions:</p>
<ol> <li>Firefox versions 1.5 through 1.5.0.4 have {{ Bug("337095") }}, which causes wrappers to not be created for protected scripts in some cases. Specifically, if a protected script makes a property access or function call that returns an untrusted object, a wrapper will be created. However, if a function in a protected script is called from C++ and an untrusted object is passed as an argument to this function, a wrapper will <em>not</em> be created. Functions that expect to be called in this way need to <a href="#XPCNativeWrapper_constructor_call_with_no_string_arguments">do their own wrapping</a>. This bug is fixed in Firefox 1.5.0.5 and later.</li> <li>Firefox versions 1.5 through 1.5.0.5 have {{ Bug("345991") }}, which causes components written in JavaScript to not be protected scripts. This bug is fixed in Firefox 1.5.0.6 and later.</li>
</ol>
<h3 name="Limitations_of_XPCNativeWrapper">Limitations of <code>XPCNativeWrapper</code></h3>
<p>There are some commonly used properties and coding styles that cannot be used with <code>XPCNativeWrapper</code>. Specifically:</p>
<ol> <li>Assigning to or reading an <code>on*</code> property on an <code>XPCNativeWrapper</code> of a DOM node or Window object will throw an exception. (Use addEventListener instead, and use "event.preventDefault();" in your handler if you used "return false;" before.)</li> <li>Access to frames by window name (e.g. <code>window.frameName</code>) does not work on an <code>XPCNativeWrapper</code></li> <li><code>document.all</code> does not work on an <code>XPCNativeWrapper</code> for a document.</li> <li>Access to named items by name does not work on an <code>XPCNativeWrapper</code> for an HTML document. For example, if you have a <code>&lt;form name="foo"&gt;</code> and <code>docWrapper</code> is a wrapper for the HTML document <code>doc</code> then <code>doc.foo</code> is an <code>HTMLFormElement</code> while <code>docWrapper.foo</code> is <code>undefined</code>. Code that wishes to do this could use <code>docWrapper.forms.namedItem("foo")</code> instead.</li> <li>Access to nodes by id doesn't work on an <code>XPCNativeWrapper</code> for an HTML document. <code>getElementById</code> should be used instead.</li> <li>Access to inputs by name doesn't work on an <code>XPCNativeWrapper</code> for an HTML form. Code that wishes to do this should use <code>form.elements.namedItem("inputname")</code>.</li> <li>Access to elements by name doesn't work on an <code>XPCNativeWrapper</code> for an <code>HTMLCollection</code>. Code that wishes to do this should use the <code>namedItem()</code> method. Note that <code>namedItem</code> only returns the first input element with the name, even if there are multiple elements (e.g. radio buttons) with the same name in the form.</li> <li>Similarly, access to items by name does not work on an <code>XPCNativeWrapper</code> for a <code>Plugin</code>, a <code>PluginArray</code>, or a <code>MimeTypeArray</code>. You should use <code>namedItem()</code> here as well.</li> <li>Calling methods implemented by NPAPI plugins through the <code>XPCNativeWrapper</code> for the corresponding node does not work.</li> <li>Getting or setting properties implemented by NPAPI plugins though the <code>XPCNativeWrapper</code> for the corresponding node does not work.</li> <li>Calling methods implemented via XBL bindings attached to a node through an <code>XPCNativeWrapper</code> for that node does not work.</li> <li>Getting or setting properties implemented via XBL bindings attached to a node through an <code>XPCNativeWrapper</code> for that node does not work.</li> <li>Object.prototype is not on the prototype chain of an <code>XPCNativeWrapper</code>. As a result, various <code>Object.prototype</code> properties are undefined on an <code>XPCNativeWrapper</code> (to be precise, these are <code>__proto__</code>, <code>toSource</code>, <code>toLocaleString</code>, <code>valueOf</code>, <code>watch</code>, <code>unwatch</code>, <code>hasOwnProperty</code>, <code>isPrototypeOf</code>, <code>propertyIsEnumerable</code>, <code>__defineGetter__</code>, <code>__defineSetter__</code>, <code>__lookupGetter__</code>, and <code>__lookupSetter__</code>).</li> <li>There is no support for the <code>importXPCNative</code> method the old <code>XPCNativeWrapper</code> implementation used to have.</li> <li>Accessing standard classes (such as <code>Function</code>) through an XPCNativeWrapper will not work. To create functions and objects with a particular window's parent, use the <code>evalInSandbox</code> function.</li> <li>Prior to Gecko 2.0 {{ geckoRelease("2.0") }}, using the <a href="/en/JavaScript/Reference/Operators/Special_Operators/delete_Operator" title="en/JavaScript/Reference/Operators/Special Operators/delete Operator"><code>delete</code></a> operator on "expando" properties of an XPCNativeWrapper threw a security exception; this limitation was removed in Gecko 2.0.</li>
</ol>
<p>{{ fx_minversion_note("3") }}</p>
<p><a class="external" href="http://oreillynet.com/pub/a/network/2005/11/01/avoid-common-greasemonkey-pitfalls.html?page=3">Avoid Common Pitfalls in Greasemonkey</a> has an elaborate explanation for some of these limitations (in context of Greasemonkey scripts).</p>
<p>{{ languages( { "es": "es/XPCNativeWrapper", "fr": "fr/XPCNativeWrapper", "it": "it/XPCNativeWrapper", "ja": "ja/XPCNativeWrapper", "pl": "pl/XPCNativeWrapper" } ) }}</p>
Revert to this revision