Backed out 2 changesets (bug 1558923) for mochitest crashes on AssertIsOnMainThread(). CLOSED TREE

Backed out changeset 643de99320a8 (bug 1558923)
Backed out changeset f758b5ccd0c0 (bug 1558923)
This commit is contained in:
Narcis Beleuzu 2019-06-13 20:59:33 +03:00
parent 9b7249b587
commit 8e2da98d46
10 changed files with 570 additions and 118 deletions

View File

@ -5745,6 +5745,7 @@ nsresult nsContentUtils::GetASCIIOrigin(nsIPrincipal* aPrincipal,
/* static */
nsresult nsContentUtils::GetASCIIOrigin(nsIURI* aURI, nsACString& aOrigin) {
MOZ_ASSERT(aURI, "missing uri");
MOZ_ASSERT(NS_IsMainThread());
bool isBlobURL = false;
nsresult rv = aURI->SchemeIs(BLOBURI_SCHEME, &isBlobURL);
@ -5795,6 +5796,69 @@ nsresult nsContentUtils::GetASCIIOrigin(nsIURI* aURI, nsACString& aOrigin) {
return NS_OK;
}
/* static */
nsresult nsContentUtils::GetThreadSafeASCIIOrigin(nsIURI* aURI,
nsACString& aOrigin) {
MOZ_ASSERT(aURI, "missing uri");
bool isBlobURL = false;
nsresult rv = aURI->SchemeIs(BLOBURI_SCHEME, &isBlobURL);
NS_ENSURE_SUCCESS(rv, rv);
// For Blob URI, the path is the URL of the owning page.
if (isBlobURL) {
nsAutoCString path;
rv = aURI->GetPathQueryRef(path);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), path);
if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
if (NS_FAILED(rv)) {
aOrigin.AssignLiteral("null");
return NS_OK;
}
return GetThreadSafeASCIIOrigin(uri, aOrigin);
}
aOrigin.Truncate();
// This is not supported yet.
nsCOMPtr<nsINestedURI> nestedURI(do_QueryInterface(aURI));
if (nestedURI) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
nsAutoCString host;
rv = aURI->GetAsciiHost(host);
if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
nsAutoCString userPass;
aURI->GetUserPass(userPass);
nsCOMPtr<nsIURI> uri = aURI;
nsAutoCString prePath;
if (!userPass.IsEmpty()) {
rv = NS_MutateURI(uri).SetUserPass(EmptyCString()).Finalize(uri);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = uri->GetPrePath(prePath);
NS_ENSURE_SUCCESS(rv, rv);
aOrigin = prePath;
} else {
aOrigin.AssignLiteral("null");
}
return NS_OK;
}
/* static */
nsresult nsContentUtils::GetUTFOrigin(nsIPrincipal* aPrincipal,
nsAString& aOrigin) {
@ -5813,6 +5877,7 @@ nsresult nsContentUtils::GetUTFOrigin(nsIPrincipal* aPrincipal,
/* static */
nsresult nsContentUtils::GetUTFOrigin(nsIURI* aURI, nsAString& aOrigin) {
MOZ_ASSERT(aURI, "missing uri");
MOZ_ASSERT(NS_IsMainThread());
nsresult rv;
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
@ -5836,6 +5901,24 @@ nsresult nsContentUtils::GetUTFOrigin(nsIURI* aURI, nsAString& aOrigin) {
return NS_OK;
}
/* static */
nsresult nsContentUtils::GetThreadSafeUTFOrigin(nsIURI* aURI,
nsAString& aOrigin) {
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
return NS_ERROR_UNKNOWN_PROTOCOL;
#endif
MOZ_ASSERT(aURI, "missing uri");
nsresult rv;
nsAutoCString asciiOrigin;
rv = GetThreadSafeASCIIOrigin(aURI, asciiOrigin);
NS_ENSURE_SUCCESS(rv, rv);
aOrigin = NS_ConvertUTF8toUTF16(asciiOrigin);
return NS_OK;
}
/* static */
bool nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal,
nsIChannel* aChannel,

View File

@ -2141,8 +2141,10 @@ class nsContentUtils {
*/
static nsresult GetASCIIOrigin(nsIPrincipal* aPrincipal, nsACString& aOrigin);
static nsresult GetASCIIOrigin(nsIURI* aURI, nsACString& aOrigin);
static nsresult GetThreadSafeASCIIOrigin(nsIURI* aURI, nsACString& aOrigin);
static nsresult GetUTFOrigin(nsIPrincipal* aPrincipal, nsAString& aOrigin);
static nsresult GetUTFOrigin(nsIURI* aURI, nsAString& aOrigin);
static nsresult GetThreadSafeUTFOrigin(nsIURI* aURI, nsAString& aOrigin);
/**
* This method creates and dispatches "command" event, which implements

View File

@ -178,8 +178,7 @@ already_AddRefed<URL> ParseURLFromWorker(const GlobalObject& aGlobal,
worker->AssertIsOnWorkerThread();
NS_ConvertUTF8toUTF16 baseURL(worker->GetLocationInfo().mHref);
RefPtr<URL> url =
URL::Constructor(aGlobal.GetAsSupports(), aInput, baseURL, aRv);
RefPtr<URL> url = URL::WorkerConstructor(aGlobal, aInput, baseURL, aRv);
if (NS_WARN_IF(aRv.Failed())) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aInput);
}

View File

@ -126,8 +126,7 @@ already_AddRefed<Response> Response::Redirect(const GlobalObject& aGlobal,
worker->AssertIsOnWorkerThread();
NS_ConvertUTF8toUTF16 baseURL(worker->GetLocationInfo().mHref);
RefPtr<URL> url =
URL::Constructor(aGlobal.GetAsSupports(), aUrl, baseURL, aRv);
RefPtr<URL> url = URL::WorkerConstructor(aGlobal, aUrl, baseURL, aRv);
if (aRv.Failed()) {
return nullptr;
}

View File

@ -14,7 +14,6 @@
#include "nsContentUtils.h"
#include "mozilla/dom/Document.h"
#include "nsIURIMutator.h"
#include "nsNetUtil.h"
namespace mozilla {
namespace dom {
@ -38,46 +37,19 @@ already_AddRefed<URL> URL::Constructor(const GlobalObject& aGlobal,
const nsAString& aURL,
const Optional<nsAString>& aBase,
ErrorResult& aRv) {
if (aBase.WasPassed()) {
return Constructor(aGlobal.GetAsSupports(), aURL, aBase.Value(), aRv);
if (NS_IsMainThread()) {
return URLMainThread::Constructor(aGlobal, aURL, aBase, aRv);
}
return Constructor(aGlobal.GetAsSupports(), aURL, nullptr, aRv);
return URLWorker::Constructor(aGlobal, aURL, aBase, aRv);
}
/* static */
already_AddRefed<URL> URL::Constructor(nsISupports* aParent,
const nsAString& aURL,
const nsAString& aBase,
ErrorResult& aRv) {
nsCOMPtr<nsIURI> baseUri;
nsresult rv = NS_NewURI(getter_AddRefs(baseUri), aBase, nullptr, nullptr,
nsContentUtils::GetIOService());
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aBase);
return nullptr;
}
return Constructor(aParent, aURL, baseUri, aRv);
}
/* static */
already_AddRefed<URL> URL::Constructor(nsISupports* aParent,
const nsAString& aURL, nsIURI* aBase,
ErrorResult& aRv) {
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, nullptr, aBase,
nsContentUtils::GetIOService());
if (NS_FAILED(rv)) {
// No need to warn in this case. It's common to use the URL constructor
// to determine if a URL is valid and an exception will be propagated.
aRv.ThrowTypeError<MSG_INVALID_URL>(aURL);
return nullptr;
}
RefPtr<URL> url = new URL(aParent);
url->SetURI(uri.forget());
return url.forget();
already_AddRefed<URL> URL::WorkerConstructor(const GlobalObject& aGlobal,
const nsAString& aURL,
const nsAString& aBase,
ErrorResult& aRv) {
return URLWorker::Constructor(aGlobal, aURL, aBase, aRv);
}
void URL::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
@ -156,69 +128,11 @@ void URL::URLSearchParamsUpdated(URLSearchParams* aSearchParams) {
void URL::GetHref(nsAString& aHref) const { URL_GETTER(aHref, GetSpec); }
void URL::SetHref(const nsAString& aHref, ErrorResult& aRv) {
AssertIsOnMainThread();
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aHref, nullptr, nullptr,
nsContentUtils::GetIOService());
if (NS_FAILED(rv)) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aHref);
return;
}
mURI = std::move(uri);
UpdateURLSearchParams();
}
void URL::GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const {
nsresult rv = nsContentUtils::GetUTFOrigin(GetURI(), aOrigin);
if (NS_WARN_IF(NS_FAILED(rv))) {
aOrigin.Truncate();
}
}
void URL::GetProtocol(nsAString& aProtocol) const {
URL_GETTER(aProtocol, GetScheme);
aProtocol.Append(char16_t(':'));
}
void URL::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv) {
nsAString::const_iterator start;
aProtocol.BeginReading(start);
nsAString::const_iterator end;
aProtocol.EndReading(end);
nsAString::const_iterator iter(start);
FindCharInReadable(':', iter, end);
// Changing the protocol of a URL, changes the "nature" of the URI
// implementation. In order to do this properly, we have to serialize the
// existing URL and reparse it in a new object.
nsCOMPtr<nsIURI> clone;
nsresult rv = NS_MutateURI(GetURI())
.SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)))
.Finalize(clone);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsAutoCString href;
rv = clone->GetSpec(href);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), href);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
mURI = std::move(uri);
}
void URL::GetUsername(nsAString& aUsername) const {
URL_GETTER(aUsername, GetUsername);
}

View File

@ -26,32 +26,29 @@ class Blob;
class MediaSource;
class GlobalObject;
class URL final : public URLSearchParamsObserver, public nsWrapperCache {
class URL : public URLSearchParamsObserver, public nsWrapperCache {
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(URL)
explicit URL(nsISupports* aParent) : mParent(aParent) {}
URL(nsISupports* aParent) : mParent(aParent) {}
// WebIDL methods
nsISupports* GetParentObject() const { return mParent; }
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
static already_AddRefed<URL> Constructor(const GlobalObject& aGlobal,
const nsAString& aURL,
const Optional<nsAString>& aBase,
ErrorResult& aRv);
static already_AddRefed<URL> Constructor(nsISupports* aParent,
const nsAString& aURL,
const nsAString& aBase,
ErrorResult& aRv);
static already_AddRefed<URL> Constructor(nsISupports* aParent,
const nsAString& aURL, nsIURI* aBase,
ErrorResult& aRv);
// Helper for Fetch API
static already_AddRefed<URL> WorkerConstructor(const GlobalObject& aGlobal,
const nsAString& aURL,
const nsAString& aBase,
ErrorResult& aRv);
static void CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
nsAString& aResult, ErrorResult& aRv);
@ -67,13 +64,13 @@ class URL final : public URLSearchParamsObserver, public nsWrapperCache {
void GetHref(nsAString& aHref) const;
void SetHref(const nsAString& aHref, ErrorResult& aRv);
virtual void SetHref(const nsAString& aHref, ErrorResult& aRv) = 0;
void GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const;
virtual void GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const = 0;
void GetProtocol(nsAString& aProtocol) const;
void SetProtocol(const nsAString& aProtocol, ErrorResult& aRv);
virtual void SetProtocol(const nsAString& aProtocol, ErrorResult& aRv) = 0;
void GetUsername(nsAString& aUsername) const;
@ -101,7 +98,7 @@ class URL final : public URLSearchParamsObserver, public nsWrapperCache {
void GetSearch(nsAString& aSearch) const;
void SetSearch(const nsAString& aSearch);
virtual void SetSearch(const nsAString& aSearch);
URLSearchParams* SearchParams();
@ -116,8 +113,8 @@ class URL final : public URLSearchParamsObserver, public nsWrapperCache {
// URLSearchParamsObserver
void URLSearchParamsUpdated(URLSearchParams* aSearchParams) override;
private:
~URL() = default;
protected:
virtual ~URL() = default;
void SetURI(already_AddRefed<nsIURI> aURI);

View File

@ -18,6 +18,55 @@
namespace mozilla {
namespace dom {
/* static */
already_AddRefed<URLMainThread> URLMainThread::Constructor(
const GlobalObject& aGlobal, const nsAString& aURL,
const Optional<nsAString>& aBase, ErrorResult& aRv) {
if (aBase.WasPassed()) {
return Constructor(aGlobal.GetAsSupports(), aURL, aBase.Value(), aRv);
}
return Constructor(aGlobal.GetAsSupports(), aURL, nullptr, aRv);
}
/* static */
already_AddRefed<URLMainThread> URLMainThread::Constructor(
nsISupports* aParent, const nsAString& aURL, const nsAString& aBase,
ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIURI> baseUri;
nsresult rv = NS_NewURI(getter_AddRefs(baseUri), aBase, nullptr, nullptr,
nsContentUtils::GetIOService());
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aBase);
return nullptr;
}
return Constructor(aParent, aURL, baseUri, aRv);
}
/* static */
already_AddRefed<URLMainThread> URLMainThread::Constructor(
nsISupports* aParent, const nsAString& aURL, nsIURI* aBase,
ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, nullptr, aBase,
nsContentUtils::GetIOService());
if (NS_FAILED(rv)) {
// No need to warn in this case. It's common to use the URL constructor
// to determine if a URL is valid and an exception will be propagated.
aRv.ThrowTypeError<MSG_INVALID_URL>(aURL);
return nullptr;
}
RefPtr<URLMainThread> url = new URLMainThread(aParent);
url->SetURI(uri.forget());
return url.forget();
}
/* static */
void URLMainThread::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
nsAString& aResult, ErrorResult& aRv) {
@ -89,6 +138,12 @@ void URLMainThread::RevokeObjectURL(const GlobalObject& aGlobal,
}
}
URLMainThread::URLMainThread(nsISupports* aParent) : URL(aParent) {
MOZ_ASSERT(NS_IsMainThread());
}
URLMainThread::~URLMainThread() { MOZ_ASSERT(NS_IsMainThread()); }
/* static */
bool URLMainThread::IsValidURL(const GlobalObject& aGlobal,
const nsAString& aURL, ErrorResult& aRv) {
@ -97,5 +152,64 @@ bool URLMainThread::IsValidURL(const GlobalObject& aGlobal,
return BlobURLProtocolHandler::HasDataEntry(asciiurl);
}
void URLMainThread::SetHref(const nsAString& aHref, ErrorResult& aRv) {
NS_ConvertUTF16toUTF8 href(aHref);
nsresult rv;
nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
}
nsCOMPtr<nsIURI> uri;
rv = ioService->NewURI(href, nullptr, nullptr, getter_AddRefs(uri));
if (NS_FAILED(rv)) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aHref);
return;
}
SetURI(uri.forget());
UpdateURLSearchParams();
}
void URLMainThread::GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const {
nsContentUtils::GetUTFOrigin(GetURI(), aOrigin);
}
void URLMainThread::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv) {
nsAString::const_iterator start, end;
aProtocol.BeginReading(start);
aProtocol.EndReading(end);
nsAString::const_iterator iter(start);
FindCharInReadable(':', iter, end);
// Changing the protocol of a URL, changes the "nature" of the URI
// implementation. In order to do this properly, we have to serialize the
// existing URL and reparse it in a new object.
nsCOMPtr<nsIURI> clone;
nsresult rv = NS_MutateURI(GetURI())
.SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)))
.Finalize(clone);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsAutoCString href;
rv = clone->GetSpec(href);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), href);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
SetURI(uri.forget());
}
} // namespace dom
} // namespace mozilla

View File

@ -12,8 +12,23 @@
namespace mozilla {
namespace dom {
class URLMainThread final {
// The URL implementation for the main-thread
class URLMainThread final : public URL {
public:
static already_AddRefed<URLMainThread> Constructor(
const GlobalObject& aGlobal, const nsAString& aURL,
const Optional<nsAString>& aBase, ErrorResult& aRv);
static already_AddRefed<URLMainThread> Constructor(nsISupports* aParent,
const nsAString& aURL,
const nsAString& aBase,
ErrorResult& aRv);
static already_AddRefed<URLMainThread> Constructor(nsISupports* aParent,
const nsAString& aURL,
nsIURI* aBase,
ErrorResult& aRv);
static void CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
nsAString& aResult, ErrorResult& aRv);
@ -25,6 +40,18 @@ class URLMainThread final {
static bool IsValidURL(const GlobalObject& aGlobal, const nsAString& aURL,
ErrorResult& aRv);
explicit URLMainThread(nsISupports* aParent);
virtual void SetHref(const nsAString& aHref, ErrorResult& aRv) override;
virtual void GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const override;
virtual void SetProtocol(const nsAString& aProtocol,
ErrorResult& aRv) override;
private:
~URLMainThread();
};
} // namespace dom

View File

@ -11,8 +11,15 @@
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRunnable.h"
#include "mozilla/dom/WorkerScope.h"
#include "mozilla/Unused.h"
#include "nsProxyRelease.h"
#include "nsStandardURL.h"
#include "nsURLHelper.h"
namespace mozilla {
using net::nsStandardURL;
namespace dom {
// This class creates an URL from a DOM Blob on the main thread.
@ -154,6 +161,163 @@ class IsValidURLRunnable : public WorkerMainThreadRunnable {
bool IsValidURL() const { return mValid; }
};
// This class creates a URL object on the main thread.
class ConstructorRunnable : public WorkerMainThreadRunnable {
private:
const nsString mURL;
nsString mBase; // IsVoid() if we have no base URI string.
nsCOMPtr<nsIURI> mRetval;
public:
ConstructorRunnable(WorkerPrivate* aWorkerPrivate, const nsAString& aURL,
const Optional<nsAString>& aBase)
: WorkerMainThreadRunnable(aWorkerPrivate,
NS_LITERAL_CSTRING("URL :: Constructor")),
mURL(aURL) {
if (aBase.WasPassed()) {
mBase = aBase.Value();
} else {
mBase.SetIsVoid(true);
}
mWorkerPrivate->AssertIsOnWorkerThread();
}
bool MainThreadRun() override {
AssertIsOnMainThread();
nsCOMPtr<nsIURI> baseUri;
if (!mBase.IsVoid()) {
nsresult rv = NS_NewURI(getter_AddRefs(baseUri), mBase, nullptr, nullptr,
nsContentUtils::GetIOService());
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
}
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), mURL, nullptr, baseUri,
nsContentUtils::GetIOService());
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
mRetval = std::move(uri);
return true;
}
nsIURI* GetURI(ErrorResult& aRv) const {
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
if (!mRetval) {
aRv.ThrowTypeError<MSG_INVALID_URL>(mURL);
}
return mRetval;
}
};
class OriginGetterRunnable : public WorkerMainThreadRunnable {
public:
OriginGetterRunnable(WorkerPrivate* aWorkerPrivate, nsAString& aValue,
nsIURI* aURI)
: WorkerMainThreadRunnable(aWorkerPrivate,
NS_LITERAL_CSTRING("URL :: origin getter")),
mValue(aValue),
mURI(aURI) {
mWorkerPrivate->AssertIsOnWorkerThread();
}
bool MainThreadRun() override {
AssertIsOnMainThread();
ErrorResult rv;
nsContentUtils::GetUTFOrigin(mURI, mValue);
return true;
}
void Dispatch(ErrorResult& aRv) {
WorkerMainThreadRunnable::Dispatch(Canceling, aRv);
}
private:
nsAString& mValue;
nsCOMPtr<nsIURI> mURI;
};
class ProtocolSetterRunnable : public WorkerMainThreadRunnable {
public:
ProtocolSetterRunnable(WorkerPrivate* aWorkerPrivate,
const nsACString& aValue, nsIURI* aURI)
: WorkerMainThreadRunnable(aWorkerPrivate,
NS_LITERAL_CSTRING("ProtocolSetterRunnable")),
mValue(aValue),
mURI(aURI) {
mWorkerPrivate->AssertIsOnWorkerThread();
}
bool MainThreadRun() override {
AssertIsOnMainThread();
nsCOMPtr<nsIURI> clone;
nsresult rv = NS_MutateURI(mURI).SetScheme(mValue).Finalize(clone);
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
nsAutoCString href;
rv = clone->GetSpec(href);
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), href);
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
mRetval = std::move(uri);
return true;
}
void Dispatch(ErrorResult& aRv) {
WorkerMainThreadRunnable::Dispatch(Canceling, aRv);
}
nsIURI* GetRetval() const { return mRetval; }
private:
const nsCString mValue;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mRetval;
};
/* 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<URLWorker> url = new URLWorker(workerPrivate);
url->Init(aURL, aBase, aRv);
return aRv.Failed() ? nullptr : url.forget();
}
/* static */
already_AddRefed<URLWorker> URLWorker::Constructor(const GlobalObject& aGlobal,
const nsAString& aURL,
const nsAString& aBase,
ErrorResult& aRv) {
Optional<nsAString> base;
base = &aBase;
return Constructor(aGlobal, aURL, base, aRv);
}
/* static */
void URLWorker::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
nsAString& aResult, mozilla::ErrorResult& aRv) {
@ -223,5 +387,138 @@ bool URLWorker::IsValidURL(const GlobalObject& aGlobal, const nsAString& aUrl,
return runnable->IsValidURL();
}
URLWorker::URLWorker(WorkerPrivate* aWorkerPrivate)
: URL(nullptr), mWorkerPrivate(aWorkerPrivate) {}
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;
}
}
// Let's check if the baseURI was passed and if it can be parsed on the worker
// thread.
bool useProxy = false;
nsCOMPtr<nsIURI> baseURI;
if (aBase.WasPassed()) {
rv = NS_NewURI(getter_AddRefs(baseURI),
NS_ConvertUTF16toUTF8(aBase.Value()));
if (NS_FAILED(rv)) {
if (rv != NS_ERROR_UNKNOWN_PROTOCOL) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aBase.Value());
return;
}
useProxy = true;
}
}
// Let's see if we can parse aURI on this thread.
nsCOMPtr<nsIURI> uri;
if (!useProxy) {
rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(aURL), nullptr,
baseURI);
if (NS_FAILED(rv)) {
if (rv != NS_ERROR_UNKNOWN_PROTOCOL) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aURL);
return;
}
useProxy = true;
}
}
// Fallback by proxy.
if (useProxy) {
RefPtr<ConstructorRunnable> runnable =
new ConstructorRunnable(mWorkerPrivate, aURL, aBase);
runnable->Dispatch(Canceling, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
uri = runnable->GetURI(aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
}
SetURI(uri.forget());
}
URLWorker::~URLWorker() = default;
void URLWorker::SetHref(const nsAString& aHref, ErrorResult& aRv) {
nsAutoCString scheme;
nsresult rv = net_ExtractURLScheme(NS_ConvertUTF16toUTF8(aHref), scheme);
if (NS_FAILED(rv)) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aHref);
return;
}
RefPtr<ConstructorRunnable> runnable =
new ConstructorRunnable(mWorkerPrivate, aHref, Optional<nsAString>());
runnable->Dispatch(Canceling, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
nsCOMPtr<nsIURI> uri = runnable->GetURI(aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
SetURI(uri.forget());
UpdateURLSearchParams();
}
void URLWorker::GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const {
nsresult rv = nsContentUtils::GetThreadSafeUTFOrigin(GetURI(), aOrigin);
if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
RefPtr<OriginGetterRunnable> runnable =
new OriginGetterRunnable(mWorkerPrivate, aOrigin, GetURI());
runnable->Dispatch(aRv);
return;
}
if (NS_WARN_IF(NS_FAILED(rv))) {
aOrigin.Truncate();
}
}
void URLWorker::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv) {
nsAString::const_iterator start, end;
aProtocol.BeginReading(start);
aProtocol.EndReading(end);
nsAString::const_iterator iter(start);
FindCharInReadable(':', iter, end);
NS_ConvertUTF16toUTF8 scheme(Substring(start, iter));
RefPtr<ProtocolSetterRunnable> runnable =
new ProtocolSetterRunnable(mWorkerPrivate, scheme, GetURI());
runnable->Dispatch(aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
nsCOMPtr<nsIURI> uri = runnable->GetRetval();
if (NS_WARN_IF(!uri)) {
return;
}
SetURI(uri.forget());
}
} // namespace dom
} // namespace mozilla

View File

@ -18,7 +18,10 @@ class nsStandardURL;
namespace dom {
class URLWorker final {
class WorkerPrivate;
// URLWorker implements the URL object in workers.
class URLWorker final : public URL {
public:
static already_AddRefed<URLWorker> Constructor(
const GlobalObject& aGlobal, const nsAString& aURL,
@ -37,6 +40,23 @@ class URLWorker final {
static bool IsValidURL(const GlobalObject& aGlobal, const nsAString& aUrl,
ErrorResult& aRv);
explicit URLWorker(WorkerPrivate* aWorkerPrivate);
void Init(const nsAString& aURL, const Optional<nsAString>& aBase,
ErrorResult& aRv);
virtual void SetHref(const nsAString& aHref, ErrorResult& aRv) override;
virtual void GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const override;
virtual void SetProtocol(const nsAString& aProtocol,
ErrorResult& aRv) override;
private:
~URLWorker();
WorkerPrivate* mWorkerPrivate;
};
} // namespace dom