/* 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/UniquePtr.h" extern "C" { struct rusturl; } 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 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. class MozURL final { public: static nsresult Init(MozURL** aURL, const nsACString& aSpec, const MozURL* aBaseURL = nullptr); nsresult GetScheme(nsACString& aScheme); nsresult GetSpec(nsACString& aSpec); nsresult GetUsername(nsACString& aUser); nsresult GetPassword(nsACString& aPassword); // Will return the hostname of URL. If the hostname is an IPv6 address, // it will be enclosed in square brackets, such as `[::1]` nsresult GetHostname(nsACString& aHost); // 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 nsresult GetHostPort(nsACString& aHostPort); // Will return the port number, if specified, or -1 nsresult GetPort(int32_t* aPort); nsresult GetFilePath(nsACString& aPath); nsresult GetQuery(nsACString& aQuery); nsresult GetRef(nsACString& aRef); nsresult GetOrigin(nsACString& aOrigin); private: explicit MozURL(rusturl* rawPtr) : mURL(rawPtr) { } virtual ~MozURL() {} struct FreeRustURL { void operator()(rusturl* aPtr); }; mozilla::UniquePtr mURL; public: 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); // These setter methods will return a reference to `this` so that you may // chain setter operations as such: // // RefPtr 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); Mutator& SetUsername(const nsACString& aUser); Mutator& SetPassword(const nsACString& aPassword); Mutator& SetHostname(const nsACString& aHost); Mutator& SetHostPort(const nsACString& aHostPort); Mutator& SetFilePath(const nsACString& aPath); Mutator& SetQuery(const nsACString& aQuery); Mutator& SetRef(const nsACString& aRef); Mutator& SetPort(int32_t aPort); // 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 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 mStatus; } private: explicit Mutator(MozURL* url); mozilla::UniquePtr mURL; bool mFinalized; nsresult mStatus; friend class MozURL; }; Mutator Mutate() { return Mutator(this); } // These are used to avoid inheriting from nsISupports public: NS_IMETHOD_(MozExternalRefCountType) AddRef(void); NS_IMETHOD_(MozExternalRefCountType) Release(void); typedef mozilla::TrueType HasThreadSafeRefCnt; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; NS_DECL_OWNINGTHREAD }; } // namespace net } // namespace mozilla #endif // mozURL_h__