Bug 1344751 - use nsStandardURL for http and https in workers. r=baku
authorCatalin Badea <catalin.badea392@gmail.com>
Fri, 09 Jun 2017 14:20:16 +0100
changeset 417450 f87c65cf26de00bf9a4504a80c5480521c1337b5
parent 417445 31973778f0ed30ddde8b8aafe15ebf3c1dbe65d2
child 417451 9cb4e53f36aaf29f656bca5bffa3df61011ce8ed
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1344751
milestone56.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 1344751 - use nsStandardURL for http and https in workers. r=baku
dom/url/URLWorker.cpp
dom/url/URLWorker.h
dom/url/moz.build
--- a/dom/url/URLWorker.cpp
+++ b/dom/url/URLWorker.cpp
@@ -6,18 +6,23 @@
 
 #include "URLWorker.h"
 
 #include "mozilla/dom/Blob.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 #include "WorkerScope.h"
+#include "nsStandardURL.h"
+#include "nsURLHelper.h"
 
 namespace mozilla {
+
+using net::nsStandardURL;
+
 namespace dom {
 
 using namespace workers;
 
 // Proxy class to forward all the requests to a URLMainThread object.
 class URLWorker::URLProxy final
 {
 public:
@@ -500,61 +505,37 @@ public:
 
 private:
   const nsString mValue;
   SetterType mType;
   RefPtr<URLWorker::URLProxy> mURLProxy;
   bool mFailed;
 };
 
-already_AddRefed<URLWorker>
-FinishConstructor(JSContext* aCx, WorkerPrivate* aPrivate,
-                  ConstructorRunnable* aRunnable, ErrorResult& aRv)
-{
-  aRunnable->Dispatch(Terminating, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  RefPtr<URLWorker::URLProxy> proxy = aRunnable->GetURLProxy(aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  RefPtr<URLWorker> url = new URLWorker(aPrivate, proxy);
-  return url.forget();
-}
-
 /* static */ already_AddRefed<URLWorker>
 URLWorker::Constructor(const GlobalObject& aGlobal, const nsAString& aURL,
                        const Optional<nsAString>& aBase, ErrorResult& aRv)
 {
   JSContext* cx = aGlobal.Context();
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
 
-  RefPtr<ConstructorRunnable> runnable =
-    new ConstructorRunnable(workerPrivate, aURL, aBase);
+  RefPtr<URLWorker> url = new URLWorker(workerPrivate);
+  url->Init(aURL, aBase, aRv);
 
-  return FinishConstructor(cx, workerPrivate, runnable, aRv);
+  return aRv.Failed() ? nullptr : url.forget();
 }
 
 /* static */ already_AddRefed<URLWorker>
 URLWorker::Constructor(const GlobalObject& aGlobal, const nsAString& aURL,
                        const nsAString& aBase, ErrorResult& aRv)
 {
-  JSContext* cx = aGlobal.Context();
-  WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
-
   Optional<nsAString> base;
   base = &aBase;
 
-  RefPtr<ConstructorRunnable> runnable =
-    new ConstructorRunnable(workerPrivate, aURL, base);
-
-  return FinishConstructor(cx, workerPrivate, runnable, aRv);
+  return Constructor(aGlobal, aURL, base, aRv);
 }
 
 /* static */ void
 URLWorker::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
                            nsAString& aResult, mozilla::ErrorResult& aRv)
 {
   JSContext* cx = aGlobal.Context();
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
@@ -619,22 +600,67 @@ URLWorker::IsValidURL(const GlobalObject
   runnable->Dispatch(Terminating, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return false;
   }
 
   return runnable->IsValidURL();
 }
 
-URLWorker::URLWorker(WorkerPrivate* aWorkerPrivate, URLProxy* aURLProxy)
+URLWorker::URLWorker(WorkerPrivate* aWorkerPrivate)
   : URL(nullptr)
   , mWorkerPrivate(aWorkerPrivate)
-  , mURLProxy(aURLProxy)
 {}
 
+void
+URLWorker::Init(const nsAString& aURL, const Optional<nsAString>& aBase,
+                ErrorResult& aRv)
+{
+  nsAutoCString scheme;
+  nsresult rv = net_ExtractURLScheme(NS_ConvertUTF16toUTF8(aURL), scheme);
+  if (NS_FAILED(rv)) {
+    // this may be a relative URL, check baseURL
+    if (!aBase.WasPassed()) {
+      aRv.ThrowTypeError<MSG_INVALID_URL>(aURL);
+      return;
+    }
+    rv = net_ExtractURLScheme(NS_ConvertUTF16toUTF8(aBase.Value()), scheme);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      aRv.ThrowTypeError<MSG_INVALID_URL>(aURL);
+      return;
+    }
+  }
+
+  if (scheme.Equals(NS_LITERAL_CSTRING("http")) ||
+      scheme.Equals(NS_LITERAL_CSTRING("https"))) {
+    RefPtr<nsStandardURL> baseURL;
+    if (aBase.WasPassed()) {
+      baseURL = new nsStandardURL();
+      rv = baseURL->SetSpec(NS_ConvertUTF16toUTF8(aBase.Value()));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        aRv.ThrowTypeError<MSG_INVALID_URL>(aBase.Value());
+        return;
+      }
+    }
+    mStdURL = new nsStandardURL();
+    aRv = mStdURL->Init(nsIStandardURL::URLTYPE_STANDARD, -1,
+                        NS_ConvertUTF16toUTF8(aURL), nullptr, baseURL);
+    return;
+  }
+
+  // create url proxy
+  RefPtr<ConstructorRunnable> runnable =
+    new ConstructorRunnable(mWorkerPrivate, aURL, aBase);
+  runnable->Dispatch(Terminating, aRv);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
+  mURLProxy = runnable->GetURLProxy(aRv);
+}
+
 URLWorker::~URLWorker()
 {
   if (mURLProxy) {
     mWorkerPrivate->AssertIsOnWorkerThread();
 
     RefPtr<TeardownURLRunnable> runnable =
       new TeardownURLRunnable(mURLProxy);
     mURLProxy = nullptr;
@@ -643,263 +669,481 @@ URLWorker::~URLWorker()
       NS_ERROR("Failed to dispatch teardown runnable!");
     }
   }
 }
 
 void
 URLWorker::GetHref(nsAString& aHref, ErrorResult& aRv) const
 {
+  aHref.Truncate();
+  if (mStdURL) {
+    nsAutoCString href;
+    aRv = mStdURL->GetSpec(href);
+    if (!aRv.Failed()) {
+      CopyUTF8toUTF16(href, aHref);
+    }
+    return;
+  }
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHref, aHref,
                        mURLProxy);
-
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::SetHref(const nsAString& aHref, ErrorResult& aRv)
 {
-  RefPtr<SetterRunnable> runnable =
-    new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHref, aHref,
-                       mURLProxy);
+  nsAutoCString scheme;
+  nsresult rv = net_ExtractURLScheme(NS_ConvertUTF16toUTF8(aHref), scheme);
+  if (NS_FAILED(rv)) {
+    aRv.ThrowTypeError<MSG_INVALID_URL>(aHref);
+    return;
+  }
+
+  if (scheme.Equals(NS_LITERAL_CSTRING("http")) ||
+      scheme.Equals(NS_LITERAL_CSTRING("https"))) {
+    mStdURL = new nsStandardURL();
+    aRv = mStdURL->SetSpec(NS_ConvertUTF16toUTF8(aHref));
+    if (mURLProxy) {
+      mWorkerPrivate->AssertIsOnWorkerThread();
+
+      RefPtr<TeardownURLRunnable> runnable =
+        new TeardownURLRunnable(mURLProxy);
+      mURLProxy = nullptr;
+
+      if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)))) {
+        return;
+      }
+    }
 
-  runnable->Dispatch(aRv);
+    UpdateURLSearchParams();
+    return;
+  }
+
+  mStdURL = nullptr;
+  // fallback to using a main thread url proxy
+  if (mURLProxy) {
+    RefPtr<SetterRunnable> runnable =
+      new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHref, aHref,
+                         mURLProxy);
+
+    runnable->Dispatch(aRv);
+    if (NS_WARN_IF(aRv.Failed())) {
+      return;
+    }
+
+    UpdateURLSearchParams();
+    return;
+  }
+
+  // create the proxy now
+  RefPtr<ConstructorRunnable> runnable =
+    new ConstructorRunnable(mWorkerPrivate, aHref, Optional<nsAString>());
+  runnable->Dispatch(Terminating, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
-
-  if (runnable->Failed()) {
-    aRv.ThrowTypeError<MSG_INVALID_URL>(aHref);
-    return;
-  }
+  mURLProxy = runnable->GetURLProxy(aRv);
 
   UpdateURLSearchParams();
 }
 
 void
 URLWorker::GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const
 {
+  if (mStdURL) {
+    nsContentUtils::GetUTFOrigin(mStdURL, aOrigin);
+    return;
+  }
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterOrigin, aOrigin,
                        mURLProxy);
 
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::GetProtocol(nsAString& aProtocol, ErrorResult& aRv) const
 {
+  aProtocol.Truncate();
+  nsAutoCString protocol;
+  if (mStdURL) {
+    if (NS_SUCCEEDED(mStdURL->GetScheme(protocol))) {
+      CopyASCIItoUTF16(protocol, aProtocol);
+      aProtocol.Append(char16_t(':'));
+    }
+
+    return;
+  }
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterProtocol, aProtocol,
                        mURLProxy);
 
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv)
 {
+  if (mStdURL) {
+    nsAString::const_iterator start, end;
+    aProtocol.BeginReading(start);
+    aProtocol.EndReading(end);
+    nsAString::const_iterator iter(start);
+
+    FindCharInReadable(':', iter, end);
+
+    nsresult rv = mStdURL->SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return;
+    }
+
+    nsAutoCString href;
+    rv = mStdURL->GetSpec(href);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return;
+    }
+
+    SetHref(NS_ConvertUTF8toUTF16(href), aRv);
+    return;
+  }
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<SetterRunnable> runnable =
     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterProtocol,
                        aProtocol, mURLProxy);
 
   runnable->Dispatch(aRv);
 
   MOZ_ASSERT(!runnable->Failed());
 }
 
+#define STDURL_GETTER(value, method)    \
+  if (mStdURL) {                        \
+    value.Truncate();                   \
+    nsAutoCString tmp;                  \
+    nsresult rv = mStdURL->method(tmp); \
+    if (NS_SUCCEEDED(rv)) {             \
+      CopyUTF8toUTF16(tmp, value);      \
+    }                                   \
+    return;                             \
+  }
+
+#define STDURL_SETTER(value, method)                     \
+  if (mStdURL) {                                         \
+    aRv = mStdURL->method(NS_ConvertUTF16toUTF8(value)); \
+    return;                                              \
+  }
+
 void
 URLWorker::GetUsername(nsAString& aUsername, ErrorResult& aRv) const
 {
+  STDURL_GETTER(aUsername, GetUsername);
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterUsername, aUsername,
                        mURLProxy);
 
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::SetUsername(const nsAString& aUsername, ErrorResult& aRv)
 {
+  STDURL_SETTER(aUsername, SetUsername);
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<SetterRunnable> runnable =
     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterUsername,
                        aUsername, mURLProxy);
 
   runnable->Dispatch(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   MOZ_ASSERT(!runnable->Failed());
 }
 
 void
 URLWorker::GetPassword(nsAString& aPassword, ErrorResult& aRv) const
 {
+  STDURL_GETTER(aPassword, GetPassword);
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPassword, aPassword,
                        mURLProxy);
 
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::SetPassword(const nsAString& aPassword, ErrorResult& aRv)
 {
+  STDURL_SETTER(aPassword, SetPassword);
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<SetterRunnable> runnable =
     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPassword,
                        aPassword, mURLProxy);
 
   runnable->Dispatch(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   MOZ_ASSERT(!runnable->Failed());
 }
 
 void
 URLWorker::GetHost(nsAString& aHost, ErrorResult& aRv) const
 {
+  STDURL_GETTER(aHost, GetHostPort);
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHost, aHost,
                        mURLProxy);
 
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::SetHost(const nsAString& aHost, ErrorResult& aRv)
 {
+  STDURL_SETTER(aHost, SetHostPort);
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<SetterRunnable> runnable =
     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHost,
                        aHost, mURLProxy);
 
   runnable->Dispatch(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   MOZ_ASSERT(!runnable->Failed());
 }
 
 void
 URLWorker::GetHostname(nsAString& aHostname, ErrorResult& aRv) const
 {
+  aHostname.Truncate();
+  if (mStdURL) {
+    aRv = nsContentUtils::GetHostOrIPv6WithBrackets(mStdURL, aHostname);
+    return;
+  }
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHostname, aHostname,
                        mURLProxy);
 
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::SetHostname(const nsAString& aHostname, ErrorResult& aRv)
 {
+  STDURL_SETTER(aHostname, SetHost);
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<SetterRunnable> runnable =
     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHostname,
                        aHostname, mURLProxy);
 
   runnable->Dispatch(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   MOZ_ASSERT(!runnable->Failed());
 }
 
 void
 URLWorker::GetPort(nsAString& aPort, ErrorResult& aRv) const
 {
+  aPort.Truncate();
+
+  if (mStdURL) {
+    int32_t port;
+    nsresult rv = mStdURL->GetPort(&port);
+    if (NS_SUCCEEDED(rv) && port != -1) {
+      nsAutoString portStr;
+      portStr.AppendInt(port, 10);
+      aPort.Assign(portStr);
+    }
+    return;
+  }
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPort, aPort,
                        mURLProxy);
 
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::SetPort(const nsAString& aPort, ErrorResult& aRv)
 {
+  if (mStdURL) {
+    nsresult rv;
+    nsAutoString portStr(aPort);
+    int32_t port = -1;
+
+    // nsIURI uses -1 as default value.
+    if (!portStr.IsEmpty()) {
+      port = portStr.ToInteger(&rv);
+      if (NS_FAILED(rv)) {
+        return;
+      }
+    }
+
+    mStdURL->SetPort(port);
+    return;
+  }
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<SetterRunnable> runnable =
     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPort,
                        aPort, mURLProxy);
 
   runnable->Dispatch(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   MOZ_ASSERT(!runnable->Failed());
 }
 
 void
 URLWorker::GetPathname(nsAString& aPathname, ErrorResult& aRv) const
 {
+  aPathname.Truncate();
+
+  if (mStdURL) {
+    nsAutoCString file;
+    nsresult rv = mStdURL->GetFilePath(file);
+    if (NS_SUCCEEDED(rv)) {
+      CopyUTF8toUTF16(file, aPathname);
+    }
+    return;
+  }
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPathname,
                        aPathname, mURLProxy);
 
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::SetPathname(const nsAString& aPathname, ErrorResult& aRv)
 {
+  STDURL_SETTER(aPathname, SetFilePath);
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<SetterRunnable> runnable =
     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPathname,
                        aPathname, mURLProxy);
 
   runnable->Dispatch(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   MOZ_ASSERT(!runnable->Failed());
 }
 
 void
 URLWorker::GetSearch(nsAString& aSearch, ErrorResult& aRv) const
 {
+  aSearch.Truncate();
+
+  if (mStdURL) {
+    nsAutoCString search;
+    nsresult rv;
+
+    rv = mStdURL->GetQuery(search);
+    if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
+      CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch);
+    }
+    return;
+  }
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterSearch, aSearch,
                        mURLProxy);
 
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::GetHash(nsAString& aHash, ErrorResult& aRv) const
 {
+  aHash.Truncate();
+  if (mStdURL) {
+    nsAutoCString ref;
+    nsresult rv = mStdURL->GetRef(ref);
+    if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
+      aHash.Assign(char16_t('#'));
+      AppendUTF8toUTF16(ref, aHash);
+    }
+    return;
+  }
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHash, aHash,
                        mURLProxy);
 
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::SetHash(const nsAString& aHash, ErrorResult& aRv)
 {
+  STDURL_SETTER(aHash, SetRef);
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<SetterRunnable> runnable =
     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHash,
                        aHash, mURLProxy);
 
   runnable->Dispatch(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   MOZ_ASSERT(!runnable->Failed());
 }
 
 void
 URLWorker::SetSearchInternal(const nsAString& aSearch, ErrorResult& aRv)
 {
+  if (mStdURL) {
+    // URLMainThread ignores failures here.
+    mStdURL->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
+    return;
+  }
+
+  MOZ_ASSERT(mURLProxy);
   RefPtr<SetterRunnable> runnable =
     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterSearch,
                        aSearch, mURLProxy);
 
   runnable->Dispatch(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
@@ -918,17 +1162,10 @@ URLWorker::UpdateURLSearchParams()
     if (NS_WARN_IF(rv.Failed())) {
       rv.SuppressException();
     }
 
     mSearchParams->ParseInput(NS_ConvertUTF16toUTF8(Substring(search, 1)));
   }
 }
 
-URLWorker::URLProxy*
-URLWorker::GetURLProxy() const
-{
-  mWorkerPrivate->AssertIsOnWorkerThread();
-  return mURLProxy;
-}
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/url/URLWorker.h
+++ b/dom/url/URLWorker.h
@@ -6,16 +6,21 @@
 
 #ifndef mozilla_dom_URLWorker_h
 #define mozilla_dom_URLWorker_h
 
 #include "URL.h"
 #include "URLMainThread.h"
 
 namespace mozilla {
+
+namespace net {
+class nsStandardURL;
+}
+
 namespace dom {
 
 namespace workers {
 class WorkerPrivate;
 }
 
 // URLWorker implements the URL object in workers.
 class URLWorker final : public URL
@@ -38,17 +43,21 @@ public:
   static void
   RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aUrl,
                   ErrorResult& aRv);
 
   static bool
   IsValidURL(const GlobalObject& aGlobal, const nsAString& aUrl,
              ErrorResult& aRv);
 
-  URLWorker(workers::WorkerPrivate* aWorkerPrivate, URLProxy* aURLProxy);
+  explicit URLWorker(workers::WorkerPrivate* aWorkerPrivate);
+
+  void
+  Init(const nsAString& aURL, const Optional<nsAString>& aBase,
+       ErrorResult& aRv);
 
   virtual void
   GetHref(nsAString& aHref, ErrorResult& aRv) const override;
 
   virtual void
   SetHref(const nsAString& aHref, ErrorResult& aRv) override;
 
   virtual void
@@ -105,22 +114,20 @@ public:
   virtual void
   SetHash(const nsAString& aHash, ErrorResult& aRv) override;
 
   virtual void UpdateURLSearchParams() override;
 
   virtual void
   SetSearchInternal(const nsAString& aSearch, ErrorResult& aRv) override;
 
-  URLProxy*
-  GetURLProxy() const;
-
 private:
   ~URLWorker();
 
   workers::WorkerPrivate* mWorkerPrivate;
   RefPtr<URLProxy> mURLProxy;
+  RefPtr<net::nsStandardURL> mStdURL;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_URLWorker_h
--- a/dom/url/moz.build
+++ b/dom/url/moz.build
@@ -16,16 +16,17 @@ UNIFIED_SOURCES += [
     'URL.cpp',
     'URLMainThread.cpp',
     'URLSearchParams.cpp',
     'URLWorker.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '../workers',
+    '/netwerk/base',
 ]
 
 MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += [ 'tests/chrome.ini' ]
 BROWSER_CHROME_MANIFESTS += [ 'tests/browser.ini' ]
 
 include('/ipc/chromium/chromium-config.mozbuild')