1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=4 sw=2 sts=2 et cin: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 // HttpLog.h should generally be included first
10 #include "nsNetUtil.h"
12 #include "mozilla/Atomics.h"
13 #include "mozilla/Encoding.h"
14 #include "mozilla/LoadContext.h"
15 #include "mozilla/LoadInfo.h"
16 #include "mozilla/BasePrincipal.h"
17 #include "mozilla/Monitor.h"
18 #include "mozilla/TaskQueue.h"
19 #include "mozilla/Telemetry.h"
20 #include "nsCategoryCache.h"
21 #include "nsContentUtils.h"
22 #include "nsFileStreams.h"
23 #include "nsHashKeys.h"
25 #include "nsIAsyncStreamCopier.h"
26 #include "nsIAuthPrompt.h"
27 #include "nsIAuthPrompt2.h"
28 #include "nsIAuthPromptAdapterFactory.h"
29 #include "nsIBufferedStreams.h"
30 #include "nsIChannelEventSink.h"
31 #include "nsIContentSniffer.h"
32 #include "mozilla/dom/Document.h"
33 #include "nsIDownloader.h"
34 #include "nsIFileProtocolHandler.h"
35 #include "nsIFileStreams.h"
36 #include "nsIFileURL.h"
37 #include "nsIIDNService.h"
38 #include "nsIInputStreamChannel.h"
39 #include "nsIInputStreamPump.h"
40 #include "nsIInterfaceRequestorUtils.h"
41 #include "nsILoadContext.h"
42 #include "nsIMIMEHeaderParam.h"
43 #include "nsIMutable.h"
45 #include "nsIObjectLoadingContent.h"
46 #include "nsIOfflineCacheUpdate.h"
47 #include "nsPersistentProperties.h"
48 #include "nsIPrivateBrowsingChannel.h"
49 #include "nsIPropertyBag2.h"
50 #include "nsIProtocolProxyService.h"
51 #include "mozilla/net/RedirectChannelRegistrar.h"
52 #include "nsRequestObserverProxy.h"
53 #include "nsIScriptSecurityManager.h"
54 #include "nsISensitiveInfoHiddenURI.h"
55 #include "nsISimpleStreamListener.h"
56 #include "nsISocketProvider.h"
57 #include "nsISocketProviderService.h"
58 #include "nsIStandardURL.h"
59 #include "nsIStreamLoader.h"
60 #include "nsIIncrementalStreamLoader.h"
61 #include "nsIStreamTransportService.h"
62 #include "nsStringStream.h"
63 #include "nsSyncStreamListener.h"
64 #include "nsITransport.h"
65 #include "nsIURIWithSpecialOrigin.h"
66 #include "nsIURLParser.h"
67 #include "nsIUUIDGenerator.h"
68 #include "nsIViewSourceChannel.h"
69 #include "nsInterfaceRequestorAgg.h"
71 #include "nsINestedURI.h"
72 #include "mozilla/dom/nsCSPUtils.h"
73 #include "mozilla/dom/nsMixedContentBlocker.h"
74 #include "mozilla/dom/BlobURLProtocolHandler.h"
75 #include "mozilla/net/HttpBaseChannel.h"
76 #include "nsIScriptError.h"
77 #include "nsISiteSecurityService.h"
78 #include "nsHttpHandler.h"
79 #include "nsNSSComponent.h"
80 #include "nsIRedirectHistoryEntry.h"
81 #include "nsICertBlocklist.h"
82 #include "nsICertOverrideService.h"
83 #include "nsQueryObject.h"
84 #include "mozIThirdPartyUtil.h"
85 #include "../mime/nsMIMEHeaderParamImpl.h"
89 using namespace mozilla
;
90 using namespace mozilla::net
;
91 using mozilla::dom::BlobURLProtocolHandler
;
92 using mozilla::dom::ClientInfo
;
93 using mozilla::dom::PerformanceStorage
;
94 using mozilla::dom::ServiceWorkerDescriptor
;
97 #define DEFAULT_PRIVATE_RP 2
99 static uint32_t sDefaultRp
= DEFAULT_RP
;
100 static uint32_t defaultPrivateRp
= DEFAULT_PRIVATE_RP
;
102 already_AddRefed
<nsIIOService
> do_GetIOService(nsresult
*error
/* = 0 */) {
103 nsCOMPtr
<nsIIOService
> io
= mozilla::services::GetIOService();
104 if (error
) *error
= io
? NS_OK
: NS_ERROR_FAILURE
;
108 nsresult
NS_NewLocalFileInputStream(nsIInputStream
**result
, nsIFile
*file
,
109 int32_t ioFlags
/* = -1 */,
110 int32_t perm
/* = -1 */,
111 int32_t behaviorFlags
/* = 0 */) {
113 nsCOMPtr
<nsIFileInputStream
> in
=
114 do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID
, &rv
);
115 if (NS_SUCCEEDED(rv
)) {
116 rv
= in
->Init(file
, ioFlags
, perm
, behaviorFlags
);
117 if (NS_SUCCEEDED(rv
)) in
.forget(result
);
122 nsresult
NS_NewLocalFileOutputStream(nsIOutputStream
**result
, nsIFile
*file
,
123 int32_t ioFlags
/* = -1 */,
124 int32_t perm
/* = -1 */,
125 int32_t behaviorFlags
/* = 0 */) {
127 nsCOMPtr
<nsIFileOutputStream
> out
=
128 do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID
, &rv
);
129 if (NS_SUCCEEDED(rv
)) {
130 rv
= out
->Init(file
, ioFlags
, perm
, behaviorFlags
);
131 if (NS_SUCCEEDED(rv
)) out
.forget(result
);
136 nsresult
net_EnsureIOService(nsIIOService
**ios
, nsCOMPtr
<nsIIOService
> &grip
) {
139 grip
= do_GetIOService(&rv
);
145 nsresult
NS_NewFileURI(
146 nsIURI
**result
, nsIFile
*spec
,
148 *ioService
/* = nullptr */) // pass in nsIIOService to optimize callers
151 nsCOMPtr
<nsIIOService
> grip
;
152 rv
= net_EnsureIOService(&ioService
, grip
);
153 if (ioService
) rv
= ioService
->NewFileURI(spec
, result
);
157 nsresult
NS_GetURIWithNewRef(nsIURI
*aInput
, const nsACString
&aRef
,
159 if (NS_WARN_IF(!aInput
|| !aOutput
)) {
160 return NS_ERROR_INVALID_ARG
;
164 nsresult rv
= aInput
->GetHasRef(&hasRef
);
167 if (NS_SUCCEEDED(rv
)) {
168 rv
= aInput
->GetRef(ref
);
171 // If the ref is already equal to the new ref, we do not need to do anything.
172 // Also, if the GetRef failed (it could return NS_ERROR_NOT_IMPLEMENTED)
173 // we can assume SetRef would fail as well, so returning the original
175 if (NS_FAILED(rv
) || (!hasRef
&& aRef
.IsEmpty()) ||
176 (!aRef
.IsEmpty() && aRef
== ref
)) {
177 nsCOMPtr
<nsIURI
> uri
= aInput
;
182 return NS_MutateURI(aInput
).SetRef(aRef
).Finalize(aOutput
);
185 nsresult
NS_GetURIWithoutRef(nsIURI
*aInput
, nsIURI
**aOutput
) {
186 return NS_GetURIWithNewRef(aInput
, EmptyCString(), aOutput
);
189 nsresult
NS_NewChannelInternal(
190 nsIChannel
**outChannel
, nsIURI
*aUri
, nsILoadInfo
*aLoadInfo
,
191 PerformanceStorage
*aPerformanceStorage
/* = nullptr */,
192 nsILoadGroup
*aLoadGroup
/* = nullptr */,
193 nsIInterfaceRequestor
*aCallbacks
/* = nullptr */,
194 nsLoadFlags aLoadFlags
/* = nsIRequest::LOAD_NORMAL */,
195 nsIIOService
*aIoService
/* = nullptr */) {
196 // NS_NewChannelInternal is mostly called for channel redirects. We should
197 // allow the creation of a channel even if the original channel did not have a
198 // loadinfo attached.
199 NS_ENSURE_ARG_POINTER(outChannel
);
201 nsCOMPtr
<nsIIOService
> grip
;
202 nsresult rv
= net_EnsureIOService(&aIoService
, grip
);
203 NS_ENSURE_SUCCESS(rv
, rv
);
205 nsCOMPtr
<nsIChannel
> channel
;
206 rv
= aIoService
->NewChannelFromURIWithLoadInfo(aUri
, aLoadInfo
,
207 getter_AddRefs(channel
));
208 NS_ENSURE_SUCCESS(rv
, rv
);
211 rv
= channel
->SetLoadGroup(aLoadGroup
);
212 NS_ENSURE_SUCCESS(rv
, rv
);
216 rv
= channel
->SetNotificationCallbacks(aCallbacks
);
217 NS_ENSURE_SUCCESS(rv
, rv
);
221 nsLoadFlags channelLoadFlags
= 0;
222 channel
->GetLoadFlags(&channelLoadFlags
);
223 // Will be removed when we remove LOAD_REPLACE altogether
224 // This check is trying to catch protocol handlers that still
225 // try to set the LOAD_REPLACE flag.
226 MOZ_DIAGNOSTIC_ASSERT(!(channelLoadFlags
& nsIChannel::LOAD_REPLACE
));
229 if (aLoadFlags
!= nsIRequest::LOAD_NORMAL
) {
230 rv
= channel
->SetLoadFlags(aLoadFlags
);
231 NS_ENSURE_SUCCESS(rv
, rv
);
234 if (aPerformanceStorage
) {
235 nsCOMPtr
<nsILoadInfo
> loadInfo
;
236 rv
= channel
->GetLoadInfo(getter_AddRefs(loadInfo
));
237 NS_ENSURE_SUCCESS(rv
, rv
);
239 loadInfo
->SetPerformanceStorage(aPerformanceStorage
);
242 channel
.forget(outChannel
);
248 void AssertLoadingPrincipalAndClientInfoMatch(
249 nsIPrincipal
*aLoadingPrincipal
, const ClientInfo
&aLoadingClientInfo
,
250 nsContentPolicyType aType
) {
251 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
252 // Verify that the provided loading ClientInfo matches the loading
253 // principal. Unfortunately we can't just use nsIPrincipal::Equals() here
254 // because of some corner cases:
256 // 1. Worker debugger scripts want to use a system loading principal for
257 // worker scripts with a content principal. We exempt these from this
259 // 2. Null principals currently require exact object identity for
260 // nsIPrincipal::Equals() to return true. This doesn't work here because
261 // ClientInfo::GetPrincipal() uses PrincipalInfoToPrincipal() to allocate
262 // a new object. To work around this we compare the principal origin
263 // string itself. If bug 1431771 is fixed then we could switch to
266 // Allow worker debugger to load with a system principal.
267 if (aLoadingPrincipal
->IsSystemPrincipal() &&
268 (aType
== nsIContentPolicy::TYPE_INTERNAL_WORKER
||
269 aType
== nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER
||
270 aType
== nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER
||
271 aType
== nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS
)) {
275 // Perform a fast comparison for most principal checks.
276 nsCOMPtr
<nsIPrincipal
> clientPrincipal(aLoadingClientInfo
.GetPrincipal());
277 if (aLoadingPrincipal
->Equals(clientPrincipal
)) {
281 // Fall back to a slower origin equality test to support null principals.
282 nsAutoCString loadingOrigin
;
283 MOZ_ALWAYS_SUCCEEDS(aLoadingPrincipal
->GetOrigin(loadingOrigin
));
285 nsAutoCString clientOrigin
;
286 MOZ_ALWAYS_SUCCEEDS(clientPrincipal
->GetOrigin(clientOrigin
));
288 MOZ_DIAGNOSTIC_ASSERT(loadingOrigin
== clientOrigin
);
294 nsresult
NS_NewChannel(nsIChannel
**outChannel
, nsIURI
*aUri
,
295 nsIPrincipal
*aLoadingPrincipal
,
296 nsSecurityFlags aSecurityFlags
,
297 nsContentPolicyType aContentPolicyType
,
298 PerformanceStorage
*aPerformanceStorage
/* nullptr */,
299 nsILoadGroup
*aLoadGroup
/* = nullptr */,
300 nsIInterfaceRequestor
*aCallbacks
/* = nullptr */,
301 nsLoadFlags aLoadFlags
/* = nsIRequest::LOAD_NORMAL */,
302 nsIIOService
*aIoService
/* = nullptr */) {
303 return NS_NewChannelInternal(outChannel
, aUri
,
304 nullptr, // aLoadingNode,
306 nullptr, // aTriggeringPrincipal
308 Maybe
<ServiceWorkerDescriptor
>(), aSecurityFlags
,
309 aContentPolicyType
, aPerformanceStorage
,
310 aLoadGroup
, aCallbacks
, aLoadFlags
, aIoService
);
313 nsresult
NS_NewChannel(nsIChannel
**outChannel
, nsIURI
*aUri
,
314 nsIPrincipal
*aLoadingPrincipal
,
315 const ClientInfo
&aLoadingClientInfo
,
316 const Maybe
<ServiceWorkerDescriptor
> &aController
,
317 nsSecurityFlags aSecurityFlags
,
318 nsContentPolicyType aContentPolicyType
,
319 PerformanceStorage
*aPerformanceStorage
/* nullptr */,
320 nsILoadGroup
*aLoadGroup
/* = nullptr */,
321 nsIInterfaceRequestor
*aCallbacks
/* = nullptr */,
322 nsLoadFlags aLoadFlags
/* = nsIRequest::LOAD_NORMAL */,
323 nsIIOService
*aIoService
/* = nullptr */) {
324 AssertLoadingPrincipalAndClientInfoMatch(
325 aLoadingPrincipal
, aLoadingClientInfo
, aContentPolicyType
);
327 Maybe
<ClientInfo
> loadingClientInfo
;
328 loadingClientInfo
.emplace(aLoadingClientInfo
);
330 return NS_NewChannelInternal(outChannel
, aUri
,
331 nullptr, // aLoadingNode,
333 nullptr, // aTriggeringPrincipal
334 loadingClientInfo
, aController
, aSecurityFlags
,
335 aContentPolicyType
, aPerformanceStorage
,
336 aLoadGroup
, aCallbacks
, aLoadFlags
, aIoService
);
339 nsresult
NS_NewChannelInternal(
340 nsIChannel
**outChannel
, nsIURI
*aUri
, nsINode
*aLoadingNode
,
341 nsIPrincipal
*aLoadingPrincipal
, nsIPrincipal
*aTriggeringPrincipal
,
342 const Maybe
<ClientInfo
> &aLoadingClientInfo
,
343 const Maybe
<ServiceWorkerDescriptor
> &aController
,
344 nsSecurityFlags aSecurityFlags
, nsContentPolicyType aContentPolicyType
,
345 PerformanceStorage
*aPerformanceStorage
/* nullptr */,
346 nsILoadGroup
*aLoadGroup
/* = nullptr */,
347 nsIInterfaceRequestor
*aCallbacks
/* = nullptr */,
348 nsLoadFlags aLoadFlags
/* = nsIRequest::LOAD_NORMAL */,
349 nsIIOService
*aIoService
/* = nullptr */) {
350 NS_ENSURE_ARG_POINTER(outChannel
);
352 nsCOMPtr
<nsIIOService
> grip
;
353 nsresult rv
= net_EnsureIOService(&aIoService
, grip
);
354 NS_ENSURE_SUCCESS(rv
, rv
);
356 nsCOMPtr
<nsIChannel
> channel
;
357 rv
= aIoService
->NewChannelFromURIWithClientAndController(
358 aUri
, aLoadingNode
, aLoadingPrincipal
, aTriggeringPrincipal
,
359 aLoadingClientInfo
, aController
, aSecurityFlags
, aContentPolicyType
,
360 getter_AddRefs(channel
));
366 rv
= channel
->SetLoadGroup(aLoadGroup
);
367 NS_ENSURE_SUCCESS(rv
, rv
);
371 rv
= channel
->SetNotificationCallbacks(aCallbacks
);
372 NS_ENSURE_SUCCESS(rv
, rv
);
376 nsLoadFlags channelLoadFlags
= 0;
377 channel
->GetLoadFlags(&channelLoadFlags
);
378 // Will be removed when we remove LOAD_REPLACE altogether
379 // This check is trying to catch protocol handlers that still
380 // try to set the LOAD_REPLACE flag.
381 MOZ_DIAGNOSTIC_ASSERT(!(channelLoadFlags
& nsIChannel::LOAD_REPLACE
));
384 if (aLoadFlags
!= nsIRequest::LOAD_NORMAL
) {
385 rv
= channel
->SetLoadFlags(aLoadFlags
);
386 NS_ENSURE_SUCCESS(rv
, rv
);
389 if (aPerformanceStorage
) {
390 nsCOMPtr
<nsILoadInfo
> loadInfo
;
391 rv
= channel
->GetLoadInfo(getter_AddRefs(loadInfo
));
392 NS_ENSURE_SUCCESS(rv
, rv
);
394 loadInfo
->SetPerformanceStorage(aPerformanceStorage
);
397 channel
.forget(outChannel
);
401 nsresult
/*NS_NewChannelWithNodeAndTriggeringPrincipal */
402 NS_NewChannelWithTriggeringPrincipal(
403 nsIChannel
**outChannel
, nsIURI
*aUri
, nsINode
*aLoadingNode
,
404 nsIPrincipal
*aTriggeringPrincipal
, nsSecurityFlags aSecurityFlags
,
405 nsContentPolicyType aContentPolicyType
,
406 PerformanceStorage
*aPerformanceStorage
/* = nullptr */,
407 nsILoadGroup
*aLoadGroup
/* = nullptr */,
408 nsIInterfaceRequestor
*aCallbacks
/* = nullptr */,
409 nsLoadFlags aLoadFlags
/* = nsIRequest::LOAD_NORMAL */,
410 nsIIOService
*aIoService
/* = nullptr */) {
411 MOZ_ASSERT(aLoadingNode
);
412 NS_ASSERTION(aTriggeringPrincipal
,
413 "Can not create channel without a triggering Principal!");
414 return NS_NewChannelInternal(
415 outChannel
, aUri
, aLoadingNode
, aLoadingNode
->NodePrincipal(),
416 aTriggeringPrincipal
, Maybe
<ClientInfo
>(),
417 Maybe
<ServiceWorkerDescriptor
>(), aSecurityFlags
, aContentPolicyType
,
418 aPerformanceStorage
, aLoadGroup
, aCallbacks
, aLoadFlags
, aIoService
);
421 // See NS_NewChannelInternal for usage and argument description
422 nsresult
NS_NewChannelWithTriggeringPrincipal(
423 nsIChannel
**outChannel
, nsIURI
*aUri
, nsIPrincipal
*aLoadingPrincipal
,
424 nsIPrincipal
*aTriggeringPrincipal
, nsSecurityFlags aSecurityFlags
,
425 nsContentPolicyType aContentPolicyType
,
426 PerformanceStorage
*aPerformanceStorage
/* = nullptr */,
427 nsILoadGroup
*aLoadGroup
/* = nullptr */,
428 nsIInterfaceRequestor
*aCallbacks
/* = nullptr */,
429 nsLoadFlags aLoadFlags
/* = nsIRequest::LOAD_NORMAL */,
430 nsIIOService
*aIoService
/* = nullptr */) {
431 NS_ASSERTION(aLoadingPrincipal
,
432 "Can not create channel without a loading Principal!");
433 return NS_NewChannelInternal(
435 nullptr, // aLoadingNode
436 aLoadingPrincipal
, aTriggeringPrincipal
, Maybe
<ClientInfo
>(),
437 Maybe
<ServiceWorkerDescriptor
>(), aSecurityFlags
, aContentPolicyType
,
438 aPerformanceStorage
, aLoadGroup
, aCallbacks
, aLoadFlags
, aIoService
);
441 // See NS_NewChannelInternal for usage and argument description
442 nsresult
NS_NewChannelWithTriggeringPrincipal(
443 nsIChannel
**outChannel
, nsIURI
*aUri
, nsIPrincipal
*aLoadingPrincipal
,
444 nsIPrincipal
*aTriggeringPrincipal
, const ClientInfo
&aLoadingClientInfo
,
445 const Maybe
<ServiceWorkerDescriptor
> &aController
,
446 nsSecurityFlags aSecurityFlags
, nsContentPolicyType aContentPolicyType
,
447 PerformanceStorage
*aPerformanceStorage
/* = nullptr */,
448 nsILoadGroup
*aLoadGroup
/* = nullptr */,
449 nsIInterfaceRequestor
*aCallbacks
/* = nullptr */,
450 nsLoadFlags aLoadFlags
/* = nsIRequest::LOAD_NORMAL */,
451 nsIIOService
*aIoService
/* = nullptr */) {
452 AssertLoadingPrincipalAndClientInfoMatch(
453 aLoadingPrincipal
, aLoadingClientInfo
, aContentPolicyType
);
455 Maybe
<ClientInfo
> loadingClientInfo
;
456 loadingClientInfo
.emplace(aLoadingClientInfo
);
458 return NS_NewChannelInternal(outChannel
, aUri
,
459 nullptr, // aLoadingNode
460 aLoadingPrincipal
, aTriggeringPrincipal
,
461 loadingClientInfo
, aController
, aSecurityFlags
,
462 aContentPolicyType
, aPerformanceStorage
,
463 aLoadGroup
, aCallbacks
, aLoadFlags
, aIoService
);
466 nsresult
NS_NewChannel(nsIChannel
**outChannel
, nsIURI
*aUri
,
467 nsINode
*aLoadingNode
, nsSecurityFlags aSecurityFlags
,
468 nsContentPolicyType aContentPolicyType
,
469 PerformanceStorage
*aPerformanceStorage
/* = nullptr */,
470 nsILoadGroup
*aLoadGroup
/* = nullptr */,
471 nsIInterfaceRequestor
*aCallbacks
/* = nullptr */,
472 nsLoadFlags aLoadFlags
/* = nsIRequest::LOAD_NORMAL */,
473 nsIIOService
*aIoService
/* = nullptr */) {
474 NS_ASSERTION(aLoadingNode
, "Can not create channel without a loading Node!");
475 return NS_NewChannelInternal(
476 outChannel
, aUri
, aLoadingNode
, aLoadingNode
->NodePrincipal(),
477 nullptr, // aTriggeringPrincipal
478 Maybe
<ClientInfo
>(), Maybe
<ServiceWorkerDescriptor
>(), aSecurityFlags
,
479 aContentPolicyType
, aPerformanceStorage
, aLoadGroup
, aCallbacks
,
480 aLoadFlags
, aIoService
);
483 nsresult
NS_GetIsDocumentChannel(nsIChannel
*aChannel
, bool *aIsDocument
) {
484 // Check if this channel is going to be used to create a document. If it has
485 // LOAD_DOCUMENT_URI set it is trivially creating a document. If
486 // LOAD_HTML_OBJECT_DATA is set it may or may not be used to create a
487 // document, depending on its MIME type.
489 if (!aChannel
|| !aIsDocument
) {
490 return NS_ERROR_NULL_POINTER
;
492 *aIsDocument
= false;
493 nsLoadFlags loadFlags
;
494 nsresult rv
= aChannel
->GetLoadFlags(&loadFlags
);
498 if (loadFlags
& nsIChannel::LOAD_DOCUMENT_URI
) {
502 if (!(loadFlags
& nsIRequest::LOAD_HTML_OBJECT_DATA
)) {
503 *aIsDocument
= false;
506 nsAutoCString mimeType
;
507 rv
= aChannel
->GetContentType(mimeType
);
511 if (nsContentUtils::HtmlObjectContentTypeForMIMEType(
512 mimeType
, false, nullptr) == nsIObjectLoadingContent::TYPE_DOCUMENT
) {
516 *aIsDocument
= false;
520 nsresult
NS_MakeAbsoluteURI(nsACString
&result
, const nsACString
&spec
,
524 NS_WARNING("It doesn't make sense to not supply a base URI");
527 } else if (spec
.IsEmpty())
528 rv
= baseURI
->GetSpec(result
);
530 rv
= baseURI
->Resolve(spec
, result
);
534 nsresult
NS_MakeAbsoluteURI(char **result
, const char *spec
, nsIURI
*baseURI
) {
536 nsAutoCString resultBuf
;
537 rv
= NS_MakeAbsoluteURI(resultBuf
, nsDependentCString(spec
), baseURI
);
538 if (NS_SUCCEEDED(rv
)) {
539 *result
= ToNewCString(resultBuf
);
540 if (!*result
) rv
= NS_ERROR_OUT_OF_MEMORY
;
545 nsresult
NS_MakeAbsoluteURI(nsAString
&result
, const nsAString
&spec
,
549 NS_WARNING("It doesn't make sense to not supply a base URI");
553 nsAutoCString resultBuf
;
555 rv
= baseURI
->GetSpec(resultBuf
);
557 rv
= baseURI
->Resolve(NS_ConvertUTF16toUTF8(spec
), resultBuf
);
558 if (NS_SUCCEEDED(rv
)) CopyUTF8toUTF16(resultBuf
, result
);
563 int32_t NS_GetDefaultPort(const char *scheme
,
564 nsIIOService
*ioService
/* = nullptr */) {
567 // Getting the default port through the protocol handler has a lot of XPCOM
568 // overhead involved. We optimize the protocols that matter for Web pages
569 // (HTTP and HTTPS) by hardcoding their default ports here.
570 if (strncmp(scheme
, "http", 4) == 0) {
571 if (scheme
[4] == 's' && scheme
[5] == '\0') {
574 if (scheme
[4] == '\0') {
579 nsCOMPtr
<nsIIOService
> grip
;
580 net_EnsureIOService(&ioService
, grip
);
581 if (!ioService
) return -1;
583 nsCOMPtr
<nsIProtocolHandler
> handler
;
584 rv
= ioService
->GetProtocolHandler(scheme
, getter_AddRefs(handler
));
585 if (NS_FAILED(rv
)) return -1;
587 rv
= handler
->GetDefaultPort(&port
);
588 return NS_SUCCEEDED(rv
) ? port
: -1;
592 * This function is a helper function to apply the ToAscii conversion
595 bool NS_StringToACE(const nsACString
&idn
, nsACString
&result
) {
596 nsCOMPtr
<nsIIDNService
> idnSrv
= do_GetService(NS_IDNSERVICE_CONTRACTID
);
597 if (!idnSrv
) return false;
598 nsresult rv
= idnSrv
->ConvertUTF8toACE(idn
, result
);
599 if (NS_FAILED(rv
)) return false;
604 int32_t NS_GetRealPort(nsIURI
*aURI
) {
606 nsresult rv
= aURI
->GetPort(&port
);
607 if (NS_FAILED(rv
)) return -1;
609 if (port
!= -1) return port
; // explicitly specified
611 // Otherwise, we have to get the default port from the protocol handler
613 // Need the scheme first
614 nsAutoCString scheme
;
615 rv
= aURI
->GetScheme(scheme
);
616 if (NS_FAILED(rv
)) return -1;
618 return NS_GetDefaultPort(scheme
.get());
621 nsresult
NS_NewInputStreamChannelInternal(
622 nsIChannel
**outChannel
, nsIURI
*aUri
,
623 already_AddRefed
<nsIInputStream
> aStream
, const nsACString
&aContentType
,
624 const nsACString
&aContentCharset
, nsILoadInfo
*aLoadInfo
) {
626 nsCOMPtr
<nsIInputStreamChannel
> isc
=
627 do_CreateInstance(NS_INPUTSTREAMCHANNEL_CONTRACTID
, &rv
);
628 NS_ENSURE_SUCCESS(rv
, rv
);
629 rv
= isc
->SetURI(aUri
);
630 NS_ENSURE_SUCCESS(rv
, rv
);
632 nsCOMPtr
<nsIInputStream
> stream
= std::move(aStream
);
633 rv
= isc
->SetContentStream(stream
);
634 NS_ENSURE_SUCCESS(rv
, rv
);
636 nsCOMPtr
<nsIChannel
> channel
= do_QueryInterface(isc
, &rv
);
637 NS_ENSURE_SUCCESS(rv
, rv
);
639 if (!aContentType
.IsEmpty()) {
640 rv
= channel
->SetContentType(aContentType
);
641 NS_ENSURE_SUCCESS(rv
, rv
);
644 if (!aContentCharset
.IsEmpty()) {
645 rv
= channel
->SetContentCharset(aContentCharset
);
646 NS_ENSURE_SUCCESS(rv
, rv
);
649 channel
->SetLoadInfo(aLoadInfo
);
651 // If we're sandboxed, make sure to clear any owner the channel
652 // might already have.
653 if (aLoadInfo
&& aLoadInfo
->GetLoadingSandboxed()) {
654 channel
->SetOwner(nullptr);
657 channel
.forget(outChannel
);
661 nsresult
NS_NewInputStreamChannelInternal(
662 nsIChannel
**outChannel
, nsIURI
*aUri
,
663 already_AddRefed
<nsIInputStream
> aStream
, const nsACString
&aContentType
,
664 const nsACString
&aContentCharset
, nsINode
*aLoadingNode
,
665 nsIPrincipal
*aLoadingPrincipal
, nsIPrincipal
*aTriggeringPrincipal
,
666 nsSecurityFlags aSecurityFlags
, nsContentPolicyType aContentPolicyType
) {
667 nsCOMPtr
<nsILoadInfo
> loadInfo
= new mozilla::net::LoadInfo(
668 aLoadingPrincipal
, aTriggeringPrincipal
, aLoadingNode
, aSecurityFlags
,
671 return NS_ERROR_UNEXPECTED
;
674 nsCOMPtr
<nsIInputStream
> stream
= std::move(aStream
);
676 return NS_NewInputStreamChannelInternal(outChannel
, aUri
, stream
.forget(),
677 aContentType
, aContentCharset
,
681 nsresult
NS_NewInputStreamChannel(
682 nsIChannel
**outChannel
, nsIURI
*aUri
,
683 already_AddRefed
<nsIInputStream
> aStream
, nsIPrincipal
*aLoadingPrincipal
,
684 nsSecurityFlags aSecurityFlags
, nsContentPolicyType aContentPolicyType
,
685 const nsACString
&aContentType
/* = EmptyCString() */,
686 const nsACString
&aContentCharset
/* = EmptyCString() */) {
687 nsCOMPtr
<nsIInputStream
> stream
= aStream
;
688 return NS_NewInputStreamChannelInternal(outChannel
, aUri
, stream
.forget(),
689 aContentType
, aContentCharset
,
690 nullptr, // aLoadingNode
692 nullptr, // aTriggeringPrincipal
693 aSecurityFlags
, aContentPolicyType
);
696 nsresult
NS_NewInputStreamChannelInternal(nsIChannel
**outChannel
, nsIURI
*aUri
,
697 const nsAString
&aData
,
698 const nsACString
&aContentType
,
699 nsILoadInfo
*aLoadInfo
,
700 bool aIsSrcdocChannel
/* = false */) {
702 nsCOMPtr
<nsIStringInputStream
> stream
;
703 stream
= do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID
, &rv
);
704 NS_ENSURE_SUCCESS(rv
, rv
);
707 char *utf8Bytes
= ToNewUTF8String(aData
, &len
);
708 rv
= stream
->AdoptData(utf8Bytes
, len
);
710 nsCOMPtr
<nsIChannel
> channel
;
711 rv
= NS_NewInputStreamChannelInternal(getter_AddRefs(channel
), aUri
,
712 stream
.forget(), aContentType
,
713 NS_LITERAL_CSTRING("UTF-8"), aLoadInfo
);
715 NS_ENSURE_SUCCESS(rv
, rv
);
717 if (aIsSrcdocChannel
) {
718 nsCOMPtr
<nsIInputStreamChannel
> inStrmChan
= do_QueryInterface(channel
);
719 NS_ENSURE_TRUE(inStrmChan
, NS_ERROR_FAILURE
);
720 inStrmChan
->SetSrcdocData(aData
);
722 channel
.forget(outChannel
);
726 nsresult
NS_NewInputStreamChannelInternal(
727 nsIChannel
**outChannel
, nsIURI
*aUri
, const nsAString
&aData
,
728 const nsACString
&aContentType
, nsINode
*aLoadingNode
,
729 nsIPrincipal
*aLoadingPrincipal
, nsIPrincipal
*aTriggeringPrincipal
,
730 nsSecurityFlags aSecurityFlags
, nsContentPolicyType aContentPolicyType
,
731 bool aIsSrcdocChannel
/* = false */) {
732 nsCOMPtr
<nsILoadInfo
> loadInfo
= new mozilla::net::LoadInfo(
733 aLoadingPrincipal
, aTriggeringPrincipal
, aLoadingNode
, aSecurityFlags
,
735 return NS_NewInputStreamChannelInternal(outChannel
, aUri
, aData
, aContentType
,
736 loadInfo
, aIsSrcdocChannel
);
739 nsresult
NS_NewInputStreamChannel(nsIChannel
**outChannel
, nsIURI
*aUri
,
740 const nsAString
&aData
,
741 const nsACString
&aContentType
,
742 nsIPrincipal
*aLoadingPrincipal
,
743 nsSecurityFlags aSecurityFlags
,
744 nsContentPolicyType aContentPolicyType
,
745 bool aIsSrcdocChannel
/* = false */) {
746 return NS_NewInputStreamChannelInternal(outChannel
, aUri
, aData
, aContentType
,
747 nullptr, // aLoadingNode
749 nullptr, // aTriggeringPrincipal
750 aSecurityFlags
, aContentPolicyType
,
754 nsresult
NS_NewInputStreamPump(
755 nsIInputStreamPump
**aResult
, already_AddRefed
<nsIInputStream
> aStream
,
756 uint32_t aSegsize
/* = 0 */, uint32_t aSegcount
/* = 0 */,
757 bool aCloseWhenDone
/* = false */,
758 nsIEventTarget
*aMainThreadTarget
/* = nullptr */) {
759 nsCOMPtr
<nsIInputStream
> stream
= std::move(aStream
);
762 nsCOMPtr
<nsIInputStreamPump
> pump
=
763 do_CreateInstance(NS_INPUTSTREAMPUMP_CONTRACTID
, &rv
);
764 if (NS_SUCCEEDED(rv
)) {
765 rv
= pump
->Init(stream
, aSegsize
, aSegcount
, aCloseWhenDone
,
767 if (NS_SUCCEEDED(rv
)) {
775 nsresult
NS_NewLoadGroup(nsILoadGroup
**result
, nsIRequestObserver
*obs
) {
777 nsCOMPtr
<nsILoadGroup
> group
=
778 do_CreateInstance(NS_LOADGROUP_CONTRACTID
, &rv
);
779 if (NS_SUCCEEDED(rv
)) {
780 rv
= group
->SetGroupObserver(obs
);
781 if (NS_SUCCEEDED(rv
)) {
789 bool NS_IsReasonableHTTPHeaderValue(const nsACString
&aValue
) {
790 return mozilla::net::nsHttp::IsReasonableHeaderValue(aValue
);
793 bool NS_IsValidHTTPToken(const nsACString
&aToken
) {
794 return mozilla::net::nsHttp::IsValidToken(aToken
);
797 void NS_TrimHTTPWhitespace(const nsACString
&aSource
, nsACString
&aDest
) {
798 mozilla::net::nsHttp::TrimHTTPWhitespace(aSource
, aDest
);
801 nsresult
NS_NewLoadGroup(nsILoadGroup
**aResult
, nsIPrincipal
*aPrincipal
) {
802 using mozilla::LoadContext
;
805 nsCOMPtr
<nsILoadGroup
> group
=
806 do_CreateInstance(NS_LOADGROUP_CONTRACTID
, &rv
);
807 NS_ENSURE_SUCCESS(rv
, rv
);
809 RefPtr
<LoadContext
> loadContext
= new LoadContext(aPrincipal
);
810 rv
= group
->SetNotificationCallbacks(loadContext
);
811 NS_ENSURE_SUCCESS(rv
, rv
);
813 group
.forget(aResult
);
817 bool NS_LoadGroupMatchesPrincipal(nsILoadGroup
*aLoadGroup
,
818 nsIPrincipal
*aPrincipal
) {
823 // If this is a null principal then the load group doesn't really matter.
824 // The principal will not be allowed to perform any actions that actually
825 // use the load group. Unconditionally treat null principals as a match.
826 if (aPrincipal
->GetIsNullPrincipal()) {
834 nsCOMPtr
<nsILoadContext
> loadContext
;
835 NS_QueryNotificationCallbacks(nullptr, aLoadGroup
, NS_GET_IID(nsILoadContext
),
836 getter_AddRefs(loadContext
));
837 NS_ENSURE_TRUE(loadContext
, false);
839 // Verify load context browser flag match the principal
840 bool contextInIsolatedBrowser
;
842 loadContext
->GetIsInIsolatedMozBrowserElement(&contextInIsolatedBrowser
);
843 NS_ENSURE_SUCCESS(rv
, false);
845 return contextInIsolatedBrowser
==
846 aPrincipal
->GetIsInIsolatedMozBrowserElement();
849 nsresult
NS_NewDownloader(nsIStreamListener
**result
,
850 nsIDownloadObserver
*observer
,
851 nsIFile
*downloadLocation
/* = nullptr */) {
853 nsCOMPtr
<nsIDownloader
> downloader
=
854 do_CreateInstance(NS_DOWNLOADER_CONTRACTID
, &rv
);
855 if (NS_SUCCEEDED(rv
)) {
856 rv
= downloader
->Init(observer
, downloadLocation
);
857 if (NS_SUCCEEDED(rv
)) {
858 downloader
.forget(result
);
864 nsresult
NS_NewIncrementalStreamLoader(
865 nsIIncrementalStreamLoader
**result
,
866 nsIIncrementalStreamLoaderObserver
*observer
) {
868 nsCOMPtr
<nsIIncrementalStreamLoader
> loader
=
869 do_CreateInstance(NS_INCREMENTALSTREAMLOADER_CONTRACTID
, &rv
);
870 if (NS_SUCCEEDED(rv
)) {
871 rv
= loader
->Init(observer
);
872 if (NS_SUCCEEDED(rv
)) {
874 loader
.swap(*result
);
880 nsresult
NS_NewStreamLoader(
881 nsIStreamLoader
**result
, nsIStreamLoaderObserver
*observer
,
882 nsIRequestObserver
*requestObserver
/* = nullptr */) {
884 nsCOMPtr
<nsIStreamLoader
> loader
=
885 do_CreateInstance(NS_STREAMLOADER_CONTRACTID
, &rv
);
886 if (NS_SUCCEEDED(rv
)) {
887 rv
= loader
->Init(observer
, requestObserver
);
888 if (NS_SUCCEEDED(rv
)) {
890 loader
.swap(*result
);
896 nsresult
NS_NewStreamLoaderInternal(
897 nsIStreamLoader
**outStream
, nsIURI
*aUri
,
898 nsIStreamLoaderObserver
*aObserver
, nsINode
*aLoadingNode
,
899 nsIPrincipal
*aLoadingPrincipal
, nsSecurityFlags aSecurityFlags
,
900 nsContentPolicyType aContentPolicyType
,
901 nsILoadGroup
*aLoadGroup
/* = nullptr */,
902 nsIInterfaceRequestor
*aCallbacks
/* = nullptr */,
903 nsLoadFlags aLoadFlags
/* = nsIRequest::LOAD_NORMAL */,
904 nsIURI
*aReferrer
/* = nullptr */) {
905 nsCOMPtr
<nsIChannel
> channel
;
906 nsresult rv
= NS_NewChannelInternal(
907 getter_AddRefs(channel
), aUri
, aLoadingNode
, aLoadingPrincipal
,
908 nullptr, // aTriggeringPrincipal
909 Maybe
<ClientInfo
>(), Maybe
<ServiceWorkerDescriptor
>(), aSecurityFlags
,
911 nullptr, // PerformanceStorage
912 aLoadGroup
, aCallbacks
, aLoadFlags
);
914 NS_ENSURE_SUCCESS(rv
, rv
);
915 nsCOMPtr
<nsIHttpChannel
> httpChannel(do_QueryInterface(channel
));
917 rv
= httpChannel
->SetReferrer(aReferrer
);
918 MOZ_ASSERT(NS_SUCCEEDED(rv
));
920 rv
= NS_NewStreamLoader(outStream
, aObserver
);
921 NS_ENSURE_SUCCESS(rv
, rv
);
922 return channel
->AsyncOpen2(*outStream
);
925 nsresult
NS_NewStreamLoader(
926 nsIStreamLoader
**outStream
, nsIURI
*aUri
,
927 nsIStreamLoaderObserver
*aObserver
, nsINode
*aLoadingNode
,
928 nsSecurityFlags aSecurityFlags
, nsContentPolicyType aContentPolicyType
,
929 nsILoadGroup
*aLoadGroup
/* = nullptr */,
930 nsIInterfaceRequestor
*aCallbacks
/* = nullptr */,
931 nsLoadFlags aLoadFlags
/* = nsIRequest::LOAD_NORMAL */,
932 nsIURI
*aReferrer
/* = nullptr */) {
933 NS_ASSERTION(aLoadingNode
,
934 "Can not create stream loader without a loading Node!");
935 return NS_NewStreamLoaderInternal(
936 outStream
, aUri
, aObserver
, aLoadingNode
, aLoadingNode
->NodePrincipal(),
937 aSecurityFlags
, aContentPolicyType
, aLoadGroup
, aCallbacks
, aLoadFlags
,
941 nsresult
NS_NewStreamLoader(
942 nsIStreamLoader
**outStream
, nsIURI
*aUri
,
943 nsIStreamLoaderObserver
*aObserver
, nsIPrincipal
*aLoadingPrincipal
,
944 nsSecurityFlags aSecurityFlags
, nsContentPolicyType aContentPolicyType
,
945 nsILoadGroup
*aLoadGroup
/* = nullptr */,
946 nsIInterfaceRequestor
*aCallbacks
/* = nullptr */,
947 nsLoadFlags aLoadFlags
/* = nsIRequest::LOAD_NORMAL */,
948 nsIURI
*aReferrer
/* = nullptr */) {
949 return NS_NewStreamLoaderInternal(outStream
, aUri
, aObserver
,
950 nullptr, // aLoadingNode
951 aLoadingPrincipal
, aSecurityFlags
,
952 aContentPolicyType
, aLoadGroup
, aCallbacks
,
953 aLoadFlags
, aReferrer
);
956 nsresult
NS_NewSyncStreamListener(nsIStreamListener
**result
,
957 nsIInputStream
**stream
) {
958 nsCOMPtr
<nsISyncStreamListener
> listener
= nsSyncStreamListener::Create();
960 nsresult rv
= listener
->GetInputStream(stream
);
961 if (NS_SUCCEEDED(rv
)) {
962 listener
.forget(result
);
966 return NS_ERROR_FAILURE
;
969 nsresult
NS_ImplementChannelOpen(nsIChannel
*channel
, nsIInputStream
**result
) {
970 nsCOMPtr
<nsIStreamListener
> listener
;
971 nsCOMPtr
<nsIInputStream
> stream
;
972 nsresult rv
= NS_NewSyncStreamListener(getter_AddRefs(listener
),
973 getter_AddRefs(stream
));
974 NS_ENSURE_SUCCESS(rv
, rv
);
976 rv
= NS_MaybeOpenChannelUsingAsyncOpen2(channel
, listener
);
977 NS_ENSURE_SUCCESS(rv
, rv
);
980 // block until the initial response is received or an error occurs.
981 rv
= stream
->Available(&n
);
982 NS_ENSURE_SUCCESS(rv
, rv
);
985 stream
.swap(*result
);
990 nsresult
NS_NewRequestObserverProxy(nsIRequestObserver
**result
,
991 nsIRequestObserver
*observer
,
992 nsISupports
*context
) {
993 nsCOMPtr
<nsIRequestObserverProxy
> proxy
= new nsRequestObserverProxy();
994 nsresult rv
= proxy
->Init(observer
, context
);
995 if (NS_SUCCEEDED(rv
)) {
996 proxy
.forget(result
);
1001 nsresult
NS_NewSimpleStreamListener(
1002 nsIStreamListener
**result
, nsIOutputStream
*sink
,
1003 nsIRequestObserver
*observer
/* = nullptr */) {
1005 nsCOMPtr
<nsISimpleStreamListener
> listener
=
1006 do_CreateInstance(NS_SIMPLESTREAMLISTENER_CONTRACTID
, &rv
);
1007 if (NS_SUCCEEDED(rv
)) {
1008 rv
= listener
->Init(sink
, observer
);
1009 if (NS_SUCCEEDED(rv
)) {
1010 listener
.forget(result
);
1016 nsresult
NS_CheckPortSafety(int32_t port
, const char *scheme
,
1017 nsIIOService
*ioService
/* = nullptr */) {
1019 nsCOMPtr
<nsIIOService
> grip
;
1020 rv
= net_EnsureIOService(&ioService
, grip
);
1023 rv
= ioService
->AllowPort(port
, scheme
, &allow
);
1024 if (NS_SUCCEEDED(rv
) && !allow
) {
1025 NS_WARNING("port blocked");
1026 rv
= NS_ERROR_PORT_ACCESS_NOT_ALLOWED
;
1032 nsresult
NS_CheckPortSafety(nsIURI
*uri
) {
1034 nsresult rv
= uri
->GetPort(&port
);
1035 if (NS_FAILED(rv
) || port
== -1) // port undefined or default-valued
1037 nsAutoCString scheme
;
1038 uri
->GetScheme(scheme
);
1039 return NS_CheckPortSafety(port
, scheme
.get());
1042 nsresult
NS_NewProxyInfo(const nsACString
&type
, const nsACString
&host
,
1043 int32_t port
, uint32_t flags
, nsIProxyInfo
**result
) {
1045 nsCOMPtr
<nsIProtocolProxyService
> pps
=
1046 do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID
, &rv
);
1047 if (NS_SUCCEEDED(rv
))
1049 pps
->NewProxyInfo(type
, host
, port
, flags
, UINT32_MAX
, nullptr, result
);
1053 nsresult
NS_GetFileProtocolHandler(nsIFileProtocolHandler
**result
,
1054 nsIIOService
*ioService
/* = nullptr */) {
1056 nsCOMPtr
<nsIIOService
> grip
;
1057 rv
= net_EnsureIOService(&ioService
, grip
);
1059 nsCOMPtr
<nsIProtocolHandler
> handler
;
1060 rv
= ioService
->GetProtocolHandler("file", getter_AddRefs(handler
));
1061 if (NS_SUCCEEDED(rv
)) rv
= CallQueryInterface(handler
, result
);
1066 nsresult
NS_GetFileFromURLSpec(const nsACString
&inURL
, nsIFile
**result
,
1067 nsIIOService
*ioService
/* = nullptr */) {
1069 nsCOMPtr
<nsIFileProtocolHandler
> fileHandler
;
1070 rv
= NS_GetFileProtocolHandler(getter_AddRefs(fileHandler
), ioService
);
1071 if (NS_SUCCEEDED(rv
)) rv
= fileHandler
->GetFileFromURLSpec(inURL
, result
);
1075 nsresult
NS_GetURLSpecFromFile(nsIFile
*file
, nsACString
&url
,
1076 nsIIOService
*ioService
/* = nullptr */) {
1078 nsCOMPtr
<nsIFileProtocolHandler
> fileHandler
;
1079 rv
= NS_GetFileProtocolHandler(getter_AddRefs(fileHandler
), ioService
);
1080 if (NS_SUCCEEDED(rv
)) rv
= fileHandler
->GetURLSpecFromFile(file
, url
);
1084 nsresult
NS_GetURLSpecFromActualFile(nsIFile
*file
, nsACString
&url
,
1085 nsIIOService
*ioService
/* = nullptr */) {
1087 nsCOMPtr
<nsIFileProtocolHandler
> fileHandler
;
1088 rv
= NS_GetFileProtocolHandler(getter_AddRefs(fileHandler
), ioService
);
1089 if (NS_SUCCEEDED(rv
)) rv
= fileHandler
->GetURLSpecFromActualFile(file
, url
);
1093 nsresult
NS_GetURLSpecFromDir(nsIFile
*file
, nsACString
&url
,
1094 nsIIOService
*ioService
/* = nullptr */) {
1096 nsCOMPtr
<nsIFileProtocolHandler
> fileHandler
;
1097 rv
= NS_GetFileProtocolHandler(getter_AddRefs(fileHandler
), ioService
);
1098 if (NS_SUCCEEDED(rv
)) rv
= fileHandler
->GetURLSpecFromDir(file
, url
);
1102 nsresult
NS_GetReferrerFromChannel(nsIChannel
*channel
, nsIURI
**referrer
) {
1103 nsresult rv
= NS_ERROR_NOT_AVAILABLE
;
1104 *referrer
= nullptr;
1106 nsCOMPtr
<nsIPropertyBag2
> props(do_QueryInterface(channel
));
1108 // We have to check for a property on a property bag because the
1109 // referrer may be empty for security reasons (for example, when loading
1110 // an http page with an https referrer).
1111 rv
= props
->GetPropertyAsInterface(
1112 NS_LITERAL_STRING("docshell.internalReferrer"), NS_GET_IID(nsIURI
),
1113 reinterpret_cast<void **>(referrer
));
1114 if (NS_FAILED(rv
)) *referrer
= nullptr;
1117 // if that didn't work, we can still try to get the referrer from the
1118 // nsIHttpChannel (if we can QI to it)
1120 nsCOMPtr
<nsIHttpChannel
> chan(do_QueryInterface(channel
));
1122 rv
= chan
->GetReferrer(referrer
);
1123 if (NS_FAILED(rv
)) *referrer
= nullptr;
1129 already_AddRefed
<nsINetUtil
> do_GetNetUtil(nsresult
*error
/* = 0 */) {
1130 nsCOMPtr
<nsIIOService
> io
= mozilla::services::GetIOService();
1131 nsCOMPtr
<nsINetUtil
> util
;
1132 if (io
) util
= do_QueryInterface(io
);
1134 if (error
) *error
= !!util
? NS_OK
: NS_ERROR_FAILURE
;
1135 return util
.forget();
1138 nsresult
NS_ParseRequestContentType(const nsACString
&rawContentType
,
1139 nsCString
&contentType
,
1140 nsCString
&contentCharset
) {
1141 // contentCharset is left untouched if not present in rawContentType
1143 nsCOMPtr
<nsINetUtil
> util
= do_GetNetUtil(&rv
);
1144 NS_ENSURE_SUCCESS(rv
, rv
);
1147 rv
= util
->ParseRequestContentType(rawContentType
, charset
, &hadCharset
,
1149 if (NS_SUCCEEDED(rv
) && hadCharset
) contentCharset
= charset
;
1153 nsresult
NS_ParseResponseContentType(const nsACString
&rawContentType
,
1154 nsCString
&contentType
,
1155 nsCString
&contentCharset
) {
1156 // contentCharset is left untouched if not present in rawContentType
1158 nsCOMPtr
<nsINetUtil
> util
= do_GetNetUtil(&rv
);
1159 NS_ENSURE_SUCCESS(rv
, rv
);
1162 rv
= util
->ParseResponseContentType(rawContentType
, charset
, &hadCharset
,
1164 if (NS_SUCCEEDED(rv
) && hadCharset
) contentCharset
= charset
;
1168 nsresult
NS_ExtractCharsetFromContentType(const nsACString
&rawContentType
,
1169 nsCString
&contentCharset
,
1171 int32_t *charsetStart
,
1172 int32_t *charsetEnd
) {
1173 // contentCharset is left untouched if not present in rawContentType
1175 nsCOMPtr
<nsINetUtil
> util
= do_GetNetUtil(&rv
);
1176 NS_ENSURE_SUCCESS(rv
, rv
);
1178 return util
->ExtractCharsetFromContentType(
1179 rawContentType
, contentCharset
, charsetStart
, charsetEnd
, hadCharset
);
1182 nsresult
NS_NewAtomicFileOutputStream(nsIOutputStream
**result
, nsIFile
*file
,
1183 int32_t ioFlags
/* = -1 */,
1184 int32_t perm
/* = -1 */,
1185 int32_t behaviorFlags
/* = 0 */) {
1187 nsCOMPtr
<nsIFileOutputStream
> out
=
1188 do_CreateInstance(NS_ATOMICLOCALFILEOUTPUTSTREAM_CONTRACTID
, &rv
);
1189 if (NS_SUCCEEDED(rv
)) {
1190 rv
= out
->Init(file
, ioFlags
, perm
, behaviorFlags
);
1191 if (NS_SUCCEEDED(rv
)) out
.forget(result
);
1196 nsresult
NS_NewSafeLocalFileOutputStream(nsIOutputStream
**result
,
1198 int32_t ioFlags
/* = -1 */,
1199 int32_t perm
/* = -1 */,
1200 int32_t behaviorFlags
/* = 0 */) {
1202 nsCOMPtr
<nsIFileOutputStream
> out
=
1203 do_CreateInstance(NS_SAFELOCALFILEOUTPUTSTREAM_CONTRACTID
, &rv
);
1204 if (NS_SUCCEEDED(rv
)) {
1205 rv
= out
->Init(file
, ioFlags
, perm
, behaviorFlags
);
1206 if (NS_SUCCEEDED(rv
)) out
.forget(result
);
1211 nsresult
NS_NewLocalFileStream(nsIFileStream
**result
, nsIFile
*file
,
1212 int32_t ioFlags
/* = -1 */,
1213 int32_t perm
/* = -1 */,
1214 int32_t behaviorFlags
/* = 0 */) {
1215 nsCOMPtr
<nsIFileStream
> stream
= new nsFileStream();
1216 nsresult rv
= stream
->Init(file
, ioFlags
, perm
, behaviorFlags
);
1217 if (NS_SUCCEEDED(rv
)) {
1218 stream
.forget(result
);
1223 nsresult
NS_NewBufferedOutputStream(
1224 nsIOutputStream
**aResult
, already_AddRefed
<nsIOutputStream
> aOutputStream
,
1225 uint32_t aBufferSize
) {
1226 nsCOMPtr
<nsIOutputStream
> outputStream
= std::move(aOutputStream
);
1229 nsCOMPtr
<nsIBufferedOutputStream
> out
=
1230 do_CreateInstance(NS_BUFFEREDOUTPUTSTREAM_CONTRACTID
, &rv
);
1231 if (NS_SUCCEEDED(rv
)) {
1232 rv
= out
->Init(outputStream
, aBufferSize
);
1233 if (NS_SUCCEEDED(rv
)) {
1234 out
.forget(aResult
);
1240 MOZ_MUST_USE nsresult
NS_NewBufferedInputStream(
1241 nsIInputStream
**aResult
, already_AddRefed
<nsIInputStream
> aInputStream
,
1242 uint32_t aBufferSize
) {
1243 nsCOMPtr
<nsIInputStream
> inputStream
= std::move(aInputStream
);
1246 nsCOMPtr
<nsIBufferedInputStream
> in
=
1247 do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID
, &rv
);
1248 if (NS_SUCCEEDED(rv
)) {
1249 rv
= in
->Init(inputStream
, aBufferSize
);
1250 if (NS_SUCCEEDED(rv
)) {
1259 #define BUFFER_SIZE 8192
1261 class BufferWriter final
: public nsIInputStreamCallback
{
1263 NS_DECL_THREADSAFE_ISUPPORTS
1265 BufferWriter(nsIInputStream
*aInputStream
, void *aBuffer
, int64_t aCount
)
1266 : mMonitor("BufferWriter.mMonitor"),
1267 mInputStream(aInputStream
),
1271 mBufferType(aBuffer
? eExternal
: eInternal
),
1273 MOZ_ASSERT(aInputStream
);
1274 MOZ_ASSERT(aCount
== -1 || aCount
> 0);
1275 MOZ_ASSERT_IF(mBuffer
, aCount
> 0);
1279 NS_ASSERT_OWNINGTHREAD(BufferWriter
);
1281 // Let's make the inputStream buffered if it's not.
1282 if (!NS_InputStreamIsBuffered(mInputStream
)) {
1283 nsCOMPtr
<nsIInputStream
> bufferedStream
;
1284 nsresult rv
= NS_NewBufferedInputStream(
1285 getter_AddRefs(bufferedStream
), mInputStream
.forget(), BUFFER_SIZE
);
1286 NS_ENSURE_SUCCESS(rv
, rv
);
1288 mInputStream
= bufferedStream
;
1291 mAsyncInputStream
= do_QueryInterface(mInputStream
);
1293 if (!mAsyncInputStream
) {
1297 // Let's use mAsyncInputStream only.
1298 mInputStream
= nullptr;
1300 return WriteAsync();
1303 uint64_t WrittenData() const {
1304 NS_ASSERT_OWNINGTHREAD(BufferWriter
);
1305 return mWrittenData
;
1308 void *StealBuffer() {
1309 NS_ASSERT_OWNINGTHREAD(BufferWriter
);
1310 MOZ_ASSERT(mBufferType
== eInternal
);
1312 void *buffer
= mBuffer
;
1322 if (mBuffer
&& mBufferType
== eInternal
) {
1327 mTaskQueue
->BeginShutdown();
1331 nsresult
WriteSync() {
1332 NS_ASSERT_OWNINGTHREAD(BufferWriter
);
1334 uint64_t length
= (uint64_t)mCount
;
1337 nsresult rv
= mInputStream
->Available(&length
);
1338 NS_ENSURE_SUCCESS(rv
, rv
);
1346 if (mBufferType
== eInternal
) {
1347 mBuffer
= malloc(length
);
1348 if (NS_WARN_IF(!mBuffer
)) {
1349 return NS_ERROR_OUT_OF_MEMORY
;
1353 uint32_t writtenData
;
1354 nsresult rv
= mInputStream
->ReadSegments(NS_CopySegmentToBuffer
, mBuffer
,
1355 length
, &writtenData
);
1356 NS_ENSURE_SUCCESS(rv
, rv
);
1358 mWrittenData
= writtenData
;
1362 nsresult
WriteAsync() {
1363 NS_ASSERT_OWNINGTHREAD(BufferWriter
);
1365 if (mCount
> 0 && mBufferType
== eInternal
) {
1366 mBuffer
= malloc(mCount
);
1367 if (NS_WARN_IF(!mBuffer
)) {
1368 return NS_ERROR_OUT_OF_MEMORY
;
1373 if (mCount
== -1 && !MaybeExpandBufferSize()) {
1374 return NS_ERROR_OUT_OF_MEMORY
;
1377 uint64_t offset
= mWrittenData
;
1378 uint64_t length
= mCount
== -1 ? BUFFER_SIZE
: mCount
;
1380 // Let's try to read data directly.
1381 uint32_t writtenData
;
1382 nsresult rv
= mAsyncInputStream
->ReadSegments(
1383 NS_CopySegmentToBuffer
, static_cast<char *>(mBuffer
) + offset
, length
,
1386 // Operation completed. Nothing more to read.
1387 if (NS_SUCCEEDED(rv
) && writtenData
== 0) {
1391 // If we succeeded, let's try to read again.
1392 if (NS_SUCCEEDED(rv
)) {
1393 mWrittenData
+= writtenData
;
1395 MOZ_ASSERT(mCount
>= writtenData
);
1396 mCount
-= writtenData
;
1398 // Is this the end of the reading?
1408 if (rv
== NS_BASE_STREAM_WOULD_BLOCK
) {
1409 rv
= MaybeCreateTaskQueue();
1410 if (NS_WARN_IF(NS_FAILED(rv
))) {
1414 MonitorAutoLock
lock(mMonitor
);
1416 rv
= mAsyncInputStream
->AsyncWait(this, 0, length
, mTaskQueue
);
1417 if (NS_WARN_IF(NS_FAILED(rv
))) {
1425 // Otherwise, let's propagate the error.
1429 MOZ_ASSERT_UNREACHABLE("We should not be here");
1430 return NS_ERROR_FAILURE
;
1433 nsresult
MaybeCreateTaskQueue() {
1434 NS_ASSERT_OWNINGTHREAD(BufferWriter
);
1437 nsCOMPtr
<nsIEventTarget
> target
=
1438 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID
);
1440 return NS_ERROR_FAILURE
;
1443 mTaskQueue
= new TaskQueue(target
.forget());
1450 OnInputStreamReady(nsIAsyncInputStream
*aStream
) override
{
1451 MOZ_ASSERT(!NS_IsMainThread());
1453 // We have something to read. Let's unlock the main-thread.
1454 MonitorAutoLock
lock(mMonitor
);
1459 bool MaybeExpandBufferSize() {
1460 NS_ASSERT_OWNINGTHREAD(BufferWriter
);
1462 MOZ_ASSERT(mCount
== -1);
1464 if (mBufferSize
>= mWrittenData
+ BUFFER_SIZE
) {
1465 // The buffer is big enough.
1469 CheckedUint32 bufferSize
=
1470 std::max
<uint32_t>(static_cast<uint32_t>(mWrittenData
), BUFFER_SIZE
);
1471 while (bufferSize
.isValid() &&
1472 bufferSize
.value() < mWrittenData
+ BUFFER_SIZE
) {
1476 if (!bufferSize
.isValid()) {
1480 void *buffer
= realloc(mBuffer
, bufferSize
.value());
1486 mBufferSize
= bufferSize
.value();
1490 // All the members of this class are touched on the owning thread only. The
1491 // monitor is only used to communicate when there is more data to read.
1494 nsCOMPtr
<nsIInputStream
> mInputStream
;
1495 nsCOMPtr
<nsIAsyncInputStream
> mAsyncInputStream
;
1497 RefPtr
<TaskQueue
> mTaskQueue
;
1501 uint64_t mWrittenData
;
1504 // The buffer is allocated internally and this object must release it
1505 // in the DTOR if not stolen. The buffer can be reallocated.
1508 // The buffer is not owned by this object and it cannot be reallocated.
1512 // The following set if needed for the async read.
1513 uint64_t mBufferSize
;
1516 NS_IMPL_ISUPPORTS(BufferWriter
, nsIInputStreamCallback
)
1518 } // anonymous namespace
1520 nsresult
NS_ReadInputStreamToBuffer(nsIInputStream
*aInputStream
, void **aDest
,
1521 int64_t aCount
, uint64_t *aWritten
) {
1522 MOZ_ASSERT(aInputStream
);
1523 MOZ_ASSERT(aCount
>= -1);
1525 uint64_t dummyWritten
;
1527 aWritten
= &dummyWritten
;
1535 // This will take care of allocating and reallocating aDest.
1536 RefPtr
<BufferWriter
> writer
= new BufferWriter(aInputStream
, *aDest
, aCount
);
1538 nsresult rv
= writer
->Write();
1539 NS_ENSURE_SUCCESS(rv
, rv
);
1541 *aWritten
= writer
->WrittenData();
1544 *aDest
= writer
->StealBuffer();
1550 nsresult
NS_ReadInputStreamToString(nsIInputStream
*aInputStream
,
1551 nsACString
&aDest
, int64_t aCount
,
1552 uint64_t *aWritten
) {
1553 uint64_t dummyWritten
;
1555 aWritten
= &dummyWritten
;
1558 // Nothing to do if aCount is 0.
1565 // If we have the size, we can pre-allocate the buffer.
1567 if (NS_WARN_IF(aCount
>= INT32_MAX
) ||
1568 NS_WARN_IF(!aDest
.SetLength(aCount
, mozilla::fallible
))) {
1569 return NS_ERROR_OUT_OF_MEMORY
;
1572 void *dest
= aDest
.BeginWriting();
1574 NS_ReadInputStreamToBuffer(aInputStream
, &dest
, aCount
, aWritten
);
1575 NS_ENSURE_SUCCESS(rv
, rv
);
1577 if ((uint64_t)aCount
> *aWritten
) {
1578 aDest
.Truncate(*aWritten
);
1584 // If the size is unknown, BufferWriter will allocate the buffer.
1585 void *dest
= nullptr;
1587 NS_ReadInputStreamToBuffer(aInputStream
, &dest
, aCount
, aWritten
);
1588 MOZ_ASSERT_IF(NS_FAILED(rv
), dest
== nullptr);
1589 NS_ENSURE_SUCCESS(rv
, rv
);
1592 MOZ_ASSERT(*aWritten
== 0);
1597 aDest
.Adopt(reinterpret_cast<char *>(dest
), *aWritten
);
1602 nsIURI
**result
, const nsACString
&spec
,
1603 const char *charset
/* = nullptr */, nsIURI
*baseURI
/* = nullptr */,
1605 *ioService
/* = nullptr */) // pass in nsIIOService to optimize callers
1608 nsCOMPtr
<nsIIOService
> grip
;
1609 rv
= net_EnsureIOService(&ioService
, grip
);
1610 if (ioService
) rv
= ioService
->NewURI(spec
, charset
, baseURI
, result
);
1615 nsIURI
**result
, const nsACString
&spec
, NotNull
<const Encoding
*> encoding
,
1616 nsIURI
*baseURI
/* = nullptr */,
1618 *ioService
/* = nullptr */) // pass in nsIIOService to optimize callers
1620 nsAutoCString charset
;
1621 encoding
->Name(charset
);
1622 return NS_NewURI(result
, spec
, charset
.get(), baseURI
, ioService
);
1626 nsIURI
**result
, const nsAString
&spec
, const char *charset
/* = nullptr */,
1627 nsIURI
*baseURI
/* = nullptr */,
1629 *ioService
/* = nullptr */) // pass in nsIIOService to optimize callers
1631 return NS_NewURI(result
, NS_ConvertUTF16toUTF8(spec
), charset
, baseURI
,
1636 nsIURI
**result
, const nsAString
&spec
, NotNull
<const Encoding
*> encoding
,
1637 nsIURI
*baseURI
/* = nullptr */,
1639 *ioService
/* = nullptr */) // pass in nsIIOService to optimize callers
1641 return NS_NewURI(result
, NS_ConvertUTF16toUTF8(spec
), encoding
, baseURI
,
1646 nsIURI
**result
, const char *spec
, nsIURI
*baseURI
/* = nullptr */,
1648 *ioService
/* = nullptr */) // pass in nsIIOService to optimize callers
1650 return NS_NewURI(result
, nsDependentCString(spec
), nullptr, baseURI
,
1654 nsresult
NS_GetSanitizedURIStringFromURI(nsIURI
*aUri
,
1655 nsAString
&aSanitizedSpec
) {
1656 aSanitizedSpec
.Truncate();
1658 nsCOMPtr
<nsISensitiveInfoHiddenURI
> safeUri
= do_QueryInterface(aUri
);
1659 nsAutoCString cSpec
;
1662 rv
= safeUri
->GetSensitiveInfoHiddenSpec(cSpec
);
1664 rv
= aUri
->GetSpec(cSpec
);
1667 if (NS_SUCCEEDED(rv
)) {
1668 aSanitizedSpec
.Assign(NS_ConvertUTF8toUTF16(cSpec
));
1673 nsresult
NS_LoadPersistentPropertiesFromURISpec(
1674 nsIPersistentProperties
**outResult
, const nsACString
&aSpec
) {
1675 nsCOMPtr
<nsIURI
> uri
;
1676 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aSpec
);
1677 NS_ENSURE_SUCCESS(rv
, rv
);
1679 nsCOMPtr
<nsIChannel
> channel
;
1680 rv
= NS_NewChannel(getter_AddRefs(channel
), uri
,
1681 nsContentUtils::GetSystemPrincipal(),
1682 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL
,
1683 nsIContentPolicy::TYPE_OTHER
);
1684 NS_ENSURE_SUCCESS(rv
, rv
);
1685 nsCOMPtr
<nsIInputStream
> in
;
1686 rv
= channel
->Open2(getter_AddRefs(in
));
1687 NS_ENSURE_SUCCESS(rv
, rv
);
1689 nsCOMPtr
<nsIPersistentProperties
> properties
= new nsPersistentProperties();
1690 rv
= properties
->Load(in
);
1691 NS_ENSURE_SUCCESS(rv
, rv
);
1693 properties
.swap(*outResult
);
1697 bool NS_UsePrivateBrowsing(nsIChannel
*channel
) {
1698 OriginAttributes attrs
;
1699 bool result
= NS_GetOriginAttributes(channel
, attrs
);
1700 NS_ENSURE_TRUE(result
, result
);
1701 return attrs
.mPrivateBrowsingId
> 0;
1704 bool NS_GetOriginAttributes(nsIChannel
*aChannel
,
1705 mozilla::OriginAttributes
&aAttributes
) {
1706 nsCOMPtr
<nsILoadInfo
> loadInfo
= aChannel
->GetLoadInfo();
1707 // For some channels, they might not have loadInfo, like
1708 // ExternalHelperAppParent..
1710 loadInfo
->GetOriginAttributes(&aAttributes
);
1713 bool isPrivate
= false;
1714 nsCOMPtr
<nsIPrivateBrowsingChannel
> pbChannel
= do_QueryInterface(aChannel
);
1716 nsresult rv
= pbChannel
->GetIsChannelPrivate(&isPrivate
);
1717 NS_ENSURE_SUCCESS(rv
, false);
1719 // Some channels may not implement nsIPrivateBrowsingChannel
1720 nsCOMPtr
<nsILoadContext
> loadContext
;
1721 NS_QueryNotificationCallbacks(aChannel
, loadContext
);
1722 isPrivate
= loadContext
&& loadContext
->UsePrivateBrowsing();
1724 aAttributes
.SyncAttributesWithPrivateBrowsing(isPrivate
);
1728 bool NS_HasBeenCrossOrigin(nsIChannel
*aChannel
, bool aReport
) {
1729 nsCOMPtr
<nsILoadInfo
> loadInfo
= aChannel
->GetLoadInfo();
1732 "Origin tracking only works for channels created with a loadinfo");
1738 // TYPE_DOCUMENT loads have a null LoadingPrincipal and can not be cross
1740 if (!loadInfo
->LoadingPrincipal()) {
1744 // Always treat tainted channels as cross-origin.
1745 if (loadInfo
->GetTainting() != LoadTainting::Basic
) {
1749 nsCOMPtr
<nsIPrincipal
> loadingPrincipal
= loadInfo
->LoadingPrincipal();
1750 uint32_t mode
= loadInfo
->GetSecurityMode();
1752 mode
== nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS
||
1753 mode
== nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS
||
1754 mode
== nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS
;
1756 bool aboutBlankInherits
= dataInherits
&& loadInfo
->GetAboutBlankInherits();
1758 for (nsIRedirectHistoryEntry
*redirectHistoryEntry
:
1759 loadInfo
->RedirectChain()) {
1760 nsCOMPtr
<nsIPrincipal
> principal
;
1761 redirectHistoryEntry
->GetPrincipal(getter_AddRefs(principal
));
1766 nsCOMPtr
<nsIURI
> uri
;
1767 principal
->GetURI(getter_AddRefs(uri
));
1772 if (aboutBlankInherits
&& NS_IsAboutBlank(uri
)) {
1776 if (NS_FAILED(loadingPrincipal
->CheckMayLoad(uri
, aReport
, dataInherits
))) {
1781 nsCOMPtr
<nsIURI
> uri
;
1782 NS_GetFinalChannelURI(aChannel
, getter_AddRefs(uri
));
1787 if (aboutBlankInherits
&& NS_IsAboutBlank(uri
)) {
1791 return NS_FAILED(loadingPrincipal
->CheckMayLoad(uri
, aReport
, dataInherits
));
1794 bool NS_IsSafeTopLevelNav(nsIChannel
*aChannel
) {
1798 nsCOMPtr
<nsILoadInfo
> loadInfo
= aChannel
->GetLoadInfo();
1802 if (loadInfo
->GetExternalContentPolicyType() !=
1803 nsIContentPolicy::TYPE_DOCUMENT
) {
1806 RefPtr
<HttpBaseChannel
> baseChan
= do_QueryObject(aChannel
);
1810 nsHttpRequestHead
*requestHead
= baseChan
->GetRequestHead();
1814 return requestHead
->IsSafeMethod();
1817 bool NS_IsSameSiteForeign(nsIChannel
*aChannel
, nsIURI
*aHostURI
) {
1821 nsCOMPtr
<nsILoadInfo
> loadInfo
= aChannel
->GetLoadInfo();
1826 // Do not treat loads triggered by web extensions as foreign
1827 nsCOMPtr
<nsIURI
> channelURI
;
1828 NS_GetFinalChannelURI(aChannel
, getter_AddRefs(channelURI
));
1829 if (BasePrincipal::Cast(loadInfo
->TriggeringPrincipal())
1830 ->AddonAllowsLoad(channelURI
)) {
1834 nsCOMPtr
<nsIURI
> uri
;
1835 if (loadInfo
->GetExternalContentPolicyType() ==
1836 nsIContentPolicy::TYPE_DOCUMENT
) {
1837 // for loads of TYPE_DOCUMENT we query the hostURI from the
1838 // triggeringPricnipal which returns the URI of the document that caused the
1840 loadInfo
->TriggeringPrincipal()->GetURI(getter_AddRefs(uri
));
1845 nsCOMPtr
<mozIThirdPartyUtil
> thirdPartyUtil
=
1846 do_GetService(THIRDPARTYUTIL_CONTRACTID
);
1847 if (!thirdPartyUtil
) {
1851 bool isForeign
= true;
1852 nsresult rv
= thirdPartyUtil
->IsThirdPartyChannel(aChannel
, uri
, &isForeign
);
1853 // if we are dealing with a cross origin request, we can return here
1854 // because we already know the request is 'foreign'.
1855 if (NS_FAILED(rv
) || isForeign
) {
1859 // for loads of TYPE_SUBDOCUMENT we have to perform an additional test,
1860 // because a cross-origin iframe might perform a navigation to a same-origin
1861 // iframe which would send same-site cookies. Hence, if the iframe navigation
1862 // was triggered by a cross-origin triggeringPrincipal, we treat the load as
1864 if (loadInfo
->GetExternalContentPolicyType() ==
1865 nsIContentPolicy::TYPE_SUBDOCUMENT
) {
1866 nsCOMPtr
<nsIURI
> triggeringPrincipalURI
;
1867 loadInfo
->TriggeringPrincipal()->GetURI(
1868 getter_AddRefs(triggeringPrincipalURI
));
1869 rv
= thirdPartyUtil
->IsThirdPartyChannel(aChannel
, triggeringPrincipalURI
,
1871 if (NS_FAILED(rv
) || isForeign
) {
1876 // for the purpose of same-site cookies we have to treat any cross-origin
1877 // redirects as foreign. E.g. cross-site to same-site redirect is a problem
1878 // with regards to CSRF.
1880 nsCOMPtr
<nsIPrincipal
> redirectPrincipal
;
1881 nsCOMPtr
<nsIURI
> redirectURI
;
1882 for (nsIRedirectHistoryEntry
*entry
: loadInfo
->RedirectChain()) {
1883 entry
->GetPrincipal(getter_AddRefs(redirectPrincipal
));
1884 if (redirectPrincipal
) {
1885 redirectPrincipal
->GetURI(getter_AddRefs(redirectURI
));
1886 rv
= thirdPartyUtil
->IsThirdPartyChannel(aChannel
, redirectURI
,
1888 // if at any point we encounter a cross-origin redirect we can return.
1889 if (NS_FAILED(rv
) || isForeign
) {
1897 bool NS_ShouldCheckAppCache(nsIPrincipal
*aPrincipal
) {
1898 uint32_t privateBrowsingId
= 0;
1899 nsresult rv
= aPrincipal
->GetPrivateBrowsingId(&privateBrowsingId
);
1900 if (NS_SUCCEEDED(rv
) && (privateBrowsingId
> 0)) {
1904 nsCOMPtr
<nsIOfflineCacheUpdateService
> offlineService
=
1905 do_GetService("@mozilla.org/offlinecacheupdate-service;1");
1906 if (!offlineService
) {
1911 rv
= offlineService
->OfflineAppAllowed(aPrincipal
, nullptr, &allowed
);
1912 return NS_SUCCEEDED(rv
) && allowed
;
1915 void NS_WrapAuthPrompt(nsIAuthPrompt
*aAuthPrompt
,
1916 nsIAuthPrompt2
**aAuthPrompt2
) {
1917 nsCOMPtr
<nsIAuthPromptAdapterFactory
> factory
=
1918 do_GetService(NS_AUTHPROMPT_ADAPTER_FACTORY_CONTRACTID
);
1919 if (!factory
) return;
1921 NS_WARNING("Using deprecated nsIAuthPrompt");
1922 factory
->CreateAdapter(aAuthPrompt
, aAuthPrompt2
);
1925 void NS_QueryAuthPrompt2(nsIInterfaceRequestor
*aCallbacks
,
1926 nsIAuthPrompt2
**aAuthPrompt
) {
1927 CallGetInterface(aCallbacks
, aAuthPrompt
);
1928 if (*aAuthPrompt
) return;
1930 // Maybe only nsIAuthPrompt is provided and we have to wrap it.
1931 nsCOMPtr
<nsIAuthPrompt
> prompt(do_GetInterface(aCallbacks
));
1932 if (!prompt
) return;
1934 NS_WrapAuthPrompt(prompt
, aAuthPrompt
);
1937 void NS_QueryAuthPrompt2(nsIChannel
*aChannel
, nsIAuthPrompt2
**aAuthPrompt
) {
1938 *aAuthPrompt
= nullptr;
1940 // We want to use any auth prompt we can find on the channel's callbacks,
1941 // and if that fails use the loadgroup's prompt (if any)
1942 // Therefore, we can't just use NS_QueryNotificationCallbacks, because
1943 // that would prefer a loadgroup's nsIAuthPrompt2 over a channel's
1945 nsCOMPtr
<nsIInterfaceRequestor
> callbacks
;
1946 aChannel
->GetNotificationCallbacks(getter_AddRefs(callbacks
));
1948 NS_QueryAuthPrompt2(callbacks
, aAuthPrompt
);
1949 if (*aAuthPrompt
) return;
1952 nsCOMPtr
<nsILoadGroup
> group
;
1953 aChannel
->GetLoadGroup(getter_AddRefs(group
));
1956 group
->GetNotificationCallbacks(getter_AddRefs(callbacks
));
1957 if (!callbacks
) return;
1958 NS_QueryAuthPrompt2(callbacks
, aAuthPrompt
);
1961 nsresult
NS_NewNotificationCallbacksAggregation(
1962 nsIInterfaceRequestor
*callbacks
, nsILoadGroup
*loadGroup
,
1963 nsIEventTarget
*target
, nsIInterfaceRequestor
**result
) {
1964 nsCOMPtr
<nsIInterfaceRequestor
> cbs
;
1965 if (loadGroup
) loadGroup
->GetNotificationCallbacks(getter_AddRefs(cbs
));
1966 return NS_NewInterfaceRequestorAggregation(callbacks
, cbs
, target
, result
);
1969 nsresult
NS_NewNotificationCallbacksAggregation(
1970 nsIInterfaceRequestor
*callbacks
, nsILoadGroup
*loadGroup
,
1971 nsIInterfaceRequestor
**result
) {
1972 return NS_NewNotificationCallbacksAggregation(callbacks
, loadGroup
, nullptr,
1976 nsresult
NS_DoImplGetInnermostURI(nsINestedURI
*nestedURI
, nsIURI
**result
) {
1977 MOZ_ASSERT(nestedURI
, "Must have a nested URI!");
1978 MOZ_ASSERT(!*result
, "Must have null *result");
1980 nsCOMPtr
<nsIURI
> inner
;
1981 nsresult rv
= nestedURI
->GetInnerURI(getter_AddRefs(inner
));
1982 NS_ENSURE_SUCCESS(rv
, rv
);
1984 // We may need to loop here until we reach the innermost
1986 nsCOMPtr
<nsINestedURI
> nestedInner(do_QueryInterface(inner
));
1987 while (nestedInner
) {
1988 rv
= nestedInner
->GetInnerURI(getter_AddRefs(inner
));
1989 NS_ENSURE_SUCCESS(rv
, rv
);
1990 nestedInner
= do_QueryInterface(inner
);
1993 // Found the innermost one if we reach here.
1994 inner
.swap(*result
);
1999 nsresult
NS_ImplGetInnermostURI(nsINestedURI
*nestedURI
, nsIURI
**result
) {
2000 // Make it safe to use swap()
2003 return NS_DoImplGetInnermostURI(nestedURI
, result
);
2006 already_AddRefed
<nsIURI
> NS_GetInnermostURI(nsIURI
*aURI
) {
2007 MOZ_ASSERT(aURI
, "Must have URI");
2009 nsCOMPtr
<nsIURI
> uri
= aURI
;
2011 nsCOMPtr
<nsINestedURI
> nestedURI(do_QueryInterface(uri
));
2013 return uri
.forget();
2016 nsresult rv
= nestedURI
->GetInnermostURI(getter_AddRefs(uri
));
2017 if (NS_FAILED(rv
)) {
2021 return uri
.forget();
2024 nsresult
NS_GetFinalChannelURI(nsIChannel
*channel
, nsIURI
**uri
) {
2027 nsCOMPtr
<nsILoadInfo
> loadInfo
= channel
->GetLoadInfo();
2029 nsCOMPtr
<nsIURI
> resultPrincipalURI
;
2030 loadInfo
->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI
));
2031 if (resultPrincipalURI
) {
2032 resultPrincipalURI
.forget(uri
);
2037 return channel
->GetOriginalURI(uri
);
2040 nsresult
NS_URIChainHasFlags(nsIURI
*uri
, uint32_t flags
, bool *result
) {
2042 nsCOMPtr
<nsINetUtil
> util
= do_GetNetUtil(&rv
);
2043 NS_ENSURE_SUCCESS(rv
, rv
);
2045 return util
->URIChainHasFlags(uri
, flags
, result
);
2048 uint32_t NS_SecurityHashURI(nsIURI
*aURI
) {
2049 nsCOMPtr
<nsIURI
> baseURI
= NS_GetInnermostURI(aURI
);
2051 nsAutoCString scheme
;
2052 uint32_t schemeHash
= 0;
2053 if (NS_SUCCEEDED(baseURI
->GetScheme(scheme
)))
2054 schemeHash
= mozilla::HashString(scheme
);
2056 // TODO figure out how to hash file:// URIs
2057 if (scheme
.EqualsLiteral("file")) return schemeHash
; // sad face
2059 #if IS_ORIGIN_IS_FULL_SPEC_DEFINED
2061 if (NS_FAILED(NS_URIChainHasFlags(
2062 baseURI
, nsIProtocolHandler::ORIGIN_IS_FULL_SPEC
, &hasFlag
)) ||
2066 nsresult res
= baseURI
->GetSpec(spec
);
2067 if (NS_SUCCEEDED(res
))
2068 specHash
= mozilla::HashString(spec
);
2070 specHash
= static_cast<uint32_t>(res
);
2076 uint32_t hostHash
= 0;
2077 if (NS_SUCCEEDED(baseURI
->GetAsciiHost(host
)))
2078 hostHash
= mozilla::HashString(host
);
2080 return mozilla::AddToHash(schemeHash
, hostHash
, NS_GetRealPort(baseURI
));
2083 bool NS_SecurityCompareURIs(nsIURI
*aSourceURI
, nsIURI
*aTargetURI
,
2084 bool aStrictFileOriginPolicy
) {
2087 // Note that this is not an Equals() test on purpose -- for URIs that don't
2088 // support host/port, we want equality to basically be object identity, for
2089 // security purposes. Otherwise, for example, two javascript: URIs that
2090 // are otherwise unrelated could end up "same origin", which would be
2092 if (aSourceURI
&& aSourceURI
== aTargetURI
) {
2096 if (!aTargetURI
|| !aSourceURI
) {
2100 // If either URI is a nested URI, get the base URI
2101 nsCOMPtr
<nsIURI
> sourceBaseURI
= NS_GetInnermostURI(aSourceURI
);
2102 nsCOMPtr
<nsIURI
> targetBaseURI
= NS_GetInnermostURI(aTargetURI
);
2104 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
2105 // Check if either URI has a special origin.
2106 nsCOMPtr
<nsIURI
> origin
;
2107 nsCOMPtr
<nsIURIWithSpecialOrigin
> uriWithSpecialOrigin
=
2108 do_QueryInterface(sourceBaseURI
);
2109 if (uriWithSpecialOrigin
) {
2110 rv
= uriWithSpecialOrigin
->GetOrigin(getter_AddRefs(origin
));
2111 if (NS_WARN_IF(NS_FAILED(rv
))) {
2115 sourceBaseURI
= origin
;
2117 uriWithSpecialOrigin
= do_QueryInterface(targetBaseURI
);
2118 if (uriWithSpecialOrigin
) {
2119 rv
= uriWithSpecialOrigin
->GetOrigin(getter_AddRefs(origin
));
2120 if (NS_WARN_IF(NS_FAILED(rv
))) {
2124 targetBaseURI
= origin
;
2128 nsCOMPtr
<nsIPrincipal
> sourceBlobPrincipal
;
2129 if (BlobURLProtocolHandler::GetBlobURLPrincipal(
2130 sourceBaseURI
, getter_AddRefs(sourceBlobPrincipal
))) {
2131 nsCOMPtr
<nsIURI
> sourceBlobOwnerURI
;
2132 rv
= sourceBlobPrincipal
->GetURI(getter_AddRefs(sourceBlobOwnerURI
));
2133 if (NS_SUCCEEDED(rv
)) {
2134 sourceBaseURI
= sourceBlobOwnerURI
;
2138 nsCOMPtr
<nsIPrincipal
> targetBlobPrincipal
;
2139 if (BlobURLProtocolHandler::GetBlobURLPrincipal(
2140 targetBaseURI
, getter_AddRefs(targetBlobPrincipal
))) {
2141 nsCOMPtr
<nsIURI
> targetBlobOwnerURI
;
2142 rv
= targetBlobPrincipal
->GetURI(getter_AddRefs(targetBlobOwnerURI
));
2143 if (NS_SUCCEEDED(rv
)) {
2144 targetBaseURI
= targetBlobOwnerURI
;
2148 if (!sourceBaseURI
|| !targetBaseURI
) return false;
2151 nsAutoCString targetScheme
;
2152 bool sameScheme
= false;
2153 if (NS_FAILED(targetBaseURI
->GetScheme(targetScheme
)) ||
2154 NS_FAILED(sourceBaseURI
->SchemeIs(targetScheme
.get(), &sameScheme
)) ||
2156 // Not same-origin if schemes differ
2160 // For file scheme, reject unless the files are identical. See
2161 // NS_RelaxStrictFileOriginPolicy for enforcing file same-origin checking
2162 if (targetScheme
.EqualsLiteral("file")) {
2163 // in traditional unsafe behavior all files are the same origin
2164 if (!aStrictFileOriginPolicy
) return true;
2166 nsCOMPtr
<nsIFileURL
> sourceFileURL(do_QueryInterface(sourceBaseURI
));
2167 nsCOMPtr
<nsIFileURL
> targetFileURL(do_QueryInterface(targetBaseURI
));
2169 if (!sourceFileURL
|| !targetFileURL
) return false;
2171 nsCOMPtr
<nsIFile
> sourceFile
, targetFile
;
2173 sourceFileURL
->GetFile(getter_AddRefs(sourceFile
));
2174 targetFileURL
->GetFile(getter_AddRefs(targetFile
));
2176 if (!sourceFile
|| !targetFile
) return false;
2178 // Otherwise they had better match
2179 bool filesAreEqual
= false;
2180 rv
= sourceFile
->Equals(targetFile
, &filesAreEqual
);
2181 return NS_SUCCEEDED(rv
) && filesAreEqual
;
2184 #if IS_ORIGIN_IS_FULL_SPEC_DEFINED
2186 if (NS_FAILED(NS_URIChainHasFlags(
2187 targetBaseURI
, nsIProtocolHandler::ORIGIN_IS_FULL_SPEC
, &hasFlag
)) ||
2189 // URIs with this flag have the whole spec as a distinct trust
2190 // domain; use the whole spec for comparison
2191 nsAutoCString targetSpec
;
2192 nsAutoCString sourceSpec
;
2193 return (NS_SUCCEEDED(targetBaseURI
->GetSpec(targetSpec
)) &&
2194 NS_SUCCEEDED(sourceBaseURI
->GetSpec(sourceSpec
)) &&
2195 targetSpec
.Equals(sourceSpec
));
2200 nsAutoCString targetHost
;
2201 nsAutoCString sourceHost
;
2202 if (NS_FAILED(targetBaseURI
->GetAsciiHost(targetHost
)) ||
2203 NS_FAILED(sourceBaseURI
->GetAsciiHost(sourceHost
))) {
2207 nsCOMPtr
<nsIStandardURL
> targetURL(do_QueryInterface(targetBaseURI
));
2208 nsCOMPtr
<nsIStandardURL
> sourceURL(do_QueryInterface(sourceBaseURI
));
2209 if (!targetURL
|| !sourceURL
) {
2213 if (!targetHost
.Equals(sourceHost
, nsCaseInsensitiveCStringComparator())) {
2217 return NS_GetRealPort(targetBaseURI
) == NS_GetRealPort(sourceBaseURI
);
2220 bool NS_URIIsLocalFile(nsIURI
*aURI
) {
2221 nsCOMPtr
<nsINetUtil
> util
= do_GetNetUtil();
2225 NS_SUCCEEDED(util
->ProtocolHasFlags(
2226 aURI
, nsIProtocolHandler::URI_IS_LOCAL_FILE
, &isFile
)) &&
2230 bool NS_RelaxStrictFileOriginPolicy(nsIURI
*aTargetURI
, nsIURI
*aSourceURI
,
2231 bool aAllowDirectoryTarget
/* = false */) {
2232 if (!NS_URIIsLocalFile(aTargetURI
)) {
2233 // This is probably not what the caller intended
2234 MOZ_ASSERT_UNREACHABLE(
2235 "NS_RelaxStrictFileOriginPolicy called with non-file URI");
2239 if (!NS_URIIsLocalFile(aSourceURI
)) {
2240 // If the source is not also a file: uri then forget it
2241 // (don't want resource: principals in a file: doc)
2243 // note: we're not de-nesting jar: uris here, we want to
2244 // keep archive content bottled up in its own little island
2249 // pull out the internal files
2251 nsCOMPtr
<nsIFileURL
> targetFileURL(do_QueryInterface(aTargetURI
));
2252 nsCOMPtr
<nsIFileURL
> sourceFileURL(do_QueryInterface(aSourceURI
));
2253 nsCOMPtr
<nsIFile
> targetFile
;
2254 nsCOMPtr
<nsIFile
> sourceFile
;
2257 // Make sure targetFile is not a directory (bug 209234)
2258 // and that it exists w/out unescaping (bug 395343)
2259 if (!sourceFileURL
|| !targetFileURL
||
2260 NS_FAILED(targetFileURL
->GetFile(getter_AddRefs(targetFile
))) ||
2261 NS_FAILED(sourceFileURL
->GetFile(getter_AddRefs(sourceFile
))) ||
2262 !targetFile
|| !sourceFile
|| NS_FAILED(targetFile
->Normalize()) ||
2263 #ifndef MOZ_WIDGET_ANDROID
2264 NS_FAILED(sourceFile
->Normalize()) ||
2266 (!aAllowDirectoryTarget
&&
2267 (NS_FAILED(targetFile
->IsDirectory(&targetIsDir
)) || targetIsDir
))) {
2272 // If the file to be loaded is in a subdirectory of the source
2273 // (or same-dir if source is not a directory) then it will
2274 // inherit its source principal and be scriptable by that source.
2277 bool allowed
= false;
2278 nsresult rv
= sourceFile
->IsDirectory(&sourceIsDir
);
2279 if (NS_SUCCEEDED(rv
) && sourceIsDir
) {
2280 rv
= sourceFile
->Contains(targetFile
, &allowed
);
2282 nsCOMPtr
<nsIFile
> sourceParent
;
2283 rv
= sourceFile
->GetParent(getter_AddRefs(sourceParent
));
2284 if (NS_SUCCEEDED(rv
) && sourceParent
) {
2285 rv
= sourceParent
->Equals(targetFile
, &allowed
);
2286 if (NS_FAILED(rv
) || !allowed
) {
2287 rv
= sourceParent
->Contains(targetFile
, &allowed
);
2289 MOZ_ASSERT(aAllowDirectoryTarget
,
2290 "sourceFile->Parent == targetFile, but targetFile "
2291 "should've been disallowed if it is a directory");
2296 if (NS_SUCCEEDED(rv
) && allowed
) {
2303 bool NS_IsInternalSameURIRedirect(nsIChannel
*aOldChannel
,
2304 nsIChannel
*aNewChannel
, uint32_t aFlags
) {
2305 if (!(aFlags
& nsIChannelEventSink::REDIRECT_INTERNAL
)) {
2309 nsCOMPtr
<nsIURI
> oldURI
, newURI
;
2310 aOldChannel
->GetURI(getter_AddRefs(oldURI
));
2311 aNewChannel
->GetURI(getter_AddRefs(newURI
));
2313 if (!oldURI
|| !newURI
) {
2318 return NS_SUCCEEDED(oldURI
->Equals(newURI
, &res
)) && res
;
2321 bool NS_IsHSTSUpgradeRedirect(nsIChannel
*aOldChannel
, nsIChannel
*aNewChannel
,
2323 if (!(aFlags
& nsIChannelEventSink::REDIRECT_STS_UPGRADE
)) {
2327 nsCOMPtr
<nsIURI
> oldURI
, newURI
;
2328 aOldChannel
->GetURI(getter_AddRefs(oldURI
));
2329 aNewChannel
->GetURI(getter_AddRefs(newURI
));
2331 if (!oldURI
|| !newURI
) {
2336 if (NS_FAILED(oldURI
->SchemeIs("http", &isHttp
)) || !isHttp
) {
2340 nsCOMPtr
<nsIURI
> upgradedURI
;
2341 nsresult rv
= NS_GetSecureUpgradedURI(oldURI
, getter_AddRefs(upgradedURI
));
2342 if (NS_FAILED(rv
)) {
2347 return NS_SUCCEEDED(upgradedURI
->Equals(newURI
, &res
)) && res
;
2350 nsresult
NS_LinkRedirectChannels(uint32_t channelId
,
2351 nsIParentChannel
*parentChannel
,
2352 nsIChannel
**_result
) {
2353 nsCOMPtr
<nsIRedirectChannelRegistrar
> registrar
=
2354 RedirectChannelRegistrar::GetOrCreate();
2355 MOZ_ASSERT(registrar
);
2357 return registrar
->LinkChannels(channelId
, parentChannel
, _result
);
2360 nsresult
NS_MaybeOpenChannelUsingOpen2(nsIChannel
*aChannel
,
2361 nsIInputStream
**aStream
) {
2362 nsCOMPtr
<nsILoadInfo
> loadInfo
= aChannel
->GetLoadInfo();
2363 if (loadInfo
&& loadInfo
->GetSecurityMode() != 0) {
2364 return aChannel
->Open2(aStream
);
2366 return aChannel
->Open(aStream
);
2369 nsresult
NS_MaybeOpenChannelUsingAsyncOpen2(nsIChannel
*aChannel
,
2370 nsIStreamListener
*aListener
) {
2371 nsCOMPtr
<nsILoadInfo
> loadInfo
= aChannel
->GetLoadInfo();
2372 if (loadInfo
&& loadInfo
->GetSecurityMode() != 0) {
2373 return aChannel
->AsyncOpen2(aListener
);
2375 return aChannel
->AsyncOpen(aListener
, nullptr);
2378 /** Given the first (disposition) token from a Content-Disposition header,
2379 * tell whether it indicates the content is inline or attachment
2380 * @param aDispToken the disposition token from the content-disposition header
2382 uint32_t NS_GetContentDispositionFromToken(const nsAString
&aDispToken
) {
2383 // RFC 2183, section 2.8 says that an unknown disposition
2384 // value should be treated as "attachment"
2385 // If all of these tests eval to false, then we have a content-disposition of
2386 // "attachment" or unknown
2387 if (aDispToken
.IsEmpty() || aDispToken
.LowerCaseEqualsLiteral("inline") ||
2388 // Broken sites just send
2389 // Content-Disposition: filename="file"
2390 // without a disposition token... screen those out.
2391 StringHead(aDispToken
, 8).LowerCaseEqualsLiteral("filename"))
2392 return nsIChannel::DISPOSITION_INLINE
;
2394 return nsIChannel::DISPOSITION_ATTACHMENT
;
2397 uint32_t NS_GetContentDispositionFromHeader(const nsACString
&aHeader
,
2398 nsIChannel
*aChan
/* = nullptr */) {
2400 nsCOMPtr
<nsIMIMEHeaderParam
> mimehdrpar
=
2401 do_GetService(NS_MIMEHEADERPARAM_CONTRACTID
, &rv
);
2402 if (NS_FAILED(rv
)) return nsIChannel::DISPOSITION_ATTACHMENT
;
2404 nsAutoString dispToken
;
2405 rv
= mimehdrpar
->GetParameterHTTP(aHeader
, "", EmptyCString(), true, nullptr,
2408 if (NS_FAILED(rv
)) {
2409 // special case (see bug 272541): empty disposition type handled as "inline"
2410 if (rv
== NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY
)
2411 return nsIChannel::DISPOSITION_INLINE
;
2412 return nsIChannel::DISPOSITION_ATTACHMENT
;
2415 return NS_GetContentDispositionFromToken(dispToken
);
2418 nsresult
NS_GetFilenameFromDisposition(nsAString
&aFilename
,
2419 const nsACString
&aDisposition
,
2420 nsIURI
*aURI
/* = nullptr */) {
2421 aFilename
.Truncate();
2424 nsCOMPtr
<nsIMIMEHeaderParam
> mimehdrpar
=
2425 do_GetService(NS_MIMEHEADERPARAM_CONTRACTID
, &rv
);
2426 if (NS_FAILED(rv
)) return rv
;
2428 // Get the value of 'filename' parameter
2429 rv
= mimehdrpar
->GetParameterHTTP(aDisposition
, "filename", EmptyCString(),
2430 true, nullptr, aFilename
);
2432 if (NS_FAILED(rv
)) {
2433 aFilename
.Truncate();
2437 if (aFilename
.IsEmpty()) return NS_ERROR_NOT_AVAILABLE
;
2442 void net_EnsurePSMInit() {
2444 nsCOMPtr
<nsISupports
> psm
= do_GetService(PSM_COMPONENT_CONTRACTID
, &rv
);
2445 MOZ_ASSERT(NS_SUCCEEDED(rv
));
2447 nsCOMPtr
<nsISupports
> sss
= do_GetService(NS_SSSERVICE_CONTRACTID
);
2448 nsCOMPtr
<nsISupports
> cbl
= do_GetService(NS_CERTBLOCKLIST_CONTRACTID
);
2449 nsCOMPtr
<nsISupports
> cos
= do_GetService(NS_CERTOVERRIDE_CONTRACTID
);
2452 bool NS_IsAboutBlank(nsIURI
*uri
) {
2453 // GetSpec can be expensive for some URIs, so check the scheme first.
2454 bool isAbout
= false;
2455 if (NS_FAILED(uri
->SchemeIs("about", &isAbout
)) || !isAbout
) {
2459 return uri
->GetSpecOrDefault().EqualsLiteral("about:blank");
2462 nsresult
NS_GenerateHostPort(const nsCString
&host
, int32_t port
,
2463 nsACString
&hostLine
) {
2464 if (strchr(host
.get(), ':')) {
2465 // host is an IPv6 address literal and must be encapsulated in []'s
2466 hostLine
.Assign('[');
2467 // scope id is not needed for Host header.
2468 int scopeIdPos
= host
.FindChar('%');
2469 if (scopeIdPos
== -1)
2470 hostLine
.Append(host
);
2471 else if (scopeIdPos
> 0)
2472 hostLine
.Append(Substring(host
, 0, scopeIdPos
));
2474 return NS_ERROR_MALFORMED_URI
;
2475 hostLine
.Append(']');
2477 hostLine
.Assign(host
);
2479 hostLine
.Append(':');
2480 hostLine
.AppendInt(port
);
2485 void NS_SniffContent(const char *aSnifferType
, nsIRequest
*aRequest
,
2486 const uint8_t *aData
, uint32_t aLength
,
2487 nsACString
&aSniffedType
) {
2488 typedef nsCategoryCache
<nsIContentSniffer
> ContentSnifferCache
;
2489 extern ContentSnifferCache
*gNetSniffers
;
2490 extern ContentSnifferCache
*gDataSniffers
;
2491 ContentSnifferCache
*cache
= nullptr;
2492 if (!strcmp(aSnifferType
, NS_CONTENT_SNIFFER_CATEGORY
)) {
2493 if (!gNetSniffers
) {
2494 gNetSniffers
= new ContentSnifferCache(NS_CONTENT_SNIFFER_CATEGORY
);
2496 cache
= gNetSniffers
;
2497 } else if (!strcmp(aSnifferType
, NS_DATA_SNIFFER_CATEGORY
)) {
2498 if (!gDataSniffers
) {
2499 gDataSniffers
= new ContentSnifferCache(NS_DATA_SNIFFER_CATEGORY
);
2501 cache
= gDataSniffers
;
2503 // Invalid content sniffer type was requested
2508 nsCOMArray
<nsIContentSniffer
> sniffers
;
2509 cache
->GetEntries(sniffers
);
2510 for (int32_t i
= 0; i
< sniffers
.Count(); ++i
) {
2511 nsresult rv
= sniffers
[i
]->GetMIMETypeFromContent(aRequest
, aData
, aLength
,
2513 if (NS_SUCCEEDED(rv
) && !aSniffedType
.IsEmpty()) {
2518 aSniffedType
.Truncate();
2521 bool NS_IsSrcdocChannel(nsIChannel
*aChannel
) {
2523 nsCOMPtr
<nsIInputStreamChannel
> isr
= do_QueryInterface(aChannel
);
2525 isr
->GetIsSrcdocChannel(&isSrcdoc
);
2528 nsCOMPtr
<nsIViewSourceChannel
> vsc
= do_QueryInterface(aChannel
);
2530 nsresult rv
= vsc
->GetIsSrcdocChannel(&isSrcdoc
);
2531 if (NS_SUCCEEDED(rv
)) {
2538 nsresult
NS_ShouldSecureUpgrade(nsIURI
*aURI
, nsILoadInfo
*aLoadInfo
,
2539 nsIPrincipal
*aChannelResultPrincipal
,
2540 bool aPrivateBrowsing
, bool aAllowSTS
,
2541 const OriginAttributes
&aOriginAttributes
,
2542 bool &aShouldUpgrade
) {
2543 // Even if we're in private browsing mode, we still enforce existing STS
2544 // data (it is read-only).
2545 // if the connection is not using SSL and either the exact host matches or
2546 // a superdomain wants to force HTTPS, do it.
2547 bool isHttps
= false;
2548 nsresult rv
= aURI
->SchemeIs("https", &isHttps
);
2549 NS_ENSURE_SUCCESS(rv
, rv
);
2552 !nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI
)) {
2554 // If any of the documents up the chain to the root document makes use of
2555 // the CSP directive 'upgrade-insecure-requests', then it's time to
2556 // fulfill the promise to CSP and mixed content blocking to upgrade the
2557 // channel from http to https.
2558 if (aLoadInfo
->GetUpgradeInsecureRequests() ||
2559 aLoadInfo
->GetBrowserUpgradeInsecureRequests()) {
2560 // let's log a message to the console that we are upgrading a request
2561 nsAutoCString scheme
;
2562 aURI
->GetScheme(scheme
);
2563 // append the additional 's' for security to the scheme :-)
2564 scheme
.AppendLiteral("s");
2565 NS_ConvertUTF8toUTF16
reportSpec(aURI
->GetSpecOrDefault());
2566 NS_ConvertUTF8toUTF16
reportScheme(scheme
);
2568 if (aLoadInfo
->GetUpgradeInsecureRequests()) {
2569 const char16_t
*params
[] = {reportSpec
.get(), reportScheme
.get()};
2570 uint32_t innerWindowId
= aLoadInfo
->GetInnerWindowID();
2571 CSP_LogLocalizedStr(
2572 "upgradeInsecureRequest", params
, ArrayLength(params
),
2573 EmptyString(), // aSourceFile
2574 EmptyString(), // aScriptSample
2577 nsIScriptError::warningFlag
,
2578 NS_LITERAL_CSTRING("upgradeInsecureRequest"), innerWindowId
,
2579 !!aLoadInfo
->GetOriginAttributes().mPrivateBrowsingId
);
2580 Telemetry::AccumulateCategorical(
2581 Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::CSP
);
2583 RefPtr
<dom::Document
> doc
;
2584 nsINode
*node
= aLoadInfo
->LoadingNode();
2586 doc
= node
->OwnerDoc();
2589 nsAutoString brandName
;
2590 nsresult rv
= nsContentUtils::GetLocalizedString(
2591 nsContentUtils::eBRAND_PROPERTIES
, "brandShortName", brandName
);
2592 if (NS_SUCCEEDED(rv
)) {
2593 const char16_t
*params
[] = {brandName
.get(), reportSpec
.get(),
2594 reportScheme
.get()};
2595 nsContentUtils::ReportToConsole(
2596 nsIScriptError::warningFlag
,
2597 NS_LITERAL_CSTRING("DATA_URI_BLOCKED"), doc
,
2598 nsContentUtils::eSECURITY_PROPERTIES
,
2599 "BrowserUpgradeInsecureDisplayRequest", params
,
2600 ArrayLength(params
));
2602 Telemetry::AccumulateCategorical(
2603 Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::BrowserDisplay
);
2606 aShouldUpgrade
= true;
2611 // enforce Strict-Transport-Security
2612 nsISiteSecurityService
*sss
= gHttpHandler
->GetSSService();
2613 NS_ENSURE_TRUE(sss
, NS_ERROR_OUT_OF_MEMORY
);
2615 bool isStsHost
= false;
2616 uint32_t hstsSource
= 0;
2618 aPrivateBrowsing
? nsISocketProvider::NO_PERMANENT_STORAGE
: 0;
2619 rv
= sss
->IsSecureURI(nsISiteSecurityService::HEADER_HSTS
, aURI
, flags
,
2620 aOriginAttributes
, nullptr, &hstsSource
, &isStsHost
);
2622 // if the SSS check fails, it's likely because this load is on a
2623 // malformed URI or something else in the setup is wrong, so any error
2624 // should be reported.
2625 NS_ENSURE_SUCCESS(rv
, rv
);
2628 LOG(("nsHttpChannel::Connect() STS permissions found\n"));
2630 Telemetry::AccumulateCategorical(
2631 Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::STS
);
2632 aShouldUpgrade
= true;
2633 switch (hstsSource
) {
2634 case nsISiteSecurityService::SOURCE_PRELOAD_LIST
:
2635 Telemetry::Accumulate(Telemetry::HSTS_UPGRADE_SOURCE
, 0);
2637 case nsISiteSecurityService::SOURCE_ORGANIC_REQUEST
:
2638 Telemetry::Accumulate(Telemetry::HSTS_UPGRADE_SOURCE
, 1);
2640 case nsISiteSecurityService::SOURCE_UNKNOWN
:
2642 // record this as an organic request
2643 Telemetry::Accumulate(Telemetry::HSTS_UPGRADE_SOURCE
, 1);
2648 Telemetry::AccumulateCategorical(
2649 Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::PrefBlockedSTS
);
2651 Telemetry::AccumulateCategorical(
2652 Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::NoReasonToUpgrade
);
2655 Telemetry::AccumulateCategorical(
2656 Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::AlreadyHTTPS
);
2658 aShouldUpgrade
= false;
2662 nsresult
NS_GetSecureUpgradedURI(nsIURI
*aURI
, nsIURI
**aUpgradedURI
) {
2663 NS_MutateURI
mutator(aURI
);
2665 NS_LITERAL_CSTRING("https")); // Change the scheme to HTTPS:
2667 // Change the default port to 443:
2668 nsCOMPtr
<nsIStandardURL
> stdURL
= do_QueryInterface(aURI
);
2671 NS_MutatorMethod(&nsIStandardURLMutator::SetDefaultPort
, 443, nullptr));
2673 // If we don't have a nsStandardURL, fall back to using GetPort/SetPort.
2674 // XXXdholbert Is this function even called with a non-nsStandardURL arg,
2676 NS_WARNING("Calling NS_GetSecureUpgradedURI for non nsStandardURL");
2677 int32_t oldPort
= -1;
2678 nsresult rv
= aURI
->GetPort(&oldPort
);
2679 if (NS_FAILED(rv
)) return rv
;
2681 // Keep any nonstandard ports so only the scheme is changed.
2683 // http://foo.com:80 -> https://foo.com:443
2684 // http://foo.com:81 -> https://foo.com:81
2686 if (oldPort
== 80 || oldPort
== -1) {
2687 mutator
.SetPort(-1);
2689 mutator
.SetPort(oldPort
);
2693 return mutator
.Finalize(aUpgradedURI
);
2696 nsresult
NS_CompareLoadInfoAndLoadContext(nsIChannel
*aChannel
) {
2697 nsCOMPtr
<nsILoadInfo
> loadInfo
;
2698 aChannel
->GetLoadInfo(getter_AddRefs(loadInfo
));
2700 nsCOMPtr
<nsILoadContext
> loadContext
;
2701 NS_QueryNotificationCallbacks(aChannel
, loadContext
);
2702 if (!loadInfo
|| !loadContext
) {
2706 // We try to skip about:newtab.
2707 // about:newtab will use SystemPrincipal to download thumbnails through
2708 // https:// and blob URLs.
2709 bool isAboutPage
= false;
2710 nsINode
*node
= loadInfo
->LoadingNode();
2712 nsIURI
*uri
= node
->OwnerDoc()->GetDocumentURI();
2713 nsresult rv
= uri
->SchemeIs("about", &isAboutPage
);
2714 NS_ENSURE_SUCCESS(rv
, rv
);
2721 // We skip the favicon loading here. The favicon loading might be
2722 // triggered by the XUL image. For that case, the loadContext will have
2723 // default originAttributes since the XUL image uses SystemPrincipal, but
2724 // the loadInfo will use originAttributes from the content. Thus, the
2725 // originAttributes between loadInfo and loadContext will be different.
2726 // That's why we have to skip the comparison for the favicon loading.
2727 if (nsContentUtils::IsSystemPrincipal(loadInfo
->LoadingPrincipal()) &&
2728 loadInfo
->InternalContentPolicyType() ==
2729 nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON
) {
2733 bool loadContextIsInBE
= false;
2735 loadContext
->GetIsInIsolatedMozBrowserElement(&loadContextIsInBE
);
2736 if (NS_FAILED(rv
)) {
2737 return NS_ERROR_UNEXPECTED
;
2740 OriginAttributes originAttrsLoadInfo
= loadInfo
->GetOriginAttributes();
2741 OriginAttributes originAttrsLoadContext
;
2742 loadContext
->GetOriginAttributes(originAttrsLoadContext
);
2745 ("NS_CompareLoadInfoAndLoadContext - loadInfo: %d, %d, %d; "
2746 "loadContext: %d %d, %d. [channel=%p]",
2747 originAttrsLoadInfo
.mInIsolatedMozBrowser
,
2748 originAttrsLoadInfo
.mUserContextId
,
2749 originAttrsLoadInfo
.mPrivateBrowsingId
, loadContextIsInBE
,
2750 originAttrsLoadContext
.mUserContextId
,
2751 originAttrsLoadContext
.mPrivateBrowsingId
, aChannel
));
2753 MOZ_ASSERT(originAttrsLoadInfo
.mInIsolatedMozBrowser
== loadContextIsInBE
,
2754 "The value of InIsolatedMozBrowser in the loadContext and in "
2755 "the loadInfo are not the same!");
2757 MOZ_ASSERT(originAttrsLoadInfo
.mUserContextId
==
2758 originAttrsLoadContext
.mUserContextId
,
2759 "The value of mUserContextId in the loadContext and in the "
2760 "loadInfo are not the same!");
2762 MOZ_ASSERT(originAttrsLoadInfo
.mPrivateBrowsingId
==
2763 originAttrsLoadContext
.mPrivateBrowsingId
,
2764 "The value of mPrivateBrowsingId in the loadContext and in the "
2765 "loadInfo are not the same!");
2770 uint32_t NS_GetDefaultReferrerPolicy(bool privateBrowsing
) {
2771 static bool preferencesInitialized
= false;
2773 if (!preferencesInitialized
) {
2774 mozilla::Preferences::AddUintVarCache(
2775 &sDefaultRp
, "network.http.referer.defaultPolicy", DEFAULT_RP
);
2776 mozilla::Preferences::AddUintVarCache(
2777 &defaultPrivateRp
, "network.http.referer.defaultPolicy.pbmode",
2778 DEFAULT_PRIVATE_RP
);
2779 preferencesInitialized
= true;
2782 uint32_t defaultToUse
;
2783 if (privateBrowsing
) {
2784 defaultToUse
= defaultPrivateRp
;
2786 defaultToUse
= sDefaultRp
;
2789 switch (defaultToUse
) {
2791 return nsIHttpChannel::REFERRER_POLICY_NO_REFERRER
;
2793 return nsIHttpChannel::REFERRER_POLICY_SAME_ORIGIN
;
2795 return nsIHttpChannel::REFERRER_POLICY_STRICT_ORIGIN_WHEN_XORIGIN
;
2798 return nsIHttpChannel::REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE
;
2801 bool NS_IsOffline() {
2802 bool offline
= true;
2803 bool connectivity
= true;
2804 nsCOMPtr
<nsIIOService
> ios
= do_GetIOService();
2806 ios
->GetOffline(&offline
);
2807 ios
->GetConnectivity(&connectivity
);
2809 return offline
|| !connectivity
;
2815 bool InScriptableRange(int64_t val
) {
2816 return (val
<= kJS_MAX_SAFE_INTEGER
) && (val
>= kJS_MIN_SAFE_INTEGER
);
2819 bool InScriptableRange(uint64_t val
) { return val
<= kJS_MAX_SAFE_UINTEGER
; }
2821 nsresult
GetParameterHTTP(const nsACString
&aHeaderVal
, const char *aParamName
,
2822 nsAString
&aResult
) {
2823 return nsMIMEHeaderParamImpl::GetParameterHTTP(aHeaderVal
, aParamName
,
2827 bool SchemeIsHTTP(nsIURI
*aURI
) {
2829 return aURI
->SchemeIs("http");
2832 bool SchemeIsHTTPS(nsIURI
*aURI
) {
2834 return aURI
->SchemeIs("https");
2837 bool SchemeIsJavascript(nsIURI
*aURI
) {
2839 return aURI
->SchemeIs("javascript");
2842 bool SchemeIsChrome(nsIURI
*aURI
) {
2844 return aURI
->SchemeIs("chrome");
2847 bool SchemeIsAbout(nsIURI
*aURI
) {
2849 return aURI
->SchemeIs("about");
2852 bool SchemeIsBlob(nsIURI
*aURI
) {
2854 return aURI
->SchemeIs("blob");
2857 bool SchemeIsFile(nsIURI
*aURI
) {
2859 return aURI
->SchemeIs("file");
2862 bool SchemeIsData(nsIURI
*aURI
) {
2864 return aURI
->SchemeIs("data");
2867 bool SchemeIsWYCIWYG(nsIURI
*aURI
) {
2869 return aURI
->SchemeIs("wyciwyg");
2872 bool SchemeIsViewSource(nsIURI
*aURI
) {
2874 return aURI
->SchemeIs("view-source");
2877 bool SchemeIsResource(nsIURI
*aURI
) {
2879 return aURI
->SchemeIs("resource");
2882 bool SchemeIsFTP(nsIURI
*aURI
) {
2884 return aURI
->SchemeIs("ftp");
2888 } // namespace mozilla