From 6f29260d28857bb8e0f6997d0324d9e1745d13db Mon Sep 17 00:00:00 2001 From: Catalin Badea Date: Fri, 9 Jun 2017 14:20:16 +0100 Subject: [PATCH] Bug 1344751 - use nsStandardURL for http and https in workers. r=baku --- dom/url/URLWorker.cpp | 333 ++++++++++++++++++++++++++++++++++++------ dom/url/URLWorker.h | 15 +- dom/url/moz.build | 1 + 3 files changed, 297 insertions(+), 52 deletions(-) diff --git a/dom/url/URLWorker.cpp b/dom/url/URLWorker.cpp index 0e66489033e1..768731068048 100644 --- a/dom/url/URLWorker.cpp +++ b/dom/url/URLWorker.cpp @@ -11,8 +11,13 @@ #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; @@ -505,24 +510,6 @@ private: bool mFailed; }; -already_AddRefed -FinishConstructor(JSContext* aCx, WorkerPrivate* aPrivate, - ConstructorRunnable* aRunnable, ErrorResult& aRv) -{ - aRunnable->Dispatch(Terminating, aRv); - if (NS_WARN_IF(aRv.Failed())) { - return nullptr; - } - - RefPtr proxy = aRunnable->GetURLProxy(aRv); - if (NS_WARN_IF(aRv.Failed())) { - return nullptr; - } - - RefPtr url = new URLWorker(aPrivate, proxy); - return url.forget(); -} - /* static */ already_AddRefed URLWorker::Constructor(const GlobalObject& aGlobal, const nsAString& aURL, const Optional& aBase, ErrorResult& aRv) @@ -530,26 +517,20 @@ URLWorker::Constructor(const GlobalObject& aGlobal, const nsAString& aURL, JSContext* cx = aGlobal.Context(); WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); - RefPtr runnable = - new ConstructorRunnable(workerPrivate, aURL, aBase); + RefPtr 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::Constructor(const GlobalObject& aGlobal, const nsAString& aURL, const nsAString& aBase, ErrorResult& aRv) { - JSContext* cx = aGlobal.Context(); - WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); - Optional base; base = &aBase; - RefPtr runnable = - new ConstructorRunnable(workerPrivate, aURL, base); - - return FinishConstructor(cx, workerPrivate, runnable, aRv); + return Constructor(aGlobal, aURL, base, aRv); } /* static */ void @@ -624,12 +605,57 @@ URLWorker::IsValidURL(const GlobalObject& aGlobal, const nsAString& aUrl, 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& 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(aURL); + return; + } + rv = net_ExtractURLScheme(NS_ConvertUTF16toUTF8(aBase.Value()), scheme); + if (NS_WARN_IF(NS_FAILED(rv))) { + aRv.ThrowTypeError(aURL); + return; + } + } + + if (scheme.Equals(NS_LITERAL_CSTRING("http")) || + scheme.Equals(NS_LITERAL_CSTRING("https"))) { + RefPtr baseURL; + if (aBase.WasPassed()) { + baseURL = new nsStandardURL(); + rv = baseURL->SetSpec(NS_ConvertUTF16toUTF8(aBase.Value())); + if (NS_WARN_IF(NS_FAILED(rv))) { + aRv.ThrowTypeError(aBase.Value()); + return; + } + } + mStdURL = new nsStandardURL(); + aRv = mStdURL->Init(nsIStandardURL::URLTYPE_STANDARD, -1, + NS_ConvertUTF16toUTF8(aURL), nullptr, baseURL); + return; + } + + // create url proxy + RefPtr 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) { @@ -648,36 +674,90 @@ URLWorker::~URLWorker() 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 runnable = new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHref, aHref, mURLProxy); - runnable->Dispatch(aRv); } void URLWorker::SetHref(const nsAString& aHref, ErrorResult& aRv) { - RefPtr runnable = - new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHref, aHref, - mURLProxy); - - runnable->Dispatch(aRv); - if (NS_WARN_IF(aRv.Failed())) { - return; - } - - if (runnable->Failed()) { + nsAutoCString scheme; + nsresult rv = net_ExtractURLScheme(NS_ConvertUTF16toUTF8(aHref), scheme); + if (NS_FAILED(rv)) { aRv.ThrowTypeError(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 runnable = + new TeardownURLRunnable(mURLProxy); + mURLProxy = nullptr; + + if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)))) { + return; + } + } + + UpdateURLSearchParams(); + return; + } + + mStdURL = nullptr; + // fallback to using a main thread url proxy + if (mURLProxy) { + RefPtr 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 runnable = + new ConstructorRunnable(mWorkerPrivate, aHref, Optional()); + runnable->Dispatch(Terminating, aRv); + if (NS_WARN_IF(aRv.Failed())) { + 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 runnable = new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterOrigin, aOrigin, mURLProxy); @@ -688,6 +768,18 @@ URLWorker::GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const 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 runnable = new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterProtocol, aProtocol, mURLProxy); @@ -698,6 +790,30 @@ URLWorker::GetProtocol(nsAString& aProtocol, ErrorResult& aRv) const 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 runnable = new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterProtocol, aProtocol, mURLProxy); @@ -707,9 +823,29 @@ URLWorker::SetProtocol(const nsAString& aProtocol, ErrorResult& 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 runnable = new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterUsername, aUsername, mURLProxy); @@ -720,6 +856,9 @@ URLWorker::GetUsername(nsAString& aUsername, ErrorResult& aRv) const void URLWorker::SetUsername(const nsAString& aUsername, ErrorResult& aRv) { + STDURL_SETTER(aUsername, SetUsername); + + MOZ_ASSERT(mURLProxy); RefPtr runnable = new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterUsername, aUsername, mURLProxy); @@ -735,6 +874,9 @@ URLWorker::SetUsername(const nsAString& aUsername, ErrorResult& aRv) void URLWorker::GetPassword(nsAString& aPassword, ErrorResult& aRv) const { + STDURL_GETTER(aPassword, GetPassword); + + MOZ_ASSERT(mURLProxy); RefPtr runnable = new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPassword, aPassword, mURLProxy); @@ -745,6 +887,9 @@ URLWorker::GetPassword(nsAString& aPassword, ErrorResult& aRv) const void URLWorker::SetPassword(const nsAString& aPassword, ErrorResult& aRv) { + STDURL_SETTER(aPassword, SetPassword); + + MOZ_ASSERT(mURLProxy); RefPtr runnable = new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPassword, aPassword, mURLProxy); @@ -760,6 +905,9 @@ URLWorker::SetPassword(const nsAString& aPassword, ErrorResult& aRv) void URLWorker::GetHost(nsAString& aHost, ErrorResult& aRv) const { + STDURL_GETTER(aHost, GetHostPort); + + MOZ_ASSERT(mURLProxy); RefPtr runnable = new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHost, aHost, mURLProxy); @@ -770,6 +918,9 @@ URLWorker::GetHost(nsAString& aHost, ErrorResult& aRv) const void URLWorker::SetHost(const nsAString& aHost, ErrorResult& aRv) { + STDURL_SETTER(aHost, SetHostPort); + + MOZ_ASSERT(mURLProxy); RefPtr runnable = new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHost, aHost, mURLProxy); @@ -785,6 +936,13 @@ URLWorker::SetHost(const nsAString& aHost, ErrorResult& aRv) void URLWorker::GetHostname(nsAString& aHostname, ErrorResult& aRv) const { + aHostname.Truncate(); + if (mStdURL) { + aRv = nsContentUtils::GetHostOrIPv6WithBrackets(mStdURL, aHostname); + return; + } + + MOZ_ASSERT(mURLProxy); RefPtr runnable = new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHostname, aHostname, mURLProxy); @@ -795,6 +953,9 @@ URLWorker::GetHostname(nsAString& aHostname, ErrorResult& aRv) const void URLWorker::SetHostname(const nsAString& aHostname, ErrorResult& aRv) { + STDURL_SETTER(aHostname, SetHost); + + MOZ_ASSERT(mURLProxy); RefPtr runnable = new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHostname, aHostname, mURLProxy); @@ -810,6 +971,20 @@ URLWorker::SetHostname(const nsAString& aHostname, ErrorResult& aRv) 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 runnable = new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPort, aPort, mURLProxy); @@ -820,6 +995,24 @@ URLWorker::GetPort(nsAString& aPort, ErrorResult& aRv) const 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 runnable = new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPort, aPort, mURLProxy); @@ -835,6 +1028,18 @@ URLWorker::SetPort(const nsAString& aPort, ErrorResult& aRv) 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 runnable = new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPathname, aPathname, mURLProxy); @@ -845,6 +1050,9 @@ URLWorker::GetPathname(nsAString& aPathname, ErrorResult& aRv) const void URLWorker::SetPathname(const nsAString& aPathname, ErrorResult& aRv) { + STDURL_SETTER(aPathname, SetFilePath); + + MOZ_ASSERT(mURLProxy); RefPtr runnable = new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPathname, aPathname, mURLProxy); @@ -860,6 +1068,20 @@ URLWorker::SetPathname(const nsAString& aPathname, ErrorResult& aRv) 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 runnable = new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterSearch, aSearch, mURLProxy); @@ -870,6 +1092,18 @@ URLWorker::GetSearch(nsAString& aSearch, ErrorResult& aRv) const 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 runnable = new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHash, aHash, mURLProxy); @@ -880,6 +1114,9 @@ URLWorker::GetHash(nsAString& aHash, ErrorResult& aRv) const void URLWorker::SetHash(const nsAString& aHash, ErrorResult& aRv) { + STDURL_SETTER(aHash, SetRef); + + MOZ_ASSERT(mURLProxy); RefPtr runnable = new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHash, aHash, mURLProxy); @@ -895,6 +1132,13 @@ URLWorker::SetHash(const nsAString& aHash, ErrorResult& aRv) void URLWorker::SetSearchInternal(const nsAString& aSearch, ErrorResult& aRv) { + if (mStdURL) { + // URLMainThread ignores failures here. + mStdURL->SetQuery(NS_ConvertUTF16toUTF8(aSearch)); + return; + } + + MOZ_ASSERT(mURLProxy); RefPtr runnable = new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterSearch, aSearch, mURLProxy); @@ -923,12 +1167,5 @@ URLWorker::UpdateURLSearchParams() } } -URLWorker::URLProxy* -URLWorker::GetURLProxy() const -{ - mWorkerPrivate->AssertIsOnWorkerThread(); - return mURLProxy; -} - } // namespace dom } // namespace mozilla diff --git a/dom/url/URLWorker.h b/dom/url/URLWorker.h index f21ca45e4876..bc5b2eeea620 100644 --- a/dom/url/URLWorker.h +++ b/dom/url/URLWorker.h @@ -11,6 +11,11 @@ #include "URLMainThread.h" namespace mozilla { + +namespace net { +class nsStandardURL; +} + namespace dom { namespace workers { @@ -43,7 +48,11 @@ public: 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& aBase, + ErrorResult& aRv); virtual void GetHref(nsAString& aHref, ErrorResult& aRv) const override; @@ -110,14 +119,12 @@ public: virtual void SetSearchInternal(const nsAString& aSearch, ErrorResult& aRv) override; - URLProxy* - GetURLProxy() const; - private: ~URLWorker(); workers::WorkerPrivate* mWorkerPrivate; RefPtr mURLProxy; + RefPtr mStdURL; }; } // namespace dom diff --git a/dom/url/moz.build b/dom/url/moz.build index a7d349cc3663..14cfb568543e 100644 --- a/dom/url/moz.build +++ b/dom/url/moz.build @@ -21,6 +21,7 @@ UNIFIED_SOURCES += [ LOCAL_INCLUDES += [ '../workers', + '/netwerk/base', ] MOCHITEST_MANIFESTS += ['tests/mochitest.ini']