Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/dom/InternalRequest.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
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
#ifndef mozilla_dom_InternalRequest_h
8
#define mozilla_dom_InternalRequest_h
9
10
#include "mozilla/dom/HeadersBinding.h"
11
#include "mozilla/dom/InternalHeaders.h"
12
#include "mozilla/dom/RequestBinding.h"
13
#include "mozilla/LoadTainting.h"
14
#include "mozilla/net/ReferrerPolicy.h"
15
16
#include "nsIContentPolicy.h"
17
#include "nsIInputStream.h"
18
#include "nsISupportsImpl.h"
19
#ifdef DEBUG
20
#include "nsIURLParser.h"
21
#include "nsNetCID.h"
22
#include "nsServiceManagerUtils.h"
23
#endif
24
25
namespace mozilla {
26
27
namespace ipc {
28
class PrincipalInfo;
29
} // namespace ipc
30
31
namespace dom {
32
33
/*
34
 * The mapping of RequestDestination and nsContentPolicyType is currently as the
35
 * following.  Note that this mapping is not perfect yet (see the TODO comments
36
 * below for examples).
37
 *
38
 * RequestDestination| nsContentPolicyType
39
 * ------------------+--------------------
40
 * audio             | TYPE_INTERNAL_AUDIO
41
 * audioworklet      | TODO
42
 * document          | TYPE_DOCUMENT, TYPE_INTERNAL_IFRAME, TYPE_SUBDOCUMENT
43
 * embed             | TYPE_INTERNAL_EMBED
44
 * font              | TYPE_FONT
45
 * image             | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD,
46
 *                   | TYPE_IMAGE, TYPE_INTERNAL_IMAGE_FAVICON, TYPE_IMAGESET
47
 * manifest          | TYPE_WEB_MANIFEST
48
 * object            | TYPE_INTERNAL_OBJECT, TYPE_OBJECT
49
 * "paintworklet"    | TODO
50
 * report"           | TODO
51
 * script            | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD, TYPE_SCRIPT
52
 *                   | TYPE_INTERNAL_SERVICE_WORKER, TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS
53
 * sharedworker      | TYPE_INTERNAL_SHARED_WORKER
54
 * serviceworker     | The spec lists this as a valid value for the enum,however it
55
 *                   | is impossible to observe a request with this destination value.
56
 * style             | TYPE_INTERNAL_STYLESHEET, TYPE_INTERNAL_STYLESHEET_PRELOAD,
57
 *                   | TYPE_STYLESHEET
58
 * track             | TYPE_INTERNAL_TRACK
59
 * video             | TYPE_INTERNAL_VIDEO
60
 * worker            | TYPE_INTERNAL_WORKER
61
 * xslt              | TYPE_XSLT
62
 * _empty            | Default for everything else.
63
 *
64
 */
65
66
class Request;
67
class IPCInternalRequest;
68
69
#define kFETCH_CLIENT_REFERRER_STR "about:client"
70
class InternalRequest final
71
{
72
  friend class Request;
73
public:
74
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalRequest)
75
  InternalRequest(const nsACString& aURL, const nsACString& aFragment);
76
  InternalRequest(const nsACString& aURL,
77
                  const nsACString& aFragment,
78
                  const nsACString& aMethod,
79
                  already_AddRefed<InternalHeaders> aHeaders,
80
                  RequestCache aCacheMode,
81
                  RequestMode aMode,
82
                  RequestRedirect aRequestRedirect,
83
                  RequestCredentials aRequestCredentials,
84
                  const nsAString& aReferrer,
85
                  ReferrerPolicy aReferrerPolicy,
86
                  nsContentPolicyType aContentPolicyType,
87
                  const nsAString& aIntegrity);
88
89
  explicit InternalRequest(const IPCInternalRequest& aIPCRequest);
90
91
  void ToIPC(IPCInternalRequest* aIPCRequest);
92
93
  already_AddRefed<InternalRequest> Clone();
94
95
  void
96
  GetMethod(nsCString& aMethod) const
97
0
  {
98
0
    aMethod.Assign(mMethod);
99
0
  }
100
101
  void
102
  SetMethod(const nsACString& aMethod)
103
0
  {
104
0
    mMethod.Assign(aMethod);
105
0
  }
106
107
  bool
108
  HasSimpleMethod() const
109
  {
110
    return mMethod.LowerCaseEqualsASCII("get") ||
111
           mMethod.LowerCaseEqualsASCII("post") ||
112
           mMethod.LowerCaseEqualsASCII("head");
113
  }
114
  // GetURL should get the request's current url with fragment. A request has
115
  // an associated current url. It is a pointer to the last fetch URL in
116
  // request's url list.
117
  void
118
  GetURL(nsACString& aURL) const
119
0
  {
120
0
    aURL.Assign(GetURLWithoutFragment());
121
0
    if (GetFragment().IsEmpty()) {
122
0
      return;
123
0
    }
124
0
    aURL.AppendLiteral("#");
125
0
    aURL.Append(GetFragment());
126
0
  }
127
128
  const nsCString&
129
  GetURLWithoutFragment() const
130
0
  {
131
0
    MOZ_RELEASE_ASSERT(!mURLList.IsEmpty(),
132
0
                       "Internal Request's urlList should not be empty.");
133
0
134
0
    return mURLList.LastElement();
135
0
  }
136
137
  // A safe guard for ensuring that request's URL is only allowed to be set in a
138
  // sw internal redirect.
139
  void
140
  SetURLForInternalRedirect(const uint32_t aFlag,
141
                            const nsACString& aURL,
142
                            const nsACString& aFragment)
143
  {
144
    // Only check in debug build to prevent it from being used unexpectedly.
145
    MOZ_ASSERT(aFlag & nsIChannelEventSink::REDIRECT_INTERNAL);
146
147
    return SetURL(aURL, aFragment);
148
  }
149
150
  // AddURL should append the url into url list.
151
  // Normally we strip the fragment from the URL in Request::Constructor and
152
  // pass the fragment as the second argument into it.
153
  // If a fragment is present in the URL it must be stripped and passed in
154
  // separately.
155
  void
156
  AddURL(const nsACString& aURL, const nsACString& aFragment)
157
  {
158
    MOZ_ASSERT(!aURL.IsEmpty());
159
    MOZ_ASSERT(!aURL.Contains('#'));
160
161
    mURLList.AppendElement(aURL);
162
163
    mFragment.Assign(aFragment);
164
  }
165
  // Get the URL list without their fragments.
166
  void
167
  GetURLListWithoutFragment(nsTArray<nsCString>& aURLList)
168
  {
169
    aURLList.Assign(mURLList);
170
  }
171
  void
172
  GetReferrer(nsAString& aReferrer) const
173
0
  {
174
0
    aReferrer.Assign(mReferrer);
175
0
  }
176
177
  void
178
  SetReferrer(const nsAString& aReferrer)
179
0
  {
180
#ifdef DEBUG
181
    bool validReferrer = false;
182
    if (aReferrer.IsEmpty() ||
183
        aReferrer.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
184
      validReferrer = true;
185
    } else {
186
      nsCOMPtr<nsIURLParser> parser = do_GetService(NS_STDURLPARSER_CONTRACTID);
187
      if (!parser) {
188
        NS_WARNING("Could not get parser to validate URL!");
189
      } else {
190
        uint32_t schemePos;
191
        int32_t schemeLen;
192
        uint32_t authorityPos;
193
        int32_t authorityLen;
194
        uint32_t pathPos;
195
        int32_t pathLen;
196
197
        NS_ConvertUTF16toUTF8 ref(aReferrer);
198
        nsresult rv = parser->ParseURL(ref.get(), ref.Length(),
199
                                       &schemePos, &schemeLen,
200
                                       &authorityPos, &authorityLen,
201
                                       &pathPos, &pathLen);
202
        if (NS_FAILED(rv)) {
203
          NS_WARNING("Invalid referrer URL!");
204
        } else if (schemeLen < 0 || authorityLen < 0) {
205
          NS_WARNING("Invalid referrer URL!");
206
        } else {
207
          validReferrer = true;
208
        }
209
      }
210
    }
211
212
    MOZ_ASSERT(validReferrer);
213
#endif
214
215
0
    mReferrer.Assign(aReferrer);
216
0
  }
217
218
  ReferrerPolicy
219
  ReferrerPolicy_() const
220
0
  {
221
0
    return mReferrerPolicy;
222
0
  }
223
224
  void
225
  SetReferrerPolicy(ReferrerPolicy aReferrerPolicy)
226
0
  {
227
0
    mReferrerPolicy = aReferrerPolicy;
228
0
  }
229
230
  void
231
  SetReferrerPolicy(net::ReferrerPolicy aReferrerPolicy)
232
  {
233
    switch (aReferrerPolicy) {
234
      case net::RP_Unset:
235
        mReferrerPolicy = ReferrerPolicy::_empty;
236
        break;
237
      case net::RP_No_Referrer:
238
        mReferrerPolicy = ReferrerPolicy::No_referrer;
239
        break;
240
      case net::RP_No_Referrer_When_Downgrade:
241
        mReferrerPolicy = ReferrerPolicy::No_referrer_when_downgrade;
242
        break;
243
      case net::RP_Origin:
244
        mReferrerPolicy = ReferrerPolicy::Origin;
245
        break;
246
      case net::RP_Origin_When_Crossorigin:
247
        mReferrerPolicy = ReferrerPolicy::Origin_when_cross_origin;
248
        break;
249
      case net::RP_Unsafe_URL:
250
        mReferrerPolicy = ReferrerPolicy::Unsafe_url;
251
        break;
252
      case net::RP_Same_Origin:
253
        mReferrerPolicy = ReferrerPolicy::Same_origin;
254
        break;
255
      case net::RP_Strict_Origin:
256
        mReferrerPolicy = ReferrerPolicy::Strict_origin;
257
        break;
258
      case net::RP_Strict_Origin_When_Cross_Origin:
259
        mReferrerPolicy = ReferrerPolicy::Strict_origin_when_cross_origin;
260
        break;
261
      default:
262
        MOZ_ASSERT_UNREACHABLE("Invalid ReferrerPolicy value");
263
        break;
264
    }
265
  }
266
267
  net::ReferrerPolicy
268
  GetReferrerPolicy()
269
  {
270
    switch (mReferrerPolicy) {
271
      case ReferrerPolicy::_empty:
272
        return net::RP_Unset;
273
      case ReferrerPolicy::No_referrer:
274
        return net::RP_No_Referrer;
275
      case ReferrerPolicy::No_referrer_when_downgrade:
276
        return net::RP_No_Referrer_When_Downgrade;
277
      case ReferrerPolicy::Origin:
278
        return net::RP_Origin;
279
      case ReferrerPolicy::Origin_when_cross_origin:
280
        return net::RP_Origin_When_Crossorigin;
281
      case ReferrerPolicy::Unsafe_url:
282
        return net::RP_Unsafe_URL;
283
      case ReferrerPolicy::Strict_origin:
284
        return net::RP_Strict_Origin;
285
      case ReferrerPolicy::Same_origin:
286
        return net::RP_Same_Origin;
287
      case ReferrerPolicy::Strict_origin_when_cross_origin:
288
        return net::RP_Strict_Origin_When_Cross_Origin;
289
      default:
290
        MOZ_ASSERT_UNREACHABLE("Invalid ReferrerPolicy enum value?");
291
        break;
292
    }
293
    return net::RP_Unset;
294
  }
295
296
  net::ReferrerPolicy
297
  GetEnvironmentReferrerPolicy() const
298
  {
299
    return mEnvironmentReferrerPolicy;
300
  }
301
302
  void
303
  SetEnvironmentReferrerPolicy(net::ReferrerPolicy aReferrerPolicy)
304
  {
305
    mEnvironmentReferrerPolicy = aReferrerPolicy;
306
  }
307
308
  bool
309
  SkipServiceWorker() const
310
  {
311
    return mSkipServiceWorker;
312
  }
313
314
  void
315
  SetSkipServiceWorker()
316
  {
317
    mSkipServiceWorker = true;
318
  }
319
320
  bool
321
  IsSynchronous() const
322
  {
323
    return mSynchronous;
324
  }
325
326
  RequestMode
327
  Mode() const
328
0
  {
329
0
    return mMode;
330
0
  }
331
332
  void
333
  SetMode(RequestMode aMode)
334
0
  {
335
0
    mMode = aMode;
336
0
  }
337
338
  RequestCredentials
339
  GetCredentialsMode() const
340
0
  {
341
0
    return mCredentialsMode;
342
0
  }
343
344
  void
345
  SetCredentialsMode(RequestCredentials aCredentialsMode)
346
0
  {
347
0
    mCredentialsMode = aCredentialsMode;
348
0
  }
349
350
  LoadTainting
351
  GetResponseTainting() const
352
  {
353
    return mResponseTainting;
354
  }
355
356
  void
357
  MaybeIncreaseResponseTainting(LoadTainting aTainting)
358
  {
359
    if (aTainting > mResponseTainting) {
360
      mResponseTainting = aTainting;
361
    }
362
  }
363
364
  RequestCache
365
  GetCacheMode() const
366
0
  {
367
0
    return mCacheMode;
368
0
  }
369
370
  void
371
  SetCacheMode(RequestCache aCacheMode)
372
0
  {
373
0
    mCacheMode = aCacheMode;
374
0
  }
375
376
  RequestRedirect
377
  GetRedirectMode() const
378
0
  {
379
0
    return mRedirectMode;
380
0
  }
381
382
  void
383
  SetRedirectMode(RequestRedirect aRedirectMode)
384
0
  {
385
0
    mRedirectMode = aRedirectMode;
386
0
  }
387
388
  const nsString&
389
  GetIntegrity() const
390
0
  {
391
0
    return mIntegrity;
392
0
  }
393
  void
394
  SetIntegrity(const nsAString& aIntegrity)
395
0
  {
396
0
    MOZ_ASSERT(mIntegrity.IsEmpty());
397
0
    mIntegrity.Assign(aIntegrity);
398
0
  }
399
400
  bool
401
  MozErrors() const
402
0
  {
403
0
    return mMozErrors;
404
0
  }
405
406
  void
407
  SetMozErrors()
408
  {
409
    mMozErrors = true;
410
  }
411
412
  const nsCString&
413
  GetFragment() const
414
0
  {
415
0
    return mFragment;
416
0
  }
417
418
  nsContentPolicyType
419
  ContentPolicyType() const
420
0
  {
421
0
    return mContentPolicyType;
422
0
  }
423
  void
424
  SetContentPolicyType(nsContentPolicyType aContentPolicyType);
425
426
  void
427
  OverrideContentPolicyType(nsContentPolicyType aContentPolicyType);
428
429
  RequestDestination
430
  Destination() const
431
0
  {
432
0
    return MapContentPolicyTypeToRequestDestination(mContentPolicyType);
433
0
  }
434
435
  bool
436
  UnsafeRequest() const
437
  {
438
    return mUnsafeRequest;
439
  }
440
441
  void
442
  SetUnsafeRequest()
443
  {
444
    mUnsafeRequest = true;
445
  }
446
447
  InternalHeaders*
448
  Headers()
449
0
  {
450
0
    return mHeaders;
451
0
  }
452
453
  bool
454
  ForceOriginHeader()
455
  {
456
    return mForceOriginHeader;
457
  }
458
459
  bool
460
  SameOriginDataURL() const
461
0
  {
462
0
    return mSameOriginDataURL;
463
0
  }
464
465
  void
466
  UnsetSameOriginDataURL()
467
0
  {
468
0
    mSameOriginDataURL = false;
469
0
  }
470
471
  void
472
  SetBody(nsIInputStream* aStream, int64_t aBodyLength)
473
0
  {
474
0
    // A request's body may not be reset once set.
475
0
    MOZ_ASSERT_IF(aStream, !mBodyStream);
476
0
    mBodyStream = aStream;
477
0
    mBodyLength = aBodyLength;
478
0
  }
479
480
  // Will return the original stream!
481
  // Use a tee or copy if you don't want to erase the original.
482
  void
483
  GetBody(nsIInputStream** aStream, int64_t* aBodyLength = nullptr)
484
0
  {
485
0
    nsCOMPtr<nsIInputStream> s = mBodyStream;
486
0
    s.forget(aStream);
487
0
488
0
    if (aBodyLength) {
489
0
      *aBodyLength = mBodyLength;
490
0
    }
491
0
  }
492
493
  void
494
  SetBodyLocalPath(nsAString& aLocalPath)
495
0
  {
496
0
    mBodyLocalPath = aLocalPath;
497
0
  }
498
499
  const nsAString&
500
  BodyLocalPath() const
501
  {
502
    return mBodyLocalPath;
503
  }
504
505
  // The global is used as the client for the new object.
506
  already_AddRefed<InternalRequest>
507
  GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult& aRv) const;
508
509
  bool
510
  WasCreatedByFetchEvent() const
511
  {
512
    return mCreatedByFetchEvent;
513
  }
514
515
  void
516
  SetCreatedByFetchEvent()
517
0
  {
518
0
    mCreatedByFetchEvent = true;
519
0
  }
520
521
  void
522
  ClearCreatedByFetchEvent()
523
  {
524
    mCreatedByFetchEvent = false;
525
  }
526
527
  bool
528
  IsNavigationRequest() const;
529
530
  bool
531
  IsWorkerRequest() const;
532
533
  bool
534
  IsClientRequest() const;
535
536
  void
537
  MaybeSkipCacheIfPerformingRevalidation();
538
539
  bool
540
  IsContentPolicyTypeOverridden() const
541
0
  {
542
0
    return mContentPolicyTypeOverridden;
543
0
  }
544
545
  static RequestMode
546
  MapChannelToRequestMode(nsIChannel* aChannel);
547
548
  static RequestCredentials
549
  MapChannelToRequestCredentials(nsIChannel* aChannel);
550
551
  // Takes ownership of the principal info.
552
  void
553
  SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo);
554
555
  const UniquePtr<mozilla::ipc::PrincipalInfo>&
556
  GetPrincipalInfo() const
557
  {
558
    return mPrincipalInfo;
559
  }
560
561
  const nsCString&
562
  GetPreferredAlternativeDataType() const
563
  {
564
    return mPreferredAlternativeDataType;
565
  }
566
567
  void
568
  SetPreferredAlternativeDataType(const nsACString& aDataType)
569
0
  {
570
0
    mPreferredAlternativeDataType = aDataType;
571
0
  }
572
573
private:
574
  // Does not copy mBodyStream.  Use fallible Clone() for complete copy.
575
  explicit InternalRequest(const InternalRequest& aOther);
576
577
  ~InternalRequest();
578
579
  // Map the content policy type to the associated fetch destination, as defined
580
  // by the spec at https://fetch.spec.whatwg.org/#concept-request-destination.
581
  // Note that while the HTML spec for the "Link" element and its "as" attribute
582
  // (https://html.spec.whatwg.org/#attr-link-as) reuse fetch's definition of
583
  // destination, and the Link class has an internal Link::AsDestination enum type,
584
  // the latter is only a support type to map the string values via
585
  // Link::ParseAsValue and Link::AsValueToContentPolicy to our canonical nsContentPolicyType.
586
  static RequestDestination
587
  MapContentPolicyTypeToRequestDestination(nsContentPolicyType aContentPolicyType);
588
589
  static bool
590
  IsNavigationContentPolicy(nsContentPolicyType aContentPolicyType);
591
592
  static bool
593
  IsWorkerContentPolicy(nsContentPolicyType aContentPolicyType);
594
595
  // It should only be called while there is a service-worker-internal-redirect.
596
  void
597
  SetURL(const nsACString& aURL, const nsACString& aFragment)
598
  {
599
    MOZ_ASSERT(!aURL.IsEmpty());
600
    MOZ_ASSERT(!aURL.Contains('#'));
601
    MOZ_ASSERT(mURLList.Length() > 0);
602
603
    mURLList.LastElement() = aURL;
604
    mFragment.Assign(aFragment);
605
  }
606
607
  nsCString mMethod;
608
  // mURLList: a list of one or more fetch URLs
609
  nsTArray<nsCString> mURLList;
610
  RefPtr<InternalHeaders> mHeaders;
611
  nsString mBodyLocalPath;
612
  nsCOMPtr<nsIInputStream> mBodyStream;
613
  int64_t mBodyLength;
614
615
  nsCString mPreferredAlternativeDataType;
616
617
  nsContentPolicyType mContentPolicyType;
618
619
  // Empty string: no-referrer
620
  // "about:client": client (default)
621
  // URL: an URL
622
  nsString mReferrer;
623
  ReferrerPolicy mReferrerPolicy;
624
625
  // This will be used for request created from Window or Worker contexts
626
  // In case there's no Referrer Policy in Request, this will be passed to
627
  // channel.
628
  // The Environment Referrer Policy should be net::ReferrerPolicy so that it
629
  // could be associated with nsIHttpChannel.
630
  net::ReferrerPolicy mEnvironmentReferrerPolicy;
631
  RequestMode mMode;
632
  RequestCredentials mCredentialsMode;
633
  MOZ_INIT_OUTSIDE_CTOR LoadTainting mResponseTainting;
634
  RequestCache mCacheMode;
635
  RequestRedirect mRedirectMode;
636
  nsString mIntegrity;
637
  bool mMozErrors;
638
  nsCString mFragment;
639
  MOZ_INIT_OUTSIDE_CTOR bool mAuthenticationFlag;
640
  MOZ_INIT_OUTSIDE_CTOR bool mForceOriginHeader;
641
  MOZ_INIT_OUTSIDE_CTOR bool mPreserveContentCodings;
642
  MOZ_INIT_OUTSIDE_CTOR bool mSameOriginDataURL;
643
  MOZ_INIT_OUTSIDE_CTOR bool mSkipServiceWorker;
644
  MOZ_INIT_OUTSIDE_CTOR bool mSynchronous;
645
  MOZ_INIT_OUTSIDE_CTOR bool mUnsafeRequest;
646
  MOZ_INIT_OUTSIDE_CTOR bool mUseURLCredentials;
647
  // This is only set when a Request object is created by a fetch event.  We
648
  // use it to check if Service Workers are simply fetching intercepted Request
649
  // objects without modifying them.
650
  bool mCreatedByFetchEvent = false;
651
  // This is only set when Request.overrideContentPolicyType() has been set.
652
  // It is illegal to pass such a Request object to a fetch() method unless
653
  // if the caller has chrome privileges.
654
  bool mContentPolicyTypeOverridden = false;
655
656
  UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
657
};
658
659
} // namespace dom
660
} // namespace mozilla
661
662
#endif // mozilla_dom_InternalRequest_h