tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MozURL.h (9063B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef mozURL_h__
      6 #define mozURL_h__
      7 
      8 #include "mozilla/net/MozURL_ffi.h"
      9 #include "mozilla/RefPtr.h"
     10 #include "mozilla/Result.h"
     11 
     12 namespace mozilla {
     13 namespace net {
     14 
     15 // This class provides a thread-safe, immutable URL parser.
     16 // As long as there is RefPtr to the object, you may use it on any thread.
     17 // The constructor is private. One can instantiate the object by
     18 // calling the Init() method as such:
     19 //
     20 // RefPtr<MozURL> url;
     21 // nsAutoCString href("http://example.com/path?query#ref");
     22 // nsresult rv = MozURL::Init(getter_AddRefs(url), href);
     23 // if (NS_SUCCEEDED(rv)) { /* use url */ }
     24 //
     25 // When changing the URL is needed, you need to call the Mutate() method.
     26 // This gives you a Mutator object, on which you can perform setter operations.
     27 // Calling Finalize() on the Mutator will result in a new MozURL and a status
     28 // code. If any of the setter operations failed, it will be reflected in the
     29 // status code, and a null MozURL.
     30 //
     31 // Note: In the case of a domain name containing non-ascii characters,
     32 // GetSpec and GetHostname will return the IDNA(punycode) version of the host.
     33 // Also note that for now, MozURL only supports the UTF-8 charset.
     34 //
     35 // Implementor Note: This type is only a holder for methods in C++, and does not
     36 // reflect the actual layout of the type.
     37 class MozURL final {
     38 public:
     39  static nsresult Init(MozURL** aURL, const nsACString& aSpec,
     40                       const MozURL* aBaseURL = nullptr) {
     41    return mozurl_new(aURL, &aSpec, aBaseURL);
     42  }
     43 
     44  nsDependentCSubstring Spec() const { return mozurl_spec(this); }
     45  nsDependentCSubstring Scheme() const { return mozurl_scheme(this); }
     46  nsDependentCSubstring Username() const { return mozurl_username(this); }
     47  nsDependentCSubstring Password() const { return mozurl_password(this); }
     48  // Will return the hostname of URL. If the hostname is an IPv6 address,
     49  // it will be enclosed in square brackets, such as `[::1]`
     50  nsDependentCSubstring Host() const { return mozurl_host(this); }
     51  // Will return the port number, if specified, or -1
     52  int32_t Port() const { return mozurl_port(this); }
     53  int32_t RealPort() const { return mozurl_real_port(this); }
     54  // If the URL's port number is equal to the default port, will only return the
     55  // hostname, otherwise it will return a string of the form `{host}:{port}`
     56  // See: https://url.spec.whatwg.org/#default-port
     57  nsDependentCSubstring HostPort() const { return mozurl_host_port(this); }
     58  nsDependentCSubstring FilePath() const { return mozurl_filepath(this); }
     59  nsDependentCSubstring Path() const { return mozurl_path(this); }
     60  nsDependentCSubstring Query() const { return mozurl_query(this); }
     61  bool HasQuery() const { return mozurl_has_query(this); }
     62  nsDependentCSubstring Ref() const { return mozurl_fragment(this); }
     63  bool HasFragment() const { return mozurl_has_fragment(this); }
     64  nsDependentCSubstring Directory() const { return mozurl_directory(this); }
     65  nsDependentCSubstring PrePath() const { return mozurl_prepath(this); }
     66  nsDependentCSubstring SpecNoRef() const { return mozurl_spec_no_ref(this); }
     67 
     68  // This matches the definition of origins and base domains in nsIPrincipal for
     69  // almost all URIs (some rare file:// URIs don't match and it would be hard to
     70  // fix them). It definitely matches nsIPrincipal for URIs used in quota
     71  // manager and there are checks in quota manager and its clients that prevent
     72  // different definitions (see QuotaManager::IsPrincipalInfoValid).
     73  // See also TestMozURL.cpp which enumerates a huge pile of URIs and checks
     74  // that origin and base domain definitions are in sync.
     75  void Origin(nsACString& aOrigin) const { mozurl_origin(this, &aOrigin); }
     76  bool CannotBeABase() { return mozurl_cannot_be_a_base(this); }
     77 
     78  nsresult GetCommonBase(const MozURL* aOther, MozURL** aCommon) const {
     79    return mozurl_common_base(this, aOther, aCommon);
     80  }
     81  nsresult GetRelative(const MozURL* aOther, nsACString* aRelative) const {
     82    return mozurl_relative(this, aOther, aRelative);
     83  }
     84 
     85  size_t SizeOf() { return mozurl_sizeof(this); }
     86 
     87  class Mutator {
     88   public:
     89    // Calling this method will result in the creation of a new MozURL that
     90    // adopts the mutator's mURL.
     91    // If any of the setters failed with an error code, that error code will be
     92    // returned here. It will also return an error code if Finalize is called
     93    // more than once on the Mutator.
     94    nsresult Finalize(MozURL** aURL) {
     95      nsresult rv = GetStatus();
     96      if (NS_SUCCEEDED(rv)) {
     97        mURL.forget(aURL);
     98      } else {
     99        *aURL = nullptr;
    100      }
    101      return rv;
    102    }
    103 
    104    // These setter methods will return a reference to `this` so that you may
    105    // chain setter operations as such:
    106    //
    107    // RefPtr<MozURL> url2;
    108    // nsresult rv = url->Mutate().SetHostname("newhost"_ns)
    109    //                            .SetFilePath("new/file/path"_ns)
    110    //                            .Finalize(getter_AddRefs(url2));
    111    // if (NS_SUCCEEDED(rv)) { /* use url2 */ }
    112    Mutator& SetScheme(const nsACString& aScheme) {
    113      if (NS_SUCCEEDED(GetStatus())) {
    114        mStatus = mozurl_set_scheme(mURL, &aScheme);
    115      }
    116      return *this;
    117    }
    118    Mutator& SetUsername(const nsACString& aUser) {
    119      if (NS_SUCCEEDED(GetStatus())) {
    120        mStatus = mozurl_set_username(mURL, &aUser);
    121      }
    122      return *this;
    123    }
    124    Mutator& SetPassword(const nsACString& aPassword) {
    125      if (NS_SUCCEEDED(GetStatus())) {
    126        mStatus = mozurl_set_password(mURL, &aPassword);
    127      }
    128      return *this;
    129    }
    130    Mutator& SetHostname(const nsACString& aHost) {
    131      if (NS_SUCCEEDED(GetStatus())) {
    132        mStatus = mozurl_set_hostname(mURL, &aHost);
    133      }
    134      return *this;
    135    }
    136    Mutator& SetHostPort(const nsACString& aHostPort) {
    137      if (NS_SUCCEEDED(GetStatus())) {
    138        mStatus = mozurl_set_host_port(mURL, &aHostPort);
    139      }
    140      return *this;
    141    }
    142    Mutator& SetFilePath(const nsACString& aPath) {
    143      if (NS_SUCCEEDED(GetStatus())) {
    144        mStatus = mozurl_set_pathname(mURL, &aPath);
    145      }
    146      return *this;
    147    }
    148    Mutator& SetQuery(const nsACString& aQuery) {
    149      if (NS_SUCCEEDED(GetStatus())) {
    150        mStatus = mozurl_set_query(mURL, &aQuery);
    151      }
    152      return *this;
    153    }
    154    Mutator& SetRef(const nsACString& aRef) {
    155      if (NS_SUCCEEDED(GetStatus())) {
    156        mStatus = mozurl_set_fragment(mURL, &aRef);
    157      }
    158      return *this;
    159    }
    160    Mutator& SetPort(int32_t aPort) {
    161      if (NS_SUCCEEDED(GetStatus())) {
    162        mStatus = mozurl_set_port_no(mURL, aPort);
    163      }
    164      return *this;
    165    }
    166 
    167    // This method returns the status code of the setter operations.
    168    // If any of the setters failed, it will return the code of the first error
    169    // that occured. If none of the setters failed, it will return NS_OK.
    170    // This method is useful to avoid doing expensive operations when the result
    171    // would not be used because an error occurred. For example:
    172    //
    173    // RefPtr<MozURL> url2;
    174    // MozURL::Mutator mut = url->Mutate();
    175    // mut.SetScheme("!@#$"); // this would fail
    176    // if (NS_SUCCEDED(mut.GetStatus())) {
    177    //   nsAutoCString host(ExpensiveComputing());
    178    //   rv = mut.SetHostname(host).Finalize(getter_AddRefs(url2));
    179    // }
    180    // if (NS_SUCCEEDED(rv)) { /* use url2 */ }
    181    nsresult GetStatus() { return mURL ? mStatus : NS_ERROR_NOT_AVAILABLE; }
    182 
    183    static Result<Mutator, nsresult> FromSpec(
    184        const nsACString& aSpec, const MozURL* aBaseURL = nullptr) {
    185      Mutator m = Mutator(aSpec, aBaseURL);
    186      if (m.mURL) {
    187        MOZ_ASSERT(NS_SUCCEEDED(m.mStatus));
    188        return m;
    189      }
    190 
    191      MOZ_ASSERT(NS_FAILED(m.mStatus));
    192      return Err(m.mStatus);
    193    }
    194 
    195   private:
    196    explicit Mutator(MozURL* aUrl) : mStatus(NS_OK) {
    197      mozurl_clone(aUrl, getter_AddRefs(mURL));
    198    }
    199 
    200    // This is only used to create a mutator from a string without cloning it
    201    // so we avoid a pointless copy in FromSpec. It is important that we
    202    // check the value of mURL afterwards.
    203    explicit Mutator(const nsACString& aSpec,
    204                     const MozURL* aBaseURL = nullptr) {
    205      mStatus = mozurl_new(getter_AddRefs(mURL), &aSpec, aBaseURL);
    206    }
    207    RefPtr<MozURL> mURL;
    208    nsresult mStatus;
    209    friend class MozURL;
    210  };
    211 
    212  Mutator Mutate() { return Mutator(this); }
    213 
    214  // AddRef and Release are non-virtual on this type, and always call into rust.
    215  void AddRef() { mozurl_addref(this); }
    216  void Release() { mozurl_release(this); }
    217 
    218 private:
    219  // Make it a compile time error for C++ code to ever create, destruct, or copy
    220  // MozURL objects. All of these operations will be performed by rust.
    221  MozURL();  /* never defined */
    222  ~MozURL(); /* never defined */
    223  MozURL(const MozURL&) = delete;
    224  MozURL& operator=(const MozURL&) = delete;
    225 };
    226 
    227 }  // namespace net
    228 }  // namespace mozilla
    229 
    230 #endif  // mozURL_h__