Source code

Revision control

Other Tools

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