Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "mozilla/DebugOnly.h"
7 :
8 : #undef LOG
9 : #include "IPCMessageUtils.h"
10 :
11 : #include "nsSimpleURI.h"
12 : #include "nscore.h"
13 : #include "nsString.h"
14 : #include "plstr.h"
15 : #include "nsURLHelper.h"
16 : #include "nsNetCID.h"
17 : #include "nsIObjectInputStream.h"
18 : #include "nsIObjectOutputStream.h"
19 : #include "nsEscape.h"
20 : #include "nsError.h"
21 : #include "nsIIPCSerializableURI.h"
22 : #include "mozilla/MemoryReporting.h"
23 : #include "mozilla/ipc/URIUtils.h"
24 :
25 : using namespace mozilla::ipc;
26 :
27 : namespace mozilla {
28 : namespace net {
29 :
30 : static NS_DEFINE_CID(kThisSimpleURIImplementationCID,
31 : NS_THIS_SIMPLEURI_IMPLEMENTATION_CID);
32 : static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
33 :
34 : /* static */ already_AddRefed<nsSimpleURI>
35 0 : nsSimpleURI::From(nsIURI* aURI)
36 : {
37 0 : RefPtr<nsSimpleURI> uri;
38 0 : nsresult rv = aURI->QueryInterface(kThisSimpleURIImplementationCID,
39 0 : getter_AddRefs(uri));
40 0 : if (NS_FAILED(rv)) {
41 0 : return nullptr;
42 : }
43 :
44 0 : return uri.forget();
45 : }
46 :
47 : ////////////////////////////////////////////////////////////////////////////////
48 : // nsSimpleURI methods:
49 :
50 107 : nsSimpleURI::nsSimpleURI()
51 : : mMutable(true)
52 : , mIsRefValid(false)
53 107 : , mIsQueryValid(false)
54 : {
55 107 : }
56 :
57 95 : nsSimpleURI::~nsSimpleURI()
58 : {
59 140 : }
60 :
61 1467 : NS_IMPL_ADDREF(nsSimpleURI)
62 1263 : NS_IMPL_RELEASE(nsSimpleURI)
63 1325 : NS_INTERFACE_TABLE_HEAD(nsSimpleURI)
64 1325 : NS_INTERFACE_TABLE(nsSimpleURI, nsIURI, nsISerializable,
65 : nsIClassInfo, nsIMutable, nsIIPCSerializableURI)
66 1325 : NS_INTERFACE_TABLE_TO_MAP_SEGUE
67 381 : if (aIID.Equals(kThisSimpleURIImplementationCID))
68 5 : foundInterface = static_cast<nsIURI*>(this);
69 : else
70 376 : NS_INTERFACE_MAP_ENTRY(nsISizeOf)
71 376 : NS_INTERFACE_MAP_END
72 :
73 : ////////////////////////////////////////////////////////////////////////////////
74 : // nsISerializable methods:
75 :
76 : NS_IMETHODIMP
77 0 : nsSimpleURI::Read(nsIObjectInputStream* aStream)
78 : {
79 : nsresult rv;
80 :
81 : bool isMutable;
82 0 : rv = aStream->ReadBoolean(&isMutable);
83 0 : if (NS_FAILED(rv)) return rv;
84 0 : mMutable = isMutable;
85 :
86 0 : rv = aStream->ReadCString(mScheme);
87 0 : if (NS_FAILED(rv)) return rv;
88 :
89 0 : rv = aStream->ReadCString(mPath);
90 0 : if (NS_FAILED(rv)) return rv;
91 :
92 : bool isRefValid;
93 0 : rv = aStream->ReadBoolean(&isRefValid);
94 0 : if (NS_FAILED(rv)) return rv;
95 0 : mIsRefValid = isRefValid;
96 :
97 0 : if (isRefValid) {
98 0 : rv = aStream->ReadCString(mRef);
99 0 : if (NS_FAILED(rv)) return rv;
100 : } else {
101 0 : mRef.Truncate(); // invariant: mRef should be empty when it's not valid
102 : }
103 :
104 : bool isQueryValid;
105 0 : rv = aStream->ReadBoolean(&isQueryValid);
106 0 : if (NS_FAILED(rv)) return rv;
107 0 : mIsQueryValid = isQueryValid;
108 :
109 0 : if (isQueryValid) {
110 0 : rv = aStream->ReadCString(mQuery);
111 0 : if (NS_FAILED(rv)) return rv;
112 : } else {
113 0 : mQuery.Truncate(); // invariant: mQuery should be empty when it's not valid
114 : }
115 :
116 0 : return NS_OK;
117 : }
118 :
119 : NS_IMETHODIMP
120 0 : nsSimpleURI::Write(nsIObjectOutputStream* aStream)
121 : {
122 : nsresult rv;
123 :
124 0 : rv = aStream->WriteBoolean(mMutable);
125 0 : if (NS_FAILED(rv)) return rv;
126 :
127 0 : rv = aStream->WriteStringZ(mScheme.get());
128 0 : if (NS_FAILED(rv)) return rv;
129 :
130 0 : rv = aStream->WriteStringZ(mPath.get());
131 0 : if (NS_FAILED(rv)) return rv;
132 :
133 0 : rv = aStream->WriteBoolean(mIsRefValid);
134 0 : if (NS_FAILED(rv)) return rv;
135 :
136 0 : if (mIsRefValid) {
137 0 : rv = aStream->WriteStringZ(mRef.get());
138 0 : if (NS_FAILED(rv)) return rv;
139 : }
140 :
141 0 : rv = aStream->WriteBoolean(mIsQueryValid);
142 0 : if (NS_FAILED(rv)) return rv;
143 :
144 0 : if (mIsQueryValid) {
145 0 : rv = aStream->WriteStringZ(mQuery.get());
146 0 : if (NS_FAILED(rv)) return rv;
147 : }
148 :
149 0 : return NS_OK;
150 : }
151 :
152 : ////////////////////////////////////////////////////////////////////////////////
153 : // nsIIPCSerializableURI methods:
154 :
155 : void
156 0 : nsSimpleURI::Serialize(URIParams& aParams)
157 : {
158 0 : SimpleURIParams params;
159 :
160 0 : params.scheme() = mScheme;
161 0 : params.path() = mPath;
162 :
163 0 : if (mIsRefValid) {
164 0 : params.ref() = mRef;
165 : } else {
166 0 : params.ref().SetIsVoid(true);
167 : }
168 :
169 0 : if (mIsQueryValid) {
170 0 : params.query() = mQuery;
171 : } else {
172 0 : params.query().SetIsVoid(true);
173 : }
174 :
175 0 : params.isMutable() = mMutable;
176 :
177 0 : aParams = params;
178 0 : }
179 :
180 : bool
181 0 : nsSimpleURI::Deserialize(const URIParams& aParams)
182 : {
183 0 : if (aParams.type() != URIParams::TSimpleURIParams) {
184 0 : NS_ERROR("Received unknown parameters from the other process!");
185 0 : return false;
186 : }
187 :
188 0 : const SimpleURIParams& params = aParams.get_SimpleURIParams();
189 :
190 0 : mScheme = params.scheme();
191 0 : mPath = params.path();
192 :
193 0 : if (params.ref().IsVoid()) {
194 0 : mRef.Truncate();
195 0 : mIsRefValid = false;
196 : } else {
197 0 : mRef = params.ref();
198 0 : mIsRefValid = true;
199 : }
200 :
201 0 : if (params.query().IsVoid()) {
202 0 : mQuery.Truncate();
203 0 : mIsQueryValid = false;
204 : } else {
205 0 : mQuery = params.query();
206 0 : mIsQueryValid = true;
207 : }
208 :
209 0 : mMutable = params.isMutable();
210 :
211 0 : return true;
212 : }
213 :
214 : ////////////////////////////////////////////////////////////////////////////////
215 : // nsIURI methods:
216 :
217 : NS_IMETHODIMP
218 157 : nsSimpleURI::GetSpec(nsACString &result)
219 : {
220 785 : if (!result.Assign(mScheme, fallible) ||
221 942 : !result.Append(NS_LITERAL_CSTRING(":"), fallible) ||
222 157 : !result.Append(mPath, fallible)) {
223 0 : return NS_ERROR_OUT_OF_MEMORY;
224 : }
225 :
226 157 : if (mIsQueryValid) {
227 0 : if (!result.Append(NS_LITERAL_CSTRING("?"), fallible) ||
228 0 : !result.Append(mQuery, fallible)) {
229 0 : return NS_ERROR_OUT_OF_MEMORY;
230 : }
231 : } else {
232 157 : MOZ_ASSERT(mQuery.IsEmpty(), "mIsQueryValid/mQuery invariant broken");
233 : }
234 :
235 157 : if (mIsRefValid) {
236 0 : if (!result.Append(NS_LITERAL_CSTRING("#"), fallible) ||
237 0 : !result.Append(mRef, fallible)) {
238 0 : return NS_ERROR_OUT_OF_MEMORY;
239 : }
240 : } else {
241 157 : MOZ_ASSERT(mRef.IsEmpty(), "mIsRefValid/mRef invariant broken");
242 : }
243 :
244 157 : return NS_OK;
245 : }
246 :
247 : // result may contain unescaped UTF-8 characters
248 : NS_IMETHODIMP
249 0 : nsSimpleURI::GetSpecIgnoringRef(nsACString &result)
250 : {
251 0 : result = mScheme + NS_LITERAL_CSTRING(":") + mPath;
252 0 : if (mIsQueryValid) {
253 0 : result += NS_LITERAL_CSTRING("?") + mQuery;
254 : }
255 0 : return NS_OK;
256 : }
257 :
258 : NS_IMETHODIMP
259 0 : nsSimpleURI::GetDisplaySpec(nsACString &aUnicodeSpec)
260 : {
261 0 : return GetSpec(aUnicodeSpec);
262 : }
263 :
264 : NS_IMETHODIMP
265 0 : nsSimpleURI::GetDisplayHostPort(nsACString &aUnicodeHostPort)
266 : {
267 0 : return GetHostPort(aUnicodeHostPort);
268 : }
269 :
270 : NS_IMETHODIMP
271 0 : nsSimpleURI::GetDisplayHost(nsACString &aUnicodeHost)
272 : {
273 0 : return GetHost(aUnicodeHost);
274 : }
275 :
276 : NS_IMETHODIMP
277 11 : nsSimpleURI::GetHasRef(bool *result)
278 : {
279 11 : *result = mIsRefValid;
280 11 : return NS_OK;
281 : }
282 :
283 : NS_IMETHODIMP
284 85 : nsSimpleURI::SetSpec(const nsACString &aSpec)
285 : {
286 85 : NS_ENSURE_STATE(mMutable);
287 :
288 : // filter out unexpected chars "\r\n\t" if necessary
289 170 : nsAutoCString filteredSpec;
290 85 : net_FilterURIString(aSpec, filteredSpec);
291 :
292 : // nsSimpleURI currently restricts the charset to US-ASCII
293 170 : nsAutoCString spec;
294 85 : nsresult rv = NS_EscapeURL(filteredSpec, esc_OnlyNonASCII, spec, fallible);
295 85 : if (NS_FAILED(rv)) {
296 0 : return rv;
297 : }
298 :
299 85 : int32_t colonPos = spec.FindChar(':');
300 85 : if (colonPos < 0 || !net_IsValidScheme(spec.get(), colonPos))
301 0 : return NS_ERROR_MALFORMED_URI;
302 :
303 85 : mScheme.Truncate();
304 170 : DebugOnly<int32_t> n = spec.Left(mScheme, colonPos);
305 85 : NS_ASSERTION(n == colonPos, "Left failed");
306 85 : ToLowerCase(mScheme);
307 :
308 : // This sets mPath, mQuery and mRef.
309 85 : return SetPath(Substring(spec, colonPos + 1));
310 : }
311 :
312 : NS_IMETHODIMP
313 115 : nsSimpleURI::GetScheme(nsACString &result)
314 : {
315 115 : result = mScheme;
316 115 : return NS_OK;
317 : }
318 :
319 : NS_IMETHODIMP
320 0 : nsSimpleURI::SetScheme(const nsACString &scheme)
321 : {
322 0 : NS_ENSURE_STATE(mMutable);
323 :
324 0 : const nsPromiseFlatCString &flat = PromiseFlatCString(scheme);
325 0 : if (!net_IsValidScheme(flat)) {
326 0 : NS_WARNING("the given url scheme contains invalid characters");
327 0 : return NS_ERROR_MALFORMED_URI;
328 : }
329 :
330 0 : mScheme = scheme;
331 0 : ToLowerCase(mScheme);
332 0 : return NS_OK;
333 : }
334 :
335 : NS_IMETHODIMP
336 2 : nsSimpleURI::GetPrePath(nsACString &result)
337 : {
338 2 : result = mScheme + NS_LITERAL_CSTRING(":");
339 2 : return NS_OK;
340 : }
341 :
342 : NS_IMETHODIMP
343 12 : nsSimpleURI::GetUserPass(nsACString &result)
344 : {
345 12 : return NS_ERROR_FAILURE;
346 : }
347 :
348 : NS_IMETHODIMP
349 0 : nsSimpleURI::SetUserPass(const nsACString &userPass)
350 : {
351 0 : return NS_ERROR_FAILURE;
352 : }
353 :
354 : NS_IMETHODIMP
355 0 : nsSimpleURI::GetUsername(nsACString &result)
356 : {
357 0 : return NS_ERROR_FAILURE;
358 : }
359 :
360 : NS_IMETHODIMP
361 0 : nsSimpleURI::SetUsername(const nsACString &userName)
362 : {
363 0 : NS_ENSURE_STATE(mMutable);
364 :
365 0 : return NS_ERROR_FAILURE;
366 : }
367 :
368 : NS_IMETHODIMP
369 0 : nsSimpleURI::GetPassword(nsACString &result)
370 : {
371 0 : return NS_ERROR_FAILURE;
372 : }
373 :
374 : NS_IMETHODIMP
375 0 : nsSimpleURI::SetPassword(const nsACString &password)
376 : {
377 0 : NS_ENSURE_STATE(mMutable);
378 :
379 0 : return NS_ERROR_FAILURE;
380 : }
381 :
382 : NS_IMETHODIMP
383 0 : nsSimpleURI::GetHostPort(nsACString &result)
384 : {
385 : // Note: Audit all callers before changing this to return an empty
386 : // string -- CAPS and UI code may depend on this throwing.
387 : // Note: If this is changed, change GetAsciiHostPort as well.
388 0 : return NS_ERROR_FAILURE;
389 : }
390 :
391 : NS_IMETHODIMP
392 0 : nsSimpleURI::SetHostPort(const nsACString &result)
393 : {
394 0 : NS_ENSURE_STATE(mMutable);
395 :
396 0 : return NS_ERROR_FAILURE;
397 : }
398 :
399 : NS_IMETHODIMP
400 0 : nsSimpleURI::SetHostAndPort(const nsACString &result)
401 : {
402 0 : NS_ENSURE_STATE(mMutable);
403 :
404 0 : return NS_ERROR_FAILURE;
405 : }
406 :
407 : NS_IMETHODIMP
408 1 : nsSimpleURI::GetHost(nsACString &result)
409 : {
410 : // Note: Audit all callers before changing this to return an empty
411 : // string -- CAPS and UI code depend on this throwing.
412 1 : return NS_ERROR_FAILURE;
413 : }
414 :
415 : NS_IMETHODIMP
416 0 : nsSimpleURI::SetHost(const nsACString &host)
417 : {
418 0 : NS_ENSURE_STATE(mMutable);
419 :
420 0 : return NS_ERROR_FAILURE;
421 : }
422 :
423 : NS_IMETHODIMP
424 3 : nsSimpleURI::GetPort(int32_t *result)
425 : {
426 : // Note: Audit all callers before changing this to return an empty
427 : // string -- CAPS and UI code may depend on this throwing.
428 3 : return NS_ERROR_FAILURE;
429 : }
430 :
431 : NS_IMETHODIMP
432 0 : nsSimpleURI::SetPort(int32_t port)
433 : {
434 0 : NS_ENSURE_STATE(mMutable);
435 :
436 0 : return NS_ERROR_FAILURE;
437 : }
438 :
439 : NS_IMETHODIMP
440 138 : nsSimpleURI::GetPath(nsACString &result)
441 : {
442 138 : result = mPath;
443 138 : if (mIsQueryValid) {
444 0 : result += NS_LITERAL_CSTRING("?") + mQuery;
445 : }
446 138 : if (mIsRefValid) {
447 0 : result += NS_LITERAL_CSTRING("#") + mRef;
448 : }
449 :
450 138 : return NS_OK;
451 : }
452 :
453 : NS_IMETHODIMP
454 85 : nsSimpleURI::SetPath(const nsACString &aPath)
455 : {
456 85 : NS_ENSURE_STATE(mMutable);
457 :
458 170 : nsAutoCString path;
459 85 : if (!path.Assign(aPath, fallible)) {
460 0 : return NS_ERROR_OUT_OF_MEMORY;
461 : }
462 85 : int32_t queryPos = path.FindChar('?');
463 85 : int32_t hashPos = path.FindChar('#');
464 :
465 85 : if (queryPos != kNotFound && hashPos != kNotFound && hashPos < queryPos) {
466 0 : queryPos = kNotFound;
467 : }
468 :
469 170 : nsAutoCString query;
470 85 : if (queryPos != kNotFound) {
471 0 : query.Assign(Substring(path, queryPos));
472 0 : path.Truncate(queryPos);
473 : }
474 :
475 170 : nsAutoCString hash;
476 85 : if (hashPos != kNotFound) {
477 0 : if (query.IsEmpty()) {
478 0 : hash.Assign(Substring(path, hashPos));
479 0 : path.Truncate(hashPos);
480 : } else {
481 : // We have to search the hash character in the query
482 0 : hashPos = query.FindChar('#');
483 0 : hash.Assign(Substring(query, hashPos));
484 0 : query.Truncate(hashPos);
485 : }
486 : }
487 :
488 85 : mIsQueryValid = false;
489 85 : mQuery.Truncate();
490 :
491 85 : mIsRefValid = false;
492 85 : mRef.Truncate();
493 :
494 : // The path
495 85 : if (!mPath.Assign(path, fallible)) {
496 0 : return NS_ERROR_OUT_OF_MEMORY;
497 : }
498 :
499 85 : nsresult rv = SetQuery(query);
500 85 : if (NS_FAILED(rv)) {
501 0 : return rv;
502 : }
503 :
504 85 : return SetRef(hash);
505 : }
506 :
507 : NS_IMETHODIMP
508 11 : nsSimpleURI::GetRef(nsACString &result)
509 : {
510 11 : if (!mIsRefValid) {
511 11 : MOZ_ASSERT(mRef.IsEmpty(), "mIsRefValid/mRef invariant broken");
512 11 : result.Truncate();
513 : } else {
514 0 : result = mRef;
515 : }
516 :
517 11 : return NS_OK;
518 : }
519 :
520 : // NOTE: SetRef("") removes our ref, whereas SetRef("#") sets it to the empty
521 : // string (and will result in .spec and .path having a terminal #).
522 : NS_IMETHODIMP
523 85 : nsSimpleURI::SetRef(const nsACString &aRef)
524 : {
525 85 : NS_ENSURE_STATE(mMutable);
526 :
527 170 : nsAutoCString ref;
528 85 : nsresult rv = NS_EscapeURL(aRef, esc_OnlyNonASCII, ref, fallible);
529 85 : if (NS_FAILED(rv)) {
530 0 : return rv;
531 : }
532 :
533 85 : if (ref.IsEmpty()) {
534 : // Empty string means to remove ref completely.
535 85 : mIsRefValid = false;
536 85 : mRef.Truncate(); // invariant: mRef should be empty when it's not valid
537 85 : return NS_OK;
538 : }
539 :
540 0 : mIsRefValid = true;
541 :
542 : // Gracefully skip initial hash
543 0 : if (ref[0] == '#') {
544 0 : mRef = Substring(ref, 1);
545 : } else {
546 0 : mRef = ref;
547 : }
548 :
549 0 : return NS_OK;
550 : }
551 :
552 : NS_IMETHODIMP
553 4 : nsSimpleURI::Equals(nsIURI* other, bool *result)
554 : {
555 4 : return EqualsInternal(other, eHonorRef, result);
556 : }
557 :
558 : NS_IMETHODIMP
559 10 : nsSimpleURI::EqualsExceptRef(nsIURI* other, bool *result)
560 : {
561 10 : return EqualsInternal(other, eIgnoreRef, result);
562 : }
563 :
564 : /* virtual */ nsresult
565 5 : nsSimpleURI::EqualsInternal(nsIURI* other,
566 : nsSimpleURI::RefHandlingEnum refHandlingMode,
567 : bool* result)
568 : {
569 5 : NS_ENSURE_ARG_POINTER(other);
570 5 : NS_PRECONDITION(result, "null pointer");
571 :
572 10 : RefPtr<nsSimpleURI> otherUri;
573 10 : nsresult rv = other->QueryInterface(kThisSimpleURIImplementationCID,
574 10 : getter_AddRefs(otherUri));
575 5 : if (NS_FAILED(rv)) {
576 0 : *result = false;
577 0 : return NS_OK;
578 : }
579 :
580 5 : *result = EqualsInternal(otherUri, refHandlingMode);
581 5 : return NS_OK;
582 : }
583 :
584 : bool
585 5 : nsSimpleURI::EqualsInternal(nsSimpleURI* otherUri, RefHandlingEnum refHandlingMode)
586 : {
587 10 : bool result = (mScheme == otherUri->mScheme &&
588 10 : mPath == otherUri->mPath);
589 :
590 5 : if (result) {
591 15 : result = (mIsQueryValid == otherUri->mIsQueryValid &&
592 5 : (!mIsQueryValid || mQuery == otherUri->mQuery));
593 : }
594 :
595 5 : if (result && refHandlingMode == eHonorRef) {
596 9 : result = (mIsRefValid == otherUri->mIsRefValid &&
597 3 : (!mIsRefValid || mRef == otherUri->mRef));
598 : }
599 :
600 5 : return result;
601 : }
602 :
603 : NS_IMETHODIMP
604 251 : nsSimpleURI::SchemeIs(const char *i_Scheme, bool *o_Equals)
605 : {
606 251 : NS_ENSURE_ARG_POINTER(o_Equals);
607 251 : if (!i_Scheme) return NS_ERROR_NULL_POINTER;
608 :
609 251 : const char *this_scheme = mScheme.get();
610 :
611 : // mScheme is guaranteed to be lower case.
612 251 : if (*i_Scheme == *this_scheme || *i_Scheme == (*this_scheme - ('a' - 'A')) ) {
613 134 : *o_Equals = PL_strcasecmp(this_scheme, i_Scheme) ? false : true;
614 : } else {
615 117 : *o_Equals = false;
616 : }
617 :
618 251 : return NS_OK;
619 : }
620 :
621 : /* virtual */ nsSimpleURI*
622 11 : nsSimpleURI::StartClone(nsSimpleURI::RefHandlingEnum refHandlingMode,
623 : const nsACString& newRef)
624 : {
625 11 : nsSimpleURI* url = new nsSimpleURI();
626 11 : SetRefOnClone(url, refHandlingMode, newRef);
627 11 : return url;
628 : }
629 :
630 : /* virtual */ void
631 22 : nsSimpleURI::SetRefOnClone(nsSimpleURI* url,
632 : nsSimpleURI::RefHandlingEnum refHandlingMode,
633 : const nsACString& newRef)
634 : {
635 22 : if (refHandlingMode == eHonorRef) {
636 16 : url->mRef = mRef;
637 16 : url->mIsRefValid = mIsRefValid;
638 6 : } else if (refHandlingMode == eReplaceRef) {
639 0 : url->SetRef(newRef);
640 : }
641 22 : }
642 :
643 : NS_IMETHODIMP
644 16 : nsSimpleURI::Clone(nsIURI** result)
645 : {
646 16 : return CloneInternal(eHonorRef, EmptyCString(), result);
647 : }
648 :
649 : NS_IMETHODIMP
650 6 : nsSimpleURI::CloneIgnoringRef(nsIURI** result)
651 : {
652 6 : return CloneInternal(eIgnoreRef, EmptyCString(), result);
653 : }
654 :
655 : NS_IMETHODIMP
656 0 : nsSimpleURI::CloneWithNewRef(const nsACString &newRef, nsIURI** result)
657 : {
658 0 : return CloneInternal(eReplaceRef, newRef, result);
659 : }
660 :
661 : nsresult
662 22 : nsSimpleURI::CloneInternal(nsSimpleURI::RefHandlingEnum refHandlingMode,
663 : const nsACString &newRef,
664 : nsIURI** result)
665 : {
666 44 : RefPtr<nsSimpleURI> url = StartClone(refHandlingMode, newRef);
667 22 : if (!url)
668 0 : return NS_ERROR_OUT_OF_MEMORY;
669 :
670 : // Note: |url| may well have mMutable false at this point, so
671 : // don't call any setter methods.
672 22 : url->mScheme = mScheme;
673 22 : url->mPath = mPath;
674 :
675 22 : url->mIsQueryValid = mIsQueryValid;
676 22 : if (url->mIsQueryValid) {
677 0 : url->mQuery = mQuery;
678 : }
679 :
680 22 : url.forget(result);
681 22 : return NS_OK;
682 : }
683 :
684 : NS_IMETHODIMP
685 0 : nsSimpleURI::Resolve(const nsACString &relativePath, nsACString &result)
686 : {
687 0 : result = relativePath;
688 0 : return NS_OK;
689 : }
690 :
691 : NS_IMETHODIMP
692 27 : nsSimpleURI::GetAsciiSpec(nsACString &result)
693 : {
694 54 : nsAutoCString buf;
695 27 : nsresult rv = GetSpec(buf);
696 27 : if (NS_FAILED(rv)) return rv;
697 27 : return NS_EscapeURL(buf, esc_OnlyNonASCII|esc_AlwaysCopy, result, fallible);
698 : }
699 :
700 : NS_IMETHODIMP
701 0 : nsSimpleURI::GetAsciiHostPort(nsACString &result)
702 : {
703 : // XXX This behavior mimics GetHostPort.
704 0 : return NS_ERROR_FAILURE;
705 : }
706 :
707 : NS_IMETHODIMP
708 0 : nsSimpleURI::GetAsciiHost(nsACString &result)
709 : {
710 0 : result.Truncate();
711 0 : return NS_OK;
712 : }
713 :
714 : NS_IMETHODIMP
715 0 : nsSimpleURI::GetOriginCharset(nsACString &result)
716 : {
717 0 : result.Truncate();
718 0 : return NS_OK;
719 : }
720 :
721 : //----------------------------------------------------------------------------
722 : // nsSimpleURI::nsIClassInfo
723 : //----------------------------------------------------------------------------
724 :
725 : NS_IMETHODIMP
726 21 : nsSimpleURI::GetInterfaces(uint32_t *count, nsIID * **array)
727 : {
728 21 : *count = 0;
729 21 : *array = nullptr;
730 21 : return NS_OK;
731 : }
732 :
733 : NS_IMETHODIMP
734 39 : nsSimpleURI::GetScriptableHelper(nsIXPCScriptable **_retval)
735 : {
736 39 : *_retval = nullptr;
737 39 : return NS_OK;
738 : }
739 :
740 : NS_IMETHODIMP
741 0 : nsSimpleURI::GetContractID(char * *aContractID)
742 : {
743 : // Make sure to modify any subclasses as needed if this ever
744 : // changes.
745 0 : *aContractID = nullptr;
746 0 : return NS_OK;
747 : }
748 :
749 : NS_IMETHODIMP
750 0 : nsSimpleURI::GetClassDescription(char * *aClassDescription)
751 : {
752 0 : *aClassDescription = nullptr;
753 0 : return NS_OK;
754 : }
755 :
756 : NS_IMETHODIMP
757 0 : nsSimpleURI::GetClassID(nsCID * *aClassID)
758 : {
759 : // Make sure to modify any subclasses as needed if this ever
760 : // changes to not call the virtual GetClassIDNoAlloc.
761 0 : *aClassID = (nsCID*) moz_xmalloc(sizeof(nsCID));
762 0 : if (!*aClassID)
763 0 : return NS_ERROR_OUT_OF_MEMORY;
764 0 : return GetClassIDNoAlloc(*aClassID);
765 : }
766 :
767 : NS_IMETHODIMP
768 42 : nsSimpleURI::GetFlags(uint32_t *aFlags)
769 : {
770 42 : *aFlags = nsIClassInfo::MAIN_THREAD_ONLY;
771 42 : return NS_OK;
772 : }
773 :
774 : NS_IMETHODIMP
775 0 : nsSimpleURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
776 : {
777 0 : *aClassIDNoAlloc = kSimpleURICID;
778 0 : return NS_OK;
779 : }
780 :
781 : //----------------------------------------------------------------------------
782 : // nsSimpleURI::nsISimpleURI
783 : //----------------------------------------------------------------------------
784 : NS_IMETHODIMP
785 74 : nsSimpleURI::GetMutable(bool *value)
786 : {
787 74 : *value = mMutable;
788 74 : return NS_OK;
789 : }
790 :
791 : NS_IMETHODIMP
792 124 : nsSimpleURI::SetMutable(bool value)
793 : {
794 124 : NS_ENSURE_ARG(mMutable || !value);
795 :
796 124 : mMutable = value;
797 124 : return NS_OK;
798 : }
799 :
800 : //----------------------------------------------------------------------------
801 : // nsSimpleURI::nsISizeOf
802 : //----------------------------------------------------------------------------
803 :
804 : size_t
805 0 : nsSimpleURI::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
806 : {
807 0 : return mScheme.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
808 0 : mPath.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
809 0 : mQuery.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
810 0 : mRef.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
811 : }
812 :
813 : size_t
814 0 : nsSimpleURI::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
815 0 : return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
816 : }
817 :
818 : NS_IMETHODIMP
819 0 : nsSimpleURI::GetFilePath(nsACString& aFilePath)
820 : {
821 0 : aFilePath = mPath;
822 0 : return NS_OK;
823 : }
824 :
825 : NS_IMETHODIMP
826 0 : nsSimpleURI::SetFilePath(const nsACString& aFilePath)
827 : {
828 0 : return NS_ERROR_FAILURE;
829 : }
830 :
831 : NS_IMETHODIMP
832 0 : nsSimpleURI::GetQuery(nsACString& aQuery)
833 : {
834 0 : if (!mIsQueryValid) {
835 0 : MOZ_ASSERT(mQuery.IsEmpty(), "mIsQueryValid/mQuery invariant broken");
836 0 : aQuery.Truncate();
837 : } else {
838 0 : aQuery = mQuery;
839 : }
840 0 : return NS_OK;
841 : }
842 :
843 : NS_IMETHODIMP
844 85 : nsSimpleURI::SetQuery(const nsACString& aQuery)
845 : {
846 85 : NS_ENSURE_STATE(mMutable);
847 :
848 170 : nsAutoCString query;
849 85 : nsresult rv = NS_EscapeURL(aQuery, esc_OnlyNonASCII, query, fallible);
850 85 : if (NS_FAILED(rv)) {
851 0 : return rv;
852 : }
853 :
854 85 : if (query.IsEmpty()) {
855 : // Empty string means to remove query completely.
856 85 : mIsQueryValid = false;
857 85 : mQuery.Truncate(); // invariant: mQuery should be empty when it's not valid
858 85 : return NS_OK;
859 : }
860 :
861 0 : mIsQueryValid = true;
862 :
863 : // Gracefully skip initial question mark
864 0 : if (query[0] == '?') {
865 0 : mQuery = Substring(query, 1);
866 : } else {
867 0 : mQuery = query;
868 : }
869 :
870 0 : return NS_OK;
871 : }
872 :
873 : } // namespace net
874 : } // namespace mozilla
|