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 #include "DefaultURI.h"
6 #include "nsIClassInfoImpl.h"
7 #include "nsIObjectInputStream.h"
8 #include "nsIObjectOutputStream.h"
9 namespace mozilla {
10 namespace net {
11 
12 #define NS_DEFAULTURI_CID                            \
13   { /* 04445aa0-fd27-4c99-bd41-6be6318ae92c */       \
14     0x04445aa0, 0xfd27, 0x4c99, {                    \
15       0xbd, 0x41, 0x6b, 0xe6, 0x31, 0x8a, 0xe9, 0x2c \
16     }                                                \
17   }
18 
19 #define ASSIGN_AND_ADDREF_THIS(ptrToMutator)    \
20   do {                                          \
21     if (ptrToMutator) {                         \
22       *(ptrToMutator) = do_AddRef(this).take(); \
23     }                                           \
24   } while (0)
25 
26 static NS_DEFINE_CID(kDefaultURICID, NS_DEFAULTURI_CID);
27 
28 //----------------------------------------------------------------------------
29 // nsIClassInfo
30 //----------------------------------------------------------------------------
31 
32 NS_IMPL_CLASSINFO(DefaultURI, nullptr, nsIClassInfo::THREADSAFE,
33                   NS_DEFAULTURI_CID)
34 // Empty CI getter. We only need nsIClassInfo for Serialization
35 NS_IMPL_CI_INTERFACE_GETTER0(DefaultURI)
36 
37 //----------------------------------------------------------------------------
38 // nsISupports
39 //----------------------------------------------------------------------------
40 
41 NS_IMPL_ADDREF(DefaultURI)
42 NS_IMPL_RELEASE(DefaultURI)
43 NS_INTERFACE_TABLE_HEAD(DefaultURI)
44   NS_INTERFACE_TABLE(DefaultURI, nsIURI, nsISerializable)
45   NS_INTERFACE_TABLE_TO_MAP_SEGUE
46   NS_IMPL_QUERY_CLASSINFO(DefaultURI)
47   if (aIID.Equals(kDefaultURICID)) {
48     foundInterface = static_cast<nsIURI*>(this);
49   } else
NS_INTERFACE_MAP_ENTRY(nsISizeOf)50     NS_INTERFACE_MAP_ENTRY(nsISizeOf)
51 NS_INTERFACE_MAP_END
52 
53 //----------------------------------------------------------------------------
54 // nsISerializable
55 //----------------------------------------------------------------------------
56 
57 NS_IMETHODIMP DefaultURI::Read(nsIObjectInputStream* aInputStream) {
58   MOZ_ASSERT_UNREACHABLE("Use nsIURIMutator.read() instead");
59   return NS_ERROR_NOT_IMPLEMENTED;
60 }
61 
Write(nsIObjectOutputStream * aOutputStream)62 NS_IMETHODIMP DefaultURI::Write(nsIObjectOutputStream* aOutputStream) {
63   nsAutoCString spec(mURL->Spec());
64   return aOutputStream->WriteStringZ(spec.get());
65 }
66 
67 //----------------------------------------------------------------------------
68 // nsISizeOf
69 //----------------------------------------------------------------------------
70 
SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const71 size_t DefaultURI::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
72   return mURL->SizeOf();
73 }
74 
SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const75 size_t DefaultURI::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
76   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
77 }
78 
79 //----------------------------------------------------------------------------
80 // nsIURI
81 //----------------------------------------------------------------------------
82 
GetSpec(nsACString & aSpec)83 NS_IMETHODIMP DefaultURI::GetSpec(nsACString& aSpec) {
84   aSpec = mURL->Spec();
85   return NS_OK;
86 }
87 
GetPrePath(nsACString & aPrePath)88 NS_IMETHODIMP DefaultURI::GetPrePath(nsACString& aPrePath) {
89   aPrePath = mURL->PrePath();
90   return NS_OK;
91 }
92 
GetScheme(nsACString & aScheme)93 NS_IMETHODIMP DefaultURI::GetScheme(nsACString& aScheme) {
94   aScheme = mURL->Scheme();
95   return NS_OK;
96 }
97 
GetUserPass(nsACString & aUserPass)98 NS_IMETHODIMP DefaultURI::GetUserPass(nsACString& aUserPass) {
99   aUserPass = mURL->Username();
100   nsAutoCString pass(mURL->Password());
101   if (pass.IsEmpty()) {
102     return NS_OK;
103   }
104   aUserPass.Append(':');
105   aUserPass.Append(pass);
106   return NS_OK;
107 }
108 
GetUsername(nsACString & aUsername)109 NS_IMETHODIMP DefaultURI::GetUsername(nsACString& aUsername) {
110   aUsername = mURL->Username();
111   return NS_OK;
112 }
113 
GetPassword(nsACString & aPassword)114 NS_IMETHODIMP DefaultURI::GetPassword(nsACString& aPassword) {
115   aPassword = mURL->Password();
116   return NS_OK;
117 }
118 
GetHostPort(nsACString & aHostPort)119 NS_IMETHODIMP DefaultURI::GetHostPort(nsACString& aHostPort) {
120   aHostPort = mURL->HostPort();
121   return NS_OK;
122 }
123 
GetHost(nsACString & aHost)124 NS_IMETHODIMP DefaultURI::GetHost(nsACString& aHost) {
125   aHost = mURL->Host();
126 
127   // Historically nsIURI.host has always returned an IPv6 address that isn't
128   // enclosed in brackets. Ideally we want to change that, but for the sake of
129   // consitency we'll leave it like that for the moment.
130   // Bug 1603199 should fix this.
131   if (StringBeginsWith(aHost, "["_ns) && StringEndsWith(aHost, "]"_ns) &&
132       aHost.FindChar(':') != kNotFound) {
133     aHost = Substring(aHost, 1, aHost.Length() - 2);
134   }
135   return NS_OK;
136 }
137 
GetPort(int32_t * aPort)138 NS_IMETHODIMP DefaultURI::GetPort(int32_t* aPort) {
139   *aPort = mURL->Port();
140   return NS_OK;
141 }
142 
GetPathQueryRef(nsACString & aPathQueryRef)143 NS_IMETHODIMP DefaultURI::GetPathQueryRef(nsACString& aPathQueryRef) {
144   aPathQueryRef = mURL->Path();
145   return NS_OK;
146 }
147 
Equals(nsIURI * other,bool * _retval)148 NS_IMETHODIMP DefaultURI::Equals(nsIURI* other, bool* _retval) {
149   RefPtr<DefaultURI> otherUri;
150   nsresult rv = other->QueryInterface(kDefaultURICID, getter_AddRefs(otherUri));
151   if (NS_FAILED(rv)) {
152     *_retval = false;
153     return NS_OK;
154   }
155 
156   *_retval = mURL->Spec() == otherUri->mURL->Spec();
157   return NS_OK;
158 }
159 
SchemeIs(const char * scheme,bool * _retval)160 NS_IMETHODIMP DefaultURI::SchemeIs(const char* scheme, bool* _retval) {
161   *_retval = mURL->Scheme().Equals(scheme);
162   return NS_OK;
163 }
164 
Resolve(const nsACString & aRelativePath,nsACString & aResult)165 NS_IMETHODIMP DefaultURI::Resolve(const nsACString& aRelativePath,
166                                   nsACString& aResult) {
167   nsAutoCString scheme;
168   nsresult rv = net_ExtractURLScheme(aRelativePath, scheme);
169   if (NS_SUCCEEDED(rv)) {
170     aResult = aRelativePath;
171     return NS_OK;
172   }
173 
174   // We try to create another URL with this one as its base.
175   RefPtr<MozURL> resolvedURL;
176   rv = MozURL::Init(getter_AddRefs(resolvedURL), aRelativePath, mURL);
177   if (NS_WARN_IF(NS_FAILED(rv))) {
178     // If parsing the relative url fails, we revert to the previous behaviour
179     // and just return the relative path.
180     aResult = aRelativePath;
181     return NS_OK;
182   }
183 
184   aResult = resolvedURL->Spec();
185   return NS_OK;
186 }
187 
GetAsciiSpec(nsACString & aAsciiSpec)188 NS_IMETHODIMP DefaultURI::GetAsciiSpec(nsACString& aAsciiSpec) {
189   return GetSpec(aAsciiSpec);
190 }
191 
GetAsciiHostPort(nsACString & aAsciiHostPort)192 NS_IMETHODIMP DefaultURI::GetAsciiHostPort(nsACString& aAsciiHostPort) {
193   return GetHostPort(aAsciiHostPort);
194 }
195 
GetAsciiHost(nsACString & aAsciiHost)196 NS_IMETHODIMP DefaultURI::GetAsciiHost(nsACString& aAsciiHost) {
197   return GetHost(aAsciiHost);
198 }
199 
GetRef(nsACString & aRef)200 NS_IMETHODIMP DefaultURI::GetRef(nsACString& aRef) {
201   aRef = mURL->Ref();
202   return NS_OK;
203 }
204 
EqualsExceptRef(nsIURI * other,bool * _retval)205 NS_IMETHODIMP DefaultURI::EqualsExceptRef(nsIURI* other, bool* _retval) {
206   RefPtr<DefaultURI> otherUri;
207   nsresult rv = other->QueryInterface(kDefaultURICID, getter_AddRefs(otherUri));
208   if (NS_FAILED(rv)) {
209     *_retval = false;
210     return NS_OK;
211   }
212 
213   *_retval = mURL->SpecNoRef().Equals(otherUri->mURL->SpecNoRef());
214   return NS_OK;
215 }
216 
GetSpecIgnoringRef(nsACString & aSpecIgnoringRef)217 NS_IMETHODIMP DefaultURI::GetSpecIgnoringRef(nsACString& aSpecIgnoringRef) {
218   aSpecIgnoringRef = mURL->SpecNoRef();
219   return NS_OK;
220 }
221 
GetHasRef(bool * aHasRef)222 NS_IMETHODIMP DefaultURI::GetHasRef(bool* aHasRef) {
223   *aHasRef = mURL->HasFragment();
224   return NS_OK;
225 }
226 
GetFilePath(nsACString & aFilePath)227 NS_IMETHODIMP DefaultURI::GetFilePath(nsACString& aFilePath) {
228   aFilePath = mURL->FilePath();
229   return NS_OK;
230 }
231 
GetQuery(nsACString & aQuery)232 NS_IMETHODIMP DefaultURI::GetQuery(nsACString& aQuery) {
233   aQuery = mURL->Query();
234   return NS_OK;
235 }
236 
GetDisplayHost(nsACString & aDisplayHost)237 NS_IMETHODIMP DefaultURI::GetDisplayHost(nsACString& aDisplayHost) {
238   // At the moment it doesn't seem useful to decode the hostname if it happens
239   // to contain punycode.
240   return GetHost(aDisplayHost);
241 }
242 
GetDisplayHostPort(nsACString & aDisplayHostPort)243 NS_IMETHODIMP DefaultURI::GetDisplayHostPort(nsACString& aDisplayHostPort) {
244   // At the moment it doesn't seem useful to decode the hostname if it happens
245   // to contain punycode.
246   return GetHostPort(aDisplayHostPort);
247 }
248 
GetDisplaySpec(nsACString & aDisplaySpec)249 NS_IMETHODIMP DefaultURI::GetDisplaySpec(nsACString& aDisplaySpec) {
250   // At the moment it doesn't seem useful to decode the hostname if it happens
251   // to contain punycode.
252   return GetSpec(aDisplaySpec);
253 }
254 
GetDisplayPrePath(nsACString & aDisplayPrePath)255 NS_IMETHODIMP DefaultURI::GetDisplayPrePath(nsACString& aDisplayPrePath) {
256   // At the moment it doesn't seem useful to decode the hostname if it happens
257   // to contain punycode.
258   return GetPrePath(aDisplayPrePath);
259 }
260 
Mutate(nsIURIMutator ** _retval)261 NS_IMETHODIMP DefaultURI::Mutate(nsIURIMutator** _retval) {
262   RefPtr<DefaultURI::Mutator> mutator = new DefaultURI::Mutator();
263   mutator->Init(this);
264   mutator.forget(_retval);
265   return NS_OK;
266 }
267 
Serialize(ipc::URIParams & aParams)268 void DefaultURI::Serialize(ipc::URIParams& aParams) {
269   ipc::DefaultURIParams params;
270   params.spec() = mURL->Spec();
271   aParams = params;
272 }
273 
274 //----------------------------------------------------------------------------
275 // nsIURIMutator
276 //----------------------------------------------------------------------------
277 
278 NS_IMPL_ADDREF(DefaultURI::Mutator)
NS_IMPL_RELEASE(DefaultURI::Mutator)279 NS_IMPL_RELEASE(DefaultURI::Mutator)
280 NS_IMETHODIMP DefaultURI::Mutator::QueryInterface(REFNSIID aIID,
281                                                   void** aInstancePtr) {
282   NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!");
283   nsISupports* foundInterface = nullptr;
284   if (aIID.Equals(NS_GET_IID(nsIURI))) {
285     RefPtr<DefaultURI> defaultURI = new DefaultURI();
286     mMutator->Finalize(getter_AddRefs(defaultURI->mURL));
287     foundInterface =
288         static_cast<nsISupports*>(static_cast<nsIURI*>((defaultURI.get())));
289     NS_ADDREF(foundInterface);
290     *aInstancePtr = foundInterface;
291     return NS_OK;
292   }
293 
294   if (aIID.Equals(NS_GET_IID(nsIURIMutator)) ||
295       aIID.Equals(NS_GET_IID(nsISupports))) {
296     foundInterface =
297         static_cast<nsISupports*>(static_cast<nsIURIMutator*>(this));
298   } else if (aIID.Equals(NS_GET_IID(nsIURISetters))) {
299     foundInterface =
300         static_cast<nsISupports*>(static_cast<nsIURISetters*>(this));
301   } else if (aIID.Equals(NS_GET_IID(nsIURISetSpec))) {
302     foundInterface =
303         static_cast<nsISupports*>(static_cast<nsIURISetSpec*>(this));
304   } else if (aIID.Equals(NS_GET_IID(nsISerializable))) {
305     foundInterface =
306         static_cast<nsISupports*>(static_cast<nsISerializable*>(this));
307   }
308 
309   if (foundInterface) {
310     NS_ADDREF(foundInterface);
311     *aInstancePtr = foundInterface;
312     return NS_OK;
313   }
314 
315   return NS_NOINTERFACE;
316 }
317 
Read(nsIObjectInputStream * aStream)318 NS_IMETHODIMP DefaultURI::Mutator::Read(nsIObjectInputStream* aStream) {
319   nsAutoCString spec;
320   nsresult rv = aStream->ReadCString(spec);
321   if (NS_FAILED(rv)) {
322     return rv;
323   }
324   return SetSpec(spec, nullptr);
325 }
326 
Deserialize(const mozilla::ipc::URIParams & aParams)327 NS_IMETHODIMP DefaultURI::Mutator::Deserialize(
328     const mozilla::ipc::URIParams& aParams) {
329   if (aParams.type() != ipc::URIParams::TDefaultURIParams) {
330     NS_ERROR("Received unknown parameters from the other process!");
331     return NS_ERROR_FAILURE;
332   }
333 
334   const ipc::DefaultURIParams& params = aParams.get_DefaultURIParams();
335   auto result = MozURL::Mutator::FromSpec(params.spec());
336   if (result.isErr()) {
337     return result.unwrapErr();
338   }
339   mMutator = Some(result.unwrap());
340   return NS_OK;
341 }
342 
Finalize(nsIURI ** aURI)343 NS_IMETHODIMP DefaultURI::Mutator::Finalize(nsIURI** aURI) {
344   if (!mMutator.isSome()) {
345     return NS_ERROR_NOT_AVAILABLE;
346   }
347   RefPtr<DefaultURI> uri = new DefaultURI();
348   mMutator->Finalize(getter_AddRefs(uri->mURL));
349   mMutator = Nothing();
350   uri.forget(aURI);
351   return NS_OK;
352 }
353 
SetSpec(const nsACString & aSpec,nsIURIMutator ** aMutator)354 NS_IMETHODIMP DefaultURI::Mutator::SetSpec(const nsACString& aSpec,
355                                            nsIURIMutator** aMutator) {
356   ASSIGN_AND_ADDREF_THIS(aMutator);
357   auto result = MozURL::Mutator::FromSpec(aSpec);
358   if (result.isErr()) {
359     return result.unwrapErr();
360   }
361   mMutator = Some(result.unwrap());
362   return NS_OK;
363 }
364 
365 NS_IMETHODIMP
SetScheme(const nsACString & aScheme,nsIURIMutator ** aMutator)366 DefaultURI::Mutator::SetScheme(const nsACString& aScheme,
367                                nsIURIMutator** aMutator) {
368   ASSIGN_AND_ADDREF_THIS(aMutator);
369   if (!mMutator.isSome()) {
370     return NS_ERROR_NULL_POINTER;
371   }
372   mMutator->SetScheme(aScheme);
373   return mMutator->GetStatus();
374 }
375 
376 NS_IMETHODIMP
SetUserPass(const nsACString & aUserPass,nsIURIMutator ** aMutator)377 DefaultURI::Mutator::SetUserPass(const nsACString& aUserPass,
378                                  nsIURIMutator** aMutator) {
379   ASSIGN_AND_ADDREF_THIS(aMutator);
380   if (!mMutator.isSome()) {
381     return NS_ERROR_NULL_POINTER;
382   }
383   int32_t index = aUserPass.FindChar(':');
384   if (index == kNotFound) {
385     mMutator->SetUsername(aUserPass);
386     mMutator->SetPassword(""_ns);
387     return mMutator->GetStatus();
388   }
389 
390   mMutator->SetUsername(Substring(aUserPass, 0, index));
391   nsresult rv = mMutator->GetStatus();
392   if (NS_FAILED(rv)) {
393     return rv;
394   }
395   mMutator->SetPassword(Substring(aUserPass, index + 1));
396   rv = mMutator->GetStatus();
397   if (NS_FAILED(rv)) {
398     return rv;
399   }
400   return NS_OK;
401 }
402 
403 NS_IMETHODIMP
SetUsername(const nsACString & aUsername,nsIURIMutator ** aMutator)404 DefaultURI::Mutator::SetUsername(const nsACString& aUsername,
405                                  nsIURIMutator** aMutator) {
406   ASSIGN_AND_ADDREF_THIS(aMutator);
407   if (!mMutator.isSome()) {
408     return NS_ERROR_NULL_POINTER;
409   }
410   mMutator->SetUsername(aUsername);
411   return mMutator->GetStatus();
412 }
413 
414 NS_IMETHODIMP
SetPassword(const nsACString & aPassword,nsIURIMutator ** aMutator)415 DefaultURI::Mutator::SetPassword(const nsACString& aPassword,
416                                  nsIURIMutator** aMutator) {
417   ASSIGN_AND_ADDREF_THIS(aMutator);
418   if (!mMutator.isSome()) {
419     return NS_ERROR_NULL_POINTER;
420   }
421   mMutator->SetPassword(aPassword);
422   return mMutator->GetStatus();
423 }
424 
425 NS_IMETHODIMP
SetHostPort(const nsACString & aHostPort,nsIURIMutator ** aMutator)426 DefaultURI::Mutator::SetHostPort(const nsACString& aHostPort,
427                                  nsIURIMutator** aMutator) {
428   ASSIGN_AND_ADDREF_THIS(aMutator);
429   if (!mMutator.isSome()) {
430     return NS_ERROR_NULL_POINTER;
431   }
432   mMutator->SetHostPort(aHostPort);
433   return mMutator->GetStatus();
434 }
435 
436 NS_IMETHODIMP
SetHost(const nsACString & aHost,nsIURIMutator ** aMutator)437 DefaultURI::Mutator::SetHost(const nsACString& aHost,
438                              nsIURIMutator** aMutator) {
439   ASSIGN_AND_ADDREF_THIS(aMutator);
440   if (!mMutator.isSome()) {
441     return NS_ERROR_NULL_POINTER;
442   }
443   mMutator->SetHostname(aHost);
444   return mMutator->GetStatus();
445 }
446 
447 NS_IMETHODIMP
SetPort(int32_t aPort,nsIURIMutator ** aMutator)448 DefaultURI::Mutator::SetPort(int32_t aPort, nsIURIMutator** aMutator) {
449   ASSIGN_AND_ADDREF_THIS(aMutator);
450   if (!mMutator.isSome()) {
451     return NS_ERROR_NULL_POINTER;
452   }
453   mMutator->SetPort(aPort);
454   return mMutator->GetStatus();
455 }
456 
457 NS_IMETHODIMP
SetPathQueryRef(const nsACString & aPathQueryRef,nsIURIMutator ** aMutator)458 DefaultURI::Mutator::SetPathQueryRef(const nsACString& aPathQueryRef,
459                                      nsIURIMutator** aMutator) {
460   ASSIGN_AND_ADDREF_THIS(aMutator);
461   if (!mMutator.isSome()) {
462     return NS_ERROR_NULL_POINTER;
463   }
464   if (aPathQueryRef.IsEmpty()) {
465     mMutator->SetFilePath(""_ns);
466     mMutator->SetQuery(""_ns);
467     mMutator->SetRef(""_ns);
468     return mMutator->GetStatus();
469   }
470 
471   nsAutoCString pathQueryRef(aPathQueryRef);
472   if (!StringBeginsWith(pathQueryRef, "/"_ns)) {
473     pathQueryRef.Insert('/', 0);
474   }
475 
476   RefPtr<MozURL> url;
477   mMutator->Finalize(getter_AddRefs(url));
478   mMutator = Nothing();
479 
480   auto result = MozURL::Mutator::FromSpec(pathQueryRef, url);
481   if (result.isErr()) {
482     return result.unwrapErr();
483   }
484   mMutator = Some(result.unwrap());
485   return mMutator->GetStatus();
486 }
487 
488 NS_IMETHODIMP
SetRef(const nsACString & aRef,nsIURIMutator ** aMutator)489 DefaultURI::Mutator::SetRef(const nsACString& aRef, nsIURIMutator** aMutator) {
490   ASSIGN_AND_ADDREF_THIS(aMutator);
491   if (!mMutator.isSome()) {
492     return NS_ERROR_NULL_POINTER;
493   }
494   mMutator->SetRef(aRef);
495   return mMutator->GetStatus();
496 }
497 
498 NS_IMETHODIMP
SetFilePath(const nsACString & aFilePath,nsIURIMutator ** aMutator)499 DefaultURI::Mutator::SetFilePath(const nsACString& aFilePath,
500                                  nsIURIMutator** aMutator) {
501   ASSIGN_AND_ADDREF_THIS(aMutator);
502   if (!mMutator.isSome()) {
503     return NS_ERROR_NULL_POINTER;
504   }
505   mMutator->SetFilePath(aFilePath);
506   return mMutator->GetStatus();
507 }
508 
509 NS_IMETHODIMP
SetQuery(const nsACString & aQuery,nsIURIMutator ** aMutator)510 DefaultURI::Mutator::SetQuery(const nsACString& aQuery,
511                               nsIURIMutator** aMutator) {
512   ASSIGN_AND_ADDREF_THIS(aMutator);
513   if (!mMutator.isSome()) {
514     return NS_ERROR_NULL_POINTER;
515   }
516   mMutator->SetQuery(aQuery);
517   return mMutator->GetStatus();
518 }
519 
520 NS_IMETHODIMP
SetQueryWithEncoding(const nsACString & aQuery,const mozilla::Encoding * aEncoding,nsIURIMutator ** aMutator)521 DefaultURI::Mutator::SetQueryWithEncoding(const nsACString& aQuery,
522                                           const mozilla::Encoding* aEncoding,
523                                           nsIURIMutator** aMutator) {
524   ASSIGN_AND_ADDREF_THIS(aMutator);
525   if (!mMutator.isSome()) {
526     return NS_ERROR_NULL_POINTER;
527   }
528   // we only support UTF-8 for DefaultURI
529   mMutator->SetQuery(aQuery);
530   return mMutator->GetStatus();
531 }
532 
533 }  // namespace net
534 }  // namespace mozilla
535