Source code

Revision control

Other Tools

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/. */
6
7
// HttpLog.h should generally be included first
8
#include "HttpLog.h"
9
10
#include "nsNetUtil.h"
11
12
#include "mozilla/AntiTrackingCommon.h"
13
#include "mozilla/Atomics.h"
14
#include "mozilla/Encoding.h"
15
#include "mozilla/LoadContext.h"
16
#include "mozilla/LoadInfo.h"
17
#include "mozilla/BasePrincipal.h"
18
#include "mozilla/Monitor.h"
19
#include "mozilla/StaticPrefs_privacy.h"
20
#include "mozilla/StoragePrincipalHelper.h"
21
#include "mozilla/TaskQueue.h"
22
#include "mozilla/Telemetry.h"
23
#include "nsCategoryCache.h"
24
#include "nsContentUtils.h"
25
#include "nsFileStreams.h"
26
#include "nsHashKeys.h"
27
#include "nsHttp.h"
28
#include "nsMimeTypes.h"
29
#include "nsIAsyncStreamCopier.h"
30
#include "nsIAuthPrompt.h"
31
#include "nsIAuthPrompt2.h"
32
#include "nsIAuthPromptAdapterFactory.h"
33
#include "nsIBufferedStreams.h"
34
#include "nsBufferedStreams.h"
35
#include "nsIChannelEventSink.h"
36
#include "nsIContentSniffer.h"
37
#include "mozilla/dom/Document.h"
38
#include "nsICookieService.h"
39
#include "nsIDownloader.h"
40
#include "nsIFileProtocolHandler.h"
41
#include "nsIFileStreams.h"
42
#include "nsIFileURL.h"
43
#include "nsIIDNService.h"
44
#include "nsIInputStreamChannel.h"
45
#include "nsIInputStreamPump.h"
46
#include "nsIInterfaceRequestorUtils.h"
47
#include "nsILoadContext.h"
48
#include "nsIMIMEHeaderParam.h"
49
#include "nsIMutable.h"
50
#include "nsINode.h"
51
#include "nsIObjectLoadingContent.h"
52
#include "nsIOfflineCacheUpdate.h"
53
#include "nsPersistentProperties.h"
54
#include "nsIPrivateBrowsingChannel.h"
55
#include "nsIPropertyBag2.h"
56
#include "nsIProtocolProxyService.h"
57
#include "mozilla/net/RedirectChannelRegistrar.h"
58
#include "nsRequestObserverProxy.h"
59
#include "nsIScriptSecurityManager.h"
60
#include "nsISensitiveInfoHiddenURI.h"
61
#include "nsISimpleStreamListener.h"
62
#include "nsISocketProvider.h"
63
#include "nsISocketProviderService.h"
64
#include "nsIStandardURL.h"
65
#include "nsIStreamLoader.h"
66
#include "nsIIncrementalStreamLoader.h"
67
#include "nsIStreamTransportService.h"
68
#include "nsStringStream.h"
69
#include "nsSyncStreamListener.h"
70
#include "nsITransport.h"
71
#include "nsIURIWithSpecialOrigin.h"
72
#include "nsIURLParser.h"
73
#include "nsIUUIDGenerator.h"
74
#include "nsIViewSourceChannel.h"
75
#include "nsInterfaceRequestorAgg.h"
76
#include "plstr.h"
77
#include "nsINestedURI.h"
78
#include "mozilla/dom/nsCSPUtils.h"
79
#include "mozilla/dom/nsMixedContentBlocker.h"
80
#include "mozilla/dom/BlobURLProtocolHandler.h"
81
#include "mozilla/net/HttpBaseChannel.h"
82
#include "nsIScriptError.h"
83
#include "nsISiteSecurityService.h"
84
#include "nsHttpHandler.h"
85
#include "nsNSSComponent.h"
86
#include "nsIRedirectHistoryEntry.h"
87
#ifdef MOZ_NEW_CERT_STORAGE
88
# include "nsICertStorage.h"
89
#else
90
# include "nsICertBlocklist.h"
91
#endif
92
#include "nsICertOverrideService.h"
93
#include "nsQueryObject.h"
94
#include "mozIThirdPartyUtil.h"
95
#include "../mime/nsMIMEHeaderParamImpl.h"
96
#include "nsStandardURL.h"
97
#include "nsChromeProtocolHandler.h"
98
#include "nsJSProtocolHandler.h"
99
#include "nsDataHandler.h"
100
#include "mozilla/dom/BlobURLProtocolHandler.h"
101
#include "nsStreamUtils.h"
102
#include "nsSocketTransportService2.h"
103
#include "nsViewSourceHandler.h"
104
#include "nsJARURI.h"
105
#include "nsIconURI.h"
106
#include "nsAboutProtocolHandler.h"
107
#include "nsResProtocolHandler.h"
108
#include "mozilla/net/ExtensionProtocolHandler.h"
109
#include <limits>
110
111
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
112
# include "nsNewMailnewsURI.h"
113
#endif
114
115
using namespace mozilla;
116
using namespace mozilla::net;
117
using mozilla::dom::BlobURLProtocolHandler;
118
using mozilla::dom::ClientInfo;
119
using mozilla::dom::PerformanceStorage;
120
using mozilla::dom::ServiceWorkerDescriptor;
121
122
#define MAX_RECURSION_COUNT 50
123
124
already_AddRefed<nsIIOService> do_GetIOService(nsresult* error /* = 0 */) {
125
nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
126
if (error) *error = io ? NS_OK : NS_ERROR_FAILURE;
127
return io.forget();
128
}
129
130
nsresult NS_NewLocalFileInputStream(nsIInputStream** result, nsIFile* file,
131
int32_t ioFlags /* = -1 */,
132
int32_t perm /* = -1 */,
133
int32_t behaviorFlags /* = 0 */) {
134
nsresult rv;
135
nsCOMPtr<nsIFileInputStream> in =
136
do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv);
137
if (NS_SUCCEEDED(rv)) {
138
rv = in->Init(file, ioFlags, perm, behaviorFlags);
139
if (NS_SUCCEEDED(rv)) in.forget(result);
140
}
141
return rv;
142
}
143
144
nsresult NS_NewLocalFileOutputStream(nsIOutputStream** result, nsIFile* file,
145
int32_t ioFlags /* = -1 */,
146
int32_t perm /* = -1 */,
147
int32_t behaviorFlags /* = 0 */) {
148
nsresult rv;
149
nsCOMPtr<nsIFileOutputStream> out =
150
do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
151
if (NS_SUCCEEDED(rv)) {
152
rv = out->Init(file, ioFlags, perm, behaviorFlags);
153
if (NS_SUCCEEDED(rv)) out.forget(result);
154
}
155
return rv;
156
}
157
158
nsresult net_EnsureIOService(nsIIOService** ios, nsCOMPtr<nsIIOService>& grip) {
159
nsresult rv = NS_OK;
160
if (!*ios) {
161
grip = do_GetIOService(&rv);
162
*ios = grip;
163
}
164
return rv;
165
}
166
167
nsresult NS_NewFileURI(
168
nsIURI** result, nsIFile* spec,
169
nsIIOService*
170
ioService /* = nullptr */) // pass in nsIIOService to optimize callers
171
{
172
nsresult rv;
173
nsCOMPtr<nsIIOService> grip;
174
rv = net_EnsureIOService(&ioService, grip);
175
if (ioService) rv = ioService->NewFileURI(spec, result);
176
return rv;
177
}
178
179
nsresult NS_GetURIWithNewRef(nsIURI* aInput, const nsACString& aRef,
180
nsIURI** aOutput) {
181
if (NS_WARN_IF(!aInput || !aOutput)) {
182
return NS_ERROR_INVALID_ARG;
183
}
184
185
bool hasRef;
186
nsresult rv = aInput->GetHasRef(&hasRef);
187
188
nsAutoCString ref;
189
if (NS_SUCCEEDED(rv)) {
190
rv = aInput->GetRef(ref);
191
}
192
193
// If the ref is already equal to the new ref, we do not need to do anything.
194
// Also, if the GetRef failed (it could return NS_ERROR_NOT_IMPLEMENTED)
195
// we can assume SetRef would fail as well, so returning the original
196
// URI is OK.
197
if (NS_FAILED(rv) || (!hasRef && aRef.IsEmpty()) ||
198
(!aRef.IsEmpty() && aRef == ref)) {
199
nsCOMPtr<nsIURI> uri = aInput;
200
uri.forget(aOutput);
201
return NS_OK;
202
}
203
204
return NS_MutateURI(aInput).SetRef(aRef).Finalize(aOutput);
205
}
206
207
nsresult NS_GetURIWithoutRef(nsIURI* aInput, nsIURI** aOutput) {
208
return NS_GetURIWithNewRef(aInput, EmptyCString(), aOutput);
209
}
210
211
nsresult NS_NewChannelInternal(
212
nsIChannel** outChannel, nsIURI* aUri, nsILoadInfo* aLoadInfo,
213
PerformanceStorage* aPerformanceStorage /* = nullptr */,
214
nsILoadGroup* aLoadGroup /* = nullptr */,
215
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
216
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
217
nsIIOService* aIoService /* = nullptr */) {
218
// NS_NewChannelInternal is mostly called for channel redirects. We should
219
// allow the creation of a channel even if the original channel did not have a
220
// loadinfo attached.
221
NS_ENSURE_ARG_POINTER(outChannel);
222
223
nsCOMPtr<nsIIOService> grip;
224
nsresult rv = net_EnsureIOService(&aIoService, grip);
225
NS_ENSURE_SUCCESS(rv, rv);
226
227
nsCOMPtr<nsIChannel> channel;
228
rv = aIoService->NewChannelFromURIWithLoadInfo(aUri, aLoadInfo,
229
getter_AddRefs(channel));
230
NS_ENSURE_SUCCESS(rv, rv);
231
232
if (aLoadGroup) {
233
rv = channel->SetLoadGroup(aLoadGroup);
234
NS_ENSURE_SUCCESS(rv, rv);
235
}
236
237
if (aCallbacks) {
238
rv = channel->SetNotificationCallbacks(aCallbacks);
239
NS_ENSURE_SUCCESS(rv, rv);
240
}
241
242
#ifdef DEBUG
243
nsLoadFlags channelLoadFlags = 0;
244
channel->GetLoadFlags(&channelLoadFlags);
245
// Will be removed when we remove LOAD_REPLACE altogether
246
// This check is trying to catch protocol handlers that still
247
// try to set the LOAD_REPLACE flag.
248
MOZ_DIAGNOSTIC_ASSERT(!(channelLoadFlags & nsIChannel::LOAD_REPLACE));
249
#endif
250
251
if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
252
rv = channel->SetLoadFlags(aLoadFlags);
253
NS_ENSURE_SUCCESS(rv, rv);
254
}
255
256
if (aPerformanceStorage) {
257
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
258
loadInfo->SetPerformanceStorage(aPerformanceStorage);
259
}
260
261
channel.forget(outChannel);
262
return NS_OK;
263
}
264
265
namespace {
266
267
void AssertLoadingPrincipalAndClientInfoMatch(
268
nsIPrincipal* aLoadingPrincipal, const ClientInfo& aLoadingClientInfo,
269
nsContentPolicyType aType) {
270
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
271
// Verify that the provided loading ClientInfo matches the loading
272
// principal. Unfortunately we can't just use nsIPrincipal::Equals() here
273
// because of some corner cases:
274
//
275
// 1. Worker debugger scripts want to use a system loading principal for
276
// worker scripts with a content principal. We exempt these from this
277
// check.
278
// 2. Null principals currently require exact object identity for
279
// nsIPrincipal::Equals() to return true. This doesn't work here because
280
// ClientInfo::GetPrincipal() uses PrincipalInfoToPrincipal() to allocate
281
// a new object. To work around this we compare the principal origin
282
// string itself. If bug 1431771 is fixed then we could switch to
283
// Equals().
284
285
// Allow worker debugger to load with a system principal.
286
if (aLoadingPrincipal->IsSystemPrincipal() &&
287
(aType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
288
aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER ||
289
aType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER ||
290
aType == nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS)) {
291
return;
292
}
293
294
// Perform a fast comparison for most principal checks.
295
nsCOMPtr<nsIPrincipal> clientPrincipal(aLoadingClientInfo.GetPrincipal());
296
if (aLoadingPrincipal->Equals(clientPrincipal)) {
297
return;
298
}
299
300
// Fall back to a slower origin equality test to support null principals.
301
nsAutoCString loadingOrigin;
302
MOZ_ALWAYS_SUCCEEDS(aLoadingPrincipal->GetOrigin(loadingOrigin));
303
304
nsAutoCString clientOrigin;
305
MOZ_ALWAYS_SUCCEEDS(clientPrincipal->GetOrigin(clientOrigin));
306
307
MOZ_DIAGNOSTIC_ASSERT(loadingOrigin == clientOrigin);
308
#endif
309
}
310
311
} // namespace
312
313
nsresult NS_NewChannel(nsIChannel** outChannel, nsIURI* aUri,
314
nsIPrincipal* aLoadingPrincipal,
315
nsSecurityFlags aSecurityFlags,
316
nsContentPolicyType aContentPolicyType,
317
nsICookieSettings* aCookieSettings /* = nullptr */,
318
PerformanceStorage* aPerformanceStorage /* = nullptr */,
319
nsILoadGroup* aLoadGroup /* = nullptr */,
320
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
321
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
322
nsIIOService* aIoService /* = nullptr */) {
323
return NS_NewChannelInternal(
324
outChannel, aUri,
325
nullptr, // aLoadingNode,
326
aLoadingPrincipal,
327
nullptr, // aTriggeringPrincipal
328
Maybe<ClientInfo>(), Maybe<ServiceWorkerDescriptor>(), aSecurityFlags,
329
aContentPolicyType, aCookieSettings, aPerformanceStorage, aLoadGroup,
330
aCallbacks, aLoadFlags, aIoService);
331
}
332
333
nsresult NS_NewChannel(nsIChannel** outChannel, nsIURI* aUri,
334
nsIPrincipal* aLoadingPrincipal,
335
const ClientInfo& aLoadingClientInfo,
336
const Maybe<ServiceWorkerDescriptor>& aController,
337
nsSecurityFlags aSecurityFlags,
338
nsContentPolicyType aContentPolicyType,
339
nsICookieSettings* aCookieSettings /* = nullptr */,
340
PerformanceStorage* aPerformanceStorage /* = nullptr */,
341
nsILoadGroup* aLoadGroup /* = nullptr */,
342
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
343
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
344
nsIIOService* aIoService /* = nullptr */) {
345
AssertLoadingPrincipalAndClientInfoMatch(
346
aLoadingPrincipal, aLoadingClientInfo, aContentPolicyType);
347
348
Maybe<ClientInfo> loadingClientInfo;
349
loadingClientInfo.emplace(aLoadingClientInfo);
350
351
return NS_NewChannelInternal(outChannel, aUri,
352
nullptr, // aLoadingNode,
353
aLoadingPrincipal,
354
nullptr, // aTriggeringPrincipal
355
loadingClientInfo, aController, aSecurityFlags,
356
aContentPolicyType, aCookieSettings,
357
aPerformanceStorage, aLoadGroup, aCallbacks,
358
aLoadFlags, aIoService);
359
}
360
361
nsresult NS_NewChannelInternal(
362
nsIChannel** outChannel, nsIURI* aUri, nsINode* aLoadingNode,
363
nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
364
const Maybe<ClientInfo>& aLoadingClientInfo,
365
const Maybe<ServiceWorkerDescriptor>& aController,
366
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
367
nsICookieSettings* aCookieSettings /* = nullptr */,
368
PerformanceStorage* aPerformanceStorage /* = nullptr */,
369
nsILoadGroup* aLoadGroup /* = nullptr */,
370
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
371
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
372
nsIIOService* aIoService /* = nullptr */) {
373
NS_ENSURE_ARG_POINTER(outChannel);
374
375
nsCOMPtr<nsIIOService> grip;
376
nsresult rv = net_EnsureIOService(&aIoService, grip);
377
NS_ENSURE_SUCCESS(rv, rv);
378
379
nsCOMPtr<nsIChannel> channel;
380
rv = aIoService->NewChannelFromURIWithClientAndController(
381
aUri, aLoadingNode, aLoadingPrincipal, aTriggeringPrincipal,
382
aLoadingClientInfo, aController, aSecurityFlags, aContentPolicyType,
383
getter_AddRefs(channel));
384
if (NS_FAILED(rv)) {
385
return rv;
386
}
387
388
if (aLoadGroup) {
389
rv = channel->SetLoadGroup(aLoadGroup);
390
NS_ENSURE_SUCCESS(rv, rv);
391
}
392
393
if (aCallbacks) {
394
rv = channel->SetNotificationCallbacks(aCallbacks);
395
NS_ENSURE_SUCCESS(rv, rv);
396
}
397
398
#ifdef DEBUG
399
nsLoadFlags channelLoadFlags = 0;
400
channel->GetLoadFlags(&channelLoadFlags);
401
// Will be removed when we remove LOAD_REPLACE altogether
402
// This check is trying to catch protocol handlers that still
403
// try to set the LOAD_REPLACE flag.
404
MOZ_DIAGNOSTIC_ASSERT(!(channelLoadFlags & nsIChannel::LOAD_REPLACE));
405
#endif
406
407
if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
408
rv = channel->SetLoadFlags(aLoadFlags);
409
NS_ENSURE_SUCCESS(rv, rv);
410
}
411
412
if (aPerformanceStorage || aCookieSettings) {
413
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
414
415
if (aPerformanceStorage) {
416
loadInfo->SetPerformanceStorage(aPerformanceStorage);
417
}
418
419
if (aCookieSettings) {
420
loadInfo->SetCookieSettings(aCookieSettings);
421
}
422
}
423
424
channel.forget(outChannel);
425
return NS_OK;
426
}
427
428
nsresult /*NS_NewChannelWithNodeAndTriggeringPrincipal */
429
NS_NewChannelWithTriggeringPrincipal(
430
nsIChannel** outChannel, nsIURI* aUri, nsINode* aLoadingNode,
431
nsIPrincipal* aTriggeringPrincipal, nsSecurityFlags aSecurityFlags,
432
nsContentPolicyType aContentPolicyType,
433
PerformanceStorage* aPerformanceStorage /* = nullptr */,
434
nsILoadGroup* aLoadGroup /* = nullptr */,
435
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
436
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
437
nsIIOService* aIoService /* = nullptr */) {
438
MOZ_ASSERT(aLoadingNode);
439
NS_ASSERTION(aTriggeringPrincipal,
440
"Can not create channel without a triggering Principal!");
441
return NS_NewChannelInternal(
442
outChannel, aUri, aLoadingNode, aLoadingNode->NodePrincipal(),
443
aTriggeringPrincipal, Maybe<ClientInfo>(),
444
Maybe<ServiceWorkerDescriptor>(), aSecurityFlags, aContentPolicyType,
445
aLoadingNode->OwnerDoc()->CookieSettings(), aPerformanceStorage,
446
aLoadGroup, aCallbacks, aLoadFlags, aIoService);
447
}
448
449
// See NS_NewChannelInternal for usage and argument description
450
nsresult NS_NewChannelWithTriggeringPrincipal(
451
nsIChannel** outChannel, nsIURI* aUri, nsIPrincipal* aLoadingPrincipal,
452
nsIPrincipal* aTriggeringPrincipal, nsSecurityFlags aSecurityFlags,
453
nsContentPolicyType aContentPolicyType,
454
nsICookieSettings* aCookieSettings /* = nullptr */,
455
PerformanceStorage* aPerformanceStorage /* = nullptr */,
456
nsILoadGroup* aLoadGroup /* = nullptr */,
457
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
458
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
459
nsIIOService* aIoService /* = nullptr */) {
460
NS_ASSERTION(aLoadingPrincipal,
461
"Can not create channel without a loading Principal!");
462
return NS_NewChannelInternal(
463
outChannel, aUri,
464
nullptr, // aLoadingNode
465
aLoadingPrincipal, aTriggeringPrincipal, Maybe<ClientInfo>(),
466
Maybe<ServiceWorkerDescriptor>(), aSecurityFlags, aContentPolicyType,
467
aCookieSettings, aPerformanceStorage, aLoadGroup, aCallbacks, aLoadFlags,
468
aIoService);
469
}
470
471
// See NS_NewChannelInternal for usage and argument description
472
nsresult NS_NewChannelWithTriggeringPrincipal(
473
nsIChannel** outChannel, nsIURI* aUri, nsIPrincipal* aLoadingPrincipal,
474
nsIPrincipal* aTriggeringPrincipal, const ClientInfo& aLoadingClientInfo,
475
const Maybe<ServiceWorkerDescriptor>& aController,
476
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
477
nsICookieSettings* aCookieSettings /* = nullptr */,
478
PerformanceStorage* aPerformanceStorage /* = nullptr */,
479
nsILoadGroup* aLoadGroup /* = nullptr */,
480
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
481
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
482
nsIIOService* aIoService /* = nullptr */) {
483
AssertLoadingPrincipalAndClientInfoMatch(
484
aLoadingPrincipal, aLoadingClientInfo, aContentPolicyType);
485
486
Maybe<ClientInfo> loadingClientInfo;
487
loadingClientInfo.emplace(aLoadingClientInfo);
488
489
return NS_NewChannelInternal(
490
outChannel, aUri,
491
nullptr, // aLoadingNode
492
aLoadingPrincipal, aTriggeringPrincipal, loadingClientInfo, aController,
493
aSecurityFlags, aContentPolicyType, aCookieSettings, aPerformanceStorage,
494
aLoadGroup, aCallbacks, aLoadFlags, aIoService);
495
}
496
497
nsresult NS_NewChannel(nsIChannel** outChannel, nsIURI* aUri,
498
nsINode* aLoadingNode, nsSecurityFlags aSecurityFlags,
499
nsContentPolicyType aContentPolicyType,
500
PerformanceStorage* aPerformanceStorage /* = nullptr */,
501
nsILoadGroup* aLoadGroup /* = nullptr */,
502
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
503
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
504
nsIIOService* aIoService /* = nullptr */) {
505
NS_ASSERTION(aLoadingNode, "Can not create channel without a loading Node!");
506
return NS_NewChannelInternal(
507
outChannel, aUri, aLoadingNode, aLoadingNode->NodePrincipal(),
508
nullptr, // aTriggeringPrincipal
509
Maybe<ClientInfo>(), Maybe<ServiceWorkerDescriptor>(), aSecurityFlags,
510
aContentPolicyType, aLoadingNode->OwnerDoc()->CookieSettings(),
511
aPerformanceStorage, aLoadGroup, aCallbacks, aLoadFlags, aIoService);
512
}
513
514
nsresult NS_GetIsDocumentChannel(nsIChannel* aChannel, bool* aIsDocument) {
515
// Check if this channel is going to be used to create a document. If it has
516
// LOAD_DOCUMENT_URI set it is trivially creating a document. If
517
// LOAD_HTML_OBJECT_DATA is set it may or may not be used to create a
518
// document, depending on its MIME type.
519
520
if (!aChannel || !aIsDocument) {
521
return NS_ERROR_NULL_POINTER;
522
}
523
*aIsDocument = false;
524
nsLoadFlags loadFlags;
525
nsresult rv = aChannel->GetLoadFlags(&loadFlags);
526
if (NS_FAILED(rv)) {
527
return rv;
528
}
529
if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
530
*aIsDocument = true;
531
return NS_OK;
532
}
533
if (!(loadFlags & nsIRequest::LOAD_HTML_OBJECT_DATA)) {
534
*aIsDocument = false;
535
return NS_OK;
536
}
537
nsAutoCString mimeType;
538
rv = aChannel->GetContentType(mimeType);
539
if (NS_FAILED(rv)) {
540
return rv;
541
}
542
if (nsContentUtils::HtmlObjectContentTypeForMIMEType(
543
mimeType, false, nullptr) == nsIObjectLoadingContent::TYPE_DOCUMENT) {
544
*aIsDocument = true;
545
return NS_OK;
546
}
547
*aIsDocument = false;
548
return NS_OK;
549
}
550
551
nsresult NS_MakeAbsoluteURI(nsACString& result, const nsACString& spec,
552
nsIURI* baseURI) {
553
nsresult rv;
554
if (!baseURI) {
555
NS_WARNING("It doesn't make sense to not supply a base URI");
556
result = spec;
557
rv = NS_OK;
558
} else if (spec.IsEmpty())
559
rv = baseURI->GetSpec(result);
560
else
561
rv = baseURI->Resolve(spec, result);
562
return rv;
563
}
564
565
nsresult NS_MakeAbsoluteURI(char** result, const char* spec, nsIURI* baseURI) {
566
nsresult rv;
567
nsAutoCString resultBuf;
568
rv = NS_MakeAbsoluteURI(resultBuf, nsDependentCString(spec), baseURI);
569
if (NS_SUCCEEDED(rv)) {
570
*result = ToNewCString(resultBuf);
571
if (!*result) rv = NS_ERROR_OUT_OF_MEMORY;
572
}
573
return rv;
574
}
575
576
nsresult NS_MakeAbsoluteURI(nsAString& result, const nsAString& spec,
577
nsIURI* baseURI) {
578
nsresult rv;
579
if (!baseURI) {
580
NS_WARNING("It doesn't make sense to not supply a base URI");
581
result = spec;
582
rv = NS_OK;
583
} else {
584
nsAutoCString resultBuf;
585
if (spec.IsEmpty())
586
rv = baseURI->GetSpec(resultBuf);
587
else
588
rv = baseURI->Resolve(NS_ConvertUTF16toUTF8(spec), resultBuf);
589
if (NS_SUCCEEDED(rv)) CopyUTF8toUTF16(resultBuf, result);
590
}
591
return rv;
592
}
593
594
int32_t NS_GetDefaultPort(const char* scheme,
595
nsIIOService* ioService /* = nullptr */) {
596
nsresult rv;
597
598
// Getting the default port through the protocol handler has a lot of XPCOM
599
// overhead involved. We optimize the protocols that matter for Web pages
600
// (HTTP and HTTPS) by hardcoding their default ports here.
601
if (strncmp(scheme, "http", 4) == 0) {
602
if (scheme[4] == 's' && scheme[5] == '\0') {
603
return 443;
604
}
605
if (scheme[4] == '\0') {
606
return 80;
607
}
608
}
609
610
nsCOMPtr<nsIIOService> grip;
611
net_EnsureIOService(&ioService, grip);
612
if (!ioService) return -1;
613
614
nsCOMPtr<nsIProtocolHandler> handler;
615
rv = ioService->GetProtocolHandler(scheme, getter_AddRefs(handler));
616
if (NS_FAILED(rv)) return -1;
617
int32_t port;
618
rv = handler->GetDefaultPort(&port);
619
return NS_SUCCEEDED(rv) ? port : -1;
620
}
621
622
/**
623
* This function is a helper function to apply the ToAscii conversion
624
* to a string
625
*/
626
bool NS_StringToACE(const nsACString& idn, nsACString& result) {
627
nsCOMPtr<nsIIDNService> idnSrv = do_GetService(NS_IDNSERVICE_CONTRACTID);
628
if (!idnSrv) return false;
629
nsresult rv = idnSrv->ConvertUTF8toACE(idn, result);
630
if (NS_FAILED(rv)) return false;
631
632
return true;
633
}
634
635
int32_t NS_GetRealPort(nsIURI* aURI) {
636
int32_t port;
637
nsresult rv = aURI->GetPort(&port);
638
if (NS_FAILED(rv)) return -1;
639
640
if (port != -1) return port; // explicitly specified
641
642
// Otherwise, we have to get the default port from the protocol handler
643
644
// Need the scheme first
645
nsAutoCString scheme;
646
rv = aURI->GetScheme(scheme);
647
if (NS_FAILED(rv)) return -1;
648
649
return NS_GetDefaultPort(scheme.get());
650
}
651
652
nsresult NS_NewInputStreamChannelInternal(
653
nsIChannel** outChannel, nsIURI* aUri,
654
already_AddRefed<nsIInputStream> aStream, const nsACString& aContentType,
655
const nsACString& aContentCharset, nsILoadInfo* aLoadInfo) {
656
nsresult rv;
657
nsCOMPtr<nsIInputStreamChannel> isc =
658
do_CreateInstance(NS_INPUTSTREAMCHANNEL_CONTRACTID, &rv);
659
NS_ENSURE_SUCCESS(rv, rv);
660
rv = isc->SetURI(aUri);
661
NS_ENSURE_SUCCESS(rv, rv);
662
663
nsCOMPtr<nsIInputStream> stream = std::move(aStream);
664
rv = isc->SetContentStream(stream);
665
NS_ENSURE_SUCCESS(rv, rv);
666
667
nsCOMPtr<nsIChannel> channel = do_QueryInterface(isc, &rv);
668
NS_ENSURE_SUCCESS(rv, rv);
669
670
if (!aContentType.IsEmpty()) {
671
rv = channel->SetContentType(aContentType);
672
NS_ENSURE_SUCCESS(rv, rv);
673
}
674
675
if (!aContentCharset.IsEmpty()) {
676
rv = channel->SetContentCharset(aContentCharset);
677
NS_ENSURE_SUCCESS(rv, rv);
678
}
679
680
MOZ_ASSERT(aLoadInfo, "need a loadinfo to create a inputstreamchannel");
681
channel->SetLoadInfo(aLoadInfo);
682
683
// If we're sandboxed, make sure to clear any owner the channel
684
// might already have.
685
if (aLoadInfo && aLoadInfo->GetLoadingSandboxed()) {
686
channel->SetOwner(nullptr);
687
}
688
689
channel.forget(outChannel);
690
return NS_OK;
691
}
692
693
nsresult NS_NewInputStreamChannelInternal(
694
nsIChannel** outChannel, nsIURI* aUri,
695
already_AddRefed<nsIInputStream> aStream, const nsACString& aContentType,
696
const nsACString& aContentCharset, nsINode* aLoadingNode,
697
nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
698
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType) {
699
nsCOMPtr<nsILoadInfo> loadInfo = new mozilla::net::LoadInfo(
700
aLoadingPrincipal, aTriggeringPrincipal, aLoadingNode, aSecurityFlags,
701
aContentPolicyType);
702
if (!loadInfo) {
703
return NS_ERROR_UNEXPECTED;
704
}
705
706
nsCOMPtr<nsIInputStream> stream = std::move(aStream);
707
708
return NS_NewInputStreamChannelInternal(outChannel, aUri, stream.forget(),
709
aContentType, aContentCharset,
710
loadInfo);
711
}
712
713
nsresult NS_NewInputStreamChannel(
714
nsIChannel** outChannel, nsIURI* aUri,
715
already_AddRefed<nsIInputStream> aStream, nsIPrincipal* aLoadingPrincipal,
716
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
717
const nsACString& aContentType /* = EmptyCString() */,
718
const nsACString& aContentCharset /* = EmptyCString() */) {
719
nsCOMPtr<nsIInputStream> stream = aStream;
720
return NS_NewInputStreamChannelInternal(outChannel, aUri, stream.forget(),
721
aContentType, aContentCharset,
722
nullptr, // aLoadingNode
723
aLoadingPrincipal,
724
nullptr, // aTriggeringPrincipal
725
aSecurityFlags, aContentPolicyType);
726
}
727
728
nsresult NS_NewInputStreamChannelInternal(nsIChannel** outChannel, nsIURI* aUri,
729
const nsAString& aData,
730
const nsACString& aContentType,
731
nsILoadInfo* aLoadInfo,
732
bool aIsSrcdocChannel /* = false */) {
733
nsresult rv;
734
nsCOMPtr<nsIStringInputStream> stream;
735
stream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
736
NS_ENSURE_SUCCESS(rv, rv);
737
738
uint32_t len;
739
char* utf8Bytes = ToNewUTF8String(aData, &len);
740
rv = stream->AdoptData(utf8Bytes, len);
741
742
nsCOMPtr<nsIChannel> channel;
743
rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aUri,
744
stream.forget(), aContentType,
745
NS_LITERAL_CSTRING("UTF-8"), aLoadInfo);
746
747
NS_ENSURE_SUCCESS(rv, rv);
748
749
if (aIsSrcdocChannel) {
750
nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(channel);
751
NS_ENSURE_TRUE(inStrmChan, NS_ERROR_FAILURE);
752
inStrmChan->SetSrcdocData(aData);
753
}
754
channel.forget(outChannel);
755
return NS_OK;
756
}
757
758
nsresult NS_NewInputStreamChannelInternal(
759
nsIChannel** outChannel, nsIURI* aUri, const nsAString& aData,
760
const nsACString& aContentType, nsINode* aLoadingNode,
761
nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
762
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
763
bool aIsSrcdocChannel /* = false */) {
764
nsCOMPtr<nsILoadInfo> loadInfo = new mozilla::net::LoadInfo(
765
aLoadingPrincipal, aTriggeringPrincipal, aLoadingNode, aSecurityFlags,
766
aContentPolicyType);
767
return NS_NewInputStreamChannelInternal(outChannel, aUri, aData, aContentType,
768
loadInfo, aIsSrcdocChannel);
769
}
770
771
nsresult NS_NewInputStreamChannel(nsIChannel** outChannel, nsIURI* aUri,
772
const nsAString& aData,
773
const nsACString& aContentType,
774
nsIPrincipal* aLoadingPrincipal,
775
nsSecurityFlags aSecurityFlags,
776
nsContentPolicyType aContentPolicyType,
777
bool aIsSrcdocChannel /* = false */) {
778
return NS_NewInputStreamChannelInternal(outChannel, aUri, aData, aContentType,
779
nullptr, // aLoadingNode
780
aLoadingPrincipal,
781
nullptr, // aTriggeringPrincipal
782
aSecurityFlags, aContentPolicyType,
783
aIsSrcdocChannel);
784
}
785
786
nsresult NS_NewInputStreamPump(
787
nsIInputStreamPump** aResult, already_AddRefed<nsIInputStream> aStream,
788
uint32_t aSegsize /* = 0 */, uint32_t aSegcount /* = 0 */,
789
bool aCloseWhenDone /* = false */,
790
nsIEventTarget* aMainThreadTarget /* = nullptr */) {
791
nsCOMPtr<nsIInputStream> stream = std::move(aStream);
792
793
nsresult rv;
794
nsCOMPtr<nsIInputStreamPump> pump =
795
do_CreateInstance(NS_INPUTSTREAMPUMP_CONTRACTID, &rv);
796
if (NS_SUCCEEDED(rv)) {
797
rv = pump->Init(stream, aSegsize, aSegcount, aCloseWhenDone,
798
aMainThreadTarget);
799
if (NS_SUCCEEDED(rv)) {
800
*aResult = nullptr;
801
pump.swap(*aResult);
802
}
803
}
804
return rv;
805
}
806
807
nsresult NS_NewLoadGroup(nsILoadGroup** result, nsIRequestObserver* obs) {
808
nsresult rv;
809
nsCOMPtr<nsILoadGroup> group =
810
do_CreateInstance(NS_LOADGROUP_CONTRACTID, &rv);
811
if (NS_SUCCEEDED(rv)) {
812
rv = group->SetGroupObserver(obs);
813
if (NS_SUCCEEDED(rv)) {
814
*result = nullptr;
815
group.swap(*result);
816
}
817
}
818
return rv;
819
}
820
821
bool NS_IsReasonableHTTPHeaderValue(const nsACString& aValue) {
822
return mozilla::net::nsHttp::IsReasonableHeaderValue(aValue);
823
}
824
825
bool NS_IsValidHTTPToken(const nsACString& aToken) {
826
return mozilla::net::nsHttp::IsValidToken(aToken);
827
}
828
829
void NS_TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest) {
830
mozilla::net::nsHttp::TrimHTTPWhitespace(aSource, aDest);
831
}
832
833
nsresult NS_NewLoadGroup(nsILoadGroup** aResult, nsIPrincipal* aPrincipal) {
834
using mozilla::LoadContext;
835
nsresult rv;
836
837
nsCOMPtr<nsILoadGroup> group =
838
do_CreateInstance(NS_LOADGROUP_CONTRACTID, &rv);
839
NS_ENSURE_SUCCESS(rv, rv);
840
841
RefPtr<LoadContext> loadContext = new LoadContext(aPrincipal);
842
rv = group->SetNotificationCallbacks(loadContext);
843
NS_ENSURE_SUCCESS(rv, rv);
844
845
group.forget(aResult);
846
return rv;
847
}
848
849
bool NS_LoadGroupMatchesPrincipal(nsILoadGroup* aLoadGroup,
850
nsIPrincipal* aPrincipal) {
851
if (!aPrincipal) {
852
return false;
853
}
854
855
// If this is a null principal then the load group doesn't really matter.
856
// The principal will not be allowed to perform any actions that actually
857
// use the load group. Unconditionally treat null principals as a match.
858
if (aPrincipal->GetIsNullPrincipal()) {
859
return true;
860
}
861
862
if (!aLoadGroup) {
863
return false;
864
}
865
866
nsCOMPtr<nsILoadContext> loadContext;
867
NS_QueryNotificationCallbacks(nullptr, aLoadGroup, NS_GET_IID(nsILoadContext),
868
getter_AddRefs(loadContext));
869
NS_ENSURE_TRUE(loadContext, false);
870
871
return true;
872
}
873
874
nsresult NS_NewDownloader(nsIStreamListener** result,
875
nsIDownloadObserver* observer,
876
nsIFile* downloadLocation /* = nullptr */) {
877
nsresult rv;
878
nsCOMPtr<nsIDownloader> downloader =
879
do_CreateInstance(NS_DOWNLOADER_CONTRACTID, &rv);
880
if (NS_SUCCEEDED(rv)) {
881
rv = downloader->Init(observer, downloadLocation);
882
if (NS_SUCCEEDED(rv)) {
883
downloader.forget(result);
884
}
885
}
886
return rv;
887
}
888
889
nsresult NS_NewIncrementalStreamLoader(
890
nsIIncrementalStreamLoader** result,
891
nsIIncrementalStreamLoaderObserver* observer) {
892
nsresult rv;
893
nsCOMPtr<nsIIncrementalStreamLoader> loader =
894
do_CreateInstance(NS_INCREMENTALSTREAMLOADER_CONTRACTID, &rv);
895
if (NS_SUCCEEDED(rv)) {
896
rv = loader->Init(observer);
897
if (NS_SUCCEEDED(rv)) {
898
*result = nullptr;
899
loader.swap(*result);
900
}
901
}
902
return rv;
903
}
904
905
nsresult NS_NewStreamLoader(
906
nsIStreamLoader** result, nsIStreamLoaderObserver* observer,
907
nsIRequestObserver* requestObserver /* = nullptr */) {
908
nsresult rv;
909
nsCOMPtr<nsIStreamLoader> loader =
910
do_CreateInstance(NS_STREAMLOADER_CONTRACTID, &rv);
911
if (NS_SUCCEEDED(rv)) {
912
rv = loader->Init(observer, requestObserver);
913
if (NS_SUCCEEDED(rv)) {
914
*result = nullptr;
915
loader.swap(*result);
916
}
917
}
918
return rv;
919
}
920
921
nsresult NS_NewStreamLoaderInternal(
922
nsIStreamLoader** outStream, nsIURI* aUri,
923
nsIStreamLoaderObserver* aObserver, nsINode* aLoadingNode,
924
nsIPrincipal* aLoadingPrincipal, nsSecurityFlags aSecurityFlags,
925
nsContentPolicyType aContentPolicyType,
926
nsILoadGroup* aLoadGroup /* = nullptr */,
927
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
928
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */) {
929
nsCOMPtr<nsIChannel> channel;
930
nsresult rv = NS_NewChannelInternal(
931
getter_AddRefs(channel), aUri, aLoadingNode, aLoadingPrincipal,
932
nullptr, // aTriggeringPrincipal
933
Maybe<ClientInfo>(), Maybe<ServiceWorkerDescriptor>(), aSecurityFlags,
934
aContentPolicyType,
935
nullptr, // nsICookieSettings
936
nullptr, // PerformanceStorage
937
aLoadGroup, aCallbacks, aLoadFlags);
938
939
NS_ENSURE_SUCCESS(rv, rv);
940
rv = NS_NewStreamLoader(outStream, aObserver);
941
NS_ENSURE_SUCCESS(rv, rv);
942
return channel->AsyncOpen(*outStream);
943
}
944
945
nsresult NS_NewStreamLoader(
946
nsIStreamLoader** outStream, nsIURI* aUri,
947
nsIStreamLoaderObserver* aObserver, nsINode* aLoadingNode,
948
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
949
nsILoadGroup* aLoadGroup /* = nullptr */,
950
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
951
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */) {
952
NS_ASSERTION(aLoadingNode,
953
"Can not create stream loader without a loading Node!");
954
return NS_NewStreamLoaderInternal(
955
outStream, aUri, aObserver, aLoadingNode, aLoadingNode->NodePrincipal(),
956
aSecurityFlags, aContentPolicyType, aLoadGroup, aCallbacks, aLoadFlags);
957
}
958
959
nsresult NS_NewStreamLoader(
960
nsIStreamLoader** outStream, nsIURI* aUri,
961
nsIStreamLoaderObserver* aObserver, nsIPrincipal* aLoadingPrincipal,
962
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
963
nsILoadGroup* aLoadGroup /* = nullptr */,
964
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
965
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */) {
966
return NS_NewStreamLoaderInternal(outStream, aUri, aObserver,
967
nullptr, // aLoadingNode
968
aLoadingPrincipal, aSecurityFlags,
969
aContentPolicyType, aLoadGroup, aCallbacks,
970
aLoadFlags);
971
}
972
973
nsresult NS_NewSyncStreamListener(nsIStreamListener** result,
974
nsIInputStream** stream) {
975
nsCOMPtr<nsISyncStreamListener> listener = nsSyncStreamListener::Create();
976
if (listener) {
977
nsresult rv = listener->GetInputStream(stream);
978
if (NS_SUCCEEDED(rv)) {
979
listener.forget(result);
980
}
981
return rv;
982
}
983
return NS_ERROR_FAILURE;
984
}
985
986
nsresult NS_ImplementChannelOpen(nsIChannel* channel, nsIInputStream** result) {
987
nsCOMPtr<nsIStreamListener> listener;
988
nsCOMPtr<nsIInputStream> stream;
989
nsresult rv = NS_NewSyncStreamListener(getter_AddRefs(listener),
990
getter_AddRefs(stream));
991
NS_ENSURE_SUCCESS(rv, rv);
992
993
rv = NS_MaybeOpenChannelUsingAsyncOpen(channel, listener);
994
NS_ENSURE_SUCCESS(rv, rv);
995
996
uint64_t n;
997
// block until the initial response is received or an error occurs.
998
rv = stream->Available(&n);
999
NS_ENSURE_SUCCESS(rv, rv);
1000
1001
*result = nullptr;
1002
stream.swap(*result);
1003
1004
return NS_OK;
1005
}
1006
1007
nsresult NS_NewRequestObserverProxy(nsIRequestObserver** result,
1008
nsIRequestObserver* observer,
1009
nsISupports* context) {
1010
nsCOMPtr<nsIRequestObserverProxy> proxy = new nsRequestObserverProxy();
1011
nsresult rv = proxy->Init(observer, context);
1012
if (NS_SUCCEEDED(rv)) {
1013
proxy.forget(result);
1014
}
1015
return rv;
1016
}
1017
1018
nsresult NS_NewSimpleStreamListener(
1019
nsIStreamListener** result, nsIOutputStream* sink,
1020
nsIRequestObserver* observer /* = nullptr */) {
1021
nsresult rv;
1022
nsCOMPtr<nsISimpleStreamListener> listener =
1023
do_CreateInstance(NS_SIMPLESTREAMLISTENER_CONTRACTID, &rv);
1024
if (NS_SUCCEEDED(rv)) {
1025
rv = listener->Init(sink, observer);
1026
if (NS_SUCCEEDED(rv)) {
1027
listener.forget(result);
1028
}
1029
}
1030
return rv;
1031
}
1032
1033
nsresult NS_CheckPortSafety(int32_t port, const char* scheme,
1034
nsIIOService* ioService /* = nullptr */) {
1035
nsresult rv;
1036
nsCOMPtr<nsIIOService> grip;
1037
rv = net_EnsureIOService(&ioService, grip);
1038
if (ioService) {
1039
bool allow;
1040
rv = ioService->AllowPort(port, scheme, &allow);
1041
if (NS_SUCCEEDED(rv) && !allow) {
1042
NS_WARNING("port blocked");
1043
rv = NS_ERROR_PORT_ACCESS_NOT_ALLOWED;
1044
}
1045
}
1046
return rv;
1047
}
1048
1049
nsresult NS_CheckPortSafety(nsIURI* uri) {
1050
int32_t port;
1051
nsresult rv = uri->GetPort(&port);
1052
if (NS_FAILED(rv) || port == -1) // port undefined or default-valued
1053
return NS_OK;
1054
nsAutoCString scheme;
1055
uri->GetScheme(scheme);
1056
return NS_CheckPortSafety(port, scheme.get());
1057
}
1058
1059
nsresult NS_NewProxyInfo(const nsACString& type, const nsACString& host,
1060
int32_t port, uint32_t flags, nsIProxyInfo** result) {
1061
nsresult rv;
1062
nsCOMPtr<nsIProtocolProxyService> pps =
1063
do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
1064
if (NS_SUCCEEDED(rv))
1065
rv = pps->NewProxyInfo(type, host, port, EmptyCString(), EmptyCString(),
1066
flags, UINT32_MAX, nullptr, result);
1067
return rv;
1068
}
1069
1070
nsresult NS_GetFileProtocolHandler(nsIFileProtocolHandler** result,
1071
nsIIOService* ioService /* = nullptr */) {
1072
nsresult rv;
1073
nsCOMPtr<nsIIOService> grip;
1074
rv = net_EnsureIOService(&ioService, grip);
1075
if (ioService) {
1076
nsCOMPtr<nsIProtocolHandler> handler;
1077
rv = ioService->GetProtocolHandler("file", getter_AddRefs(handler));
1078
if (NS_SUCCEEDED(rv)) rv = CallQueryInterface(handler, result);
1079
}
1080
return rv;
1081
}
1082
1083
nsresult NS_GetFileFromURLSpec(const nsACString& inURL, nsIFile** result,
1084
nsIIOService* ioService /* = nullptr */) {
1085
nsresult rv;
1086
nsCOMPtr<nsIFileProtocolHandler> fileHandler;
1087
rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
1088
if (NS_SUCCEEDED(rv)) rv = fileHandler->GetFileFromURLSpec(inURL, result);
1089
return rv;
1090
}
1091
1092
nsresult NS_GetURLSpecFromFile(nsIFile* file, nsACString& url,
1093
nsIIOService* ioService /* = nullptr */) {
1094
nsresult rv;
1095
nsCOMPtr<nsIFileProtocolHandler> fileHandler;
1096
rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
1097
if (NS_SUCCEEDED(rv)) rv = fileHandler->GetURLSpecFromFile(file, url);
1098
return rv;
1099
}
1100
1101
nsresult NS_GetURLSpecFromActualFile(nsIFile* file, nsACString& url,
1102
nsIIOService* ioService /* = nullptr */) {
1103
nsresult rv;
1104
nsCOMPtr<nsIFileProtocolHandler> fileHandler;
1105
rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
1106
if (NS_SUCCEEDED(rv)) rv = fileHandler->GetURLSpecFromActualFile(file, url);
1107
return rv;
1108
}
1109
1110
nsresult NS_GetURLSpecFromDir(nsIFile* file, nsACString& url,
1111
nsIIOService* ioService /* = nullptr */) {
1112
nsresult rv;
1113
nsCOMPtr<nsIFileProtocolHandler> fileHandler;
1114
rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
1115
if (NS_SUCCEEDED(rv)) rv = fileHandler->GetURLSpecFromDir(file, url);
1116
return rv;
1117
}
1118
1119
void NS_GetReferrerFromChannel(nsIChannel* channel, nsIURI** referrer) {
1120
*referrer = nullptr;
1121
1122
nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(channel));
1123
if (props) {
1124
// We have to check for a property on a property bag because the
1125
// referrer may be empty for security reasons (for example, when loading
1126
// an http page with an https referrer).
1127
nsresult rv = props->GetPropertyAsInterface(
1128
NS_LITERAL_STRING("docshell.internalReferrer"), NS_GET_IID(nsIURI),
1129
reinterpret_cast<void**>(referrer));
1130
if (NS_SUCCEEDED(rv)) {
1131
return;
1132
}
1133
}
1134
1135
// if that didn't work, we can still try to get the referrer from the
1136
// nsIHttpChannel (if we can QI to it)
1137
nsCOMPtr<nsIHttpChannel> chan(do_QueryInterface(channel));
1138
if (!chan) {
1139
return;
1140
}
1141
1142
nsCOMPtr<nsIReferrerInfo> referrerInfo = chan->GetReferrerInfo();
1143
if (!referrerInfo) {
1144
return;
1145
}
1146
1147
referrerInfo->GetOriginalReferrer(referrer);
1148
}
1149
1150
already_AddRefed<nsINetUtil> do_GetNetUtil(nsresult* error /* = 0 */) {
1151
nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
1152
nsCOMPtr<nsINetUtil> util;
1153
if (io) util = do_QueryInterface(io);
1154
1155
if (error) *error = !!util ? NS_OK : NS_ERROR_FAILURE;
1156
return util.forget();
1157
}
1158
1159
nsresult NS_ParseRequestContentType(const nsACString& rawContentType,
1160
nsCString& contentType,
1161
nsCString& contentCharset) {
1162
// contentCharset is left untouched if not present in rawContentType
1163
nsresult rv;
1164
nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
1165
NS_ENSURE_SUCCESS(rv, rv);
1166
nsCString charset;
1167
bool hadCharset;
1168
rv = util->ParseRequestContentType(rawContentType, charset, &hadCharset,
1169
contentType);
1170
if (NS_SUCCEEDED(rv) && hadCharset) contentCharset = charset;
1171
return rv;
1172
}
1173
1174
nsresult NS_ParseResponseContentType(const nsACString& rawContentType,
1175
nsCString& contentType,
1176
nsCString& contentCharset) {
1177
// contentCharset is left untouched if not present in rawContentType
1178
nsresult rv;
1179
nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
1180
NS_ENSURE_SUCCESS(rv, rv);
1181
nsCString charset;
1182
bool hadCharset;
1183
rv = util->ParseResponseContentType(rawContentType, charset, &hadCharset,
1184
contentType);
1185
if (NS_SUCCEEDED(rv) && hadCharset) contentCharset = charset;
1186
return rv;
1187
}
1188
1189
nsresult NS_ExtractCharsetFromContentType(const nsACString& rawContentType,
1190
nsCString& contentCharset,
1191
bool* hadCharset,
1192
int32_t* charsetStart,
1193
int32_t* charsetEnd) {
1194
// contentCharset is left untouched if not present in rawContentType
1195
nsresult rv;
1196
nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
1197
NS_ENSURE_SUCCESS(rv, rv);
1198
1199
return util->ExtractCharsetFromContentType(
1200
rawContentType, contentCharset, charsetStart, charsetEnd, hadCharset);
1201
}
1202
1203
nsresult NS_NewAtomicFileOutputStream(nsIOutputStream** result, nsIFile* file,
1204
int32_t ioFlags /* = -1 */,
1205
int32_t perm /* = -1 */,
1206
int32_t behaviorFlags /* = 0 */) {
1207
nsresult rv;
1208
nsCOMPtr<nsIFileOutputStream> out =
1209
do_CreateInstance(NS_ATOMICLOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
1210
if (NS_SUCCEEDED(rv)) {
1211
rv = out->Init(file, ioFlags, perm, behaviorFlags);
1212
if (NS_SUCCEEDED(rv)) out.forget(result);
1213
}
1214
return rv;
1215
}
1216
1217
nsresult NS_NewSafeLocalFileOutputStream(nsIOutputStream** result,
1218
nsIFile* file,
1219
int32_t ioFlags /* = -1 */,
1220
int32_t perm /* = -1 */,
1221
int32_t behaviorFlags /* = 0 */) {
1222
nsresult rv;
1223
nsCOMPtr<nsIFileOutputStream> out =
1224
do_CreateInstance(NS_SAFELOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
1225
if (NS_SUCCEEDED(rv)) {
1226
rv = out->Init(file, ioFlags, perm, behaviorFlags);
1227
if (NS_SUCCEEDED(rv)) out.forget(result);
1228
}
1229
return rv;
1230
}
1231
1232
nsresult NS_NewLocalFileStream(nsIFileStream** result, nsIFile* file,
1233
int32_t ioFlags /* = -1 */,
1234
int32_t perm /* = -1 */,
1235
int32_t behaviorFlags /* = 0 */) {
1236
nsCOMPtr<nsIFileStream> stream = new nsFileStream();
1237
nsresult rv = stream->Init(file, ioFlags, perm, behaviorFlags);
1238
if (NS_SUCCEEDED(rv)) {
1239
stream.forget(result);
1240
}
1241
return rv;
1242
}
1243
1244
nsresult NS_NewBufferedOutputStream(
1245
nsIOutputStream** aResult, already_AddRefed<nsIOutputStream> aOutputStream,
1246
uint32_t aBufferSize) {
1247
nsCOMPtr<nsIOutputStream> outputStream = std::move(aOutputStream);
1248
1249
nsresult rv;
1250
nsCOMPtr<nsIBufferedOutputStream> out =
1251
do_CreateInstance(NS_BUFFEREDOUTPUTSTREAM_CONTRACTID, &rv);
1252
if (NS_SUCCEEDED(rv)) {
1253
rv = out->Init(outputStream, aBufferSize);
1254
if (NS_SUCCEEDED(rv)) {
1255
out.forget(aResult);
1256
}
1257
}
1258
return rv;
1259
}
1260
1261
MOZ_MUST_USE nsresult NS_NewBufferedInputStream(
1262
nsIInputStream** aResult, already_AddRefed<nsIInputStream> aInputStream,
1263
uint32_t aBufferSize) {
1264
nsCOMPtr<nsIInputStream> inputStream = std::move(aInputStream);
1265
1266
nsresult rv;
1267
nsCOMPtr<nsIBufferedInputStream> in =
1268
do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv);
1269
if (NS_SUCCEEDED(rv)) {
1270
rv = in->Init(inputStream, aBufferSize);
1271
if (NS_SUCCEEDED(rv)) {
1272
*aResult = static_cast<nsBufferedInputStream*>(in.get())
1273
->GetInputStream()
1274
.take();
1275
}
1276
}
1277
return rv;
1278
}
1279
1280
namespace {
1281
1282
#define BUFFER_SIZE 8192
1283
1284
class BufferWriter final : public nsIInputStreamCallback {
1285
public:
1286
NS_DECL_THREADSAFE_ISUPPORTS
1287
1288
BufferWriter(nsIInputStream* aInputStream, void* aBuffer, int64_t aCount)
1289
: mMonitor("BufferWriter.mMonitor"),
1290
mInputStream(aInputStream),
1291
mBuffer(aBuffer),
1292
mCount(aCount),
1293
mWrittenData(0),
1294
mBufferType(aBuffer ? eExternal : eInternal),
1295
mBufferSize(0) {
1296
MOZ_ASSERT(aInputStream);
1297
MOZ_ASSERT(aCount == -1 || aCount > 0);
1298
MOZ_ASSERT_IF(mBuffer, aCount > 0);
1299
}
1300
1301
nsresult Write() {
1302
NS_ASSERT_OWNINGTHREAD(BufferWriter);
1303
1304
// Let's make the inputStream buffered if it's not.
1305
if (!NS_InputStreamIsBuffered(mInputStream)) {
1306
nsCOMPtr<nsIInputStream> bufferedStream;
1307
nsresult rv = NS_NewBufferedInputStream(
1308
getter_AddRefs(bufferedStream), mInputStream.forget(), BUFFER_SIZE);
1309
NS_ENSURE_SUCCESS(rv, rv);
1310
1311
mInputStream = bufferedStream;
1312
}
1313
1314
mAsyncInputStream = do_QueryInterface(mInputStream);
1315
1316
if (!mAsyncInputStream) {
1317
return WriteSync();
1318
}
1319
1320
// Let's use mAsyncInputStream only.
1321
mInputStream = nullptr;
1322
1323
return WriteAsync();
1324
}
1325
1326
uint64_t WrittenData() const {
1327
NS_ASSERT_OWNINGTHREAD(BufferWriter);
1328
return mWrittenData;
1329
}
1330
1331
void* StealBuffer() {
1332
NS_ASSERT_OWNINGTHREAD(BufferWriter);
1333
MOZ_ASSERT(mBufferType == eInternal);
1334
1335
void* buffer = mBuffer;
1336
1337
mBuffer = nullptr;
1338
mBufferSize = 0;
1339
1340
return buffer;
1341
}
1342
1343
private:
1344
~BufferWriter() {
1345
if (mBuffer && mBufferType == eInternal) {
1346
free(mBuffer);
1347
}
1348
1349
if (mTaskQueue) {
1350
mTaskQueue->BeginShutdown();
1351
}
1352
}
1353
1354
nsresult WriteSync() {
1355
NS_ASSERT_OWNINGTHREAD(BufferWriter);
1356
1357
uint64_t length = (uint64_t)mCount;
1358
1359
if (mCount == -1) {
1360
nsresult rv = mInputStream->Available(&length);
1361
NS_ENSURE_SUCCESS(rv, rv);
1362
1363
if (length == 0) {
1364
// nothing to read.
1365
return NS_OK;
1366
}
1367
}
1368
1369
if (mBufferType == eInternal) {
1370
mBuffer = malloc(length);
1371
if (NS_WARN_IF(!mBuffer)) {
1372
return NS_ERROR_OUT_OF_MEMORY;
1373
}
1374
}
1375
1376
uint32_t writtenData;
1377
nsresult rv = mInputStream->ReadSegments(NS_CopySegmentToBuffer, mBuffer,
1378
length, &writtenData);
1379
NS_ENSURE_SUCCESS(rv, rv);
1380
1381
mWrittenData = writtenData;
1382
return NS_OK;
1383
}
1384
1385
nsresult WriteAsync() {
1386
NS_ASSERT_OWNINGTHREAD(BufferWriter);
1387
1388
if (mCount > 0 && mBufferType == eInternal) {
1389
mBuffer = malloc(mCount);
1390
if (NS_WARN_IF(!mBuffer)) {
1391
return NS_ERROR_OUT_OF_MEMORY;
1392
}
1393
}
1394
1395
while (true) {
1396
if (mCount == -1 && !MaybeExpandBufferSize()) {
1397
return NS_ERROR_OUT_OF_MEMORY;
1398
}
1399
1400
uint64_t offset = mWrittenData;
1401
uint64_t length = mCount == -1 ? BUFFER_SIZE : mCount;
1402
1403
// Let's try to read data directly.
1404
uint32_t writtenData;
1405
nsresult rv = mAsyncInputStream->ReadSegments(
1406
NS_CopySegmentToBuffer, static_cast<char*>(mBuffer) + offset, length,
1407
&writtenData);
1408
1409
// Operation completed. Nothing more to read.
1410
if (NS_SUCCEEDED(rv) && writtenData == 0) {
1411
return NS_OK;
1412
}
1413
1414
// If we succeeded, let's try to read again.
1415
if (NS_SUCCEEDED(rv)) {
1416
mWrittenData += writtenData;
1417
if (mCount != -1) {
1418
MOZ_ASSERT(mCount >= writtenData);
1419
mCount -= writtenData;
1420
1421
// Is this the end of the reading?
1422
if (mCount == 0) {
1423
return NS_OK;
1424
}
1425
}
1426
1427
continue;
1428
}
1429
1430
// Async wait...
1431
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
1432
rv = MaybeCreateTaskQueue();
1433
if (NS_WARN_IF(NS_FAILED(rv))) {
1434
return rv;
1435
}
1436
1437
MonitorAutoLock lock(mMonitor);
1438
1439
rv = mAsyncInputStream->AsyncWait(this, 0, length, mTaskQueue);
1440
if (NS_WARN_IF(NS_FAILED(rv))) {
1441
return rv;
1442
}
1443
1444
lock.Wait();
1445
continue;
1446
}
1447
1448
// Otherwise, let's propagate the error.
1449
return rv;
1450
}
1451
1452
MOZ_ASSERT_UNREACHABLE("We should not be here");
1453
return NS_ERROR_FAILURE;
1454
}
1455
1456
nsresult MaybeCreateTaskQueue() {
1457
NS_ASSERT_OWNINGTHREAD(BufferWriter);
1458
1459
if (!mTaskQueue) {
1460
nsCOMPtr<nsIEventTarget> target =
1461
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
1462
if (!target) {
1463
return NS_ERROR_FAILURE;
1464
}
1465
1466
mTaskQueue = new TaskQueue(target.forget());
1467
}
1468
1469
return NS_OK;
1470
}
1471
1472
NS_IMETHOD
1473
OnInputStreamReady(nsIAsyncInputStream* aStream) override {
1474
MOZ_ASSERT(!NS_IsMainThread());
1475
1476
// We have something to read. Let's unlock the main-thread.
1477
MonitorAutoLock lock(mMonitor);
1478
lock.Notify();
1479
return NS_OK;
1480
}
1481
1482
bool MaybeExpandBufferSize() {
1483
NS_ASSERT_OWNINGTHREAD(BufferWriter);
1484
1485
MOZ_ASSERT(mCount == -1);
1486
1487
if (mBufferSize >= mWrittenData + BUFFER_SIZE) {
1488
// The buffer is big enough.
1489
return true;
1490
}
1491
1492
CheckedUint32 bufferSize =
1493
std::max<uint32_t>(static_cast<uint32_t>(mWrittenData), BUFFER_SIZE);
1494
while (bufferSize.isValid() &&
1495
bufferSize.value() < mWrittenData + BUFFER_SIZE) {
1496
bufferSize *= 2;
1497
}
1498
1499
if (!bufferSize.isValid()) {
1500
return false;
1501
}
1502
1503
void* buffer = realloc(mBuffer, bufferSize.value());
1504
if (!buffer) {
1505
return false;
1506
}
1507
1508
mBuffer = buffer;
1509
mBufferSize = bufferSize.value();
1510
return true;
1511
}
1512
1513
// All the members of this class are touched on the owning thread only. The
1514
// monitor is only used to communicate when there is more data to read.
1515
Monitor mMonitor;
1516
1517
nsCOMPtr<nsIInputStream> mInputStream;
1518
nsCOMPtr<nsIAsyncInputStream> mAsyncInputStream;
1519
1520
RefPtr<TaskQueue> mTaskQueue;
1521
1522
void* mBuffer;
1523
int64_t mCount;
1524
uint64_t mWrittenData;
1525
1526
enum {
1527
// The buffer is allocated internally and this object must release it
1528
// in the DTOR if not stolen. The buffer can be reallocated.
1529
eInternal,
1530
1531
// The buffer is not owned by this object and it cannot be reallocated.
1532
eExternal,
1533
} mBufferType;
1534
1535
// The following set if needed for the async read.
1536
uint64_t mBufferSize;
1537
};
1538
1539
NS_IMPL_ISUPPORTS(BufferWriter, nsIInputStreamCallback)
1540
1541
} // anonymous namespace
1542
1543
nsresult NS_ReadInputStreamToBuffer(nsIInputStream* aInputStream, void** aDest,
1544
int64_t aCount, uint64_t* aWritten) {
1545
MOZ_ASSERT(aInputStream);
1546
MOZ_ASSERT(aCount >= -1);
1547
1548
uint64_t dummyWritten;
1549
if (!aWritten) {
1550
aWritten = &dummyWritten;
1551
}
1552
1553
if (aCount == 0) {
1554
*aWritten = 0;
1555
return NS_OK;
1556
}
1557
1558
// This will take care of allocating and reallocating aDest.
1559
RefPtr<BufferWriter> writer = new BufferWriter(aInputStream, *aDest, aCount);
1560
1561
nsresult rv = writer->Write();
1562
NS_ENSURE_SUCCESS(rv, rv);
1563
1564
*aWritten = writer->WrittenData();
1565
1566
if (!*aDest) {
1567
*aDest = writer->StealBuffer();
1568
}
1569
1570
return NS_OK;
1571
}
1572
1573
nsresult NS_ReadInputStreamToString(nsIInputStream* aInputStream,
1574
nsACString& aDest, int64_t aCount,
1575
uint64_t* aWritten) {
1576
uint64_t dummyWritten;
1577
if (!aWritten) {
1578
aWritten = &dummyWritten;
1579
}
1580
1581
// Nothing to do if aCount is 0.
1582
if (aCount == 0) {
1583
aDest.Truncate();
1584
*aWritten = 0;
1585
return NS_OK;
1586
}
1587
1588
// If we have the size, we can pre-allocate the buffer.
1589
if (aCount > 0) {
1590
if (NS_WARN_IF(aCount >= INT32_MAX) ||
1591
NS_WARN_IF(!aDest.SetLength(aCount, mozilla::fallible))) {
1592
return NS_ERROR_OUT_OF_MEMORY;
1593
}
1594
1595
void* dest = aDest.BeginWriting();
1596
nsresult rv =
1597
NS_ReadInputStreamToBuffer(aInputStream, &dest, aCount, aWritten);
1598
NS_ENSURE_SUCCESS(rv, rv);
1599
1600
if ((uint64_t)aCount > *aWritten) {
1601
aDest.Truncate(*aWritten);
1602
}
1603
1604
return NS_OK;
1605
}
1606
1607
// If the size is unknown, BufferWriter will allocate the buffer.
1608
void* dest = nullptr;
1609
nsresult rv =
1610
NS_ReadInputStreamToBuffer(aInputStream, &dest, aCount, aWritten);
1611
MOZ_ASSERT_IF(NS_FAILED(rv), dest == nullptr);
1612
NS_ENSURE_SUCCESS(rv, rv);
1613
1614
if (!dest) {
1615
MOZ_ASSERT(*aWritten == 0);
1616
aDest.Truncate();
1617
return NS_OK;
1618
}
1619
1620
aDest.Adopt(reinterpret_cast<char*>(dest), *aWritten);
1621
return NS_OK;
1622
}
1623
1624
nsresult NS_NewURI(nsIURI** result, const nsACString& spec,
1625
NotNull<const Encoding*> encoding,
1626
nsIURI* baseURI /* = nullptr */) {
1627
nsAutoCString charset;
1628
encoding->Name(charset);
1629
return NS_NewURI(result, spec, charset.get(), baseURI);
1630
}
1631
1632
nsresult NS_NewURI(nsIURI** result, const nsAString& aSpec,
1633
const char* charset /* = nullptr */,
1634
nsIURI* baseURI /* = nullptr */) {
1635
nsAutoCString spec;
1636
if (!AppendUTF16toUTF8(aSpec, spec, mozilla::fallible)) {
1637
return NS_ERROR_OUT_OF_MEMORY;
1638
}
1639
return NS_NewURI(result, spec, charset, baseURI);
1640
}
1641
1642
nsresult NS_NewURI(nsIURI** result, const nsAString& aSpec,
1643
NotNull<const Encoding*> encoding,
1644
nsIURI* baseURI /* = nullptr */) {
1645
nsAutoCString spec;
1646
if (!AppendUTF16toUTF8(aSpec, spec, mozilla::fallible)) {
1647
return NS_ERROR_OUT_OF_MEMORY;
1648
}
1649
return NS_NewURI(result, spec, encoding, baseURI);
1650
}
1651
1652
nsresult NS_NewURI(nsIURI** result, const char* spec,
1653
nsIURI* baseURI /* = nullptr */) {
1654
return NS_NewURI(result, nsDependentCString(spec), nullptr, baseURI);
1655
}
1656
1657
static nsresult NewStandardURI(const nsACString& aSpec, const char* aCharset,
1658
nsIURI* aBaseURI, int32_t aDefaultPort,
1659
nsIURI** aURI) {
1660
nsCOMPtr<nsIURI> base(aBaseURI);
1661
return NS_MutateURI(new nsStandardURL::Mutator())
1662
.Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
1663
nsIStandardURL::URLTYPE_AUTHORITY, aDefaultPort,
1664
nsCString(aSpec), aCharset, base, nullptr))
1665
.Finalize(aURI);
1666
}
1667
1668
extern MOZ_THREAD_LOCAL(uint32_t) gTlsURLRecursionCount;
1669
1670
template <typename T>
1671
class TlsAutoIncrement {
1672
public:
1673
explicit TlsAutoIncrement(T& var) : mVar(var) {
1674
mValue = mVar.get();
1675
mVar.set(mValue + 1);
1676
}
1677
~TlsAutoIncrement() {
1678
typename T::Type value = mVar.get();
1679
MOZ_ASSERT(value == mValue + 1);
1680
mVar.set(value - 1);
1681
}
1682
1683
typename T::Type value() { return mValue; }
1684
1685
private:
1686
typename T::Type mValue;
1687
T& mVar;
1688
};
1689
1690
nsresult NS_NewURI(nsIURI** aURI, const nsACString& aSpec,
1691
const char* aCharset /* = nullptr */,
1692
nsIURI* aBaseURI /* = nullptr */) {
1693
TlsAutoIncrement<decltype(gTlsURLRecursionCount)> inc(gTlsURLRecursionCount);
1694
if (inc.value() >= MAX_RECURSION_COUNT) {
1695
return NS_ERROR_MALFORMED_URI;
1696
}
1697
1698
nsAutoCString scheme;
1699
nsresult rv = net_ExtractURLScheme(aSpec, scheme);
1700
if (NS_FAILED(rv)) {
1701
// then aSpec is relative
1702
if (!aBaseURI) {
1703
return NS_ERROR_MALFORMED_URI;
1704
}
1705
1706
if (!aSpec.IsEmpty() && aSpec[0] == '#') {
1707
// Looks like a reference instead of a fully-specified URI.
1708
// --> initialize |uri| as a clone of |aBaseURI|, with ref appended.
1709
return NS_GetURIWithNewRef(aBaseURI, aSpec, aURI);
1710
}
1711
1712
rv = aBaseURI->GetScheme(scheme);
1713
if (NS_FAILED(rv)) return rv;
1714
}
1715
1716
if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("ws")) {
1717
return NewStandardURI(aSpec, aCharset, aBaseURI, NS_HTTP_DEFAULT_PORT,
1718
aURI);
1719
}
1720
if (scheme.EqualsLiteral("https") || scheme.EqualsLiteral("wss")) {
1721
return NewStandardURI(aSpec, aCharset, aBaseURI, NS_HTTPS_DEFAULT_PORT,
1722
aURI);
1723
}
1724
if (scheme.EqualsLiteral("ftp")) {
1725
return NewStandardURI(aSpec, aCharset, aBaseURI, 21, aURI);
1726
}
1727
if (scheme.EqualsLiteral("ssh")) {
1728
return NewStandardURI(aSpec, aCharset, aBaseURI, 22, aURI);
1729
}
1730
1731
if (scheme.EqualsLiteral("file")) {
1732
nsAutoCString buf(aSpec);
1733
#if defined(XP_WIN)
1734
buf.Truncate();
1735
if (!net_NormalizeFileURL(aSpec, buf)) {
1736
buf = aSpec;
1737
}
1738
#endif
1739
1740
nsCOMPtr<nsIURI> base(aBaseURI);
1741
return NS_MutateURI(new nsStandardURL::Mutator())
1742
.Apply(NS_MutatorMethod(&nsIFileURLMutator::MarkFileURL))
1743
.Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
1744
nsIStandardURL::URLTYPE_NO_AUTHORITY, -1, buf,
1745
aCharset, base, nullptr))
1746
.Finalize(aURI);
1747
}
1748
1749
if (scheme.EqualsLiteral("data")) {
1750
return nsDataHandler::CreateNewURI(aSpec, aCharset, aBaseURI, aURI);