Merge mozilla-central into mozila-inbound
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 29 Sep 2011 12:51:50 -0400
changeset 77863 8417548adf12704b5cb198504253efd429e4f860
parent 77862 4320fd88ed156bd949a4ab6fbe31778b30c227bf (current diff)
parent 77822 1aa8a58760580670006a871de77bd1db3c924053 (diff)
child 77864 9928fb9a32b1ccc6aa2b61cbb19525a638010d73
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
milestone10.0a1
Merge mozilla-central into mozila-inbound
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/remote-experiment-loader.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/remote-experiment-loader.js
@@ -127,17 +127,17 @@ function downloadFile(url, cb, lastModif
     req.setRequestHeader("If-Modified-Since", d.toGMTString());
     console.info("Setting if-modified-since header to " + d.toGMTString());
   }
   //Use binary mode to download jars TODO find a better switch
   if (url.indexOf(".jar") == url.length - 4) {
     console.info("Using binary mode to download jar file.");
     req.overrideMimeType('text/plain; charset=x-user-defined');
   }
-  req.onreadystatechange = function(aEvt) {
+  req.addEventListener("readystatechange", function(aEvt) {
     if (req.readyState == 4) {
       if (req.status == 200) {
         // check security channel:
         if (verifyChannelSecurity(req.channel)) {
           cb(req.responseText);
         } else {
           cb(null);
         }
@@ -149,17 +149,17 @@ function downloadFile(url, cb, lastModif
         // calling back with null lets the RemoteExperimentLoader know it should
         // keep using the old cached version of the code.
       } else {
         // Some kind of error.
         console.warn("Got a " + req.status + " error code downloading " + url);
 	cb(null);
       }
     }
-  };
+  }, false);
   req.send();
 }
 
 // example contents of extensions.testpilot.experiment.codeFs:
 // {'fs': {"bookmark01/experiment": "<plain-text code @ bookmarks.js>"}}
 // sample code
     // example data:
     // {'experiments': [{'name': 'Bookmark Experiment',
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
@@ -841,17 +841,17 @@ TestPilotExperiment.prototype = {
     self._logger.info("Posting data to url " + url + "\n");
     self._prependMetadataToJSON( function(dataString) {
       let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
                   .createInstance( Ci.nsIXMLHttpRequest );
       req.open('POST', url, true);
       req.setRequestHeader("Content-type", "application/json");
       req.setRequestHeader("Content-length", dataString.length);
       req.setRequestHeader("Connection", "close");
-      req.onreadystatechange = function(aEvt) {
+      req.addEventListener("readystatechange", function(aEvt) {
         if (req.readyState == 4) {
           if (req.status == 200 || req.status == 201 || req.status == 202) {
             let location = req.getResponseHeader("Location");
   	    self._logger.info("DATA WAS POSTED SUCCESSFULLY " + location);
             if (self._uploadRetryTimer) {
               self._uploadRetryTimer.cancel(); // Stop retrying - it worked!
             }
             self.changeStatus(TaskConstants.STATUS_SUBMITTED);
@@ -882,17 +882,17 @@ TestPilotExperiment.prototype = {
               parseInt(Math.random() * Math.pow(2, retryCount) * interval);
             self._uploadRetryTimer.initWithCallback(
               { notify: function(timer) {
 		self.upload(callback, retryCount++);
 	      } }, (interval + delay), Ci.nsITimer.TYPE_ONE_SHOT);
             callback(false);
           }
         }
-      };
+      }, false);
       req.send(dataString);
     });
   },
 
   optOut: function TestPilotExperiment_optOut(reason, callback) {
     // Regardless of study ID, post the opt-out message to a special
     // database table of just opt-out messages; include study ID in metadata.
     let logger = this._logger;
@@ -914,31 +914,31 @@ TestPilotExperiment.prototype = {
       var req =
         Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
 	  createInstance(Ci.nsIXMLHttpRequest);
       logger.trace("Posting " + dataString + " to " + url);
       req.open('POST', url, true);
       req.setRequestHeader("Content-type", "application/json");
       req.setRequestHeader("Content-length", dataString.length);
       req.setRequestHeader("Connection", "close");
-      req.onreadystatechange = function(aEvt) {
+      req.addEventListener("readystatechange", function(aEvt) {
         if (req.readyState == 4) {
           if (req.status == 200 || req.status == 201 || req.status == 202) {
 	    logger.info("Quit reason posted successfully " + req.responseText);
             if (callback) {
               callback(true);
             }
 	  } else {
 	    logger.warn(req.status + " posting error " + req.responseText);
             if (callback) {
               callback(false);
             }
 	  }
 	}
-      };
+      }, false);
       logger.trace("Sending quit reason.");
       req.send(dataString);
     } else {
       if (callback) {
         callback(false);
       }
     }
   },
@@ -1064,17 +1064,17 @@ TestPilotBuiltinSurvey.prototype = {
       let req =
         Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
           createInstance(Ci.nsIXMLHttpRequest);
       let url = self.uploadUrl;
       req.open("POST", url, true);
       req.setRequestHeader("Content-type", "application/json");
       req.setRequestHeader("Content-length", params.length);
       req.setRequestHeader("Connection", "close");
-      req.onreadystatechange = function(aEvt) {
+      req.addEventListener("readystatechange", function(aEvt) {
         if (req.readyState == 4) {
           if (req.status == 200 || req.status == 201 ||
              req.status == 202) {
             self._logger.info(
 	    "DATA WAS POSTED SUCCESSFULLY " + req.responseText);
             if (self._uploadRetryTimer) {
               self._uploadRetryTimer.cancel(); // Stop retrying - it worked!
 	    }
@@ -1094,17 +1094,17 @@ TestPilotBuiltinSurvey.prototype = {
 	      parseInt(Math.random() * Math.pow(2, retryCount) * interval);
 	    self._uploadRetryTimer.initWithCallback(
               { notify: function(timer) {
 	          self._upload(callback, retryCount++);
 	        } }, (interval + delay), Ci.nsITimer.TYPE_ONE_SHOT);
 	    callback(false);
 	  }
         }
-      };
+      }, false);
       req.send(params);
     });
   }
 };
 TestPilotBuiltinSurvey.prototype.__proto__ = TestPilotTask;
 
 function TestPilotWebSurvey(surveyInfo) {
   this._init(surveyInfo);
--- a/build/win32/crashinject.cpp
+++ b/build/win32/crashinject.cpp
@@ -66,17 +66,17 @@ int main(int argc, char** argv)
   wchar_t* slash = wcsrchr(filename, L'\\');
   if (slash == NULL)
     return 1;
 
   slash++;
   wcscpy(slash, L"crashinjectdll.dll");
 
   // now find our target process
-  HANDLE targetProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD,
+  HANDLE targetProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION,
                                   FALSE,
                                   pid);
   if (targetProc == NULL) {
     fprintf(stderr, "Error %d opening target process\n", GetLastError());
     return 1;
   }
 
   /*
--- a/content/base/public/nsDOMEventTargetWrapperCache.h
+++ b/content/base/public/nsDOMEventTargetWrapperCache.h
@@ -81,14 +81,65 @@ public:
       // nsISupports pointer. That must be fixed, or we'll crash...
       NS_ASSERTION(target_qi == target, "Uh, fix QI!");
     }
 #endif
 
     return static_cast<nsDOMEventTargetWrapperCache*>(target);
   }
 
+  void Init(JSContext* aCx = nsnull);
+
 protected:
   nsDOMEventTargetWrapperCache() : nsDOMEventTargetHelper(), nsWrapperCache() {}
   virtual ~nsDOMEventTargetWrapperCache();
 };
 
+#define NS_DECL_EVENT_HANDLER(_event)                                         \
+  public:                                                                     \
+    NS_IMETHOD GetOn##_event(JSContext *cx, jsval *vp);                       \
+    NS_IMETHOD SetOn##_event(JSContext *cx, const jsval &vp);
+
+#define NS_DECL_AND_IMPL_EVENT_HANDLER(_event)                                \
+  public:                                                                     \
+    NS_IMPL_EVENT_HANDLER(_class, _event)
+
+#define NS_IMPL_EVENT_HANDLER(_class, _event)                                 \
+  NS_IMETHODIMP                                                               \
+  _class::GetOn##_event(JSContext *cx, jsval *vp)                             \
+  {                                                                           \
+    nsEventListenerManager* elm = GetListenerManager(PR_FALSE);               \
+    if (elm) {                                                                \
+      elm->GetJSEventListener(nsGkAtoms::on##_event, vp);                     \
+    } else {                                                                  \
+      *vp = JSVAL_NULL;                                                       \
+    }                                                                         \
+    return NS_OK;                                                             \
+  }                                                                           \
+  NS_IMETHODIMP                                                               \
+  _class::SetOn##_event(JSContext *cx, const jsval &vp)                       \
+  {                                                                           \
+    nsEventListenerManager* elm = GetListenerManager(PR_TRUE);                \
+    if (!elm) {                                                               \
+      return NS_ERROR_OUT_OF_MEMORY;                                          \
+    }                                                                         \
+                                                                              \
+    JSObject *obj = GetWrapper();                                             \
+    if (!obj) {                                                               \
+      /* Just silently do nothing */                                          \
+      return NS_OK;                                                           \
+    }                                                                         \
+    return elm->SetJSEventListenerToJsval(nsGkAtoms::on##_event, cx, obj, vp);\
+  }
+
+#define NS_IMPL_FORWARD_EVENT_HANDLER(_class, _event, _baseclass)             \
+    NS_IMETHODIMP                                                             \
+    _class::GetOn##_event(JSContext *cx, jsval *vp)                           \
+    {                                                                         \
+      return _baseclass::GetOn##_event(cx, vp);                               \
+    }                                                                         \
+    NS_IMETHODIMP                                                             \
+    _class::SetOn##_event(JSContext *cx, const jsval &vp)                     \
+    {                                                                         \
+      return _baseclass::SetOn##_event(cx, vp);                               \
+    }
+
 #endif  // nsDOMEventTargetWrapperCache_h__
--- a/content/base/public/nsIDOMFileReader.idl
+++ b/content/base/public/nsIDOMFileReader.idl
@@ -36,18 +36,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMEventListener;
 interface nsIDOMBlob;
 interface nsIDOMFileError;
 
-[scriptable, uuid(3d77e784-1459-4206-b8a2-0855d826f569)]
-interface nsIDOMFileReader : nsISupports 
+[scriptable, builtinclass, uuid(57d68e17-85fa-4509-bf71-ffac1b22a174)]
+interface nsIDOMFileReader : nsIDOMEventTarget
 {
   [implicit_jscontext]
   void readAsArrayBuffer(in nsIDOMBlob filedata);
   void readAsBinaryString(in nsIDOMBlob filedata);
   void readAsText(in nsIDOMBlob filedata, [optional] in DOMString encoding);
   void readAsDataURL(in nsIDOMBlob file);
 
   void abort();
@@ -55,16 +55,23 @@ interface nsIDOMFileReader : nsISupports
   const unsigned short EMPTY = 0;
   const unsigned short LOADING = 1;
   const unsigned short DONE = 2;
   readonly attribute unsigned short readyState;
 
   [implicit_jscontext]
   readonly attribute jsval result;
   readonly attribute nsIDOMFileError error;
+
+  [implicit_jscontext] attribute jsval onloadstart;
+  [implicit_jscontext] attribute jsval onprogress;
+  [implicit_jscontext] attribute jsval onload;
+  [implicit_jscontext] attribute jsval onabort;
+  [implicit_jscontext] attribute jsval onerror;
+  [implicit_jscontext] attribute jsval onloadend;
 };
 
 %{ C++
 #define NS_FILEREADER_CID                            \
 {0x06aa7c21, 0xfe05, 0x4cf2,                         \
 {0xb1, 0xc4, 0x0c, 0x71, 0x26, 0xa4, 0xf7, 0x13}}
 #define NS_FILEREADER_CONTRACTID \
 "@mozilla.org/files/filereader;1"
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -522,23 +522,18 @@ public:
   /**
    * Find the content node for which aDocument is a sub document.
    */
   virtual nsIContent *FindContentForSubDocument(nsIDocument *aDocument) const = 0;
 
   /**
    * Return the root element for this document.
    */
-  Element *GetRootElement() const
-  {
-    return (mCachedRootElement &&
-            mCachedRootElement->GetNodeParent() == this) ?
-           reinterpret_cast<Element*>(mCachedRootElement.get()) :
-           GetRootElementInternal();
-  }
+  Element *GetRootElement() const;
+
 protected:
   virtual Element *GetRootElementInternal() const = 0;
 
 public:
   // Get the root <html> element, or return null if there isn't one (e.g.
   // if the root isn't <html>)
   Element* GetHtmlElement();
   // Returns the first child of GetHtmlContent which has the given tag,
@@ -1639,19 +1634,17 @@ protected:
 
   nsCString mCharacterSet;
   PRInt32 mCharacterSetSource;
 
   // This is just a weak pointer; the parent document owns its children.
   nsIDocument* mParentDocument;
 
   // A reference to the element last returned from GetRootElement().
-  // This should be an Element, but that would force us to pull in
-  // Element.h and therefore nsIContent.h.
-  nsCOMPtr<nsINode> mCachedRootElement;
+  mozilla::dom::Element* mCachedRootElement;
 
   // We'd like these to be nsRefPtrs, but that'd require us to include
   // additional headers that we don't want to expose.
   // The cleanup is handled by the nsDocument destructor.
   nsNodeInfoManager* mNodeInfoManager; // [STRONG]
   mozilla::css::Loader* mCSSLoader; // [STRONG]
 
   // The set of all object, embed, applet, video and audio elements for
--- a/content/base/public/nsIEventSource.idl
+++ b/content/base/public/nsIEventSource.idl
@@ -46,31 +46,31 @@
 
 #include "nsISupports.idl"
 
 interface nsIDOMEventListener;
 interface nsIPrincipal;
 interface nsIScriptContext;
 interface nsPIDOMWindow;
 
-[scriptable, uuid(755e2d2d-a836-4539-83f4-16b51156341f)]
+[scriptable, uuid(741374e9-39ed-4712-a380-93e023b271f8)]
 interface nsIEventSource : nsISupports
 {
   readonly attribute DOMString url;
 
   // ready state
   const unsigned short CONNECTING = 0;
   const unsigned short OPEN = 1;
   const unsigned short CLOSED = 2;
   readonly attribute long readyState;
 
   // event handler attributes
-  attribute nsIDOMEventListener onopen;
-  attribute nsIDOMEventListener onmessage;
-  attribute nsIDOMEventListener onerror;
+  [implicit_jscontext] attribute jsval onopen;
+  [implicit_jscontext] attribute jsval onmessage;
+  [implicit_jscontext] attribute jsval onerror;
 
   /**
    * Close the connection, if any, and set the readyState attribute to CLOSED.
    * If the connection is already closed, the method does nothing.
    */
   void close();
 
   /**
--- a/content/base/public/nsIXMLHttpRequest.idl
+++ b/content/base/public/nsIXMLHttpRequest.idl
@@ -48,28 +48,28 @@ interface nsPIDOMWindow;
 interface nsIInputStream;
 interface nsIDOMBlob;
 
 %{C++
 // for jsval
 #include "jsapi.h"
 %}
 
-[scriptable, builtinclass, uuid(dea238a1-240f-45f4-9f07-7769bc69eb76)]
+[scriptable, builtinclass, uuid(8bc1357c-fe70-4741-a170-8fa50b6d23be)]
 interface nsIXMLHttpRequestEventTarget : nsIDOMEventTarget {
   // event handler attributes
-  attribute nsIDOMEventListener onabort;
-  attribute nsIDOMEventListener onerror;
-  attribute nsIDOMEventListener onload;
-  attribute nsIDOMEventListener onloadstart;
-  attribute nsIDOMEventListener onprogress;
-  attribute nsIDOMEventListener onloadend;
+  [implicit_jscontext] attribute jsval onabort;
+  [implicit_jscontext] attribute jsval onerror;
+  [implicit_jscontext] attribute jsval onload;
+  [implicit_jscontext] attribute jsval onloadstart;
+  [implicit_jscontext] attribute jsval onprogress;
+  [implicit_jscontext] attribute jsval onloadend;
 };
 
-[scriptable, builtinclass, uuid(09ff3682-7759-4441-a765-f70e1a1fabcf)]
+[scriptable, builtinclass, uuid(cfa2d9fc-1871-444c-aaf9-8fc7fc7261d8)]
 interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget {
   // for future use
 };
 
 /**
  * Mozilla's XMLHttpRequest is modelled after Microsoft's IXMLHttpRequest
  * object. The goal has been to make Mozilla's version match Microsoft's
  * version as closely as possible, but there are bound to be some differences.
@@ -105,17 +105,17 @@ interface nsIXMLHttpRequestUpload : nsIX
  *   The 'onload', 'onerror', and 'onreadystatechange' attributes moved to
  *   nsIJSXMLHttpRequest, but if you're coding in C++ you should avoid using
  *   those.
  *
  * Conclusion: Do not use event listeners on XMLHttpRequest from C++, unless
  * you're aware of all the security implications.  And then think twice about
  * it.
  */
-[scriptable, uuid(5cf8d518-51d0-4cd6-a69a-c3674c2de599)]
+[scriptable, uuid(10d4701f-6351-4e9b-addd-ffdba05bd425)]
 interface nsIXMLHttpRequest : nsISupports
 {
   /**
    * The request uses a channel in order to perform the
    * request.  This attribute represents the channel used
    * for the request.  NULL if the channel has not yet been
    * created.
    *
@@ -369,45 +369,45 @@ interface nsIXMLHttpRequest : nsISupport
    * readyState changes, the callback function will be called.
    * This attribute should not be used from native code!!
    *
    * After the initial response, all event listeners will be cleared.
    * // XXXbz what does that mean, exactly?   
    *
    * Call open() before setting an onreadystatechange listener.
    */
-  attribute nsIDOMEventListener onreadystatechange;
+  [implicit_jscontext] attribute jsval onreadystatechange;
 };
 
 [scriptable, uuid(840d0d00-e83e-4a29-b3c7-67e96e90a499)]
 interface nsIXHRSendable : nsISupports {
   void getSendInfo(out nsIInputStream body,
                    out ACString contentType,
                    out ACString charset);
 };
 
 /**
  * @deprecated
  */
-[deprecated, scriptable, uuid(423fdd3d-41c9-4149-8fe5-b14a1d3912a0)]
+[deprecated, scriptable, uuid(58d2c633-2efd-45be-80ed-511dcd0407cc)]
 interface nsIJSXMLHttpRequest : nsISupports {
   /**
    * Meant to be a script-only mechanism for setting an upload progress event
    * listener.
    * This attribute should not be used from native code!!
    * This event listener may be called multiple times during the upload..
    *
    * After the initial response, all event listeners will be cleared.
    * // XXXbz what does that mean, exactly?
    *
    * This event listener must be set BEFORE calling open().
    *
    * Mozilla only.
    */
-  attribute nsIDOMEventListener onuploadprogress;
+  [implicit_jscontext] attribute jsval onuploadprogress;
 };
 
 %{ C++
 #define NS_XMLHTTPREQUEST_CID                       \
  { /* d164e770-4157-11d4-9a42-000064657374 */       \
   0xd164e770, 0x4157, 0x11d4,                       \
  {0x9a, 0x42, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} }
 #define NS_XMLHTTPREQUEST_CONTRACTID \
new file mode 100644
--- /dev/null
+++ b/content/base/src/FileIOObject.cpp
@@ -0,0 +1,300 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozila.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Kyle Huey <me@kylehuey.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "FileIOObject.h"
+#include "nsDOMFile.h"
+#include "nsDOMError.h"
+#include "nsIPrivateDOMEvent.h"
+#include "nsIDOMEvent.h"
+#include "nsIDOMProgressEvent.h"
+#include "nsComponentManagerUtils.h"
+#include "nsEventDispatcher.h"
+#include "nsGkAtoms.h"
+#include "xpcprivate.h"
+
+#define ERROR_STR "error"
+#define ABORT_STR "abort"
+#define PROGRESS_STR "progress"
+
+namespace mozilla {
+namespace dom {
+
+const PRUint64 kUnknownSize = PRUint64(-1);
+
+NS_IMPL_ADDREF_INHERITED(FileIOObject, nsDOMEventTargetWrapperCache)
+NS_IMPL_RELEASE_INHERITED(FileIOObject, nsDOMEventTargetWrapperCache)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileIOObject)
+  NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
+  NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
+  NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetWrapperCache)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(FileIOObject)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FileIOObject,
+                                                  nsDOMEventTargetWrapperCache)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mProgressNotifier)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FileIOObject,
+                                                nsDOMEventTargetWrapperCache)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressNotifier)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_EVENT_HANDLER(FileIOObject, abort)
+NS_IMPL_EVENT_HANDLER(FileIOObject, error)
+NS_IMPL_EVENT_HANDLER(FileIOObject, progress)
+
+FileIOObject::FileIOObject()
+  : mProgressEventWasDelayed(PR_FALSE),
+    mTimerIsActive(PR_FALSE),
+    mReadyState(0),
+    mTotal(0), mTransferred(0)
+{}
+
+FileIOObject::~FileIOObject()
+{
+  if (mListenerManager)
+    mListenerManager->Disconnect();
+}
+
+void
+FileIOObject::StartProgressEventTimer()
+{
+  if (!mProgressNotifier) {
+    mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
+  }
+  if (mProgressNotifier) {
+    mProgressEventWasDelayed = PR_FALSE;
+    mTimerIsActive = PR_TRUE;
+    mProgressNotifier->Cancel();
+    mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,
+                                        nsITimer::TYPE_ONE_SHOT);
+  }
+}
+
+void
+FileIOObject::ClearProgressEventTimer()
+{
+  mProgressEventWasDelayed = PR_FALSE;
+  mTimerIsActive = PR_FALSE;
+  if (mProgressNotifier) {
+    mProgressNotifier->Cancel();
+  }
+}
+
+void
+FileIOObject::DispatchError(nsresult rv, nsAString& finalEvent)
+{
+  // Set the status attribute, and dispatch the error event
+  switch (rv) {
+  case NS_ERROR_FILE_NOT_FOUND:
+    mError = new nsDOMFileError(nsIDOMFileError::NOT_FOUND_ERR);
+    break;
+  case NS_ERROR_FILE_ACCESS_DENIED:
+    mError = new nsDOMFileError(nsIDOMFileError::SECURITY_ERR);
+    break;
+  default:
+    mError = new nsDOMFileError(nsIDOMFileError::NOT_READABLE_ERR);
+    break;
+  }
+
+  // Dispatch error event to signify load failure
+  DispatchProgressEvent(NS_LITERAL_STRING(ERROR_STR));
+  DispatchProgressEvent(finalEvent);
+}
+
+nsresult
+FileIOObject::DispatchProgressEvent(const nsAString& aType)
+{
+  nsCOMPtr<nsIDOMEvent> event;
+  nsresult rv = nsEventDispatcher::CreateEvent(nsnull, nsnull,
+                                               NS_LITERAL_STRING("ProgressEvent"),
+                                               getter_AddRefs(event));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIPrivateDOMEvent> privevent(do_QueryInterface(event));
+  NS_ENSURE_TRUE(privevent, NS_ERROR_UNEXPECTED);
+
+  privevent->SetTrusted(PR_TRUE);
+  nsCOMPtr<nsIDOMProgressEvent> progress = do_QueryInterface(event);
+  NS_ENSURE_TRUE(progress, NS_ERROR_UNEXPECTED);
+
+  bool known;
+  PRUint64 size;
+  if (mTotal != kUnknownSize) {
+    known = PR_TRUE;
+    size = mTotal;
+  } else {
+    known = PR_FALSE;
+    size = 0;
+  }
+  rv = progress->InitProgressEvent(aType, PR_FALSE, PR_FALSE, known,
+                                   mTransferred, size);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return DispatchDOMEvent(nsnull, event, nsnull, nsnull);
+}
+
+// nsITimerCallback
+NS_IMETHODIMP
+FileIOObject::Notify(nsITimer* aTimer)
+{
+  nsresult rv;
+  mTimerIsActive = PR_FALSE;
+
+  if (mProgressEventWasDelayed) {
+    rv = DispatchProgressEvent(NS_LITERAL_STRING("progress"));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    StartProgressEventTimer();
+  }
+
+  return NS_OK;
+}
+
+// nsIStreamListener
+NS_IMETHODIMP
+FileIOObject::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
+{
+  return DoOnStartRequest(aRequest, aContext);
+}
+
+NS_IMETHODIMP
+FileIOObject::DoOnStartRequest(nsIRequest *request, nsISupports *ctxt)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+FileIOObject::OnDataAvailable(nsIRequest *aRequest,
+                              nsISupports *aContext,
+                              nsIInputStream *aInputStream,
+                              PRUint32 aOffset,
+                              PRUint32 aCount)
+{
+  nsresult rv;
+  rv = DoOnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mTransferred += aCount;
+
+  //Notify the timer is the appropriate timeframe has passed
+  if (mTimerIsActive) {
+    mProgressEventWasDelayed = PR_TRUE;
+  } else {
+    rv = DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    StartProgressEventTimer();
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+FileIOObject::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
+                            nsresult aStatus)
+{
+  // If we're here as a result of a call from Abort(),
+  // simply ignore the request.
+  if (aRequest != mChannel)
+    return NS_OK;
+
+  // Cancel the progress event timer
+  ClearProgressEventTimer();
+
+  // FileIOObject must be in DONE stage after an operation
+  mReadyState = 2;
+
+  nsString successEvent, termEvent;
+  nsresult rv = DoOnStopRequest(aRequest, aContext, aStatus,
+                                successEvent, termEvent);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Set the status field as appropriate
+  if (NS_FAILED(aStatus)) {
+    DispatchError(aStatus, termEvent);
+    return NS_OK;
+  }
+
+  // Dispatch event to signify end of a successful operation
+  DispatchProgressEvent(successEvent);
+  DispatchProgressEvent(termEvent);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+FileIOObject::Abort()
+{
+  if (mReadyState != 1)
+    return NS_ERROR_DOM_FILE_ABORT_ERR;
+
+  ClearProgressEventTimer();
+
+  mReadyState = 2; // There are DONE constants on multiple interfaces,
+                   // but they all have value 2.
+  mError = new nsDOMFileError(nsIDOMFileError::ABORT_ERR);
+
+  nsString finalEvent;
+  nsresult rv = DoAbort(finalEvent);
+
+  // Dispatch the events
+  DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR));
+  DispatchProgressEvent(finalEvent);
+
+  return rv;
+}
+
+NS_IMETHODIMP
+FileIOObject::GetReadyState(PRUint16 *aReadyState)
+{
+  *aReadyState = mReadyState;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+FileIOObject::GetError(nsIDOMFileError** aError)
+{
+  NS_IF_ADDREF(*aError = mError);
+  return NS_OK;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/base/src/FileIOObject.h
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozila.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Kyle Huey <me@kylehuey.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef FileIOObject_h__
+#define FileIOObject_h__
+
+#include "nsIDOMEventTarget.h"
+#include "nsDOMEventTargetWrapperCache.h"
+#include "nsIChannel.h"
+#include "nsIFile.h"
+#include "nsIDOMFile.h"
+#include "nsIStreamListener.h"
+#include "nsITimer.h"
+
+#include "nsCOMPtr.h"
+
+#define NS_PROGRESS_EVENT_INTERVAL 50
+
+namespace mozilla {
+namespace dom {
+
+extern const PRUint64 kUnknownSize;
+
+// A common base class for FileReader and FileSaver
+
+class FileIOObject : public nsDOMEventTargetWrapperCache,
+                     public nsIStreamListener,
+                     public nsITimerCallback
+{
+public:
+  FileIOObject();
+  ~FileIOObject();
+
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // Common methods
+  NS_METHOD Abort();
+  NS_METHOD GetReadyState(PRUint16* aReadyState);
+  NS_METHOD GetError(nsIDOMFileError** aError);
+
+  NS_DECL_EVENT_HANDLER(abort);
+  NS_DECL_EVENT_HANDLER(error);
+  NS_DECL_EVENT_HANDLER(progress);
+
+  NS_DECL_NSITIMERCALLBACK
+
+  NS_DECL_NSISTREAMLISTENER
+
+  NS_DECL_NSIREQUESTOBSERVER
+
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FileIOObject,
+                                           nsDOMEventTargetWrapperCache)
+
+protected:
+  // Implemented by the derived class to do whatever it needs to do for abort
+  NS_IMETHOD DoAbort(nsAString& aEvent) = 0;
+  // for onStartRequest (this has a default impl since FileReader doesn't need
+  // special handling
+  NS_IMETHOD DoOnStartRequest(nsIRequest *aRequest, nsISupports *aContext);
+  // for onStopRequest
+  NS_IMETHOD DoOnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
+                             nsresult aStatus, nsAString& aSuccessEvent,
+                             nsAString& aTerminationEvent) = 0;
+  // and for onDataAvailable
+  NS_IMETHOD DoOnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
+                               nsIInputStream *aInputStream, PRUint32 aOffset,
+                               PRUint32 aCount) = 0;
+
+  void StartProgressEventTimer();
+  void ClearProgressEventTimer();
+  void DispatchError(nsresult rv, nsAString& finalEvent);
+  nsresult DispatchProgressEvent(const nsAString& aType);
+
+  nsCOMPtr<nsITimer> mProgressNotifier;
+  bool mProgressEventWasDelayed;
+  bool mTimerIsActive;
+
+  nsCOMPtr<nsIDOMFileError> mError;
+  nsCOMPtr<nsIChannel> mChannel;
+
+  PRUint16 mReadyState;
+
+  PRUint64 mTotal;
+  PRUint64 mTransferred;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -150,16 +150,17 @@ CPPSRCS		= \
 		nsXMLHttpRequest.cpp \
 		nsXMLNameSpaceMap.cpp \
 		Link.cpp \
 		nsFileDataProtocolHandler.cpp \
 		nsFrameMessageManager.cpp \
 		nsInProcessTabChildGlobal.cpp \
 		ThirdPartyUtil.cpp \
 		nsEventSource.cpp \
+		FileIOObject.cpp \
 		$(NULL)
 
 # Are we targeting x86-32 or x86-64?  If so, we want to include SSE2 code for
 # nsTextFragment.cpp
 ifneq (,$(INTEL_ARCHITECTURE))
 CPPSRCS += nsTextFragmentSSE2.cpp
 endif
 
--- a/content/base/src/nsDOMEventTargetWrapperCache.cpp
+++ b/content/base/src/nsDOMEventTargetWrapperCache.cpp
@@ -35,16 +35,19 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsContentUtils.h"
 #include "nsDOMEventTargetWrapperCache.h"
 #include "nsIDocument.h"
+#include "nsIJSContextStack.h"
+#include "nsServiceManagerUtils.h"
+#include "nsDOMJSUtils.h"
 
 nsDOMEventTargetWrapperCache::~nsDOMEventTargetWrapperCache()
 {
   nsISupports *supports = static_cast<nsIDOMEventTarget*>(this);
   nsContentUtils::ReleaseWrapper(supports, this);
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEventTargetWrapperCache)
@@ -64,8 +67,34 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMEventTargetWrapperCache)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsDOMEventTargetWrapperCache, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsDOMEventTargetWrapperCache, nsDOMEventTargetHelper)
+
+void
+nsDOMEventTargetWrapperCache::Init(JSContext* aCx)
+{
+  // Set the original mScriptContext and mPrincipal, if available
+  JSContext* cx = aCx;
+  if (!cx) {
+    nsIJSContextStack* stack = nsContentUtils::ThreadJSContextStack();
+
+    if (!stack)
+      return;
+
+    if (NS_FAILED(stack->Peek(&cx)) || !cx)
+      return;
+  }
+
+  NS_ASSERTION(cx, "Should have returned earlier ...");
+  nsIScriptContext* context = GetScriptContextFromJSContext(cx);
+  if (context) {
+    mScriptContext = context;
+    nsCOMPtr<nsPIDOMWindow> window =
+      do_QueryInterface(context->GetGlobalObject());
+    if (window)
+      mOwner = window->GetCurrentInnerWindow();
+  }
+}
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -67,82 +67,72 @@
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMEventListener.h"
 #include "nsIJSContextStack.h"
 #include "nsJSEnvironment.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIDOMClassInfo.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIStreamConverterService.h"
-#include "nsEventDispatcher.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsLayoutStatics.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsFileDataProtocolHandler.h"
 #include "mozilla/Preferences.h"
-#include "xpcprivate.h" 	
+#include "xpcprivate.h"
+#include "xpcpublic.h"
 #include "xpcquickstubs.h"
 #include "jstypedarray.h"
 
 using namespace mozilla;
 
 #define LOAD_STR "load"
-#define ERROR_STR "error"
-#define ABORT_STR "abort"
 #define LOADSTART_STR "loadstart"
-#define PROGRESS_STR "progress"
-#define UPLOADPROGRESS_STR "uploadprogress"
 #define LOADEND_STR "loadend"
 
-#define NS_PROGRESS_EVENT_INTERVAL 50
-const PRUint64 kUnknownSize = PRUint64(-1);
+using mozilla::dom::FileIOObject;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileReader)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileReader,
-                                                  nsXHREventTarget)
+                                                  FileIOObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFile)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mProgressNotifier)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileReader,
-                                                nsXHREventTarget)
+                                                FileIOObject)
   tmp->mResultArrayBuffer = nsnull;
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFile)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressNotifier)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrincipal)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsDOMFileReader,
-                                               nsXHREventTarget)
+                                               nsDOMEventTargetWrapperCache)
   if(tmp->mResultArrayBuffer) {
     NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->mResultArrayBuffer,
                                                "mResultArrayBuffer")
   }
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 DOMCI_DATA(FileReader, nsDOMFileReader)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMFileReader)
   NS_INTERFACE_MAP_ENTRY(nsIDOMFileReader)
-  NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
-  NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(FileReader)
-NS_INTERFACE_MAP_END_INHERITING(nsXHREventTarget)
+NS_INTERFACE_MAP_END_INHERITING(FileIOObject)
 
-NS_IMPL_ADDREF_INHERITED(nsDOMFileReader, nsXHREventTarget)
-NS_IMPL_RELEASE_INHERITED(nsDOMFileReader, nsXHREventTarget)
+NS_IMPL_ADDREF_INHERITED(nsDOMFileReader, FileIOObject)
+NS_IMPL_RELEASE_INHERITED(nsDOMFileReader, FileIOObject)
 
 void
 nsDOMFileReader::RootResultArrayBuffer()
 {
   nsContentUtils::PreserveWrapper(
     static_cast<nsIDOMEventTarget*>(
       static_cast<nsDOMEventTargetHelper*>(this)), this);
 }
@@ -156,76 +146,53 @@ nsDOMFileReader::Notify(const char *aCha
   return NS_OK;
 }
 
 //nsDOMFileReader constructors/initializers
 
 nsDOMFileReader::nsDOMFileReader()
   : mFileData(nsnull),
     mDataLen(0), mDataFormat(FILE_AS_BINARY),
-    mReadyState(nsIDOMFileReader::EMPTY),
-    mProgressEventWasDelayed(PR_FALSE),
-    mTimerIsActive(PR_FALSE),
-    mReadTotal(0), mReadTransferred(0),
     mResultArrayBuffer(nsnull)     
 {
   nsLayoutStatics::AddRef();
   SetDOMStringToNull(mResult);
 }
 
 nsDOMFileReader::~nsDOMFileReader()
 {
-  if (mListenerManager) 
-    mListenerManager->Disconnect();
-
   FreeFileData();
 
   nsLayoutStatics::Release();
 }
 
 nsresult
 nsDOMFileReader::Init()
 {
-  // Set the original mScriptContext and mPrincipal, if available.
-  // Get JSContext from stack.
-  nsCOMPtr<nsIJSContextStack> stack =
-    do_GetService("@mozilla.org/js/xpc/ContextStack;1");
-
-  if (!stack) {
-    return NS_OK;
-  }
-
-  JSContext *cx;
-
-  if (NS_FAILED(stack->Peek(&cx)) || !cx) {
-    return NS_OK;
-  }
+  nsDOMEventTargetWrapperCache::Init();
 
   nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
   nsCOMPtr<nsIPrincipal> subjectPrincipal;
   if (secMan) {
     nsresult rv = secMan->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
     NS_ENSURE_SUCCESS(rv, rv);
   }
   NS_ENSURE_STATE(subjectPrincipal);
-  mPrincipal = subjectPrincipal;
-
-  nsIScriptContext* context = GetScriptContextFromJSContext(cx);
-  if (context) {
-    mScriptContext = context;
-    nsCOMPtr<nsPIDOMWindow> window =
-      do_QueryInterface(context->GetGlobalObject());
-    if (window) {
-      mOwner = window->GetCurrentInnerWindow();
-    }
-  }
+  mPrincipal.swap(subjectPrincipal);
 
   return NS_OK;
 }
 
+NS_IMPL_EVENT_HANDLER(nsDOMFileReader, load)
+NS_IMPL_EVENT_HANDLER(nsDOMFileReader, loadstart)
+NS_IMPL_EVENT_HANDLER(nsDOMFileReader, loadend)
+NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, abort, FileIOObject)
+NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, progress, FileIOObject)
+NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, error, FileIOObject)
+
 NS_IMETHODIMP
 nsDOMFileReader::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
                             PRUint32 argc, jsval *argv)
 {
   mOwner = do_QueryInterface(aOwner);
   if (!mOwner) {
     NS_WARNING("Unexpected nsIJSNativeInitializer owner");
     return NS_OK;
@@ -252,18 +219,17 @@ nsDOMFileReader::GetInterface(const nsII
   return QueryInterface(aIID, aResult);
 }
 
 // nsIDOMFileReader
 
 NS_IMETHODIMP
 nsDOMFileReader::GetReadyState(PRUint16 *aReadyState)
 {
-  *aReadyState = mReadyState;
-  return NS_OK;
+  return FileIOObject::GetReadyState(aReadyState);
 }
 
 NS_IMETHODIMP
 nsDOMFileReader::GetResult(JSContext* aCx, jsval* aResult)
 {
   if (mDataFormat == FILE_AS_ARRAYBUFFER) {
     if (mReadyState == nsIDOMFileReader::DONE && mResultArrayBuffer) {
       JSObject* tmp = mResultArrayBuffer;
@@ -279,18 +245,17 @@ nsDOMFileReader::GetResult(JSContext* aC
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMFileReader::GetError(nsIDOMFileError** aError)
 {
-  NS_IF_ADDREF(*aError = mError);
-  return NS_OK;
+  return FileIOObject::GetError(aError);
 }
 
 NS_IMETHODIMP
 nsDOMFileReader::ReadAsArrayBuffer(nsIDOMBlob* aFile, JSContext* aCx)
 {
   return ReadFileContent(aCx, aFile, EmptyString(), FILE_AS_ARRAYBUFFER);
 }
 
@@ -311,85 +276,39 @@ NS_IMETHODIMP
 nsDOMFileReader::ReadAsDataURL(nsIDOMBlob* aFile)
 {
   return ReadFileContent(nsnull, aFile, EmptyString(), FILE_AS_DATAURL);
 }
 
 NS_IMETHODIMP
 nsDOMFileReader::Abort()
 {
-  if (mReadyState != nsIDOMFileReader::LOADING)
-    return NS_ERROR_DOM_FILE_ABORT_ERR;
+  return FileIOObject::Abort();
+}
 
-  //Clear progress and file data
-  mProgressEventWasDelayed = PR_FALSE;
-  mTimerIsActive = PR_FALSE;
-  if (mProgressNotifier) {
-    mProgressNotifier->Cancel();
-  }
-
-  //Revert status, result and readystate attributes
+nsresult
+nsDOMFileReader::DoAbort(nsAString& aEvent)
+{
+  // Revert status and result attributes
   SetDOMStringToNull(mResult);
   mResultArrayBuffer = nsnull;
-  mReadyState = nsIDOMFileReader::DONE;
-  mError = new nsDOMFileError(nsIDOMFileError::ABORT_ERR);
     
-  //Non-null channel indicates a read is currently active
+  // Non-null channel indicates a read is currently active
   if (mChannel) {
-    //Cancel request requires an error status
+    // Cancel request requires an error status
     mChannel->Cancel(NS_ERROR_FAILURE);
     mChannel = nsnull;
   }
   mFile = nsnull;
 
   //Clean up memory buffer
   FreeFileData();
 
-  //Dispatch the abort event
-  DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR));
-  DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
-
-  mReadyState = nsIDOMFileReader::EMPTY;
-
-  return NS_OK;
-}
-
-// nsITimerCallback
-NS_IMETHODIMP
-nsDOMFileReader::Notify(nsITimer* aTimer)
-{
-  mTimerIsActive = PR_FALSE;
-  if (mProgressEventWasDelayed) {
-    DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR));
-    StartProgressEventTimer();
-  }
-
-  return NS_OK;
-}
-
-void
-nsDOMFileReader::StartProgressEventTimer()
-{
-  if (!mProgressNotifier) {
-    mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
-  }
-  if (mProgressNotifier) {
-    mProgressEventWasDelayed = PR_FALSE;
-    mTimerIsActive = PR_TRUE;
-    mProgressNotifier->Cancel();
-    mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,
-                                              nsITimer::TYPE_ONE_SHOT);
-  }
-}
-
-// nsIStreamListener
-
-NS_IMETHODIMP
-nsDOMFileReader::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
-{
+  // Tell the base class which event to dispatch
+  aEvent = NS_LITERAL_STRING(LOADEND_STR);
   return NS_OK;
 }
 
 static
 NS_METHOD
 ReadFuncBinaryString(nsIInputStream* in,
                      void* closure,
                      const char* fromRawSegment,
@@ -405,22 +324,22 @@ ReadFuncBinaryString(nsIInputStream* in,
     ++dest;
     ++source;
   }
   *writeCount = count;
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDOMFileReader::OnDataAvailable(nsIRequest *aRequest,
-                                 nsISupports *aContext,
-                                 nsIInputStream *aInputStream,
-                                 PRUint32 aOffset,
-                                 PRUint32 aCount)
+nsresult
+nsDOMFileReader::DoOnDataAvailable(nsIRequest *aRequest,
+                                   nsISupports *aContext,
+                                   nsIInputStream *aInputStream,
+                                   PRUint32 aOffset,
+                                   PRUint32 aCount)
 {
   if (mDataFormat == FILE_AS_BINARY) {
     //Continuously update our binary string as data comes in
     NS_ASSERTION(mResult.Length() == aOffset,
                  "unexpected mResult length");
     PRUint32 oldLen = mResult.Length();
     PRUnichar *buf = nsnull;
     mResult.GetMutableData(&buf, oldLen + aCount);
@@ -446,54 +365,32 @@ nsDOMFileReader::OnDataAvailable(nsIRequ
 
     PRUint32 bytesRead = 0;
     aInputStream->Read(mFileData + aOffset, aCount, &bytesRead);
     NS_ASSERTION(bytesRead == aCount, "failed to read data");
 
     mDataLen += aCount;
   }
 
-  mReadTransferred += aCount;
-
-  //Notify the timer is the appropriate timeframe has passed
-  if (mTimerIsActive) {
-    mProgressEventWasDelayed = PR_TRUE;
-  }
-  else {
-    DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR));
-    StartProgressEventTimer();
-  }
-
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDOMFileReader::OnStopRequest(nsIRequest *aRequest,
-                               nsISupports *aContext,
-                               nsresult aStatus)
+nsresult
+nsDOMFileReader::DoOnStopRequest(nsIRequest *aRequest,
+                                 nsISupports *aContext,
+                                 nsresult aStatus,
+                                 nsAString& aSuccessEvent,
+                                 nsAString& aTerminationEvent)
 {
-  //If we're here as a result of a call from Abort(),
-  //simply ignore the request.
-  if (aRequest != mChannel)
-    return NS_OK;
+  aSuccessEvent = NS_LITERAL_STRING(LOAD_STR);
+  aTerminationEvent = NS_LITERAL_STRING(LOADEND_STR);
 
-  //Cancel the progress event timer
-  mProgressEventWasDelayed = PR_FALSE;
-  mTimerIsActive = PR_FALSE;
-  if (mProgressNotifier) {
-    mProgressNotifier->Cancel();
-  }
-
-  //FileReader must be in DONE stage after a load
-  mReadyState = nsIDOMFileReader::DONE;
-
-  //Set the status field as appropriate
+  // Clear out the data if necessary
   if (NS_FAILED(aStatus)) {
     FreeFileData();
-    DispatchError(aStatus);
     return NS_OK;
   }
 
   nsresult rv = NS_OK;
   switch (mDataFormat) {
     case FILE_AS_ARRAYBUFFER:
       break; //Already accumulated mResultArrayBuffer
     case FILE_AS_BINARY:
@@ -505,26 +402,17 @@ nsDOMFileReader::OnStopRequest(nsIReques
       rv = GetAsDataURL(mFile, mFileData, mDataLen, mResult);
       break;
   }
   
   mResult.SetIsVoid(PR_FALSE);
 
   FreeFileData();
 
-  if (NS_FAILED(rv)) {
-    DispatchError(rv);
-    return NS_OK;
-  }
-
-  //Dispatch load event to signify end of a successful load
-  DispatchProgressEvent(NS_LITERAL_STRING(LOAD_STR));
-  DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
-
-  return NS_OK;
+  return rv;
 }
 
 // Helper methods
 
 nsresult
 nsDOMFileReader::ReadFileContent(JSContext* aCx,
                                  nsIDOMBlob* aFile,
                                  const nsAString &aCharset,
@@ -532,18 +420,18 @@ nsDOMFileReader::ReadFileContent(JSConte
 {
   nsresult rv;
   NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
 
   //Implicit abort to clear any other activity going on
   Abort();
   mError = nsnull;
   SetDOMStringToNull(mResult);
-  mReadTransferred = 0;
-  mReadTotal = 0;
+  mTransferred = 0;
+  mTotal = 0;
   mReadyState = nsIDOMFileReader::EMPTY;
   FreeFileData();
 
   mFile = aFile;
   mDataFormat = aDataFormat;
   CopyUTF16toUTF8(aCharset, mCharset);
 
   //Establish a channel with our file
@@ -557,96 +445,38 @@ nsDOMFileReader::ReadFileContent(JSConte
     rv = NS_NewURI(getter_AddRefs(uri), urlHolder.mUrl);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = NS_NewChannel(getter_AddRefs(mChannel), uri);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   //Obtain the total size of the file before reading
-  mReadTotal = kUnknownSize;
-  mFile->GetSize(&mReadTotal);
+  mTotal = mozilla::dom::kUnknownSize;
+  mFile->GetSize(&mTotal);
 
   rv = mChannel->AsyncOpen(this, nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
 
   //FileReader should be in loading state here
   mReadyState = nsIDOMFileReader::LOADING;
   DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
   
   if (mDataFormat == FILE_AS_ARRAYBUFFER) {
     RootResultArrayBuffer();
-    mResultArrayBuffer = js_CreateArrayBuffer(aCx, mReadTotal);
+    mResultArrayBuffer = js_CreateArrayBuffer(aCx, mTotal);
     if (!mResultArrayBuffer) {
       NS_WARNING("Failed to create JS array buffer");
       return NS_ERROR_FAILURE;
     }
   }
  
   return NS_OK;
 }
 
-void
-nsDOMFileReader::DispatchError(nsresult rv)
-{
-  //Set the status attribute, and dispatch the error event
-  switch (rv) {
-    case NS_ERROR_FILE_NOT_FOUND:
-      mError = new nsDOMFileError(nsIDOMFileError::NOT_FOUND_ERR);
-      break;
-    case NS_ERROR_FILE_ACCESS_DENIED:
-      mError = new nsDOMFileError(nsIDOMFileError::SECURITY_ERR);
-      break;
-    default:
-      mError = new nsDOMFileError(nsIDOMFileError::NOT_READABLE_ERR);
-      break;
-  }
-
-  //Dispatch error event to signify load failure
-  DispatchProgressEvent(NS_LITERAL_STRING(ERROR_STR));
-  DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
-}
-
-void
-nsDOMFileReader::DispatchProgressEvent(const nsAString& aType)
-{
-  nsCOMPtr<nsIDOMEvent> event;
-  nsresult rv = nsEventDispatcher::CreateEvent(nsnull, nsnull,
-                                               NS_LITERAL_STRING("ProgressEvent"),
-                                               getter_AddRefs(event));
-  if (NS_FAILED(rv))
-    return;
-
-  nsCOMPtr<nsIPrivateDOMEvent> privevent(do_QueryInterface(event));
-
-  if (!privevent)
-    return;
-
-  privevent->SetTrusted(PR_TRUE);
-
-  nsCOMPtr<nsIDOMProgressEvent> progress = do_QueryInterface(event);
-
-  if (!progress)
-    return;
-
-  bool known;
-  PRUint64 size;
-  if (mReadTotal != kUnknownSize) {
-    known = PR_TRUE;
-    size = mReadTotal;
-  } else {
-    known = PR_FALSE;
-    size = 0;
-  }
-  progress->InitProgressEvent(aType, PR_FALSE, PR_FALSE, known,
-                              mReadTransferred, size);
-
-  this->DispatchDOMEvent(nsnull, event, nsnull, nsnull);
-}
-
 nsresult
 nsDOMFileReader::GetAsText(const nsACString &aCharset,
                            const char *aFileData,
                            PRUint32 aDataLen,
                            nsAString& aResult)
 {
   nsresult rv;
   nsCAutoString charsetGuess;
--- a/content/base/src/nsDOMFileReader.h
+++ b/content/base/src/nsDOMFileReader.h
@@ -34,129 +34,109 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsDOMFileReader_h__
 #define nsDOMFileReader_h__
 
 #include "nsISupportsUtils.h"      
-#include "nsString.h"              
+#include "nsString.h"
+#include "nsWeakReference.h"
 #include "nsIStreamListener.h"     
-#include "nsIScriptContext.h"      
 #include "nsIInterfaceRequestor.h" 
 #include "nsJSUtils.h"             
 #include "nsTArray.h"              
 #include "nsIJSNativeInitializer.h"
 #include "prtime.h"                
 #include "nsITimer.h"              
-#include "nsDOMEventTargetHelper.h"
 #include "nsICharsetDetector.h"
 #include "nsICharsetDetectionObserver.h"
 
 #include "nsIDOMFile.h"
 #include "nsIDOMFileReader.h"
 #include "nsIDOMFileList.h"
 #include "nsIDOMFileError.h"
 #include "nsIInputStream.h"
 #include "nsCOMPtr.h"
 #include "nsIStreamLoader.h"
 #include "nsIChannel.h"
 #include "prmem.h"
 
-#include "nsXMLHttpRequest.h"
+#include "FileIOObject.h"
 
-class nsDOMFileReader : public nsXHREventTarget,
+class nsDOMFileReader : public mozilla::dom::FileIOObject,
                         public nsIDOMFileReader,
-                        public nsIStreamListener,
                         public nsIInterfaceRequestor,
                         public nsSupportsWeakReference,
                         public nsIJSNativeInitializer,
-                        public nsITimerCallback,
                         public nsICharsetDetectionObserver
 {
 public:
   nsDOMFileReader();
   virtual ~nsDOMFileReader();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSIDOMFILEREADER
 
-  NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::);
-        
-  // nsIStreamListener
-  NS_DECL_NSISTREAMLISTENER
-                               
-  // nsIRequestObserver
-  NS_DECL_NSIREQUESTOBSERVER
-                               
+  NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
+
   // nsIInterfaceRequestor 
   NS_DECL_NSIINTERFACEREQUESTOR
 
-  // nsITimerCallback
-  NS_DECL_NSITIMERCALLBACK
-                               
   // nsIJSNativeInitializer                                                
   NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj, 
                         PRUint32 argc, jsval* argv);
 
-  NS_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget::)
-
   // nsICharsetDetectionObserver
   NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf);
 
-  void DispatchProgressEvent(const nsAString& aType);
+  // FileIOObject overrides
+  NS_IMETHOD DoAbort(nsAString& aEvent);
+  NS_IMETHOD DoOnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
+                             nsresult aStatus, nsAString& aSuccessEvent,
+                             nsAString& aTerminationEvent);
+  NS_IMETHOD DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
+                               nsIInputStream* aInputStream, PRUint32 aOffset,
+                               PRUint32 aCount);
 
   nsresult Init();
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsDOMFileReader,
-                                           nsXHREventTarget) 
+                                                         FileIOObject)
   void RootResultArrayBuffer();
 
 protected:
   enum eDataFormat {
     FILE_AS_ARRAYBUFFER,
     FILE_AS_BINARY,
     FILE_AS_TEXT,
     FILE_AS_DATAURL
   };
 
   nsresult ReadFileContent(JSContext* aCx, nsIDOMBlob *aFile, const nsAString &aCharset, eDataFormat aDataFormat); 
   nsresult GetAsText(const nsACString &aCharset,
                      const char *aFileData, PRUint32 aDataLen, nsAString &aResult);
   nsresult GetAsDataURL(nsIDOMBlob *aFile, const char *aFileData, PRUint32 aDataLen, nsAString &aResult); 
   nsresult GuessCharset(const char *aFileData, PRUint32 aDataLen, nsACString &aCharset); 
   nsresult ConvertStream(const char *aFileData, PRUint32 aDataLen, const char *aCharset, nsAString &aResult); 
-  void DispatchError(nsresult rv);
-  void StartProgressEventTimer();
 
   void FreeFileData() {
     PR_Free(mFileData);
     mFileData = nsnull;
     mDataLen = 0;
   }
 
   char *mFileData;
   nsCOMPtr<nsIDOMBlob> mFile;
   nsCString mCharset;
   PRUint32 mDataLen;
 
   eDataFormat mDataFormat;
 
   nsString mResult;
-  PRUint16 mReadyState;
-
-  bool mProgressEventWasDelayed;
-  bool mTimerIsActive;
-  nsCOMPtr<nsIDOMFileError> mError;
-
-  nsCOMPtr<nsITimer> mProgressNotifier;
   nsCOMPtr<nsIPrincipal> mPrincipal;
-  nsCOMPtr<nsIChannel> mChannel;
-
-  PRUint64 mReadTotal;
-  PRUint64 mReadTransferred;
   
   JSObject* mResultArrayBuffer;
 };
 
 #endif
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1820,17 +1820,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
 
   // Traverse the mChildren nsAttrAndChildArray.
   for (PRInt32 indx = PRInt32(tmp->mChildren.ChildCount()); indx > 0; --indx) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mChildren[i]");
     cb.NoteXPCOMChild(tmp->mChildren.ChildAt(indx - 1));
   }
 
   // Traverse all nsIDocument pointer members.
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCachedRootElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSecurityInfo)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDisplayDocument)
 
   // Traverse all nsDocument nsCOMPtrs.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParser)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptGlobalObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
                                                   nsEventListenerManager)
@@ -1901,17 +1900,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   for (PRInt32 indx = PRInt32(tmp->mChildren.ChildCount()) - 1; 
        indx >= 0; --indx) {
     tmp->mChildren.ChildAt(indx)->UnbindFromTree();
     tmp->mChildren.RemoveChildAt(indx);
   }
   tmp->mFirstChild = nsnull;
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXPathEvaluatorTearoff)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedRootElement)
+  tmp->mCachedRootElement = nsnull; // Avoid a dangling pointer
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDisplayDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstBaseNodeWithHref)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDOMImplementation)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mImageMaps)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOriginalDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedEncoder)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFullScreenElement)
 
@@ -3392,25 +3391,32 @@ nsDocument::NodeType()
 
 void
 nsDocument::NodeName(nsAString& aNodeName)
 {
   aNodeName.AssignLiteral("#document");
 }
 
 Element*
+nsIDocument::GetRootElement() const
+{
+  return (mCachedRootElement && mCachedRootElement->GetNodeParent() == this) ?
+         mCachedRootElement : GetRootElementInternal();
+}
+
+Element*
 nsDocument::GetRootElementInternal() const
 {
   // Loop backwards because any non-elements, such as doctypes and PIs
   // are likely to appear before the root element.
   PRUint32 i;
   for (i = mChildren.ChildCount(); i > 0; --i) {
     nsIContent* child = mChildren.ChildAt(i - 1);
     if (child->IsElement()) {
-      const_cast<nsDocument*>(this)->mCachedRootElement = child;
+      const_cast<nsDocument*>(this)->mCachedRootElement = child->AsElement();
       return child->AsElement();
     }
   }
   
   const_cast<nsDocument*>(this)->mCachedRootElement = nsnull;
   return nsnull;
 }
 
--- a/content/base/src/nsEventSource.cpp
+++ b/content/base/src/nsEventSource.cpp
@@ -54,16 +54,17 @@
 #include "nsJSUtils.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIScriptError.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
+#include "xpcpublic.h"
 
 using namespace mozilla;
 
 #define REPLACEMENT_CHAR     (PRUnichar)0xFFFD
 #define BOM_CHAR             (PRUnichar)0xFEFF
 #define SPACE_CHAR           (PRUnichar)0x0020
 #define CR_CHAR              (PRUnichar)0x000D
 #define LF_CHAR              (PRUnichar)0x000A
@@ -108,27 +109,21 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventSo
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsEventSource,
                                                   nsDOMEventTargetWrapperCache)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSrc)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNotificationCallbacks)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLoadGroup)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannelEventSink)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mHttpChannel)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTimer)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnOpenListener)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnMessageListener)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mUnicodeDecoder)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsEventSource, nsDOMEventTargetWrapperCache)
   tmp->Close();
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnOpenListener)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnMessageListener)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 DOMCI_DATA(EventSource, nsEventSource)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsEventSource)
   NS_INTERFACE_MAP_ENTRY(nsIEventSource)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
@@ -157,33 +152,19 @@ nsEventSource::GetUrl(nsAString& aURL)
 NS_IMETHODIMP
 nsEventSource::GetReadyState(PRInt32 *aReadyState)
 {
   NS_ENSURE_ARG_POINTER(aReadyState);
   *aReadyState = mReadyState;
   return NS_OK;
 }
 
-#define NS_EVENTSRC_IMPL_DOMEVENTLISTENER(_eventlistenername, _eventlistener)  \
-  NS_IMETHODIMP                                                                \
-  nsEventSource::GetOn##_eventlistenername(nsIDOMEventListener * *aListener)   \
-  {                                                                            \
-    return GetInnerEventListener(_eventlistener, aListener);                   \
-  }                                                                            \
-                                                                               \
-  NS_IMETHODIMP                                                                \
-  nsEventSource::SetOn##_eventlistenername(nsIDOMEventListener * aListener)    \
-  {                                                                            \
-    return RemoveAddEventListener(NS_LITERAL_STRING(#_eventlistenername),      \
-                                  _eventlistener, aListener);                  \
-  }
-
-NS_EVENTSRC_IMPL_DOMEVENTLISTENER(open, mOnOpenListener)
-NS_EVENTSRC_IMPL_DOMEVENTLISTENER(error, mOnErrorListener)
-NS_EVENTSRC_IMPL_DOMEVENTLISTENER(message, mOnMessageListener)
+NS_IMPL_EVENT_HANDLER(nsEventSource, open)
+NS_IMPL_EVENT_HANDLER(nsEventSource, error)
+NS_IMPL_EVENT_HANDLER(nsEventSource, message)
 
 NS_IMETHODIMP
 nsEventSource::Close()
 {
   if (mReadyState == nsIEventSource::CLOSED) {
     return NS_OK;
   }
 
--- a/content/base/src/nsEventSource.h
+++ b/content/base/src/nsEventSource.h
@@ -217,20 +217,16 @@ protected:
   bool mGoingToDispatchAllMessages;
 
   // used while reading the input streams
   nsCOMPtr<nsIUnicodeDecoder> mUnicodeDecoder;
   nsresult mLastConvertionResult;
   nsString mLastFieldName;
   nsString mLastFieldValue;
 
-  nsRefPtr<nsDOMEventListenerWrapper> mOnOpenListener;
-  nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener;
-  nsRefPtr<nsDOMEventListenerWrapper> mOnMessageListener;
-
   nsCOMPtr<nsILoadGroup> mLoadGroup;
 
   /**
    * The notification callbacks the channel had initially.
    * We want to forward things here as needed.
    */
   nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
   nsCOMPtr<nsIChannelEventSink>   mChannelEventSink;
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1785,17 +1785,19 @@ GK_ATOM(svgRadialGradientFrame, "SVGRadi
 GK_ATOM(svgStopFrame, "SVGStopFrame")
 GK_ATOM(svgSwitchFrame, "SVGSwitchFrame")
 GK_ATOM(svgTextFrame, "SVGTextFrame")
 GK_ATOM(svgTextPathFrame, "SVGTextPathFrame")
 GK_ATOM(svgTSpanFrame, "SVGTSpanFrame")
 GK_ATOM(svgUseFrame, "SVGUseFrame")
 GK_ATOM(HTMLVideoFrame, "VideoFrame")
 GK_ATOM(onloadstart, "onloadstart")
+GK_ATOM(onloadend, "onloadend")
 GK_ATOM(onprogress, "onprogress")
+GK_ATOM(onuploadprogress, "onuploadprogress")
 GK_ATOM(onsuspend, "onsuspend")
 GK_ATOM(onemptied, "onemptied")
 GK_ATOM(onstalled, "onstalled")
 GK_ATOM(onplay, "onplay")
 GK_ATOM(onpause, "onpause")
 GK_ATOM(onloadedmetadata, "onloadedmetadata")
 GK_ATOM(onloadeddata, "onloadeddata")
 GK_ATOM(onwaiting, "onwaiting")
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -73,16 +73,17 @@
 #include "nsIScriptError.h"
 #include "nsNetUtil.h"
 #include "nsIWebSocketChannel.h"
 #include "nsIWebSocketListener.h"
 #include "nsILoadGroup.h"
 #include "nsIRequest.h"
 #include "mozilla/Preferences.h"
 #include "nsDOMLists.h"
+#include "xpcpublic.h"
 
 using namespace mozilla;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsWebSocketEstablishedConnection
 ////////////////////////////////////////////////////////////////////////////////
 
 #define UTF_8_REPLACEMENT_CHAR    static_cast<PRUnichar>(0xFFFD)
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -283,120 +283,40 @@ nsMultipartProxyListener::OnDataAvailabl
   return mDestListener->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset,
                                         count);
 }
 
 /////////////////////////////////////////////
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXHREventTarget)
 
+// nsXHREventTarget's CC participant doesn't actually do anything anymore
+// but these are left here as placeholders in case it needs to do something
+// in the future.
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXHREventTarget,
                                                   nsDOMEventTargetWrapperCache)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadListener)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnAbortListener)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadStartListener)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnProgressListener)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadendListener)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXHREventTarget,
                                                 nsDOMEventTargetWrapperCache)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadListener)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnAbortListener)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadStartListener)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnProgressListener)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadendListener)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXHREventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequestEventTarget)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetWrapperCache)
 
 NS_IMPL_ADDREF_INHERITED(nsXHREventTarget, nsDOMEventTargetWrapperCache)
 NS_IMPL_RELEASE_INHERITED(nsXHREventTarget, nsDOMEventTargetWrapperCache)
 
-NS_IMETHODIMP
-nsXHREventTarget::GetOnload(nsIDOMEventListener** aOnLoad)
-{
-  return GetInnerEventListener(mOnLoadListener, aOnLoad);
-}
-
-NS_IMETHODIMP
-nsXHREventTarget::SetOnload(nsIDOMEventListener* aOnLoad)
-{
-  return RemoveAddEventListener(NS_LITERAL_STRING(LOAD_STR),
-                                mOnLoadListener, aOnLoad);
-}
-
-NS_IMETHODIMP
-nsXHREventTarget::GetOnerror(nsIDOMEventListener** aOnerror)
-{
-  return GetInnerEventListener(mOnErrorListener, aOnerror);
-}
-
-NS_IMETHODIMP
-nsXHREventTarget::SetOnerror(nsIDOMEventListener* aOnerror)
-{
-  return RemoveAddEventListener(NS_LITERAL_STRING(ERROR_STR),
-                                mOnErrorListener, aOnerror);
-}
-
-NS_IMETHODIMP
-nsXHREventTarget::GetOnabort(nsIDOMEventListener** aOnabort)
-{
-  return GetInnerEventListener(mOnAbortListener, aOnabort);
-}
-
-NS_IMETHODIMP
-nsXHREventTarget::SetOnabort(nsIDOMEventListener* aOnabort)
-{
-  return RemoveAddEventListener(NS_LITERAL_STRING(ABORT_STR),
-                                mOnAbortListener, aOnabort);
-}
-
-NS_IMETHODIMP
-nsXHREventTarget::GetOnloadstart(nsIDOMEventListener** aOnloadstart)
-{
-  return GetInnerEventListener(mOnLoadStartListener, aOnloadstart);
-}
-
-NS_IMETHODIMP
-nsXHREventTarget::SetOnloadstart(nsIDOMEventListener* aOnloadstart)
-{
-  return RemoveAddEventListener(NS_LITERAL_STRING(LOADSTART_STR),
-                                mOnLoadStartListener, aOnloadstart);
-}
-
-NS_IMETHODIMP
-nsXHREventTarget::GetOnprogress(nsIDOMEventListener** aOnprogress)
-{
-  return GetInnerEventListener(mOnProgressListener, aOnprogress);
-}
-
-NS_IMETHODIMP
-nsXHREventTarget::SetOnprogress(nsIDOMEventListener* aOnprogress)
-{
-  return RemoveAddEventListener(NS_LITERAL_STRING(PROGRESS_STR),
-                                mOnProgressListener, aOnprogress);
-}
-
-NS_IMETHODIMP
-nsXHREventTarget::GetOnloadend(nsIDOMEventListener** aOnLoadend)
-{
-  return GetInnerEventListener(mOnLoadendListener, aOnLoadend);
-}
-
-NS_IMETHODIMP
-nsXHREventTarget::SetOnloadend(nsIDOMEventListener* aOnLoadend)
-{
-  return RemoveAddEventListener(NS_LITERAL_STRING(LOADEND_STR),
-                                mOnLoadendListener, aOnLoadend);
-}
+NS_IMPL_EVENT_HANDLER(nsXHREventTarget, load)
+NS_IMPL_EVENT_HANDLER(nsXHREventTarget, error)
+NS_IMPL_EVENT_HANDLER(nsXHREventTarget, abort)
+NS_IMPL_EVENT_HANDLER(nsXHREventTarget, loadstart)
+NS_IMPL_EVENT_HANDLER(nsXHREventTarget, progress)
+NS_IMPL_EVENT_HANDLER(nsXHREventTarget, loadend)
 
 /////////////////////////////////////////////
 
 nsXMLHttpRequestUpload::~nsXMLHttpRequestUpload()
 {
   if (mListenerManager) {
     mListenerManager->Disconnect();
   }
@@ -580,19 +500,16 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttp
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest,
                                                   nsXHREventTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mReadRequest)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mResponseXML)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCORSPreflightChannel)
 
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnUploadProgressListener)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnReadystatechangeListener)
-
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mXMLParserStreamListener)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannelEventSink)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mProgressEventSink)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mUpload,
                                                        nsIXMLHttpRequestUpload)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -602,19 +519,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
   tmp->mResultArrayBuffer = nsnull;
   tmp->mResultJSON = JSVAL_VOID;
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReadRequest)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mResponseXML)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCORSPreflightChannel)
 
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnUploadProgressListener)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnReadystatechangeListener)
-
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXMLParserStreamListener)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannelEventSink)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressEventSink)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mUpload)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
@@ -645,49 +559,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XMLHttpRequest)
 NS_INTERFACE_MAP_END_INHERITING(nsXHREventTarget)
 
 NS_IMPL_ADDREF_INHERITED(nsXMLHttpRequest, nsXHREventTarget)
 NS_IMPL_RELEASE_INHERITED(nsXMLHttpRequest, nsXHREventTarget)
 
-NS_IMETHODIMP
-nsXMLHttpRequest::GetOnreadystatechange(nsIDOMEventListener * *aOnreadystatechange)
-{
-  return
-    nsXHREventTarget::GetInnerEventListener(mOnReadystatechangeListener,
-                                            aOnreadystatechange);
-}
-
-NS_IMETHODIMP
-nsXMLHttpRequest::SetOnreadystatechange(nsIDOMEventListener * aOnreadystatechange)
-{
-  return
-    nsXHREventTarget::RemoveAddEventListener(NS_LITERAL_STRING(READYSTATE_STR),
-                                             mOnReadystatechangeListener,
-                                             aOnreadystatechange);
-}
-
-NS_IMETHODIMP
-nsXMLHttpRequest::GetOnuploadprogress(nsIDOMEventListener * *aOnuploadprogress)
-{
-  return
-    nsXHREventTarget::GetInnerEventListener(mOnUploadProgressListener,
-                                            aOnuploadprogress);
-}
-
-NS_IMETHODIMP
-nsXMLHttpRequest::SetOnuploadprogress(nsIDOMEventListener * aOnuploadprogress)
-{
-  return
-    nsXHREventTarget::RemoveAddEventListener(NS_LITERAL_STRING(UPLOADPROGRESS_STR),
-                                             mOnUploadProgressListener,
-                                             aOnuploadprogress);
-}
+NS_IMPL_EVENT_HANDLER(nsXMLHttpRequest, readystatechange)
+NS_IMPL_EVENT_HANDLER(nsXMLHttpRequest, uploadprogress)
 
 /* readonly attribute nsIChannel channel; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetChannel(nsIChannel **aChannel)
 {
   NS_ENSURE_ARG_POINTER(aChannel);
   NS_IF_ADDREF(*aChannel = mChannel);
 
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -75,24 +75,16 @@ class nsXHREventTarget : public nsDOMEve
 {
 public:
   virtual ~nsXHREventTarget() {}
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXHREventTarget,
                                            nsDOMEventTargetWrapperCache)
   NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
-
-protected:
-  nsRefPtr<nsDOMEventListenerWrapper> mOnLoadListener;
-  nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener;
-  nsRefPtr<nsDOMEventListenerWrapper> mOnAbortListener;
-  nsRefPtr<nsDOMEventListenerWrapper> mOnLoadStartListener;
-  nsRefPtr<nsDOMEventListenerWrapper> mOnProgressListener;
-  nsRefPtr<nsDOMEventListenerWrapper> mOnLoadendListener;
 };
 
 class nsXMLHttpRequestUpload : public nsXHREventTarget,
                                public nsIXMLHttpRequestUpload
 {
 public:
   nsXMLHttpRequestUpload(nsPIDOMWindow* aOwner,
                          nsIScriptContext* aScriptContext)
@@ -128,18 +120,17 @@ public:
   virtual ~nsXMLHttpRequest();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIXMLHttpRequest
   NS_DECL_NSIXMLHTTPREQUEST
 
   // nsIJSXMLHttpRequest
-  NS_IMETHOD GetOnuploadprogress(nsIDOMEventListener** aOnuploadprogress);
-  NS_IMETHOD SetOnuploadprogress(nsIDOMEventListener* aOnuploadprogress);
+  NS_DECL_NSIJSXMLHTTPREQUEST
 
   NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::)
 
   // nsIStreamListener
   NS_DECL_NSISTREAMLISTENER
 
   // nsIRequestObserver
   NS_DECL_NSIREQUESTOBSERVER
@@ -252,19 +243,16 @@ protected:
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIChannel> mChannel;
   // mReadRequest is different from mChannel for multipart requests
   nsCOMPtr<nsIRequest> mReadRequest;
   nsCOMPtr<nsIDOMDocument> mResponseXML;
   nsCOMPtr<nsIChannel> mCORSPreflightChannel;
   nsTArray<nsCString> mCORSUnsafeHeaders;
 
-  nsRefPtr<nsDOMEventListenerWrapper> mOnUploadProgressListener;
-  nsRefPtr<nsDOMEventListenerWrapper> mOnReadystatechangeListener;
-
   nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
 
   // used to implement getAllResponseHeaders()
   class nsHeaderVisitor : public nsIHttpHeaderVisitor {
   public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIHTTPHEADERVISITOR
     nsHeaderVisitor() { }
--- a/content/base/test/unit/test_bug553888.js
+++ b/content/base/test/unit/test_bug553888.js
@@ -74,21 +74,21 @@ function run_test() {
   server.registerPathHandler(headerCheckPath, headerCheckHandler);
   server.start(SERVER_PORT);
 
   do_test_pending();
   var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
                 .createInstance(Components.interfaces.nsIXMLHttpRequest);
   request.open("GET", redirectURL, true);
   request.setRequestHeader("X-Custom-Header", "present");
-  request.onreadystatechange = function() {
+  request.addEventListener("readystatechange", function() {
     if (request.readyState == 4) {
       do_check_eq(request.status, 200);
       server.stop(do_test_finished);
     }
-  };
+  }, false);
   request.send();
   try {
     request.setRequestHeader("X-Unwanted-Header", "present");
     do_throw("Shouldn't be able to set a header after send");
   } catch (x) {
   }    
 }
--- a/content/base/test/unit/test_error_codes.js
+++ b/content/base/test/unit/test_error_codes.js
@@ -41,17 +41,17 @@ var gNextTestFunc   = null;
 
 var asyncXHR = {
   load: function() {
     var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
                             .createInstance(Components.interfaces.nsIXMLHttpRequest);
     request.open("GET", "http://localhost:4444/test_error_code.xml", true);
 
     var self = this;
-    request.onerror = function(event) { self.onError(event); };
+    request.addEventListener("error", function(event) { self.onError(event); }, false);
     request.send(null);
   },
   onError: function doAsyncRequest_onError(event) {
     var request = event.target.channel.QueryInterface(Components.interfaces.nsIRequest);
     do_check_eq(request.status, gExpectedStatus);
     gNextTestFunc();
   }
 }
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -583,27 +583,16 @@ protected:
                                 BaseInterfaceType *aInterface,
                                 bool *isNull = 0,
                                 bool *isDeleted = 0);
 
     PRInt32 MaxTextureSizeForTarget(WebGLenum target) const {
         return target == LOCAL_GL_TEXTURE_2D ? mGLMaxTextureSize : mGLMaxCubeMapTextureSize;
     }
     
-    // bug 684882 comment 37. On Mac OS (confirmed on 10.7.1), Intel driver, rendering to a face of a cube map
-    // copies random video memory into it.
-    // In particular, since glGenerateMipmap does that, it must be avoided.
-    bool WorkAroundCubeMapBug684882() const {
-        #ifdef XP_MACOSX
-            return gl->Vendor() == gl::GLContext::VendorIntel;
-        #else
-            return false;
-        #endif
-    }
-    
     /** like glBufferData but if the call may change the buffer size, checks any GL error generated
      * by this glBufferData call and returns it */
     GLenum CheckedBufferData(GLenum target,
                              GLsizeiptr size,
                              const GLvoid *data,
                              GLenum usage);
     /** like glTexImage2D but if the call may change the texture size, checks any GL error generated
      * by this glTexImage2D call and returns it */
@@ -1160,17 +1149,16 @@ public:
     void SetWrapS(WebGLenum aWrapS) {
         mWrapS = aWrapS;
         SetDontKnowIfNeedFakeBlack();
     }
     void SetWrapT(WebGLenum aWrapT) {
         mWrapT = aWrapT;
         SetDontKnowIfNeedFakeBlack();
     }
-    
     WebGLenum MinFilter() const { return mMinFilter; }
 
     bool DoesMinFilterRequireMipmap() const {
         return !(mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_LINEAR);
     }
 
     void SetGeneratedMipmap() {
         if (!mHaveGeneratedMipmap) {
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -1691,27 +1691,20 @@ WebGLContext::FramebufferRenderbuffer(We
 
 NS_IMETHODIMP
 WebGLContext::FramebufferTexture2D(WebGLenum target,
                                    WebGLenum attachment,
                                    WebGLenum textarget,
                                    nsIWebGLTexture *tobj,
                                    WebGLint level)
 {
-    if (!mBoundFramebuffer)
+    if (mBoundFramebuffer)
+        return mBoundFramebuffer->FramebufferTexture2D(target, attachment, textarget, tobj, level);
+    else
         return ErrorInvalidOperation("framebufferTexture2D: cannot modify framebuffer 0");
-
-    if (textarget != LOCAL_GL_TEXTURE_2D && WorkAroundCubeMapBug684882()) {
-        return ErrorInvalidOperation("framebufferTexture2D: Attaching a face of a cube map to a framebuffer is disabled "
-                                     "on Mac OS X on Intel GPUs to protect you from a bug causing random "
-                                     "video memory to be copied into cube maps attached to framebuffers "
-                                     "(Mozilla bug 684882, Apple bug 9129398)");
-    }
-    
-    return mBoundFramebuffer->FramebufferTexture2D(target, attachment, textarget, tobj, level);
 }
 
 GL_SAME_METHOD_0(Flush, Flush)
 
 GL_SAME_METHOD_0(Finish, Finish)
 
 NS_IMETHODIMP
 WebGLContext::FrontFace(WebGLenum mode)
@@ -1779,28 +1772,17 @@ WebGLContext::GenerateMipmap(WebGLenum t
 
     if (!tex->AreAllLevel0ImageInfosEqual()) {
         return ErrorInvalidOperation("generateMipmap: the six faces of this cube map have different dimensions, format, or type.");
     }
 
     tex->SetGeneratedMipmap();
 
     MakeContextCurrent();
-
-    if (WorkAroundCubeMapBug684882()) {
-        if (target == LOCAL_GL_TEXTURE_2D) {
-            gl->fGenerateMipmap(target);
-        } else {
-            // do nothing! Accordingly we must make sure to never actually set texture parameters to something that requires mipmaps,
-            // or else we'll fail to render.
-        }
-    } else {
-        gl->fGenerateMipmap(target);
-    }
-
+    gl->fGenerateMipmap(target);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetActiveUniform(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLActiveInfo **retval)
 {
     *retval = nsnull;
 
@@ -2522,43 +2504,22 @@ nsresult WebGLContext::TexParameter_base
         // even for texParameterf. why not.
         if (intParamPtr)
             return ErrorInvalidEnum("texParameteri: pname %x and param %x (decimal %d) are mutually incompatible",
                                     pname, intParam, intParam);
         else
             return ErrorInvalidEnum("texParameterf: pname %x and floating-point param %e are mutually incompatible",
                                     pname, floatParam);
     }
-    
-    WebGLint intParamForGL = intParam;
-    WebGLfloat floatParamForGL = floatParam;
-    
-    if (WorkAroundCubeMapBug684882()) {
-        // bug 684882 - we skip mipmap generation in this case to work around a Mac GL bug, so we have
-        // to tweak the minification filter to avoid requiring a mipmap
-        if (pname == LOCAL_GL_TEXTURE_MIN_FILTER) {
-            if (intParam == LOCAL_GL_NEAREST_MIPMAP_NEAREST ||
-                intParam == LOCAL_GL_NEAREST_MIPMAP_LINEAR)
-            {
-                intParamForGL = LOCAL_GL_NEAREST;
-                floatParamForGL = WebGLfloat(intParamForGL);
-            } else if (intParam == LOCAL_GL_LINEAR_MIPMAP_NEAREST ||
-                       intParam == LOCAL_GL_LINEAR_MIPMAP_LINEAR)
-            {
-                intParamForGL = LOCAL_GL_LINEAR;
-                floatParamForGL = WebGLfloat(intParamForGL);
-            }
-        }
-    }
 
     MakeContextCurrent();
     if (intParamPtr)
-        gl->fTexParameteri(target, pname, intParamForGL);
+        gl->fTexParameteri(target, pname, intParam);
     else
-        gl->fTexParameterf(target, pname, floatParamForGL);
+        gl->fTexParameterf(target, pname, floatParam);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::TexParameterf(WebGLenum target, WebGLenum pname, WebGLfloat param)
 {
     return TexParameter_base(target, pname, nsnull, &param);
@@ -2574,39 +2535,33 @@ NS_IMETHODIMP
 WebGLContext::GetTexParameter(WebGLenum target, WebGLenum pname, nsIVariant **retval)
 {
     *retval = nsnull;
 
     MakeContextCurrent();
 
     if (!ValidateTextureTargetEnum(target, "getTexParameter: target"))
         return NS_OK;
-    
-    WebGLTexture *tex = activeBoundTextureForTarget(target);
-
-    if (!tex)
+
+    if (!activeBoundTextureForTarget(target))
         return ErrorInvalidOperation("getTexParameter: no texture bound");
 
     nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
     NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
 
     switch (pname) {
-        // note that because of bug 684882, the minification filter for OpenGL is sometimes spoofed.
-        // here we want to return our own value, not OpenGL's value
         case LOCAL_GL_TEXTURE_MIN_FILTER:
-            wrval->SetAsInt32(tex->mMinFilter);
-            break;
         case LOCAL_GL_TEXTURE_MAG_FILTER:
-            wrval->SetAsInt32(tex->mMagFilter);
-            break;
         case LOCAL_GL_TEXTURE_WRAP_S:
-            wrval->SetAsInt32(tex->mWrapS);
-            break;
         case LOCAL_GL_TEXTURE_WRAP_T:
-            wrval->SetAsInt32(tex->mWrapT);
+        {
+            GLint i = 0;
+            gl->fGetTexParameteriv(target, pname, &i);
+            wrval->SetAsInt32(i);
+        }
             break;
 
         default:
             return ErrorInvalidEnumInfo("getTexParameter: parameter", pname);
     }
 
     *retval = wrval.forget().get();
 
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -550,16 +550,24 @@ WebGLContext::InitAndValidateGL()
         return PR_FALSE;
     }
 
     mBound2DTextures.SetLength(mGLMaxTextureUnits);
     mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
 
     gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mGLMaxTextureSize);
     gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mGLMaxCubeMapTextureSize);
+    
+#ifdef XP_MACOSX
+    if (gl->Vendor() == gl::GLContext::VendorIntel) {
+        // bug 684882, corruption in large cube maps on Intel Mac driver.
+        // Is reported to only affect Mac OS < 10.7.2 but don't want to rely on that yet.
+        mGLMaxCubeMapTextureSize = NS_MIN(mGLMaxCubeMapTextureSize, 512);
+    }
+#endif
 
     gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxTextureImageUnits);
     gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits);
 
     if (gl->HasES2Compatibility()) {
         gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGLMaxFragmentUniformVectors);
         gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS, &mGLMaxVertexUniformVectors);
         gl->fGetIntegerv(LOCAL_GL_MAX_VARYING_VECTORS, &mGLMaxVaryingVectors);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -3818,18 +3818,16 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN(FileException, nsIDOMFileException)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileException)
     DOM_CLASSINFO_MAP_ENTRY(nsIException)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(FileReader, nsIDOMFileReader)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileReader)
-    DOM_CLASSINFO_MAP_ENTRY(nsIXMLHttpRequestEventTarget)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIInterfaceRequestor)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozURLProperty, nsIDOMMozURLProperty)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozURLProperty)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozBlobBuilder, nsIDOMMozBlobBuilder)
--- a/dom/system/NetworkGeolocationProvider.js
+++ b/dom/system/NetworkGeolocationProvider.js
@@ -234,20 +234,20 @@ WifiGeoPositionProvider.prototype = {
     // send our request to a wifi geolocation network provider:
     let xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
                         .createInstance(Ci.nsIXMLHttpRequest);
 
     // This is a background load
     xhr.mozBackgroundRequest = true;
     xhr.open("GET", providerUrl, false);
     xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
-    xhr.onerror = function(req) {
+    xhr.addEventListener("error", function(req) {
         LOG("onerror: " + req);
-    };
-    xhr.onload = function (req) {  
+    }, false);
+    xhr.addEventListener("load", function (req) {  
         LOG("service returned: " + req.target.responseText);
         response = JSON.parse(req.target.responseText);
         /*
           {
             "status": "OK",
             "accuracy": 150.0,
             "location": {
               "lat": -33.85702,
@@ -283,17 +283,17 @@ WifiGeoPositionProvider.prototype = {
               try {
                 Services.prefs.setIntPref(accessTokenPrefName + ".time", nowInSeconds());
                 Services.prefs.setCharPref(accessTokenPrefName, newAccessToken);
               } catch (x) {
                   // XXX temporary hack for bug 575346 to allow geolocation to function
               }
           }
         }
-    };
+    }, false);
 
     LOG("************************************* ------>>>> sending.");
     xhr.send(null);
   },
 
   onError: function (code) {
     LOG("wifi error: " + code);
   },
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -385,18 +385,18 @@ public:
 
 protected:
     gfxPlatform();
     virtual ~gfxPlatform();
 
     void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, 
                             eFontPrefLang aCharLang, eFontPrefLang aPageLang);
                                                
-    bool    mAllowDownloadableFonts;
-    bool    mDownloadableFontsSanitize;
+    PRInt8  mAllowDownloadableFonts;
+    PRInt8  mDownloadableFontsSanitize;
 
     // which scripts should be shaped with harfbuzz
     PRInt32 mUseHarfBuzzScripts;
 
 private:
     virtual qcms_profile* GetPlatformCMSOutputProfile();
 
     nsRefPtr<gfxASurface> mScreenReferenceSurface;
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -251,18 +251,18 @@ public:
     ID3D10Device1 *GetD3D10Device() { return mD2DDevice ? cairo_d2d_device_get_device(mD2DDevice) : nsnull; }
 #endif
 
     static bool IsOptimus();
 
 protected:
     RenderMode mRenderMode;
 
-    bool mUseClearTypeForDownloadableFonts;
-    bool mUseClearTypeAlways;
+    PRInt8 mUseClearTypeForDownloadableFonts;
+    PRInt8 mUseClearTypeAlways;
     HDC mScreenDC;
 
 private:
     void Init();
 
     bool mUseDirectWrite;
     bool mUsingGDIFonts;
 
--- a/js/src/xpconnect/tests/chrome/test_doublewrappedcompartments.xul
+++ b/js/src/xpconnect/tests/chrome/test_doublewrappedcompartments.xul
@@ -25,20 +25,20 @@ https://bugzilla.mozilla.org/show_bug.cg
       const Ci = Components.interfaces;
       const utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
                           .getInterface(Ci.nsIDOMWindowUtils);
 
       function go() {
         var wrappedWin = $('ifr').contentWindow;
         var unwrapped = wrappedWin.wrappedJSObject;
 
-        var readystatechange = unwrapped.xhr.onreadystatechange;
-        is(utils.getClassName(readystatechange), 'Proxy', 'properly wrapped');
-        is(typeof readystatechange.QueryInterface, 'function', 'double wrapped');
+        var filter = unwrapped.filter;
+        is(utils.getClassName(filter), 'Proxy', 'properly wrapped');
+        is(typeof filter.QueryInterface, 'function', 'double wrapped');
 
-        ok(unwrapped.testme(readystatechange),
-           'content didn\'t get a proxy, but another double wrapped object');
+        ok(unwrapped.testme(filter),
+           "content didn't get a proxy, but another double wrapped object");
         SimpleTest.finish();
       }
 
       SimpleTest.waitForExplicitFinish();
   ]]></script>
 </window>
--- a/js/src/xpconnect/tests/mochitest/file_doublewrappedcompartments.html
+++ b/js/src/xpconnect/tests/mochitest/file_doublewrappedcompartments.html
@@ -1,14 +1,14 @@
 <html>
     <head>
         <script>
-            var xhr = new XMLHttpRequest();
-            var readystatechange = function() {};
-            xhr.onreadystatechange = readystatechange;
+            var fcn = function() {};
+            var iter = document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, fcn, false);
+            var filter = iter.filter;
 
             function testme(obj) {
                 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
                 const Ci = Components.interfaces;
                 const utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
                                     .getInterface(Ci.nsIDOMWindowUtils);
 
                 return utils.getClassName(obj) != "Proxy" &&
--- a/js/src/xpconnect/tests/mochitest/test_bug502959.html
+++ b/js/src/xpconnect/tests/mochitest/test_bug502959.html
@@ -13,25 +13,29 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 502959 **/
-var xhr = new XMLHttpRequest();
+// Whatever you do don't use the word "wrapped" in this function.
+function foo() {
+  ok(true, "Able to call the function");
+}
 
-xhr.onreadystatechange = function() { ok(true, "Able to call the double-wrapped function"); };
-var doublewrapped = xhr.onreadystatechange;
+var iter = document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, foo, false);
+var doublewrapped = iter.filter;
+
 ok(doublewrapped.toString().indexOf("wrapped") > 0, "got a double-wrapped object back");
 
 (function () {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     Components.utils.forceGC();
 })();
 
-doublewrapped.handleEvent({});
+doublewrapped.acceptNode(document);
 
 </script>
 </pre>
 </body>
 </html>
--- a/js/src/xpconnect/tests/mochitest/test_bug505915.html
+++ b/js/src/xpconnect/tests/mochitest/test_bug505915.html
@@ -33,26 +33,16 @@ function go() {
     try {
         document.createTreeWalker(ifr.contentDocument, 0, null, false);
         ok(false, "should have thrown a security exception");
     } catch (e) {
         ok(/NS_ERROR_XPC_SECURITY_MANAGER_VETO/.test(e),
            "threw a security exception instead of an invalid child exception");
     }
 
-    var xhr = new XMLHttpRequest();
-
-    try {
-        xhr.onreadystatechange = ifr.contentWindow;
-        ok(false, "weird behavior");
-    } catch (e) {
-        ok(/NS_ERROR_XPC_SECURITY_MANAGER_VETO/.test(e),
-           "threw a security exception instead of an invalid child exception");
-    }
-
     // Location is always wrapped, so test it separately.
 
     ifr.onload = null;
     var path = "/tests/js/src/xpconnect/tests/mochitest/file_bug505915.html";
 
     ifr.contentWindow.location = "http://mochi.test:8888/" + path;
     yield;
     try {
--- a/mobile/modules/LocaleRepository.jsm
+++ b/mobile/modules/LocaleRepository.jsm
@@ -100,34 +100,34 @@ var LocaleRepository = {
     url = Services.urlFormatter.formatURL(url);
 
     let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
     request.mozBackgroundRequest = true;
     request.open("GET", url, true);
     request.overrideMimeType("text/xml");
   
     let self = this;
-    request.onreadystatechange = function () {
+    request.addEventListener("readystatechange", function () {
       if (request.readyState == 4) {
         if (request.status == 200) {
           self.log("---- got response")
           let documentElement = request.responseXML.documentElement;
           let elements = documentElement.getElementsByTagName("addon");
           let totalResults = elements.length;
           let parsedTotalResults = parseInt(documentElement.getAttribute("total_results"));
           if (parsedTotalResults >= totalResults)
             totalResults = parsedTotalResults;
 
           // TODO: Create a real Skip object from installed locales
           self._parseLocales(elements, totalResults, { ids: [], sourceURIs: [] }, aCallback);
         } else {
           Cu.reportError("Locale Repository: Error getting locale from AMO [" + request.status + "]");
         }
       }
-    };
+    }, false);
   
     request.send(null);
   },
 
   _parseLocale: function _parseLocale(aElement, aSkip) {
     let skipIDs = (aSkip && aSkip.ids) ? aSkip.ids : [];
     let skipSourceURIs = (aSkip && aSkip.sourceURIs) ? aSkip.sourceURIs : [];
   
--- a/netwerk/test/unit/test_xmlhttprequest.js
+++ b/netwerk/test/unit/test_xmlhttprequest.js
@@ -33,20 +33,20 @@ function run_test()
 
   // Test sync XHR sending
   var sync = createXHR(false);
   sync.send(null);
   checkResults(sync);
 
   // Test async XHR sending
   let async = createXHR(true);
-  async.onreadystatechange = function(event) {
+  async.addEventListener("readystatechange", function(event) {
     if (checkResults(async))
       httpserver.stop(do_test_finished);
-  };
+  }, false);
   async.send(null);
   do_test_pending();
 }
 
 function serverHandler(metadata, response)
 {
   response.setHeader("Content-Type", "text/xml", false);
   response.bodyOutputStream.write(httpbody, httpbody.length);
--- a/testing/mozmill/Makefile.in
+++ b/testing/mozmill/Makefile.in
@@ -90,11 +90,12 @@ install-develop: install
 else
 install-develop: mozmill-dir
 	$(INSTALL) $(foreach f, $(TEST_HARNESS_PACKAGES), "$(srcdir)/$f") $(PKG_STAGE)/mozmill/
 	(cd $(srcdir) && tar $(TAR_CREATE_FLAGS) - $(MOZMILL_EXTRAS)) | (cd $(PKG_STAGE)/mozmill && tar -xf -)
 	$(INSTALL) $(topsrcdir)/testing/mozmill/tests $(PKG_STAGE)/mozmill
 endif
 
 # Rules for staging the necessary harness bits for a test package
-stage-package: PKG_STAGE = $(DIST)/test-package-stage
 stage-package: install
+
+PKG_STAGE = $(DIST)/test-package-stage
 	
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -315,18 +315,18 @@ TelemetryPing.prototype = {
         success = channel.QueryInterface(Ci.nsIHttpChannel).requestSucceeded;
       } catch(e) {
       }
       hsuccess.add(success);
       hping.add(new Date() - startTime);
       if (isTestPing)
         Services.obs.notifyObservers(null, "telemetry-test-xhr-complete", null);
     }
-    request.onerror = function(aEvent) finishRequest(request.channel);
-    request.onload = function(aEvent) finishRequest(request.channel);
+    request.addEventListener("error", function(aEvent) finishRequest(request.channel), false);
+    request.addEventListener("load", function(aEvent) finishRequest(request.channel), false);
 
     request.send(JSON.stringify(payload));
   },
   
   attachObservers: function attachObservers() {
     if (!this._initialized)
       return;
     Services.obs.addObserver(this, "cycle-collector-begin", false);
--- a/toolkit/components/url-classifier/content/xml-fetcher.js
+++ b/toolkit/components/url-classifier/content/xml-fetcher.js
@@ -98,25 +98,24 @@ PROT_XMLFetcher.prototype = {
     this._request.open("GET", page, asynchronous);
     this._request.channel.notificationCallbacks = this;
 
     if (this._stripCookies)
       new PROT_CookieStripper(this._request.channel);
 
     // Create a closure
     var self = this;
-    this._request.onreadystatechange = function() {
+    this._request.addEventListener("readystatechange", function() {
       self.readyStateChange(self);
-    }
+    }, false);
 
     this._request.send(null);
   },
 
   cancel: function() {
-    this._request.onreadystatechange = null;
     this._request.abort();
     this._request = null;
   },
 
   /**
    * Called periodically by the request to indicate some state change. 4
    * means content has been received.
    */
--- a/toolkit/crashreporter/CrashSubmit.jsm
+++ b/toolkit/crashreporter/CrashSubmit.jsm
@@ -252,27 +252,27 @@ Submitter.prototype = {
     }
     if (this.noThrottle) {
       // tell the server not to throttle this, since it was manually submitted
       formData.append("Throttleable", "0");
     }
     // add the minidump
     formData.append("upload_file_minidump", File(this.dump.path));
     let self = this;
-    xhr.onreadystatechange = function (aEvt) {
+    xhr.addEventListener("readystatechange", function (aEvt) {
       if (xhr.readyState == 4) {
         if (xhr.status != 200) {
           self.notifyStatus(FAILED);
           self.cleanup();
         } else {
           let ret = parseKeyValuePairs(xhr.responseText);
           self.submitSuccess(ret);
         }
       }
-    };
+    }, false);
 
     xhr.send(formData);
     return true;
   },
 
   notifyStatus: function Submitter_notify(status, ret)
   {
     let propBag = Cc["@mozilla.org/hash-property-bag;1"].
--- a/toolkit/mozapps/extensions/AddonRepository.jsm
+++ b/toolkit/mozapps/extensions/AddonRepository.jsm
@@ -1171,18 +1171,20 @@ var AddonRepository = {
 
     this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
                     createInstance(Ci.nsIXMLHttpRequest);
     this._request.mozBackgroundRequest = true;
     this._request.open("GET", aURI, true);
     this._request.overrideMimeType("text/xml");
 
     let self = this;
-    this._request.onerror = function(aEvent) { self._reportFailure(); };
-    this._request.onload = function(aEvent) {
+    this._request.addEventListener("error", function(aEvent) {
+      self._reportFailure();
+    }, false);
+    this._request.addEventListener("load", function(aEvent) {
       let request = aEvent.target;
       let responseXML = request.responseXML;
 
       if (!responseXML || responseXML.documentElement.namespaceURI == XMLURI_PARSE_ERROR ||
           (request.status != 200 && request.status != 0)) {
         self._reportFailure();
         return;
       }
@@ -1191,17 +1193,17 @@ var AddonRepository = {
       let elements = documentElement.getElementsByTagName("addon");
       let totalResults = elements.length;
       let parsedTotalResults = parseInt(documentElement.getAttribute("total_results"));
       // Parsed value of total results only makes sense if >= elements.length
       if (parsedTotalResults >= totalResults)
         totalResults = parsedTotalResults;
 
       aHandleResults(elements, totalResults);
-    };
+    }, false);
     this._request.send(null);
   },
 
   // Gets the id's of local add-ons, and the sourceURI's of local installs,
   // passing the results to aCallback
   _getLocalAddonIds: function(aCallback) {
     let self = this;
     let localAddonIds = {ids: null, sourceURIs: null};
--- a/toolkit/mozapps/extensions/AddonUpdateChecker.jsm
+++ b/toolkit/mozapps/extensions/AddonUpdateChecker.jsm
@@ -446,18 +446,18 @@ function UpdateParser(aId, aType, aUpdat
   try {
     this.request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
                    createInstance(Ci.nsIXMLHttpRequest);
     this.request.open("GET", aUrl, true);
     this.request.channel.notificationCallbacks = new BadCertHandler(!requireBuiltIn);
     this.request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
     this.request.overrideMimeType("text/xml");
     var self = this;
-    this.request.onload = function(event) { self.onLoad() };
-    this.request.onerror = function(event) { self.onError() };
+    this.request.addEventListener("load", function(event) { self.onLoad() }, false);
+    this.request.addEventListener("error", function(event) { self.onError() }, false);
     this.request.send(null);
   }
   catch (e) {
     ERROR("Failed to request update manifest", e);
   }
 }
 
 UpdateParser.prototype = {
--- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -222,30 +222,30 @@ var LightweightThemeManager = {
     var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
                 .createInstance(Ci.nsIXMLHttpRequest);
 
     req.mozBackgroundRequest = true;
     req.overrideMimeType("text/plain");
     req.open("GET", theme.updateURL, true);
 
     var self = this;
-    req.onload = function () {
+    req.addEventListener("load", function () {
       if (req.status != 200)
         return;
 
       let newData = self.parseTheme(req.responseText, theme.updateURL);
       if (!newData ||
           newData.id != theme.id ||
           _version(newData) == _version(theme))
         return;
 
       var currentTheme = self.currentTheme;
       if (currentTheme && currentTheme.id == theme.id)
         self.currentTheme = newData;
-    };
+    }, false);
 
     req.send(null);
   },
 
   /**
    * Switches to a new lightweight theme.
    *
    * @param  aData
--- a/toolkit/mozapps/extensions/nsBlocklistService.js
+++ b/toolkit/mozapps/extensions/nsBlocklistService.js
@@ -541,18 +541,18 @@ Blocklist.prototype = {
                   createInstance(Ci.nsIXMLHttpRequest);
     request.open("GET", uri.spec, true);
     request.channel.notificationCallbacks = new gCertUtils.BadCertHandler();
     request.overrideMimeType("text/xml");
     request.setRequestHeader("Cache-Control", "no-cache");
     request.QueryInterface(Components.interfaces.nsIJSXMLHttpRequest);
 
     var self = this;
-    request.onerror = function(event) { self.onXMLError(event); };
-    request.onload  = function(event) { self.onXMLLoad(event);  };
+    request.addEventListener("error", function(event) { self.onXMLError(event); }, false);
+    request.addEventListener("load", function(event) { self.onXMLLoad(event);  }, false);
     request.send(null);
 
     // When the blocklist loads we need to compare it to the current copy so
     // make sure we have loaded it.
     if (!this._addonEntries)
       this._loadBlocklist();
   },
 
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -2150,19 +2150,19 @@ Checker.prototype = {
     this._request.open("GET", url, true);
     var allowNonBuiltIn = !getPref("getBoolPref",
                                    PREF_APP_UPDATE_CERT_REQUIREBUILTIN, true);
     this._request.channel.notificationCallbacks = new gCertUtils.BadCertHandler(allowNonBuiltIn);
     this._request.overrideMimeType("text/xml");
     this._request.setRequestHeader("Cache-Control", "no-cache");
 
     var self = this;
-    this._request.onerror     = function(event) { self.onError(event);    };
-    this._request.onload      = function(event) { self.onLoad(event);     };
-    this._request.onprogress  = function(event) { self.onProgress(event); };
+    this._request.addEventListener("error", function(event) { self.onError(event); } ,false);
+    this._request.addEventListener("load", function(event) { self.onLoad(event); }, false);
+    this._request.addEventListener("progress", function(event) { self.onProgress(event); }, false);
 
     LOG("Checker:checkForUpdates - sending request to: " + url);
     this._request.send(null);
 
     this._callback = listener;
   },
 
   /**
--- a/toolkit/mozapps/update/test/unit/head_update.js.in
+++ b/toolkit/mozapps/update/test/unit/head_update.js.in
@@ -1002,16 +1002,19 @@ xhr.prototype = {
   set onprogress(val) { gXHR._onprogress = makeHandler(val); },
   get onprogress() { return gXHR._onprogress; },
   _onerror: null,
   set onerror(val) { gXHR._onerror = makeHandler(val); },
   get onerror() { return gXHR._onerror; },
   _onload: null,
   set onload(val) { gXHR._onload = makeHandler(val); },
   get onload() { return gXHR._onload; },
+  addEventListener: function(event, val, capturing) {
+    eval("gXHR._on" + event + " = val");
+  },
   flags: AUS_Ci.nsIClassInfo.SINGLETON,
   implementationLanguage: AUS_Ci.nsIProgrammingLanguage.JAVASCRIPT,
   getHelperForLanguage: function(language) null,
   getInterfaces: function(count) {
     var interfaces = [AUS_Ci.nsISupports];
     count.value = interfaces.length;
     return interfaces;
   },
--- a/toolkit/mozapps/update/test/unit/test_0020_general.js
+++ b/toolkit/mozapps/update/test/unit/test_0020_general.js
@@ -82,17 +82,17 @@ function callHandleEvent() {
     var parser = AUS_Cc["@mozilla.org/xmlextras/domparser;1"].
                  createInstance(AUS_Ci.nsIDOMParser);
     gXHR.responseXML = parser.parseFromString(gResponseBody, "application/xml");
   }
   catch(e) {
     gXHR.responseXML = null;
   }
   var e = { target: gXHR };
-  gXHR.onload.handleEvent(e);
+  gXHR.onload(e);
 }
 
 // update xml not found
 function run_test_pt01() {
   run_test_helper_pt1("testing update xml not available",
                       null, run_test_pt02);
 }
 
--- a/toolkit/mozapps/update/test/unit/test_0030_general.js
+++ b/toolkit/mozapps/update/test/unit/test_0030_general.js
@@ -72,17 +72,17 @@ function callHandleEvent() {
   try {
     var parser = AUS_Cc["@mozilla.org/xmlextras/domparser;1"].
                  createInstance(AUS_Ci.nsIDOMParser);
     gXHR.responseXML = parser.parseFromString(gResponseBody, "application/xml");
   }
   catch(e) {
   }
   var e = { target: gXHR };
-  gXHR.onload.handleEvent(e);
+  gXHR.onload(e);
 }
 
 // Helper function for testing mar downloads that have the correct size
 // specified in the update xml.
 function run_test_helper_pt1(aMsg, aExpectedStatusResult, aNextRunFunc) {
   gUpdates = null;
   gUpdateCount = null;
   gStatusResult = null;
--- a/toolkit/mozapps/update/test/unit/test_0040_general.js
+++ b/toolkit/mozapps/update/test/unit/test_0040_general.js
@@ -58,17 +58,17 @@ function run_test() {
 function end_test() {
   cleanUp();
 }
 
 // Callback function used by the custom XMLHttpRequest implementation to
 // call the nsIDOMEventListener's handleEvent method for onload.
 function callHandleEvent() {
   var e = { target: gXHR };
-  gXHR.onload.handleEvent(e);
+  gXHR.onload(e);
 }
 
 // Helper function for parsing the result from the contructed url
 function getResult(url) {
   return url.substr(URL_PREFIX.length).split("/")[0];
 }
 
 // url constructed with %PRODUCT%
--- a/toolkit/mozapps/update/test/unit/test_0050_general.js
+++ b/toolkit/mozapps/update/test/unit/test_0050_general.js
@@ -63,17 +63,17 @@ function end_test() {
   cleanUp();
 }
 
 // Callback function used by the custom XMLHttpRequest implementation to
 // call the nsIDOMEventListener's handleEvent method for onload.
 function callHandleEvent() {
   gXHR.status = gExpectedStatusCode;
   var e = { target: gXHR };
-  gXHR.onload.handleEvent(e);
+  gXHR.onload(e);
 }
 
 // Helper functions for testing nsIUpdateCheckListener statusText
 function run_test_helper(aNextRunFunc, aExpectedStatusCode, aMsg) {
   gStatusCode = null;
   gStatusText = null;
   gCheckFunc = check_test_helper;
   gNextRunFunc = aNextRunFunc;
--- a/toolkit/mozapps/webapps/OpenWebapps.js
+++ b/toolkit/mozapps/webapps/OpenWebapps.js
@@ -161,17 +161,17 @@ OpenWebapps.prototype = {
   // nsIOpenWebapps implementation
   
   install: function(aURL, aInstallData, aSuccess, aError) {
     let self = this;
 
     let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
     xhr.open("GET", aURL, true);
 
-    xhr.onload = function() {
+    xhr.addEventListener("load", function() {
       if (xhr.status == 200) {
         try {
           let manifest = JSON.parse(xhr.responseText);
           if (!self.checkManifest(manifest)) {
             if (aError)
               aError.handle({ code: "invalidManifest", message: "Invalid manifest" });
           } else {
             self.mm.sendAsyncMessage("OpenWebapps:Install", { storeURI: self._window.location.href, manifestURI: aURL, manifest: xhr.responseText,
@@ -180,22 +180,22 @@ OpenWebapps.prototype = {
         } catch(e) {
           if (aError)
             aError.handle({ code: "manifestParseError", message: "Unable to parse the manifest" });
         }
       }
       else if (aError) {
         aError.handle({ code: "networkError", message: "Unable to retrieve manifest" });
       }      
-    }
+    }, false);
 
-    xhr.onerror = function() {
+    xhr.addEventListener("error", function() {
       if (aError)
         aError.handle({ code: "networkError", message: "Unable to retrieve manifest" });
-    }
+    }, false);
 
     xhr.send(null);
   },
   
   amInstalled: function(aSuccess, aError) {
     this.mm.sendAsyncMessage("OpenWebapps:AmInstalled", { appURI: this._window.location.href, callbackID:  this.getCallbackId({ success: aSuccess, error: aError }) });
   },