Bug 1269162 - part 6 - Merge XMLHttpRequestWorker and XMLHttpRequestMainThread, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Mon, 27 Jun 2016 19:13:41 +0200
changeset 342798 155012d3d3731e10e085ae0841d308ca0515a35c
parent 342797 ddb3b5ac04aff12d9b18c2504477cb5bc00abad1
child 342799 9f1e2864e569ced540dbc6dc75d7709a7c47fade
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1269162
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1269162 - part 6 - Merge XMLHttpRequestWorker and XMLHttpRequestMainThread, r=smaug
dom/bindings/Bindings.conf
dom/webidl/XMLHttpRequest.webidl
dom/xhr/XMLHttpRequest.cpp
dom/xhr/XMLHttpRequest.h
dom/xhr/XMLHttpRequestEventTarget.h
dom/xhr/XMLHttpRequestMainThread.cpp
dom/xhr/XMLHttpRequestMainThread.h
dom/xhr/XMLHttpRequestUpload.h
dom/xhr/XMLHttpRequestWorker.cpp
dom/xhr/XMLHttpRequestWorker.h
dom/xhr/moz.build
dom/xhr/nsXMLHttpRequest.cpp
dom/xhr/nsXMLHttpRequest.h
dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp
js/xpconnect/src/Sandbox.cpp
layout/base/nsDocumentViewer.cpp
layout/build/nsLayoutModule.cpp
netwerk/base/LoadInfo.h
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1572,26 +1572,19 @@ DOMInterfaces = {
     ],
     # Rename a few things so we don't have both classes and methods
     # with the same name
     'binaryNames': {
         'performance': 'getPerformance',
     },
 },
 
-'XMLHttpRequest': [
-{
-    'nativeType': 'nsXMLHttpRequest',
+'XMLHttpRequest': {
     'implicitJSContext': [ 'send'],
 },
-{
-    'nativeType': 'mozilla::dom::workers::XMLHttpRequestWorker',
-    'headerFile': 'mozilla/dom/workers/bindings/XMLHttpRequestWorker.h',
-    'workers': True,
-}],
 
 'XMLHttpRequestEventTarget': {
     'concrete': False
 },
 
 'XMLSerializer': {
     'nativeType': 'nsDOMSerializer',
 },
--- a/dom/webidl/XMLHttpRequest.webidl
+++ b/dom/webidl/XMLHttpRequest.webidl
@@ -78,17 +78,17 @@ interface XMLHttpRequest : XMLHttpReques
   void setRequestHeader(ByteString header, ByteString value);
 
   [SetterThrows]
   attribute unsigned long timeout;
 
   [SetterThrows]
   attribute boolean withCredentials;
 
-  [Throws=Workers]
+  [Throws]
   readonly attribute XMLHttpRequestUpload upload;
 
   [Throws]
   void send();
   [Throws]
   void send(ArrayBuffer data);
   [Throws]
   void send(ArrayBufferView data);
@@ -98,30 +98,32 @@ interface XMLHttpRequest : XMLHttpReques
   void send(Document data);
   [Throws]
   void send(DOMString? data);
   [Throws]
   void send(FormData data);
   [Throws]
   void send(InputStream data);
 
-  [Throws=Workers]
+  [Throws]
   void abort();
 
   // response
   readonly attribute DOMString responseURL;
 
-  [Throws=Workers]
+  [Throws]
   readonly attribute unsigned short status;
 
+  [Throws]
   readonly attribute ByteString statusText;
+
   [Throws]
   ByteString? getResponseHeader(ByteString header);
 
-  [Throws=Workers]
+  [Throws]
   ByteString getAllResponseHeaders();
 
   [Throws]
   void overrideMimeType(DOMString mime);
 
   [SetterThrows]
   attribute XMLHttpRequestResponseType responseType;
   [Throws]
@@ -129,17 +131,17 @@ interface XMLHttpRequest : XMLHttpReques
   [Throws]
   readonly attribute DOMString? responseText;
 
   [Throws, Exposed=Window]
   readonly attribute Document? responseXML;
 
   // Mozilla-specific stuff
 
-  [ChromeOnly, SetterThrows=Workers]
+  [ChromeOnly, SetterThrows]
   attribute boolean mozBackgroundRequest;
 
   [ChromeOnly, Exposed=Window]
   readonly attribute MozChannel? channel;
 
   // A platform-specific identifer to represent the network interface 
   // which the HTTP request would occur on.
   [ChromeOnly, Exposed=Window]
new file mode 100644
--- /dev/null
+++ b/dom/xhr/XMLHttpRequest.cpp
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "XMLHttpRequest.h"
+#include "XMLHttpRequestMainThread.h"
+#include "XMLHttpRequestWorker.h"
+
+namespace mozilla {
+namespace dom {
+
+/* static */ already_AddRefed<XMLHttpRequest>
+XMLHttpRequest::Constructor(const GlobalObject& aGlobal,
+                            const MozXMLHttpRequestParameters& aParams,
+                            ErrorResult& aRv)
+{
+  if (NS_IsMainThread()) {
+    nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
+    nsCOMPtr<nsIScriptObjectPrincipal> principal =
+      do_QueryInterface(aGlobal.GetAsSupports());
+    if (!global || ! principal) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
+
+    RefPtr<XMLHttpRequestMainThread> req = new XMLHttpRequestMainThread();
+    req->Construct(principal->GetPrincipal(), global);
+    req->InitParameters(aParams.mMozAnon, aParams.mMozSystem);
+    return req.forget();
+  }
+
+  return XMLHttpRequestWorker::Construct(aGlobal, aParams, aRv);
+}
+
+} // dom namespace
+} // mozilla namespace
new file mode 100644
--- /dev/null
+++ b/dom/xhr/XMLHttpRequest.h
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_XMLHttpRequest_h
+#define mozilla_dom_XMLHttpRequest_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/dom/XMLHttpRequestEventTarget.h"
+#include "mozilla/dom/XMLHttpRequestBinding.h"
+#include "nsIXMLHttpRequest.h"
+
+class nsIJSID;
+
+namespace mozilla {
+namespace dom {
+
+class Blob;
+class FormData;
+class XMLHttpRequestUpload;
+
+class XMLHttpRequest : public XMLHttpRequestEventTarget
+{
+public:
+  static already_AddRefed<XMLHttpRequest>
+  Constructor(const GlobalObject& aGlobal,
+              const MozXMLHttpRequestParameters& aParams,
+              ErrorResult& aRv);
+
+  static already_AddRefed<XMLHttpRequest>
+  Constructor(const GlobalObject& aGlobal, const nsAString& ignored,
+              ErrorResult& aRv)
+  {
+    // Pretend like someone passed null, so we can pick up the default values
+    MozXMLHttpRequestParameters params;
+    if (!params.Init(aGlobal.Context(), JS::NullHandleValue)) {
+      aRv.Throw(NS_ERROR_UNEXPECTED);
+      return nullptr;
+    }
+
+    return Constructor(aGlobal, params, aRv);
+  }
+
+  IMPL_EVENT_HANDLER(readystatechange)
+
+  virtual uint16_t
+  ReadyState() const = 0;
+
+  virtual void
+  Open(const nsACString& aMethod, const nsAString& aUrl, ErrorResult& aRv) = 0;
+
+  virtual void
+  Open(const nsACString& aMethod, const nsAString& aUrl,
+       bool aAsync, const Optional<nsAString>& aUser,
+       const Optional<nsAString>& aPassword, ErrorResult& aRv) = 0;
+
+  virtual void
+  SetRequestHeader(const nsACString& aHeader, const nsACString& aValue,
+                   ErrorResult& aRv) = 0;
+
+  virtual uint32_t
+  Timeout() const = 0;
+
+  virtual void
+  SetTimeout(uint32_t aTimeout, ErrorResult& aRv) = 0;
+
+  virtual bool
+  WithCredentials() const = 0;
+
+  virtual void
+  SetWithCredentials(bool aWithCredentials, ErrorResult& aRv) = 0;
+
+  virtual XMLHttpRequestUpload*
+  GetUpload(ErrorResult& aRv) = 0;
+
+  virtual void
+  Send(JSContext* aCx, ErrorResult& aRv) = 0;
+
+  virtual void
+  Send(JSContext* aCx, const ArrayBuffer& aArrayBuffer, ErrorResult& aRv) = 0;
+
+  virtual void
+  Send(JSContext* aCx, const ArrayBufferView& aArrayBufferView,
+       ErrorResult& aRv) = 0;
+
+  virtual void
+  Send(JSContext* aCx, Blob& aBlob, ErrorResult& aRv) = 0;
+
+  virtual void
+  Send(JSContext* aCx, nsIDocument& aDoc, ErrorResult& aRv) = 0;
+
+  virtual void
+  Send(JSContext* aCx, const nsAString& aString, ErrorResult& aRv) = 0;
+
+  virtual void
+  Send(JSContext* aCx, FormData& aFormData, ErrorResult& aRv) = 0;
+
+  virtual void
+  Send(JSContext* aCx, nsIInputStream* aStream, ErrorResult& aRv) = 0;
+
+  virtual void
+  Abort(ErrorResult& aRv) = 0;
+
+  virtual void
+  GetResponseURL(nsAString& aUrl) = 0;
+
+  virtual uint32_t
+  GetStatus(ErrorResult& aRv) = 0;
+
+  virtual void
+  GetStatusText(nsACString& aStatusText, ErrorResult& aRv) = 0;
+
+  virtual void
+  GetResponseHeader(const nsACString& aHeader, nsACString& aResult,
+                    ErrorResult& aRv) = 0;
+
+  virtual void
+  GetAllResponseHeaders(nsACString& aResponseHeaders,
+                        ErrorResult& aRv) = 0;
+
+  virtual void
+  OverrideMimeType(const nsAString& aMimeType, ErrorResult& aRv) = 0;
+
+  virtual XMLHttpRequestResponseType
+  ResponseType() const = 0;
+
+  virtual void
+  SetResponseType(XMLHttpRequestResponseType aType,
+                  ErrorResult& aRv) = 0;
+
+  virtual void
+  GetResponse(JSContext* aCx, JS::MutableHandle<JS::Value> aResponse,
+              ErrorResult& aRv) = 0;
+
+  virtual void
+  GetResponseText(nsAString& aResponseText, ErrorResult& aRv) = 0;
+
+  virtual nsIDocument*
+  GetResponseXML(ErrorResult& aRv) = 0;
+
+  virtual bool
+  MozBackgroundRequest() const = 0;
+
+  virtual void
+  SetMozBackgroundRequest(bool aMozBackgroundRequest, ErrorResult& aRv) = 0;
+
+  virtual nsIChannel*
+  GetChannel() const = 0;
+
+  virtual void
+  GetNetworkInterfaceId(nsACString& aId) const = 0;
+
+  virtual void
+  SetNetworkInterfaceId(const nsACString& aId) = 0;
+
+  // We need a GetInterface callable from JS for chrome JS
+  virtual void
+  GetInterface(JSContext* aCx, nsIJSID* aIID,
+               JS::MutableHandle<JS::Value> aRetval,
+               ErrorResult& aRv) = 0;
+
+  virtual bool
+  MozAnon() const = 0;
+
+  virtual bool
+  MozSystem() const = 0;
+
+  virtual JSObject*
+  WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override
+  {
+    return mozilla::dom::XMLHttpRequestBinding::Wrap(aCx, this, aGivenProto);
+  }
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_XMLHttpRequest_h
--- a/dom/xhr/XMLHttpRequestEventTarget.h
+++ b/dom/xhr/XMLHttpRequestEventTarget.h
@@ -36,15 +36,20 @@ public:
   IMPL_EVENT_HANDLER(loadstart)
   IMPL_EVENT_HANDLER(progress)
   IMPL_EVENT_HANDLER(abort)
   IMPL_EVENT_HANDLER(error)
   IMPL_EVENT_HANDLER(load)
   IMPL_EVENT_HANDLER(timeout)
   IMPL_EVENT_HANDLER(loadend)
 
+  nsISupports* GetParentObject() const
+  {
+    return GetOwner();
+  }
+
   virtual void DisconnectFromOwner() override;
 };
 
 } // dom namespace
 } // mozilla namespace
 
 #endif // mozilla_dom_XMLHttpRequestEventTarget_h
rename from dom/xhr/nsXMLHttpRequest.cpp
rename to dom/xhr/XMLHttpRequestMainThread.cpp
--- a/dom/xhr/nsXMLHttpRequest.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsXMLHttpRequest.h"
+#include "XMLHttpRequestMainThread.h"
 
 #ifndef XP_WIN
 #include <unistd.h>
 #endif
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/BlobSet.h"
 #include "mozilla/dom/File.h"
@@ -76,20 +76,21 @@
 #include "xpcjsid.h"
 #include "nsITimedChannel.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsZipArchive.h"
 #include "mozilla/Preferences.h"
 #include "private/pprio.h"
 #include "XMLHttpRequestUpload.h"
 
-using namespace mozilla;
-using namespace mozilla::dom;
 using namespace mozilla::net;
 
+namespace mozilla {
+namespace dom {
+
 // Maximum size that we'll grow an ArrayBuffer instead of doubling,
 // once doubling reaches this threshold
 #define XML_HTTP_REQUEST_ARRAYBUFFER_MAX_GROWTH (32*1024*1024)
 // start at 32k to avoid lots of doubling right at the start
 #define XML_HTTP_REQUEST_ARRAYBUFFER_MIN_SIZE (32*1024)
 // the maximum Content-Length that we'll preallocate.  1GB.  Must fit
 // in an int32_t!
 #define XML_HTTP_REQUEST_MAX_CONTENT_LENGTH_PREALLOCATE (1*1024*1024*1024LL)
@@ -135,26 +136,16 @@ using namespace mozilla::net;
    XML_HTTP_REQUEST_DONE |                  \
    XML_HTTP_REQUEST_SENT)
 
 #define NS_BADCERTHANDLER_CONTRACTID \
   "@mozilla.org/content/xmlhttprequest-bad-cert-handler;1"
 
 #define NS_PROGRESS_EVENT_INTERVAL 50
 
-#define IMPL_CSTRING_GETTER(_name)                                              \
-  NS_IMETHODIMP                                                                 \
-  nsXMLHttpRequest::_name(nsACString& aOut)                                     \
-  {                                                                             \
-    nsCString tmp;                                                              \
-    _name(tmp);                                                                 \
-    aOut = tmp;                                                                 \
-    return NS_OK;                                                               \
-  }
-
 NS_IMPL_ISUPPORTS(nsXHRParseEndListener, nsIDOMEventListener)
 
 class nsResumeTimeoutsEvent : public Runnable
 {
 public:
   explicit nsResumeTimeoutsEvent(nsPIDOMWindowInner* aWindow) : mWindow(aWindow) {}
 
   NS_IMETHOD Run()
@@ -179,19 +170,19 @@ static void AddLoadFlags(nsIRequest *req
 }
 
 /////////////////////////////////////////////
 //
 //
 /////////////////////////////////////////////
 
 bool
-nsXMLHttpRequest::sDontWarnAboutSyncXHR = false;
-
-nsXMLHttpRequest::nsXMLHttpRequest()
+XMLHttpRequestMainThread::sDontWarnAboutSyncXHR = false;
+
+XMLHttpRequestMainThread::XMLHttpRequestMainThread()
   : mResponseBodyDecodedPos(0),
     mResponseType(XML_HTTP_RESPONSE_TYPE_DEFAULT),
     mRequestObserver(nullptr),
     mState(XML_HTTP_REQUEST_UNSENT | XML_HTTP_REQUEST_ASYNC),
     mUploadTransferred(0), mUploadTotal(0), mUploadComplete(true),
     mProgressSinceLastProgressEvent(false),
     mRequestSentTime(0), mTimeoutMilliseconds(0),
     mErrorLoad(false), mWaitingForOnStopRequest(false),
@@ -208,17 +199,17 @@ nsXMLHttpRequest::nsXMLHttpRequest()
     mIsMappedArrayBuffer(false),
     mXPCOMifier(nullptr)
 {
 #ifdef DEBUG
   StaticAssertions();
 #endif
 }
 
-nsXMLHttpRequest::~nsXMLHttpRequest()
+XMLHttpRequestMainThread::~XMLHttpRequestMainThread()
 {
   mState |= XML_HTTP_REQUEST_DELETED;
 
   if (mState & (XML_HTTP_REQUEST_SENT |
                 XML_HTTP_REQUEST_LOADING)) {
     Abort();
   }
 
@@ -226,26 +217,26 @@ nsXMLHttpRequest::~nsXMLHttpRequest()
   mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
 
   mResultJSON.setUndefined();
   mResultArrayBuffer = nullptr;
   mozilla::DropJSObjects(this);
 }
 
 void
-nsXMLHttpRequest::RootJSResultObjects()
+XMLHttpRequestMainThread::RootJSResultObjects()
 {
   mozilla::HoldJSObjects(this);
 }
 
 /**
  * This Init method is called from the factory constructor.
  */
 nsresult
-nsXMLHttpRequest::Init()
+XMLHttpRequestMainThread::Init()
 {
   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
   nsCOMPtr<nsIPrincipal> subjectPrincipal;
   if (secMan) {
     secMan->GetSystemPrincipal(getter_AddRefs(subjectPrincipal));
   }
   NS_ENSURE_STATE(subjectPrincipal);
 
@@ -255,29 +246,29 @@ nsXMLHttpRequest::Init()
   Construct(subjectPrincipal, xpc::NativeGlobal(xpc::PrivilegedJunkScope()));
   return NS_OK;
 }
 
 /**
  * This Init method should only be called by C++ consumers.
  */
 NS_IMETHODIMP
-nsXMLHttpRequest::Init(nsIPrincipal* aPrincipal,
-                       nsIScriptContext* aScriptContext,
-                       nsIGlobalObject* aGlobalObject,
-                       nsIURI* aBaseURI,
-                       nsILoadGroup* aLoadGroup)
+XMLHttpRequestMainThread::Init(nsIPrincipal* aPrincipal,
+                               nsIScriptContext* aScriptContext,
+                               nsIGlobalObject* aGlobalObject,
+                               nsIURI* aBaseURI,
+                               nsILoadGroup* aLoadGroup)
 {
   NS_ENSURE_ARG_POINTER(aPrincipal);
   Construct(aPrincipal, aGlobalObject, aBaseURI, aLoadGroup);
   return NS_OK;
 }
 
 void
-nsXMLHttpRequest::InitParameters(bool aAnon, bool aSystem)
+XMLHttpRequestMainThread::InitParameters(bool aAnon, bool aSystem)
 {
   if (!aAnon && !aSystem) {
     return;
   }
 
   // Check for permissions.
   // Chrome is always allowed access, so do the permission check only
   // for non-chrome pages.
@@ -309,64 +300,64 @@ nsXMLHttpRequest::InitParameters(bool aA
       return;
     }
   }
 
   SetParameters(aAnon, aSystem);
 }
 
 void
-nsXMLHttpRequest::ResetResponse()
+XMLHttpRequestMainThread::ResetResponse()
 {
   mResponseXML = nullptr;
   mResponseBody.Truncate();
   mResponseText.Truncate();
   mResponseBlob = nullptr;
   mDOMBlob = nullptr;
   mBlobSet = nullptr;
   mResultArrayBuffer = nullptr;
   mArrayBufferBuilder.reset();
   mResultJSON.setUndefined();
   mDataAvailable = 0;
   mLoadTransferred = 0;
   mResponseBodyDecodedPos = 0;
 }
 
 void
-nsXMLHttpRequest::SetRequestObserver(nsIRequestObserver* aObserver)
+XMLHttpRequestMainThread::SetRequestObserver(nsIRequestObserver* aObserver)
 {
   mRequestObserver = aObserver;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequest)
-
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsXMLHttpRequest)
+NS_IMPL_CYCLE_COLLECTION_CLASS(XMLHttpRequestMainThread)
+
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(XMLHttpRequestMainThread)
   bool isBlack = tmp->IsBlack();
   if (isBlack || tmp->mWaitingForOnStopRequest) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->MarkForCC();
     }
     if (!isBlack && tmp->PreservingWrapper()) {
       // This marks the wrapper black.
       tmp->GetWrapper();
     }
     return true;
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsXMLHttpRequest)
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(XMLHttpRequestMainThread)
   return tmp->
     IsBlackAndDoesNotNeedTracing(static_cast<DOMEventTargetHelper*>(tmp));
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsXMLHttpRequest)
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(XMLHttpRequestMainThread)
   return tmp->IsBlack();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest,
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XMLHttpRequestMainThread,
                                                   XMLHttpRequestEventTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannel)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResponseXML)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mXMLParserStreamListener)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResponseBlob)
@@ -374,17 +365,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotificationCallbacks)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannelEventSink)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProgressEventSink)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUpload)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest,
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XMLHttpRequestMainThread,
                                                 XMLHttpRequestEventTarget)
   tmp->mResultArrayBuffer = nullptr;
   tmp->mArrayBufferBuilder.reset();
   tmp->mResultJSON.setUndefined();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChannel)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mResponseXML)
 
@@ -395,50 +386,50 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNotificationCallbacks)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChannelEventSink)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mProgressEventSink)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mUpload)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsXMLHttpRequest,
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(XMLHttpRequestMainThread,
                                                XMLHttpRequestEventTarget)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mResultArrayBuffer)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mResultJSON)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
-// QueryInterface implementation for nsXMLHttpRequest
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLHttpRequest)
+// QueryInterface implementation for XMLHttpRequestMainThread
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XMLHttpRequestMainThread)
   NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequest)
   NS_INTERFACE_MAP_ENTRY(nsIJSXMLHttpRequest)
   NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
   NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
   NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
   NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_INTERFACE_MAP_ENTRY(nsISizeOfEventTarget)
 NS_INTERFACE_MAP_END_INHERITING(XMLHttpRequestEventTarget)
 
-NS_IMPL_ADDREF_INHERITED(nsXMLHttpRequest, XMLHttpRequestEventTarget)
-NS_IMPL_RELEASE_INHERITED(nsXMLHttpRequest, XMLHttpRequestEventTarget)
-
-NS_IMPL_EVENT_HANDLER(nsXMLHttpRequest, readystatechange)
+NS_IMPL_ADDREF_INHERITED(XMLHttpRequestMainThread, XMLHttpRequestEventTarget)
+NS_IMPL_RELEASE_INHERITED(XMLHttpRequestMainThread, XMLHttpRequestEventTarget)
+
+NS_IMPL_EVENT_HANDLER(XMLHttpRequestMainThread, readystatechange)
 
 void
-nsXMLHttpRequest::DisconnectFromOwner()
+XMLHttpRequestMainThread::DisconnectFromOwner()
 {
   XMLHttpRequestEventTarget::DisconnectFromOwner();
   Abort();
 }
 
 size_t
-nsXMLHttpRequest::SizeOfEventTargetIncludingThis(
+XMLHttpRequestMainThread::SizeOfEventTargetIncludingThis(
   MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
   n += mResponseBody.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
 
   // Why is this safe?  Because no-one else will report this string.  The
   // other possible sharers of this string are as follows.
   //
@@ -455,17 +446,17 @@ nsXMLHttpRequest::SizeOfEventTargetInclu
   return n;
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - lots
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetChannel(nsIChannel **aChannel)
+XMLHttpRequestMainThread::GetChannel(nsIChannel **aChannel)
 {
   NS_ENSURE_ARG_POINTER(aChannel);
   NS_IF_ADDREF(*aChannel = mChannel);
 
   return NS_OK;
 }
 
 static void LogMessage(const char* aWarning, nsPIDOMWindowInner* aWindow)
@@ -476,34 +467,34 @@ static void LogMessage(const char* aWarn
   }
   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                   NS_LITERAL_CSTRING("DOM"), doc,
                                   nsContentUtils::eDOM_PROPERTIES,
                                   aWarning);
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetResponseXML(nsIDOMDocument **aResponseXML)
+XMLHttpRequestMainThread::GetResponseXML(nsIDOMDocument **aResponseXML)
 {
   ErrorResult rv;
   nsIDocument* responseXML = GetResponseXML(rv);
   if (rv.Failed()) {
     return rv.StealNSResult();
   }
 
   if (!responseXML) {
     *aResponseXML = nullptr;
     return NS_OK;
   }
 
   return CallQueryInterface(responseXML, aResponseXML);
 }
 
 nsIDocument*
-nsXMLHttpRequest::GetResponseXML(ErrorResult& aRv)
+XMLHttpRequestMainThread::GetResponseXML(ErrorResult& aRv)
 {
   if (mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT &&
       mResponseType != XML_HTTP_RESPONSE_TYPE_DOCUMENT) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
   if (mWarnAboutSyncHtml) {
     mWarnAboutSyncHtml = false;
@@ -515,17 +506,17 @@ nsXMLHttpRequest::GetResponseXML(ErrorRe
   return mResponseXML;
 }
 
 /*
  * This piece copied from XMLDocument, we try to get the charset
  * from HTTP headers.
  */
 nsresult
-nsXMLHttpRequest::DetectCharset()
+XMLHttpRequestMainThread::DetectCharset()
 {
   mResponseCharset.Truncate();
   mDecoder = nullptr;
 
   if (mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT &&
       mResponseType != XML_HTTP_RESPONSE_TYPE_TEXT &&
       mResponseType != XML_HTTP_RESPONSE_TYPE_JSON &&
       mResponseType != XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT) {
@@ -549,18 +540,18 @@ nsXMLHttpRequest::DetectCharset()
   }
 
   mDecoder = EncodingUtils::DecoderForEncoding(mResponseCharset);
 
   return NS_OK;
 }
 
 nsresult
-nsXMLHttpRequest::AppendToResponseText(const char * aSrcBuffer,
-                                       uint32_t aSrcBufferLen)
+XMLHttpRequestMainThread::AppendToResponseText(const char * aSrcBuffer,
+                                               uint32_t aSrcBufferLen)
 {
   NS_ENSURE_STATE(mDecoder);
 
   int32_t destBufferLen;
   nsresult rv = mDecoder->GetMaxLength(aSrcBuffer, aSrcBufferLen,
                                        &destBufferLen);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -592,27 +583,28 @@ nsXMLHttpRequest::AppendToResponseText(c
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   mResponseText.SetLength(totalChars.value());
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetResponseText(nsAString& aResponseText)
+XMLHttpRequestMainThread::GetResponseText(nsAString& aResponseText)
 {
   ErrorResult rv;
   nsString responseText;
   GetResponseText(responseText, rv);
   aResponseText = responseText;
   return rv.StealNSResult();
 }
 
 void
-nsXMLHttpRequest::GetResponseText(nsString& aResponseText, ErrorResult& aRv)
+XMLHttpRequestMainThread::GetResponseText(nsAString& aResponseText,
+                                          ErrorResult& aRv)
 {
   aResponseText.Truncate();
 
   if (mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT &&
       mResponseType != XML_HTTP_RESPONSE_TYPE_TEXT &&
       mResponseType != XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
@@ -659,17 +651,17 @@ nsXMLHttpRequest::GetResponseText(nsStri
     mResponseBody.Truncate();
     mResponseBodyDecodedPos = 0;
   }
 
   aResponseText = mResponseText;
 }
 
 nsresult
-nsXMLHttpRequest::CreateResponseParsedJSON(JSContext* aCx)
+XMLHttpRequestMainThread::CreateResponseParsedJSON(JSContext* aCx)
 {
   if (!aCx) {
     return NS_ERROR_FAILURE;
   }
   RootJSResultObjects();
 
   // The Unicode converter has already zapped the BOM if there was one
   JS::Rooted<JS::Value> value(aCx);
@@ -679,17 +671,17 @@ nsXMLHttpRequest::CreateResponseParsedJS
     return NS_ERROR_FAILURE;
   }
 
   mResultJSON = value;
   return NS_OK;
 }
 
 void
-nsXMLHttpRequest::CreatePartialBlob(ErrorResult& aRv)
+XMLHttpRequestMainThread::CreatePartialBlob(ErrorResult& aRv)
 {
   if (mDOMBlob) {
     // Use progress info to determine whether load is complete, but use
     // mDataAvailable to ensure a slice is created based on the uncompressed
     // data count.
     if (mLoadTotal == mLoadTransferred) {
       mResponseBlob = mDOMBlob;
     } else {
@@ -707,17 +699,17 @@ nsXMLHttpRequest::CreatePartialBlob(Erro
   nsAutoCString contentType;
   if (mLoadTotal == mLoadTransferred) {
     mChannel->GetContentType(contentType);
   }
 
   mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType, aRv);
 }
 
-NS_IMETHODIMP nsXMLHttpRequest::GetResponseType(nsAString& aResponseType)
+NS_IMETHODIMP XMLHttpRequestMainThread::GetResponseType(nsAString& aResponseType)
 {
   switch (mResponseType) {
   case XML_HTTP_RESPONSE_TYPE_DEFAULT:
     aResponseType.Truncate();
     break;
   case XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER:
     aResponseType.AssignLiteral("arraybuffer");
     break;
@@ -746,17 +738,17 @@ NS_IMETHODIMP nsXMLHttpRequest::GetRespo
     NS_ERROR("Should not happen");
   }
 
   return NS_OK;
 }
 
 #ifdef DEBUG
 void
-nsXMLHttpRequest::StaticAssertions()
+XMLHttpRequestMainThread::StaticAssertions()
 {
 #define ASSERT_ENUM_EQUAL(_lc, _uc) \
   static_assert(\
     static_cast<int>(XMLHttpRequestResponseType::_lc)  \
     == XML_HTTP_RESPONSE_TYPE_ ## _uc, \
     #_uc " should match")
 
   ASSERT_ENUM_EQUAL(_empty, DEFAULT);
@@ -767,19 +759,19 @@ nsXMLHttpRequest::StaticAssertions()
   ASSERT_ENUM_EQUAL(Text, TEXT);
   ASSERT_ENUM_EQUAL(Moz_chunked_text, CHUNKED_TEXT);
   ASSERT_ENUM_EQUAL(Moz_chunked_arraybuffer, CHUNKED_ARRAYBUFFER);
   ASSERT_ENUM_EQUAL(Moz_blob, MOZ_BLOB);
 #undef ASSERT_ENUM_EQUAL
 }
 #endif
 
-NS_IMETHODIMP nsXMLHttpRequest::SetResponseType(const nsAString& aResponseType)
+NS_IMETHODIMP XMLHttpRequestMainThread::SetResponseType(const nsAString& aResponseType)
 {
-  nsXMLHttpRequest::ResponseTypeEnum responseType;
+  XMLHttpRequestMainThread::ResponseTypeEnum responseType;
   if (aResponseType.IsEmpty()) {
     responseType = XML_HTTP_RESPONSE_TYPE_DEFAULT;
   } else if (aResponseType.EqualsLiteral("arraybuffer")) {
     responseType = XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER;
   } else if (aResponseType.EqualsLiteral("blob")) {
     responseType = XML_HTTP_RESPONSE_TYPE_BLOB;
   } else if (aResponseType.EqualsLiteral("document")) {
     responseType = XML_HTTP_RESPONSE_TYPE_DOCUMENT;
@@ -798,25 +790,25 @@ NS_IMETHODIMP nsXMLHttpRequest::SetRespo
   }
 
   ErrorResult rv;
   SetResponseType(responseType, rv);
   return rv.StealNSResult();
 }
 
 void
-nsXMLHttpRequest::SetResponseType(XMLHttpRequestResponseType aType,
-                                  ErrorResult& aRv)
+XMLHttpRequestMainThread::SetResponseType(XMLHttpRequestResponseType aType,
+                                          ErrorResult& aRv)
 {
   SetResponseType(ResponseTypeEnum(static_cast<int>(aType)), aRv);
 }
 
 void
-nsXMLHttpRequest::SetResponseType(nsXMLHttpRequest::ResponseTypeEnum aResponseType,
-                                  ErrorResult& aRv)
+XMLHttpRequestMainThread::SetResponseType(XMLHttpRequestMainThread::ResponseTypeEnum aResponseType,
+                                          ErrorResult& aRv)
 {
   // If the state is LOADING or DONE raise an INVALID_STATE_ERR exception
   // and terminate these steps.
   if ((mState & (XML_HTTP_REQUEST_LOADING | XML_HTTP_REQUEST_DONE))) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
@@ -836,27 +828,27 @@ nsXMLHttpRequest::SetResponseType(nsXMLH
   }
 
   // Set the responseType attribute's value to the given value.
   mResponseType = aResponseType;
 
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetResponse(JSContext *aCx, JS::MutableHandle<JS::Value> aResult)
+XMLHttpRequestMainThread::GetResponse(JSContext *aCx, JS::MutableHandle<JS::Value> aResult)
 {
   ErrorResult rv;
   GetResponse(aCx, aResult, rv);
   return rv.StealNSResult();
 }
 
 void
-nsXMLHttpRequest::GetResponse(JSContext* aCx,
-                              JS::MutableHandle<JS::Value> aResponse,
-                              ErrorResult& aRv)
+XMLHttpRequestMainThread::GetResponse(JSContext* aCx,
+                                      JS::MutableHandle<JS::Value> aResponse,
+                                      ErrorResult& aRv)
 {
   switch (mResponseType) {
   case XML_HTTP_RESPONSE_TYPE_DEFAULT:
   case XML_HTTP_RESPONSE_TYPE_TEXT:
   case XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT:
   {
     nsString str;
     aRv = GetResponseText(str);
@@ -951,43 +943,43 @@ nsXMLHttpRequest::GetResponse(JSContext*
   default:
     NS_ERROR("Should not happen");
   }
 
   aResponse.setNull();
 }
 
 bool
-nsXMLHttpRequest::IsCrossSiteCORSRequest() const
+XMLHttpRequestMainThread::IsCrossSiteCORSRequest() const
 {
   if (!mChannel) {
     return false;
   }
 
   nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
   MOZ_ASSERT(loadInfo);
 
   return loadInfo->GetTainting() == LoadTainting::CORS;
 }
 
 bool
-nsXMLHttpRequest::IsDeniedCrossSiteCORSRequest()
+XMLHttpRequestMainThread::IsDeniedCrossSiteCORSRequest()
 {
   if (IsCrossSiteCORSRequest()) {
     nsresult rv;
     mChannel->GetStatus(&rv);
     if (NS_FAILED(rv)) {
       return true;
     }
   }
   return false;
 }
 
 void
-nsXMLHttpRequest::GetResponseURL(nsAString& aUrl)
+XMLHttpRequestMainThread::GetResponseURL(nsAString& aUrl)
 {
   aUrl.Truncate();
 
   uint16_t readyState = ReadyState();
   if ((readyState == UNSENT || readyState == OPENED) || !mChannel) {
     return;
   }
 
@@ -1005,24 +997,25 @@ nsXMLHttpRequest::GetResponseURL(nsAStri
   }
 
   nsAutoCString temp;
   responseUrl->GetSpecIgnoringRef(temp);
   CopyUTF8toUTF16(temp, aUrl);
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetStatus(uint32_t *aStatus)
+XMLHttpRequestMainThread::GetStatus(uint32_t *aStatus)
 {
-  *aStatus = Status();
-  return NS_OK;
+  ErrorResult rv;
+  *aStatus = GetStatus(rv);
+  return rv.StealNSResult();
 }
 
 uint32_t
-nsXMLHttpRequest::Status()
+XMLHttpRequestMainThread::GetStatus(ErrorResult& aRv)
 {
   // Make sure we don't leak status information from denied cross-site
   // requests.
   if (IsDeniedCrossSiteCORSRequest()) {
     return 0;
   }
 
   uint16_t readyState = ReadyState();
@@ -1057,19 +1050,27 @@ nsXMLHttpRequest::Status()
   nsresult rv = httpChannel->GetResponseStatus(&status);
   if (NS_FAILED(rv)) {
     status = 0;
   }
 
   return status;
 }
 
-IMPL_CSTRING_GETTER(GetStatusText)
+NS_IMETHODIMP
+XMLHttpRequestMainThread::GetStatusText(nsACString& aOut)
+{
+  ErrorResult rv;
+  GetStatusText(aOut, rv);
+  return rv.StealNSResult();
+}
+
 void
-nsXMLHttpRequest::GetStatusText(nsCString& aStatusText)
+XMLHttpRequestMainThread::GetStatusText(nsACString& aStatusText,
+                                        ErrorResult& aRv)
 {
   // Return an empty status text on all error loads.
   aStatusText.Truncate();
 
   // Make sure we don't leak status information from denied cross-site
   // requests.
   if (IsDeniedCrossSiteCORSRequest()) {
     return;
@@ -1092,18 +1093,18 @@ nsXMLHttpRequest::GetStatusText(nsCStrin
   if (httpChannel) {
     httpChannel->GetResponseStatusText(aStatusText);
   } else {
     aStatusText.AssignLiteral("OK");
   }
 }
 
 void
-nsXMLHttpRequest::CloseRequestWithError(const nsAString& aType,
-                                        const uint32_t aFlag)
+XMLHttpRequestMainThread::CloseRequestWithError(const nsAString& aType,
+                                                const uint32_t aFlag)
 {
   if (mChannel) {
     mChannel->Cancel(NS_BINDING_ABORTED);
   }
   if (mTimeoutTimer) {
     mTimeoutTimer->Cancel();
   }
   uint32_t responseLength = mResponseBody.Length();
@@ -1128,42 +1129,43 @@ nsXMLHttpRequest::CloseRequestWithError(
         mUploadComplete = true;
         DispatchProgressEvent(mUpload, aType, true, mUploadTransferred,
                               mUploadTotal);
       }
     }
   }
 
   // The ChangeState call above calls onreadystatechange handlers which
-  // if they load a new url will cause nsXMLHttpRequest::Open to clear
+  // if they load a new url will cause XMLHttpRequestMainThread::Open to clear
   // the abort state bit. If this occurs we're not uninitialized (bug 361773).
   if (mState & XML_HTTP_REQUEST_ABORTED) {
     ChangeState(XML_HTTP_REQUEST_UNSENT, false);  // IE seems to do it
   }
 
   mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
 }
 
 void
-nsXMLHttpRequest::Abort()
+XMLHttpRequestMainThread::Abort(ErrorResult& arv)
 {
   CloseRequestWithError(NS_LITERAL_STRING(ABORT_STR), XML_HTTP_REQUEST_ABORTED);
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::SlowAbort()
+XMLHttpRequestMainThread::SlowAbort()
 {
   Abort();
   return NS_OK;
 }
 
 /*Method that checks if it is safe to expose a header value to the client.
 It is used to check what headers are exposed for CORS requests.*/
 bool
-nsXMLHttpRequest::IsSafeHeader(const nsACString& aHeader, NotNull<nsIHttpChannel*> aHttpChannel) const
+XMLHttpRequestMainThread::IsSafeHeader(const nsACString& aHeader,
+                                       NotNull<nsIHttpChannel*> aHttpChannel) const
 {
   // See bug #380418. Hide "Set-Cookie" headers from non-chrome scripts.
   if (!IsSystemXHR() && nsContentUtils::IsForbiddenResponseHeader(aHeader)) {
     NS_WARNING("blocked access to response header");
     return false;
   }
   // if this is not a CORS call all headers are safe
   if (!IsCrossSiteCORSRequest()) {
@@ -1206,19 +1208,27 @@ nsXMLHttpRequest::IsSafeHeader(const nsA
     }
     if (aHeader.Equals(token, nsCaseInsensitiveCStringComparator())) {
       isSafe = true;
     }
   }
   return isSafe;
 }
 
-IMPL_CSTRING_GETTER(GetAllResponseHeaders)
+NS_IMETHODIMP
+XMLHttpRequestMainThread::GetAllResponseHeaders(nsACString& aOut)
+{
+  ErrorResult rv;
+  GetAllResponseHeaders(aOut, rv);
+  return rv.StealNSResult();
+}
+
 void
-nsXMLHttpRequest::GetAllResponseHeaders(nsCString& aResponseHeaders)
+XMLHttpRequestMainThread::GetAllResponseHeaders(nsACString& aResponseHeaders,
+                                                ErrorResult& aRv)
 {
   aResponseHeaders.Truncate();
 
   // If the state is UNSENT or OPENED,
   // return the empty string and terminate these steps.
   if (mState & (XML_HTTP_REQUEST_UNSENT |
                 XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT)) {
     return;
@@ -1253,27 +1263,27 @@ nsXMLHttpRequest::GetAllResponseHeaders(
   if (NS_SUCCEEDED(mChannel->GetContentLength(&length))) {
     aResponseHeaders.AppendLiteral("Content-Length: ");
     aResponseHeaders.AppendInt(length);
     aResponseHeaders.AppendLiteral("\r\n");
   }
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetResponseHeader(const nsACString& aHeader,
-                                    nsACString& aResult)
+XMLHttpRequestMainThread::GetResponseHeader(const nsACString& aHeader,
+                                            nsACString& aResult)
 {
   ErrorResult rv;
   GetResponseHeader(aHeader, aResult, rv);
   return rv.StealNSResult();
 }
 
 void
-nsXMLHttpRequest::GetResponseHeader(const nsACString& header,
-                                    nsACString& _retval, ErrorResult& aRv)
+XMLHttpRequestMainThread::GetResponseHeader(const nsACString& header,
+                                            nsACString& _retval, ErrorResult& aRv)
 {
   _retval.SetIsVoid(true);
 
   nsCOMPtr<nsIHttpChannel> httpChannel = GetCurrentHttpChannel();
 
   if (!httpChannel) {
     // If the state is UNSENT or OPENED,
     // return null and terminate these steps.
@@ -1328,17 +1338,17 @@ nsXMLHttpRequest::GetResponseHeader(cons
   if (aRv.ErrorCodeIs(NS_ERROR_NOT_AVAILABLE)) {
     // Means no header
     _retval.SetIsVoid(true);
     aRv.SuppressException();
   }
 }
 
 already_AddRefed<nsILoadGroup>
-nsXMLHttpRequest::GetLoadGroup() const
+XMLHttpRequestMainThread::GetLoadGroup() const
 {
   if (mState & XML_HTTP_REQUEST_BACKGROUND) {
     return nullptr;
   }
 
   if (mLoadGroup) {
     nsCOMPtr<nsILoadGroup> ref = mLoadGroup;
     return ref.forget();
@@ -1348,35 +1358,35 @@ nsXMLHttpRequest::GetLoadGroup() const
   if (doc) {
     return doc->GetDocumentLoadGroup();
   }
 
   return nullptr;
 }
 
 nsresult
-nsXMLHttpRequest::CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent)
+XMLHttpRequestMainThread::CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent)
 {
   RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
   event.forget(aDOMEvent);
 
   (*aDOMEvent)->InitEvent(NS_LITERAL_STRING(READYSTATE_STR),
                           false, false);
 
   // We assume anyone who managed to call CreateReadystatechangeEvent is trusted
   (*aDOMEvent)->SetTrusted(true);
 
   return NS_OK;
 }
 
 void
-nsXMLHttpRequest::DispatchProgressEvent(DOMEventTargetHelper* aTarget,
-                                        const nsAString& aType,
-                                        bool aLengthComputable,
-                                        int64_t aLoaded, int64_t aTotal)
+XMLHttpRequestMainThread::DispatchProgressEvent(DOMEventTargetHelper* aTarget,
+                                                const nsAString& aType,
+                                                bool aLengthComputable,
+                                                int64_t aLoaded, int64_t aTotal)
 {
   NS_ASSERTION(aTarget, "null target");
   NS_ASSERTION(!aType.IsEmpty(), "missing event type");
 
   if (NS_FAILED(CheckInnerWindowCorrectness()) ||
       (!AllowUploadProgress() && aTarget == mUpload)) {
     return;
   }
@@ -1401,39 +1411,39 @@ nsXMLHttpRequest::DispatchProgressEvent(
 
   if (dispatchLoadend) {
     DispatchProgressEvent(aTarget, NS_LITERAL_STRING(LOADEND_STR),
                           aLengthComputable, aLoaded, aTotal);
   }
 }
 
 already_AddRefed<nsIHttpChannel>
-nsXMLHttpRequest::GetCurrentHttpChannel()
+XMLHttpRequestMainThread::GetCurrentHttpChannel()
 {
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
   return httpChannel.forget();
 }
 
 already_AddRefed<nsIJARChannel>
-nsXMLHttpRequest::GetCurrentJARChannel()
+XMLHttpRequestMainThread::GetCurrentJARChannel()
 {
   nsCOMPtr<nsIJARChannel> appChannel = do_QueryInterface(mChannel);
   return appChannel.forget();
 }
 
 bool
-nsXMLHttpRequest::IsSystemXHR() const
+XMLHttpRequestMainThread::IsSystemXHR() const
 {
   return mIsSystem || nsContentUtils::IsSystemPrincipal(mPrincipal);
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
-                       bool async, const nsAString& user,
-                       const nsAString& password, uint8_t optional_argc)
+XMLHttpRequestMainThread::Open(const nsACString& method, const nsACString& url,
+                               bool async, const nsAString& user,
+                               const nsAString& password, uint8_t optional_argc)
 {
   if (!optional_argc) {
     // No optional arguments were passed in. Default async to true.
     async = true;
   }
   Optional<nsAString> realUser;
   if (optional_argc > 1) {
     realUser = &user;
@@ -1441,19 +1451,19 @@ nsXMLHttpRequest::Open(const nsACString&
   Optional<nsAString> realPassword;
   if (optional_argc > 2) {
     realPassword = &password;
   }
   return Open(method, url, async, realUser, realPassword);
 }
 
 nsresult
-nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
-                       bool async, const Optional<nsAString>& user,
-                       const Optional<nsAString>& password)
+XMLHttpRequestMainThread::Open(const nsACString& inMethod, const nsACString& url,
+                               bool async, const Optional<nsAString>& user,
+                               const Optional<nsAString>& password)
 {
   if (inMethod.IsEmpty()) {
     return NS_ERROR_DOM_SYNTAX_ERR;
   }
 
   if (!async && !DontWarnAboutSyncXHR() && GetOwner() &&
       GetOwner()->GetExtantDoc()) {
     GetOwner()->GetExtantDoc()->WarnOnceAbout(nsIDocument::eSyncXMLHttpRequest);
@@ -1628,40 +1638,40 @@ nsXMLHttpRequest::Open(const nsACString&
   }
 
   ChangeState(XML_HTTP_REQUEST_OPENED);
 
   return NS_OK;
 }
 
 void
-nsXMLHttpRequest::PopulateNetworkInterfaceId()
+XMLHttpRequestMainThread::PopulateNetworkInterfaceId()
 {
   if (mNetworkInterfaceId.IsEmpty()) {
     return;
   }
   nsCOMPtr<nsIHttpChannelInternal> channel(do_QueryInterface(mChannel));
   if (!channel) {
     return;
   }
   channel->SetNetworkInterfaceId(mNetworkInterfaceId);
 }
 
 /*
  * "Copy" from a stream.
  */
 NS_METHOD
-nsXMLHttpRequest::StreamReaderFunc(nsIInputStream* in,
-                                   void* closure,
-                                   const char* fromRawSegment,
-                                   uint32_t toOffset,
-                                   uint32_t count,
-                                   uint32_t *writeCount)
+XMLHttpRequestMainThread::StreamReaderFunc(nsIInputStream* in,
+                                           void* closure,
+                                           const char* fromRawSegment,
+                                           uint32_t toOffset,
+                                           uint32_t count,
+                                           uint32_t *writeCount)
 {
-  nsXMLHttpRequest* xmlHttpRequest = static_cast<nsXMLHttpRequest*>(closure);
+  XMLHttpRequestMainThread* xmlHttpRequest = static_cast<XMLHttpRequestMainThread*>(closure);
   if (!xmlHttpRequest || !writeCount) {
     NS_WARNING("XMLHttpRequest cannot read from stream: no closure or writeCount");
     return NS_ERROR_FAILURE;
   }
 
   nsresult rv = NS_OK;
 
   if (xmlHttpRequest->mResponseType == XML_HTTP_RESPONSE_TYPE_BLOB ||
@@ -1729,17 +1739,17 @@ nsXMLHttpRequest::StreamReaderFunc(nsIIn
     *writeCount = count;
   } else {
     *writeCount = 0;
   }
 
   return rv;
 }
 
-bool nsXMLHttpRequest::CreateDOMBlob(nsIRequest *request)
+bool XMLHttpRequestMainThread::CreateDOMBlob(nsIRequest *request)
 {
   nsCOMPtr<nsIFile> file;
   nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(request);
   if (fc) {
     fc->GetFile(getter_AddRefs(file));
   }
 
   if (!file)
@@ -1752,38 +1762,38 @@ bool nsXMLHttpRequest::CreateDOMBlob(nsI
                                   NS_ConvertASCIItoUTF16(contentType));
 
   mBlobSet = nullptr;
   NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty");
   return true;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::OnDataAvailable(nsIRequest *request,
-                                  nsISupports *ctxt,
-                                  nsIInputStream *inStr,
-                                  uint64_t sourceOffset,
-                                  uint32_t count)
+XMLHttpRequestMainThread::OnDataAvailable(nsIRequest *request,
+                                          nsISupports *ctxt,
+                                          nsIInputStream *inStr,
+                                          uint64_t sourceOffset,
+                                          uint32_t count)
 {
   NS_ENSURE_ARG_POINTER(inStr);
 
   MOZ_ASSERT(mContext.get() == ctxt,"start context different from OnDataAvailable context");
 
   mProgressSinceLastProgressEvent = true;
 
   bool cancelable = false;
   if ((mResponseType == XML_HTTP_RESPONSE_TYPE_BLOB ||
        mResponseType == XML_HTTP_RESPONSE_TYPE_MOZ_BLOB) && !mDOMBlob) {
     cancelable = CreateDOMBlob(request);
     // The nsIStreamListener contract mandates us
     // to read from the stream before returning.
   }
 
   uint32_t totalRead;
-  nsresult rv = inStr->ReadSegments(nsXMLHttpRequest::StreamReaderFunc,
+  nsresult rv = inStr->ReadSegments(XMLHttpRequestMainThread::StreamReaderFunc,
                                     (void*)this, count, &totalRead);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (cancelable) {
     // We don't have to read from the local file for the blob response
     ErrorResult error;
     mDataAvailable = mDOMBlob->GetSize(error);
     if (NS_WARN_IF(error.Failed())) {
@@ -1799,19 +1809,19 @@ nsXMLHttpRequest::OnDataAvailable(nsIReq
   ChangeState(XML_HTTP_REQUEST_LOADING);
 
   MaybeDispatchProgressEvents(false);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
+XMLHttpRequestMainThread::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
 {
-  PROFILER_LABEL("nsXMLHttpRequest", "OnStartRequest",
+  PROFILER_LABEL("XMLHttpRequestMainThread", "OnStartRequest",
     js::ProfileEntry::Category::NETWORK);
 
   nsresult rv = NS_OK;
   if (!mFirstStartRequestSeen && mRequestObserver) {
     mFirstStartRequestSeen = true;
     mRequestObserver->OnStartRequest(request, ctxt);
   }
 
@@ -2044,19 +2054,19 @@ nsXMLHttpRequest::OnStartRequest(nsIRequ
       HasListenersFor(nsGkAtoms::onprogress)) {
     StartProgressEventTimer();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status)
+XMLHttpRequestMainThread::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status)
 {
-  PROFILER_LABEL("nsXMLHttpRequest", "OnStopRequest",
+  PROFILER_LABEL("XMLHttpRequestMainThread", "OnStopRequest",
     js::ProfileEntry::Category::NETWORK);
 
   if (request != mChannel) {
     // Can this still happen?
     return NS_OK;
   }
 
   mWaitingForOnStopRequest = false;
@@ -2182,17 +2192,17 @@ nsXMLHttpRequest::OnStopRequest(nsIReque
   if (!mResponseXML->GetRootElement()) {
     mResponseXML = nullptr;
   }
   ChangeStateToDone();
   return NS_OK;
 }
 
 void
-nsXMLHttpRequest::ChangeStateToDone()
+XMLHttpRequestMainThread::ChangeStateToDone()
 {
   if (mIsHtml) {
     // In the HTML case, this has to be deferred, because the parser doesn't
     // do it's job synchronously.
     MaybeDispatchProgressEvents(true);
   }
 
   ChangeState(XML_HTTP_REQUEST_DONE, true);
@@ -2217,19 +2227,19 @@ nsXMLHttpRequest::ChangeStateToDone()
     // for that and throw. Also calling the various status
     // methods/members will not throw.
     // This matches what IE does.
     mChannel = nullptr;
   }
 }
 
 static nsresult
-GetRequestBody(nsIDOMDocument* aDoc, nsIInputStream** aResult,
-               uint64_t* aContentLength, nsACString& aContentType,
-               nsACString& aCharset)
+GetRequestBodyInternal(nsIDOMDocument* aDoc, nsIInputStream** aResult,
+                       uint64_t* aContentLength, nsACString& aContentType,
+                       nsACString& aCharset)
 {
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(aDoc));
   NS_ENSURE_STATE(doc);
   aCharset.AssignLiteral("UTF-8");
 
   nsresult rv;
   nsCOMPtr<nsIStorageStream> storStream;
   rv = NS_NewStorageStream(4096, UINT32_MAX, getter_AddRefs(storStream));
@@ -2272,56 +2282,57 @@ GetRequestBody(nsIDOMDocument* aDoc, nsI
   rv = storStream->GetLength(&length);
   NS_ENSURE_SUCCESS(rv, rv);
   *aContentLength = length;
 
   return storStream->NewInputStream(0, aResult);
 }
 
 static nsresult
-GetRequestBody(const nsAString& aString, nsIInputStream** aResult,
-               uint64_t* aContentLength, nsACString& aContentType,
-               nsACString& aCharset)
+GetRequestBodyInternal(const nsAString& aString, nsIInputStream** aResult,
+                       uint64_t* aContentLength, nsACString& aContentType,
+                       nsACString& aCharset)
 {
   aContentType.AssignLiteral("text/plain");
   aCharset.AssignLiteral("UTF-8");
 
   nsCString converted = NS_ConvertUTF16toUTF8(aString);
   *aContentLength = converted.Length();
   return NS_NewCStringInputStream(aResult, converted);
 }
 
 static nsresult
-GetRequestBody(nsIInputStream* aStream, nsIInputStream** aResult,
-               uint64_t* aContentLength, nsACString& aContentType,
-               nsACString& aCharset)
+GetRequestBodyInternal(nsIInputStream* aStream, nsIInputStream** aResult,
+                       uint64_t* aContentLength, nsACString& aContentType,
+                       nsACString& aCharset)
 {
   aContentType.AssignLiteral("text/plain");
   aCharset.Truncate();
 
   nsresult rv = aStream->Available(aContentLength);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ADDREF(*aResult = aStream);
 
   return NS_OK;
 }
 
 static nsresult
-GetRequestBody(nsIXHRSendable* aSendable, nsIInputStream** aResult, uint64_t* aContentLength,
-               nsACString& aContentType, nsACString& aCharset)
+GetRequestBodyInternal(nsIXHRSendable* aSendable, nsIInputStream** aResult,
+                       uint64_t* aContentLength, nsACString& aContentType,
+                       nsACString& aCharset)
 {
   return aSendable->GetSendInfo(aResult, aContentLength, aContentType, aCharset);
 }
 
 // Used for array buffers and array buffer views
 static nsresult
-GetRequestBody(const uint8_t* aData, uint32_t aDataLength,
-               nsIInputStream** aResult, uint64_t* aContentLength,
-               nsACString& aContentType, nsACString& aCharset)
+GetRequestBodyInternal(const uint8_t* aData, uint32_t aDataLength,
+                       nsIInputStream** aResult, uint64_t* aContentLength,
+                       nsACString& aContentType, nsACString& aCharset)
 {
   aContentType.SetIsVoid(true);
   aCharset.Truncate();
 
   *aContentLength = aDataLength;
   const char* data = reinterpret_cast<const char*>(aData);
 
   nsCOMPtr<nsIInputStream> stream;
@@ -2330,18 +2341,19 @@ GetRequestBody(const uint8_t* aData, uin
   NS_ENSURE_SUCCESS(rv, rv);
 
   stream.forget(aResult);
 
   return NS_OK;
 }
 
 static nsresult
-GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult, uint64_t* aContentLength,
-               nsACString& aContentType, nsACString& aCharset)
+GetRequestBodyInternal(nsIVariant* aBody, nsIInputStream** aResult,
+                       uint64_t* aContentLength, nsACString& aContentType,
+                       nsACString& aCharset)
 {
   *aResult = nullptr;
 
   uint16_t dataType;
   nsresult rv = aBody->GetDataType(&dataType);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (dataType == nsIDataType::VTYPE_INTERFACE ||
@@ -2351,52 +2363,56 @@ GetRequestBody(nsIVariant* aBody, nsIInp
     rv = aBody->GetAsInterface(&iid, getter_AddRefs(supports));
     NS_ENSURE_SUCCESS(rv, rv);
 
     free(iid);
 
     // document?
     nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(supports);
     if (doc) {
-      return GetRequestBody(doc, aResult, aContentLength, aContentType, aCharset);
+      return GetRequestBodyInternal(doc, aResult, aContentLength, aContentType,
+                                    aCharset);
     }
 
     // nsISupportsString?
     nsCOMPtr<nsISupportsString> wstr = do_QueryInterface(supports);
     if (wstr) {
       nsAutoString string;
       wstr->GetData(string);
 
-      return GetRequestBody(string, aResult, aContentLength, aContentType, aCharset);
+      return GetRequestBodyInternal(string, aResult, aContentLength,
+                                    aContentType, aCharset);
     }
 
     // nsIInputStream?
     nsCOMPtr<nsIInputStream> stream = do_QueryInterface(supports);
     if (stream) {
-      return GetRequestBody(stream, aResult, aContentLength, aContentType, aCharset);
+      return GetRequestBodyInternal(stream, aResult, aContentLength,
+                                    aContentType, aCharset);
     }
 
     // nsIXHRSendable?
     nsCOMPtr<nsIXHRSendable> sendable = do_QueryInterface(supports);
     if (sendable) {
-      return GetRequestBody(sendable, aResult, aContentLength, aContentType, aCharset);
+      return GetRequestBodyInternal(sendable, aResult, aContentLength,
+                                    aContentType, aCharset);
     }
 
     // ArrayBuffer?
     JSContext* rootingCx = nsContentUtils::RootingCx();
     JS::Rooted<JS::Value> realVal(rootingCx);
 
     nsresult rv = aBody->GetAsJSVal(&realVal);
     if (NS_SUCCEEDED(rv) && !realVal.isPrimitive()) {
       JS::Rooted<JSObject*> obj(rootingCx, realVal.toObjectOrNull());
       RootedTypedArray<ArrayBuffer> buf(rootingCx);
       if (buf.Init(obj)) {
           buf.ComputeLengthAndData();
-          return GetRequestBody(buf.Data(), buf.Length(), aResult,
-                                aContentLength, aContentType, aCharset);
+          return GetRequestBodyInternal(buf.Data(), buf.Length(), aResult,
+                                        aContentLength, aContentType, aCharset);
       }
     }
   }
   else if (dataType == nsIDataType::VTYPE_VOID ||
            dataType == nsIDataType::VTYPE_EMPTY) {
     // Makes us act as if !aBody, don't upload anything
     aContentType.AssignLiteral("text/plain");
     aCharset.AssignLiteral("UTF-8");
@@ -2408,96 +2424,101 @@ GetRequestBody(nsIVariant* aBody, nsIInp
   char16_t* data = nullptr;
   uint32_t len = 0;
   rv = aBody->GetAsWStringWithSize(&len, &data);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsString string;
   string.Adopt(data, len);
 
-  return GetRequestBody(string, aResult, aContentLength, aContentType, aCharset);
+  return GetRequestBodyInternal(string, aResult, aContentLength, aContentType,
+                                aCharset);
 }
 
 /* static */
 nsresult
-nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant,
-                                 const Nullable<RequestBody>& aBody,
-                                 nsIInputStream** aResult,
-                                 uint64_t* aContentLength,
-                                 nsACString& aContentType, nsACString& aCharset)
+XMLHttpRequestMainThread::GetRequestBody(nsIVariant* aVariant,
+                                         const Nullable<RequestBody>& aBody,
+                                         nsIInputStream** aResult,
+                                         uint64_t* aContentLength,
+                                         nsACString& aContentType,
+                                         nsACString& aCharset)
 {
   if (aVariant) {
-    return ::GetRequestBody(aVariant, aResult, aContentLength, aContentType, aCharset);
+    return GetRequestBodyInternal(aVariant, aResult, aContentLength,
+                                  aContentType, aCharset);
   }
 
   const RequestBody& body = aBody.Value();
   RequestBody::Value value = body.GetValue();
   switch (body.GetType()) {
-    case nsXMLHttpRequest::RequestBody::ArrayBuffer:
+    case XMLHttpRequestMainThread::RequestBody::eArrayBuffer:
     {
       const ArrayBuffer* buffer = value.mArrayBuffer;
       buffer->ComputeLengthAndData();
-      return ::GetRequestBody(buffer->Data(), buffer->Length(), aResult,
-                              aContentLength, aContentType, aCharset);
+      return GetRequestBodyInternal(buffer->Data(), buffer->Length(), aResult,
+                                    aContentLength, aContentType, aCharset);
     }
-    case nsXMLHttpRequest::RequestBody::ArrayBufferView:
+    case XMLHttpRequestMainThread::RequestBody::eArrayBufferView:
     {
       const ArrayBufferView* view = value.mArrayBufferView;
       view->ComputeLengthAndData();
-      return ::GetRequestBody(view->Data(), view->Length(), aResult,
-                              aContentLength, aContentType, aCharset);
+      return GetRequestBodyInternal(view->Data(), view->Length(), aResult,
+                                    aContentLength, aContentType, aCharset);
     }
-    case nsXMLHttpRequest::RequestBody::Blob:
+    case XMLHttpRequestMainThread::RequestBody::eBlob:
     {
       nsresult rv;
       nsCOMPtr<nsIDOMBlob> blob = value.mBlob;
       nsCOMPtr<nsIXHRSendable> sendable = do_QueryInterface(blob, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
-      return ::GetRequestBody(sendable, aResult, aContentLength, aContentType, aCharset);
+      return GetRequestBodyInternal(sendable, aResult, aContentLength,
+                                    aContentType, aCharset);
     }
-    case nsXMLHttpRequest::RequestBody::Document:
+    case XMLHttpRequestMainThread::RequestBody::eDocument:
     {
       nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(value.mDocument);
-      return ::GetRequestBody(document, aResult, aContentLength, aContentType, aCharset);
+      return GetRequestBodyInternal(document, aResult, aContentLength,
+                                    aContentType, aCharset);
     }
-    case nsXMLHttpRequest::RequestBody::DOMString:
+    case XMLHttpRequestMainThread::RequestBody::eDOMString:
     {
-      return ::GetRequestBody(*value.mString, aResult, aContentLength,
-                              aContentType, aCharset);
+      return GetRequestBodyInternal(*value.mString, aResult, aContentLength,
+                                    aContentType, aCharset);
     }
-    case nsXMLHttpRequest::RequestBody::FormData:
+    case XMLHttpRequestMainThread::RequestBody::eFormData:
     {
       MOZ_ASSERT(value.mFormData);
-      return ::GetRequestBody(value.mFormData, aResult, aContentLength,
-                              aContentType, aCharset);
+      return GetRequestBodyInternal(value.mFormData, aResult, aContentLength,
+                                    aContentType, aCharset);
     }
-    case nsXMLHttpRequest::RequestBody::InputStream:
+    case XMLHttpRequestMainThread::RequestBody::eInputStream:
     {
-      return ::GetRequestBody(value.mStream, aResult, aContentLength,
-                              aContentType, aCharset);
+      return GetRequestBodyInternal(value.mStream, aResult, aContentLength,
+                                    aContentType, aCharset);
     }
     default:
     {
       return NS_ERROR_FAILURE;
     }
   }
 
   NS_NOTREACHED("Default cases exist for a reason");
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::Send(nsIVariant *aBody)
+XMLHttpRequestMainThread::Send(nsIVariant *aBody)
 {
   return Send(aBody, Nullable<RequestBody>());
 }
 
 nsresult
-nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
+XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
 {
   NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
 
   PopulateNetworkInterfaceId();
 
   nsresult rv = CheckInnerWindowCorrectness();
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2890,18 +2911,18 @@ nsXMLHttpRequest::Send(nsIVariant* aVari
     return NS_ERROR_FAILURE;
   }
 
   return rv;
 }
 
 // http://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#dom-xmlhttprequest-setrequestheader
 NS_IMETHODIMP
-nsXMLHttpRequest::SetRequestHeader(const nsACString& header,
-                                   const nsACString& value)
+XMLHttpRequestMainThread::SetRequestHeader(const nsACString& header,
+                                           const nsACString& value)
 {
   // Step 1 and 2
   if (!(mState & XML_HTTP_REQUEST_OPENED)) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
   NS_ASSERTION(mChannel, "mChannel must be valid if we're OPENED.");
 
   // Step 3
@@ -2986,32 +3007,32 @@ nsXMLHttpRequest::SetRequestHeader(const
       nsCString(header), nsCString(value)
     };
     mModifiedRequestHeaders.AppendElement(reqHeader);
   }
   return rv;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetTimeout(uint32_t *aTimeout)
+XMLHttpRequestMainThread::GetTimeout(uint32_t *aTimeout)
 {
   *aTimeout = Timeout();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::SetTimeout(uint32_t aTimeout)
+XMLHttpRequestMainThread::SetTimeout(uint32_t aTimeout)
 {
   ErrorResult rv;
   SetTimeout(aTimeout, rv);
   return rv.StealNSResult();
 }
 
 void
-nsXMLHttpRequest::SetTimeout(uint32_t aTimeout, ErrorResult& aRv)
+XMLHttpRequestMainThread::SetTimeout(uint32_t aTimeout, ErrorResult& aRv)
 {
   if (!(mState & (XML_HTTP_REQUEST_ASYNC | XML_HTTP_REQUEST_UNSENT)) &&
       HasOrHasHadOwner()) {
     /* Timeout is not supported for synchronous requests with an owning window,
        per XHR2 spec. */
     LogMessage("TimeoutSyncXHRWarning", GetOwner());
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
@@ -3019,17 +3040,17 @@ nsXMLHttpRequest::SetTimeout(uint32_t aT
 
   mTimeoutMilliseconds = aTimeout;
   if (mRequestSentTime) {
     StartTimeoutTimer();
   }
 }
 
 void
-nsXMLHttpRequest::StartTimeoutTimer()
+XMLHttpRequestMainThread::StartTimeoutTimer()
 {
   MOZ_ASSERT(mRequestSentTime,
              "StartTimeoutTimer mustn't be called before the request was sent!");
   if (mState & XML_HTTP_REQUEST_DONE) {
     // do nothing!
     return;
   }
 
@@ -3049,24 +3070,24 @@ nsXMLHttpRequest::StartTimeoutTimer()
   mTimeoutTimer->InitWithCallback(
     this,
     mTimeoutMilliseconds > elapsed ? mTimeoutMilliseconds - elapsed : 0,
     nsITimer::TYPE_ONE_SHOT
   );
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetReadyState(uint16_t *aState)
+XMLHttpRequestMainThread::GetReadyState(uint16_t *aState)
 {
   *aState = ReadyState();
   return NS_OK;
 }
 
 uint16_t
-nsXMLHttpRequest::ReadyState()
+XMLHttpRequestMainThread::ReadyState() const
 {
   // Translate some of our internal states for external consumers
   if (mState & XML_HTTP_REQUEST_UNSENT) {
     return UNSENT;
   }
   if (mState & (XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT)) {
     return OPENED;
   }
@@ -3075,100 +3096,100 @@ nsXMLHttpRequest::ReadyState()
   }
   if (mState & XML_HTTP_REQUEST_LOADING) {
     return LOADING;
   }
   MOZ_ASSERT(mState & XML_HTTP_REQUEST_DONE);
   return DONE;
 }
 
-void nsXMLHttpRequest::OverrideMimeType(const nsAString& aMimeType, ErrorResult& aRv)
+void XMLHttpRequestMainThread::OverrideMimeType(const nsAString& aMimeType, ErrorResult& aRv)
 {
   if ((mState & XML_HTTP_REQUEST_LOADING) || (mState & XML_HTTP_REQUEST_DONE)) {
     ResetResponse();
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   mOverrideMimeType = aMimeType;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::SlowOverrideMimeType(const nsAString& aMimeType)
+XMLHttpRequestMainThread::SlowOverrideMimeType(const nsAString& aMimeType)
 {
   ErrorResult aRv;
   OverrideMimeType(aMimeType, aRv);
   return aRv.StealNSResult();
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetMozBackgroundRequest(bool *_retval)
+XMLHttpRequestMainThread::GetMozBackgroundRequest(bool *_retval)
 {
   *_retval = MozBackgroundRequest();
   return NS_OK;
 }
 
 bool
-nsXMLHttpRequest::MozBackgroundRequest()
+XMLHttpRequestMainThread::MozBackgroundRequest() const
 {
   return !!(mState & XML_HTTP_REQUEST_BACKGROUND);
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::SetMozBackgroundRequest(bool aMozBackgroundRequest)
-{
-  nsresult rv = NS_OK;
-  SetMozBackgroundRequest(aMozBackgroundRequest, rv);
-  return rv;
-}
-
-void
-nsXMLHttpRequest::SetMozBackgroundRequest(bool aMozBackgroundRequest, nsresult& aRv)
+XMLHttpRequestMainThread::SetMozBackgroundRequest(bool aMozBackgroundRequest)
 {
   if (!IsSystemXHR()) {
-    aRv = NS_ERROR_DOM_SECURITY_ERR;
-    return;
+    return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   if (!(mState & XML_HTTP_REQUEST_UNSENT)) {
     // Can't change this while we're in the middle of something.
-    aRv = NS_ERROR_IN_PROGRESS;
-    return;
+     return NS_ERROR_IN_PROGRESS;
   }
 
   if (aMozBackgroundRequest) {
     mState |= XML_HTTP_REQUEST_BACKGROUND;
   } else {
     mState &= ~XML_HTTP_REQUEST_BACKGROUND;
   }
+
+  return NS_OK;
+}
+
+void
+XMLHttpRequestMainThread::SetMozBackgroundRequest(bool aMozBackgroundRequest,
+                                                  ErrorResult& aRv)
+{
+  // No errors for this webIDL method on main-thread.
+  SetMozBackgroundRequest(aMozBackgroundRequest);
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetWithCredentials(bool *_retval)
+XMLHttpRequestMainThread::GetWithCredentials(bool *_retval)
 {
   *_retval = WithCredentials();
   return NS_OK;
 }
 
 bool
-nsXMLHttpRequest::WithCredentials()
+XMLHttpRequestMainThread::WithCredentials() const
 {
   return !!(mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS);
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::SetWithCredentials(bool aWithCredentials)
+XMLHttpRequestMainThread::SetWithCredentials(bool aWithCredentials)
 {
   ErrorResult rv;
   SetWithCredentials(aWithCredentials, rv);
   return rv.StealNSResult();
 }
 
 void
-nsXMLHttpRequest::SetWithCredentials(bool aWithCredentials, ErrorResult& aRv)
+XMLHttpRequestMainThread::SetWithCredentials(bool aWithCredentials, ErrorResult& aRv)
 {
   // Return error if we're already processing a request.  Note that we can't use
   // ReadyState() here, because it can't differentiate between "opened" and
   // "sent", so we use mState directly.
   if ((!(mState & XML_HTTP_REQUEST_UNSENT) &&
        !(mState & XML_HTTP_REQUEST_OPENED)) ||
       mIsAnon) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
@@ -3178,17 +3199,17 @@ nsXMLHttpRequest::SetWithCredentials(boo
   if (aWithCredentials) {
     mState |= XML_HTTP_REQUEST_AC_WITH_CREDENTIALS;
   } else {
     mState &= ~XML_HTTP_REQUEST_AC_WITH_CREDENTIALS;
   }
 }
 
 nsresult
-nsXMLHttpRequest::ChangeState(uint32_t aState, bool aBroadcast)
+XMLHttpRequestMainThread::ChangeState(uint32_t aState, bool aBroadcast)
 {
   // If we are setting one of the mutually exclusive states,
   // unset those state bits first.
   if (aState & XML_HTTP_REQUEST_LOADSTATES) {
     mState &= ~XML_HTTP_REQUEST_LOADSTATES;
   }
   mState |= aState;
   nsresult rv = NS_OK;
@@ -3214,20 +3235,20 @@ nsXMLHttpRequest::ChangeState(uint32_t a
 
   return rv;
 }
 
 /////////////////////////////////////////////////////
 // nsIChannelEventSink methods:
 //
 NS_IMETHODIMP
-nsXMLHttpRequest::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
-                                         nsIChannel *aNewChannel,
-                                         uint32_t    aFlags,
-                                         nsIAsyncVerifyRedirectCallback *callback)
+XMLHttpRequestMainThread::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
+                                                 nsIChannel *aNewChannel,
+                                                 uint32_t    aFlags,
+                                                 nsIAsyncVerifyRedirectCallback *callback)
 {
   NS_PRECONDITION(aNewChannel, "Redirect without a channel?");
 
   // Prepare to receive callback
   mRedirectCallback = callback;
   mNewRedirectChannel = aNewChannel;
 
   if (mChannelEventSink) {
@@ -3243,17 +3264,17 @@ nsXMLHttpRequest::AsyncOnChannelRedirect
     }
     return rv;
   }
   OnRedirectVerifyCallback(NS_OK);
   return NS_OK;
 }
 
 nsresult
-nsXMLHttpRequest::OnRedirectVerifyCallback(nsresult result)
+XMLHttpRequestMainThread::OnRedirectVerifyCallback(nsresult result)
 {
   NS_ASSERTION(mRedirectCallback, "mRedirectCallback not set in callback");
   NS_ASSERTION(mNewRedirectChannel, "mNewRedirectChannel not set in callback");
 
   if (NS_SUCCEEDED(result)) {
     mChannel = mNewRedirectChannel;
 
     nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel));
@@ -3281,17 +3302,17 @@ nsXMLHttpRequest::OnRedirectVerifyCallba
   return result;
 }
 
 /////////////////////////////////////////////////////
 // nsIProgressEventSink methods:
 //
 
 void
-nsXMLHttpRequest::MaybeDispatchProgressEvents(bool aFinalProgress)
+XMLHttpRequestMainThread::MaybeDispatchProgressEvents(bool aFinalProgress)
 {
   if (aFinalProgress && mProgressTimerIsActive) {
     mProgressTimerIsActive = false;
     mProgressNotifier->Cancel();
   }
 
   if (mProgressTimerIsActive ||
       !mProgressSinceLastProgressEvent ||
@@ -3329,17 +3350,17 @@ nsXMLHttpRequest::MaybeDispatchProgressE
       mArrayBufferBuilder.reset();
     }
   }
 
   mProgressSinceLastProgressEvent = false;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::OnProgress(nsIRequest *aRequest, nsISupports *aContext, int64_t aProgress, int64_t aProgressMax)
+XMLHttpRequestMainThread::OnProgress(nsIRequest *aRequest, nsISupports *aContext, int64_t aProgress, int64_t aProgressMax)
 {
   // We're uploading if our state is XML_HTTP_REQUEST_OPENED or
   // XML_HTTP_REQUEST_SENT
   bool upload = !!((XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT) & mState);
   // When uploading, OnProgress reports also headers in aProgress and aProgressMax.
   // So, try to remove the headers, if possible.
   bool lengthComputable = (aProgressMax != -1);
   if (upload) {
@@ -3365,37 +3386,37 @@ nsXMLHttpRequest::OnProgress(nsIRequest 
     mProgressEventSink->OnProgress(aRequest, aContext, aProgress,
                                    aProgressMax);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::OnStatus(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatus, const char16_t *aStatusArg)
+XMLHttpRequestMainThread::OnStatus(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatus, const char16_t *aStatusArg)
 {
   if (mProgressEventSink) {
     mProgressEventSink->OnStatus(aRequest, aContext, aStatus, aStatusArg);
   }
 
   return NS_OK;
 }
 
 bool
-nsXMLHttpRequest::AllowUploadProgress()
+XMLHttpRequestMainThread::AllowUploadProgress()
 {
   return !IsCrossSiteCORSRequest() ||
     (mState & XML_HTTP_REQUEST_HAD_UPLOAD_LISTENERS_ON_SEND);
 }
 
 /////////////////////////////////////////////////////
 // nsIInterfaceRequestor methods:
 //
 NS_IMETHODIMP
-nsXMLHttpRequest::GetInterface(const nsIID & aIID, void **aResult)
+XMLHttpRequestMainThread::GetInterface(const nsIID & aIID, void **aResult)
 {
   nsresult rv;
 
   // Make sure to return ourselves for the channel event sink interface and
   // progress event sink interface, no matter what.  We can forward these to
   // mNotificationCallbacks if it wants to get notifications for them.  But we
   // need to see these notifications for proper functioning.
   if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
@@ -3461,81 +3482,82 @@ nsXMLHttpRequest::GetInterface(const nsI
     *aResult = static_cast<nsITimerCallback*>(EnsureXPCOMifier().take());
     return NS_OK;
   }
 
   return QueryInterface(aIID, aResult);
 }
 
 void
-nsXMLHttpRequest::GetInterface(JSContext* aCx, nsIJSID* aIID,
-                               JS::MutableHandle<JS::Value> aRetval,
-                               ErrorResult& aRv)
+XMLHttpRequestMainThread::GetInterface(JSContext* aCx, nsIJSID* aIID,
+                                       JS::MutableHandle<JS::Value> aRetval,
+                                       ErrorResult& aRv)
 {
   dom::GetInterface(aCx, this, aIID, aRetval, aRv);
 }
 
 XMLHttpRequestUpload*
-nsXMLHttpRequest::Upload()
+XMLHttpRequestMainThread::GetUpload(ErrorResult& aRv)
 {
   if (!mUpload) {
     mUpload = new XMLHttpRequestUpload(this);
   }
   return mUpload;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetUpload(nsIXMLHttpRequestUpload** aUpload)
+XMLHttpRequestMainThread::GetUpload(nsIXMLHttpRequestUpload** aUpload)
 {
-  RefPtr<XMLHttpRequestUpload> upload = Upload();
+  ErrorResult rv;
+  RefPtr<XMLHttpRequestUpload> upload = GetUpload(rv);
   upload.forget(aUpload);
-  return NS_OK;
+  return rv.StealNSResult();
 }
 
 bool
-nsXMLHttpRequest::MozAnon()
+XMLHttpRequestMainThread::MozAnon() const
 {
   return mIsAnon;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetMozAnon(bool* aAnon)
+XMLHttpRequestMainThread::GetMozAnon(bool* aAnon)
 {
   *aAnon = MozAnon();
   return NS_OK;
 }
 
 bool
-nsXMLHttpRequest::MozSystem()
+XMLHttpRequestMainThread::MozSystem() const
 {
   return IsSystemXHR();
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::GetMozSystem(bool* aSystem)
+XMLHttpRequestMainThread::GetMozSystem(bool* aSystem)
 {
   *aSystem = MozSystem();
   return NS_OK;
 }
 
 void
-nsXMLHttpRequest::HandleTimeoutCallback()
+XMLHttpRequestMainThread::HandleTimeoutCallback()
 {
   if (mState & XML_HTTP_REQUEST_DONE) {
-    NS_NOTREACHED("nsXMLHttpRequest::HandleTimeoutCallback with completed request");
+    NS_NOTREACHED("XMLHttpRequestMainThread::HandleTimeoutCallback with completed request");
     // do nothing!
     return;
   }
 
   CloseRequestWithError(NS_LITERAL_STRING(TIMEOUT_STR),
                         XML_HTTP_REQUEST_TIMED_OUT);
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::Notify(nsITimer* aTimer)
+XMLHttpRequestMainThread::Notify(nsITimer* aTimer)
 {
   if (mProgressNotifier == aTimer) {
     HandleProgressTimerCallback();
     return NS_OK;
   }
 
   if (mTimeoutTimer == aTimer) {
     HandleTimeoutCallback();
@@ -3543,48 +3565,48 @@ nsXMLHttpRequest::Notify(nsITimer* aTime
   }
 
   // Just in case some JS user wants to QI to nsITimerCallback and play with us...
   NS_WARNING("Unexpected timer!");
   return NS_ERROR_INVALID_POINTER;
 }
 
 void
-nsXMLHttpRequest::HandleProgressTimerCallback()
+XMLHttpRequestMainThread::HandleProgressTimerCallback()
 {
   mProgressTimerIsActive = false;
   MaybeDispatchProgressEvents(false);
 }
 
 void
-nsXMLHttpRequest::StartProgressEventTimer()
+XMLHttpRequestMainThread::StartProgressEventTimer()
 {
   if (!mProgressNotifier) {
     mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
   }
   if (mProgressNotifier) {
     mProgressTimerIsActive = true;
     mProgressNotifier->Cancel();
     mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,
                                         nsITimer::TYPE_ONE_SHOT);
   }
 }
 
 already_AddRefed<nsXMLHttpRequestXPCOMifier>
-nsXMLHttpRequest::EnsureXPCOMifier()
+XMLHttpRequestMainThread::EnsureXPCOMifier()
 {
   if (!mXPCOMifier) {
     mXPCOMifier = new nsXMLHttpRequestXPCOMifier(this);
   }
   RefPtr<nsXMLHttpRequestXPCOMifier> newRef(mXPCOMifier);
   return newRef.forget();
 }
 
 bool
-nsXMLHttpRequest::ShouldBlockAuthPrompt()
+XMLHttpRequestMainThread::ShouldBlockAuthPrompt()
 {
   // Verify that it's ok to prompt for credentials here, per spec
   // http://xhr.spec.whatwg.org/#the-send%28%29-method
 
   for (uint32_t i = 0, len = mModifiedRequestHeaders.Length(); i < len; ++i) {
     if (mModifiedRequestHeaders[i].header.
           LowerCaseEqualsLiteral("authorization")) {
       return true;
@@ -3612,19 +3634,19 @@ nsXMLHttpRequest::ShouldBlockAuthPrompt(
 
   if (!username.IsEmpty() || !password.IsEmpty()) {
     return true;
   }
 
   return false;
 }
 
-NS_IMPL_ISUPPORTS(nsXMLHttpRequest::nsHeaderVisitor, nsIHttpHeaderVisitor)
-
-NS_IMETHODIMP nsXMLHttpRequest::
+NS_IMPL_ISUPPORTS(XMLHttpRequestMainThread::nsHeaderVisitor, nsIHttpHeaderVisitor)
+
+NS_IMETHODIMP XMLHttpRequestMainThread::
 nsHeaderVisitor::VisitHeader(const nsACString &header, const nsACString &value)
 {
   if (mXHR.IsSafeHeader(header, mHttpChannel)) {
     mHeaders.Append(header);
     mHeaders.AppendLiteral(": ");
     mHeaders.Append(value);
     mHeaders.AppendLiteral("\r\n");
   }
@@ -3671,18 +3693,16 @@ nsXMLHttpRequestXPCOMifier::GetInterface
     if (NS_SUCCEEDED(rv)) {
       return rv;
     }
   }
 
   return mXHR->GetInterface(aIID, aResult);
 }
 
-namespace mozilla {
-
 ArrayBufferBuilder::ArrayBufferBuilder()
   : mDataPtr(nullptr),
     mCapacity(0),
     mLength(0),
     mMapPtr(nullptr)
 {
 }
 
@@ -3862,9 +3882,10 @@ ArrayBufferBuilder::areOverlappingRegion
   const uint8_t* end2 = aStart2 + aLength2;
 
   const uint8_t* max_start = aStart1 > aStart2 ? aStart1 : aStart2;
   const uint8_t* min_end   = end1 < end2 ? end1 : end2;
 
   return max_start < min_end;
 }
 
-} // namespace mozilla
+} // dom namespace
+} // mozilla namespaceo
rename from dom/xhr/nsXMLHttpRequest.h
rename to dom/xhr/XMLHttpRequestMainThread.h
--- a/dom/xhr/nsXMLHttpRequest.h
+++ b/dom/xhr/XMLHttpRequestMainThread.h
@@ -1,21 +1,20 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef nsXMLHttpRequest_h__
-#define nsXMLHttpRequest_h__
+#ifndef mozilla_dom_XMLHttpRequestMainThread_h
+#define mozilla_dom_XMLHttpRequestMainThread_h
 
 #include "nsAutoPtr.h"
 #include "nsIXMLHttpRequest.h"
 #include "nsISupportsUtils.h"
-#include "nsString.h"
 #include "nsIURI.h"
 #include "nsIHttpChannel.h"
 #include "nsIDocument.h"
 #include "nsIStreamListener.h"
 #include "nsWeakReference.h"
 #include "nsIChannelEventSink.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIInterfaceRequestor.h"
@@ -30,38 +29,38 @@
 #include "nsIXPConnect.h"
 #include "nsIInputStream.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/NotNull.h"
 #include "mozilla/dom/TypedArray.h"
+#include "mozilla/dom/XMLHttpRequest.h"
 #include "mozilla/dom/XMLHttpRequestBinding.h"
 #include "mozilla/dom/XMLHttpRequestEventTarget.h"
 
 #ifdef Status
 /* Xlib headers insist on this for some reason... Nuke it because
    it'll override our member name */
 #undef Status
 #endif
 
 class nsIJARChannel;
 class nsILoadGroup;
 class nsIUnicodeDecoder;
 class nsIJSID;
 
 namespace mozilla {
+namespace dom {
 
-namespace dom {
 class Blob;
 class BlobSet;
 class FormData;
 class XMLHttpRequestUpload;
-} // namespace dom
 
 // A helper for building up an ArrayBuffer object's data
 // before creating the ArrayBuffer itself.  Will do doubling
 // based reallocation, up to an optional maximum growth given.
 //
 // When all the data has been appended, call getArrayBuffer,
 // passing in the JSContext* for which the ArrayBuffer object
 // is to be created.  This also implicitly resets the builder,
@@ -104,82 +103,36 @@ public:
   // in JS engine.
   nsresult mapToFileInPackage(const nsCString& aFile, nsIFile* aJarFile);
 
 protected:
   static bool areOverlappingRegions(const uint8_t* aStart1, uint32_t aLength1,
                                     const uint8_t* aStart2, uint32_t aLength2);
 };
 
-} // namespace mozilla
-
 class nsXMLHttpRequestXPCOMifier;
 
 // Make sure that any non-DOM interfaces added here are also added to
 // nsXMLHttpRequestXPCOMifier.
-class nsXMLHttpRequest final : public mozilla::dom::XMLHttpRequestEventTarget,
-                               public nsIXMLHttpRequest,
-                               public nsIJSXMLHttpRequest,
-                               public nsIStreamListener,
-                               public nsIChannelEventSink,
-                               public nsIProgressEventSink,
-                               public nsIInterfaceRequestor,
-                               public nsSupportsWeakReference,
-                               public nsITimerCallback,
-                               public nsISizeOfEventTarget
+class XMLHttpRequestMainThread final : public XMLHttpRequest,
+                                       public nsIXMLHttpRequest,
+                                       public nsIJSXMLHttpRequest,
+                                       public nsIStreamListener,
+                                       public nsIChannelEventSink,
+                                       public nsIProgressEventSink,
+                                       public nsIInterfaceRequestor,
+                                       public nsSupportsWeakReference,
+                                       public nsITimerCallback,
+                                       public nsISizeOfEventTarget
 {
   friend class nsXHRParseEndListener;
   friend class nsXMLHttpRequestXPCOMifier;
 
 public:
-  nsXMLHttpRequest();
-
-  virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override
-  {
-    return mozilla::dom::XMLHttpRequestBinding::Wrap(cx, this, aGivenProto);
-  }
-  nsISupports* GetParentObject()
-  {
-    return GetOwner();
-  }
-
-  // The WebIDL constructors.
-  static already_AddRefed<nsXMLHttpRequest>
-  Constructor(const mozilla::dom::GlobalObject& aGlobal,
-              const mozilla::dom::MozXMLHttpRequestParameters& aParams,
-              mozilla::ErrorResult& aRv)
-  {
-    nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
-    nsCOMPtr<nsIScriptObjectPrincipal> principal =
-      do_QueryInterface(aGlobal.GetAsSupports());
-    if (!global || ! principal) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return nullptr;
-    }
-
-    RefPtr<nsXMLHttpRequest> req = new nsXMLHttpRequest();
-    req->Construct(principal->GetPrincipal(), global);
-    req->InitParameters(aParams.mMozAnon, aParams.mMozSystem);
-    return req.forget();
-  }
-
-  static already_AddRefed<nsXMLHttpRequest>
-  Constructor(const mozilla::dom::GlobalObject& aGlobal,
-              const nsAString& ignored,
-              mozilla::ErrorResult& aRv)
-  {
-    // Pretend like someone passed null, so we can pick up the default values
-    mozilla::dom::MozXMLHttpRequestParameters params;
-    if (!params.Init(aGlobal.Context(), JS::NullHandleValue)) {
-      aRv.Throw(NS_ERROR_UNEXPECTED);
-      return nullptr;
-    }
-
-    return Constructor(aGlobal, params, aRv);
-  }
+  XMLHttpRequestMainThread();
 
   void Construct(nsIPrincipal* aPrincipal,
                  nsIGlobalObject* aGlobalObject,
                  nsIURI* aBaseURI = nullptr,
                  nsILoadGroup* aLoadGroup = nullptr)
   {
     MOZ_ASSERT(aPrincipal);
     MOZ_ASSERT_IF(nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(
@@ -198,17 +151,17 @@ public:
     mIsSystem = aSystem;
   }
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIXMLHttpRequest
   NS_DECL_NSIXMLHTTPREQUEST
 
-  NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(mozilla::dom::XMLHttpRequestEventTarget::)
+  NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(XMLHttpRequestEventTarget::)
 
   // nsIStreamListener
   NS_DECL_NSISTREAMLISTENER
 
   // nsIRequestObserver
   NS_DECL_NSIREQUESTOBSERVER
 
   // nsIChannelEventSink
@@ -220,127 +173,138 @@ public:
   // nsIInterfaceRequestor
   NS_DECL_NSIINTERFACEREQUESTOR
 
   // nsITimerCallback
   NS_DECL_NSITIMERCALLBACK
 
   // nsISizeOfEventTarget
   virtual size_t
-    SizeOfEventTargetIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
+    SizeOfEventTargetIncludingThis(MallocSizeOf aMallocSizeOf) const override;
 
-  NS_REALLY_FORWARD_NSIDOMEVENTTARGET(mozilla::dom::XMLHttpRequestEventTarget)
+  NS_REALLY_FORWARD_NSIDOMEVENTTARGET(XMLHttpRequestEventTarget)
 
 #ifdef DEBUG
   void StaticAssertions();
 #endif
 
-  // event handler
-  IMPL_EVENT_HANDLER(readystatechange)
-
   // states
-  uint16_t ReadyState();
+  virtual uint16_t ReadyState() const override;
 
   // request
-  void Open(const nsACString& aMethod, const nsAString& aUrl,
-            mozilla::ErrorResult& aRv)
+  virtual void
+  Open(const nsACString& aMethod, const nsAString& aUrl,
+       ErrorResult& aRv) override
   {
     Open(aMethod, aUrl, true,
-         mozilla::dom::Optional<nsAString>(),
-         mozilla::dom::Optional<nsAString>(),
+         Optional<nsAString>(),
+         Optional<nsAString>(),
          aRv);
   }
-  void Open(const nsACString& aMethod, const nsAString& aUrl, bool aAsync,
-            const mozilla::dom::Optional<nsAString>& aUser,
-            const mozilla::dom::Optional<nsAString>& aPassword,
-            mozilla::ErrorResult& aRv)
+
+  virtual void
+  Open(const nsACString& aMethod, const nsAString& aUrl, bool aAsync,
+       const Optional<nsAString>& aUser,
+       const Optional<nsAString>& aPassword,
+       ErrorResult& aRv) override
   {
     aRv = Open(aMethod, NS_ConvertUTF16toUTF8(aUrl),
                aAsync, aUser, aPassword);
   }
-  void SetRequestHeader(const nsACString& aHeader, const nsACString& aValue,
-                        mozilla::ErrorResult& aRv)
+
+  virtual void
+  SetRequestHeader(const nsACString& aHeader, const nsACString& aValue,
+                   ErrorResult& aRv) override
   {
     aRv = SetRequestHeader(aHeader, aValue);
   }
-  uint32_t Timeout()
+
+  virtual uint32_t
+  Timeout() const override
   {
     return mTimeoutMilliseconds;
   }
-  void SetTimeout(uint32_t aTimeout, mozilla::ErrorResult& aRv);
-  bool WithCredentials();
-  void SetWithCredentials(bool aWithCredentials, mozilla::ErrorResult& aRv);
-  mozilla::dom::XMLHttpRequestUpload* Upload();
+
+  virtual void
+  SetTimeout(uint32_t aTimeout, ErrorResult& aRv) override;
+
+  virtual bool WithCredentials() const override;
+
+  virtual void
+  SetWithCredentials(bool aWithCredentials, ErrorResult& aRv) override;
+
+  virtual XMLHttpRequestUpload*
+  GetUpload(ErrorResult& aRv) override;
 
 private:
-  virtual ~nsXMLHttpRequest();
+  virtual ~XMLHttpRequestMainThread();
 
   class RequestBody
   {
   public:
-    RequestBody() : mType(Uninitialized)
+    RequestBody() : mType(eUninitialized)
     {
     }
-    explicit RequestBody(const mozilla::dom::ArrayBuffer* aArrayBuffer) : mType(ArrayBuffer)
+    explicit RequestBody(const ArrayBuffer* aArrayBuffer) : mType(eArrayBuffer)
     {
       mValue.mArrayBuffer = aArrayBuffer;
     }
-    explicit RequestBody(const mozilla::dom::ArrayBufferView* aArrayBufferView) : mType(ArrayBufferView)
+    explicit RequestBody(const ArrayBufferView* aArrayBufferView) : mType(eArrayBufferView)
     {
       mValue.mArrayBufferView = aArrayBufferView;
     }
-    explicit RequestBody(mozilla::dom::Blob& aBlob) : mType(Blob)
+    explicit RequestBody(Blob& aBlob) : mType(eBlob)
     {
       mValue.mBlob = &aBlob;
     }
-    explicit RequestBody(nsIDocument* aDocument) : mType(Document)
+    explicit RequestBody(nsIDocument* aDocument) : mType(eDocument)
     {
       mValue.mDocument = aDocument;
     }
-    explicit RequestBody(const nsAString& aString) : mType(DOMString)
+    explicit RequestBody(const nsAString& aString) : mType(eDOMString)
     {
       mValue.mString = &aString;
     }
-    explicit RequestBody(mozilla::dom::FormData& aFormData) : mType(FormData)
+    explicit RequestBody(FormData& aFormData) : mType(eFormData)
     {
       mValue.mFormData = &aFormData;
     }
-    explicit RequestBody(nsIInputStream* aStream) : mType(InputStream)
+    explicit RequestBody(nsIInputStream* aStream) : mType(eInputStream)
     {
       mValue.mStream = aStream;
     }
 
     enum Type {
-      Uninitialized,
-      ArrayBuffer,
-      ArrayBufferView,
-      Blob,
-      Document,
-      DOMString,
-      FormData,
-      InputStream
+      eUninitialized,
+      eArrayBuffer,
+      eArrayBufferView,
+      eBlob,
+      eDocument,
+      eDOMString,
+      eFormData,
+      eInputStream
     };
     union Value {
-      const mozilla::dom::ArrayBuffer* mArrayBuffer;
-      const mozilla::dom::ArrayBufferView* mArrayBufferView;
-      mozilla::dom::Blob* mBlob;
+      const ArrayBuffer* mArrayBuffer;
+      const ArrayBufferView* mArrayBufferView;
+      Blob* mBlob;
       nsIDocument* mDocument;
       const nsAString* mString;
-      mozilla::dom::FormData* mFormData;
+      FormData* mFormData;
       nsIInputStream* mStream;
     };
 
     Type GetType() const
     {
-      MOZ_ASSERT(mType != Uninitialized);
+      MOZ_ASSERT(mType != eUninitialized);
       return mType;
     }
     Value GetValue() const
     {
-      MOZ_ASSERT(mType != Uninitialized);
+      MOZ_ASSERT(mType != eUninitialized);
       return mValue;
     }
 
   private:
     Type mType;
     Value mValue;
   };
 
@@ -365,144 +329,198 @@ private:
   bool IsDeniedCrossSiteCORSRequest();
 
   // Tell our channel what network interface ID we were told to use.
   // If it's an HTTP channel and we were told to use a non-default
   // interface ID.
   void PopulateNetworkInterfaceId();
 
 public:
-  void Send(JSContext* /*aCx*/, mozilla::ErrorResult& aRv)
+  virtual void
+  Send(JSContext* /*aCx*/, ErrorResult& aRv) override
   {
     aRv = Send(Nullable<RequestBody>());
   }
-  void Send(JSContext* /*aCx*/,
-            const mozilla::dom::ArrayBuffer& aArrayBuffer,
-            mozilla::ErrorResult& aRv)
+
+  virtual void
+  Send(JSContext* /*aCx*/, const ArrayBuffer& aArrayBuffer,
+       ErrorResult& aRv) override
   {
     aRv = Send(RequestBody(&aArrayBuffer));
   }
-  void Send(JSContext* /*aCx*/,
-            const mozilla::dom::ArrayBufferView& aArrayBufferView,
-            mozilla::ErrorResult& aRv)
+
+  virtual void
+  Send(JSContext* /*aCx*/, const ArrayBufferView& aArrayBufferView,
+       ErrorResult& aRv) override
   {
     aRv = Send(RequestBody(&aArrayBufferView));
   }
-  void Send(JSContext* /*aCx*/, mozilla::dom::Blob& aBlob,
-            mozilla::ErrorResult& aRv)
+
+  virtual void
+  Send(JSContext* /*aCx*/, Blob& aBlob, ErrorResult& aRv) override
   {
     aRv = Send(RequestBody(aBlob));
   }
-  void Send(JSContext* /*aCx*/, nsIDocument& aDoc, mozilla::ErrorResult& aRv)
+
+  virtual void
+  Send(JSContext* /*aCx*/, nsIDocument& aDoc, ErrorResult& aRv) override
   {
     aRv = Send(RequestBody(&aDoc));
   }
-  void Send(JSContext* aCx, const nsAString& aString, mozilla::ErrorResult& aRv)
+
+  virtual void
+  Send(JSContext* aCx, const nsAString& aString, ErrorResult& aRv) override
   {
     if (DOMStringIsNull(aString)) {
       Send(aCx, aRv);
     }
     else {
       aRv = Send(RequestBody(aString));
     }
   }
-  void Send(JSContext* /*aCx*/, mozilla::dom::FormData& aFormData,
-            mozilla::ErrorResult& aRv)
+
+  virtual void
+  Send(JSContext* /*aCx*/, FormData& aFormData, ErrorResult& aRv) override
   {
     aRv = Send(RequestBody(aFormData));
   }
-  void Send(JSContext* aCx, nsIInputStream* aStream, mozilla::ErrorResult& aRv)
+
+  virtual void
+  Send(JSContext* aCx, nsIInputStream* aStream, ErrorResult& aRv) override
   {
     NS_ASSERTION(aStream, "Null should go to string version");
     nsCOMPtr<nsIXPConnectWrappedJS> wjs = do_QueryInterface(aStream);
     if (wjs) {
       JSObject* data = wjs->GetJSObject();
       if (!data) {
         aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
         return;
       }
       JS::Rooted<JS::Value> dataAsValue(aCx, JS::ObjectValue(*data));
       nsAutoString dataAsString;
-      if (ConvertJSValueToString(aCx, dataAsValue, mozilla::dom::eNull,
-                                 mozilla::dom::eNull, dataAsString)) {
+      if (ConvertJSValueToString(aCx, dataAsValue, eNull,
+                                 eNull, dataAsString)) {
         Send(aCx, dataAsString, aRv);
       } else {
         aRv.Throw(NS_ERROR_FAILURE);
       }
       return;
     }
     aRv = Send(RequestBody(aStream));
   }
 
-  void Abort();
+  void
+  Abort() {
+    ErrorResult rv;
+    Abort(rv);
+    MOZ_ASSERT(!rv.Failed());
+  }
+
+  virtual void
+  Abort(ErrorResult& aRv) override;
 
   // response
-  void GetResponseURL(nsAString& aUrl);
-  uint32_t Status();
-  void GetStatusText(nsCString& aStatusText);
-  void GetResponseHeader(const nsACString& aHeader, nsACString& aResult,
-                         mozilla::ErrorResult& aRv);
-  void GetResponseHeader(const nsAString& aHeader, nsString& aResult,
-                         mozilla::ErrorResult& aRv)
+  virtual void
+  GetResponseURL(nsAString& aUrl) override;
+
+  virtual uint32_t
+  GetStatus(ErrorResult& aRv) override;
+
+  virtual void
+  GetStatusText(nsACString& aStatusText, ErrorResult& aRv) override;
+
+  virtual void
+  GetResponseHeader(const nsACString& aHeader, nsACString& aResult,
+                    ErrorResult& aRv) override;
+
+  void
+  GetResponseHeader(const nsAString& aHeader, nsAString& aResult,
+                    ErrorResult& aRv)
   {
-    nsCString result;
+    nsAutoCString result;
     GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader), result, aRv);
     if (result.IsVoid()) {
       aResult.SetIsVoid(true);
     }
     else {
       // The result value should be inflated:
       CopyASCIItoUTF16(result, aResult);
     }
   }
-  void GetAllResponseHeaders(nsCString& aResponseHeaders);
+
+  virtual void
+  GetAllResponseHeaders(nsACString& aResponseHeaders,
+                        ErrorResult& aRv) override;
+
   bool IsSafeHeader(const nsACString& aHeaderName,
-                    mozilla::NotNull<nsIHttpChannel*> aHttpChannel) const;
-  void OverrideMimeType(const nsAString& aMimeType, mozilla::ErrorResult& aRv);
-  mozilla::dom::XMLHttpRequestResponseType ResponseType()
+                    NotNull<nsIHttpChannel*> aHttpChannel) const;
+
+  virtual void
+  OverrideMimeType(const nsAString& aMimeType, ErrorResult& aRv) override;
+
+  virtual XMLHttpRequestResponseType
+  ResponseType() const override
   {
-    return mozilla::dom::XMLHttpRequestResponseType(mResponseType);
+    return XMLHttpRequestResponseType(mResponseType);
   }
-  void SetResponseType(mozilla::dom::XMLHttpRequestResponseType aType,
-                       mozilla::ErrorResult& aRv);
-  void GetResponse(JSContext* aCx, JS::MutableHandle<JS::Value> aResponse,
-                   mozilla::ErrorResult& aRv);
-  void GetResponseText(nsString& aResponseText, mozilla::ErrorResult& aRv);
-  nsIDocument* GetResponseXML(mozilla::ErrorResult& aRv);
+
+  virtual void
+  SetResponseType(XMLHttpRequestResponseType aType,
+                  ErrorResult& aRv) override;
+
+  virtual void
+  GetResponse(JSContext* aCx, JS::MutableHandle<JS::Value> aResponse,
+              ErrorResult& aRv) override;
+
+  virtual void
+  GetResponseText(nsAString& aResponseText, ErrorResult& aRv) override;
+
+  virtual nsIDocument*
+  GetResponseXML(ErrorResult& aRv) override;
 
-  bool MozBackgroundRequest();
-  void SetMozBackgroundRequest(bool aMozBackgroundRequest, nsresult& aRv);
+  virtual bool
+  MozBackgroundRequest() const override;
+
+  virtual void
+  SetMozBackgroundRequest(bool aMozBackgroundRequest, ErrorResult& aRv) override;
 
-  bool MozAnon();
-  bool MozSystem();
+  virtual bool
+  MozAnon() const override;
 
-  nsIChannel* GetChannel()
+  virtual bool
+  MozSystem() const override;
+
+  virtual nsIChannel*
+  GetChannel() const override
   {
     return mChannel;
   }
 
-  void GetNetworkInterfaceId(nsACString& aId) const
+  virtual void
+  GetNetworkInterfaceId(nsACString& aId) const override
   {
     aId = mNetworkInterfaceId;
   }
 
-  void SetNetworkInterfaceId(const nsACString& aId)
+  virtual void
+  SetNetworkInterfaceId(const nsACString& aId) override
   {
     mNetworkInterfaceId = aId;
   }
 
   // We need a GetInterface callable from JS for chrome JS
-  void GetInterface(JSContext* aCx, nsIJSID* aIID,
-                    JS::MutableHandle<JS::Value> aRetval,
-                    mozilla::ErrorResult& aRv);
+  virtual void
+  GetInterface(JSContext* aCx, nsIJSID* aIID,
+               JS::MutableHandle<JS::Value> aRetval,
+               ErrorResult& aRv) override;
 
   // This creates a trusted readystatechange event, which is not cancelable and
   // doesn't bubble.
   nsresult CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent);
-  void DispatchProgressEvent(mozilla::DOMEventTargetHelper* aTarget,
+  void DispatchProgressEvent(DOMEventTargetHelper* aTarget,
                              const nsAString& aType,
                              bool aLengthComputable,
                              int64_t aLoaded, int64_t aTotal);
 
   // Dispatch the "progress" event on the XHR or XHR.upload object if we've
   // received data since the last "progress" event. Also dispatches
   // "uploadprogress" as needed.
   void MaybeDispatchProgressEvents(bool aFinalProgress);
@@ -512,18 +530,18 @@ public:
 
   nsresult init(nsIPrincipal* principal,
                 nsIScriptContext* scriptContext,
                 nsPIDOMWindowInner* globalObject,
                 nsIURI* baseURI);
 
   void SetRequestObserver(nsIRequestObserver* aObserver);
 
-  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(nsXMLHttpRequest,
-                                                                   mozilla::dom::XMLHttpRequestEventTarget)
+  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(XMLHttpRequestMainThread,
+                                                                   XMLHttpRequest)
   bool AllowUploadProgress();
   void RootJSResultObjects();
 
   virtual void DisconnectFromOwner() override;
 
   static void SetDontWarnAboutSyncXHR(bool aVal)
   {
     sDontWarnAboutSyncXHR = aVal;
@@ -537,17 +555,17 @@ protected:
   nsresult AppendToResponseText(const char * aBuffer, uint32_t aBufferLen);
   static NS_METHOD StreamReaderFunc(nsIInputStream* in,
                 void* closure,
                 const char* fromRawSegment,
                 uint32_t toOffset,
                 uint32_t count,
                 uint32_t *writeCount);
   nsresult CreateResponseParsedJSON(JSContext* aCx);
-  void CreatePartialBlob(mozilla::ErrorResult& aRv);
+  void CreatePartialBlob(ErrorResult& aRv);
   bool CreateDOMBlob(nsIRequest *request);
   // Change the state of the object with this. The broadcast argument
   // determines if the onreadystatechange listener should be called.
   nsresult ChangeState(uint32_t aState, bool aBroadcast = true);
   already_AddRefed<nsILoadGroup> GetLoadGroup() const;
   nsIURI *GetBaseURI();
 
   already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel();
@@ -557,18 +575,18 @@ protected:
 
   void ChangeStateToDone();
 
   void StartProgressEventTimer();
 
   nsresult OnRedirectVerifyCallback(nsresult result);
 
   nsresult Open(const nsACString& method, const nsACString& url, bool async,
-                const mozilla::dom::Optional<nsAString>& user,
-                const mozilla::dom::Optional<nsAString>& password);
+                const Optional<nsAString>& user,
+                const Optional<nsAString>& password);
 
   already_AddRefed<nsXMLHttpRequestXPCOMifier> EnsureXPCOMifier();
 
   nsCOMPtr<nsISupports> mContext;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIChannel> mChannel;
   nsCOMPtr<nsIDocument> mResponseXML;
   nsTArray<nsCString> mCORSUnsafeHeaders;
@@ -576,26 +594,26 @@ protected:
   nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
 
   // used to implement getAllResponseHeaders()
   class nsHeaderVisitor : public nsIHttpHeaderVisitor
   {
   public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIHTTPHEADERVISITOR
-    nsHeaderVisitor(const nsXMLHttpRequest& aXMLHttpRequest,
-                    mozilla::NotNull<nsIHttpChannel*> aHttpChannel)
+    nsHeaderVisitor(const XMLHttpRequestMainThread& aXMLHttpRequest,
+                    NotNull<nsIHttpChannel*> aHttpChannel)
       : mXHR(aXMLHttpRequest), mHttpChannel(aHttpChannel) {}
     const nsACString &Headers() { return mHeaders; }
   private:
     virtual ~nsHeaderVisitor() {}
 
     nsCString mHeaders;
-    const nsXMLHttpRequest& mXHR;
-    mozilla::NotNull<nsCOMPtr<nsIHttpChannel>> mHttpChannel;
+    const XMLHttpRequestMainThread& mXHR;
+    NotNull<nsCOMPtr<nsIHttpChannel>> mHttpChannel;
   };
 
   // The bytes of our response body. Only used for DEFAULT, ARRAYBUFFER and
   // BLOB responseTypes
   nsCString mResponseBody;
 
   // The text version of our response body. This is incrementally decoded into
   // as we receive network data. However for the DEFAULT responseType we
@@ -625,30 +643,30 @@ protected:
     XML_HTTP_RESPONSE_TYPE_DOCUMENT,
     XML_HTTP_RESPONSE_TYPE_JSON,
     XML_HTTP_RESPONSE_TYPE_TEXT,
     XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT,
     XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER,
     XML_HTTP_RESPONSE_TYPE_MOZ_BLOB
   };
 
-  void SetResponseType(nsXMLHttpRequest::ResponseTypeEnum aType,
-                       mozilla::ErrorResult& aRv);
+  void SetResponseType(XMLHttpRequestMainThread::ResponseTypeEnum aType,
+                       ErrorResult& aRv);
 
   ResponseTypeEnum mResponseType;
 
   // It is either a cached blob-response from the last call to GetResponse,
   // but is also explicitly set in OnStopRequest.
-  RefPtr<mozilla::dom::Blob> mResponseBlob;
+  RefPtr<Blob> mResponseBlob;
   // Non-null only when we are able to get a os-file representation of the
   // response, i.e. when loading from a file.
-  RefPtr<mozilla::dom::Blob> mDOMBlob;
+  RefPtr<Blob> mDOMBlob;
   // We stream data to mBlobSet when response type is "blob" or "moz-blob"
   // and mDOMBlob is null.
-  nsAutoPtr<mozilla::dom::BlobSet> mBlobSet;
+  nsAutoPtr<BlobSet> mBlobSet;
 
   nsString mOverrideMimeType;
 
   /**
    * The notification callbacks the channel had when Send() was
    * called.  We want to forward things here as needed.
    */
   nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
@@ -662,17 +680,17 @@ protected:
 
   nsIRequestObserver* mRequestObserver;
 
   nsCOMPtr<nsIURI> mBaseURI;
   nsCOMPtr<nsILoadGroup> mLoadGroup;
 
   uint32_t mState;
 
-  RefPtr<mozilla::dom::XMLHttpRequestUpload> mUpload;
+  RefPtr<XMLHttpRequestUpload> mUpload;
   int64_t mUploadTransferred;
   int64_t mUploadTotal;
   bool mUploadLengthComputable;
   bool mUploadComplete;
   bool mProgressSinceLastProgressEvent;
 
   // Timeout support
   PRTime mRequestSentTime;
@@ -711,29 +729,29 @@ protected:
   nsCString mNetworkInterfaceId;
 
   /**
    * Close the XMLHttpRequest's channels and dispatch appropriate progress
    * events.
    *
    * @param aType The progress event type.
    * @param aFlag A XML_HTTP_REQUEST_* state flag defined in
-   *              nsXMLHttpRequest.cpp.
+   *              XMLHttpRequestMainthread.cpp.
    */
   void CloseRequestWithError(const nsAString& aType, const uint32_t aFlag);
 
   bool mFirstStartRequestSeen;
   bool mInLoadProgressEvent;
 
   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
   nsCOMPtr<nsIChannel> mNewRedirectChannel;
 
   JS::Heap<JS::Value> mResultJSON;
 
-  mozilla::ArrayBufferBuilder mArrayBufferBuilder;
+  ArrayBufferBuilder mArrayBufferBuilder;
   JS::Heap<JSObject*> mResultArrayBuffer;
   bool mIsMappedArrayBuffer;
 
   void ResetResponse();
 
   bool ShouldBlockAuthPrompt();
 
   struct RequestHeader
@@ -749,24 +767,24 @@ protected:
   nsXMLHttpRequestXPCOMifier* mXPCOMifier;
 
   static bool sDontWarnAboutSyncXHR;
 };
 
 class MOZ_STACK_CLASS AutoDontWarnAboutSyncXHR
 {
 public:
-  AutoDontWarnAboutSyncXHR() : mOldVal(nsXMLHttpRequest::DontWarnAboutSyncXHR())
+  AutoDontWarnAboutSyncXHR() : mOldVal(XMLHttpRequestMainThread::DontWarnAboutSyncXHR())
   {
-    nsXMLHttpRequest::SetDontWarnAboutSyncXHR(true);
+    XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(true);
   }
 
   ~AutoDontWarnAboutSyncXHR()
   {
-    nsXMLHttpRequest::SetDontWarnAboutSyncXHR(mOldVal);
+    XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(mOldVal);
   }
 
 private:
   bool mOldVal;
 };
 
 // A shim class designed to expose the non-DOM interfaces of
 // XMLHttpRequest via XPCOM stuff.
@@ -776,17 +794,17 @@ class nsXMLHttpRequestXPCOMifier final :
                                          public nsIProgressEventSink,
                                          public nsIInterfaceRequestor,
                                          public nsITimerCallback
 {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier,
                                            nsIStreamListener)
 
-  explicit nsXMLHttpRequestXPCOMifier(nsXMLHttpRequest* aXHR) :
+  explicit nsXMLHttpRequestXPCOMifier(XMLHttpRequestMainThread* aXHR) :
     mXHR(aXHR)
   {
   }
 
 private:
   ~nsXMLHttpRequestXPCOMifier() {
     if (mXHR) {
       mXHR->mXPCOMifier = nullptr;
@@ -799,33 +817,36 @@ public:
   NS_FORWARD_NSICHANNELEVENTSINK(mXHR->)
   NS_FORWARD_NSIASYNCVERIFYREDIRECTCALLBACK(mXHR->)
   NS_FORWARD_NSIPROGRESSEVENTSINK(mXHR->)
   NS_FORWARD_NSITIMERCALLBACK(mXHR->)
 
   NS_DECL_NSIINTERFACEREQUESTOR
 
 private:
-  RefPtr<nsXMLHttpRequest> mXHR;
+  RefPtr<XMLHttpRequestMainThread> mXHR;
 };
 
 class nsXHRParseEndListener : public nsIDOMEventListener
 {
 public:
   NS_DECL_ISUPPORTS
   NS_IMETHOD HandleEvent(nsIDOMEvent *event) override
   {
     nsCOMPtr<nsIXMLHttpRequest> xhr = do_QueryReferent(mXHR);
     if (xhr) {
-      static_cast<nsXMLHttpRequest*>(xhr.get())->ChangeStateToDone();
+      static_cast<XMLHttpRequestMainThread*>(xhr.get())->ChangeStateToDone();
     }
     mXHR = nullptr;
     return NS_OK;
   }
   explicit nsXHRParseEndListener(nsIXMLHttpRequest* aXHR)
     : mXHR(do_GetWeakReference(aXHR)) {}
 private:
   virtual ~nsXHRParseEndListener() {}
 
   nsWeakPtr mXHR;
 };
 
-#endif
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_XMLHttpRequestMainThread_h
--- a/dom/xhr/XMLHttpRequestUpload.h
+++ b/dom/xhr/XMLHttpRequestUpload.h
@@ -8,20 +8,16 @@
 #define mozilla_dom_XMLHttpRequestUpload_h
 
 #include "mozilla/dom/XMLHttpRequestEventTarget.h"
 #include "nsIXMLHttpRequest.h"
 
 namespace mozilla {
 namespace dom {
 
-namespace workers {
-class XMLHttpRequestWorker;
-}
-
 class XMLHttpRequestUpload final : public XMLHttpRequestEventTarget,
                                    public nsIXMLHttpRequestUpload
 {
 public:
   explicit XMLHttpRequestUpload(DOMEventTargetHelper* aOwner)
     : XMLHttpRequestEventTarget(aOwner)
   {}
 
--- a/dom/xhr/XMLHttpRequestWorker.cpp
+++ b/dom/xhr/XMLHttpRequestWorker.cpp
@@ -31,34 +31,34 @@
 #include "RuntimeService.h"
 #include "WorkerScope.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 #include "XMLHttpRequestUpload.h"
 
 #include "mozilla/UniquePtr.h"
 
-using namespace mozilla;
-
-using namespace mozilla::dom;
-USING_WORKERS_NAMESPACE
+namespace mozilla {
+namespace dom {
+
+using namespace workers;
 
 /* static */ void
 XMLHttpRequestWorker::StateData::trace(JSTracer *aTrc)
 {
-    JS::TraceEdge(aTrc, &mResponse, "XMLHttpRequestWorker::StateData::mResponse");
+  JS::TraceEdge(aTrc, &mResponse, "XMLHttpRequestWorker::StateData::mResponse");
 }
 
 /**
  *  XMLHttpRequest in workers
  *
  *  XHR in workers is implemented by proxying calls/events/etc between the
- *  worker thread and an nsXMLHttpRequest on the main thread.  The glue
+ *  worker thread and an XMLHttpRequest on the main thread.  The glue
  *  object here is the Proxy, which lives on both threads.  All other objects
- *  live on either the main thread (the nsXMLHttpRequest) or the worker thread
+ *  live on either the main thread (the XMLHttpRequest) or the worker thread
  *  (the worker and XHR private objects).
  *
  *  The main thread XHR is always operated in async mode, even for sync XHR
  *  in workers.  Calls made on the worker thread are proxied to the main thread
  *  synchronously (meaning the worker thread is blocked until the call
  *  returns).  Each proxied call spins up a sync queue, which captures any
  *  synchronously dispatched events and ensures that they run synchronously
  *  on the worker as well.  Asynchronously dispatched events are posted to the
@@ -85,31 +85,29 @@ XMLHttpRequestWorker::StateData::trace(J
  *  regular runnables.  In the event that we reach Proxy::Teardown and there
  *  the outstanding Send count is still non-zero, we dispatch a control
  *  runnable which is guaranteed to run.
  *
  *  NB: Some of this could probably be simplified now that we have the
  *  inner/outer channel ids.
  */
 
-BEGIN_WORKERS_NAMESPACE
-
 class Proxy final : public nsIDOMEventListener
 {
 public:
   // Read on multiple threads.
   WorkerPrivate* mWorkerPrivate;
   XMLHttpRequestWorker* mXMLHttpRequestPrivate;
 
   // XHR Params:
   bool mMozAnon;
   bool mMozSystem;
 
   // Only touched on the main thread.
-  RefPtr<nsXMLHttpRequest> mXHR;
+  RefPtr<XMLHttpRequestMainThread> mXHR;
   nsCOMPtr<nsIXMLHttpRequestUpload> mXHRUpload;
   nsCOMPtr<nsIEventTarget> mSyncLoopTarget;
   nsCOMPtr<nsIEventTarget> mSyncEventResponseTarget;
   uint32_t mInnerEventStreamId;
   uint32_t mInnerChannelId;
   uint32_t mOutstandingSendCount;
 
   // Only touched on the worker thread.
@@ -220,18 +218,18 @@ public:
       aRv.Throw(mErrorCode);
     }
   }
 
 protected:
   virtual ~WorkerThreadProxySyncRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() = 0;
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) = 0;
 
 private:
   virtual bool MainThreadRun() override;
 };
 
 class SendRunnable final
   : public WorkerThreadProxySyncRunnable
   , public StructuredCloneHolder
@@ -260,52 +258,22 @@ public:
   {
     mSyncLoopTarget = aSyncLoopTarget;
   }
 
 private:
   ~SendRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override;
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override;
 };
 
-END_WORKERS_NAMESPACE
-
 namespace {
 
-inline void
-ConvertResponseTypeToString(XMLHttpRequestResponseType aType,
-                            nsString& aString)
-{
-  using namespace
-    mozilla::dom::XMLHttpRequestResponseTypeValues;
-
-  size_t index = static_cast<size_t>(aType);
-  MOZ_ASSERT(index < ArrayLength(strings), "Codegen gave us a bad value!");
-
-  aString.AssignASCII(strings[index].value, strings[index].length);
-}
-
-inline XMLHttpRequestResponseType
-ConvertStringToResponseType(const nsAString& aString)
-{
-  using namespace
-    mozilla::dom::XMLHttpRequestResponseTypeValues;
-
-  for (size_t index = 0; index < ArrayLength(strings) - 1; index++) {
-    if (aString.EqualsASCII(strings[index].value, strings[index].length)) {
-      return static_cast<XMLHttpRequestResponseType>(index);
-    }
-  }
-
-  MOZ_CRASH("Don't know anything about this response type!");
-}
-
 enum
 {
   STRING_abort = 0,
   STRING_error,
   STRING_load,
   STRING_loadstart,
   STRING_progress,
   STRING_timeout,
@@ -411,17 +379,17 @@ private:
   }
 };
 
 class LoadStartDetectionRunnable final : public Runnable,
                                          public nsIDOMEventListener
 {
   WorkerPrivate* mWorkerPrivate;
   RefPtr<Proxy> mProxy;
-  RefPtr<nsXMLHttpRequest> mXHR;
+  RefPtr<XMLHttpRequest> mXHR;
   XMLHttpRequestWorker* mXMLHttpRequestPrivate;
   nsString mEventType;
   uint32_t mChannelId;
   bool mReceivedLoadStart;
 
   class ProxyCompleteRunnable final : public MainThreadProxyRunnable
   {
     XMLHttpRequestWorker* mXMLHttpRequestPrivate;
@@ -572,22 +540,21 @@ public:
   SyncTeardownRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy)
   : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
   { }
 
 private:
   ~SyncTeardownRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override
   {
     mProxy->Teardown(/* aSendUnpin */ true);
     MOZ_ASSERT(!mProxy->mSyncLoopTarget);
-    return NS_OK;
   }
 };
 
 class SetBackgroundRequestRunnable final :
   public WorkerThreadProxySyncRunnable
 {
   bool mValue;
 
@@ -597,20 +564,20 @@ public:
   : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
   , mValue(aValue)
   { }
 
 private:
   ~SetBackgroundRequestRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override
   {
-    return mProxy->mXHR->SetMozBackgroundRequest(mValue);
+    mProxy->mXHR->SetMozBackgroundRequest(mValue, aRv);
   }
 };
 
 class SetWithCredentialsRunnable final :
   public WorkerThreadProxySyncRunnable
 {
   bool mValue;
 
@@ -620,53 +587,51 @@ public:
   : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
   , mValue(aValue)
   { }
 
 private:
   ~SetWithCredentialsRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override
   {
-    return mProxy->mXHR->SetWithCredentials(mValue);
+    mProxy->mXHR->SetWithCredentials(mValue, aRv);
   }
 };
 
 class SetResponseTypeRunnable final : public WorkerThreadProxySyncRunnable
 {
-  nsString mResponseType;
+  XMLHttpRequestResponseType mResponseType;
 
 public:
   SetResponseTypeRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy,
-                          const nsAString& aResponseType)
+                          XMLHttpRequestResponseType aResponseType)
   : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy),
     mResponseType(aResponseType)
   { }
 
-  void
-  GetResponseType(nsAString& aResponseType)
+  XMLHttpRequestResponseType
+  ResponseType()
   {
-    aResponseType.Assign(mResponseType);
+    return mResponseType;
   }
 
 private:
   ~SetResponseTypeRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override
   {
-    nsresult rv = mProxy->mXHR->SetResponseType(mResponseType);
-    mResponseType.Truncate();
-    if (NS_SUCCEEDED(rv)) {
-      rv = mProxy->mXHR->GetResponseType(mResponseType);
+    mProxy->mXHR->SetResponseType(mResponseType, aRv);
+    if (!aRv.Failed()) {
+      mResponseType = mProxy->mXHR->ResponseType();
     }
-    return rv;
   }
 };
 
 class SetTimeoutRunnable final : public WorkerThreadProxySyncRunnable
 {
   uint32_t mTimeout;
 
 public:
@@ -675,36 +640,36 @@ public:
   : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy),
     mTimeout(aTimeout)
   { }
 
 private:
   ~SetTimeoutRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override
   {
-    return mProxy->mXHR->SetTimeout(mTimeout);
+    mProxy->mXHR->SetTimeout(mTimeout, aRv);
   }
 };
 
 class AbortRunnable final : public WorkerThreadProxySyncRunnable
 {
 public:
   AbortRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy)
   : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
   { }
 
 private:
   ~AbortRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override;
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override;
 };
 
 class GetAllResponseHeadersRunnable final :
   public WorkerThreadProxySyncRunnable
 {
   nsCString& mResponseHeaders;
 
 public:
@@ -713,21 +678,20 @@ public:
   : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy),
     mResponseHeaders(aResponseHeaders)
   { }
 
 private:
   ~GetAllResponseHeadersRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override
   {
-    mProxy->mXHR->GetAllResponseHeaders(mResponseHeaders);
-    return NS_OK;
+    mProxy->mXHR->GetAllResponseHeaders(mResponseHeaders, aRv);
   }
 };
 
 class GetResponseHeaderRunnable final : public WorkerThreadProxySyncRunnable
 {
   const nsCString mHeader;
   nsCString& mValue;
 
@@ -738,20 +702,20 @@ public:
     mHeader(aHeader),
     mValue(aValue)
   { }
 
 private:
   ~GetResponseHeaderRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override
   {
-    return mProxy->mXHR->GetResponseHeader(mHeader, mValue);
+    mProxy->mXHR->GetResponseHeader(mHeader, mValue, aRv);
   }
 };
 
 class OpenRunnable final : public WorkerThreadProxySyncRunnable
 {
   nsCString mMethod;
   nsString mURL;
   Optional<nsAString> mUser;
@@ -785,26 +749,25 @@ public:
       mPassword = &mPasswordStr;
     }
   }
 
 private:
   ~OpenRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override
   {
     WorkerPrivate* oldWorker = mProxy->mWorkerPrivate;
     mProxy->mWorkerPrivate = mWorkerPrivate;
 
-    nsresult rv = MainThreadRunInternal();
+    aRv = MainThreadRunInternal();
 
     mProxy->mWorkerPrivate = oldWorker;
-    return rv;
   }
 
   nsresult
   MainThreadRunInternal();
 };
 
 class SetRequestHeaderRunnable final : public WorkerThreadProxySyncRunnable
 {
@@ -818,20 +781,20 @@ public:
     mHeader(aHeader),
     mValue(aValue)
   { }
 
 private:
   ~SetRequestHeaderRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override
   {
-    return mProxy->mXHR->SetRequestHeader(mHeader, mValue);
+    mProxy->mXHR->SetRequestHeader(mHeader, mValue, aRv);
   }
 };
 
 class OverrideMimeTypeRunnable final : public WorkerThreadProxySyncRunnable
 {
   nsString mMimeType;
 
 public:
@@ -840,22 +803,20 @@ public:
   : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy),
     mMimeType(aMimeType)
   { }
 
 private:
   ~OverrideMimeTypeRunnable()
   { }
 
-  virtual nsresult
-  RunOnMainThread() override
+  virtual void
+  RunOnMainThread(ErrorResult& aRv) override
   {
-    ErrorResult aRv;
     mProxy->mXHR->OverrideMimeType(mMimeType, aRv);
-    return aRv.StealNSResult();
   }
 };
 
 class AutoUnpinXHR
 {
   XMLHttpRequestWorker* mXMLHttpRequestPrivate;
 
 public:
@@ -891,37 +852,35 @@ Proxy::Init()
   }
 
   nsPIDOMWindowInner* ownerWindow = mWorkerPrivate->GetWindow();
   if (ownerWindow && !ownerWindow->IsCurrentInnerWindow()) {
     NS_WARNING("Window has navigated, cannot create XHR here.");
     return false;
   }
 
-  mXHR = new nsXMLHttpRequest();
-
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(ownerWindow);
-  if (NS_FAILED(mXHR->Init(mWorkerPrivate->GetPrincipal(),
-                           mWorkerPrivate->GetScriptContext(),
-                           global, mWorkerPrivate->GetBaseURI(),
-                           mWorkerPrivate->GetLoadGroup()))) {
-    mXHR = nullptr;
-    return false;
-  }
+
+  mXHR = new XMLHttpRequestMainThread();
+  mXHR->Construct(mWorkerPrivate->GetPrincipal(), global,
+                  mWorkerPrivate->GetBaseURI(),
+                  mWorkerPrivate->GetLoadGroup());
 
   mXHR->SetParameters(mMozAnon, mMozSystem);
 
-  if (NS_FAILED(mXHR->GetUpload(getter_AddRefs(mXHRUpload)))) {
+  ErrorResult rv;
+  mXHRUpload = mXHR->GetUpload(rv);
+  if (NS_WARN_IF(rv.Failed())) {
     mXHR = nullptr;
     return false;
   }
 
   if (!AddRemoveEventListeners(false, true)) {
+    mXHR = nullptr;
     mXHRUpload = nullptr;
-    mXHR = nullptr;
     return false;
   }
 
   return true;
 }
 
 void
 Proxy::Teardown(bool aSendUnpin)
@@ -929,17 +888,22 @@ Proxy::Teardown(bool aSendUnpin)
   AssertIsOnMainThread();
 
   if (mXHR) {
     Reset();
 
     // NB: We are intentionally dropping events coming from xhr.abort on the
     // floor.
     AddRemoveEventListeners(false, false);
-    mXHR->Abort();
+
+    ErrorResult rv;
+    mXHR->Abort(rv);
+    if (NS_WARN_IF(rv.Failed())) {
+      rv.SuppressException();
+    }
 
     if (mOutstandingSendCount) {
       if (aSendUnpin) {
         RefPtr<XHRUnpinRunnable> runnable =
           new XHRUnpinRunnable(mWorkerPrivate, mXMLHttpRequestPrivate);
         if (!runnable->Dispatch()) {
           NS_RUNTIMEABORT("We're going to hang at shutdown anyways.");
         }
@@ -1153,17 +1117,17 @@ EventRunnable::PreDispatch(WorkerPrivate
   MOZ_ASSERT(ok);
   JSContext* cx = jsapi.cx();
   // Now keep the mScopeObj alive for the duration
   JS::Rooted<JSObject*> scopeObj(cx, mScopeObj);
   // And reset mScopeObj now, before we have a chance to run its destructor on
   // some background thread.
   mScopeObj.reset();
 
-  RefPtr<nsXMLHttpRequest>& xhr = mProxy->mXHR;
+  RefPtr<XMLHttpRequestMainThread>& xhr = mProxy->mXHR;
   MOZ_ASSERT(xhr);
 
   if (NS_FAILED(xhr->GetResponseType(mResponseType))) {
     MOZ_ASSERT(false, "This should never fail!");
   }
 
   mResponseTextResult = xhr->GetResponseText(mResponseText);
   if (NS_SUCCEEDED(mResponseTextResult)) {
@@ -1217,17 +1181,19 @@ EventRunnable::PreDispatch(WorkerPrivate
           }
         }
       }
     }
   }
 
   mStatusResult = xhr->GetStatus(&mStatus);
 
-  xhr->GetStatusText(mStatusText);
+  ErrorResult rv;
+  xhr->GetStatusText(mStatusText, rv);
+  MOZ_ASSERT(!rv.Failed());
 
   mReadyState = xhr->ReadyState();
 
   xhr->GetResponseURL(mResponseURL);
 
   return true;
 }
 
@@ -1402,38 +1368,38 @@ bool
 WorkerThreadProxySyncRunnable::MainThreadRun()
 {
   AssertIsOnMainThread();
 
   nsCOMPtr<nsIEventTarget> tempTarget = mSyncLoopTarget;
 
   mProxy->mSyncEventResponseTarget.swap(tempTarget);
 
-  mErrorCode = RunOnMainThread();
+  ErrorResult rv;
+  RunOnMainThread(rv);
+  mErrorCode = rv.StealNSResult();
 
   mProxy->mSyncEventResponseTarget.swap(tempTarget);
 
   return true;
 }
 
-nsresult
-AbortRunnable::RunOnMainThread()
+void
+AbortRunnable::RunOnMainThread(ErrorResult& aRv)
 {
   mProxy->mInnerEventStreamId++;
 
   WorkerPrivate* oldWorker = mProxy->mWorkerPrivate;
   mProxy->mWorkerPrivate = mWorkerPrivate;
 
-  mProxy->mXHR->Abort();
+  mProxy->mXHR->Abort(aRv);
 
   mProxy->mWorkerPrivate = oldWorker;
 
   mProxy->Reset();
-
-  return NS_OK;
 }
 
 nsresult
 OpenRunnable::MainThreadRunInternal()
 {
   if (!mProxy->Init()) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
@@ -1471,65 +1437,65 @@ OpenRunnable::MainThreadRunInternal()
   mProxy->mXHR->SetResponseType(mResponseType, rv2);
   if (rv2.Failed()) {
     return rv2.StealNSResult();
   }
 
   return NS_OK;
 }
 
-
-nsresult
-SendRunnable::RunOnMainThread()
+void
+SendRunnable::RunOnMainThread(ErrorResult& aRv)
 {
   nsCOMPtr<nsIVariant> variant;
 
   if (HasData()) {
     AutoSafeJSContext cx;
     JSAutoRequest ar(cx);
 
     nsIXPConnect* xpc = nsContentUtils::XPConnect();
     MOZ_ASSERT(xpc);
 
-    ErrorResult rv;
-
     JS::Rooted<JSObject*> globalObject(cx, JS::CurrentGlobalOrNull(cx));
     if (NS_WARN_IF(!globalObject)) {
-      return NS_ERROR_FAILURE;
+      aRv.Throw(NS_ERROR_FAILURE);
+      return;
     }
 
     nsCOMPtr<nsIGlobalObject> parent = xpc::NativeGlobal(globalObject);
     if (NS_WARN_IF(!parent)) {
-      return NS_ERROR_FAILURE;
+      aRv.Throw(NS_ERROR_FAILURE);
+      return;
     }
 
     JS::Rooted<JS::Value> body(cx);
-    Read(parent, cx, &body, rv);
-    if (NS_WARN_IF(rv.Failed())) {
-      return rv.StealNSResult();
+    Read(parent, cx, &body, aRv);
+    if (NS_WARN_IF(aRv.Failed())) {
+      return;
     }
 
-    rv = xpc->JSValToVariant(cx, body, getter_AddRefs(variant));
-    if (NS_WARN_IF(rv.Failed())) {
-      return rv.StealNSResult();
+    aRv = xpc->JSValToVariant(cx, body, getter_AddRefs(variant));
+    if (NS_WARN_IF(aRv.Failed())) {
+      return;
     }
   }
   else {
     RefPtr<nsVariant> wvariant = new nsVariant();
 
     if (NS_FAILED(wvariant->SetAsAString(mStringBody))) {
       MOZ_ASSERT(false, "This should never fail!");
     }
 
     variant = wvariant;
   }
 
   // Send() has been already called.
   if (mProxy->mWorkerPrivate) {
-    return NS_ERROR_DOM_INVALID_STATE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
   }
 
   mProxy->mWorkerPrivate = mWorkerPrivate;
 
   MOZ_ASSERT(!mProxy->mSyncLoopTarget);
   mProxy->mSyncLoopTarget.swap(mSyncLoopTarget);
 
   if (mHasUploadListeners) {
@@ -1538,30 +1504,28 @@ SendRunnable::RunOnMainThread()
       MOZ_ASSERT(false, "This should never fail!");
     }
   }
 
   mProxy->mArrayBufferResponseWasTransferred = false;
 
   mProxy->mInnerChannelId++;
 
-  nsresult rv = mProxy->mXHR->Send(variant);
-
-  if (NS_SUCCEEDED(rv)) {
+  aRv = mProxy->mXHR->Send(variant);
+
+  if (!aRv.Failed()) {
     mProxy->mOutstandingSendCount++;
 
     if (!mHasUploadListeners) {
       NS_ASSERTION(!mProxy->mUploadEventListenersAttached, "Huh?!");
       if (!mProxy->AddRemoveEventListeners(true, true)) {
         MOZ_ASSERT(false, "This should never fail!");
       }
     }
   }
-
-  return rv;
 }
 
 XMLHttpRequestWorker::XMLHttpRequestWorker(WorkerPrivate* aWorkerPrivate)
 : mWorkerPrivate(aWorkerPrivate),
   mResponseType(XMLHttpRequestResponseType::Text), mTimeout(0),
   mRooted(false), mBackgroundRequest(false), mWithCredentials(false),
   mCanceled(false), mMozAnon(false), mMozSystem(false)
 {
@@ -1601,27 +1565,20 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
   tmp->mStateData.mResponse.setUndefined();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(XMLHttpRequestWorker,
                                                XMLHttpRequestEventTarget)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mStateData.mResponse)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
-JSObject*
-XMLHttpRequestWorker::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return XMLHttpRequestBinding_workers::Wrap(aCx, this, aGivenProto);
-}
-
-// static
-already_AddRefed<XMLHttpRequestWorker>
-XMLHttpRequestWorker::Constructor(const GlobalObject& aGlobal,
-                                  const MozXMLHttpRequestParameters& aParams,
-                                  ErrorResult& aRv)
+/* static */ already_AddRefed<XMLHttpRequest>
+XMLHttpRequestWorker::Construct(const GlobalObject& aGlobal,
+                                const MozXMLHttpRequestParameters& aParams,
+                                ErrorResult& aRv)
 {
   JSContext* cx = aGlobal.Context();
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
   MOZ_ASSERT(workerPrivate);
 
   Telemetry::Accumulate(Telemetry::XHR_IN_WORKER, 1);
 
   RefPtr<XMLHttpRequestWorker> xhr = new XMLHttpRequestWorker(workerPrivate);
@@ -2045,17 +2002,17 @@ XMLHttpRequestWorker::GetUpload(ErrorRes
       return nullptr;
     }
   }
 
   return mUpload;
 }
 
 void
-XMLHttpRequestWorker::Send(ErrorResult& aRv)
+XMLHttpRequestWorker::Send(JSContext* aCx, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   if (mCanceled) {
     aRv.ThrowUncatchableException();
     return;
   }
 
@@ -2067,17 +2024,18 @@ XMLHttpRequestWorker::Send(ErrorResult& 
   RefPtr<SendRunnable> sendRunnable =
     new SendRunnable(mWorkerPrivate, mProxy, NullString());
 
   // Nothing to clone.
   SendInternal(sendRunnable, aRv);
 }
 
 void
-XMLHttpRequestWorker::Send(const nsAString& aBody, ErrorResult& aRv)
+XMLHttpRequestWorker::Send(JSContext* aCx, const nsAString& aBody,
+                           ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   if (mCanceled) {
     aRv.ThrowUncatchableException();
     return;
   }
 
@@ -2089,151 +2047,150 @@ XMLHttpRequestWorker::Send(const nsAStri
   RefPtr<SendRunnable> sendRunnable =
     new SendRunnable(mWorkerPrivate, mProxy, aBody);
 
   // Nothing to clone.
   SendInternal(sendRunnable, aRv);
 }
 
 void
-XMLHttpRequestWorker::Send(JS::Handle<JSObject*> aBody, ErrorResult& aRv)
+XMLHttpRequestWorker::Send(JSContext* aCx, JS::Handle<JSObject*> aBody,
+                           ErrorResult& aRv)
 {
-  JSContext* cx = mWorkerPrivate->GetJSContext();
-
   MOZ_ASSERT(aBody);
 
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   if (mCanceled) {
     aRv.ThrowUncatchableException();
     return;
   }
 
   if (!mProxy) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
-  JS::Rooted<JS::Value> valToClone(cx);
+  JS::Rooted<JS::Value> valToClone(aCx);
   if (JS_IsArrayBufferObject(aBody) || JS_IsArrayBufferViewObject(aBody)) {
     valToClone.setObject(*aBody);
   }
   else {
-    JS::Rooted<JS::Value> obj(cx, JS::ObjectValue(*aBody));
-    JSString* bodyStr = JS::ToString(cx, obj);
+    JS::Rooted<JS::Value> obj(aCx, JS::ObjectValue(*aBody));
+    JSString* bodyStr = JS::ToString(aCx, obj);
     if (!bodyStr) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     valToClone.setString(bodyStr);
   }
 
   RefPtr<SendRunnable> sendRunnable =
     new SendRunnable(mWorkerPrivate, mProxy, EmptyString());
 
-  sendRunnable->Write(cx, valToClone, aRv);
+  sendRunnable->Write(aCx, valToClone, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   SendInternal(sendRunnable, aRv);
 }
 
 void
-XMLHttpRequestWorker::Send(Blob& aBody, ErrorResult& aRv)
+XMLHttpRequestWorker::Send(JSContext* aCx, Blob& aBody, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
-  JSContext* cx = mWorkerPrivate->GetJSContext();
 
   if (mCanceled) {
     aRv.ThrowUncatchableException();
     return;
   }
 
   if (!mProxy) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
-  JS::Rooted<JS::Value> value(cx);
-  if (!GetOrCreateDOMReflector(cx, &aBody, &value)) {
+  JS::Rooted<JS::Value> value(aCx);
+  if (!GetOrCreateDOMReflector(aCx, &aBody, &value)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   RefPtr<BlobImpl> blobImpl = aBody.Impl();
   MOZ_ASSERT(blobImpl);
 
   aRv = blobImpl->SetMutable(false);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   RefPtr<SendRunnable> sendRunnable =
     new SendRunnable(mWorkerPrivate, mProxy, EmptyString());
 
-  sendRunnable->Write(cx, value, aRv);
+  sendRunnable->Write(aCx, value, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   SendInternal(sendRunnable, aRv);
 }
 
 void
-XMLHttpRequestWorker::Send(FormData& aBody, ErrorResult& aRv)
+XMLHttpRequestWorker::Send(JSContext* aCx, FormData& aBody, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
-  JSContext* cx = mWorkerPrivate->GetJSContext();
 
   if (mCanceled) {
     aRv.ThrowUncatchableException();
     return;
   }
 
   if (!mProxy) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
-  JS::Rooted<JS::Value> value(cx);
-  if (!GetOrCreateDOMReflector(cx, &aBody, &value)) {
+  JS::Rooted<JS::Value> value(aCx);
+  if (!GetOrCreateDOMReflector(aCx, &aBody, &value)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   RefPtr<SendRunnable> sendRunnable =
     new SendRunnable(mWorkerPrivate, mProxy, EmptyString());
 
-  sendRunnable->Write(cx, value, aRv);
+  sendRunnable->Write(aCx, value, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   SendInternal(sendRunnable, aRv);
 }
 
 void
-XMLHttpRequestWorker::Send(const ArrayBuffer& aBody, ErrorResult& aRv)
+XMLHttpRequestWorker::Send(JSContext* aCx, const ArrayBuffer& aBody,
+                           ErrorResult& aRv)
 {
   JS::Rooted<JSObject*> obj(mWorkerPrivate->GetJSContext(), aBody.Obj());
-  return Send(obj, aRv);
+  return Send(aCx, obj, aRv);
 }
 
 void
-XMLHttpRequestWorker::Send(const ArrayBufferView& aBody, ErrorResult& aRv)
+XMLHttpRequestWorker::Send(JSContext* aCx, const ArrayBufferView& aBody,
+                           ErrorResult& aRv)
 {
   if (JS_IsTypedArrayObject(aBody.Obj()) &&
       JS_GetTypedArraySharedness(aBody.Obj())) {
     // Throw if the object is mapping shared memory (must opt in).
     aRv.ThrowTypeError<MSG_TYPEDARRAY_IS_SHARED>(NS_LITERAL_STRING("Argument of XMLHttpRequest.send"));
     return;
   }
-  JS::Rooted<JSObject*> obj(mWorkerPrivate->GetJSContext(), aBody.Obj());
-  return Send(obj, aRv);
+  JS::Rooted<JSObject*> obj(aCx, aBody.Obj());
+  return Send(aCx, obj, aRv);
 }
 
 void
 XMLHttpRequestWorker::Abort(ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   if (mCanceled) {
@@ -2369,30 +2326,24 @@ XMLHttpRequestWorker::SetResponseType(XM
 
   if (SendInProgress() &&
       (mProxy->mSeenLoadStart ||
        mStateData.mReadyState > nsIXMLHttpRequest::OPENED)) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
-  nsString responseType;
-  ConvertResponseTypeToString(aResponseType, responseType);
-
   RefPtr<SetResponseTypeRunnable> runnable =
-    new SetResponseTypeRunnable(mWorkerPrivate, mProxy, responseType);
+    new SetResponseTypeRunnable(mWorkerPrivate, mProxy, aResponseType);
   runnable->Dispatch(aRv);
   if (aRv.Failed()) {
     return;
   }
 
-  nsString acceptedResponseTypeString;
-  runnable->GetResponseType(acceptedResponseTypeString);
-
-  mResponseType = ConvertStringToResponseType(acceptedResponseTypeString);
+  mResponseType = runnable->ResponseType();
 }
 
 void
 XMLHttpRequestWorker::GetResponse(JSContext* /* unused */,
                                   JS::MutableHandle<JS::Value> aResponse,
                                   ErrorResult& aRv)
 {
   if (NS_SUCCEEDED(mStateData.mResponseTextResult) &&
@@ -2441,8 +2392,11 @@ XMLHttpRequestWorker::UpdateState(const 
                                    mStateData.mResponse);
     mStateData = aStateData;
     mStateData.mResponse = response;
   }
   else {
     mStateData = aStateData;
   }
 }
+
+} // dom namespace
+} // mozilla namespace
--- a/dom/xhr/XMLHttpRequestWorker.h
+++ b/dom/xhr/XMLHttpRequestWorker.h
@@ -1,41 +1,33 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_dom_workers_xmlhttprequest_h__
-#define mozilla_dom_workers_xmlhttprequest_h__
-
-#include "mozilla/dom/workers/bindings/WorkerHolder.h"
+#ifndef mozilla_dom_XMLHttpRequestWorker_h
+#define mozilla_dom_XMLHttpRequestWorker_h
 
-// Need this for XMLHttpRequestResponseType.
-#include "mozilla/dom/XMLHttpRequestBinding.h"
-
+#include "WorkerHolder.h"
+#include "XMLHttpRequest.h"
 #include "mozilla/dom/TypedArray.h"
 
-#include "nsXMLHttpRequest.h"
-
 namespace mozilla {
 namespace dom {
-class Blob;
-class XMLHttpRequestUpload;
-} // namespace dom
-} // namespace mozilla
-
-BEGIN_WORKERS_NAMESPACE
 
 class Proxy;
 class SendRunnable;
-class WorkerPrivate;
 
-class XMLHttpRequestWorker final : public XMLHttpRequestEventTarget,
-                                   public WorkerHolder
+namespace workers {
+class WorkerPrivate;
+}
+
+class XMLHttpRequestWorker final : public XMLHttpRequest,
+                                   public worker::WorkerHolder
 {
 public:
   struct StateData
   {
     nsString mResponseText;
     nsString mResponseURL;
     uint32_t mStatus;
     nsCString mStatusText;
@@ -51,195 +43,209 @@ public:
       mResponseResult(NS_OK)
     { }
 
     void trace(JSTracer* trc);
   };
 
 private:
   RefPtr<XMLHttpRequestUpload> mUpload;
-  WorkerPrivate* mWorkerPrivate;
+  workers::WorkerPrivate* mWorkerPrivate;
   RefPtr<Proxy> mProxy;
   XMLHttpRequestResponseType mResponseType;
   StateData mStateData;
 
   uint32_t mTimeout;
 
   bool mRooted;
   bool mBackgroundRequest;
   bool mWithCredentials;
   bool mCanceled;
 
   bool mMozAnon;
   bool mMozSystem;
 
 public:
-  virtual JSObject*
-  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(XMLHttpRequestWorker,
-                                                         XMLHttpRequestEventTarget)
+                                                         XMLHttpRequest)
 
-  nsISupports*
-  GetParentObject() const
-  {
-    // There's only one global on a worker, so we don't need to specify.
-    return nullptr;
-  }
-
-  static already_AddRefed<XMLHttpRequestWorker>
-  Constructor(const GlobalObject& aGlobal,
-              const MozXMLHttpRequestParameters& aParams,
-              ErrorResult& aRv);
 
-  static already_AddRefed<XMLHttpRequestWorker>
-  Constructor(const GlobalObject& aGlobal, const nsAString& ignored,
-              ErrorResult& aRv)
-  {
-    // Pretend like someone passed null, so we can pick up the default values
-    MozXMLHttpRequestParameters params;
-    if (!params.Init(aGlobal.Context(), JS::NullHandleValue)) {
-      aRv.Throw(NS_ERROR_UNEXPECTED);
-      return nullptr;
-    }
-
-    return Constructor(aGlobal, params, aRv);
-  }
+  static already_AddRefed<XMLHttpRequest>
+  Construct(const GlobalObject& aGlobal,
+            const MozXMLHttpRequestParameters& aParams,
+            ErrorResult& aRv);
 
   void
   Unpin();
 
   bool
-  Notify(Status aStatus) override;
+  Notify(workers::Status aStatus) override;
 
-  IMPL_EVENT_HANDLER(readystatechange)
-
-  uint16_t
-  ReadyState() const
+  virtual uint16_t
+  ReadyState() const override
   {
     return mStateData.mReadyState;
   }
 
-  void Open(const nsACString& aMethod, const nsAString& aUrl, ErrorResult& aRv)
+  virtual void
+  Open(const nsACString& aMethod, const nsAString& aUrl,
+       ErrorResult& aRv) override
   {
     Open(aMethod, aUrl, true, Optional<nsAString>(),
          Optional<nsAString>(), aRv);
   }
-  void
+
+  virtual void
   Open(const nsACString& aMethod, const nsAString& aUrl, bool aAsync,
        const Optional<nsAString>& aUser, const Optional<nsAString>& aPassword,
-       ErrorResult& aRv);
+       ErrorResult& aRv) override;
 
-  void
+  virtual void
   SetRequestHeader(const nsACString& aHeader, const nsACString& aValue,
-                   ErrorResult& aRv);
+                   ErrorResult& aRv) override;
 
-  uint32_t
-  Timeout() const
+  virtual uint32_t
+  Timeout() const override
   {
     return mTimeout;
   }
 
-  void
-  SetTimeout(uint32_t aTimeout, ErrorResult& aRv);
+  virtual void
+  SetTimeout(uint32_t aTimeout, ErrorResult& aRv) override;
 
-  bool
-  WithCredentials() const
+  virtual bool
+  WithCredentials() const override
   {
     return mWithCredentials;
   }
 
-  void
-  SetWithCredentials(bool aWithCredentials, ErrorResult& aRv);
+  virtual void
+  SetWithCredentials(bool aWithCredentials, ErrorResult& aRv) override;
 
-  bool
-  MozBackgroundRequest() const
+  virtual bool
+  MozBackgroundRequest() const override
   {
     return mBackgroundRequest;
   }
 
-  void
-  SetMozBackgroundRequest(bool aBackgroundRequest, ErrorResult& aRv);
+  virtual void
+  SetMozBackgroundRequest(bool aBackgroundRequest, ErrorResult& aRv) override;
 
-  XMLHttpRequestUpload*
-  GetUpload(ErrorResult& aRv);
+  virtual nsIChannel*
+  GetChannel() const override
+  {
+    MOZ_CRASH("This method cannot be called on workers.");
+  }
+
+  virtual void
+  GetNetworkInterfaceId(nsACString& aId) const override
+  {
+    MOZ_CRASH("This method cannot be called on workers.");
+  }
 
-  void
-  Send(ErrorResult& aRv);
+  virtual void
+  SetNetworkInterfaceId(const nsACString& aId) override
+  {
+    MOZ_CRASH("This method cannot be called on workers.");
+  }
 
-  void
-  Send(const nsAString& aBody, ErrorResult& aRv);
+  virtual XMLHttpRequestUpload*
+  GetUpload(ErrorResult& aRv) override;
 
-  void
-  Send(JS::Handle<JSObject*> aBody, ErrorResult& aRv);
+  virtual void
+  Send(JSContext* aCx, ErrorResult& aRv) override;
+
+  virtual void
+  Send(JSContext* aCx, const nsAString& aBody, ErrorResult& aRv) override;
 
-  void
-  Send(Blob& aBody, ErrorResult& aRv);
+  virtual void
+  Send(JSContext* aCx, nsIInputStream* aStream, ErrorResult& aRv) override
+  {
+    MOZ_CRASH("This method cannot be called on workers.");
+  }
 
-  void
-  Send(FormData& aBody, ErrorResult& aRv);
+  virtual void
+  Send(JSContext* aCx, Blob& aBody, ErrorResult& aRv) override;
 
-  void
-  Send(const ArrayBuffer& aBody, ErrorResult& aRv);
+  virtual void
+  Send(JSContext* aCx, FormData& aBody, ErrorResult& aRv) override;
+
+  virtual void
+  Send(JSContext* aCx, const ArrayBuffer& aBody, ErrorResult& aRv) override;
 
-  void
-  Send(const ArrayBufferView& aBody, ErrorResult& aRv);
+  virtual void
+  Send(JSContext* aCx, const ArrayBufferView& aBody, ErrorResult& aRv) override;
 
-  void
-  Abort(ErrorResult& aRv);
+  virtual void
+  Send(JSContext* aCx, nsIDocument& aDoc, ErrorResult& aRv) override
+  {
+    MOZ_CRASH("This method cannot be called on workers.");
+  }
 
-  void
-  GetResponseURL(nsAString& aUrl) const
+  virtual void
+  Abort(ErrorResult& aRv) override;
+
+  virtual void
+  GetResponseURL(nsAString& aUrl) override
   {
     aUrl = mStateData.mResponseURL;
   }
 
-  uint16_t
-  GetStatus(ErrorResult& aRv) const
+  uint32_t
+  GetStatus(ErrorResult& aRv) override
   {
     aRv = mStateData.mStatusResult;
     return mStateData.mStatus;
   }
 
-  void
-  GetStatusText(nsACString& aStatusText) const
+  virtual void
+  GetStatusText(nsACString& aStatusText, ErrorResult& aRv) override
   {
     aStatusText = mStateData.mStatusText;
   }
 
-  void
+  virtual void
   GetResponseHeader(const nsACString& aHeader, nsACString& aResponseHeader,
-                    ErrorResult& aRv);
+                    ErrorResult& aRv) override;
 
-  void
-  GetAllResponseHeaders(nsACString& aResponseHeaders, ErrorResult& aRv);
+  virtual void
+  GetAllResponseHeaders(nsACString& aResponseHeaders,
+                        ErrorResult& aRv) override;
 
-  void
-  OverrideMimeType(const nsAString& aMimeType, ErrorResult& aRv);
+  virtual void
+  OverrideMimeType(const nsAString& aMimeType, ErrorResult& aRv) override;
 
-  XMLHttpRequestResponseType
-  ResponseType() const
+  virtual XMLHttpRequestResponseType
+  ResponseType() const override
   {
     return mResponseType;
   }
 
-  void
-  SetResponseType(XMLHttpRequestResponseType aResponseType, ErrorResult& aRv);
+  virtual void
+  SetResponseType(XMLHttpRequestResponseType aResponseType,
+                  ErrorResult& aRv) override;
 
-  void
+  virtual void
   GetResponse(JSContext* /* unused */, JS::MutableHandle<JS::Value> aResponse,
-              ErrorResult& aRv);
+              ErrorResult& aRv) override;
+
+  virtual void
+  GetResponseText(nsAString& aResponseText, ErrorResult& aRv) override;
 
-  void
-  GetResponseText(nsAString& aResponseText, ErrorResult& aRv);
+  virtual nsIDocument*
+  GetResponseXML(ErrorResult& aRv) override
+  {
+    MOZ_CRASH("This method should not be called.");
+  }
 
-  void
-  GetInterface(JSContext* cx, JS::Handle<JSObject*> aIID,
-               JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv)
+  virtual void
+  GetInterface(JSContext* aCx, nsIJSID* aIID,
+               JS::MutableHandle<JS::Value> aRetval,
+               ErrorResult& aRv) override
   {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 
   XMLHttpRequestUpload*
   GetUploadObjectNoCreate() const
   {
     return mUpload;
@@ -250,34 +256,34 @@ public:
 
   void
   NullResponseText()
   {
     mStateData.mResponseText.SetIsVoid(true);
     mStateData.mResponse.setNull();
   }
 
-  bool MozAnon() const
+  virtual bool MozAnon() const override
   {
     return mMozAnon;
   }
 
-  bool MozSystem() const
+  virtual bool MozSystem() const override
   {
     return mMozSystem;
   }
 
   bool
   SendInProgress() const
   {
     return mRooted;
   }
 
 private:
-  explicit XMLHttpRequestWorker(WorkerPrivate* aWorkerPrivate);
+  explicit XMLHttpRequestWorker(workers::WorkerPrivate* aWorkerPrivate);
   ~XMLHttpRequestWorker();
 
   enum ReleaseType { Default, XHRIsGoingAway, WorkerIsGoingAway };
 
   void
   ReleaseProxy(ReleaseType aType = Default);
 
   void
@@ -287,15 +293,19 @@ private:
   MaybeDispatchPrematureAbortEvents(ErrorResult& aRv);
 
   void
   DispatchPrematureAbortEvent(EventTarget* aTarget,
                               const nsAString& aEventType, bool aUploadTarget,
                               ErrorResult& aRv);
 
   void
+  Send(JSContext* aCx, JS::Handle<JSObject*> aBody, ErrorResult& aRv);
+
+  void
   SendInternal(SendRunnable* aRunnable,
                ErrorResult& aRv);
 };
 
-END_WORKERS_NAMESPACE
+} // dom namespace
+} // mozilla namespace
 
 #endif // mozilla_dom_workers_xmlhttprequest_h__
--- a/dom/xhr/moz.build
+++ b/dom/xhr/moz.build
@@ -5,33 +5,27 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPIDL_SOURCES += [
     'nsIXMLHttpRequest.idl',
 ]
 
 XPIDL_MODULE = 'dom_xhr'
 
-# Stuff needed for the bindings, not really public though.
-EXPORTS.mozilla.dom.workers.bindings += [
-    'XMLHttpRequestWorker.h',
-]
-
 EXPORTS.mozilla.dom += [
+    'XMLHttpRequest.h',
     'XMLHttpRequestEventTarget.h',
+    'XMLHttpRequestMainThread.h',
     'XMLHttpRequestUpload.h',
 ]
 
-EXPORTS += [
-    'nsXMLHttpRequest.h',
-]
-
 UNIFIED_SOURCES += [
-    'nsXMLHttpRequest.cpp',
+    'XMLHttpRequest.cpp',
     'XMLHttpRequestEventTarget.cpp',
+    'XMLHttpRequestMainThread.cpp',
     'XMLHttpRequestUpload.cpp',
     'XMLHttpRequestWorker.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/workers',
     '/netwerk/base',
--- a/dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp
@@ -14,22 +14,22 @@
 #include "nsComponentManagerUtils.h"
 #include "nsGkAtoms.h"
 #include "nsIURI.h"
 #include "nsIArray.h"
 #include "nsIScriptContext.h"
 #include "nsArrayUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsXULContentUtils.h"
-#include "nsXMLHttpRequest.h"
 #include "mozilla/dom/XPathEvaluator.h"
 #include "nsXULTemplateQueryProcessorXML.h"
 #include "nsXULTemplateResultXML.h"
 #include "nsXULSortService.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/XMLHttpRequest.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 NS_IMPL_ISUPPORTS(nsXMLQuery, nsXMLQuery)
 
 //----------------------------------------------------------------------
 //
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -16,17 +16,16 @@
 #include "nsGlobalWindow.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIURI.h"
 #include "nsJSUtils.h"
 #include "nsNetUtil.h"
 #include "nsNullPrincipal.h"
 #include "nsPrincipal.h"
-#include "nsXMLHttpRequest.h"
 #include "WrapperFactory.h"
 #include "xpcprivate.h"
 #include "XPCWrapper.h"
 #include "XrayWrapper.h"
 #include "Crypto.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/cache/CacheStorage.h"
@@ -43,16 +42,17 @@
 #endif
 #include "mozilla/dom/FileReaderBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/TextDecoderBinding.h"
 #include "mozilla/dom/TextEncoderBinding.h"
 #include "mozilla/dom/UnionConversions.h"
 #include "mozilla/dom/URLBinding.h"
 #include "mozilla/dom/URLSearchParamsBinding.h"
+#include "mozilla/dom/XMLHttpRequest.h"
 
 using namespace mozilla;
 using namespace JS;
 using namespace xpc;
 
 using mozilla::dom::DestroyProtoAndIfaceCache;
 using mozilla::dom::IndexedDatabaseManager;
 
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -114,17 +114,17 @@
 #include "nsIDOMEventListener.h"
 #include "nsISelectionController.h"
 
 #include "mozilla/EventDispatcher.h"
 #include "nsISHEntry.h"
 #include "nsISHistory.h"
 #include "nsISHistoryInternal.h"
 #include "nsIWebNavigation.h"
-#include "nsXMLHttpRequest.h"
+#include "mozilla/dom/XMLHttpRequestMainThread.h"
 
 //paint forcing
 #include <stdio.h>
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -56,18 +56,18 @@
 #include "nsIMessageManager.h"
 
 // Transformiix stuff
 #include "mozilla/dom/XPathEvaluator.h"
 #include "txMozillaXSLTProcessor.h"
 #include "txNodeSetAdaptor.h"
 
 #include "mozilla/dom/DOMParser.h"
+#include "mozilla/dom/XMLHttpRequestMainThread.h"
 #include "nsDOMSerializer.h"
-#include "nsXMLHttpRequest.h"
 
 // view stuff
 #include "nsContentCreatorFunctions.h"
 
 #include "mozilla/dom/FormData.h"
 #include "nsHostObjectURI.h"
 #include "nsGlobalWindowCommands.h"
 #include "nsIControllerCommandTable.h"
@@ -303,17 +303,17 @@ using mozilla::dom::NotificationTelemetr
 
 already_AddRefed<nsIPresentationService> NS_CreatePresentationService();
 
 // Factory Constructor
 NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor)
 NS_GENERIC_FACTORY_CONSTRUCTOR(XPathEvaluator)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSerializer)
-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsXMLHttpRequest, Init)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(XMLHttpRequestMainThread, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(FormData)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHostObjectURI)
 NS_GENERIC_FACTORY_CONSTRUCTOR(DOMParser)
 NS_GENERIC_FACTORY_CONSTRUCTOR(Exception)
 NS_GENERIC_FACTORY_CONSTRUCTOR(DOMSessionStorageManager)
 NS_GENERIC_FACTORY_CONSTRUCTOR(DOMLocalStorageManager)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(DOMRequestService,
                                          DOMRequestService::FactoryCreate)
@@ -1068,17 +1068,17 @@ static const mozilla::Module::CIDEntry k
   { &kNS_VIDEODOCUMENT_CID, false, nullptr, CreateVideoDocument },
   { &kNS_STYLESHEETSERVICE_CID, false, nullptr, nsStyleSheetServiceConstructor },
   { &kTRANSFORMIIX_XSLT_PROCESSOR_CID, false, nullptr, txMozillaXSLTProcessorConstructor },
   { &kTRANSFORMIIX_XPATH_EVALUATOR_CID, false, nullptr, XPathEvaluatorConstructor },
   { &kTRANSFORMIIX_NODESET_CID, false, nullptr, txNodeSetAdaptorConstructor },
   { &kNS_XMLSERIALIZER_CID, false, nullptr, nsDOMSerializerConstructor },
   { &kNS_FORMDATA_CID, false, nullptr, FormDataConstructor },
   { &kNS_HOSTOBJECTURI_CID, false, nullptr, nsHostObjectURIConstructor },
-  { &kNS_XMLHTTPREQUEST_CID, false, nullptr, nsXMLHttpRequestConstructor },
+  { &kNS_XMLHTTPREQUEST_CID, false, nullptr, XMLHttpRequestMainThreadConstructor },
   { &kNS_DOMPARSER_CID, false, nullptr, DOMParserConstructor },
   { &kNS_XPCEXCEPTION_CID, false, nullptr, ExceptionConstructor },
   { &kNS_DOMSESSIONSTORAGEMANAGER_CID, false, nullptr, DOMSessionStorageManagerConstructor },
   { &kNS_DOMLOCALSTORAGEMANAGER_CID, false, nullptr, DOMLocalStorageManagerConstructor },
   { &kNS_DOMJSON_CID, false, nullptr, NS_NewJSON },
   { &kNS_TEXTEDITOR_CID, false, nullptr, nsPlaintextEditorConstructor },
   { &kDOMREQUEST_SERVICE_CID, false, nullptr, DOMRequestServiceConstructor },
   { &kQUOTAMANAGER_SERVICE_CID, false, nullptr, QuotaManagerServiceConstructor },
--- a/netwerk/base/LoadInfo.h
+++ b/netwerk/base/LoadInfo.h
@@ -13,20 +13,23 @@
 #include "nsIWeakReferenceUtils.h" // for nsWeakPtr
 #include "nsIURI.h"
 #include "nsTArray.h"
 
 #include "mozilla/BasePrincipal.h"
 
 class nsINode;
 class nsPIDOMWindowOuter;
-class nsXMLHttpRequest;
 
 namespace mozilla {
 
+namespace dom {
+class XMLHttpRequestMainThread;
+}
+
 namespace net {
 class OptionalLoadInfoArgs;
 } // namespace net
 
 namespace ipc {
 // we have to forward declare that function so we can use it as a friend.
 nsresult
 LoadInfoArgsToLoadInfo(const mozilla::net::OptionalLoadInfoArgs& aLoadInfoArgs,
@@ -112,17 +115,17 @@ private:
   ~LoadInfo();
 
   void ComputeIsThirdPartyContext(nsPIDOMWindowOuter* aOuterWindow);
 
   // This function is the *only* function which can change the securityflags
   // of a loadinfo. It only exists because of the XHR code. Don't call it
   // from anywhere else!
   void SetIncludeCookiesSecFlag();
-  friend class ::nsXMLHttpRequest;
+  friend class mozilla::dom::XMLHttpRequestMainThread;
 
   // if you add a member, please also update the copy constructor
   nsCOMPtr<nsIPrincipal>           mLoadingPrincipal;
   nsCOMPtr<nsIPrincipal>           mTriggeringPrincipal;
   nsWeakPtr                        mLoadingContext;
   nsSecurityFlags                  mSecurityFlags;
   nsContentPolicyType              mInternalContentPolicyType;
   LoadTainting                     mTainting;