Merge mozilla-central to autoland. CLOSED TREE
[gecko.git] / netwerk / base / DefaultURI.cpp
blob0a70218af5e825d491b3e6d45039f3859e45d08f
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/. */
5 #include "DefaultURI.h"
6 #include "nsIClassInfoImpl.h"
7 #include "nsIObjectInputStream.h"
8 #include "nsIObjectOutputStream.h"
9 #include "nsURLHelper.h"
11 #include "mozilla/ipc/URIParams.h"
13 namespace mozilla {
14 namespace net {
16 #define NS_DEFAULTURI_CID \
17 { /* 04445aa0-fd27-4c99-bd41-6be6318ae92c */ \
18 0x04445aa0, 0xfd27, 0x4c99, { \
19 0xbd, 0x41, 0x6b, 0xe6, 0x31, 0x8a, 0xe9, 0x2c \
20 } \
23 #define ASSIGN_AND_ADDREF_THIS(ptrToMutator) \
24 do { \
25 if (ptrToMutator) { \
26 *(ptrToMutator) = do_AddRef(this).take(); \
27 } \
28 } while (0)
30 static NS_DEFINE_CID(kDefaultURICID, NS_DEFAULTURI_CID);
32 //----------------------------------------------------------------------------
33 // nsIClassInfo
34 //----------------------------------------------------------------------------
36 NS_IMPL_CLASSINFO(DefaultURI, nullptr, nsIClassInfo::THREADSAFE,
37 NS_DEFAULTURI_CID)
38 // Empty CI getter. We only need nsIClassInfo for Serialization
39 NS_IMPL_CI_INTERFACE_GETTER0(DefaultURI)
41 //----------------------------------------------------------------------------
42 // nsISupports
43 //----------------------------------------------------------------------------
45 NS_IMPL_ADDREF(DefaultURI)
46 NS_IMPL_RELEASE(DefaultURI)
47 NS_INTERFACE_TABLE_HEAD(DefaultURI)
48 NS_INTERFACE_TABLE(DefaultURI, nsIURI, nsISerializable)
49 NS_INTERFACE_TABLE_TO_MAP_SEGUE
50 NS_IMPL_QUERY_CLASSINFO(DefaultURI)
51 if (aIID.Equals(kDefaultURICID)) {
52 foundInterface = static_cast<nsIURI*>(this);
53 } else
54 NS_INTERFACE_MAP_ENTRY(nsISizeOf)
55 NS_INTERFACE_MAP_END
57 //----------------------------------------------------------------------------
58 // nsISerializable
59 //----------------------------------------------------------------------------
61 NS_IMETHODIMP DefaultURI::Read(nsIObjectInputStream* aInputStream) {
62 MOZ_ASSERT_UNREACHABLE("Use nsIURIMutator.read() instead");
63 return NS_ERROR_NOT_IMPLEMENTED;
66 NS_IMETHODIMP DefaultURI::Write(nsIObjectOutputStream* aOutputStream) {
67 nsAutoCString spec(mURL->Spec());
68 return aOutputStream->WriteStringZ(spec.get());
71 //----------------------------------------------------------------------------
72 // nsISizeOf
73 //----------------------------------------------------------------------------
75 size_t DefaultURI::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
76 return mURL->SizeOf();
79 size_t DefaultURI::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
80 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
83 //----------------------------------------------------------------------------
84 // nsIURI
85 //----------------------------------------------------------------------------
87 NS_IMETHODIMP DefaultURI::GetSpec(nsACString& aSpec) {
88 aSpec = mURL->Spec();
89 return NS_OK;
92 NS_IMETHODIMP DefaultURI::GetPrePath(nsACString& aPrePath) {
93 aPrePath = mURL->PrePath();
94 return NS_OK;
97 NS_IMETHODIMP DefaultURI::GetScheme(nsACString& aScheme) {
98 aScheme = mURL->Scheme();
99 return NS_OK;
102 NS_IMETHODIMP DefaultURI::GetUserPass(nsACString& aUserPass) {
103 aUserPass = mURL->Username();
104 nsAutoCString pass(mURL->Password());
105 if (pass.IsEmpty()) {
106 return NS_OK;
108 aUserPass.Append(':');
109 aUserPass.Append(pass);
110 return NS_OK;
113 NS_IMETHODIMP DefaultURI::GetUsername(nsACString& aUsername) {
114 aUsername = mURL->Username();
115 return NS_OK;
118 NS_IMETHODIMP DefaultURI::GetPassword(nsACString& aPassword) {
119 aPassword = mURL->Password();
120 return NS_OK;
123 NS_IMETHODIMP DefaultURI::GetHostPort(nsACString& aHostPort) {
124 aHostPort = mURL->HostPort();
125 return NS_OK;
128 NS_IMETHODIMP DefaultURI::GetHost(nsACString& aHost) {
129 aHost = mURL->Host();
131 // Historically nsIURI.host has always returned an IPv6 address that isn't
132 // enclosed in brackets. Ideally we want to change that, but for the sake of
133 // consitency we'll leave it like that for the moment.
134 // Bug 1603199 should fix this.
135 if (StringBeginsWith(aHost, "["_ns) && StringEndsWith(aHost, "]"_ns) &&
136 aHost.FindChar(':') != kNotFound) {
137 aHost = Substring(aHost, 1, aHost.Length() - 2);
139 return NS_OK;
142 NS_IMETHODIMP DefaultURI::GetPort(int32_t* aPort) {
143 *aPort = mURL->Port();
144 return NS_OK;
147 NS_IMETHODIMP DefaultURI::GetPathQueryRef(nsACString& aPathQueryRef) {
148 aPathQueryRef = mURL->Path();
149 return NS_OK;
152 NS_IMETHODIMP DefaultURI::Equals(nsIURI* other, bool* _retval) {
153 if (!other) {
154 *_retval = false;
155 return NS_OK;
157 RefPtr<DefaultURI> otherUri;
158 nsresult rv = other->QueryInterface(kDefaultURICID, getter_AddRefs(otherUri));
159 if (NS_FAILED(rv)) {
160 *_retval = false;
161 return NS_OK;
164 *_retval = mURL->Spec() == otherUri->mURL->Spec();
165 return NS_OK;
168 NS_IMETHODIMP DefaultURI::SchemeIs(const char* scheme, bool* _retval) {
169 if (!scheme) {
170 *_retval = false;
171 return NS_OK;
173 *_retval = mURL->Scheme().Equals(scheme);
174 return NS_OK;
177 NS_IMETHODIMP DefaultURI::Resolve(const nsACString& aRelativePath,
178 nsACString& aResult) {
179 nsAutoCString scheme;
180 nsresult rv = net_ExtractURLScheme(aRelativePath, scheme);
181 if (NS_SUCCEEDED(rv)) {
182 aResult = aRelativePath;
183 return NS_OK;
186 // We try to create another URL with this one as its base.
187 RefPtr<MozURL> resolvedURL;
188 rv = MozURL::Init(getter_AddRefs(resolvedURL), aRelativePath, mURL);
189 if (NS_WARN_IF(NS_FAILED(rv))) {
190 // If parsing the relative url fails, we revert to the previous behaviour
191 // and just return the relative path.
192 aResult = aRelativePath;
193 return NS_OK;
196 aResult = resolvedURL->Spec();
197 return NS_OK;
200 NS_IMETHODIMP DefaultURI::GetAsciiSpec(nsACString& aAsciiSpec) {
201 return GetSpec(aAsciiSpec);
204 NS_IMETHODIMP DefaultURI::GetAsciiHostPort(nsACString& aAsciiHostPort) {
205 return GetHostPort(aAsciiHostPort);
208 NS_IMETHODIMP DefaultURI::GetAsciiHost(nsACString& aAsciiHost) {
209 return GetHost(aAsciiHost);
212 NS_IMETHODIMP DefaultURI::GetRef(nsACString& aRef) {
213 aRef = mURL->Ref();
214 return NS_OK;
217 NS_IMETHODIMP DefaultURI::EqualsExceptRef(nsIURI* other, bool* _retval) {
218 if (!_retval || !other) {
219 return NS_ERROR_NULL_POINTER;
221 RefPtr<DefaultURI> otherUri;
222 nsresult rv = other->QueryInterface(kDefaultURICID, getter_AddRefs(otherUri));
223 if (NS_FAILED(rv)) {
224 *_retval = false;
225 return NS_OK;
228 *_retval = mURL->SpecNoRef().Equals(otherUri->mURL->SpecNoRef());
229 return NS_OK;
232 NS_IMETHODIMP DefaultURI::GetSpecIgnoringRef(nsACString& aSpecIgnoringRef) {
233 aSpecIgnoringRef = mURL->SpecNoRef();
234 return NS_OK;
237 NS_IMETHODIMP DefaultURI::GetHasRef(bool* aHasRef) {
238 *aHasRef = mURL->HasFragment();
239 return NS_OK;
242 NS_IMETHODIMP DefaultURI::GetHasUserPass(bool* aHasUserPass) {
243 *aHasUserPass = !mURL->Username().IsEmpty() || !mURL->Password().IsEmpty();
244 return NS_OK;
247 NS_IMETHODIMP DefaultURI::GetFilePath(nsACString& aFilePath) {
248 aFilePath = mURL->FilePath();
249 return NS_OK;
252 NS_IMETHODIMP DefaultURI::GetQuery(nsACString& aQuery) {
253 aQuery = mURL->Query();
254 return NS_OK;
257 NS_IMETHODIMP DefaultURI::GetHasQuery(bool* aHasQuery) {
258 *aHasQuery = mURL->HasQuery();
259 return NS_OK;
262 NS_IMETHODIMP DefaultURI::GetDisplayHost(nsACString& aDisplayHost) {
263 // At the moment it doesn't seem useful to decode the hostname if it happens
264 // to contain punycode.
265 return GetHost(aDisplayHost);
268 NS_IMETHODIMP DefaultURI::GetDisplayHostPort(nsACString& aDisplayHostPort) {
269 // At the moment it doesn't seem useful to decode the hostname if it happens
270 // to contain punycode.
271 return GetHostPort(aDisplayHostPort);
274 NS_IMETHODIMP DefaultURI::GetDisplaySpec(nsACString& aDisplaySpec) {
275 // At the moment it doesn't seem useful to decode the hostname if it happens
276 // to contain punycode.
277 return GetSpec(aDisplaySpec);
280 NS_IMETHODIMP DefaultURI::GetDisplayPrePath(nsACString& aDisplayPrePath) {
281 // At the moment it doesn't seem useful to decode the hostname if it happens
282 // to contain punycode.
283 return GetPrePath(aDisplayPrePath);
286 NS_IMETHODIMP DefaultURI::Mutate(nsIURIMutator** _retval) {
287 RefPtr<DefaultURI::Mutator> mutator = new DefaultURI::Mutator();
288 mutator->Init(this);
289 mutator.forget(_retval);
290 return NS_OK;
293 void DefaultURI::Serialize(ipc::URIParams& aParams) {
294 ipc::DefaultURIParams params;
295 params.spec() = mURL->Spec();
296 aParams = params;
299 //----------------------------------------------------------------------------
300 // nsIURIMutator
301 //----------------------------------------------------------------------------
303 NS_IMPL_ADDREF(DefaultURI::Mutator)
304 NS_IMPL_RELEASE(DefaultURI::Mutator)
305 NS_IMETHODIMP DefaultURI::Mutator::QueryInterface(REFNSIID aIID,
306 void** aInstancePtr) {
307 NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!");
308 nsISupports* foundInterface = nullptr;
309 if (aIID.Equals(NS_GET_IID(nsIURI))) {
310 RefPtr<DefaultURI> defaultURI = new DefaultURI();
311 mMutator->Finalize(getter_AddRefs(defaultURI->mURL));
312 foundInterface =
313 static_cast<nsISupports*>(static_cast<nsIURI*>((defaultURI.get())));
314 NS_ADDREF(foundInterface);
315 *aInstancePtr = foundInterface;
316 return NS_OK;
319 if (aIID.Equals(NS_GET_IID(nsIURIMutator)) ||
320 aIID.Equals(NS_GET_IID(nsISupports))) {
321 foundInterface =
322 static_cast<nsISupports*>(static_cast<nsIURIMutator*>(this));
323 } else if (aIID.Equals(NS_GET_IID(nsIURISetters))) {
324 foundInterface =
325 static_cast<nsISupports*>(static_cast<nsIURISetters*>(this));
326 } else if (aIID.Equals(NS_GET_IID(nsIURISetSpec))) {
327 foundInterface =
328 static_cast<nsISupports*>(static_cast<nsIURISetSpec*>(this));
329 } else if (aIID.Equals(NS_GET_IID(nsISerializable))) {
330 foundInterface =
331 static_cast<nsISupports*>(static_cast<nsISerializable*>(this));
334 if (foundInterface) {
335 NS_ADDREF(foundInterface);
336 *aInstancePtr = foundInterface;
337 return NS_OK;
340 return NS_NOINTERFACE;
343 NS_IMETHODIMP DefaultURI::Mutator::Read(nsIObjectInputStream* aStream) {
344 nsAutoCString spec;
345 nsresult rv = aStream->ReadCString(spec);
346 if (NS_FAILED(rv)) {
347 return rv;
349 return SetSpec(spec, nullptr);
352 NS_IMETHODIMP DefaultURI::Mutator::Deserialize(
353 const mozilla::ipc::URIParams& aParams) {
354 if (aParams.type() != ipc::URIParams::TDefaultURIParams) {
355 NS_ERROR("Received unknown parameters from the other process!");
356 return NS_ERROR_FAILURE;
359 const ipc::DefaultURIParams& params = aParams.get_DefaultURIParams();
360 auto result = MozURL::Mutator::FromSpec(params.spec());
361 if (result.isErr()) {
362 return result.unwrapErr();
364 mMutator = Some(result.unwrap());
365 return NS_OK;
368 NS_IMETHODIMP DefaultURI::Mutator::Finalize(nsIURI** aURI) {
369 if (!mMutator.isSome()) {
370 return NS_ERROR_NOT_AVAILABLE;
372 RefPtr<DefaultURI> uri = new DefaultURI();
373 mMutator->Finalize(getter_AddRefs(uri->mURL));
374 mMutator = Nothing();
375 uri.forget(aURI);
376 return NS_OK;
379 NS_IMETHODIMP DefaultURI::Mutator::SetSpec(const nsACString& aSpec,
380 nsIURIMutator** aMutator) {
381 ASSIGN_AND_ADDREF_THIS(aMutator);
382 auto result = MozURL::Mutator::FromSpec(aSpec);
383 if (result.isErr()) {
384 return result.unwrapErr();
386 mMutator = Some(result.unwrap());
387 return NS_OK;
390 NS_IMETHODIMP
391 DefaultURI::Mutator::SetScheme(const nsACString& aScheme,
392 nsIURIMutator** aMutator) {
393 ASSIGN_AND_ADDREF_THIS(aMutator);
394 if (!mMutator.isSome()) {
395 return NS_ERROR_NULL_POINTER;
397 mMutator->SetScheme(aScheme);
398 return mMutator->GetStatus();
401 NS_IMETHODIMP
402 DefaultURI::Mutator::SetUserPass(const nsACString& aUserPass,
403 nsIURIMutator** aMutator) {
404 ASSIGN_AND_ADDREF_THIS(aMutator);
405 if (!mMutator.isSome()) {
406 return NS_ERROR_NULL_POINTER;
408 int32_t index = aUserPass.FindChar(':');
409 if (index == kNotFound) {
410 mMutator->SetUsername(aUserPass);
411 mMutator->SetPassword(""_ns);
412 return mMutator->GetStatus();
415 mMutator->SetUsername(Substring(aUserPass, 0, index));
416 nsresult rv = mMutator->GetStatus();
417 if (NS_FAILED(rv)) {
418 return rv;
420 mMutator->SetPassword(Substring(aUserPass, index + 1));
421 rv = mMutator->GetStatus();
422 if (NS_FAILED(rv)) {
423 return rv;
425 return NS_OK;
428 NS_IMETHODIMP
429 DefaultURI::Mutator::SetUsername(const nsACString& aUsername,
430 nsIURIMutator** aMutator) {
431 ASSIGN_AND_ADDREF_THIS(aMutator);
432 if (!mMutator.isSome()) {
433 return NS_ERROR_NULL_POINTER;
435 mMutator->SetUsername(aUsername);
436 return mMutator->GetStatus();
439 NS_IMETHODIMP
440 DefaultURI::Mutator::SetPassword(const nsACString& aPassword,
441 nsIURIMutator** aMutator) {
442 ASSIGN_AND_ADDREF_THIS(aMutator);
443 if (!mMutator.isSome()) {
444 return NS_ERROR_NULL_POINTER;
446 mMutator->SetPassword(aPassword);
447 return mMutator->GetStatus();
450 NS_IMETHODIMP
451 DefaultURI::Mutator::SetHostPort(const nsACString& aHostPort,
452 nsIURIMutator** aMutator) {
453 ASSIGN_AND_ADDREF_THIS(aMutator);
454 if (!mMutator.isSome()) {
455 return NS_ERROR_NULL_POINTER;
457 mMutator->SetHostPort(aHostPort);
458 return mMutator->GetStatus();
461 NS_IMETHODIMP
462 DefaultURI::Mutator::SetHost(const nsACString& aHost,
463 nsIURIMutator** aMutator) {
464 ASSIGN_AND_ADDREF_THIS(aMutator);
465 if (!mMutator.isSome()) {
466 return NS_ERROR_NULL_POINTER;
468 mMutator->SetHostname(aHost);
469 return mMutator->GetStatus();
472 NS_IMETHODIMP
473 DefaultURI::Mutator::SetPort(int32_t aPort, nsIURIMutator** aMutator) {
474 ASSIGN_AND_ADDREF_THIS(aMutator);
475 if (!mMutator.isSome()) {
476 return NS_ERROR_NULL_POINTER;
478 mMutator->SetPort(aPort);
479 return mMutator->GetStatus();
482 NS_IMETHODIMP
483 DefaultURI::Mutator::SetPathQueryRef(const nsACString& aPathQueryRef,
484 nsIURIMutator** aMutator) {
485 ASSIGN_AND_ADDREF_THIS(aMutator);
486 if (!mMutator.isSome()) {
487 return NS_ERROR_NULL_POINTER;
489 if (aPathQueryRef.IsEmpty()) {
490 mMutator->SetFilePath(""_ns);
491 mMutator->SetQuery(""_ns);
492 mMutator->SetRef(""_ns);
493 return mMutator->GetStatus();
496 RefPtr<MozURL> url;
497 mMutator->Finalize(getter_AddRefs(url));
498 mMutator = Nothing();
500 if (!url) {
501 return NS_ERROR_FAILURE;
504 nsAutoCString pathQueryRef(aPathQueryRef);
505 if (url->CannotBeABase()) {
506 // If the base URL cannot be a base, then setting the pathQueryRef
507 // needs to change everything after the scheme.
508 pathQueryRef.Insert(":", 0);
509 pathQueryRef.Insert(url->Scheme(), 0);
510 // Clear the URL to make sure FromSpec creates an absolute URL
511 url = nullptr;
512 } else if (!StringBeginsWith(pathQueryRef, "/"_ns)) {
513 // If the base URL can be a base, make sure the path
514 // begins with a /
515 pathQueryRef.Insert('/', 0);
518 auto result = MozURL::Mutator::FromSpec(pathQueryRef, url);
519 if (result.isErr()) {
520 return result.unwrapErr();
522 mMutator = Some(result.unwrap());
523 return mMutator->GetStatus();
526 NS_IMETHODIMP
527 DefaultURI::Mutator::SetRef(const nsACString& aRef, nsIURIMutator** aMutator) {
528 ASSIGN_AND_ADDREF_THIS(aMutator);
529 if (!mMutator.isSome()) {
530 return NS_ERROR_NULL_POINTER;
532 mMutator->SetRef(aRef);
533 return mMutator->GetStatus();
536 NS_IMETHODIMP
537 DefaultURI::Mutator::SetFilePath(const nsACString& aFilePath,
538 nsIURIMutator** aMutator) {
539 ASSIGN_AND_ADDREF_THIS(aMutator);
540 if (!mMutator.isSome()) {
541 return NS_ERROR_NULL_POINTER;
543 mMutator->SetFilePath(aFilePath);
544 return mMutator->GetStatus();
547 NS_IMETHODIMP
548 DefaultURI::Mutator::SetQuery(const nsACString& aQuery,
549 nsIURIMutator** aMutator) {
550 ASSIGN_AND_ADDREF_THIS(aMutator);
551 if (!mMutator.isSome()) {
552 return NS_ERROR_NULL_POINTER;
554 mMutator->SetQuery(aQuery);
555 return mMutator->GetStatus();
558 NS_IMETHODIMP
559 DefaultURI::Mutator::SetQueryWithEncoding(const nsACString& aQuery,
560 const mozilla::Encoding* aEncoding,
561 nsIURIMutator** aMutator) {
562 ASSIGN_AND_ADDREF_THIS(aMutator);
563 if (!mMutator.isSome()) {
564 return NS_ERROR_NULL_POINTER;
566 // we only support UTF-8 for DefaultURI
567 mMutator->SetQuery(aQuery);
568 return mMutator->GetStatus();
571 } // namespace net
572 } // namespace mozilla