michael@0: /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "URL.h" michael@0: michael@0: #include "nsIDocument.h" michael@0: #include "nsIDOMFile.h" michael@0: #include "nsIIOService.h" michael@0: #include "nsPIDOMWindow.h" michael@0: michael@0: #include "mozilla/dom/URL.h" michael@0: #include "mozilla/dom/URLBinding.h" michael@0: #include "mozilla/dom/URLSearchParams.h" michael@0: #include "nsGlobalWindow.h" michael@0: #include "nsHostObjectProtocolHandler.h" michael@0: #include "nsNetCID.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: #include "nsThreadUtils.h" michael@0: michael@0: #include "File.h" michael@0: #include "WorkerPrivate.h" michael@0: #include "WorkerRunnable.h" michael@0: michael@0: BEGIN_WORKERS_NAMESPACE michael@0: using mozilla::dom::GlobalObject; michael@0: michael@0: class URLProxy MOZ_FINAL michael@0: { michael@0: public: michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(URLProxy) michael@0: michael@0: URLProxy(mozilla::dom::URL* aURL) michael@0: : mURL(aURL) michael@0: { michael@0: AssertIsOnMainThread(); michael@0: } michael@0: michael@0: mozilla::dom::URL* URL() michael@0: { michael@0: return mURL; michael@0: } michael@0: michael@0: nsIURI* URI() michael@0: { michael@0: return mURL->GetURI(); michael@0: } michael@0: michael@0: void ReleaseURI() michael@0: { michael@0: AssertIsOnMainThread(); michael@0: mURL = nullptr; michael@0: } michael@0: michael@0: private: michael@0: // Private destructor, to discourage deletion outside of Release(): michael@0: ~URLProxy() michael@0: { michael@0: MOZ_ASSERT(!mURL); michael@0: } michael@0: michael@0: nsRefPtr mURL; michael@0: }; michael@0: michael@0: // Base class for the URL runnable objects. michael@0: class URLRunnable : public nsRunnable michael@0: { michael@0: protected: michael@0: WorkerPrivate* mWorkerPrivate; michael@0: nsCOMPtr mSyncLoopTarget; michael@0: michael@0: protected: michael@0: URLRunnable(WorkerPrivate* aWorkerPrivate) michael@0: : mWorkerPrivate(aWorkerPrivate) michael@0: { michael@0: mWorkerPrivate->AssertIsOnWorkerThread(); michael@0: } michael@0: michael@0: public: michael@0: bool michael@0: Dispatch(JSContext* aCx) michael@0: { michael@0: mWorkerPrivate->AssertIsOnWorkerThread(); michael@0: michael@0: AutoSyncLoopHolder syncLoop(mWorkerPrivate); michael@0: michael@0: mSyncLoopTarget = syncLoop.EventTarget(); michael@0: michael@0: if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) { michael@0: JS_ReportError(aCx, "Failed to dispatch to main thread!"); michael@0: return false; michael@0: } michael@0: michael@0: return syncLoop.Run(); michael@0: } michael@0: michael@0: private: michael@0: NS_IMETHOD Run() michael@0: { michael@0: AssertIsOnMainThread(); michael@0: michael@0: MainThreadRun(); michael@0: michael@0: nsRefPtr response = michael@0: new MainThreadStopSyncLoopRunnable(mWorkerPrivate, michael@0: mSyncLoopTarget.forget(), michael@0: true); michael@0: if (!response->Dispatch(nullptr)) { michael@0: NS_WARNING("Failed to dispatch response!"); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: protected: michael@0: virtual void michael@0: MainThreadRun() = 0; michael@0: }; michael@0: michael@0: // This class creates an URL from a DOM Blob on the main thread. michael@0: class CreateURLRunnable : public URLRunnable michael@0: { michael@0: private: michael@0: nsIDOMBlob* mBlob; michael@0: nsString& mURL; michael@0: michael@0: public: michael@0: CreateURLRunnable(WorkerPrivate* aWorkerPrivate, nsIDOMBlob* aBlob, michael@0: const mozilla::dom::objectURLOptions& aOptions, michael@0: nsString& aURL) michael@0: : URLRunnable(aWorkerPrivate), michael@0: mBlob(aBlob), michael@0: mURL(aURL) michael@0: { michael@0: MOZ_ASSERT(aBlob); michael@0: } michael@0: michael@0: void michael@0: MainThreadRun() michael@0: { michael@0: AssertIsOnMainThread(); michael@0: michael@0: nsCOMPtr principal; michael@0: nsIDocument* doc = nullptr; michael@0: michael@0: nsCOMPtr window = mWorkerPrivate->GetWindow(); michael@0: if (window) { michael@0: doc = window->GetExtantDoc(); michael@0: if (!doc) { michael@0: SetDOMStringToNull(mURL); michael@0: return; michael@0: } michael@0: michael@0: principal = doc->NodePrincipal(); michael@0: } else { michael@0: MOZ_ASSERT_IF(!mWorkerPrivate->GetParent(), mWorkerPrivate->IsChromeWorker()); michael@0: principal = mWorkerPrivate->GetPrincipal(); michael@0: } michael@0: michael@0: nsCString url; michael@0: nsresult rv = nsHostObjectProtocolHandler::AddDataEntry( michael@0: NS_LITERAL_CSTRING(BLOBURI_SCHEME), michael@0: mBlob, principal, url); michael@0: michael@0: if (NS_FAILED(rv)) { michael@0: NS_WARNING("Failed to add data entry for the blob!"); michael@0: SetDOMStringToNull(mURL); michael@0: return; michael@0: } michael@0: michael@0: if (doc) { michael@0: doc->RegisterHostObjectUri(url); michael@0: } else { michael@0: mWorkerPrivate->RegisterHostObjectURI(url); michael@0: } michael@0: michael@0: mURL = NS_ConvertUTF8toUTF16(url); michael@0: } michael@0: }; michael@0: michael@0: // This class revokes an URL on the main thread. michael@0: class RevokeURLRunnable : public URLRunnable michael@0: { michael@0: private: michael@0: const nsString mURL; michael@0: michael@0: public: michael@0: RevokeURLRunnable(WorkerPrivate* aWorkerPrivate, michael@0: const nsAString& aURL) michael@0: : URLRunnable(aWorkerPrivate), michael@0: mURL(aURL) michael@0: {} michael@0: michael@0: void michael@0: MainThreadRun() michael@0: { michael@0: AssertIsOnMainThread(); michael@0: michael@0: nsCOMPtr principal; michael@0: nsIDocument* doc = nullptr; michael@0: michael@0: nsCOMPtr window = mWorkerPrivate->GetWindow(); michael@0: if (window) { michael@0: doc = window->GetExtantDoc(); michael@0: if (!doc) { michael@0: return; michael@0: } michael@0: michael@0: principal = doc->NodePrincipal(); michael@0: } else { michael@0: MOZ_ASSERT_IF(!mWorkerPrivate->GetParent(), mWorkerPrivate->IsChromeWorker()); michael@0: principal = mWorkerPrivate->GetPrincipal(); michael@0: } michael@0: michael@0: NS_ConvertUTF16toUTF8 url(mURL); michael@0: michael@0: nsIPrincipal* urlPrincipal = michael@0: nsHostObjectProtocolHandler::GetDataEntryPrincipal(url); michael@0: michael@0: bool subsumes; michael@0: if (urlPrincipal && michael@0: NS_SUCCEEDED(principal->Subsumes(urlPrincipal, &subsumes)) && michael@0: subsumes) { michael@0: if (doc) { michael@0: doc->UnregisterHostObjectUri(url); michael@0: } michael@0: michael@0: nsHostObjectProtocolHandler::RemoveDataEntry(url); michael@0: } michael@0: michael@0: if (!window) { michael@0: mWorkerPrivate->UnregisterHostObjectURI(url); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: // This class creates a URL object on the main thread. michael@0: class ConstructorRunnable : public URLRunnable michael@0: { michael@0: private: michael@0: const nsString mURL; michael@0: michael@0: const nsString mBase; michael@0: nsRefPtr mBaseProxy; michael@0: mozilla::ErrorResult& mRv; michael@0: michael@0: nsRefPtr mRetval; michael@0: michael@0: public: michael@0: ConstructorRunnable(WorkerPrivate* aWorkerPrivate, michael@0: const nsAString& aURL, const nsAString& aBase, michael@0: mozilla::ErrorResult& aRv) michael@0: : URLRunnable(aWorkerPrivate) michael@0: , mURL(aURL) michael@0: , mBase(aBase) michael@0: , mRv(aRv) michael@0: { michael@0: mWorkerPrivate->AssertIsOnWorkerThread(); michael@0: } michael@0: michael@0: ConstructorRunnable(WorkerPrivate* aWorkerPrivate, michael@0: const nsAString& aURL, URLProxy* aBaseProxy, michael@0: mozilla::ErrorResult& aRv) michael@0: : URLRunnable(aWorkerPrivate) michael@0: , mURL(aURL) michael@0: , mBaseProxy(aBaseProxy) michael@0: , mRv(aRv) michael@0: { michael@0: mWorkerPrivate->AssertIsOnWorkerThread(); michael@0: } michael@0: michael@0: void michael@0: MainThreadRun() michael@0: { michael@0: AssertIsOnMainThread(); michael@0: michael@0: nsresult rv; michael@0: nsCOMPtr ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv)); michael@0: if (NS_FAILED(rv)) { michael@0: mRv.Throw(rv); michael@0: return; michael@0: } michael@0: michael@0: nsCOMPtr baseURL; michael@0: michael@0: if (!mBaseProxy) { michael@0: rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mBase), nullptr, nullptr, michael@0: getter_AddRefs(baseURL)); michael@0: if (NS_FAILED(rv)) { michael@0: mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); michael@0: return; michael@0: } michael@0: } else { michael@0: baseURL = mBaseProxy->URI(); michael@0: } michael@0: michael@0: nsCOMPtr url; michael@0: rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mURL), nullptr, baseURL, michael@0: getter_AddRefs(url)); michael@0: if (NS_FAILED(rv)) { michael@0: mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); michael@0: return; michael@0: } michael@0: michael@0: mRetval = new URLProxy(new mozilla::dom::URL(url)); michael@0: } michael@0: michael@0: URLProxy* michael@0: GetURLProxy() michael@0: { michael@0: return mRetval; michael@0: } michael@0: }; michael@0: michael@0: class TeardownURLRunnable : public nsRunnable michael@0: { michael@0: public: michael@0: TeardownURLRunnable(URLProxy* aURLProxy) michael@0: : mURLProxy(aURLProxy) michael@0: { michael@0: } michael@0: michael@0: NS_IMETHOD Run() michael@0: { michael@0: AssertIsOnMainThread(); michael@0: michael@0: mURLProxy->ReleaseURI(); michael@0: mURLProxy = nullptr; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: private: michael@0: nsRefPtr mURLProxy; michael@0: }; michael@0: michael@0: // This class is the generic getter for any URL property. michael@0: class GetterRunnable : public URLRunnable michael@0: { michael@0: public: michael@0: enum GetterType { michael@0: GetterHref, michael@0: GetterOrigin, michael@0: GetterProtocol, michael@0: GetterUsername, michael@0: GetterPassword, michael@0: GetterHost, michael@0: GetterHostname, michael@0: GetterPort, michael@0: GetterPathname, michael@0: GetterSearch, michael@0: GetterHash, michael@0: }; michael@0: michael@0: GetterRunnable(WorkerPrivate* aWorkerPrivate, michael@0: GetterType aType, nsString& aValue, michael@0: URLProxy* aURLProxy) michael@0: : URLRunnable(aWorkerPrivate) michael@0: , mValue(aValue) michael@0: , mType(aType) michael@0: , mURLProxy(aURLProxy) michael@0: { michael@0: mWorkerPrivate->AssertIsOnWorkerThread(); michael@0: } michael@0: michael@0: void michael@0: MainThreadRun() michael@0: { michael@0: AssertIsOnMainThread(); michael@0: michael@0: switch (mType) { michael@0: case GetterHref: michael@0: mURLProxy->URL()->GetHref(mValue); michael@0: break; michael@0: michael@0: case GetterOrigin: michael@0: mURLProxy->URL()->GetOrigin(mValue); michael@0: break; michael@0: michael@0: case GetterProtocol: michael@0: mURLProxy->URL()->GetProtocol(mValue); michael@0: break; michael@0: michael@0: case GetterUsername: michael@0: mURLProxy->URL()->GetUsername(mValue); michael@0: break; michael@0: michael@0: case GetterPassword: michael@0: mURLProxy->URL()->GetPassword(mValue); michael@0: break; michael@0: michael@0: case GetterHost: michael@0: mURLProxy->URL()->GetHost(mValue); michael@0: break; michael@0: michael@0: case GetterHostname: michael@0: mURLProxy->URL()->GetHostname(mValue); michael@0: break; michael@0: michael@0: case GetterPort: michael@0: mURLProxy->URL()->GetPort(mValue); michael@0: break; michael@0: michael@0: case GetterPathname: michael@0: mURLProxy->URL()->GetPathname(mValue); michael@0: break; michael@0: michael@0: case GetterSearch: michael@0: mURLProxy->URL()->GetSearch(mValue); michael@0: break; michael@0: michael@0: case GetterHash: michael@0: mURLProxy->URL()->GetHash(mValue); michael@0: break; michael@0: } michael@0: } michael@0: michael@0: private: michael@0: nsString& mValue; michael@0: GetterType mType; michael@0: nsRefPtr mURLProxy; michael@0: }; michael@0: michael@0: // This class is the generic setter for any URL property. michael@0: class SetterRunnable : public URLRunnable michael@0: { michael@0: public: michael@0: enum SetterType { michael@0: SetterHref, michael@0: SetterProtocol, michael@0: SetterUsername, michael@0: SetterPassword, michael@0: SetterHost, michael@0: SetterHostname, michael@0: SetterPort, michael@0: SetterPathname, michael@0: SetterSearch, michael@0: SetterHash, michael@0: }; michael@0: michael@0: SetterRunnable(WorkerPrivate* aWorkerPrivate, michael@0: SetterType aType, const nsAString& aValue, michael@0: URLProxy* aURLProxy, mozilla::ErrorResult& aRv) michael@0: : URLRunnable(aWorkerPrivate) michael@0: , mValue(aValue) michael@0: , mType(aType) michael@0: , mURLProxy(aURLProxy) michael@0: , mRv(aRv) michael@0: { michael@0: mWorkerPrivate->AssertIsOnWorkerThread(); michael@0: } michael@0: michael@0: void michael@0: MainThreadRun() michael@0: { michael@0: AssertIsOnMainThread(); michael@0: michael@0: switch (mType) { michael@0: case SetterHref: michael@0: mURLProxy->URL()->SetHref(mValue, mRv); michael@0: break; michael@0: michael@0: case SetterProtocol: michael@0: mURLProxy->URL()->SetProtocol(mValue); michael@0: break; michael@0: michael@0: case SetterUsername: michael@0: mURLProxy->URL()->SetUsername(mValue); michael@0: break; michael@0: michael@0: case SetterPassword: michael@0: mURLProxy->URL()->SetPassword(mValue); michael@0: break; michael@0: michael@0: case SetterHost: michael@0: mURLProxy->URL()->SetHost(mValue); michael@0: break; michael@0: michael@0: case SetterHostname: michael@0: mURLProxy->URL()->SetHostname(mValue); michael@0: break; michael@0: michael@0: case SetterPort: michael@0: mURLProxy->URL()->SetPort(mValue); michael@0: break; michael@0: michael@0: case SetterPathname: michael@0: mURLProxy->URL()->SetPathname(mValue); michael@0: break; michael@0: michael@0: case SetterSearch: michael@0: mURLProxy->URL()->SetSearch(mValue); michael@0: break; michael@0: michael@0: case SetterHash: michael@0: mURLProxy->URL()->SetHash(mValue); michael@0: break; michael@0: } michael@0: } michael@0: michael@0: private: michael@0: const nsString mValue; michael@0: SetterType mType; michael@0: nsRefPtr mURLProxy; michael@0: mozilla::ErrorResult& mRv; michael@0: }; michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION(URL, mSearchParams) michael@0: michael@0: // The reason for using worker::URL is to have different refcnt logging than michael@0: // for main thread URL. michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(workers::URL) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(workers::URL) michael@0: michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URL) michael@0: NS_INTERFACE_MAP_ENTRY(nsISupports) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: // static michael@0: URL* michael@0: URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl, michael@0: URL& aBase, ErrorResult& aRv) michael@0: { michael@0: JSContext* cx = aGlobal.GetContext(); michael@0: WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); michael@0: michael@0: nsRefPtr runnable = michael@0: new ConstructorRunnable(workerPrivate, aUrl, aBase.GetURLProxy(), aRv); michael@0: michael@0: if (!runnable->Dispatch(cx)) { michael@0: JS_ReportPendingException(cx); michael@0: } michael@0: michael@0: nsRefPtr proxy = runnable->GetURLProxy(); michael@0: if (!proxy) { michael@0: aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); michael@0: return nullptr; michael@0: } michael@0: michael@0: return new URL(workerPrivate, proxy); michael@0: } michael@0: michael@0: // static michael@0: URL* michael@0: URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl, michael@0: const nsAString& aBase, ErrorResult& aRv) michael@0: { michael@0: JSContext* cx = aGlobal.GetContext(); michael@0: WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); michael@0: michael@0: nsRefPtr runnable = michael@0: new ConstructorRunnable(workerPrivate, aUrl, aBase, aRv); michael@0: michael@0: if (!runnable->Dispatch(cx)) { michael@0: JS_ReportPendingException(cx); michael@0: } michael@0: michael@0: nsRefPtr proxy = runnable->GetURLProxy(); michael@0: if (!proxy) { michael@0: aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); michael@0: return nullptr; michael@0: } michael@0: michael@0: return new URL(workerPrivate, proxy); michael@0: } michael@0: michael@0: URL::URL(WorkerPrivate* aWorkerPrivate, URLProxy* aURLProxy) michael@0: : mWorkerPrivate(aWorkerPrivate) michael@0: , mURLProxy(aURLProxy) michael@0: { michael@0: MOZ_COUNT_CTOR(workers::URL); michael@0: } michael@0: michael@0: URL::~URL() michael@0: { michael@0: MOZ_COUNT_DTOR(workers::URL); michael@0: michael@0: if (mURLProxy) { michael@0: nsRefPtr runnable = michael@0: new TeardownURLRunnable(mURLProxy); michael@0: mURLProxy = nullptr; michael@0: michael@0: if (NS_FAILED(NS_DispatchToMainThread(runnable))) { michael@0: NS_ERROR("Failed to dispatch teardown runnable!"); michael@0: } michael@0: } michael@0: } michael@0: michael@0: JSObject* michael@0: URL::WrapObject(JSContext* aCx) michael@0: { michael@0: return URLBinding_workers::Wrap(aCx, this); michael@0: } michael@0: michael@0: void michael@0: URL::GetHref(nsString& aHref) const michael@0: { michael@0: nsRefPtr runnable = michael@0: new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHref, aHref, michael@0: mURLProxy); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::SetHref(const nsAString& aHref, ErrorResult& aRv) michael@0: { michael@0: nsRefPtr runnable = michael@0: new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHref, aHref, michael@0: mURLProxy, aRv); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: michael@0: UpdateURLSearchParams(); michael@0: } michael@0: michael@0: void michael@0: URL::GetOrigin(nsString& aOrigin) const michael@0: { michael@0: nsRefPtr runnable = michael@0: new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterOrigin, aOrigin, michael@0: mURLProxy); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::GetProtocol(nsString& aProtocol) const michael@0: { michael@0: nsRefPtr runnable = michael@0: new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterProtocol, aProtocol, michael@0: mURLProxy); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::SetProtocol(const nsAString& aProtocol) michael@0: { michael@0: ErrorResult rv; michael@0: nsRefPtr runnable = michael@0: new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterProtocol, michael@0: aProtocol, mURLProxy, rv); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::GetUsername(nsString& aUsername) const michael@0: { michael@0: nsRefPtr runnable = michael@0: new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterUsername, aUsername, michael@0: mURLProxy); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::SetUsername(const nsAString& aUsername) michael@0: { michael@0: ErrorResult rv; michael@0: nsRefPtr runnable = michael@0: new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterUsername, michael@0: aUsername, mURLProxy, rv); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::GetPassword(nsString& aPassword) const michael@0: { michael@0: nsRefPtr runnable = michael@0: new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPassword, aPassword, michael@0: mURLProxy); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::SetPassword(const nsAString& aPassword) michael@0: { michael@0: ErrorResult rv; michael@0: nsRefPtr runnable = michael@0: new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPassword, michael@0: aPassword, mURLProxy, rv); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::GetHost(nsString& aHost) const michael@0: { michael@0: nsRefPtr runnable = michael@0: new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHost, aHost, michael@0: mURLProxy); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::SetHost(const nsAString& aHost) michael@0: { michael@0: ErrorResult rv; michael@0: nsRefPtr runnable = michael@0: new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHost, michael@0: aHost, mURLProxy, rv); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::GetHostname(nsString& aHostname) const michael@0: { michael@0: nsRefPtr runnable = michael@0: new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHostname, aHostname, michael@0: mURLProxy); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::SetHostname(const nsAString& aHostname) michael@0: { michael@0: ErrorResult rv; michael@0: nsRefPtr runnable = michael@0: new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHostname, michael@0: aHostname, mURLProxy, rv); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::GetPort(nsString& aPort) const michael@0: { michael@0: nsRefPtr runnable = michael@0: new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPort, aPort, michael@0: mURLProxy); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::SetPort(const nsAString& aPort) michael@0: { michael@0: ErrorResult rv; michael@0: nsRefPtr runnable = michael@0: new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPort, michael@0: aPort, mURLProxy, rv); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::GetPathname(nsString& aPathname) const michael@0: { michael@0: nsRefPtr runnable = michael@0: new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPathname, aPathname, michael@0: mURLProxy); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::SetPathname(const nsAString& aPathname) michael@0: { michael@0: ErrorResult rv; michael@0: nsRefPtr runnable = michael@0: new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPathname, michael@0: aPathname, mURLProxy, rv); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::GetSearch(nsString& aSearch) const michael@0: { michael@0: nsRefPtr runnable = michael@0: new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterSearch, aSearch, michael@0: mURLProxy); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::SetSearch(const nsAString& aSearch) michael@0: { michael@0: SetSearchInternal(aSearch); michael@0: UpdateURLSearchParams(); michael@0: } michael@0: michael@0: void michael@0: URL::SetSearchInternal(const nsAString& aSearch) michael@0: { michael@0: ErrorResult rv; michael@0: nsRefPtr runnable = michael@0: new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterSearch, michael@0: aSearch, mURLProxy, rv); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: mozilla::dom::URLSearchParams* michael@0: URL::SearchParams() michael@0: { michael@0: CreateSearchParamsIfNeeded(); michael@0: return mSearchParams; michael@0: } michael@0: michael@0: void michael@0: URL::SetSearchParams(URLSearchParams& aSearchParams) michael@0: { michael@0: if (mSearchParams) { michael@0: mSearchParams->RemoveObserver(this); michael@0: } michael@0: michael@0: mSearchParams = &aSearchParams; michael@0: mSearchParams->AddObserver(this); michael@0: michael@0: nsString search; michael@0: mSearchParams->Serialize(search); michael@0: SetSearchInternal(search); michael@0: } michael@0: michael@0: void michael@0: URL::GetHash(nsString& aHash) const michael@0: { michael@0: nsRefPtr runnable = michael@0: new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHash, aHash, michael@0: mURLProxy); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::SetHash(const nsAString& aHash) michael@0: { michael@0: ErrorResult rv; michael@0: nsRefPtr runnable = michael@0: new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHash, michael@0: aHash, mURLProxy, rv); michael@0: michael@0: if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) { michael@0: JS_ReportPendingException(mWorkerPrivate->GetJSContext()); michael@0: } michael@0: } michael@0: michael@0: // static michael@0: void michael@0: URL::CreateObjectURL(const GlobalObject& aGlobal, JSObject* aBlob, michael@0: const mozilla::dom::objectURLOptions& aOptions, michael@0: nsString& aResult, mozilla::ErrorResult& aRv) michael@0: { michael@0: JSContext* cx = aGlobal.GetContext(); michael@0: WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); michael@0: michael@0: nsCOMPtr blob = file::GetDOMBlobFromJSObject(aBlob); michael@0: if (!blob) { michael@0: SetDOMStringToNull(aResult); michael@0: michael@0: NS_NAMED_LITERAL_STRING(argStr, "Argument 1 of URL.createObjectURL"); michael@0: NS_NAMED_LITERAL_STRING(blobStr, "Blob"); michael@0: aRv.ThrowTypeError(MSG_DOES_NOT_IMPLEMENT_INTERFACE, &argStr, &blobStr); michael@0: return; michael@0: } michael@0: michael@0: nsRefPtr runnable = michael@0: new CreateURLRunnable(workerPrivate, blob, aOptions, aResult); michael@0: michael@0: if (!runnable->Dispatch(cx)) { michael@0: JS_ReportPendingException(cx); michael@0: } michael@0: } michael@0: michael@0: // static michael@0: void michael@0: URL::CreateObjectURL(const GlobalObject& aGlobal, JSObject& aBlob, michael@0: const mozilla::dom::objectURLOptions& aOptions, michael@0: nsString& aResult, mozilla::ErrorResult& aRv) michael@0: { michael@0: return CreateObjectURL(aGlobal, &aBlob, aOptions, aResult, aRv); michael@0: } michael@0: michael@0: // static michael@0: void michael@0: URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aUrl) michael@0: { michael@0: JSContext* cx = aGlobal.GetContext(); michael@0: WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); michael@0: michael@0: nsRefPtr runnable = michael@0: new RevokeURLRunnable(workerPrivate, aUrl); michael@0: michael@0: if (!runnable->Dispatch(cx)) { michael@0: JS_ReportPendingException(cx); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::URLSearchParamsUpdated() michael@0: { michael@0: MOZ_ASSERT(mSearchParams); michael@0: michael@0: nsString search; michael@0: mSearchParams->Serialize(search); michael@0: SetSearchInternal(search); michael@0: } michael@0: michael@0: void michael@0: URL::UpdateURLSearchParams() michael@0: { michael@0: if (mSearchParams) { michael@0: nsString search; michael@0: GetSearch(search); michael@0: mSearchParams->ParseInput(NS_ConvertUTF16toUTF8(Substring(search, 1)), this); michael@0: } michael@0: } michael@0: michael@0: void michael@0: URL::CreateSearchParamsIfNeeded() michael@0: { michael@0: if (!mSearchParams) { michael@0: mSearchParams = new URLSearchParams(); michael@0: mSearchParams->AddObserver(this); michael@0: UpdateURLSearchParams(); michael@0: } michael@0: } michael@0: michael@0: END_WORKERS_NAMESPACE