mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 02:25:34 +00:00
232 lines
7.5 KiB
C++
232 lines
7.5 KiB
C++
/* 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/. */
|
|
|
|
#ifndef mozURL_h__
|
|
#define mozURL_h__
|
|
|
|
#include "mozilla/net/MozURL_ffi.h"
|
|
#include "mozilla/RefPtr.h"
|
|
|
|
namespace mozilla {
|
|
namespace net {
|
|
|
|
// This class provides a thread-safe, immutable URL parser.
|
|
// As long as there is RefPtr to the object, you may use it on any thread.
|
|
// The constructor is private. One can instantiate the object by
|
|
// calling the Init() method as such:
|
|
//
|
|
// RefPtr<MozURL> url;
|
|
// nsAutoCString href("http://example.com/path?query#ref");
|
|
// nsresult rv = MozURL::Init(getter_AddRefs(url), href);
|
|
// if (NS_SUCCEEDED(rv)) { /* use url */ }
|
|
//
|
|
// When changing the URL is needed, you need to call the Mutate() method.
|
|
// This gives you a Mutator object, on which you can perform setter operations.
|
|
// Calling Finalize() on the Mutator will result in a new MozURL and a status
|
|
// code. If any of the setter operations failed, it will be reflected in the
|
|
// status code, and a null MozURL.
|
|
//
|
|
// Note: In the case of a domain name containing non-ascii characters,
|
|
// GetSpec and GetHostname will return the IDNA(punycode) version of the host.
|
|
// Also note that for now, MozURL only supports the UTF-8 charset.
|
|
//
|
|
// Implementor Note: This type is only a holder for methods in C++, and does not
|
|
// reflect the actual layout of the type.
|
|
class MozURL final
|
|
{
|
|
public:
|
|
static nsresult Init(MozURL** aURL, const nsACString& aSpec,
|
|
const MozURL* aBaseURL = nullptr)
|
|
{
|
|
return mozurl_new(aURL, &aSpec, aBaseURL);
|
|
}
|
|
|
|
nsDependentCSubstring Spec() const {
|
|
return mozurl_spec(this);
|
|
}
|
|
nsDependentCSubstring Scheme() const {
|
|
return mozurl_scheme(this);
|
|
}
|
|
nsDependentCSubstring Username() const {
|
|
return mozurl_username(this);
|
|
}
|
|
nsDependentCSubstring Password() const {
|
|
return mozurl_password(this);
|
|
}
|
|
// Will return the hostname of URL. If the hostname is an IPv6 address,
|
|
// it will be enclosed in square brackets, such as `[::1]`
|
|
nsDependentCSubstring Host() const {
|
|
return mozurl_host(this);
|
|
}
|
|
// Will return the port number, if specified, or -1
|
|
int32_t Port() const {
|
|
return mozurl_port(this);
|
|
}
|
|
// If the URL's port number is equal to the default port, will only return the
|
|
// hostname, otherwise it will return a string of the form `{host}:{port}`
|
|
// See: https://url.spec.whatwg.org/#default-port
|
|
nsDependentCSubstring HostPort() const {
|
|
return mozurl_host_port(this);
|
|
}
|
|
nsDependentCSubstring FilePath() const {
|
|
return mozurl_filepath(this);
|
|
}
|
|
nsDependentCSubstring Path() const {
|
|
return mozurl_path(this);
|
|
}
|
|
nsDependentCSubstring Query() const {
|
|
return mozurl_query(this);
|
|
}
|
|
nsDependentCSubstring Ref() const {
|
|
return mozurl_fragment(this);
|
|
}
|
|
bool HasFragment() const {
|
|
return mozurl_has_fragment(this);
|
|
}
|
|
|
|
// WARNING: This does not match the definition of origins in nsIPrincipal for
|
|
// all URIs.
|
|
// XXX: Consider bringing these implementations in sync with one-another?
|
|
void Origin(nsACString& aOrigin) const {
|
|
mozurl_origin(this, &aOrigin);
|
|
}
|
|
|
|
nsresult GetCommonBase(const MozURL* aOther, MozURL** aCommon) const {
|
|
return mozurl_common_base(this, aOther, aCommon);
|
|
}
|
|
nsresult GetRelative(const MozURL* aOther, nsACString* aRelative) const {
|
|
return mozurl_relative(this, aOther, aRelative);
|
|
}
|
|
|
|
class MOZ_STACK_CLASS Mutator
|
|
{
|
|
public:
|
|
// Calling this method will result in the creation of a new MozURL that
|
|
// adopts the mutator's mURL.
|
|
// If any of the setters failed with an error code, that error code will be
|
|
// returned here. It will also return an error code if Finalize is called
|
|
// more than once on the Mutator.
|
|
nsresult Finalize(MozURL** aURL) {
|
|
nsresult rv = GetStatus();
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mURL.forget(aURL);
|
|
} else {
|
|
*aURL = nullptr;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
// These setter methods will return a reference to `this` so that you may
|
|
// chain setter operations as such:
|
|
//
|
|
// RefPtr<MozURL> url2;
|
|
// nsresult rv = url->Mutate().SetHostname(NS_LITERAL_CSTRING("newhost"))
|
|
// .SetFilePath(NS_LITERAL_CSTRING("new/file/path"))
|
|
// .Finalize(getter_AddRefs(url2));
|
|
// if (NS_SUCCEEDED(rv)) { /* use url2 */ }
|
|
Mutator& SetScheme(const nsACString& aScheme) {
|
|
if (NS_SUCCEEDED(GetStatus())) {
|
|
mStatus = mozurl_set_scheme(mURL, &aScheme);
|
|
}
|
|
return *this;
|
|
}
|
|
Mutator& SetUsername(const nsACString& aUser) {
|
|
if (NS_SUCCEEDED(GetStatus())) {
|
|
mStatus = mozurl_set_username(mURL, &aUser);
|
|
}
|
|
return *this;
|
|
}
|
|
Mutator& SetPassword(const nsACString& aPassword) {
|
|
if (NS_SUCCEEDED(GetStatus())) {
|
|
mStatus = mozurl_set_password(mURL, &aPassword);
|
|
}
|
|
return *this;
|
|
}
|
|
Mutator& SetHostname(const nsACString& aHost) {
|
|
if (NS_SUCCEEDED(GetStatus())) {
|
|
mStatus = mozurl_set_hostname(mURL, &aHost);
|
|
}
|
|
return *this;
|
|
}
|
|
Mutator& SetHostPort(const nsACString& aHostPort) {
|
|
if (NS_SUCCEEDED(GetStatus())) {
|
|
mStatus = mozurl_set_host_port(mURL, &aHostPort);
|
|
}
|
|
return *this;
|
|
}
|
|
Mutator& SetFilePath(const nsACString& aPath) {
|
|
if (NS_SUCCEEDED(GetStatus())) {
|
|
mStatus = mozurl_set_pathname(mURL, &aPath);
|
|
}
|
|
return *this;
|
|
}
|
|
Mutator& SetQuery(const nsACString& aQuery) {
|
|
if (NS_SUCCEEDED(GetStatus())) {
|
|
mStatus = mozurl_set_query(mURL, &aQuery);
|
|
}
|
|
return *this;
|
|
}
|
|
Mutator& SetRef(const nsACString& aRef) {
|
|
if (NS_SUCCEEDED(GetStatus())) {
|
|
mStatus = mozurl_set_fragment(mURL, &aRef);
|
|
}
|
|
return *this;
|
|
}
|
|
Mutator& SetPort(int32_t aPort) {
|
|
if (NS_SUCCEEDED(GetStatus())) {
|
|
mStatus = mozurl_set_port_no(mURL, aPort);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
// This method returns the status code of the setter operations.
|
|
// If any of the setters failed, it will return the code of the first error
|
|
// that occured. If none of the setters failed, it will return NS_OK.
|
|
// This method is useful to avoid doing expensive operations when the result
|
|
// would not be used because an error occurred. For example:
|
|
//
|
|
// RefPtr<MozURL> url2;
|
|
// MozURL::Mutator mut = url->Mutate();
|
|
// mut.SetScheme("!@#$"); // this would fail
|
|
// if (NS_SUCCEDED(mut.GetStatus())) {
|
|
// nsAutoCString host(ExpensiveComputing());
|
|
// rv = mut.SetHostname(host).Finalize(getter_AddRefs(url2));
|
|
// }
|
|
// if (NS_SUCCEEDED(rv)) { /* use url2 */ }
|
|
nsresult GetStatus() {
|
|
return mURL ? mStatus : NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
private:
|
|
explicit Mutator(MozURL* aUrl) : mStatus(NS_OK) {
|
|
mozurl_clone(aUrl, getter_AddRefs(mURL));
|
|
}
|
|
RefPtr<MozURL> mURL;
|
|
nsresult mStatus;
|
|
friend class MozURL;
|
|
};
|
|
|
|
Mutator Mutate() { return Mutator(this); }
|
|
|
|
// AddRef and Release are non-virtual on this type, and always call into rust.
|
|
nsrefcnt AddRef() {
|
|
return mozurl_addref(this);
|
|
}
|
|
nsrefcnt Release() {
|
|
return mozurl_release(this);
|
|
}
|
|
|
|
private:
|
|
// Make it a compile time error for C++ code to ever create, destruct, or copy
|
|
// MozURL objects. All of these operations will be performed by rust.
|
|
MozURL(); /* never defined */
|
|
~MozURL(); /* never defined */
|
|
MozURL(const MozURL&) = delete;
|
|
MozURL& operator=(const MozURL&) = delete;
|
|
};
|
|
|
|
} // namespace net
|
|
} // namespace mozilla
|
|
|
|
#endif // mozURL_h__
|