Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
6 #include "mozilla/DebugOnly.h"
8 #undef LOG
9 #include "IPCMessageUtils.h"
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 "nsIProgrammingLanguage.h"
22 #include "nsIIPCSerializableURI.h"
23 #include "mozilla/MemoryReporting.h"
24 #include "mozilla/ipc/URIUtils.h"
26 using namespace mozilla::ipc;
28 static NS_DEFINE_CID(kThisSimpleURIImplementationCID,
29 NS_THIS_SIMPLEURI_IMPLEMENTATION_CID);
30 static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
32 ////////////////////////////////////////////////////////////////////////////////
33 // nsSimpleURI methods:
35 nsSimpleURI::nsSimpleURI()
36 : mMutable(true),
37 mIsRefValid(false)
38 {
39 }
41 nsSimpleURI::~nsSimpleURI()
42 {
43 }
45 NS_IMPL_ADDREF(nsSimpleURI)
46 NS_IMPL_RELEASE(nsSimpleURI)
47 NS_INTERFACE_TABLE_HEAD(nsSimpleURI)
48 NS_INTERFACE_TABLE(nsSimpleURI, nsIURI, nsISerializable, nsIClassInfo,
49 nsIMutable, nsIIPCSerializableURI)
50 NS_INTERFACE_TABLE_TO_MAP_SEGUE
51 if (aIID.Equals(kThisSimpleURIImplementationCID))
52 foundInterface = static_cast<nsIURI*>(this);
53 else
54 NS_INTERFACE_MAP_ENTRY(nsISizeOf)
55 NS_INTERFACE_MAP_END
57 ////////////////////////////////////////////////////////////////////////////////
58 // nsISerializable methods:
60 NS_IMETHODIMP
61 nsSimpleURI::Read(nsIObjectInputStream* aStream)
62 {
63 nsresult rv;
65 bool isMutable;
66 rv = aStream->ReadBoolean(&isMutable);
67 if (NS_FAILED(rv)) return rv;
68 mMutable = isMutable;
70 rv = aStream->ReadCString(mScheme);
71 if (NS_FAILED(rv)) return rv;
73 rv = aStream->ReadCString(mPath);
74 if (NS_FAILED(rv)) return rv;
76 bool isRefValid;
77 rv = aStream->ReadBoolean(&isRefValid);
78 if (NS_FAILED(rv)) return rv;
79 mIsRefValid = isRefValid;
81 if (isRefValid) {
82 rv = aStream->ReadCString(mRef);
83 if (NS_FAILED(rv)) return rv;
84 } else {
85 mRef.Truncate(); // invariant: mRef should be empty when it's not valid
86 }
88 return NS_OK;
89 }
91 NS_IMETHODIMP
92 nsSimpleURI::Write(nsIObjectOutputStream* aStream)
93 {
94 nsresult rv;
96 rv = aStream->WriteBoolean(mMutable);
97 if (NS_FAILED(rv)) return rv;
99 rv = aStream->WriteStringZ(mScheme.get());
100 if (NS_FAILED(rv)) return rv;
102 rv = aStream->WriteStringZ(mPath.get());
103 if (NS_FAILED(rv)) return rv;
105 rv = aStream->WriteBoolean(mIsRefValid);
106 if (NS_FAILED(rv)) return rv;
108 if (mIsRefValid) {
109 rv = aStream->WriteStringZ(mRef.get());
110 if (NS_FAILED(rv)) return rv;
111 }
113 return NS_OK;
114 }
116 ////////////////////////////////////////////////////////////////////////////////
117 // nsIIPCSerializableURI methods:
119 void
120 nsSimpleURI::Serialize(URIParams& aParams)
121 {
122 SimpleURIParams params;
124 params.scheme() = mScheme;
125 params.path() = mPath;
126 if (mIsRefValid) {
127 params.ref() = mRef;
128 }
129 else {
130 params.ref().SetIsVoid(true);
131 }
132 params.isMutable() = mMutable;
134 aParams = params;
135 }
137 bool
138 nsSimpleURI::Deserialize(const URIParams& aParams)
139 {
140 if (aParams.type() != URIParams::TSimpleURIParams) {
141 NS_ERROR("Received unknown parameters from the other process!");
142 return false;
143 }
145 const SimpleURIParams& params = aParams.get_SimpleURIParams();
147 mScheme = params.scheme();
148 mPath = params.path();
149 if (params.ref().IsVoid()) {
150 mRef.Truncate();
151 mIsRefValid = false;
152 }
153 else {
154 mRef = params.ref();
155 mIsRefValid = true;
156 }
157 mMutable = params.isMutable();
159 return true;
160 }
162 ////////////////////////////////////////////////////////////////////////////////
163 // nsIURI methods:
165 NS_IMETHODIMP
166 nsSimpleURI::GetSpec(nsACString &result)
167 {
168 result = mScheme + NS_LITERAL_CSTRING(":") + mPath;
169 if (mIsRefValid) {
170 result += NS_LITERAL_CSTRING("#") + mRef;
171 } else {
172 NS_ABORT_IF_FALSE(mRef.IsEmpty(), "mIsRefValid/mRef invariant broken");
173 }
174 return NS_OK;
175 }
177 // result may contain unescaped UTF-8 characters
178 NS_IMETHODIMP
179 nsSimpleURI::GetSpecIgnoringRef(nsACString &result)
180 {
181 result = mScheme + NS_LITERAL_CSTRING(":") + mPath;
182 return NS_OK;
183 }
185 NS_IMETHODIMP
186 nsSimpleURI::GetHasRef(bool *result)
187 {
188 *result = mIsRefValid;
189 return NS_OK;
190 }
192 NS_IMETHODIMP
193 nsSimpleURI::SetSpec(const nsACString &aSpec)
194 {
195 NS_ENSURE_STATE(mMutable);
197 const nsAFlatCString& flat = PromiseFlatCString(aSpec);
198 const char* specPtr = flat.get();
200 // filter out unexpected chars "\r\n\t" if necessary
201 nsAutoCString filteredSpec;
202 int32_t specLen;
203 if (net_FilterURIString(specPtr, filteredSpec)) {
204 specPtr = filteredSpec.get();
205 specLen = filteredSpec.Length();
206 } else
207 specLen = flat.Length();
209 // nsSimpleURI currently restricts the charset to US-ASCII
210 nsAutoCString spec;
211 NS_EscapeURL(specPtr, specLen, esc_OnlyNonASCII|esc_AlwaysCopy, spec);
213 int32_t colonPos = spec.FindChar(':');
214 if (colonPos < 0 || !net_IsValidScheme(spec.get(), colonPos))
215 return NS_ERROR_MALFORMED_URI;
217 mScheme.Truncate();
218 mozilla::DebugOnly<int32_t> n = spec.Left(mScheme, colonPos);
219 NS_ASSERTION(n == colonPos, "Left failed");
220 ToLowerCase(mScheme);
222 // This sets both mPath and mRef.
223 return SetPath(Substring(spec, colonPos + 1));
224 }
226 NS_IMETHODIMP
227 nsSimpleURI::GetScheme(nsACString &result)
228 {
229 result = mScheme;
230 return NS_OK;
231 }
233 NS_IMETHODIMP
234 nsSimpleURI::SetScheme(const nsACString &scheme)
235 {
236 NS_ENSURE_STATE(mMutable);
238 const nsPromiseFlatCString &flat = PromiseFlatCString(scheme);
239 if (!net_IsValidScheme(flat)) {
240 NS_ERROR("the given url scheme contains invalid characters");
241 return NS_ERROR_MALFORMED_URI;
242 }
244 mScheme = scheme;
245 ToLowerCase(mScheme);
246 return NS_OK;
247 }
249 NS_IMETHODIMP
250 nsSimpleURI::GetPrePath(nsACString &result)
251 {
252 result = mScheme + NS_LITERAL_CSTRING(":");
253 return NS_OK;
254 }
256 NS_IMETHODIMP
257 nsSimpleURI::GetUserPass(nsACString &result)
258 {
259 return NS_ERROR_FAILURE;
260 }
262 NS_IMETHODIMP
263 nsSimpleURI::SetUserPass(const nsACString &userPass)
264 {
265 NS_ENSURE_STATE(mMutable);
267 return NS_ERROR_FAILURE;
268 }
270 NS_IMETHODIMP
271 nsSimpleURI::GetUsername(nsACString &result)
272 {
273 return NS_ERROR_FAILURE;
274 }
276 NS_IMETHODIMP
277 nsSimpleURI::SetUsername(const nsACString &userName)
278 {
279 NS_ENSURE_STATE(mMutable);
281 return NS_ERROR_FAILURE;
282 }
284 NS_IMETHODIMP
285 nsSimpleURI::GetPassword(nsACString &result)
286 {
287 return NS_ERROR_FAILURE;
288 }
290 NS_IMETHODIMP
291 nsSimpleURI::SetPassword(const nsACString &password)
292 {
293 NS_ENSURE_STATE(mMutable);
295 return NS_ERROR_FAILURE;
296 }
298 NS_IMETHODIMP
299 nsSimpleURI::GetHostPort(nsACString &result)
300 {
301 // Note: Audit all callers before changing this to return an empty
302 // string -- CAPS and UI code may depend on this throwing.
303 return NS_ERROR_FAILURE;
304 }
306 NS_IMETHODIMP
307 nsSimpleURI::SetHostPort(const nsACString &result)
308 {
309 NS_ENSURE_STATE(mMutable);
311 return NS_ERROR_FAILURE;
312 }
314 NS_IMETHODIMP
315 nsSimpleURI::GetHost(nsACString &result)
316 {
317 // Note: Audit all callers before changing this to return an empty
318 // string -- CAPS and UI code depend on this throwing.
319 return NS_ERROR_FAILURE;
320 }
322 NS_IMETHODIMP
323 nsSimpleURI::SetHost(const nsACString &host)
324 {
325 NS_ENSURE_STATE(mMutable);
327 return NS_ERROR_FAILURE;
328 }
330 NS_IMETHODIMP
331 nsSimpleURI::GetPort(int32_t *result)
332 {
333 // Note: Audit all callers before changing this to return an empty
334 // string -- CAPS and UI code may depend on this throwing.
335 return NS_ERROR_FAILURE;
336 }
338 NS_IMETHODIMP
339 nsSimpleURI::SetPort(int32_t port)
340 {
341 NS_ENSURE_STATE(mMutable);
343 return NS_ERROR_FAILURE;
344 }
346 NS_IMETHODIMP
347 nsSimpleURI::GetPath(nsACString &result)
348 {
349 result = mPath;
350 if (mIsRefValid) {
351 result += NS_LITERAL_CSTRING("#") + mRef;
352 }
354 return NS_OK;
355 }
357 NS_IMETHODIMP
358 nsSimpleURI::SetPath(const nsACString &path)
359 {
360 NS_ENSURE_STATE(mMutable);
362 int32_t hashPos = path.FindChar('#');
363 if (hashPos < 0) {
364 mIsRefValid = false;
365 mRef.Truncate(); // invariant: mRef should be empty when it's not valid
366 mPath = path;
367 return NS_OK;
368 }
370 mPath = StringHead(path, hashPos);
371 return SetRef(Substring(path, uint32_t(hashPos)));
372 }
374 NS_IMETHODIMP
375 nsSimpleURI::GetRef(nsACString &result)
376 {
377 if (!mIsRefValid) {
378 NS_ABORT_IF_FALSE(mRef.IsEmpty(), "mIsRefValid/mRef invariant broken");
379 result.Truncate();
380 } else {
381 result = mRef;
382 }
384 return NS_OK;
385 }
387 // NOTE: SetRef("") removes our ref, whereas SetRef("#") sets it to the empty
388 // string (and will result in .spec and .path having a terminal #).
389 NS_IMETHODIMP
390 nsSimpleURI::SetRef(const nsACString &aRef)
391 {
392 NS_ENSURE_STATE(mMutable);
394 if (aRef.IsEmpty()) {
395 // Empty string means to remove ref completely.
396 mIsRefValid = false;
397 mRef.Truncate(); // invariant: mRef should be empty when it's not valid
398 return NS_OK;
399 }
401 mIsRefValid = true;
403 // Gracefully skip initial hash
404 if (aRef[0] == '#') {
405 mRef = Substring(aRef, 1);
406 } else {
407 mRef = aRef;
408 }
410 return NS_OK;
411 }
413 NS_IMETHODIMP
414 nsSimpleURI::Equals(nsIURI* other, bool *result)
415 {
416 return EqualsInternal(other, eHonorRef, result);
417 }
419 NS_IMETHODIMP
420 nsSimpleURI::EqualsExceptRef(nsIURI* other, bool *result)
421 {
422 return EqualsInternal(other, eIgnoreRef, result);
423 }
425 /* virtual */ nsresult
426 nsSimpleURI::EqualsInternal(nsIURI* other,
427 nsSimpleURI::RefHandlingEnum refHandlingMode,
428 bool* result)
429 {
430 NS_ENSURE_ARG_POINTER(other);
431 NS_PRECONDITION(result, "null pointer");
433 nsRefPtr<nsSimpleURI> otherUri;
434 nsresult rv = other->QueryInterface(kThisSimpleURIImplementationCID,
435 getter_AddRefs(otherUri));
436 if (NS_FAILED(rv)) {
437 *result = false;
438 return NS_OK;
439 }
441 *result = EqualsInternal(otherUri, refHandlingMode);
442 return NS_OK;
443 }
445 bool
446 nsSimpleURI::EqualsInternal(nsSimpleURI* otherUri, RefHandlingEnum refHandlingMode)
447 {
448 bool result = (mScheme == otherUri->mScheme &&
449 mPath == otherUri->mPath);
451 if (result && refHandlingMode == eHonorRef) {
452 result = (mIsRefValid == otherUri->mIsRefValid &&
453 (!mIsRefValid || mRef == otherUri->mRef));
454 }
456 return result;
457 }
459 NS_IMETHODIMP
460 nsSimpleURI::SchemeIs(const char *i_Scheme, bool *o_Equals)
461 {
462 NS_ENSURE_ARG_POINTER(o_Equals);
463 if (!i_Scheme) return NS_ERROR_NULL_POINTER;
465 const char *this_scheme = mScheme.get();
467 // mScheme is guaranteed to be lower case.
468 if (*i_Scheme == *this_scheme || *i_Scheme == (*this_scheme - ('a' - 'A')) ) {
469 *o_Equals = PL_strcasecmp(this_scheme, i_Scheme) ? false : true;
470 } else {
471 *o_Equals = false;
472 }
474 return NS_OK;
475 }
477 /* virtual */ nsSimpleURI*
478 nsSimpleURI::StartClone(nsSimpleURI::RefHandlingEnum /* ignored */)
479 {
480 return new nsSimpleURI();
481 }
483 NS_IMETHODIMP
484 nsSimpleURI::Clone(nsIURI** result)
485 {
486 return CloneInternal(eHonorRef, result);
487 }
489 NS_IMETHODIMP
490 nsSimpleURI::CloneIgnoringRef(nsIURI** result)
491 {
492 return CloneInternal(eIgnoreRef, result);
493 }
495 nsresult
496 nsSimpleURI::CloneInternal(nsSimpleURI::RefHandlingEnum refHandlingMode,
497 nsIURI** result)
498 {
499 nsRefPtr<nsSimpleURI> url = StartClone(refHandlingMode);
500 if (!url)
501 return NS_ERROR_OUT_OF_MEMORY;
503 // Note: |url| may well have mMutable false at this point, so
504 // don't call any setter methods.
505 url->mScheme = mScheme;
506 url->mPath = mPath;
507 if (refHandlingMode == eHonorRef) {
508 url->mRef = mRef;
509 url->mIsRefValid = mIsRefValid;
510 }
512 url.forget(result);
513 return NS_OK;
514 }
516 NS_IMETHODIMP
517 nsSimpleURI::Resolve(const nsACString &relativePath, nsACString &result)
518 {
519 result = relativePath;
520 return NS_OK;
521 }
523 NS_IMETHODIMP
524 nsSimpleURI::GetAsciiSpec(nsACString &result)
525 {
526 nsAutoCString buf;
527 nsresult rv = GetSpec(buf);
528 if (NS_FAILED(rv)) return rv;
529 NS_EscapeURL(buf, esc_OnlyNonASCII|esc_AlwaysCopy, result);
530 return NS_OK;
531 }
533 NS_IMETHODIMP
534 nsSimpleURI::GetAsciiHost(nsACString &result)
535 {
536 result.Truncate();
537 return NS_OK;
538 }
540 NS_IMETHODIMP
541 nsSimpleURI::GetOriginCharset(nsACString &result)
542 {
543 result.Truncate();
544 return NS_OK;
545 }
547 //----------------------------------------------------------------------------
548 // nsSimpleURI::nsIClassInfo
549 //----------------------------------------------------------------------------
551 NS_IMETHODIMP
552 nsSimpleURI::GetInterfaces(uint32_t *count, nsIID * **array)
553 {
554 *count = 0;
555 *array = nullptr;
556 return NS_OK;
557 }
559 NS_IMETHODIMP
560 nsSimpleURI::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
561 {
562 *_retval = nullptr;
563 return NS_OK;
564 }
566 NS_IMETHODIMP
567 nsSimpleURI::GetContractID(char * *aContractID)
568 {
569 // Make sure to modify any subclasses as needed if this ever
570 // changes.
571 *aContractID = nullptr;
572 return NS_OK;
573 }
575 NS_IMETHODIMP
576 nsSimpleURI::GetClassDescription(char * *aClassDescription)
577 {
578 *aClassDescription = nullptr;
579 return NS_OK;
580 }
582 NS_IMETHODIMP
583 nsSimpleURI::GetClassID(nsCID * *aClassID)
584 {
585 // Make sure to modify any subclasses as needed if this ever
586 // changes to not call the virtual GetClassIDNoAlloc.
587 *aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
588 if (!*aClassID)
589 return NS_ERROR_OUT_OF_MEMORY;
590 return GetClassIDNoAlloc(*aClassID);
591 }
593 NS_IMETHODIMP
594 nsSimpleURI::GetImplementationLanguage(uint32_t *aImplementationLanguage)
595 {
596 *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
597 return NS_OK;
598 }
600 NS_IMETHODIMP
601 nsSimpleURI::GetFlags(uint32_t *aFlags)
602 {
603 *aFlags = nsIClassInfo::MAIN_THREAD_ONLY;
604 return NS_OK;
605 }
607 NS_IMETHODIMP
608 nsSimpleURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
609 {
610 *aClassIDNoAlloc = kSimpleURICID;
611 return NS_OK;
612 }
614 //----------------------------------------------------------------------------
615 // nsSimpleURI::nsISimpleURI
616 //----------------------------------------------------------------------------
617 NS_IMETHODIMP
618 nsSimpleURI::GetMutable(bool *value)
619 {
620 *value = mMutable;
621 return NS_OK;
622 }
624 NS_IMETHODIMP
625 nsSimpleURI::SetMutable(bool value)
626 {
627 NS_ENSURE_ARG(mMutable || !value);
629 mMutable = value;
630 return NS_OK;
631 }
633 //----------------------------------------------------------------------------
634 // nsSimpleURI::nsISizeOf
635 //----------------------------------------------------------------------------
637 size_t
638 nsSimpleURI::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
639 {
640 return mScheme.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
641 mPath.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
642 mRef.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
643 }
645 size_t
646 nsSimpleURI::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
647 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
648 }