Common Pitfalls

There are some common pitfalls that should be avoided when writing either extensions or core Mozilla code. These are the sort of things that super-review should be catching for code that goes into the tree; avoiding these to start with saves super-reviewers a lot of effort.


The first couple of items deal with loading content from a URI. It's important to create the URI correctly, and then check that it's secure to load. This will shield you from loading <tt>javascript:</tt> or <tt>chrome:</tt> URIs when you shouldn't.

How to create a URI object

In almost all cases, when creating a URI object you want to use the newURI method on the nsIIOService interface, like so:

JavaScript:

try {
  var ioServ = Components.classes["@mozilla.org/network/io-service;1"]
                         .getService(Components.interfaces.nsIIOService);
  var uriObj = ioServ.newURI(uriString, uriCharset, baseURI);
} catch (e) {
  // May want to catch NS_ERROR_MALFORMED_URI for some applications
}

C++:

nsresult rv;
nsCOMPtr<nsIIOService> ioServ =
  do_GetService("@mozilla.org/network/io-service;1");
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> uriObj;
rv = ioServ->NewURI(uriString, uriCharset, baseURI,
                    getter_AddRefs(uriObj));
if (NS_FAILED(rv)) {
  // May want to handle NS_ERROR_MALFORMED_URI for
  // some applications
  return rv;
}

or, if the code can include nsNetUtil.h:

nsCOMPtr<nsIURI> uriObj;
nsresult rv =
  NS_NewURI(getter_AddRefs(uriObj), uriString, uriCharset, baseURI);

In all cases the baseURI can be null if the uriString should be treated as an absolute URI and uriCharset can be null if there is no clear origin charset for the string (e.g. it's something the user typed in the URL bar).

The one exception to all of the above, that is the one case in which creating a specific URI class via createInstance is acceptable, is when one is implementing a protocol handler's newURI method. In that case you may not be able to use the I/O service because that service calls the newURI method on the appropriate protocol handler, which may be your own handler.

How to do security checks for URI loads

Before loading a URI, one of two security checks needs to be performed:

  1. If the URI is a string that will be loaded via passing the string to nsIWebNavigation::LoadURI, the one must call CheckLoadURIStrWithPrincipal and pass the principal that the URI originates from as the first argument and the URI string as the second argument.
  2. In all other cases, one should call CheckLoadURIWithPrincipal and pass the principal that the URI originates from as the first argument and an nsIURI object representing the URI as the second argument. If there is no nsIURI object on hand, it is secure to call CheckLoadURIStrWithPrincipal, but this will perform a more stringent security check than is strictly necessary.

What Not To Do

All other security checks (including calls to CheckLoadURI and CheckLoadURIStr) are incorrect, because they do not properly capture the originating principal. Those methods should be removed.