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