XPCNativeWrapper

From GreaseSpot Wiki
Revision as of 21:09, 6 May 2012 by LWChris (talk | contribs) (Named Items)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Overview

Most all objects on a target web page that a user script sees are wrapped in XPCNativeWrapper. The reason for this is so that a script can change the properties of an object (actually the wrapper) without any JavaScript on the target page being able to interfere. Mostly the wrapping is "transparent" - wrapped and unwrapped objects behave the same because the wrapping object passes all access through to the wrapped object; there are some exceptions though.

Note: in Firefox 4, XrayWrapper replaced XPCNativeWrapper. They have different names but in effect serve the same purpose.

wrappedJSObject

For a script to access the real underlying object there is the method

var realObj = wrappedObj.wrappedJSObject;

Be very careful when using the wrappedJSObject property. It is just as dangerous as unsafeWindow is.

Security

Related to security.

Limitations / Problems

Expando Properties

Expando Properties do not work on XPCNativeWrappers. This means that, for example, this will not work:

var el = document.createElement("a");
el.onclick = "alert('Error'); return false;";

Instead, use setAttribute and addEventListener methods. Note the use of the preventDefault method to emulate the "return false" behavior above.

addEventListener example:

function showTheError(event) {
    event.preventDefault();

    /* some code */
}
var el = document.createElement("a");
el.addEventListener("click", showTheError, false);

setAttribute example:

var el = document.createElement("a");
el.setAttribute("onclick", "alert('Error'); return false;");

This applies to any element, not just new ones you create (those references from createElement and those from getElementById et al), and any event handler, not just onclick.

for ... in on HTMLCollections

DOM methods like getElementsByTagName return HTMLCollections.

var arInputs = document.getElementsByTagName("input");

for (var elmInput in arInputs) {

  /* some code */
}

Instead use this...

var arInputs = document.getElementsByTagName("input");

var elmInput;
for (var i = arInputs.length - 1; i >= 0; --i) {
  elmInput = arInputs[i];

  /* some code */
}

or

var arInputs = document.getElementsByTagName("input");

for each(var elmInput in arInputs) {
  /* some code */
}

Named Items

Items like frames, form elements, and so on can be referenced by name in normal JavaScript. XPCNativeWrappers cannot reference items by name. Use the namedItem method.

With a <input name="foo"> in the form:

form.foo;

Instead use this...

form.elements.namedItem("foo");

The same goes for frames:

window.framename;

Instead use this...

window.frames["framename"];

Event Handlers

Normal JavaScript can access an element's event handlers with code like:

element.onclick = myClickHandler;

or

element.onclick = "myClickHandler(this)";

This does not work on XPCNativeWrappers; it will result in a Component not available error in the JavaScript console. Instead, use addEventListener:

element.addEventListener("click", myClickHandler, false);

Any Greasemonkey script written before version 0.5 was released in mid-2005 may need updating to use addEventListener.