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