diff options
Diffstat (limited to '')
-rw-r--r-- | netwerk/base/DefaultURI.cpp | 572 |
1 files changed, 572 insertions, 0 deletions
diff --git a/netwerk/base/DefaultURI.cpp b/netwerk/base/DefaultURI.cpp new file mode 100644 index 0000000000..0a70218af5 --- /dev/null +++ b/netwerk/base/DefaultURI.cpp @@ -0,0 +1,572 @@ +/* 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 "DefaultURI.h" +#include "nsIClassInfoImpl.h" +#include "nsIObjectInputStream.h" +#include "nsIObjectOutputStream.h" +#include "nsURLHelper.h" + +#include "mozilla/ipc/URIParams.h" + +namespace mozilla { +namespace net { + +#define NS_DEFAULTURI_CID \ + { /* 04445aa0-fd27-4c99-bd41-6be6318ae92c */ \ + 0x04445aa0, 0xfd27, 0x4c99, { \ + 0xbd, 0x41, 0x6b, 0xe6, 0x31, 0x8a, 0xe9, 0x2c \ + } \ + } + +#define ASSIGN_AND_ADDREF_THIS(ptrToMutator) \ + do { \ + if (ptrToMutator) { \ + *(ptrToMutator) = do_AddRef(this).take(); \ + } \ + } while (0) + +static NS_DEFINE_CID(kDefaultURICID, NS_DEFAULTURI_CID); + +//---------------------------------------------------------------------------- +// nsIClassInfo +//---------------------------------------------------------------------------- + +NS_IMPL_CLASSINFO(DefaultURI, nullptr, nsIClassInfo::THREADSAFE, + NS_DEFAULTURI_CID) +// Empty CI getter. We only need nsIClassInfo for Serialization +NS_IMPL_CI_INTERFACE_GETTER0(DefaultURI) + +//---------------------------------------------------------------------------- +// nsISupports +//---------------------------------------------------------------------------- + +NS_IMPL_ADDREF(DefaultURI) +NS_IMPL_RELEASE(DefaultURI) +NS_INTERFACE_TABLE_HEAD(DefaultURI) + NS_INTERFACE_TABLE(DefaultURI, nsIURI, nsISerializable) + NS_INTERFACE_TABLE_TO_MAP_SEGUE + NS_IMPL_QUERY_CLASSINFO(DefaultURI) + if (aIID.Equals(kDefaultURICID)) { + foundInterface = static_cast<nsIURI*>(this); + } else + NS_INTERFACE_MAP_ENTRY(nsISizeOf) +NS_INTERFACE_MAP_END + +//---------------------------------------------------------------------------- +// nsISerializable +//---------------------------------------------------------------------------- + +NS_IMETHODIMP DefaultURI::Read(nsIObjectInputStream* aInputStream) { + MOZ_ASSERT_UNREACHABLE("Use nsIURIMutator.read() instead"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DefaultURI::Write(nsIObjectOutputStream* aOutputStream) { + nsAutoCString spec(mURL->Spec()); + return aOutputStream->WriteStringZ(spec.get()); +} + +//---------------------------------------------------------------------------- +// nsISizeOf +//---------------------------------------------------------------------------- + +size_t DefaultURI::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { + return mURL->SizeOf(); +} + +size_t DefaultURI::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); +} + +//---------------------------------------------------------------------------- +// nsIURI +//---------------------------------------------------------------------------- + +NS_IMETHODIMP DefaultURI::GetSpec(nsACString& aSpec) { + aSpec = mURL->Spec(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetPrePath(nsACString& aPrePath) { + aPrePath = mURL->PrePath(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetScheme(nsACString& aScheme) { + aScheme = mURL->Scheme(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetUserPass(nsACString& aUserPass) { + aUserPass = mURL->Username(); + nsAutoCString pass(mURL->Password()); + if (pass.IsEmpty()) { + return NS_OK; + } + aUserPass.Append(':'); + aUserPass.Append(pass); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetUsername(nsACString& aUsername) { + aUsername = mURL->Username(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetPassword(nsACString& aPassword) { + aPassword = mURL->Password(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetHostPort(nsACString& aHostPort) { + aHostPort = mURL->HostPort(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetHost(nsACString& aHost) { + aHost = mURL->Host(); + + // Historically nsIURI.host has always returned an IPv6 address that isn't + // enclosed in brackets. Ideally we want to change that, but for the sake of + // consitency we'll leave it like that for the moment. + // Bug 1603199 should fix this. + if (StringBeginsWith(aHost, "["_ns) && StringEndsWith(aHost, "]"_ns) && + aHost.FindChar(':') != kNotFound) { + aHost = Substring(aHost, 1, aHost.Length() - 2); + } + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetPort(int32_t* aPort) { + *aPort = mURL->Port(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetPathQueryRef(nsACString& aPathQueryRef) { + aPathQueryRef = mURL->Path(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::Equals(nsIURI* other, bool* _retval) { + if (!other) { + *_retval = false; + return NS_OK; + } + RefPtr<DefaultURI> otherUri; + nsresult rv = other->QueryInterface(kDefaultURICID, getter_AddRefs(otherUri)); + if (NS_FAILED(rv)) { + *_retval = false; + return NS_OK; + } + + *_retval = mURL->Spec() == otherUri->mURL->Spec(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::SchemeIs(const char* scheme, bool* _retval) { + if (!scheme) { + *_retval = false; + return NS_OK; + } + *_retval = mURL->Scheme().Equals(scheme); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::Resolve(const nsACString& aRelativePath, + nsACString& aResult) { + nsAutoCString scheme; + nsresult rv = net_ExtractURLScheme(aRelativePath, scheme); + if (NS_SUCCEEDED(rv)) { + aResult = aRelativePath; + return NS_OK; + } + + // We try to create another URL with this one as its base. + RefPtr<MozURL> resolvedURL; + rv = MozURL::Init(getter_AddRefs(resolvedURL), aRelativePath, mURL); + if (NS_WARN_IF(NS_FAILED(rv))) { + // If parsing the relative url fails, we revert to the previous behaviour + // and just return the relative path. + aResult = aRelativePath; + return NS_OK; + } + + aResult = resolvedURL->Spec(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetAsciiSpec(nsACString& aAsciiSpec) { + return GetSpec(aAsciiSpec); +} + +NS_IMETHODIMP DefaultURI::GetAsciiHostPort(nsACString& aAsciiHostPort) { + return GetHostPort(aAsciiHostPort); +} + +NS_IMETHODIMP DefaultURI::GetAsciiHost(nsACString& aAsciiHost) { + return GetHost(aAsciiHost); +} + +NS_IMETHODIMP DefaultURI::GetRef(nsACString& aRef) { + aRef = mURL->Ref(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::EqualsExceptRef(nsIURI* other, bool* _retval) { + if (!_retval || !other) { + return NS_ERROR_NULL_POINTER; + } + RefPtr<DefaultURI> otherUri; + nsresult rv = other->QueryInterface(kDefaultURICID, getter_AddRefs(otherUri)); + if (NS_FAILED(rv)) { + *_retval = false; + return NS_OK; + } + + *_retval = mURL->SpecNoRef().Equals(otherUri->mURL->SpecNoRef()); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetSpecIgnoringRef(nsACString& aSpecIgnoringRef) { + aSpecIgnoringRef = mURL->SpecNoRef(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetHasRef(bool* aHasRef) { + *aHasRef = mURL->HasFragment(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetHasUserPass(bool* aHasUserPass) { + *aHasUserPass = !mURL->Username().IsEmpty() || !mURL->Password().IsEmpty(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetFilePath(nsACString& aFilePath) { + aFilePath = mURL->FilePath(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetQuery(nsACString& aQuery) { + aQuery = mURL->Query(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetHasQuery(bool* aHasQuery) { + *aHasQuery = mURL->HasQuery(); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::GetDisplayHost(nsACString& aDisplayHost) { + // At the moment it doesn't seem useful to decode the hostname if it happens + // to contain punycode. + return GetHost(aDisplayHost); +} + +NS_IMETHODIMP DefaultURI::GetDisplayHostPort(nsACString& aDisplayHostPort) { + // At the moment it doesn't seem useful to decode the hostname if it happens + // to contain punycode. + return GetHostPort(aDisplayHostPort); +} + +NS_IMETHODIMP DefaultURI::GetDisplaySpec(nsACString& aDisplaySpec) { + // At the moment it doesn't seem useful to decode the hostname if it happens + // to contain punycode. + return GetSpec(aDisplaySpec); +} + +NS_IMETHODIMP DefaultURI::GetDisplayPrePath(nsACString& aDisplayPrePath) { + // At the moment it doesn't seem useful to decode the hostname if it happens + // to contain punycode. + return GetPrePath(aDisplayPrePath); +} + +NS_IMETHODIMP DefaultURI::Mutate(nsIURIMutator** _retval) { + RefPtr<DefaultURI::Mutator> mutator = new DefaultURI::Mutator(); + mutator->Init(this); + mutator.forget(_retval); + return NS_OK; +} + +void DefaultURI::Serialize(ipc::URIParams& aParams) { + ipc::DefaultURIParams params; + params.spec() = mURL->Spec(); + aParams = params; +} + +//---------------------------------------------------------------------------- +// nsIURIMutator +//---------------------------------------------------------------------------- + +NS_IMPL_ADDREF(DefaultURI::Mutator) +NS_IMPL_RELEASE(DefaultURI::Mutator) +NS_IMETHODIMP DefaultURI::Mutator::QueryInterface(REFNSIID aIID, + void** aInstancePtr) { + NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!"); + nsISupports* foundInterface = nullptr; + if (aIID.Equals(NS_GET_IID(nsIURI))) { + RefPtr<DefaultURI> defaultURI = new DefaultURI(); + mMutator->Finalize(getter_AddRefs(defaultURI->mURL)); + foundInterface = + static_cast<nsISupports*>(static_cast<nsIURI*>((defaultURI.get()))); + NS_ADDREF(foundInterface); + *aInstancePtr = foundInterface; + return NS_OK; + } + + if (aIID.Equals(NS_GET_IID(nsIURIMutator)) || + aIID.Equals(NS_GET_IID(nsISupports))) { + foundInterface = + static_cast<nsISupports*>(static_cast<nsIURIMutator*>(this)); + } else if (aIID.Equals(NS_GET_IID(nsIURISetters))) { + foundInterface = + static_cast<nsISupports*>(static_cast<nsIURISetters*>(this)); + } else if (aIID.Equals(NS_GET_IID(nsIURISetSpec))) { + foundInterface = + static_cast<nsISupports*>(static_cast<nsIURISetSpec*>(this)); + } else if (aIID.Equals(NS_GET_IID(nsISerializable))) { + foundInterface = + static_cast<nsISupports*>(static_cast<nsISerializable*>(this)); + } + + if (foundInterface) { + NS_ADDREF(foundInterface); + *aInstancePtr = foundInterface; + return NS_OK; + } + + return NS_NOINTERFACE; +} + +NS_IMETHODIMP DefaultURI::Mutator::Read(nsIObjectInputStream* aStream) { + nsAutoCString spec; + nsresult rv = aStream->ReadCString(spec); + if (NS_FAILED(rv)) { + return rv; + } + return SetSpec(spec, nullptr); +} + +NS_IMETHODIMP DefaultURI::Mutator::Deserialize( + const mozilla::ipc::URIParams& aParams) { + if (aParams.type() != ipc::URIParams::TDefaultURIParams) { + NS_ERROR("Received unknown parameters from the other process!"); + return NS_ERROR_FAILURE; + } + + const ipc::DefaultURIParams& params = aParams.get_DefaultURIParams(); + auto result = MozURL::Mutator::FromSpec(params.spec()); + if (result.isErr()) { + return result.unwrapErr(); + } + mMutator = Some(result.unwrap()); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::Mutator::Finalize(nsIURI** aURI) { + if (!mMutator.isSome()) { + return NS_ERROR_NOT_AVAILABLE; + } + RefPtr<DefaultURI> uri = new DefaultURI(); + mMutator->Finalize(getter_AddRefs(uri->mURL)); + mMutator = Nothing(); + uri.forget(aURI); + return NS_OK; +} + +NS_IMETHODIMP DefaultURI::Mutator::SetSpec(const nsACString& aSpec, + nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + auto result = MozURL::Mutator::FromSpec(aSpec); + if (result.isErr()) { + return result.unwrapErr(); + } + mMutator = Some(result.unwrap()); + return NS_OK; +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetScheme(const nsACString& aScheme, + nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + mMutator->SetScheme(aScheme); + return mMutator->GetStatus(); +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetUserPass(const nsACString& aUserPass, + nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + int32_t index = aUserPass.FindChar(':'); + if (index == kNotFound) { + mMutator->SetUsername(aUserPass); + mMutator->SetPassword(""_ns); + return mMutator->GetStatus(); + } + + mMutator->SetUsername(Substring(aUserPass, 0, index)); + nsresult rv = mMutator->GetStatus(); + if (NS_FAILED(rv)) { + return rv; + } + mMutator->SetPassword(Substring(aUserPass, index + 1)); + rv = mMutator->GetStatus(); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetUsername(const nsACString& aUsername, + nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + mMutator->SetUsername(aUsername); + return mMutator->GetStatus(); +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetPassword(const nsACString& aPassword, + nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + mMutator->SetPassword(aPassword); + return mMutator->GetStatus(); +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetHostPort(const nsACString& aHostPort, + nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + mMutator->SetHostPort(aHostPort); + return mMutator->GetStatus(); +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetHost(const nsACString& aHost, + nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + mMutator->SetHostname(aHost); + return mMutator->GetStatus(); +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetPort(int32_t aPort, nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + mMutator->SetPort(aPort); + return mMutator->GetStatus(); +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetPathQueryRef(const nsACString& aPathQueryRef, + nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + if (aPathQueryRef.IsEmpty()) { + mMutator->SetFilePath(""_ns); + mMutator->SetQuery(""_ns); + mMutator->SetRef(""_ns); + return mMutator->GetStatus(); + } + + RefPtr<MozURL> url; + mMutator->Finalize(getter_AddRefs(url)); + mMutator = Nothing(); + + if (!url) { + return NS_ERROR_FAILURE; + } + + nsAutoCString pathQueryRef(aPathQueryRef); + if (url->CannotBeABase()) { + // If the base URL cannot be a base, then setting the pathQueryRef + // needs to change everything after the scheme. + pathQueryRef.Insert(":", 0); + pathQueryRef.Insert(url->Scheme(), 0); + // Clear the URL to make sure FromSpec creates an absolute URL + url = nullptr; + } else if (!StringBeginsWith(pathQueryRef, "/"_ns)) { + // If the base URL can be a base, make sure the path + // begins with a / + pathQueryRef.Insert('/', 0); + } + + auto result = MozURL::Mutator::FromSpec(pathQueryRef, url); + if (result.isErr()) { + return result.unwrapErr(); + } + mMutator = Some(result.unwrap()); + return mMutator->GetStatus(); +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetRef(const nsACString& aRef, nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + mMutator->SetRef(aRef); + return mMutator->GetStatus(); +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetFilePath(const nsACString& aFilePath, + nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + mMutator->SetFilePath(aFilePath); + return mMutator->GetStatus(); +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetQuery(const nsACString& aQuery, + nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + mMutator->SetQuery(aQuery); + return mMutator->GetStatus(); +} + +NS_IMETHODIMP +DefaultURI::Mutator::SetQueryWithEncoding(const nsACString& aQuery, + const mozilla::Encoding* aEncoding, + nsIURIMutator** aMutator) { + ASSIGN_AND_ADDREF_THIS(aMutator); + if (!mMutator.isSome()) { + return NS_ERROR_NULL_POINTER; + } + // we only support UTF-8 for DefaultURI + mMutator->SetQuery(aQuery); + return mMutator->GetStatus(); +} + +} // namespace net +} // namespace mozilla |