Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/base/nsNetUtil.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* vim:set ts=4 sw=4 sts=4 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/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"
24
#include "nsHttp.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 "nsIDocument.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"
44
#include "nsINode.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 "nsIRequestObserverProxy.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 "nsISyncStreamListener.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"
70
#include "plstr.h"
71
#include "nsINestedURI.h"
72
#include "mozilla/dom/nsCSPUtils.h"
73
#include "mozilla/dom/BlobURLProtocolHandler.h"
74
#include "mozilla/net/HttpBaseChannel.h"
75
#include "nsIScriptError.h"
76
#include "nsISiteSecurityService.h"
77
#include "nsHttpHandler.h"
78
#include "nsNSSComponent.h"
79
#include "nsIRedirectHistoryEntry.h"
80
#include "nsICertBlocklist.h"
81
#include "nsICertOverrideService.h"
82
#include "nsQueryObject.h"
83
#include "mozIThirdPartyUtil.h"
84
#include "../mime/nsMIMEHeaderParamImpl.h"
85
86
#include <limits>
87
88
using namespace mozilla;
89
using namespace mozilla::net;
90
using mozilla::dom::BlobURLProtocolHandler;
91
using mozilla::dom::ClientInfo;
92
using mozilla::dom::PerformanceStorage;
93
using mozilla::dom::ServiceWorkerDescriptor;
94
95
0
#define DEFAULT_RP 3
96
0
#define DEFAULT_PRIVATE_RP 2
97
98
static uint32_t sDefaultRp = DEFAULT_RP;
99
static uint32_t defaultPrivateRp = DEFAULT_PRIVATE_RP;
100
101
already_AddRefed<nsIIOService>
102
do_GetIOService(nsresult *error /* = 0 */)
103
3.05M
{
104
3.05M
    nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
105
3.05M
    if (error)
106
3.05M
        *error = io ? NS_OK : NS_ERROR_FAILURE;
107
3.05M
    return io.forget();
108
3.05M
}
109
110
nsresult
111
NS_NewLocalFileInputStream(nsIInputStream **result,
112
                           nsIFile         *file,
113
                           int32_t          ioFlags       /* = -1 */,
114
                           int32_t          perm          /* = -1 */,
115
                           int32_t          behaviorFlags /* = 0 */)
116
0
{
117
0
    nsresult rv;
118
0
    nsCOMPtr<nsIFileInputStream> in =
119
0
        do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv);
120
0
    if (NS_SUCCEEDED(rv)) {
121
0
        rv = in->Init(file, ioFlags, perm, behaviorFlags);
122
0
        if (NS_SUCCEEDED(rv))
123
0
            in.forget(result);
124
0
    }
125
0
    return rv;
126
0
}
127
128
nsresult
129
NS_NewLocalFileOutputStream(nsIOutputStream **result,
130
                            nsIFile          *file,
131
                            int32_t           ioFlags       /* = -1 */,
132
                            int32_t           perm          /* = -1 */,
133
                            int32_t           behaviorFlags /* = 0 */)
134
0
{
135
0
    nsresult rv;
136
0
    nsCOMPtr<nsIFileOutputStream> out =
137
0
        do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
138
0
    if (NS_SUCCEEDED(rv)) {
139
0
        rv = out->Init(file, ioFlags, perm, behaviorFlags);
140
0
        if (NS_SUCCEEDED(rv))
141
0
            out.forget(result);
142
0
    }
143
0
    return rv;
144
0
}
145
146
nsresult
147
net_EnsureIOService(nsIIOService **ios, nsCOMPtr<nsIIOService> &grip)
148
3.05M
{
149
3.05M
    nsresult rv = NS_OK;
150
3.05M
    if (!*ios) {
151
3.05M
        grip = do_GetIOService(&rv);
152
3.05M
        *ios = grip;
153
3.05M
    }
154
3.05M
    return rv;
155
3.05M
}
156
157
nsresult
158
NS_NewFileURI(nsIURI **result,
159
              nsIFile *spec,
160
              nsIIOService *ioService /* = nullptr */)     // pass in nsIIOService to optimize callers
161
0
{
162
0
    nsresult rv;
163
0
    nsCOMPtr<nsIIOService> grip;
164
0
    rv = net_EnsureIOService(&ioService, grip);
165
0
    if (ioService)
166
0
        rv = ioService->NewFileURI(spec, result);
167
0
    return rv;
168
0
}
169
170
nsresult
171
NS_GetURIWithNewRef(nsIURI* aInput,
172
                    const nsACString& aRef,
173
                    nsIURI** aOutput)
174
2.32k
{
175
2.32k
  if (NS_WARN_IF(!aInput || !aOutput)) {
176
0
    return NS_ERROR_INVALID_ARG;
177
0
  }
178
2.32k
179
2.32k
  bool hasRef;
180
2.32k
  nsresult rv = aInput->GetHasRef(&hasRef);
181
2.32k
182
2.32k
  nsAutoCString ref;
183
2.32k
  if (NS_SUCCEEDED(rv)) {
184
2.32k
    rv = aInput->GetRef(ref);
185
2.32k
  }
186
2.32k
187
2.32k
  // If the ref is already equal to the new ref, we do not need to do anything.
188
2.32k
  // Also, if the GetRef failed (it could return NS_ERROR_NOT_IMPLEMENTED)
189
2.32k
  // we can assume SetRef would fail as well, so returning the original
190
2.32k
  // URI is OK.
191
2.32k
  if (NS_FAILED(rv) ||
192
2.32k
      (!hasRef && aRef.IsEmpty()) ||
193
2.32k
      (!aRef.IsEmpty() && aRef == ref)) {
194
0
    nsCOMPtr<nsIURI> uri = aInput;
195
0
    uri.forget(aOutput);
196
0
    return NS_OK;
197
0
  }
198
2.32k
199
2.32k
  return NS_MutateURI(aInput)
200
2.32k
           .SetRef(aRef)
201
2.32k
           .Finalize(aOutput);
202
2.32k
}
203
204
nsresult
205
NS_GetURIWithoutRef(nsIURI* aInput,
206
                    nsIURI** aOutput)
207
0
{
208
0
  return NS_GetURIWithNewRef(aInput, EmptyCString(), aOutput);
209
0
}
210
211
nsresult
212
NS_NewChannelInternal(nsIChannel           **outChannel,
213
                      nsIURI                *aUri,
214
                      nsILoadInfo           *aLoadInfo,
215
                      PerformanceStorage    *aPerformanceStorage /* = nullptr */,
216
                      nsILoadGroup          *aLoadGroup /* = nullptr */,
217
                      nsIInterfaceRequestor *aCallbacks /* = nullptr */,
218
                      nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
219
                      nsIIOService          *aIoService /* = nullptr */)
220
4
{
221
4
  // NS_NewChannelInternal is mostly called for channel redirects. We should allow
222
4
  // the creation of a channel even if the original channel did not have a loadinfo
223
4
  // attached.
224
4
  NS_ENSURE_ARG_POINTER(outChannel);
225
4
226
4
  nsCOMPtr<nsIIOService> grip;
227
4
  nsresult rv = net_EnsureIOService(&aIoService, grip);
228
4
  NS_ENSURE_SUCCESS(rv, rv);
229
4
230
4
  nsCOMPtr<nsIChannel> channel;
231
4
  rv = aIoService->NewChannelFromURIWithLoadInfo(
232
4
         aUri,
233
4
         aLoadInfo,
234
4
         getter_AddRefs(channel));
235
4
  NS_ENSURE_SUCCESS(rv, rv);
236
4
237
4
  if (aLoadGroup) {
238
0
    rv = channel->SetLoadGroup(aLoadGroup);
239
0
    NS_ENSURE_SUCCESS(rv, rv);
240
0
  }
241
4
242
4
  if (aCallbacks) {
243
0
    rv = channel->SetNotificationCallbacks(aCallbacks);
244
0
    NS_ENSURE_SUCCESS(rv, rv);
245
0
  }
246
4
247
#ifdef DEBUG
248
  nsLoadFlags channelLoadFlags = 0;
249
  channel->GetLoadFlags(&channelLoadFlags);
250
  // Will be removed when we remove LOAD_REPLACE altogether
251
  // This check is trying to catch protocol handlers that still
252
  // try to set the LOAD_REPLACE flag.
253
  MOZ_DIAGNOSTIC_ASSERT(!(channelLoadFlags & nsIChannel::LOAD_REPLACE));
254
#endif
255
256
4
  if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
257
0
    rv = channel->SetLoadFlags(aLoadFlags);
258
0
    NS_ENSURE_SUCCESS(rv, rv);
259
0
  }
260
4
261
4
  if (aPerformanceStorage) {
262
0
    nsCOMPtr<nsILoadInfo> loadInfo;
263
0
    rv = channel->GetLoadInfo(getter_AddRefs(loadInfo));
264
0
    NS_ENSURE_SUCCESS(rv, rv);
265
0
266
0
    loadInfo->SetPerformanceStorage(aPerformanceStorage);
267
0
  }
268
4
269
4
  channel.forget(outChannel);
270
4
  return NS_OK;
271
4
}
272
273
namespace {
274
275
void
276
AssertLoadingPrincipalAndClientInfoMatch(nsIPrincipal* aLoadingPrincipal,
277
                                         const ClientInfo& aLoadingClientInfo,
278
                                         nsContentPolicyType aType)
279
0
{
280
0
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
281
0
  // Verify that the provided loading ClientInfo matches the loading
282
0
  // principal.  Unfortunately we can't just use nsIPrincipal::Equals() here
283
0
  // because of some corner cases:
284
0
  //
285
0
  //  1. Worker debugger scripts want to use a system loading principal for
286
0
  //     worker scripts with a content principal.  We exempt these from this
287
0
  //     check.
288
0
  //  2. Null principals currently require exact object identity for
289
0
  //     nsIPrincipal::Equals() to return true.  This doesn't work here because
290
0
  //     ClientInfo::GetPrincipal() uses PrincipalInfoToPrincipal() to allocate
291
0
  //     a new object.  To work around this we compare the principal origin
292
0
  //     string itself.  If bug 1431771 is fixed then we could switch to
293
0
  //     Equals().
294
0
295
0
  // Allow worker debugger to load with a system principal.
296
0
  if (aLoadingPrincipal->GetIsSystemPrincipal() &&
297
0
      (aType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
298
0
       aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER ||
299
0
       aType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER ||
300
0
       aType == nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS)) {
301
0
    return;
302
0
  }
303
0
304
0
  // Perform a fast comparison for most principal checks.
305
0
  nsCOMPtr<nsIPrincipal> clientPrincipal(aLoadingClientInfo.GetPrincipal());
306
0
  if (aLoadingPrincipal->Equals(clientPrincipal)) {
307
0
    return;
308
0
  }
309
0
310
0
  // Fall back to a slower origin equality test to support null principals.
311
0
  nsAutoCString loadingOrigin;
312
0
  MOZ_ALWAYS_SUCCEEDS(aLoadingPrincipal->GetOrigin(loadingOrigin));
313
0
314
0
  nsAutoCString clientOrigin;
315
0
  MOZ_ALWAYS_SUCCEEDS(clientPrincipal->GetOrigin(clientOrigin));
316
0
317
0
  MOZ_DIAGNOSTIC_ASSERT(loadingOrigin == clientOrigin);
318
0
#endif
319
0
}
320
321
}
322
323
nsresult
324
NS_NewChannel(nsIChannel           **outChannel,
325
              nsIURI                *aUri,
326
              nsIPrincipal          *aLoadingPrincipal,
327
              nsSecurityFlags        aSecurityFlags,
328
              nsContentPolicyType    aContentPolicyType,
329
              PerformanceStorage    *aPerformanceStorage /* nullptr */,
330
              nsILoadGroup          *aLoadGroup /* = nullptr */,
331
              nsIInterfaceRequestor *aCallbacks /* = nullptr */,
332
              nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
333
              nsIIOService          *aIoService /* = nullptr */)
334
5
{
335
5
  return NS_NewChannelInternal(outChannel,
336
5
                               aUri,
337
5
                               nullptr, // aLoadingNode,
338
5
                               aLoadingPrincipal,
339
5
                               nullptr, // aTriggeringPrincipal
340
5
                               Maybe<ClientInfo>(),
341
5
                               Maybe<ServiceWorkerDescriptor>(),
342
5
                               aSecurityFlags,
343
5
                               aContentPolicyType,
344
5
                               aPerformanceStorage,
345
5
                               aLoadGroup,
346
5
                               aCallbacks,
347
5
                               aLoadFlags,
348
5
                               aIoService);
349
5
}
350
351
nsresult
352
NS_NewChannel(nsIChannel           **outChannel,
353
              nsIURI                *aUri,
354
              nsIPrincipal          *aLoadingPrincipal,
355
              const ClientInfo      &aLoadingClientInfo,
356
              const Maybe<ServiceWorkerDescriptor>& aController,
357
              nsSecurityFlags        aSecurityFlags,
358
              nsContentPolicyType    aContentPolicyType,
359
              PerformanceStorage    *aPerformanceStorage /* nullptr */,
360
              nsILoadGroup          *aLoadGroup /* = nullptr */,
361
              nsIInterfaceRequestor *aCallbacks /* = nullptr */,
362
              nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
363
              nsIIOService          *aIoService /* = nullptr */)
364
0
{
365
0
  AssertLoadingPrincipalAndClientInfoMatch(aLoadingPrincipal,
366
0
                                           aLoadingClientInfo,
367
0
                                           aContentPolicyType);
368
0
369
0
  Maybe<ClientInfo> loadingClientInfo;
370
0
  loadingClientInfo.emplace(aLoadingClientInfo);
371
0
372
0
  return NS_NewChannelInternal(outChannel,
373
0
                               aUri,
374
0
                               nullptr, // aLoadingNode,
375
0
                               aLoadingPrincipal,
376
0
                               nullptr, // aTriggeringPrincipal
377
0
                               loadingClientInfo,
378
0
                               aController,
379
0
                               aSecurityFlags,
380
0
                               aContentPolicyType,
381
0
                               aPerformanceStorage,
382
0
                               aLoadGroup,
383
0
                               aCallbacks,
384
0
                               aLoadFlags,
385
0
                               aIoService);
386
0
}
387
388
nsresult
389
NS_NewChannelInternal(nsIChannel           **outChannel,
390
                      nsIURI                *aUri,
391
                      nsINode               *aLoadingNode,
392
                      nsIPrincipal          *aLoadingPrincipal,
393
                      nsIPrincipal          *aTriggeringPrincipal,
394
                      const Maybe<ClientInfo>& aLoadingClientInfo,
395
                      const Maybe<ServiceWorkerDescriptor>& aController,
396
                      nsSecurityFlags        aSecurityFlags,
397
                      nsContentPolicyType    aContentPolicyType,
398
                      PerformanceStorage    *aPerformanceStorage /* nullptr */,
399
                      nsILoadGroup          *aLoadGroup /* = nullptr */,
400
                      nsIInterfaceRequestor *aCallbacks /* = nullptr */,
401
                      nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
402
                      nsIIOService          *aIoService /* = nullptr */)
403
5
{
404
5
  NS_ENSURE_ARG_POINTER(outChannel);
405
5
406
5
  nsCOMPtr<nsIIOService> grip;
407
5
  nsresult rv = net_EnsureIOService(&aIoService, grip);
408
5
  NS_ENSURE_SUCCESS(rv, rv);
409
5
410
5
  nsCOMPtr<nsIChannel> channel;
411
5
  rv = aIoService->NewChannelFromURIWithClientAndController(
412
5
         aUri,
413
5
         aLoadingNode,
414
5
         aLoadingPrincipal,
415
5
         aTriggeringPrincipal,
416
5
         aLoadingClientInfo,
417
5
         aController,
418
5
         aSecurityFlags,
419
5
         aContentPolicyType,
420
5
         getter_AddRefs(channel));
421
5
  if (NS_FAILED(rv)) {
422
0
    return rv;
423
0
  }
424
5
425
5
  if (aLoadGroup) {
426
0
    rv = channel->SetLoadGroup(aLoadGroup);
427
0
    NS_ENSURE_SUCCESS(rv, rv);
428
0
  }
429
5
430
5
  if (aCallbacks) {
431
0
    rv = channel->SetNotificationCallbacks(aCallbacks);
432
0
    NS_ENSURE_SUCCESS(rv, rv);
433
0
  }
434
5
435
#ifdef DEBUG
436
  nsLoadFlags channelLoadFlags = 0;
437
  channel->GetLoadFlags(&channelLoadFlags);
438
  // Will be removed when we remove LOAD_REPLACE altogether
439
  // This check is trying to catch protocol handlers that still
440
  // try to set the LOAD_REPLACE flag.
441
  MOZ_DIAGNOSTIC_ASSERT(!(channelLoadFlags & nsIChannel::LOAD_REPLACE));
442
#endif
443
444
5
  if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
445
0
    rv = channel->SetLoadFlags(aLoadFlags);
446
0
    NS_ENSURE_SUCCESS(rv, rv);
447
0
  }
448
5
449
5
  if (aPerformanceStorage) {
450
0
    nsCOMPtr<nsILoadInfo> loadInfo;
451
0
    rv = channel->GetLoadInfo(getter_AddRefs(loadInfo));
452
0
    NS_ENSURE_SUCCESS(rv, rv);
453
0
454
0
    loadInfo->SetPerformanceStorage(aPerformanceStorage);
455
0
  }
456
5
457
5
  channel.forget(outChannel);
458
5
  return NS_OK;
459
5
}
460
461
nsresult /*NS_NewChannelWithNodeAndTriggeringPrincipal */
462
NS_NewChannelWithTriggeringPrincipal(nsIChannel           **outChannel,
463
                                     nsIURI                *aUri,
464
                                     nsINode               *aLoadingNode,
465
                                     nsIPrincipal          *aTriggeringPrincipal,
466
                                     nsSecurityFlags        aSecurityFlags,
467
                                     nsContentPolicyType    aContentPolicyType,
468
                                     PerformanceStorage    *aPerformanceStorage /* = nullptr */,
469
                                     nsILoadGroup          *aLoadGroup /* = nullptr */,
470
                                     nsIInterfaceRequestor *aCallbacks /* = nullptr */,
471
                                     nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
472
                                     nsIIOService          *aIoService /* = nullptr */)
473
0
{
474
0
  MOZ_ASSERT(aLoadingNode);
475
0
  NS_ASSERTION(aTriggeringPrincipal, "Can not create channel without a triggering Principal!");
476
0
  return NS_NewChannelInternal(outChannel,
477
0
                               aUri,
478
0
                               aLoadingNode,
479
0
                               aLoadingNode->NodePrincipal(),
480
0
                               aTriggeringPrincipal,
481
0
                               Maybe<ClientInfo>(),
482
0
                               Maybe<ServiceWorkerDescriptor>(),
483
0
                               aSecurityFlags,
484
0
                               aContentPolicyType,
485
0
                               aPerformanceStorage,
486
0
                               aLoadGroup,
487
0
                               aCallbacks,
488
0
                               aLoadFlags,
489
0
                               aIoService);
490
0
}
491
492
// See NS_NewChannelInternal for usage and argument description
493
nsresult
494
NS_NewChannelWithTriggeringPrincipal(nsIChannel           **outChannel,
495
                                     nsIURI                *aUri,
496
                                     nsIPrincipal          *aLoadingPrincipal,
497
                                     nsIPrincipal          *aTriggeringPrincipal,
498
                                     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
0
{
506
0
  NS_ASSERTION(aLoadingPrincipal, "Can not create channel without a loading Principal!");
507
0
  return NS_NewChannelInternal(outChannel,
508
0
                               aUri,
509
0
                               nullptr, // aLoadingNode
510
0
                               aLoadingPrincipal,
511
0
                               aTriggeringPrincipal,
512
0
                               Maybe<ClientInfo>(),
513
0
                               Maybe<ServiceWorkerDescriptor>(),
514
0
                               aSecurityFlags,
515
0
                               aContentPolicyType,
516
0
                               aPerformanceStorage,
517
0
                               aLoadGroup,
518
0
                               aCallbacks,
519
0
                               aLoadFlags,
520
0
                               aIoService);
521
0
}
522
523
// See NS_NewChannelInternal for usage and argument description
524
nsresult
525
NS_NewChannelWithTriggeringPrincipal(nsIChannel           **outChannel,
526
                                     nsIURI                *aUri,
527
                                     nsIPrincipal          *aLoadingPrincipal,
528
                                     nsIPrincipal          *aTriggeringPrincipal,
529
                                     const ClientInfo      &aLoadingClientInfo,
530
                                     const Maybe<ServiceWorkerDescriptor>& aController,
531
                                     nsSecurityFlags        aSecurityFlags,
532
                                     nsContentPolicyType    aContentPolicyType,
533
                                     PerformanceStorage    *aPerformanceStorage /* = nullptr */,
534
                                     nsILoadGroup          *aLoadGroup /* = nullptr */,
535
                                     nsIInterfaceRequestor *aCallbacks /* = nullptr */,
536
                                     nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
537
                                     nsIIOService          *aIoService /* = nullptr */)
538
0
{
539
0
  AssertLoadingPrincipalAndClientInfoMatch(aLoadingPrincipal,
540
0
                                           aLoadingClientInfo,
541
0
                                           aContentPolicyType);
542
0
543
0
  Maybe<ClientInfo> loadingClientInfo;
544
0
  loadingClientInfo.emplace(aLoadingClientInfo);
545
0
546
0
  return NS_NewChannelInternal(outChannel,
547
0
                               aUri,
548
0
                               nullptr, // aLoadingNode
549
0
                               aLoadingPrincipal,
550
0
                               aTriggeringPrincipal,
551
0
                               loadingClientInfo,
552
0
                               aController,
553
0
                               aSecurityFlags,
554
0
                               aContentPolicyType,
555
0
                               aPerformanceStorage,
556
0
                               aLoadGroup,
557
0
                               aCallbacks,
558
0
                               aLoadFlags,
559
0
                               aIoService);
560
0
}
561
562
nsresult
563
NS_NewChannel(nsIChannel           **outChannel,
564
              nsIURI                *aUri,
565
              nsINode               *aLoadingNode,
566
              nsSecurityFlags        aSecurityFlags,
567
              nsContentPolicyType    aContentPolicyType,
568
              PerformanceStorage    *aPerformanceStorage /* = nullptr */,
569
              nsILoadGroup          *aLoadGroup /* = nullptr */,
570
              nsIInterfaceRequestor *aCallbacks /* = nullptr */,
571
              nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
572
              nsIIOService          *aIoService /* = nullptr */)
573
0
{
574
0
  NS_ASSERTION(aLoadingNode, "Can not create channel without a loading Node!");
575
0
  return NS_NewChannelInternal(outChannel,
576
0
                               aUri,
577
0
                               aLoadingNode,
578
0
                               aLoadingNode->NodePrincipal(),
579
0
                               nullptr, // aTriggeringPrincipal
580
0
                               Maybe<ClientInfo>(),
581
0
                               Maybe<ServiceWorkerDescriptor>(),
582
0
                               aSecurityFlags,
583
0
                               aContentPolicyType,
584
0
                               aPerformanceStorage,
585
0
                               aLoadGroup,
586
0
                               aCallbacks,
587
0
                               aLoadFlags,
588
0
                               aIoService);
589
0
}
590
591
nsresult
592
NS_GetIsDocumentChannel(nsIChannel * aChannel, bool *aIsDocument)
593
0
{
594
0
  // Check if this channel is going to be used to create a document. If it has
595
0
  // LOAD_DOCUMENT_URI set it is trivially creating a document. If
596
0
  // LOAD_HTML_OBJECT_DATA is set it may or may not be used to create a
597
0
  // document, depending on its MIME type.
598
0
599
0
  if (!aChannel || !aIsDocument) {
600
0
      return NS_ERROR_NULL_POINTER;
601
0
  }
602
0
  *aIsDocument = false;
603
0
  nsLoadFlags loadFlags;
604
0
  nsresult rv = aChannel->GetLoadFlags(&loadFlags);
605
0
  if (NS_FAILED(rv)) {
606
0
      return rv;
607
0
  }
608
0
  if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
609
0
      *aIsDocument = true;
610
0
      return NS_OK;
611
0
  }
612
0
  if (!(loadFlags & nsIRequest::LOAD_HTML_OBJECT_DATA)) {
613
0
      *aIsDocument = false;
614
0
      return NS_OK;
615
0
  }
616
0
  nsAutoCString mimeType;
617
0
  rv = aChannel->GetContentType(mimeType);
618
0
  if (NS_FAILED(rv)) {
619
0
      return rv;
620
0
  }
621
0
  if (nsContentUtils::HtmlObjectContentTypeForMIMEType(mimeType, false, nullptr) ==
622
0
      nsIObjectLoadingContent::TYPE_DOCUMENT) {
623
0
      *aIsDocument = true;
624
0
      return NS_OK;
625
0
  }
626
0
  *aIsDocument = false;
627
0
  return NS_OK;
628
0
}
629
630
nsresult
631
NS_MakeAbsoluteURI(nsACString       &result,
632
                   const nsACString &spec,
633
                   nsIURI           *baseURI)
634
0
{
635
0
    nsresult rv;
636
0
    if (!baseURI) {
637
0
        NS_WARNING("It doesn't make sense to not supply a base URI");
638
0
        result = spec;
639
0
        rv = NS_OK;
640
0
    }
641
0
    else if (spec.IsEmpty())
642
0
        rv = baseURI->GetSpec(result);
643
0
    else
644
0
        rv = baseURI->Resolve(spec, result);
645
0
    return rv;
646
0
}
647
648
nsresult
649
NS_MakeAbsoluteURI(char        **result,
650
                   const char   *spec,
651
                   nsIURI       *baseURI)
652
0
{
653
0
    nsresult rv;
654
0
    nsAutoCString resultBuf;
655
0
    rv = NS_MakeAbsoluteURI(resultBuf, nsDependentCString(spec), baseURI);
656
0
    if (NS_SUCCEEDED(rv)) {
657
0
        *result = ToNewCString(resultBuf);
658
0
        if (!*result)
659
0
            rv = NS_ERROR_OUT_OF_MEMORY;
660
0
    }
661
0
    return rv;
662
0
}
663
664
nsresult
665
NS_MakeAbsoluteURI(nsAString       &result,
666
                   const nsAString &spec,
667
                   nsIURI          *baseURI)
668
0
{
669
0
    nsresult rv;
670
0
    if (!baseURI) {
671
0
        NS_WARNING("It doesn't make sense to not supply a base URI");
672
0
        result = spec;
673
0
        rv = NS_OK;
674
0
    }
675
0
    else {
676
0
        nsAutoCString resultBuf;
677
0
        if (spec.IsEmpty())
678
0
            rv = baseURI->GetSpec(resultBuf);
679
0
        else
680
0
            rv = baseURI->Resolve(NS_ConvertUTF16toUTF8(spec), resultBuf);
681
0
        if (NS_SUCCEEDED(rv))
682
0
            CopyUTF8toUTF16(resultBuf, result);
683
0
    }
684
0
    return rv;
685
0
}
686
687
int32_t
688
NS_GetDefaultPort(const char *scheme,
689
                  nsIIOService *ioService /* = nullptr */)
690
0
{
691
0
  nsresult rv;
692
0
693
0
  // Getting the default port through the protocol handler has a lot of XPCOM
694
0
  // overhead involved.  We optimize the protocols that matter for Web pages
695
0
  // (HTTP and HTTPS) by hardcoding their default ports here.
696
0
  if (strncmp(scheme, "http", 4) == 0) {
697
0
    if (scheme[4] == 's' && scheme[5] == '\0') {
698
0
      return 443;
699
0
    }
700
0
    if (scheme[4] == '\0') {
701
0
      return 80;
702
0
    }
703
0
  }
704
0
705
0
  nsCOMPtr<nsIIOService> grip;
706
0
  net_EnsureIOService(&ioService, grip);
707
0
  if (!ioService)
708
0
      return -1;
709
0
710
0
  nsCOMPtr<nsIProtocolHandler> handler;
711
0
  rv = ioService->GetProtocolHandler(scheme, getter_AddRefs(handler));
712
0
  if (NS_FAILED(rv))
713
0
    return -1;
714
0
  int32_t port;
715
0
  rv = handler->GetDefaultPort(&port);
716
0
  return NS_SUCCEEDED(rv) ? port : -1;
717
0
}
718
719
/**
720
 * This function is a helper function to apply the ToAscii conversion
721
 * to a string
722
 */
723
bool
724
NS_StringToACE(const nsACString &idn, nsACString &result)
725
0
{
726
0
  nsCOMPtr<nsIIDNService> idnSrv = do_GetService(NS_IDNSERVICE_CONTRACTID);
727
0
  if (!idnSrv)
728
0
    return false;
729
0
  nsresult rv = idnSrv->ConvertUTF8toACE(idn, result);
730
0
  if (NS_FAILED(rv))
731
0
    return false;
732
0
733
0
  return true;
734
0
}
735
736
int32_t
737
NS_GetRealPort(nsIURI *aURI)
738
0
{
739
0
    int32_t port;
740
0
    nsresult rv = aURI->GetPort(&port);
741
0
    if (NS_FAILED(rv))
742
0
        return -1;
743
0
744
0
    if (port != -1)
745
0
        return port; // explicitly specified
746
0
747
0
    // Otherwise, we have to get the default port from the protocol handler
748
0
749
0
    // Need the scheme first
750
0
    nsAutoCString scheme;
751
0
    rv = aURI->GetScheme(scheme);
752
0
    if (NS_FAILED(rv))
753
0
        return -1;
754
0
755
0
    return NS_GetDefaultPort(scheme.get());
756
0
}
757
758
nsresult
759
NS_NewInputStreamChannelInternal(nsIChannel** outChannel,
760
                                 nsIURI* aUri,
761
                                 already_AddRefed<nsIInputStream> aStream,
762
                                 const nsACString& aContentType,
763
                                 const nsACString& aContentCharset,
764
                                 nsILoadInfo* aLoadInfo)
765
0
{
766
0
  nsresult rv;
767
0
  nsCOMPtr<nsIInputStreamChannel> isc =
768
0
    do_CreateInstance(NS_INPUTSTREAMCHANNEL_CONTRACTID, &rv);
769
0
  NS_ENSURE_SUCCESS(rv, rv);
770
0
  rv = isc->SetURI(aUri);
771
0
  NS_ENSURE_SUCCESS(rv, rv);
772
0
773
0
  nsCOMPtr<nsIInputStream> stream = std::move(aStream);
774
0
  rv = isc->SetContentStream(stream);
775
0
  NS_ENSURE_SUCCESS(rv, rv);
776
0
777
0
  nsCOMPtr<nsIChannel> channel = do_QueryInterface(isc, &rv);
778
0
  NS_ENSURE_SUCCESS(rv, rv);
779
0
780
0
  if (!aContentType.IsEmpty()) {
781
0
    rv = channel->SetContentType(aContentType);
782
0
    NS_ENSURE_SUCCESS(rv, rv);
783
0
  }
784
0
785
0
  if (!aContentCharset.IsEmpty()) {
786
0
    rv = channel->SetContentCharset(aContentCharset);
787
0
    NS_ENSURE_SUCCESS(rv, rv);
788
0
  }
789
0
790
0
  channel->SetLoadInfo(aLoadInfo);
791
0
792
0
  // If we're sandboxed, make sure to clear any owner the channel
793
0
  // might already have.
794
0
  if (aLoadInfo && aLoadInfo->GetLoadingSandboxed()) {
795
0
    channel->SetOwner(nullptr);
796
0
  }
797
0
798
0
  channel.forget(outChannel);
799
0
  return NS_OK;
800
0
}
801
802
nsresult
803
NS_NewInputStreamChannelInternal(nsIChannel** outChannel,
804
                                 nsIURI* aUri,
805
                                 already_AddRefed<nsIInputStream> aStream,
806
                                 const nsACString& aContentType,
807
                                 const nsACString& aContentCharset,
808
                                 nsINode* aLoadingNode,
809
                                 nsIPrincipal* aLoadingPrincipal,
810
                                 nsIPrincipal* aTriggeringPrincipal,
811
                                 nsSecurityFlags aSecurityFlags,
812
                                 nsContentPolicyType aContentPolicyType)
813
0
{
814
0
  nsCOMPtr<nsILoadInfo> loadInfo =
815
0
    new mozilla::net::LoadInfo(aLoadingPrincipal,
816
0
                               aTriggeringPrincipal,
817
0
                               aLoadingNode,
818
0
                               aSecurityFlags,
819
0
                               aContentPolicyType);
820
0
  if (!loadInfo) {
821
0
    return NS_ERROR_UNEXPECTED;
822
0
  }
823
0
824
0
  nsCOMPtr<nsIInputStream> stream = std::move(aStream);
825
0
826
0
  return NS_NewInputStreamChannelInternal(outChannel,
827
0
                                          aUri,
828
0
                                          stream.forget(),
829
0
                                          aContentType,
830
0
                                          aContentCharset,
831
0
                                          loadInfo);
832
0
}
833
834
nsresult
835
NS_NewInputStreamChannel(nsIChannel** outChannel,
836
                         nsIURI* aUri,
837
                         already_AddRefed<nsIInputStream> aStream,
838
                         nsIPrincipal* aLoadingPrincipal,
839
                         nsSecurityFlags aSecurityFlags,
840
                         nsContentPolicyType aContentPolicyType,
841
                         const nsACString& aContentType    /* = EmptyCString() */,
842
                         const nsACString& aContentCharset /* = EmptyCString() */)
843
0
{
844
0
  nsCOMPtr<nsIInputStream> stream = aStream;
845
0
  return NS_NewInputStreamChannelInternal(outChannel,
846
0
                                          aUri,
847
0
                                          stream.forget(),
848
0
                                          aContentType,
849
0
                                          aContentCharset,
850
0
                                          nullptr, // aLoadingNode
851
0
                                          aLoadingPrincipal,
852
0
                                          nullptr, // aTriggeringPrincipal
853
0
                                          aSecurityFlags,
854
0
                                          aContentPolicyType);
855
0
}
856
857
nsresult
858
NS_NewInputStreamChannelInternal(nsIChannel        **outChannel,
859
                                 nsIURI             *aUri,
860
                                 const nsAString    &aData,
861
                                 const nsACString   &aContentType,
862
                                 nsILoadInfo        *aLoadInfo,
863
                                 bool                aIsSrcdocChannel /* = false */)
864
0
{
865
0
  nsresult rv;
866
0
  nsCOMPtr<nsIStringInputStream> stream;
867
0
  stream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
868
0
  NS_ENSURE_SUCCESS(rv, rv);
869
0
870
0
    uint32_t len;
871
0
    char* utf8Bytes = ToNewUTF8String(aData, &len);
872
0
    rv = stream->AdoptData(utf8Bytes, len);
873
0
874
0
  nsCOMPtr<nsIChannel> channel;
875
0
  rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
876
0
                                        aUri,
877
0
                                        stream.forget(),
878
0
                                        aContentType,
879
0
                                        NS_LITERAL_CSTRING("UTF-8"),
880
0
                                        aLoadInfo);
881
0
882
0
  NS_ENSURE_SUCCESS(rv, rv);
883
0
884
0
  if (aIsSrcdocChannel) {
885
0
    nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(channel);
886
0
    NS_ENSURE_TRUE(inStrmChan, NS_ERROR_FAILURE);
887
0
    inStrmChan->SetSrcdocData(aData);
888
0
  }
889
0
  channel.forget(outChannel);
890
0
  return NS_OK;
891
0
}
892
893
nsresult
894
NS_NewInputStreamChannelInternal(nsIChannel        **outChannel,
895
                                 nsIURI             *aUri,
896
                                 const nsAString    &aData,
897
                                 const nsACString   &aContentType,
898
                                 nsINode            *aLoadingNode,
899
                                 nsIPrincipal       *aLoadingPrincipal,
900
                                 nsIPrincipal       *aTriggeringPrincipal,
901
                                 nsSecurityFlags     aSecurityFlags,
902
                                 nsContentPolicyType aContentPolicyType,
903
                                 bool                aIsSrcdocChannel /* = false */)
904
0
{
905
0
  nsCOMPtr<nsILoadInfo> loadInfo =
906
0
      new mozilla::net::LoadInfo(aLoadingPrincipal, aTriggeringPrincipal,
907
0
                                 aLoadingNode, aSecurityFlags,
908
0
                                 aContentPolicyType);
909
0
  return NS_NewInputStreamChannelInternal(outChannel, aUri, aData, aContentType,
910
0
                                          loadInfo, aIsSrcdocChannel);
911
0
}
912
913
nsresult
914
NS_NewInputStreamChannel(nsIChannel        **outChannel,
915
                         nsIURI             *aUri,
916
                         const nsAString    &aData,
917
                         const nsACString   &aContentType,
918
                         nsIPrincipal       *aLoadingPrincipal,
919
                         nsSecurityFlags     aSecurityFlags,
920
                         nsContentPolicyType aContentPolicyType,
921
                         bool                aIsSrcdocChannel /* = false */)
922
0
{
923
0
  return NS_NewInputStreamChannelInternal(outChannel,
924
0
                                          aUri,
925
0
                                          aData,
926
0
                                          aContentType,
927
0
                                          nullptr, // aLoadingNode
928
0
                                          aLoadingPrincipal,
929
0
                                          nullptr, // aTriggeringPrincipal
930
0
                                          aSecurityFlags,
931
0
                                          aContentPolicyType,
932
0
                                          aIsSrcdocChannel);
933
0
}
934
935
nsresult
936
NS_NewInputStreamPump(nsIInputStreamPump** aResult,
937
                      already_AddRefed<nsIInputStream> aStream,
938
                      uint32_t aSegsize /* = 0 */,
939
                      uint32_t aSegcount /* = 0 */,
940
                      bool aCloseWhenDone /* = false */,
941
                      nsIEventTarget* aMainThreadTarget /* = nullptr */)
942
0
{
943
0
    nsCOMPtr<nsIInputStream> stream = std::move(aStream);
944
0
945
0
    nsresult rv;
946
0
    nsCOMPtr<nsIInputStreamPump> pump =
947
0
        do_CreateInstance(NS_INPUTSTREAMPUMP_CONTRACTID, &rv);
948
0
    if (NS_SUCCEEDED(rv)) {
949
0
        rv = pump->Init(stream, aSegsize, aSegcount, aCloseWhenDone,
950
0
                        aMainThreadTarget);
951
0
        if (NS_SUCCEEDED(rv)) {
952
0
            *aResult = nullptr;
953
0
            pump.swap(*aResult);
954
0
        }
955
0
    }
956
0
    return rv;
957
0
}
958
959
nsresult
960
NS_NewLoadGroup(nsILoadGroup      **result,
961
                nsIRequestObserver *obs)
962
3
{
963
3
    nsresult rv;
964
3
    nsCOMPtr<nsILoadGroup> group =
965
3
        do_CreateInstance(NS_LOADGROUP_CONTRACTID, &rv);
966
3
    if (NS_SUCCEEDED(rv)) {
967
3
        rv = group->SetGroupObserver(obs);
968
3
        if (NS_SUCCEEDED(rv)) {
969
3
            *result = nullptr;
970
3
            group.swap(*result);
971
3
        }
972
3
    }
973
3
    return rv;
974
3
}
975
976
bool NS_IsReasonableHTTPHeaderValue(const nsACString &aValue)
977
0
{
978
0
  return mozilla::net::nsHttp::IsReasonableHeaderValue(aValue);
979
0
}
980
981
bool NS_IsValidHTTPToken(const nsACString &aToken)
982
0
{
983
0
  return mozilla::net::nsHttp::IsValidToken(aToken);
984
0
}
985
986
void
987
NS_TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest)
988
0
{
989
0
  mozilla::net::nsHttp::TrimHTTPWhitespace(aSource, aDest);
990
0
}
991
992
nsresult
993
NS_NewLoadGroup(nsILoadGroup **aResult, nsIPrincipal *aPrincipal)
994
0
{
995
0
    using mozilla::LoadContext;
996
0
    nsresult rv;
997
0
998
0
    nsCOMPtr<nsILoadGroup> group =
999
0
        do_CreateInstance(NS_LOADGROUP_CONTRACTID, &rv);
1000
0
    NS_ENSURE_SUCCESS(rv, rv);
1001
0
1002
0
    RefPtr<LoadContext> loadContext = new LoadContext(aPrincipal);
1003
0
    rv = group->SetNotificationCallbacks(loadContext);
1004
0
    NS_ENSURE_SUCCESS(rv, rv);
1005
0
1006
0
    group.forget(aResult);
1007
0
    return rv;
1008
0
}
1009
1010
bool
1011
NS_LoadGroupMatchesPrincipal(nsILoadGroup *aLoadGroup,
1012
                             nsIPrincipal *aPrincipal)
1013
0
{
1014
0
    if (!aPrincipal) {
1015
0
      return false;
1016
0
    }
1017
0
1018
0
    // If this is a null principal then the load group doesn't really matter.
1019
0
    // The principal will not be allowed to perform any actions that actually
1020
0
    // use the load group.  Unconditionally treat null principals as a match.
1021
0
    if (aPrincipal->GetIsNullPrincipal()) {
1022
0
      return true;
1023
0
    }
1024
0
1025
0
    if (!aLoadGroup) {
1026
0
        return false;
1027
0
    }
1028
0
1029
0
    nsCOMPtr<nsILoadContext> loadContext;
1030
0
    NS_QueryNotificationCallbacks(nullptr, aLoadGroup, NS_GET_IID(nsILoadContext),
1031
0
                                  getter_AddRefs(loadContext));
1032
0
    NS_ENSURE_TRUE(loadContext, false);
1033
0
1034
0
    // Verify load context browser flag match the principal
1035
0
    bool contextInIsolatedBrowser;
1036
0
    nsresult rv = loadContext->GetIsInIsolatedMozBrowserElement(&contextInIsolatedBrowser);
1037
0
    NS_ENSURE_SUCCESS(rv, false);
1038
0
1039
0
    return contextInIsolatedBrowser == aPrincipal->GetIsInIsolatedMozBrowserElement();
1040
0
}
1041
1042
nsresult
1043
NS_NewDownloader(nsIStreamListener   **result,
1044
                 nsIDownloadObserver  *observer,
1045
                 nsIFile              *downloadLocation /* = nullptr */)
1046
0
{
1047
0
    nsresult rv;
1048
0
    nsCOMPtr<nsIDownloader> downloader =
1049
0
        do_CreateInstance(NS_DOWNLOADER_CONTRACTID, &rv);
1050
0
    if (NS_SUCCEEDED(rv)) {
1051
0
        rv = downloader->Init(observer, downloadLocation);
1052
0
        if (NS_SUCCEEDED(rv)) {
1053
0
            downloader.forget(result);
1054
0
        }
1055
0
    }
1056
0
    return rv;
1057
0
}
1058
1059
nsresult
1060
NS_NewIncrementalStreamLoader(nsIIncrementalStreamLoader        **result,
1061
                              nsIIncrementalStreamLoaderObserver *observer)
1062
0
{
1063
0
    nsresult rv;
1064
0
    nsCOMPtr<nsIIncrementalStreamLoader> loader =
1065
0
        do_CreateInstance(NS_INCREMENTALSTREAMLOADER_CONTRACTID, &rv);
1066
0
    if (NS_SUCCEEDED(rv)) {
1067
0
        rv = loader->Init(observer);
1068
0
        if (NS_SUCCEEDED(rv)) {
1069
0
            *result = nullptr;
1070
0
            loader.swap(*result);
1071
0
        }
1072
0
    }
1073
0
    return rv;
1074
0
}
1075
1076
nsresult
1077
NS_NewStreamLoader(nsIStreamLoader        **result,
1078
                   nsIStreamLoaderObserver *observer,
1079
                   nsIRequestObserver      *requestObserver /* = nullptr */)
1080
0
{
1081
0
    nsresult rv;
1082
0
    nsCOMPtr<nsIStreamLoader> loader =
1083
0
        do_CreateInstance(NS_STREAMLOADER_CONTRACTID, &rv);
1084
0
    if (NS_SUCCEEDED(rv)) {
1085
0
        rv = loader->Init(observer, requestObserver);
1086
0
        if (NS_SUCCEEDED(rv)) {
1087
0
            *result = nullptr;
1088
0
            loader.swap(*result);
1089
0
        }
1090
0
    }
1091
0
    return rv;
1092
0
}
1093
1094
nsresult
1095
NS_NewStreamLoaderInternal(nsIStreamLoader        **outStream,
1096
                           nsIURI                  *aUri,
1097
                           nsIStreamLoaderObserver *aObserver,
1098
                           nsINode                 *aLoadingNode,
1099
                           nsIPrincipal            *aLoadingPrincipal,
1100
                           nsSecurityFlags          aSecurityFlags,
1101
                           nsContentPolicyType      aContentPolicyType,
1102
                           nsILoadGroup            *aLoadGroup /* = nullptr */,
1103
                           nsIInterfaceRequestor   *aCallbacks /* = nullptr */,
1104
                           nsLoadFlags              aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
1105
                           nsIURI                  *aReferrer /* = nullptr */)
1106
0
{
1107
0
   nsCOMPtr<nsIChannel> channel;
1108
0
   nsresult rv = NS_NewChannelInternal(getter_AddRefs(channel),
1109
0
                                       aUri,
1110
0
                                       aLoadingNode,
1111
0
                                       aLoadingPrincipal,
1112
0
                                       nullptr, // aTriggeringPrincipal
1113
0
                                       Maybe<ClientInfo>(),
1114
0
                                       Maybe<ServiceWorkerDescriptor>(),
1115
0
                                       aSecurityFlags,
1116
0
                                       aContentPolicyType,
1117
0
                                       nullptr, // PerformanceStorage
1118
0
                                       aLoadGroup,
1119
0
                                       aCallbacks,
1120
0
                                       aLoadFlags);
1121
0
1122
0
  NS_ENSURE_SUCCESS(rv, rv);
1123
0
  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
1124
0
  if (httpChannel) {
1125
0
    rv = httpChannel->SetReferrer(aReferrer);
1126
0
    MOZ_ASSERT(NS_SUCCEEDED(rv));
1127
0
  }
1128
0
  rv = NS_NewStreamLoader(outStream, aObserver);
1129
0
  NS_ENSURE_SUCCESS(rv, rv);
1130
0
  return channel->AsyncOpen2(*outStream);
1131
0
}
1132
1133
1134
nsresult
1135
NS_NewStreamLoader(nsIStreamLoader        **outStream,
1136
                   nsIURI                  *aUri,
1137
                   nsIStreamLoaderObserver *aObserver,
1138
                   nsINode                 *aLoadingNode,
1139
                   nsSecurityFlags          aSecurityFlags,
1140
                   nsContentPolicyType      aContentPolicyType,
1141
                   nsILoadGroup            *aLoadGroup /* = nullptr */,
1142
                   nsIInterfaceRequestor   *aCallbacks /* = nullptr */,
1143
                   nsLoadFlags              aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
1144
                   nsIURI                  *aReferrer /* = nullptr */)
1145
0
{
1146
0
  NS_ASSERTION(aLoadingNode, "Can not create stream loader without a loading Node!");
1147
0
  return NS_NewStreamLoaderInternal(outStream,
1148
0
                                    aUri,
1149
0
                                    aObserver,
1150
0
                                    aLoadingNode,
1151
0
                                    aLoadingNode->NodePrincipal(),
1152
0
                                    aSecurityFlags,
1153
0
                                    aContentPolicyType,
1154
0
                                    aLoadGroup,
1155
0
                                    aCallbacks,
1156
0
                                    aLoadFlags,
1157
0
                                    aReferrer);
1158
0
}
1159
1160
nsresult
1161
NS_NewStreamLoader(nsIStreamLoader        **outStream,
1162
                   nsIURI                  *aUri,
1163
                   nsIStreamLoaderObserver *aObserver,
1164
                   nsIPrincipal            *aLoadingPrincipal,
1165
                   nsSecurityFlags          aSecurityFlags,
1166
                   nsContentPolicyType      aContentPolicyType,
1167
                   nsILoadGroup            *aLoadGroup /* = nullptr */,
1168
                   nsIInterfaceRequestor   *aCallbacks /* = nullptr */,
1169
                   nsLoadFlags              aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
1170
                   nsIURI                  *aReferrer /* = nullptr */)
1171
0
{
1172
0
  return NS_NewStreamLoaderInternal(outStream,
1173
0
                                    aUri,
1174
0
                                    aObserver,
1175
0
                                    nullptr, // aLoadingNode
1176
0
                                    aLoadingPrincipal,
1177
0
                                    aSecurityFlags,
1178
0
                                    aContentPolicyType,
1179
0
                                    aLoadGroup,
1180
0
                                    aCallbacks,
1181
0
                                    aLoadFlags,
1182
0
                                    aReferrer);
1183
0
}
1184
1185
nsresult
1186
NS_NewSyncStreamListener(nsIStreamListener **result,
1187
                         nsIInputStream    **stream)
1188
0
{
1189
0
    nsresult rv;
1190
0
    nsCOMPtr<nsISyncStreamListener> listener =
1191
0
        do_CreateInstance(NS_SYNCSTREAMLISTENER_CONTRACTID, &rv);
1192
0
    if (NS_SUCCEEDED(rv)) {
1193
0
        rv = listener->GetInputStream(stream);
1194
0
        if (NS_SUCCEEDED(rv)) {
1195
0
            listener.forget(result);
1196
0
        }
1197
0
    }
1198
0
    return rv;
1199
0
}
1200
1201
nsresult
1202
NS_ImplementChannelOpen(nsIChannel      *channel,
1203
                        nsIInputStream **result)
1204
0
{
1205
0
    nsCOMPtr<nsIStreamListener> listener;
1206
0
    nsCOMPtr<nsIInputStream> stream;
1207
0
    nsresult rv = NS_NewSyncStreamListener(getter_AddRefs(listener),
1208
0
                                           getter_AddRefs(stream));
1209
0
    NS_ENSURE_SUCCESS(rv, rv);
1210
0
1211
0
    rv = NS_MaybeOpenChannelUsingAsyncOpen2(channel, listener);
1212
0
    NS_ENSURE_SUCCESS(rv, rv);
1213
0
1214
0
    uint64_t n;
1215
0
    // block until the initial response is received or an error occurs.
1216
0
    rv = stream->Available(&n);
1217
0
    NS_ENSURE_SUCCESS(rv, rv);
1218
0
1219
0
    *result = nullptr;
1220
0
    stream.swap(*result);
1221
0
1222
0
    return NS_OK;
1223
0
 }
1224
1225
nsresult
1226
NS_NewRequestObserverProxy(nsIRequestObserver **result,
1227
                           nsIRequestObserver  *observer,
1228
                           nsISupports         *context)
1229
0
{
1230
0
    nsresult rv;
1231
0
    nsCOMPtr<nsIRequestObserverProxy> proxy =
1232
0
        do_CreateInstance(NS_REQUESTOBSERVERPROXY_CONTRACTID, &rv);
1233
0
    if (NS_SUCCEEDED(rv)) {
1234
0
        rv = proxy->Init(observer, context);
1235
0
        if (NS_SUCCEEDED(rv)) {
1236
0
            proxy.forget(result);
1237
0
        }
1238
0
    }
1239
0
    return rv;
1240
0
}
1241
1242
nsresult
1243
NS_NewSimpleStreamListener(nsIStreamListener **result,
1244
                           nsIOutputStream    *sink,
1245
                           nsIRequestObserver *observer /* = nullptr */)
1246
0
{
1247
0
    nsresult rv;
1248
0
    nsCOMPtr<nsISimpleStreamListener> listener =
1249
0
        do_CreateInstance(NS_SIMPLESTREAMLISTENER_CONTRACTID, &rv);
1250
0
    if (NS_SUCCEEDED(rv)) {
1251
0
        rv = listener->Init(sink, observer);
1252
0
        if (NS_SUCCEEDED(rv)) {
1253
0
            listener.forget(result);
1254
0
        }
1255
0
    }
1256
0
    return rv;
1257
0
}
1258
1259
nsresult
1260
NS_CheckPortSafety(int32_t       port,
1261
                   const char   *scheme,
1262
                   nsIIOService *ioService /* = nullptr */)
1263
0
{
1264
0
    nsresult rv;
1265
0
    nsCOMPtr<nsIIOService> grip;
1266
0
    rv = net_EnsureIOService(&ioService, grip);
1267
0
    if (ioService) {
1268
0
        bool allow;
1269
0
        rv = ioService->AllowPort(port, scheme, &allow);
1270
0
        if (NS_SUCCEEDED(rv) && !allow) {
1271
0
            NS_WARNING("port blocked");
1272
0
            rv = NS_ERROR_PORT_ACCESS_NOT_ALLOWED;
1273
0
        }
1274
0
    }
1275
0
    return rv;
1276
0
}
1277
1278
nsresult
1279
NS_CheckPortSafety(nsIURI *uri)
1280
0
{
1281
0
    int32_t port;
1282
0
    nsresult rv = uri->GetPort(&port);
1283
0
    if (NS_FAILED(rv) || port == -1)  // port undefined or default-valued
1284
0
        return NS_OK;
1285
0
    nsAutoCString scheme;
1286
0
    uri->GetScheme(scheme);
1287
0
    return NS_CheckPortSafety(port, scheme.get());
1288
0
}
1289
1290
nsresult
1291
NS_NewProxyInfo(const nsACString &type,
1292
                const nsACString &host,
1293
                int32_t           port,
1294
                uint32_t          flags,
1295
                nsIProxyInfo    **result)
1296
0
{
1297
0
    nsresult rv;
1298
0
    nsCOMPtr<nsIProtocolProxyService> pps =
1299
0
            do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
1300
0
    if (NS_SUCCEEDED(rv))
1301
0
        rv = pps->NewProxyInfo(type, host, port, flags, UINT32_MAX, nullptr,
1302
0
                               result);
1303
0
    return rv;
1304
0
}
1305
1306
nsresult
1307
NS_GetFileProtocolHandler(nsIFileProtocolHandler **result,
1308
                          nsIIOService            *ioService /* = nullptr */)
1309
11
{
1310
11
    nsresult rv;
1311
11
    nsCOMPtr<nsIIOService> grip;
1312
11
    rv = net_EnsureIOService(&ioService, grip);
1313
11
    if (ioService) {
1314
11
        nsCOMPtr<nsIProtocolHandler> handler;
1315
11
        rv = ioService->GetProtocolHandler("file", getter_AddRefs(handler));
1316
11
        if (NS_SUCCEEDED(rv))
1317
11
            rv = CallQueryInterface(handler, result);
1318
11
    }
1319
11
    return rv;
1320
11
}
1321
1322
nsresult
1323
NS_GetFileFromURLSpec(const nsACString  &inURL,
1324
                      nsIFile          **result,
1325
                      nsIIOService      *ioService /* = nullptr */)
1326
0
{
1327
0
    nsresult rv;
1328
0
    nsCOMPtr<nsIFileProtocolHandler> fileHandler;
1329
0
    rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
1330
0
    if (NS_SUCCEEDED(rv))
1331
0
        rv = fileHandler->GetFileFromURLSpec(inURL, result);
1332
0
    return rv;
1333
0
}
1334
1335
nsresult
1336
NS_GetURLSpecFromFile(nsIFile      *file,
1337
                      nsACString   &url,
1338
                      nsIIOService *ioService /* = nullptr */)
1339
0
{
1340
0
    nsresult rv;
1341
0
    nsCOMPtr<nsIFileProtocolHandler> fileHandler;
1342
0
    rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
1343
0
    if (NS_SUCCEEDED(rv))
1344
0
        rv = fileHandler->GetURLSpecFromFile(file, url);
1345
0
    return rv;
1346
0
}
1347
1348
nsresult
1349
NS_GetURLSpecFromActualFile(nsIFile      *file,
1350
                            nsACString   &url,
1351
                            nsIIOService *ioService /* = nullptr */)
1352
11
{
1353
11
    nsresult rv;
1354
11
    nsCOMPtr<nsIFileProtocolHandler> fileHandler;
1355
11
    rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
1356
11
    if (NS_SUCCEEDED(rv))
1357
11
        rv = fileHandler->GetURLSpecFromActualFile(file, url);
1358
11
    return rv;
1359
11
}
1360
1361
nsresult
1362
NS_GetURLSpecFromDir(nsIFile      *file,
1363
                     nsACString   &url,
1364
                     nsIIOService *ioService /* = nullptr */)
1365
0
{
1366
0
    nsresult rv;
1367
0
    nsCOMPtr<nsIFileProtocolHandler> fileHandler;
1368
0
    rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
1369
0
    if (NS_SUCCEEDED(rv))
1370
0
        rv = fileHandler->GetURLSpecFromDir(file, url);
1371
0
    return rv;
1372
0
}
1373
1374
nsresult
1375
NS_GetReferrerFromChannel(nsIChannel *channel,
1376
                          nsIURI **referrer)
1377
0
{
1378
0
    nsresult rv = NS_ERROR_NOT_AVAILABLE;
1379
0
    *referrer = nullptr;
1380
0
1381
0
    nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(channel));
1382
0
    if (props) {
1383
0
      // We have to check for a property on a property bag because the
1384
0
      // referrer may be empty for security reasons (for example, when loading
1385
0
      // an http page with an https referrer).
1386
0
      rv = props->GetPropertyAsInterface(NS_LITERAL_STRING("docshell.internalReferrer"),
1387
0
                                         NS_GET_IID(nsIURI),
1388
0
                                         reinterpret_cast<void **>(referrer));
1389
0
      if (NS_FAILED(rv))
1390
0
        *referrer = nullptr;
1391
0
    }
1392
0
1393
0
    // if that didn't work, we can still try to get the referrer from the
1394
0
    // nsIHttpChannel (if we can QI to it)
1395
0
    if (!(*referrer)) {
1396
0
      nsCOMPtr<nsIHttpChannel> chan(do_QueryInterface(channel));
1397
0
      if (chan) {
1398
0
        rv = chan->GetReferrer(referrer);
1399
0
        if (NS_FAILED(rv))
1400
0
          *referrer = nullptr;
1401
0
      }
1402
0
    }
1403
0
    return rv;
1404
0
}
1405
1406
already_AddRefed<nsINetUtil>
1407
do_GetNetUtil(nsresult *error /* = 0 */)
1408
11.6k
{
1409
11.6k
    nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
1410
11.6k
    nsCOMPtr<nsINetUtil> util;
1411
11.6k
    if (io)
1412
11.6k
        util = do_QueryInterface(io);
1413
11.6k
1414
11.6k
    if (error)
1415
11.6k
        *error = !!util ? NS_OK : NS_ERROR_FAILURE;
1416
11.6k
    return util.forget();
1417
11.6k
}
1418
1419
nsresult
1420
NS_ParseRequestContentType(const nsACString &rawContentType,
1421
                           nsCString        &contentType,
1422
                           nsCString        &contentCharset)
1423
0
{
1424
0
    // contentCharset is left untouched if not present in rawContentType
1425
0
    nsresult rv;
1426
0
    nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
1427
0
    NS_ENSURE_SUCCESS(rv, rv);
1428
0
    nsCString charset;
1429
0
    bool hadCharset;
1430
0
    rv = util->ParseRequestContentType(rawContentType, charset, &hadCharset,
1431
0
                                       contentType);
1432
0
    if (NS_SUCCEEDED(rv) && hadCharset)
1433
0
        contentCharset = charset;
1434
0
    return rv;
1435
0
}
1436
1437
nsresult
1438
NS_ParseResponseContentType(const nsACString &rawContentType,
1439
                            nsCString        &contentType,
1440
                            nsCString        &contentCharset)
1441
0
{
1442
0
    // contentCharset is left untouched if not present in rawContentType
1443
0
    nsresult rv;
1444
0
    nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
1445
0
    NS_ENSURE_SUCCESS(rv, rv);
1446
0
    nsCString charset;
1447
0
    bool hadCharset;
1448
0
    rv = util->ParseResponseContentType(rawContentType, charset, &hadCharset,
1449
0
                                        contentType);
1450
0
    if (NS_SUCCEEDED(rv) && hadCharset)
1451
0
        contentCharset = charset;
1452
0
    return rv;
1453
0
}
1454
1455
nsresult
1456
NS_ExtractCharsetFromContentType(const nsACString &rawContentType,
1457
                                 nsCString        &contentCharset,
1458
                                 bool             *hadCharset,
1459
                                 int32_t          *charsetStart,
1460
                                 int32_t          *charsetEnd)
1461
0
{
1462
0
    // contentCharset is left untouched if not present in rawContentType
1463
0
    nsresult rv;
1464
0
    nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
1465
0
    NS_ENSURE_SUCCESS(rv, rv);
1466
0
1467
0
    return util->ExtractCharsetFromContentType(rawContentType,
1468
0
                                               contentCharset,
1469
0
                                               charsetStart,
1470
0
                                               charsetEnd,
1471
0
                                               hadCharset);
1472
0
}
1473
1474
nsresult
1475
NS_NewAtomicFileOutputStream(nsIOutputStream **result,
1476
                                nsIFile       *file,
1477
                                int32_t        ioFlags       /* = -1 */,
1478
                                int32_t        perm          /* = -1 */,
1479
                                int32_t        behaviorFlags /* = 0 */)
1480
0
{
1481
0
    nsresult rv;
1482
0
    nsCOMPtr<nsIFileOutputStream> out =
1483
0
        do_CreateInstance(NS_ATOMICLOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
1484
0
    if (NS_SUCCEEDED(rv)) {
1485
0
        rv = out->Init(file, ioFlags, perm, behaviorFlags);
1486
0
        if (NS_SUCCEEDED(rv))
1487
0
            out.forget(result);
1488
0
    }
1489
0
    return rv;
1490
0
}
1491
1492
nsresult
1493
NS_NewSafeLocalFileOutputStream(nsIOutputStream **result,
1494
                                nsIFile          *file,
1495
                                int32_t           ioFlags       /* = -1 */,
1496
                                int32_t           perm          /* = -1 */,
1497
                                int32_t           behaviorFlags /* = 0 */)
1498
0
{
1499
0
    nsresult rv;
1500
0
    nsCOMPtr<nsIFileOutputStream> out =
1501
0
        do_CreateInstance(NS_SAFELOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
1502
0
    if (NS_SUCCEEDED(rv)) {
1503
0
        rv = out->Init(file, ioFlags, perm, behaviorFlags);
1504
0
        if (NS_SUCCEEDED(rv))
1505
0
            out.forget(result);
1506
0
    }
1507
0
    return rv;
1508
0
}
1509
1510
nsresult
1511
NS_NewLocalFileStream(nsIFileStream **result,
1512
                      nsIFile        *file,
1513
                      int32_t         ioFlags       /* = -1 */,
1514
                      int32_t         perm          /* = -1 */,
1515
                      int32_t         behaviorFlags /* = 0 */)
1516
0
{
1517
0
    nsCOMPtr<nsIFileStream> stream = new nsFileStream();
1518
0
    nsresult rv = stream->Init(file, ioFlags, perm, behaviorFlags);
1519
0
    if (NS_SUCCEEDED(rv)) {
1520
0
        stream.forget(result);
1521
0
    }
1522
0
    return rv;
1523
0
}
1524
1525
nsresult
1526
NS_NewBufferedOutputStream(nsIOutputStream** aResult,
1527
                           already_AddRefed<nsIOutputStream> aOutputStream,
1528
                           uint32_t aBufferSize)
1529
0
{
1530
0
    nsCOMPtr<nsIOutputStream> outputStream = std::move(aOutputStream);
1531
0
1532
0
    nsresult rv;
1533
0
    nsCOMPtr<nsIBufferedOutputStream> out =
1534
0
        do_CreateInstance(NS_BUFFEREDOUTPUTSTREAM_CONTRACTID, &rv);
1535
0
    if (NS_SUCCEEDED(rv)) {
1536
0
        rv = out->Init(outputStream, aBufferSize);
1537
0
        if (NS_SUCCEEDED(rv)) {
1538
0
            out.forget(aResult);
1539
0
        }
1540
0
    }
1541
0
    return rv;
1542
0
}
1543
1544
MOZ_MUST_USE nsresult
1545
NS_NewBufferedInputStream(nsIInputStream** aResult,
1546
                          already_AddRefed<nsIInputStream> aInputStream,
1547
                          uint32_t aBufferSize)
1548
0
{
1549
0
    nsCOMPtr<nsIInputStream> inputStream = std::move(aInputStream);
1550
0
1551
0
    nsresult rv;
1552
0
    nsCOMPtr<nsIBufferedInputStream> in =
1553
0
        do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv);
1554
0
    if (NS_SUCCEEDED(rv)) {
1555
0
        rv = in->Init(inputStream, aBufferSize);
1556
0
        if (NS_SUCCEEDED(rv)) {
1557
0
            in.forget(aResult);
1558
0
        }
1559
0
    }
1560
0
    return rv;
1561
0
}
1562
1563
namespace {
1564
1565
0
#define BUFFER_SIZE 8192
1566
1567
class BufferWriter final : public nsIInputStreamCallback
1568
{
1569
public:
1570
    NS_DECL_THREADSAFE_ISUPPORTS
1571
1572
    BufferWriter(nsIInputStream* aInputStream,
1573
                 void* aBuffer, int64_t aCount)
1574
        : mMonitor("BufferWriter.mMonitor")
1575
        , mInputStream(aInputStream)
1576
        , mBuffer(aBuffer)
1577
        , mCount(aCount)
1578
        , mWrittenData(0)
1579
        , mBufferType(aBuffer ? eExternal : eInternal)
1580
        , mBufferSize(0)
1581
0
    {
1582
0
        MOZ_ASSERT(aInputStream);
1583
0
        MOZ_ASSERT(aCount == -1 || aCount > 0);
1584
0
        MOZ_ASSERT_IF(mBuffer, aCount > 0);
1585
0
    }
1586
1587
    nsresult
1588
    Write()
1589
0
    {
1590
0
        NS_ASSERT_OWNINGTHREAD(BufferWriter);
1591
0
1592
0
        // Let's make the inputStream buffered if it's not.
1593
0
        if (!NS_InputStreamIsBuffered(mInputStream)) {
1594
0
            nsCOMPtr<nsIInputStream> bufferedStream;
1595
0
            nsresult rv =
1596
0
                NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
1597
0
                                          mInputStream.forget(), BUFFER_SIZE);
1598
0
            NS_ENSURE_SUCCESS(rv, rv);
1599
0
1600
0
            mInputStream = bufferedStream;
1601
0
        }
1602
0
1603
0
        mAsyncInputStream = do_QueryInterface(mInputStream);
1604
0
1605
0
        if (!mAsyncInputStream) {
1606
0
            return WriteSync();
1607
0
        }
1608
0
1609
0
        // Let's use mAsyncInputStream only.
1610
0
        mInputStream = nullptr;
1611
0
1612
0
        return WriteAsync();
1613
0
    }
1614
1615
    uint64_t
1616
    WrittenData() const
1617
0
    {
1618
0
        NS_ASSERT_OWNINGTHREAD(BufferWriter);
1619
0
        return mWrittenData;
1620
0
    }
1621
1622
    void*
1623
    StealBuffer()
1624
0
    {
1625
0
        NS_ASSERT_OWNINGTHREAD(BufferWriter);
1626
0
        MOZ_ASSERT(mBufferType == eInternal);
1627
0
1628
0
        void* buffer = mBuffer;
1629
0
1630
0
        mBuffer = nullptr;
1631
0
        mBufferSize = 0;
1632
0
1633
0
        return buffer;
1634
0
    }
1635
1636
private:
1637
    ~BufferWriter()
1638
0
    {
1639
0
        if (mBuffer && mBufferType == eInternal) {
1640
0
            free(mBuffer);
1641
0
        }
1642
0
1643
0
        if (mTaskQueue) {
1644
0
            mTaskQueue->BeginShutdown();
1645
0
        }
1646
0
    }
1647
1648
    nsresult
1649
    WriteSync()
1650
0
    {
1651
0
        NS_ASSERT_OWNINGTHREAD(BufferWriter);
1652
0
1653
0
        uint64_t length = (uint64_t)mCount;
1654
0
1655
0
        if (mCount == -1) {
1656
0
            nsresult rv = mInputStream->Available(&length);
1657
0
            NS_ENSURE_SUCCESS(rv, rv);
1658
0
1659
0
            if (length == 0) {
1660
0
                // nothing to read.
1661
0
                return NS_OK;
1662
0
            }
1663
0
        }
1664
0
1665
0
        if (mBufferType == eInternal) {
1666
0
            mBuffer = malloc(length);
1667
0
            if (NS_WARN_IF(!mBuffer)) {
1668
0
                return NS_ERROR_OUT_OF_MEMORY;
1669
0
            }
1670
0
        }
1671
0
1672
0
        uint32_t writtenData;
1673
0
        nsresult rv = mInputStream->ReadSegments(NS_CopySegmentToBuffer,
1674
0
                                                 mBuffer, length,
1675
0
                                                 &writtenData);
1676
0
        NS_ENSURE_SUCCESS(rv, rv);
1677
0
1678
0
        mWrittenData = writtenData;
1679
0
        return NS_OK;
1680
0
    }
1681
1682
    nsresult
1683
    WriteAsync()
1684
0
    {
1685
0
        NS_ASSERT_OWNINGTHREAD(BufferWriter);
1686
0
1687
0
        if (mCount > 0 && mBufferType == eInternal) {
1688
0
            mBuffer = malloc(mCount);
1689
0
            if (NS_WARN_IF(!mBuffer)) {
1690
0
                return NS_ERROR_OUT_OF_MEMORY;
1691
0
            }
1692
0
        }
1693
0
1694
0
        while (true) {
1695
0
            if (mCount == -1 && !MaybeExpandBufferSize()) {
1696
0
                return NS_ERROR_OUT_OF_MEMORY;
1697
0
            }
1698
0
1699
0
            uint64_t offset = mWrittenData;
1700
0
            uint64_t length = mCount == -1 ? BUFFER_SIZE : mCount;
1701
0
1702
0
            // Let's try to read data directly.
1703
0
            uint32_t writtenData;
1704
0
            nsresult rv = mAsyncInputStream->ReadSegments(NS_CopySegmentToBuffer,
1705
0
                                                         static_cast<char*>(mBuffer) + offset,
1706
0
                                                         length, &writtenData);
1707
0
1708
0
            // Operation completed. Nothing more to read.
1709
0
            if (NS_SUCCEEDED(rv) && writtenData == 0) {
1710
0
                return NS_OK;
1711
0
            }
1712
0
1713
0
            // If we succeeded, let's try to read again.
1714
0
            if (NS_SUCCEEDED(rv)) {
1715
0
                mWrittenData += writtenData;
1716
0
                if (mCount != -1) {
1717
0
                    MOZ_ASSERT(mCount >= writtenData);
1718
0
                    mCount -= writtenData;
1719
0
1720
0
                    // Is this the end of the reading?
1721
0
                    if (mCount == 0) {
1722
0
                        return NS_OK;
1723
0
                    }
1724
0
                }
1725
0
1726
0
                continue;
1727
0
            }
1728
0
1729
0
            // Async wait...
1730
0
            if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
1731
0
                rv = MaybeCreateTaskQueue();
1732
0
                if (NS_WARN_IF(NS_FAILED(rv))) {
1733
0
                    return rv;
1734
0
                }
1735
0
1736
0
                MonitorAutoLock lock(mMonitor);
1737
0
1738
0
                rv = mAsyncInputStream->AsyncWait(this, 0, length, mTaskQueue);
1739
0
                if (NS_WARN_IF(NS_FAILED(rv))) {
1740
0
                    return rv;
1741
0
                }
1742
0
1743
0
                lock.Wait();
1744
0
                continue;
1745
0
            }
1746
0
1747
0
            // Otherwise, let's propagate the error.
1748
0
            return rv;
1749
0
        }
1750
0
1751
0
        MOZ_ASSERT_UNREACHABLE("We should not be here");
1752
0
        return NS_ERROR_FAILURE;
1753
0
    }
1754
1755
    nsresult
1756
    MaybeCreateTaskQueue()
1757
0
    {
1758
0
        NS_ASSERT_OWNINGTHREAD(BufferWriter);
1759
0
1760
0
        if (!mTaskQueue) {
1761
0
            nsCOMPtr<nsIEventTarget> target =
1762
0
                do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
1763
0
            if (!target) {
1764
0
                return NS_ERROR_FAILURE;
1765
0
            }
1766
0
1767
0
            mTaskQueue = new TaskQueue(target.forget());
1768
0
        }
1769
0
1770
0
        return NS_OK;
1771
0
    }
1772
1773
    NS_IMETHOD
1774
    OnInputStreamReady(nsIAsyncInputStream* aStream) override
1775
0
    {
1776
0
        MOZ_ASSERT(!NS_IsMainThread());
1777
0
1778
0
        // We have something to read. Let's unlock the main-thread.
1779
0
        MonitorAutoLock lock(mMonitor);
1780
0
        lock.Notify();
1781
0
        return NS_OK;
1782
0
    }
1783
1784
    bool
1785
    MaybeExpandBufferSize()
1786
0
    {
1787
0
        NS_ASSERT_OWNINGTHREAD(BufferWriter);
1788
0
1789
0
        MOZ_ASSERT(mCount == -1);
1790
0
1791
0
        if (mBufferSize >= mWrittenData + BUFFER_SIZE) {
1792
0
            // The buffer is big enough.
1793
0
            return true;
1794
0
        }
1795
0
1796
0
        CheckedUint32 bufferSize =
1797
0
            std::max<uint32_t>(static_cast<uint32_t>(mWrittenData),
1798
0
                               BUFFER_SIZE);
1799
0
        while (bufferSize.isValid() &&
1800
0
               bufferSize.value() < mWrittenData + BUFFER_SIZE) {
1801
0
            bufferSize *= 2;
1802
0
        }
1803
0
1804
0
        if (!bufferSize.isValid()) {
1805
0
            return false;
1806
0
        }
1807
0
1808
0
        void* buffer = realloc(mBuffer, bufferSize.value());
1809
0
        if (!buffer) {
1810
0
            return false;
1811
0
        }
1812
0
1813
0
        mBuffer = buffer;
1814
0
        mBufferSize = bufferSize.value();
1815
0
        return true;
1816
0
    }
1817
1818
    // All the members of this class are touched on the owning thread only. The
1819
    // monitor is only used to communicate when there is more data to read.
1820
    Monitor mMonitor;
1821
1822
    nsCOMPtr<nsIInputStream> mInputStream;
1823
    nsCOMPtr<nsIAsyncInputStream> mAsyncInputStream;
1824
1825
    RefPtr<TaskQueue> mTaskQueue;
1826
1827
    void* mBuffer;
1828
    int64_t mCount;
1829
    uint64_t mWrittenData;
1830
1831
    enum {
1832
        // The buffer is allocated internally and this object must release it
1833
        // in the DTOR if not stolen. The buffer can be reallocated.
1834
        eInternal,
1835
1836
        // The buffer is not owned by this object and it cannot be reallocated.
1837
        eExternal,
1838
    } mBufferType;
1839
1840
    // The following set if needed for the async read.
1841
    uint64_t mBufferSize;
1842
};
1843
1844
NS_IMPL_ISUPPORTS(BufferWriter, nsIInputStreamCallback)
1845
1846
} // anonymous namespace
1847
1848
nsresult
1849
NS_ReadInputStreamToBuffer(nsIInputStream* aInputStream,
1850
                           void** aDest,
1851
                           int64_t aCount,
1852
                           uint64_t* aWritten)
1853
0
{
1854
0
    MOZ_ASSERT(aInputStream);
1855
0
    MOZ_ASSERT(aCount >= -1);
1856
0
1857
0
    uint64_t dummyWritten;
1858
0
    if (!aWritten) {
1859
0
        aWritten = &dummyWritten;
1860
0
    }
1861
0
1862
0
    if (aCount == 0) {
1863
0
        *aWritten = 0;
1864
0
        return NS_OK;
1865
0
    }
1866
0
1867
0
    // This will take care of allocating and reallocating aDest.
1868
0
    RefPtr<BufferWriter> writer =
1869
0
       new BufferWriter(aInputStream, *aDest, aCount);
1870
0
1871
0
    nsresult rv = writer->Write();
1872
0
    NS_ENSURE_SUCCESS(rv, rv);
1873
0
1874
0
    *aWritten = writer->WrittenData();
1875
0
1876
0
    if (!*aDest) {
1877
0
        *aDest = writer->StealBuffer();
1878
0
    }
1879
0
1880
0
    return NS_OK;
1881
0
}
1882
1883
nsresult
1884
NS_ReadInputStreamToString(nsIInputStream* aInputStream,
1885
                           nsACString& aDest,
1886
                           int64_t aCount,
1887
                           uint64_t* aWritten)
1888
0
{
1889
0
    uint64_t dummyWritten;
1890
0
    if (!aWritten) {
1891
0
        aWritten = &dummyWritten;
1892
0
    }
1893
0
1894
0
    // Nothing to do if aCount is 0.
1895
0
    if (aCount == 0) {
1896
0
        aDest.Truncate();
1897
0
        *aWritten = 0;
1898
0
        return NS_OK;
1899
0
    }
1900
0
1901
0
    // If we have the size, we can pre-allocate the buffer.
1902
0
    if (aCount > 0) {
1903
0
        if (NS_WARN_IF(aCount  >= INT32_MAX) ||
1904
0
            NS_WARN_IF(!aDest.SetLength(aCount, mozilla::fallible))) {
1905
0
            return NS_ERROR_OUT_OF_MEMORY;
1906
0
        }
1907
0
1908
0
        void* dest = aDest.BeginWriting();
1909
0
        nsresult rv = NS_ReadInputStreamToBuffer(aInputStream, &dest, aCount,
1910
0
                                                 aWritten);
1911
0
        NS_ENSURE_SUCCESS(rv, rv);
1912
0
1913
0
       if ((uint64_t)aCount > *aWritten) {
1914
0
           aDest.Truncate(*aWritten);
1915
0
       }
1916
0
1917
0
       return NS_OK;
1918
0
    }
1919
0
1920
0
    // If the size is unknown, BufferWriter will allocate the buffer.
1921
0
    void* dest = nullptr;
1922
0
    nsresult rv = NS_ReadInputStreamToBuffer(aInputStream, &dest, aCount,
1923
0
                                             aWritten);
1924
0
    MOZ_ASSERT_IF(NS_FAILED(rv), dest == nullptr);
1925
0
    NS_ENSURE_SUCCESS(rv, rv);
1926
0
1927
0
    if (!dest) {
1928
0
      MOZ_ASSERT(*aWritten == 0);
1929
0
      aDest.Truncate();
1930
0
      return NS_OK;
1931
0
    }
1932
0
1933
0
    aDest.Adopt(reinterpret_cast<char*>(dest), *aWritten);
1934
0
    return NS_OK;
1935
0
}
1936
1937
nsresult
1938
NS_NewURI(nsIURI **result,
1939
          const nsACString &spec,
1940
          const char *charset /* = nullptr */,
1941
          nsIURI *baseURI /* = nullptr */,
1942
          nsIIOService *ioService /* = nullptr */)     // pass in nsIIOService to optimize callers
1943
3.05M
{
1944
3.05M
    nsresult rv;
1945
3.05M
    nsCOMPtr<nsIIOService> grip;
1946
3.05M
    rv = net_EnsureIOService(&ioService, grip);
1947
3.05M
    if (ioService)
1948
3.05M
        rv = ioService->NewURI(spec, charset, baseURI, result);
1949
3.05M
    return rv;
1950
3.05M
}
1951
1952
nsresult
1953
NS_NewURI(nsIURI **result,
1954
          const nsACString &spec,
1955
          NotNull<const Encoding*> encoding,
1956
          nsIURI *baseURI /* = nullptr */,
1957
          nsIIOService *ioService /* = nullptr */)     // pass in nsIIOService to optimize callers
1958
0
{
1959
0
    nsAutoCString charset;
1960
0
    encoding->Name(charset);
1961
0
    return NS_NewURI(result, spec, charset.get(), baseURI, ioService);
1962
0
}
1963
1964
nsresult
1965
NS_NewURI(nsIURI **result,
1966
          const nsAString &spec,
1967
          const char *charset /* = nullptr */,
1968
          nsIURI *baseURI /* = nullptr */,
1969
          nsIIOService *ioService /* = nullptr */)     // pass in nsIIOService to optimize callers
1970
3.04M
{
1971
3.04M
    return NS_NewURI(result, NS_ConvertUTF16toUTF8(spec), charset, baseURI, ioService);
1972
3.04M
}
1973
1974
nsresult
1975
NS_NewURI(nsIURI **result,
1976
          const nsAString &spec,
1977
          NotNull<const Encoding*> encoding,
1978
          nsIURI *baseURI /* = nullptr */,
1979
          nsIIOService *ioService /* = nullptr */)     // pass in nsIIOService to optimize callers
1980
0
{
1981
0
    return NS_NewURI(result, NS_ConvertUTF16toUTF8(spec), encoding, baseURI, ioService);
1982
0
}
1983
1984
nsresult
1985
NS_NewURI(nsIURI **result,
1986
          const char *spec,
1987
          nsIURI *baseURI /* = nullptr */,
1988
          nsIIOService *ioService /* = nullptr */)     // pass in nsIIOService to optimize callers
1989
5.92k
{
1990
5.92k
    return NS_NewURI(result, nsDependentCString(spec), nullptr, baseURI, ioService);
1991
5.92k
}
1992
1993
nsresult
1994
NS_GetSanitizedURIStringFromURI(nsIURI *aUri, nsAString &aSanitizedSpec)
1995
0
{
1996
0
    aSanitizedSpec.Truncate();
1997
0
1998
0
    nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri = do_QueryInterface(aUri);
1999
0
    nsAutoCString cSpec;
2000
0
    nsresult rv;
2001
0
    if (safeUri) {
2002
0
        rv = safeUri->GetSensitiveInfoHiddenSpec(cSpec);
2003
0
    } else {
2004
0
        rv = aUri->GetSpec(cSpec);
2005
0
    }
2006
0
2007
0
    if (NS_SUCCEEDED(rv)) {
2008
0
        aSanitizedSpec.Assign(NS_ConvertUTF8toUTF16(cSpec));
2009
0
    }
2010
0
    return rv;
2011
0
}
2012
2013
nsresult
2014
NS_LoadPersistentPropertiesFromURISpec(nsIPersistentProperties **outResult,
2015
                                       const nsACString         &aSpec)
2016
0
{
2017
0
    nsCOMPtr<nsIURI> uri;
2018
0
    nsresult rv = NS_NewURI(getter_AddRefs(uri), aSpec);
2019
0
    NS_ENSURE_SUCCESS(rv, rv);
2020
0
2021
0
    nsCOMPtr<nsIChannel> channel;
2022
0
    rv = NS_NewChannel(getter_AddRefs(channel),
2023
0
                       uri,
2024
0
                       nsContentUtils::GetSystemPrincipal(),
2025
0
                       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
2026
0
                       nsIContentPolicy::TYPE_OTHER);
2027
0
    NS_ENSURE_SUCCESS(rv, rv);
2028
0
    nsCOMPtr<nsIInputStream> in;
2029
0
    rv = channel->Open2(getter_AddRefs(in));
2030
0
    NS_ENSURE_SUCCESS(rv, rv);
2031
0
2032
0
    nsCOMPtr<nsIPersistentProperties> properties = new nsPersistentProperties();
2033
0
    rv = properties->Load(in);
2034
0
    NS_ENSURE_SUCCESS(rv, rv);
2035
0
2036
0
    properties.swap(*outResult);
2037
0
    return NS_OK;
2038
0
}
2039
2040
bool
2041
NS_UsePrivateBrowsing(nsIChannel *channel)
2042
0
{
2043
0
    OriginAttributes attrs;
2044
0
    bool result = NS_GetOriginAttributes(channel, attrs);
2045
0
    NS_ENSURE_TRUE(result, result);
2046
0
    return attrs.mPrivateBrowsingId > 0;
2047
0
}
2048
2049
bool
2050
NS_GetOriginAttributes(nsIChannel *aChannel,
2051
                       mozilla::OriginAttributes &aAttributes)
2052
0
{
2053
0
    nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
2054
0
    // For some channels, they might not have loadInfo, like ExternalHelperAppParent..
2055
0
    if (loadInfo) {
2056
0
        loadInfo->GetOriginAttributes(&aAttributes);
2057
0
    }
2058
0
2059
0
    bool isPrivate = false;
2060
0
    nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(aChannel);
2061
0
    if (pbChannel) {
2062
0
        nsresult rv = pbChannel->GetIsChannelPrivate(&isPrivate);
2063
0
        NS_ENSURE_SUCCESS(rv, false);
2064
0
    } else {
2065
0
        // Some channels may not implement nsIPrivateBrowsingChannel
2066
0
        nsCOMPtr<nsILoadContext> loadContext;
2067
0
        NS_QueryNotificationCallbacks(aChannel, loadContext);
2068
0
        isPrivate = loadContext && loadContext->UsePrivateBrowsing();
2069
0
    }
2070
0
    aAttributes.SyncAttributesWithPrivateBrowsing(isPrivate);
2071
0
    return true;
2072
0
}
2073
2074
bool
2075
NS_HasBeenCrossOrigin(nsIChannel* aChannel, bool aReport)
2076
0
{
2077
0
  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
2078
0
  MOZ_RELEASE_ASSERT(loadInfo, "Origin tracking only works for channels created with a loadinfo");
2079
0
2080
0
  if (!loadInfo) {
2081
0
    return false;
2082
0
  }
2083
0
2084
0
  // TYPE_DOCUMENT loads have a null LoadingPrincipal and can not be cross origin.
2085
0
  if (!loadInfo->LoadingPrincipal()) {
2086
0
    return false;
2087
0
  }
2088
0
2089
0
  // Always treat tainted channels as cross-origin.
2090
0
  if (loadInfo->GetTainting() != LoadTainting::Basic) {
2091
0
    return true;
2092
0
  }
2093
0
2094
0
  nsCOMPtr<nsIPrincipal> loadingPrincipal = loadInfo->LoadingPrincipal();
2095
0
  uint32_t mode = loadInfo->GetSecurityMode();
2096
0
  bool dataInherits =
2097
0
    mode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS ||
2098
0
    mode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS ||
2099
0
    mode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
2100
0
2101
0
  bool aboutBlankInherits = dataInherits && loadInfo->GetAboutBlankInherits();
2102
0
2103
0
  for (nsIRedirectHistoryEntry* redirectHistoryEntry : loadInfo->RedirectChain()) {
2104
0
    nsCOMPtr<nsIPrincipal> principal;
2105
0
    redirectHistoryEntry->GetPrincipal(getter_AddRefs(principal));
2106
0
    if (!principal) {
2107
0
      return true;
2108
0
    }
2109
0
2110
0
    nsCOMPtr<nsIURI> uri;
2111
0
    principal->GetURI(getter_AddRefs(uri));
2112
0
    if (!uri) {
2113
0
      return true;
2114
0
    }
2115
0
2116
0
    if (aboutBlankInherits && NS_IsAboutBlank(uri)) {
2117
0
      continue;
2118
0
    }
2119
0
2120
0
    if (NS_FAILED(loadingPrincipal->CheckMayLoad(uri, aReport, dataInherits))) {
2121
0
      return true;
2122
0
    }
2123
0
  }
2124
0
2125
0
  nsCOMPtr<nsIURI> uri;
2126
0
  NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
2127
0
  if (!uri) {
2128
0
    return true;
2129
0
  }
2130
0
2131
0
  if (aboutBlankInherits && NS_IsAboutBlank(uri)) {
2132
0
    return false;
2133
0
  }
2134
0
2135
0
  return NS_FAILED(loadingPrincipal->CheckMayLoad(uri, aReport, dataInherits));
2136
0
}
2137
2138
bool
2139
NS_IsSafeTopLevelNav(nsIChannel* aChannel)
2140
0
{
2141
0
  if (!aChannel) {
2142
0
    return false;
2143
0
  }
2144
0
  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
2145
0
  if (!loadInfo) {
2146
0
    return false;
2147
0
  }
2148
0
  if (loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) {
2149
0
    return false;
2150
0
  }
2151
0
  RefPtr<HttpBaseChannel> baseChan = do_QueryObject(aChannel);
2152
0
  if (!baseChan) {
2153
0
    return false;
2154
0
  }
2155
0
  nsHttpRequestHead *requestHead = baseChan->GetRequestHead();
2156
0
  if (!requestHead) {
2157
0
    return false;
2158
0
  }
2159
0
  return requestHead->IsSafeMethod();
2160
0
}
2161
2162
bool NS_IsSameSiteForeign(nsIChannel* aChannel, nsIURI* aHostURI)
2163
0
{
2164
0
  if (!aChannel) {
2165
0
    return false;
2166
0
  }
2167
0
  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
2168
0
  if (!loadInfo) {
2169
0
    return false;
2170
0
  }
2171
0
2172
0
  // Do not treat loads triggered by web extensions as foreign
2173
0
  nsCOMPtr<nsIURI> channelURI;
2174
0
  NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
2175
0
  if (BasePrincipal::Cast(loadInfo->TriggeringPrincipal())->
2176
0
        AddonAllowsLoad(channelURI)) {
2177
0
    return false;
2178
0
  }
2179
0
2180
0
  nsCOMPtr<nsIURI> uri;
2181
0
  if (loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT) {
2182
0
    // for loads of TYPE_DOCUMENT we query the hostURI from the triggeringPricnipal
2183
0
    // which returns the URI of the document that caused the navigation.
2184
0
    loadInfo->TriggeringPrincipal()->GetURI(getter_AddRefs(uri));
2185
0
  }
2186
0
  else {
2187
0
    uri = aHostURI;
2188
0
  }
2189
0
2190
0
  nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
2191
0
    do_GetService(THIRDPARTYUTIL_CONTRACTID);
2192
0
  if (!thirdPartyUtil) {
2193
0
    return false;
2194
0
  }
2195
0
2196
0
  bool isForeign = true;
2197
0
  nsresult rv = thirdPartyUtil->IsThirdPartyChannel(aChannel, uri, &isForeign);
2198
0
  // if we are dealing with a cross origin request, we can return here
2199
0
  // because we already know the request is 'foreign'.
2200
0
  if (NS_FAILED(rv) || isForeign) {
2201
0
    return true;
2202
0
  }
2203
0
2204
0
  // for loads of TYPE_SUBDOCUMENT we have to perform an additional test, because
2205
0
  // a cross-origin iframe might perform a navigation to a same-origin iframe which
2206
0
  // would send same-site cookies. Hence, if the iframe navigation was triggered
2207
0
  // by a cross-origin triggeringPrincipal, we treat the load as foreign.
2208
0
  if (loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_SUBDOCUMENT) {
2209
0
    nsCOMPtr<nsIURI> triggeringPrincipalURI;
2210
0
    loadInfo->TriggeringPrincipal()->GetURI(getter_AddRefs(triggeringPrincipalURI));
2211
0
    rv = thirdPartyUtil->IsThirdPartyChannel(aChannel, triggeringPrincipalURI, &isForeign);
2212
0
    if (NS_FAILED(rv) || isForeign) {
2213
0
      return true;
2214
0
    }
2215
0
  }
2216
0
2217
0
  // for the purpose of same-site cookies we have to treat any cross-origin
2218
0
  // redirects as foreign. E.g. cross-site to same-site redirect is a problem
2219
0
  // with regards to CSRF.
2220
0
2221
0
  nsCOMPtr<nsIPrincipal> redirectPrincipal;
2222
0
  nsCOMPtr<nsIURI> redirectURI;
2223
0
  for (nsIRedirectHistoryEntry* entry : loadInfo->RedirectChain()) {
2224
0
    entry->GetPrincipal(getter_AddRefs(redirectPrincipal));
2225
0
    if (redirectPrincipal) {
2226
0
      redirectPrincipal->GetURI(getter_AddRefs(redirectURI));
2227
0
      rv = thirdPartyUtil->IsThirdPartyChannel(aChannel, redirectURI, &isForeign);
2228
0
      // if at any point we encounter a cross-origin redirect we can return.
2229
0
      if (NS_FAILED(rv) || isForeign) {
2230
0
        return true;
2231
0
      }
2232
0
    }
2233
0
  }
2234
0
  return isForeign;
2235
0
}
2236
2237
bool
2238
NS_ShouldCheckAppCache(nsIPrincipal *aPrincipal)
2239
0
{
2240
0
    uint32_t privateBrowsingId = 0;
2241
0
    nsresult rv = aPrincipal->GetPrivateBrowsingId(&privateBrowsingId);
2242
0
    if (NS_SUCCEEDED(rv) && (privateBrowsingId > 0)) {
2243
0
        return false;
2244
0
    }
2245
0
2246
0
    nsCOMPtr<nsIOfflineCacheUpdateService> offlineService =
2247
0
        do_GetService("@mozilla.org/offlinecacheupdate-service;1");
2248
0
    if (!offlineService) {
2249
0
        return false;
2250
0
    }
2251
0
2252
0
    bool allowed;
2253
0
    rv = offlineService->OfflineAppAllowed(aPrincipal, nullptr, &allowed);
2254
0
    return NS_SUCCEEDED(rv) && allowed;
2255
0
}
2256
2257
void
2258
NS_WrapAuthPrompt(nsIAuthPrompt   *aAuthPrompt,
2259
                  nsIAuthPrompt2 **aAuthPrompt2)
2260
0
{
2261
0
    nsCOMPtr<nsIAuthPromptAdapterFactory> factory =
2262
0
        do_GetService(NS_AUTHPROMPT_ADAPTER_FACTORY_CONTRACTID);
2263
0
    if (!factory)
2264
0
        return;
2265
0
2266
0
    NS_WARNING("Using deprecated nsIAuthPrompt");
2267
0
    factory->CreateAdapter(aAuthPrompt, aAuthPrompt2);
2268
0
}
2269
2270
void
2271
NS_QueryAuthPrompt2(nsIInterfaceRequestor  *aCallbacks,
2272
                    nsIAuthPrompt2        **aAuthPrompt)
2273
0
{
2274
0
    CallGetInterface(aCallbacks, aAuthPrompt);
2275
0
    if (*aAuthPrompt)
2276
0
        return;
2277
0
2278
0
    // Maybe only nsIAuthPrompt is provided and we have to wrap it.
2279
0
    nsCOMPtr<nsIAuthPrompt> prompt(do_GetInterface(aCallbacks));
2280
0
    if (!prompt)
2281
0
        return;
2282
0
2283
0
    NS_WrapAuthPrompt(prompt, aAuthPrompt);
2284
0
}
2285
2286
void
2287
NS_QueryAuthPrompt2(nsIChannel      *aChannel,
2288
                    nsIAuthPrompt2 **aAuthPrompt)
2289
0
{
2290
0
    *aAuthPrompt = nullptr;
2291
0
2292
0
    // We want to use any auth prompt we can find on the channel's callbacks,
2293
0
    // and if that fails use the loadgroup's prompt (if any)
2294
0
    // Therefore, we can't just use NS_QueryNotificationCallbacks, because
2295
0
    // that would prefer a loadgroup's nsIAuthPrompt2 over a channel's
2296
0
    // nsIAuthPrompt.
2297
0
    nsCOMPtr<nsIInterfaceRequestor> callbacks;
2298
0
    aChannel->GetNotificationCallbacks(getter_AddRefs(callbacks));
2299
0
    if (callbacks) {
2300
0
        NS_QueryAuthPrompt2(callbacks, aAuthPrompt);
2301
0
        if (*aAuthPrompt)
2302
0
            return;
2303
0
    }
2304
0
2305
0
    nsCOMPtr<nsILoadGroup> group;
2306
0
    aChannel->GetLoadGroup(getter_AddRefs(group));
2307
0
    if (!group)
2308
0
        return;
2309
0
2310
0
    group->GetNotificationCallbacks(getter_AddRefs(callbacks));
2311
0
    if (!callbacks)
2312
0
        return;
2313
0
    NS_QueryAuthPrompt2(callbacks, aAuthPrompt);
2314
0
}
2315
2316
nsresult
2317
NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor  *callbacks,
2318
                                       nsILoadGroup           *loadGroup,
2319
                                       nsIEventTarget         *target,
2320
                                       nsIInterfaceRequestor **result)
2321
0
{
2322
0
    nsCOMPtr<nsIInterfaceRequestor> cbs;
2323
0
    if (loadGroup)
2324
0
        loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
2325
0
    return NS_NewInterfaceRequestorAggregation(callbacks, cbs, target, result);
2326
0
}
2327
2328
nsresult
2329
NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor  *callbacks,
2330
                                       nsILoadGroup           *loadGroup,
2331
                                       nsIInterfaceRequestor **result)
2332
0
{
2333
0
    return NS_NewNotificationCallbacksAggregation(callbacks, loadGroup, nullptr, result);
2334
0
}
2335
2336
nsresult
2337
NS_DoImplGetInnermostURI(nsINestedURI *nestedURI, nsIURI **result)
2338
0
{
2339
0
    MOZ_ASSERT(nestedURI, "Must have a nested URI!");
2340
0
    MOZ_ASSERT(!*result, "Must have null *result");
2341
0
2342
0
    nsCOMPtr<nsIURI> inner;
2343
0
    nsresult rv = nestedURI->GetInnerURI(getter_AddRefs(inner));
2344
0
    NS_ENSURE_SUCCESS(rv, rv);
2345
0
2346
0
    // We may need to loop here until we reach the innermost
2347
0
    // URI.
2348
0
    nsCOMPtr<nsINestedURI> nestedInner(do_QueryInterface(inner));
2349
0
    while (nestedInner) {
2350
0
        rv = nestedInner->GetInnerURI(getter_AddRefs(inner));
2351
0
        NS_ENSURE_SUCCESS(rv, rv);
2352
0
        nestedInner = do_QueryInterface(inner);
2353
0
    }
2354
0
2355
0
    // Found the innermost one if we reach here.
2356
0
    inner.swap(*result);
2357
0
2358
0
    return rv;
2359
0
}
2360
2361
nsresult
2362
NS_ImplGetInnermostURI(nsINestedURI *nestedURI, nsIURI **result)
2363
0
{
2364
0
    // Make it safe to use swap()
2365
0
    *result = nullptr;
2366
0
2367
0
    return NS_DoImplGetInnermostURI(nestedURI, result);
2368
0
}
2369
2370
already_AddRefed<nsIURI>
2371
NS_GetInnermostURI(nsIURI *aURI)
2372
5.77k
{
2373
5.77k
    MOZ_ASSERT(aURI, "Must have URI");
2374
5.77k
2375
5.77k
    nsCOMPtr<nsIURI> uri = aURI;
2376
5.77k
2377
5.77k
    nsCOMPtr<nsINestedURI> nestedURI(do_QueryInterface(uri));
2378
5.77k
    if (!nestedURI) {
2379
5.77k
        return uri.forget();
2380
5.77k
    }
2381
0
2382
0
    nsresult rv = nestedURI->GetInnermostURI(getter_AddRefs(uri));
2383
0
    if (NS_FAILED(rv)) {
2384
0
        return nullptr;
2385
0
    }
2386
0
2387
0
    return uri.forget();
2388
0
}
2389
2390
nsresult
2391
NS_GetFinalChannelURI(nsIChannel *channel, nsIURI **uri)
2392
10
{
2393
10
    *uri = nullptr;
2394
10
2395
10
    nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
2396
10
    if (loadInfo) {
2397
10
        nsCOMPtr<nsIURI> resultPrincipalURI;
2398
10
        loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
2399
10
        if (resultPrincipalURI) {
2400
0
            resultPrincipalURI.forget(uri);
2401
0
            return NS_OK;
2402
0
        }
2403
10
    }
2404
10
2405
10
    return channel->GetOriginalURI(uri);
2406
10
}
2407
2408
nsresult
2409
NS_URIChainHasFlags(nsIURI   *uri,
2410
                    uint32_t  flags,
2411
                    bool     *result)
2412
11.6k
{
2413
11.6k
    nsresult rv;
2414
11.6k
    nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
2415
11.6k
    NS_ENSURE_SUCCESS(rv, rv);
2416
11.6k
2417
11.6k
    return util->URIChainHasFlags(uri, flags, result);
2418
11.6k
}
2419
2420
uint32_t
2421
NS_SecurityHashURI(nsIURI *aURI)
2422
0
{
2423
0
    nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
2424
0
2425
0
    nsAutoCString scheme;
2426
0
    uint32_t schemeHash = 0;
2427
0
    if (NS_SUCCEEDED(baseURI->GetScheme(scheme)))
2428
0
        schemeHash = mozilla::HashString(scheme);
2429
0
2430
0
    // TODO figure out how to hash file:// URIs
2431
0
    if (scheme.EqualsLiteral("file"))
2432
0
        return schemeHash; // sad face
2433
0
2434
#if IS_ORIGIN_IS_FULL_SPEC_DEFINED
2435
    bool hasFlag;
2436
    if (NS_FAILED(NS_URIChainHasFlags(baseURI,
2437
        nsIProtocolHandler::ORIGIN_IS_FULL_SPEC, &hasFlag)) ||
2438
        hasFlag)
2439
    {
2440
        nsAutoCString spec;
2441
        uint32_t specHash;
2442
        nsresult res = baseURI->GetSpec(spec);
2443
        if (NS_SUCCEEDED(res))
2444
            specHash = mozilla::HashString(spec);
2445
        else
2446
            specHash = static_cast<uint32_t>(res);
2447
        return specHash;
2448
    }
2449
#endif
2450
2451
0
    nsAutoCString host;
2452
0
    uint32_t hostHash = 0;
2453
0
    if (NS_SUCCEEDED(baseURI->GetAsciiHost(host)))
2454
0
        hostHash = mozilla::HashString(host);
2455
0
2456
0
    return mozilla::AddToHash(schemeHash, hostHash, NS_GetRealPort(baseURI));
2457
0
}
2458
2459
bool
2460
NS_SecurityCompareURIs(nsIURI *aSourceURI,
2461
                       nsIURI *aTargetURI,
2462
                       bool    aStrictFileOriginPolicy)
2463
0
{
2464
0
    nsresult rv;
2465
0
2466
0
    // Note that this is not an Equals() test on purpose -- for URIs that don't
2467
0
    // support host/port, we want equality to basically be object identity, for
2468
0
    // security purposes.  Otherwise, for example, two javascript: URIs that
2469
0
    // are otherwise unrelated could end up "same origin", which would be
2470
0
    // unfortunate.
2471
0
    if (aSourceURI && aSourceURI == aTargetURI)
2472
0
    {
2473
0
        return true;
2474
0
    }
2475
0
2476
0
    if (!aTargetURI || !aSourceURI)
2477
0
    {
2478
0
        return false;
2479
0
    }
2480
0
2481
0
    // If either URI is a nested URI, get the base URI
2482
0
    nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(aSourceURI);
2483
0
    nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI);
2484
0
2485
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
2486
    // Check if either URI has a special origin.
2487
    nsCOMPtr<nsIURI> origin;
2488
    nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin = do_QueryInterface(sourceBaseURI);
2489
    if (uriWithSpecialOrigin) {
2490
      rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
2491
      if (NS_WARN_IF(NS_FAILED(rv))) {
2492
        return false;
2493
      }
2494
      MOZ_ASSERT(origin);
2495
      sourceBaseURI = origin;
2496
    }
2497
    uriWithSpecialOrigin = do_QueryInterface(targetBaseURI);
2498
    if (uriWithSpecialOrigin) {
2499
      rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
2500
      if (NS_WARN_IF(NS_FAILED(rv))) {
2501
        return false;
2502
      }
2503
      MOZ_ASSERT(origin);
2504
      targetBaseURI = origin;
2505
    }
2506
#endif
2507
2508
0
    nsCOMPtr<nsIPrincipal> sourceBlobPrincipal;
2509
0
    if (BlobURLProtocolHandler::GetBlobURLPrincipal(sourceBaseURI,
2510
0
                                                    getter_AddRefs(sourceBlobPrincipal))) {
2511
0
      nsCOMPtr<nsIURI> sourceBlobOwnerURI;
2512
0
      rv = sourceBlobPrincipal->GetURI(getter_AddRefs(sourceBlobOwnerURI));
2513
0
      if (NS_SUCCEEDED(rv)) {
2514
0
        sourceBaseURI = sourceBlobOwnerURI;
2515
0
      }
2516
0
    }
2517
0
2518
0
    nsCOMPtr<nsIPrincipal> targetBlobPrincipal;
2519
0
    if (BlobURLProtocolHandler::GetBlobURLPrincipal(targetBaseURI,
2520
0
                                                    getter_AddRefs(targetBlobPrincipal))) {
2521
0
      nsCOMPtr<nsIURI> targetBlobOwnerURI;
2522
0
      rv = targetBlobPrincipal->GetURI(getter_AddRefs(targetBlobOwnerURI));
2523
0
      if (NS_SUCCEEDED(rv)) {
2524
0
        targetBaseURI = targetBlobOwnerURI;
2525
0
      }
2526
0
    }
2527
0
2528
0
    if (!sourceBaseURI || !targetBaseURI)
2529
0
        return false;
2530
0
2531
0
    // Compare schemes
2532
0
    nsAutoCString targetScheme;
2533
0
    bool sameScheme = false;
2534
0
    if (NS_FAILED( targetBaseURI->GetScheme(targetScheme) ) ||
2535
0
        NS_FAILED( sourceBaseURI->SchemeIs(targetScheme.get(), &sameScheme) ) ||
2536
0
        !sameScheme)
2537
0
    {
2538
0
        // Not same-origin if schemes differ
2539
0
        return false;
2540
0
    }
2541
0
2542
0
    // For file scheme, reject unless the files are identical. See
2543
0
    // NS_RelaxStrictFileOriginPolicy for enforcing file same-origin checking
2544
0
    if (targetScheme.EqualsLiteral("file"))
2545
0
    {
2546
0
        // in traditional unsafe behavior all files are the same origin
2547
0
        if (!aStrictFileOriginPolicy)
2548
0
            return true;
2549
0
2550
0
        nsCOMPtr<nsIFileURL> sourceFileURL(do_QueryInterface(sourceBaseURI));
2551
0
        nsCOMPtr<nsIFileURL> targetFileURL(do_QueryInterface(targetBaseURI));
2552
0
2553
0
        if (!sourceFileURL || !targetFileURL)
2554
0
            return false;
2555
0
2556
0
        nsCOMPtr<nsIFile> sourceFile, targetFile;
2557
0
2558
0
        sourceFileURL->GetFile(getter_AddRefs(sourceFile));
2559
0
        targetFileURL->GetFile(getter_AddRefs(targetFile));
2560
0
2561
0
        if (!sourceFile || !targetFile)
2562
0
            return false;
2563
0
2564
0
        // Otherwise they had better match
2565
0
        bool filesAreEqual = false;
2566
0
        rv = sourceFile->Equals(targetFile, &filesAreEqual);
2567
0
        return NS_SUCCEEDED(rv) && filesAreEqual;
2568
0
    }
2569
0
2570
#if IS_ORIGIN_IS_FULL_SPEC_DEFINED
2571
    bool hasFlag;
2572
    if (NS_FAILED(NS_URIChainHasFlags(targetBaseURI,
2573
        nsIProtocolHandler::ORIGIN_IS_FULL_SPEC, &hasFlag)) ||
2574
        hasFlag)
2575
    {
2576
        // URIs with this flag have the whole spec as a distinct trust
2577
        // domain; use the whole spec for comparison
2578
        nsAutoCString targetSpec;
2579
        nsAutoCString sourceSpec;
2580
        return ( NS_SUCCEEDED( targetBaseURI->GetSpec(targetSpec) ) &&
2581
                 NS_SUCCEEDED( sourceBaseURI->GetSpec(sourceSpec) ) &&
2582
                 targetSpec.Equals(sourceSpec) );
2583
    }
2584
#endif
2585
2586
0
    // Compare hosts
2587
0
    nsAutoCString targetHost;
2588
0
    nsAutoCString sourceHost;
2589
0
    if (NS_FAILED( targetBaseURI->GetAsciiHost(targetHost) ) ||
2590
0
        NS_FAILED( sourceBaseURI->GetAsciiHost(sourceHost) ))
2591
0
    {
2592
0
        return false;
2593
0
    }
2594
0
2595
0
    nsCOMPtr<nsIStandardURL> targetURL(do_QueryInterface(targetBaseURI));
2596
0
    nsCOMPtr<nsIStandardURL> sourceURL(do_QueryInterface(sourceBaseURI));
2597
0
    if (!targetURL || !sourceURL)
2598
0
    {
2599
0
        return false;
2600
0
    }
2601
0
2602
0
    if (!targetHost.Equals(sourceHost, nsCaseInsensitiveCStringComparator() ))
2603
0
    {
2604
0
        return false;
2605
0
    }
2606
0
2607
0
    return NS_GetRealPort(targetBaseURI) == NS_GetRealPort(sourceBaseURI);
2608
0
}
2609
2610
bool
2611
NS_URIIsLocalFile(nsIURI *aURI)
2612
0
{
2613
0
  nsCOMPtr<nsINetUtil> util = do_GetNetUtil();
2614
0
2615
0
  bool isFile;
2616
0
  return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
2617
0
                                nsIProtocolHandler::URI_IS_LOCAL_FILE,
2618
0
                                &isFile)) &&
2619
0
         isFile;
2620
0
}
2621
2622
bool
2623
NS_RelaxStrictFileOriginPolicy(nsIURI *aTargetURI,
2624
                               nsIURI *aSourceURI,
2625
                               bool aAllowDirectoryTarget /* = false */)
2626
0
{
2627
0
  if (!NS_URIIsLocalFile(aTargetURI)) {
2628
0
    // This is probably not what the caller intended
2629
0
    MOZ_ASSERT_UNREACHABLE("NS_RelaxStrictFileOriginPolicy called with non-file URI");
2630
0
    return false;
2631
0
  }
2632
0
2633
0
  if (!NS_URIIsLocalFile(aSourceURI)) {
2634
0
    // If the source is not also a file: uri then forget it
2635
0
    // (don't want resource: principals in a file: doc)
2636
0
    //
2637
0
    // note: we're not de-nesting jar: uris here, we want to
2638
0
    // keep archive content bottled up in its own little island
2639
0
    return false;
2640
0
  }
2641
0
2642
0
  //
2643
0
  // pull out the internal files
2644
0
  //
2645
0
  nsCOMPtr<nsIFileURL> targetFileURL(do_QueryInterface(aTargetURI));
2646
0
  nsCOMPtr<nsIFileURL> sourceFileURL(do_QueryInterface(aSourceURI));
2647
0
  nsCOMPtr<nsIFile> targetFile;
2648
0
  nsCOMPtr<nsIFile> sourceFile;
2649
0
  bool targetIsDir;
2650
0
2651
0
  // Make sure targetFile is not a directory (bug 209234)
2652
0
  // and that it exists w/out unescaping (bug 395343)
2653
0
  if (!sourceFileURL || !targetFileURL ||
2654
0
      NS_FAILED(targetFileURL->GetFile(getter_AddRefs(targetFile))) ||
2655
0
      NS_FAILED(sourceFileURL->GetFile(getter_AddRefs(sourceFile))) ||
2656
0
      !targetFile || !sourceFile ||
2657
0
      NS_FAILED(targetFile->Normalize()) ||
2658
0
#ifndef MOZ_WIDGET_ANDROID
2659
0
      NS_FAILED(sourceFile->Normalize()) ||
2660
0
#endif
2661
0
      (!aAllowDirectoryTarget &&
2662
0
       (NS_FAILED(targetFile->IsDirectory(&targetIsDir)) || targetIsDir))) {
2663
0
    return false;
2664
0
  }
2665
0
2666
0
  //
2667
0
  // If the file to be loaded is in a subdirectory of the source
2668
0
  // (or same-dir if source is not a directory) then it will
2669
0
  // inherit its source principal and be scriptable by that source.
2670
0
  //
2671
0
  bool sourceIsDir;
2672
0
  bool allowed = false;
2673
0
  nsresult rv = sourceFile->IsDirectory(&sourceIsDir);
2674
0
  if (NS_SUCCEEDED(rv) && sourceIsDir) {
2675
0
    rv = sourceFile->Contains(targetFile, &allowed);
2676
0
  } else {
2677
0
    nsCOMPtr<nsIFile> sourceParent;
2678
0
    rv = sourceFile->GetParent(getter_AddRefs(sourceParent));
2679
0
    if (NS_SUCCEEDED(rv) && sourceParent) {
2680
0
      rv = sourceParent->Equals(targetFile, &allowed);
2681
0
      if (NS_FAILED(rv) || !allowed) {
2682
0
        rv = sourceParent->Contains(targetFile, &allowed);
2683
0
      } else {
2684
0
        MOZ_ASSERT(aAllowDirectoryTarget,
2685
0
                   "sourceFile->Parent == targetFile, but targetFile "
2686
0
                   "should've been disallowed if it is a directory");
2687
0
      }
2688
0
    }
2689
0
  }
2690
0
2691
0
  if (NS_SUCCEEDED(rv) && allowed) {
2692
0
    return true;
2693
0
  }
2694
0
2695
0
  return false;
2696
0
}
2697
2698
bool
2699
NS_IsInternalSameURIRedirect(nsIChannel *aOldChannel,
2700
                             nsIChannel *aNewChannel,
2701
                             uint32_t aFlags)
2702
0
{
2703
0
  if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
2704
0
    return false;
2705
0
  }
2706
0
2707
0
  nsCOMPtr<nsIURI> oldURI, newURI;
2708
0
  aOldChannel->GetURI(getter_AddRefs(oldURI));
2709
0
  aNewChannel->GetURI(getter_AddRefs(newURI));
2710
0
2711
0
  if (!oldURI || !newURI) {
2712
0
    return false;
2713
0
  }
2714
0
2715
0
  bool res;
2716
0
  return NS_SUCCEEDED(oldURI->Equals(newURI, &res)) && res;
2717
0
}
2718
2719
bool
2720
NS_IsHSTSUpgradeRedirect(nsIChannel *aOldChannel,
2721
                         nsIChannel *aNewChannel,
2722
                         uint32_t aFlags)
2723
0
{
2724
0
  if (!(aFlags & nsIChannelEventSink::REDIRECT_STS_UPGRADE)) {
2725
0
    return false;
2726
0
  }
2727
0
2728
0
  nsCOMPtr<nsIURI> oldURI, newURI;
2729
0
  aOldChannel->GetURI(getter_AddRefs(oldURI));
2730
0
  aNewChannel->GetURI(getter_AddRefs(newURI));
2731
0
2732
0
  if (!oldURI || !newURI) {
2733
0
    return false;
2734
0
  }
2735
0
2736
0
  bool isHttp;
2737
0
  if (NS_FAILED(oldURI->SchemeIs("http", &isHttp)) || !isHttp) {
2738
0
    return false;
2739
0
  }
2740
0
2741
0
  nsCOMPtr<nsIURI> upgradedURI;
2742
0
  nsresult rv = NS_GetSecureUpgradedURI(oldURI, getter_AddRefs(upgradedURI));
2743
0
  if (NS_FAILED(rv)) {
2744
0
    return false;
2745
0
  }
2746
0
2747
0
  bool res;
2748
0
  return NS_SUCCEEDED(upgradedURI->Equals(newURI, &res)) && res;
2749
0
}
2750
2751
nsresult
2752
NS_LinkRedirectChannels(uint32_t channelId,
2753
                        nsIParentChannel *parentChannel,
2754
                        nsIChannel **_result)
2755
0
{
2756
0
  nsCOMPtr<nsIRedirectChannelRegistrar> registrar =
2757
0
      RedirectChannelRegistrar::GetOrCreate();
2758
0
  MOZ_ASSERT(registrar);
2759
0
2760
0
  return registrar->LinkChannels(channelId,
2761
0
                                 parentChannel,
2762
0
                                 _result);
2763
0
}
2764
2765
nsresult NS_MaybeOpenChannelUsingOpen2(nsIChannel* aChannel,
2766
                                       nsIInputStream **aStream)
2767
5
{
2768
5
  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
2769
5
  if (loadInfo && loadInfo->GetSecurityMode() != 0) {
2770
5
    return aChannel->Open2(aStream);
2771
5
  }
2772
0
  return aChannel->Open(aStream);
2773
0
}
2774
2775
nsresult NS_MaybeOpenChannelUsingAsyncOpen2(nsIChannel* aChannel,
2776
                                            nsIStreamListener *aListener)
2777
0
{
2778
0
  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
2779
0
  if (loadInfo && loadInfo->GetSecurityMode() != 0) {
2780
0
    return aChannel->AsyncOpen2(aListener);
2781
0
  }
2782
0
  return aChannel->AsyncOpen(aListener, nullptr);
2783
0
}
2784
2785
/** Given the first (disposition) token from a Content-Disposition header,
2786
 * tell whether it indicates the content is inline or attachment
2787
 * @param aDispToken the disposition token from the content-disposition header
2788
 */
2789
uint32_t
2790
NS_GetContentDispositionFromToken(const nsAString &aDispToken)
2791
0
{
2792
0
  // RFC 2183, section 2.8 says that an unknown disposition
2793
0
  // value should be treated as "attachment"
2794
0
  // If all of these tests eval to false, then we have a content-disposition of
2795
0
  // "attachment" or unknown
2796
0
  if (aDispToken.IsEmpty() ||
2797
0
      aDispToken.LowerCaseEqualsLiteral("inline") ||
2798
0
      // Broken sites just send
2799
0
      // Content-Disposition: filename="file"
2800
0
      // without a disposition token... screen those out.
2801
0
      StringHead(aDispToken, 8).LowerCaseEqualsLiteral("filename"))
2802
0
    return nsIChannel::DISPOSITION_INLINE;
2803
0
2804
0
  return nsIChannel::DISPOSITION_ATTACHMENT;
2805
0
}
2806
2807
uint32_t
2808
NS_GetContentDispositionFromHeader(const nsACString &aHeader,
2809
                                   nsIChannel *aChan /* = nullptr */)
2810
0
{
2811
0
  nsresult rv;
2812
0
  nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar = do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
2813
0
  if (NS_FAILED(rv))
2814
0
    return nsIChannel::DISPOSITION_ATTACHMENT;
2815
0
2816
0
  nsAutoString dispToken;
2817
0
  rv = mimehdrpar->GetParameterHTTP(aHeader, "", EmptyCString(), true, nullptr,
2818
0
                                    dispToken);
2819
0
2820
0
  if (NS_FAILED(rv)) {
2821
0
    // special case (see bug 272541): empty disposition type handled as "inline"
2822
0
    if (rv == NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY)
2823
0
        return nsIChannel::DISPOSITION_INLINE;
2824
0
    return nsIChannel::DISPOSITION_ATTACHMENT;
2825
0
  }
2826
0
2827
0
  return NS_GetContentDispositionFromToken(dispToken);
2828
0
}
2829
2830
nsresult
2831
NS_GetFilenameFromDisposition(nsAString &aFilename,
2832
                              const nsACString &aDisposition,
2833
                              nsIURI *aURI /* = nullptr */)
2834
0
{
2835
0
  aFilename.Truncate();
2836
0
2837
0
  nsresult rv;
2838
0
  nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
2839
0
      do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
2840
0
  if (NS_FAILED(rv))
2841
0
    return rv;
2842
0
2843
0
  // Get the value of 'filename' parameter
2844
0
  rv = mimehdrpar->GetParameterHTTP(aDisposition, "filename",
2845
0
                                    EmptyCString(), true, nullptr,
2846
0
                                    aFilename);
2847
0
2848
0
  if (NS_FAILED(rv)) {
2849
0
    aFilename.Truncate();
2850
0
    return rv;
2851
0
  }
2852
0
2853
0
  if (aFilename.IsEmpty())
2854
0
    return NS_ERROR_NOT_AVAILABLE;
2855
0
2856
0
  return NS_OK;
2857
0
}
2858
2859
void net_EnsurePSMInit()
2860
0
{
2861
0
    nsresult rv;
2862
0
    nsCOMPtr<nsISupports> psm = do_GetService(PSM_COMPONENT_CONTRACTID, &rv);
2863
0
    MOZ_ASSERT(NS_SUCCEEDED(rv));
2864
0
2865
0
    nsCOMPtr<nsISupports> sss = do_GetService(NS_SSSERVICE_CONTRACTID);
2866
0
    nsCOMPtr<nsISupports> cbl = do_GetService(NS_CERTBLOCKLIST_CONTRACTID);
2867
0
    nsCOMPtr<nsISupports> cos = do_GetService(NS_CERTOVERRIDE_CONTRACTID);
2868
0
}
2869
2870
bool NS_IsAboutBlank(nsIURI *uri)
2871
0
{
2872
0
    // GetSpec can be expensive for some URIs, so check the scheme first.
2873
0
    bool isAbout = false;
2874
0
    if (NS_FAILED(uri->SchemeIs("about", &isAbout)) || !isAbout) {
2875
0
        return false;
2876
0
    }
2877
0
2878
0
    return uri->GetSpecOrDefault().EqualsLiteral("about:blank");
2879
0
}
2880
2881
nsresult
2882
NS_GenerateHostPort(const nsCString& host, int32_t port,
2883
                    nsACString &hostLine)
2884
0
{
2885
0
    if (strchr(host.get(), ':')) {
2886
0
        // host is an IPv6 address literal and must be encapsulated in []'s
2887
0
        hostLine.Assign('[');
2888
0
        // scope id is not needed for Host header.
2889
0
        int scopeIdPos = host.FindChar('%');
2890
0
        if (scopeIdPos == -1)
2891
0
            hostLine.Append(host);
2892
0
        else if (scopeIdPos > 0)
2893
0
            hostLine.Append(Substring(host, 0, scopeIdPos));
2894
0
        else
2895
0
          return NS_ERROR_MALFORMED_URI;
2896
0
        hostLine.Append(']');
2897
0
    }
2898
0
    else
2899
0
        hostLine.Assign(host);
2900
0
    if (port != -1) {
2901
0
        hostLine.Append(':');
2902
0
        hostLine.AppendInt(port);
2903
0
    }
2904
0
    return NS_OK;
2905
0
}
2906
2907
void
2908
NS_SniffContent(const char *aSnifferType, nsIRequest *aRequest,
2909
                const uint8_t *aData, uint32_t aLength,
2910
                nsACString &aSniffedType)
2911
0
{
2912
0
  typedef nsCategoryCache<nsIContentSniffer> ContentSnifferCache;
2913
0
  extern ContentSnifferCache* gNetSniffers;
2914
0
  extern ContentSnifferCache* gDataSniffers;
2915
0
  ContentSnifferCache* cache = nullptr;
2916
0
  if (!strcmp(aSnifferType, NS_CONTENT_SNIFFER_CATEGORY)) {
2917
0
    if (!gNetSniffers) {
2918
0
      gNetSniffers = new ContentSnifferCache(NS_CONTENT_SNIFFER_CATEGORY);
2919
0
    }
2920
0
    cache = gNetSniffers;
2921
0
  } else if (!strcmp(aSnifferType, NS_DATA_SNIFFER_CATEGORY)) {
2922
0
    if (!gDataSniffers) {
2923
0
      gDataSniffers = new ContentSnifferCache(NS_DATA_SNIFFER_CATEGORY);
2924
0
    }
2925
0
    cache = gDataSniffers;
2926
0
  } else {
2927
0
    // Invalid content sniffer type was requested
2928
0
    MOZ_ASSERT(false);
2929
0
    return;
2930
0
  }
2931
0
2932
0
  nsCOMArray<nsIContentSniffer> sniffers;
2933
0
  cache->GetEntries(sniffers);
2934
0
  for (int32_t i = 0; i < sniffers.Count(); ++i) {
2935
0
    nsresult rv = sniffers[i]->GetMIMETypeFromContent(aRequest, aData, aLength, aSniffedType);
2936
0
    if (NS_SUCCEEDED(rv) && !aSniffedType.IsEmpty()) {
2937
0
      return;
2938
0
    }
2939
0
  }
2940
0
2941
0
  aSniffedType.Truncate();
2942
0
}
2943
2944
bool
2945
NS_IsSrcdocChannel(nsIChannel *aChannel)
2946
0
{
2947
0
  bool isSrcdoc;
2948
0
  nsCOMPtr<nsIInputStreamChannel> isr = do_QueryInterface(aChannel);
2949
0
  if (isr) {
2950
0
    isr->GetIsSrcdocChannel(&isSrcdoc);
2951
0
    return isSrcdoc;
2952
0
  }
2953
0
  nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(aChannel);
2954
0
  if (vsc) {
2955
0
    nsresult rv = vsc->GetIsSrcdocChannel(&isSrcdoc);
2956
0
    if (NS_SUCCEEDED(rv)) {
2957
0
      return isSrcdoc;
2958
0
    }
2959
0
  }
2960
0
  return false;
2961
0
}
2962
2963
nsresult
2964
NS_ShouldSecureUpgrade(nsIURI* aURI,
2965
                       nsILoadInfo* aLoadInfo,
2966
                       nsIPrincipal* aChannelResultPrincipal,
2967
                       bool aPrivateBrowsing,
2968
                       bool aAllowSTS,
2969
                       const OriginAttributes& aOriginAttributes,
2970
                       bool& aShouldUpgrade)
2971
0
{
2972
0
  // Even if we're in private browsing mode, we still enforce existing STS
2973
0
  // data (it is read-only).
2974
0
  // if the connection is not using SSL and either the exact host matches or
2975
0
  // a superdomain wants to force HTTPS, do it.
2976
0
  bool isHttps = false;
2977
0
  nsresult rv = aURI->SchemeIs("https", &isHttps);
2978
0
  NS_ENSURE_SUCCESS(rv, rv);
2979
0
2980
0
  if (!isHttps) {
2981
0
    if (aLoadInfo) {
2982
0
      // If any of the documents up the chain to the root document makes use of
2983
0
      // the CSP directive 'upgrade-insecure-requests', then it's time to fulfill
2984
0
      // the promise to CSP and mixed content blocking to upgrade the channel
2985
0
      // from http to https.
2986
0
      if (aLoadInfo->GetUpgradeInsecureRequests() ||
2987
0
          aLoadInfo->GetBrowserUpgradeInsecureRequests()) {
2988
0
        // let's log a message to the console that we are upgrading a request
2989
0
        nsAutoCString scheme;
2990
0
        aURI->GetScheme(scheme);
2991
0
        // append the additional 's' for security to the scheme :-)
2992
0
        scheme.AppendLiteral("s");
2993
0
        NS_ConvertUTF8toUTF16 reportSpec(aURI->GetSpecOrDefault());
2994
0
        NS_ConvertUTF8toUTF16 reportScheme(scheme);
2995
0
2996
0
        if (aLoadInfo->GetUpgradeInsecureRequests()) {
2997
0
          const char16_t* params[] = { reportSpec.get(), reportScheme.get() };
2998
0
          uint32_t innerWindowId = aLoadInfo->GetInnerWindowID();
2999
0
          CSP_LogLocalizedStr("upgradeInsecureRequest",
3000
0
                              params, ArrayLength(params),
3001
0
                              EmptyString(), // aSourceFile
3002
0
                              EmptyString(), // aScriptSample
3003
0
                              0, // aLineNumber
3004
0
                              0, // aColumnNumber
3005
0
                              nsIScriptError::warningFlag,
3006
0
                              NS_LITERAL_CSTRING("upgradeInsecureRequest"),
3007
0
                              innerWindowId,
3008
0
                              !!aLoadInfo->GetOriginAttributes().mPrivateBrowsingId);
3009
0
          Telemetry::AccumulateCategorical(Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::CSP);
3010
0
        } else {
3011
0
          nsCOMPtr<nsIDocument> doc;
3012
0
          nsINode* node = aLoadInfo->LoadingNode();
3013
0
          if (node) {
3014
0
            doc = node->OwnerDoc();
3015
0
          }
3016
0
3017
0
          nsAutoString brandName;
3018
0
          nsresult rv =
3019
0
            nsContentUtils::GetLocalizedString(nsContentUtils::eBRAND_PROPERTIES,
3020
0
                                               "brandShortName", brandName);
3021
0
          if (NS_SUCCEEDED(rv)) {
3022
0
            const char16_t* params[] = { brandName.get(), reportSpec.get(), reportScheme.get() };
3023
0
            nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
3024
0
                                            NS_LITERAL_CSTRING("DATA_URI_BLOCKED"),
3025
0
                                            doc,
3026
0
                                            nsContentUtils::eSECURITY_PROPERTIES,
3027
0
                                            "BrowserUpgradeInsecureDisplayRequest",
3028
0
                                            params, ArrayLength(params));
3029
0
          }
3030
0
          Telemetry::AccumulateCategorical(Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::BrowserDisplay);
3031
0
        }
3032
0
3033
0
        aShouldUpgrade = true;
3034
0
        return NS_OK;
3035
0
      }
3036
0
    }
3037
0
3038
0
    // enforce Strict-Transport-Security
3039
0
    nsISiteSecurityService* sss = gHttpHandler->GetSSService();
3040
0
    NS_ENSURE_TRUE(sss, NS_ERROR_OUT_OF_MEMORY);
3041
0
3042
0
    bool isStsHost = false;
3043
0
    uint32_t hstsSource = 0;
3044
0
    uint32_t flags = aPrivateBrowsing ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
3045
0
    rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags,
3046
0
                          aOriginAttributes, nullptr, &hstsSource, &isStsHost);
3047
0
3048
0
    // if the SSS check fails, it's likely because this load is on a
3049
0
    // malformed URI or something else in the setup is wrong, so any error
3050
0
    // should be reported.
3051
0
    NS_ENSURE_SUCCESS(rv, rv);
3052
0
3053
0
    if (isStsHost) {
3054
0
      LOG(("nsHttpChannel::Connect() STS permissions found\n"));
3055
0
      if (aAllowSTS) {
3056
0
        Telemetry::AccumulateCategorical(Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::STS);
3057
0
        aShouldUpgrade = true;
3058
0
        switch (hstsSource) {
3059
0
          case nsISiteSecurityService::SOURCE_PRELOAD_LIST:
3060
0
              Telemetry::Accumulate(Telemetry::HSTS_UPGRADE_SOURCE, 0);
3061
0
              break;
3062
0
          case nsISiteSecurityService::SOURCE_ORGANIC_REQUEST:
3063
0
              Telemetry::Accumulate(Telemetry::HSTS_UPGRADE_SOURCE, 1);
3064
0
              break;
3065
0
          case nsISiteSecurityService::SOURCE_UNKNOWN:
3066
0
          default:
3067
0
              // record this as an organic request
3068
0
              Telemetry::Accumulate(Telemetry::HSTS_UPGRADE_SOURCE, 1);
3069
0
              break;
3070
0
        }
3071
0
        return NS_OK;
3072
0
      }
3073
0
      Telemetry::AccumulateCategorical(Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::PrefBlockedSTS);
3074
0
    } else {
3075
0
      Telemetry::AccumulateCategorical(Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::NoReasonToUpgrade);
3076
0
    }
3077
0
  } else {
3078
0
    Telemetry::AccumulateCategorical(Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::AlreadyHTTPS);
3079
0
  }
3080
0
  aShouldUpgrade = false;
3081
0
  return NS_OK;
3082
0
}
3083
3084
nsresult
3085
NS_GetSecureUpgradedURI(nsIURI* aURI, nsIURI** aUpgradedURI)
3086
0
{
3087
0
  NS_MutateURI mutator(aURI);
3088
0
  mutator.SetScheme(NS_LITERAL_CSTRING("https")); // Change the scheme to HTTPS:
3089
0
3090
0
  // Change the default port to 443:
3091
0
  nsCOMPtr<nsIStandardURL> stdURL = do_QueryInterface(aURI);
3092
0
  if (stdURL) {
3093
0
    mutator.Apply(NS_MutatorMethod(&nsIStandardURLMutator::SetDefaultPort, 443, nullptr));
3094
0
  } else {
3095
0
    // If we don't have a nsStandardURL, fall back to using GetPort/SetPort.
3096
0
    // XXXdholbert Is this function even called with a non-nsStandardURL arg,
3097
0
    // in practice?
3098
0
    NS_WARNING("Calling NS_GetSecureUpgradedURI for non nsStandardURL");
3099
0
    int32_t oldPort = -1;
3100
0
    nsresult rv = aURI->GetPort(&oldPort);
3101
0
    if (NS_FAILED(rv)) return rv;
3102
0
3103
0
    // Keep any nonstandard ports so only the scheme is changed.
3104
0
    // For example:
3105
0
    //  http://foo.com:80 -> https://foo.com:443
3106
0
    //  http://foo.com:81 -> https://foo.com:81
3107
0
3108
0
    if (oldPort == 80 || oldPort == -1) {
3109
0
        mutator.SetPort(-1);
3110
0
    } else {
3111
0
        mutator.SetPort(oldPort);
3112
0
    }
3113
0
  }
3114
0
3115
0
  return mutator.Finalize(aUpgradedURI);
3116
0
}
3117
3118
nsresult
3119
NS_CompareLoadInfoAndLoadContext(nsIChannel *aChannel)
3120
0
{
3121
0
  nsCOMPtr<nsILoadInfo> loadInfo;
3122
0
  aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
3123
0
3124
0
  nsCOMPtr<nsILoadContext> loadContext;
3125
0
  NS_QueryNotificationCallbacks(aChannel, loadContext);
3126
0
  if (!loadInfo || !loadContext) {
3127
0
    return NS_OK;
3128
0
  }
3129
0
3130
0
  // We try to skip about:newtab.
3131
0
  // about:newtab will use SystemPrincipal to download thumbnails through
3132
0
  // https:// and blob URLs.
3133
0
  bool isAboutPage = false;
3134
0
  nsINode* node = loadInfo->LoadingNode();
3135
0
  if (node) {
3136
0
    nsIDocument* doc = node->OwnerDoc();
3137
0
    if (doc) {
3138
0
      nsIURI* uri = doc->GetDocumentURI();
3139
0
      nsresult rv = uri->SchemeIs("about", &isAboutPage);
3140
0
      NS_ENSURE_SUCCESS(rv, rv);
3141
0
    }
3142
0
  }
3143
0
3144
0
  if (isAboutPage) {
3145
0
    return NS_OK;
3146
0
  }
3147
0
3148
0
  // We skip the favicon loading here. The favicon loading might be
3149
0
  // triggered by the XUL image. For that case, the loadContext will have
3150
0
  // default originAttributes since the XUL image uses SystemPrincipal, but
3151
0
  // the loadInfo will use originAttributes from the content. Thus, the
3152
0
  // originAttributes between loadInfo and loadContext will be different.
3153
0
  // That's why we have to skip the comparison for the favicon loading.
3154
0
  if (nsContentUtils::IsSystemPrincipal(loadInfo->LoadingPrincipal()) &&
3155
0
      loadInfo->InternalContentPolicyType() ==
3156
0
        nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON) {
3157
0
    return NS_OK;
3158
0
  }
3159
0
3160
0
  bool loadContextIsInBE = false;
3161
0
  nsresult rv = loadContext->GetIsInIsolatedMozBrowserElement(&loadContextIsInBE);
3162
0
  if (NS_FAILED(rv)) {
3163
0
    return NS_ERROR_UNEXPECTED;
3164
0
  }
3165
0
3166
0
  OriginAttributes originAttrsLoadInfo = loadInfo->GetOriginAttributes();
3167
0
  OriginAttributes originAttrsLoadContext;
3168
0
  loadContext->GetOriginAttributes(originAttrsLoadContext);
3169
0
3170
0
  LOG(("NS_CompareLoadInfoAndLoadContext - loadInfo: %d, %d, %d; "
3171
0
       "loadContext: %d %d, %d. [channel=%p]",
3172
0
       originAttrsLoadInfo.mInIsolatedMozBrowser, originAttrsLoadInfo.mUserContextId,
3173
0
       originAttrsLoadInfo.mPrivateBrowsingId, loadContextIsInBE,
3174
0
       originAttrsLoadContext.mUserContextId, originAttrsLoadContext.mPrivateBrowsingId,
3175
0
       aChannel));
3176
0
3177
0
  MOZ_ASSERT(originAttrsLoadInfo.mInIsolatedMozBrowser ==
3178
0
             loadContextIsInBE,
3179
0
             "The value of InIsolatedMozBrowser in the loadContext and in "
3180
0
             "the loadInfo are not the same!");
3181
0
3182
0
  MOZ_ASSERT(originAttrsLoadInfo.mUserContextId ==
3183
0
             originAttrsLoadContext.mUserContextId,
3184
0
             "The value of mUserContextId in the loadContext and in the "
3185
0
             "loadInfo are not the same!");
3186
0
3187
0
  MOZ_ASSERT(originAttrsLoadInfo.mPrivateBrowsingId ==
3188
0
             originAttrsLoadContext.mPrivateBrowsingId,
3189
0
             "The value of mPrivateBrowsingId in the loadContext and in the "
3190
0
             "loadInfo are not the same!");
3191
0
3192
0
  return NS_OK;
3193
0
}
3194
3195
uint32_t
3196
NS_GetDefaultReferrerPolicy(bool privateBrowsing)
3197
0
{
3198
0
  static bool preferencesInitialized = false;
3199
0
3200
0
  if (!preferencesInitialized) {
3201
0
    mozilla::Preferences::AddUintVarCache(&sDefaultRp,
3202
0
                                          "network.http.referer.defaultPolicy",
3203
0
                                          DEFAULT_RP);
3204
0
    mozilla::Preferences::AddUintVarCache(&defaultPrivateRp,
3205
0
                                          "network.http.referer.defaultPolicy.pbmode",
3206
0
                                          DEFAULT_PRIVATE_RP);
3207
0
    preferencesInitialized = true;
3208
0
  }
3209
0
3210
0
  uint32_t defaultToUse;
3211
0
  if (privateBrowsing) {
3212
0
      defaultToUse = defaultPrivateRp;
3213
0
  } else {
3214
0
      defaultToUse = sDefaultRp;
3215
0
  }
3216
0
3217
0
  switch (defaultToUse) {
3218
0
    case 0:
3219
0
      return nsIHttpChannel::REFERRER_POLICY_NO_REFERRER;
3220
0
    case 1:
3221
0
      return nsIHttpChannel::REFERRER_POLICY_SAME_ORIGIN;
3222
0
    case 2:
3223
0
      return nsIHttpChannel::REFERRER_POLICY_STRICT_ORIGIN_WHEN_XORIGIN;
3224
0
  }
3225
0
3226
0
  return nsIHttpChannel::REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE;
3227
0
}
3228
3229
bool
3230
NS_IsOffline()
3231
0
{
3232
0
    bool offline = true;
3233
0
    bool connectivity = true;
3234
0
    nsCOMPtr<nsIIOService> ios = do_GetIOService();
3235
0
    if (ios) {
3236
0
        ios->GetOffline(&offline);
3237
0
        ios->GetConnectivity(&connectivity);
3238
0
    }
3239
0
    return offline || !connectivity;
3240
0
}
3241
3242
namespace mozilla {
3243
namespace net {
3244
3245
bool
3246
InScriptableRange(int64_t val)
3247
0
{
3248
0
    return (val <= kJS_MAX_SAFE_INTEGER) && (val >= kJS_MIN_SAFE_INTEGER);
3249
0
}
3250
3251
bool
3252
InScriptableRange(uint64_t val)
3253
0
{
3254
0
    return val <= kJS_MAX_SAFE_UINTEGER;
3255
0
}
3256
3257
nsresult
3258
GetParameterHTTP(const nsACString& aHeaderVal,
3259
                 const char* aParamName,
3260
                 nsAString& aResult)
3261
0
{
3262
0
  return nsMIMEHeaderParamImpl::GetParameterHTTP(
3263
0
    aHeaderVal, aParamName, aResult);
3264
0
}
3265
3266
} // namespace net
3267
} // namespace mozilla