tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

InternalRequest.h (17523B)


      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/LoadTainting.h"
     11 #include "mozilla/UniquePtr.h"
     12 #include "mozilla/dom/HeadersBinding.h"
     13 #include "mozilla/dom/InternalHeaders.h"
     14 #include "mozilla/dom/InternalResponse.h"
     15 #include "mozilla/dom/RequestBinding.h"
     16 #include "mozilla/dom/SafeRefPtr.h"
     17 #include "mozilla/net/NeckoChannelParams.h"
     18 #include "nsIChannelEventSink.h"
     19 #include "nsIInputStream.h"
     20 #include "nsISupportsImpl.h"
     21 #include "nsISupportsPriority.h"
     22 #ifdef DEBUG
     23 #  include "nsIURLParser.h"
     24 #  include "nsNetCID.h"
     25 #  include "nsServiceManagerUtils.h"
     26 #endif
     27 
     28 using mozilla::net::RedirectHistoryEntryInfo;
     29 
     30 namespace mozilla {
     31 
     32 namespace ipc {
     33 class PBackgroundChild;
     34 class PrincipalInfo;
     35 }  // namespace ipc
     36 
     37 namespace dom {
     38 
     39 /*
     40 * The mapping of RequestDestination and nsContentPolicyType is currently as the
     41 * following.
     42 *
     43 * RequestDestination| nsContentPolicyType
     44 * ------------------+--------------------
     45 * "audio"           | TYPE_INTERNAL_AUDIO
     46 * "audioworklet"    | TYPE_INTERNAL_AUDIOWORKLET
     47 * "document"        | TYPE_DOCUMENT
     48 * "embed"           | TYPE_INTERNAL_EMBED
     49 * "font"            | TYPE_FONT, TYPE_INTERNAL_FONT_PRELOAD
     50 * "frame"           | TYPE_INTERNAL_FRAME
     51 * "iframe"          | TYPE_SUBDOCUMENT, TYPE_INTERNAL_IFRAME
     52 * "image"           | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD,
     53 *                   | TYPE_IMAGE, TYPE_INTERNAL_IMAGE_FAVICON, TYPE_IMAGESET
     54 * "json"            | TYPE_JSON, TYPE_INTERNAL_JSON_PRELOAD
     55 * "manifest"        | TYPE_WEB_MANIFEST
     56 * "object"          | TYPE_INTERNAL_OBJECT, TYPE_OBJECT
     57 * "paintworklet"    | TYPE_INTERNAL_PAINTWORKLET
     58 * "report"          | TYPE_CSP_REPORT
     59 * "script"          | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD,
     60 *                   | TYPE_INTERNAL_MODULE, TYPE_INTERNAL_MODULE_PRELOAD,
     61 *                   | TYPE_SCRIPT,
     62 *                   | TYPE_INTERNAL_SERVICE_WORKER,
     63 *                   | TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS,
     64 *                   | TYPE_INTERNAL_CHROMEUTILS_COMPILED_SCRIPT
     65 *                   | TYPE_INTERNAL_FRAME_MESSAGEMANAGER_SCRIPT
     66 * "sharedworker"    | TYPE_INTERNAL_SHARED_WORKER
     67 * "serviceworker"   | The spec lists this as a valid value for the enum,
     68 *                   | however it is impossible to observe a request with this
     69 *                   | destination value.
     70 * "style"           | TYPE_INTERNAL_STYLESHEET,
     71 *                   | TYPE_INTERNAL_STYLESHEET_PRELOAD,
     72 *                   | TYPE_STYLESHEET
     73 * "track"           | TYPE_INTERNAL_TRACK
     74 * "video"           | TYPE_INTERNAL_VIDEO
     75 * "worker"          | TYPE_INTERNAL_WORKER, TYPE_INTERNAL_WORKER_STATIC_MODULE
     76 * "xslt"            | TYPE_XSLT
     77 * ""                | Default for everything else.
     78 *
     79 */
     80 
     81 class IPCInternalRequest;
     82 class Request;
     83 
     84 #define kFETCH_CLIENT_REFERRER_STR "about:client"
     85 class InternalRequest final : public AtomicSafeRefCounted<InternalRequest> {
     86  friend class Request;
     87 
     88 public:
     89  MOZ_DECLARE_REFCOUNTED_TYPENAME(InternalRequest)
     90  InternalRequest(const nsACString& aURL, const nsACString& aFragment);
     91 
     92  explicit InternalRequest(const IPCInternalRequest& aIPCRequest);
     93 
     94  void ToIPCInternalRequest(IPCInternalRequest* aIPCRequest,
     95                            mozilla::ipc::PBackgroundChild* aManager);
     96 
     97  SafeRefPtr<InternalRequest> Clone();
     98 
     99  void GetMethod(nsCString& aMethod) const { aMethod.Assign(mMethod); }
    100 
    101  void SetMethod(const nsACString& aMethod) { mMethod.Assign(aMethod); }
    102 
    103  bool HasSimpleMethod() const {
    104    return mMethod.LowerCaseEqualsASCII("get") ||
    105           mMethod.LowerCaseEqualsASCII("post") ||
    106           mMethod.LowerCaseEqualsASCII("head");
    107  }
    108  // GetURL should get the request's current url with fragment. A request has
    109  // an associated current url. It is a pointer to the last fetch URL in
    110  // request's url list.
    111  void GetURL(nsACString& aURL) const {
    112    aURL.Assign(GetURLWithoutFragment());
    113    if (GetFragment().IsEmpty()) {
    114      return;
    115    }
    116    aURL.AppendLiteral("#");
    117    aURL.Append(GetFragment());
    118  }
    119 
    120  const nsCString& GetURLWithoutFragment() const {
    121    MOZ_RELEASE_ASSERT(!mURLList.IsEmpty(),
    122                       "Internal Request's urlList should not be empty.");
    123 
    124    return mURLList.LastElement();
    125  }
    126 
    127  // A safe guard for ensuring that request's URL is only allowed to be set in a
    128  // sw internal redirect.
    129  void SetURLForInternalRedirect(const uint32_t aFlag, const nsACString& aURL,
    130                                 const nsACString& aFragment) {
    131    // Only check in debug build to prevent it from being used unexpectedly.
    132    MOZ_ASSERT(aFlag & nsIChannelEventSink::REDIRECT_INTERNAL);
    133 
    134    return SetURL(aURL, aFragment);
    135  }
    136 
    137  // AddURL should append the url into url list.
    138  // Normally we strip the fragment from the URL in Request::Constructor and
    139  // pass the fragment as the second argument into it.
    140  // If a fragment is present in the URL it must be stripped and passed in
    141  // separately.
    142  void AddURL(const nsACString& aURL, const nsACString& aFragment) {
    143    MOZ_ASSERT(!aURL.IsEmpty());
    144    MOZ_ASSERT(!aURL.Contains('#'));
    145 
    146    mURLList.AppendElement(aURL);
    147 
    148    mFragment.Assign(aFragment);
    149  }
    150  // Get the URL list without their fragments.
    151  void GetURLListWithoutFragment(nsTArray<nsCString>& aURLList) {
    152    aURLList.Assign(mURLList);
    153  }
    154  void GetReferrer(nsACString& aReferrer) const { aReferrer.Assign(mReferrer); }
    155 
    156  void SetReferrer(const nsACString& aReferrer) {
    157 #ifdef DEBUG
    158    bool validReferrer = false;
    159    if (aReferrer.IsEmpty() ||
    160        aReferrer.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
    161      validReferrer = true;
    162    } else {
    163      nsCOMPtr<nsIURLParser> parser = do_GetService(NS_STDURLPARSER_CONTRACTID);
    164      if (!parser) {
    165        NS_WARNING("Could not get parser to validate URL!");
    166      } else {
    167        uint32_t schemePos;
    168        int32_t schemeLen;
    169        uint32_t authorityPos;
    170        int32_t authorityLen;
    171        uint32_t pathPos;
    172        int32_t pathLen;
    173 
    174        nsresult rv = parser->ParseURL(
    175            aReferrer.BeginReading(), aReferrer.Length(), &schemePos,
    176            &schemeLen, &authorityPos, &authorityLen, &pathPos, &pathLen);
    177        if (NS_FAILED(rv)) {
    178          NS_WARNING("Invalid referrer URL!");
    179        } else if (schemeLen < 0 || authorityLen < 0) {
    180          NS_WARNING("Invalid referrer URL!");
    181        } else {
    182          validReferrer = true;
    183        }
    184      }
    185    }
    186 
    187    MOZ_ASSERT(validReferrer);
    188 #endif
    189 
    190    mReferrer.Assign(aReferrer);
    191  }
    192 
    193  ReferrerPolicy ReferrerPolicy_() const { return mReferrerPolicy; }
    194 
    195  void SetReferrerPolicy(ReferrerPolicy aReferrerPolicy) {
    196    mReferrerPolicy = aReferrerPolicy;
    197  }
    198 
    199  ReferrerPolicy GetEnvironmentReferrerPolicy() const {
    200    return mEnvironmentReferrerPolicy;
    201  }
    202 
    203  void SetEnvironmentReferrerPolicy(ReferrerPolicy aReferrerPolicy) {
    204    mEnvironmentReferrerPolicy = aReferrerPolicy;
    205  }
    206 
    207  bool SkipServiceWorker() const { return mSkipServiceWorker; }
    208 
    209  void SetSkipServiceWorker() { mSkipServiceWorker = true; }
    210 
    211  bool SkipWasmCaching() const { return mSkipWasmCaching; }
    212 
    213  void SetSkipWasmCaching() { mSkipWasmCaching = true; }
    214 
    215  bool IsSynchronous() const { return mSynchronous; }
    216 
    217  RequestMode Mode() const { return mMode; }
    218 
    219  void SetMode(RequestMode aMode) { mMode = aMode; }
    220 
    221  RequestCredentials GetCredentialsMode() const { return mCredentialsMode; }
    222 
    223  void SetCredentialsMode(RequestCredentials aCredentialsMode) {
    224    mCredentialsMode = aCredentialsMode;
    225  }
    226 
    227  LoadTainting GetResponseTainting() const { return mResponseTainting; }
    228 
    229  void MaybeIncreaseResponseTainting(LoadTainting aTainting) {
    230    if (aTainting > mResponseTainting && !mNeverTaint) {
    231      mResponseTainting = aTainting;
    232    }
    233  }
    234 
    235  RequestCache GetCacheMode() const { return mCacheMode; }
    236 
    237  void SetCacheMode(RequestCache aCacheMode) { mCacheMode = aCacheMode; }
    238 
    239  RequestRedirect GetRedirectMode() const { return mRedirectMode; }
    240 
    241  void SetRedirectMode(RequestRedirect aRedirectMode) {
    242    mRedirectMode = aRedirectMode;
    243  }
    244 
    245  RequestPriority GetPriorityMode() const { return mPriorityMode; }
    246 
    247  void SetPriorityMode(RequestPriority aPriorityMode) {
    248    mPriorityMode = aPriorityMode;
    249  }
    250 
    251  const nsString& GetIntegrity() const { return mIntegrity; }
    252 
    253  void SetIntegrity(const nsAString& aIntegrity) {
    254    mIntegrity.Assign(aIntegrity);
    255  }
    256 
    257  bool GetKeepalive() const { return mKeepalive; }
    258 
    259  void SetKeepalive(const bool aKeepalive) { mKeepalive = aKeepalive; }
    260 
    261  bool MozErrors() const { return mMozErrors; }
    262 
    263  void SetMozErrors() { mMozErrors = true; }
    264 
    265  void SetTriggeringPrincipal(nsIPrincipal* aPrincipal) {
    266    mTriggeringPrincipalOverride = aPrincipal;
    267  }
    268 
    269  nsIPrincipal* GetTriggeringPrincipalOverride() {
    270    return mTriggeringPrincipalOverride;
    271  }
    272 
    273  void SetNeverTaint(bool aNeverTaint) { mNeverTaint = aNeverTaint; }
    274 
    275  bool GetNeverTaint() { return mNeverTaint; }
    276 
    277  const nsCString& GetFragment() const { return mFragment; }
    278 
    279  nsContentPolicyType ContentPolicyType() const { return mContentPolicyType; }
    280  void SetContentPolicyType(nsContentPolicyType aContentPolicyType);
    281 
    282  void OverrideContentPolicyType(nsContentPolicyType aContentPolicyType);
    283 
    284  RequestDestination Destination() const {
    285    return MapContentPolicyTypeToRequestDestination(mContentPolicyType);
    286  }
    287 
    288  int32_t InternalPriority() const { return mInternalPriority; }
    289  void SetInternalPriority(int32_t aInternalPriority) {
    290    mInternalPriority = aInternalPriority;
    291  }
    292 
    293  bool UnsafeRequest() const { return mUnsafeRequest; }
    294 
    295  void SetUnsafeRequest() { mUnsafeRequest = true; }
    296 
    297  InternalHeaders* Headers() const { return mHeaders; }
    298 
    299  void SetHeaders(InternalHeaders* aHeaders) {
    300    MOZ_ASSERT(aHeaders);
    301    mHeaders = aHeaders;
    302  }
    303 
    304  void SetBody(nsIInputStream* aStream, int64_t aBodyLength) {
    305    // A request's body may not be reset once set.
    306    MOZ_ASSERT_IF(aStream, !mBodyStream);
    307    mBodyStream = aStream;
    308    mBodyLength = aBodyLength;
    309  }
    310 
    311  // Will return the original stream!
    312  // Use a tee or copy if you don't want to erase the original.
    313  void GetBody(nsIInputStream** aStream, int64_t* aBodyLength = nullptr) const {
    314    nsCOMPtr<nsIInputStream> s = mBodyStream;
    315    s.forget(aStream);
    316 
    317    if (aBodyLength) {
    318      *aBodyLength = mBodyLength;
    319    }
    320  }
    321 
    322  int64_t BodyLength() const { return mBodyLength; }
    323 
    324  void SetBodyBlobURISpec(nsACString& aBlobURISpec) {
    325    mBodyBlobURISpec = aBlobURISpec;
    326  }
    327 
    328  const nsACString& BodyBlobURISpec() const { return mBodyBlobURISpec; }
    329 
    330  void SetBodyLocalPath(nsAString& aLocalPath) { mBodyLocalPath = aLocalPath; }
    331 
    332  const nsAString& BodyLocalPath() const { return mBodyLocalPath; }
    333 
    334  // The global is used as the client for the new object.
    335  SafeRefPtr<InternalRequest> GetRequestConstructorCopy(
    336      nsIGlobalObject* aGlobal, ErrorResult& aRv) const;
    337 
    338  bool IsNavigationRequest() const;
    339 
    340  bool IsWorkerRequest() const;
    341 
    342  bool IsClientRequest() const;
    343 
    344  void MaybeSkipCacheIfPerformingRevalidation();
    345 
    346  bool IsContentPolicyTypeOverridden() const {
    347    return mContentPolicyTypeOverridden;
    348  }
    349 
    350  static RequestMode MapChannelToRequestMode(nsIChannel* aChannel);
    351 
    352  static RequestCredentials MapChannelToRequestCredentials(
    353      nsIChannel* aChannel);
    354 
    355  // Takes ownership of the principal info.
    356  void SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo);
    357  const UniquePtr<mozilla::ipc::PrincipalInfo>& GetPrincipalInfo() const {
    358    return mPrincipalInfo;
    359  }
    360 
    361  const nsCString& GetPreferredAlternativeDataType() const {
    362    return mPreferredAlternativeDataType;
    363  }
    364 
    365  void SetPreferredAlternativeDataType(const nsACString& aDataType) {
    366    mPreferredAlternativeDataType = aDataType;
    367  }
    368 
    369  ~InternalRequest();
    370 
    371  InternalRequest(const InternalRequest& aOther) = delete;
    372 
    373  void SetEmbedderPolicy(nsILoadInfo::CrossOriginEmbedderPolicy aPolicy) {
    374    mEmbedderPolicy = aPolicy;
    375  }
    376 
    377  nsILoadInfo::CrossOriginEmbedderPolicy GetEmbedderPolicy() const {
    378    return mEmbedderPolicy;
    379  }
    380 
    381  void SetInterceptionTriggeringPrincipalInfo(
    382      UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo);
    383 
    384  const UniquePtr<mozilla::ipc::PrincipalInfo>&
    385  GetInterceptionTriggeringPrincipalInfo() const {
    386    return mInterceptionTriggeringPrincipalInfo;
    387  }
    388 
    389  nsContentPolicyType InterceptionContentPolicyType() const {
    390    return mInterceptionContentPolicyType;
    391  }
    392  RequestDestination InterceptionDestination() const {
    393    return MapContentPolicyTypeToRequestDestination(
    394        mInterceptionContentPolicyType);
    395  }
    396  void SetInterceptionContentPolicyType(nsContentPolicyType aContentPolicyType);
    397 
    398  const nsTArray<RedirectHistoryEntryInfo>& InterceptionRedirectChain() const {
    399    return mInterceptionRedirectChain;
    400  }
    401 
    402  void SetInterceptionRedirectChain(
    403      const nsTArray<RedirectHistoryEntryInfo>& aRedirectChain) {
    404    mInterceptionRedirectChain = aRedirectChain;
    405  }
    406 
    407  const bool& InterceptionFromThirdParty() const {
    408    return mInterceptionFromThirdParty;
    409  }
    410 
    411  void SetInterceptionFromThirdParty(bool aFromThirdParty) {
    412    mInterceptionFromThirdParty = aFromThirdParty;
    413  }
    414 
    415 private:
    416  struct ConstructorGuard {};
    417 
    418 public:
    419  // Does not copy mBodyStream.  Use fallible Clone() for complete copy.
    420  InternalRequest(const InternalRequest& aOther, ConstructorGuard);
    421 
    422  // Map the content policy type to the associated fetch destination, as defined
    423  // by the spec at https://fetch.spec.whatwg.org/#concept-request-destination.
    424  // Note that while the HTML spec for the "Link" element and its "as" attribute
    425  // (https://html.spec.whatwg.org/#attr-link-as) reuse fetch's definition of
    426  // destination.
    427  static RequestDestination MapContentPolicyTypeToRequestDestination(
    428      nsContentPolicyType aContentPolicyType);
    429  static RequestDestination MapContentPolicyTypeToRequestDestination(
    430      ExtContentPolicyType aContentPolicyType);
    431 
    432 private:
    433  static bool IsNavigationContentPolicy(nsContentPolicyType aContentPolicyType);
    434 
    435  static bool IsWorkerContentPolicy(nsContentPolicyType aContentPolicyType);
    436 
    437  // It should only be called while there is a service-worker-internal-redirect.
    438  void SetURL(const nsACString& aURL, const nsACString& aFragment) {
    439    MOZ_ASSERT(!aURL.IsEmpty());
    440    MOZ_ASSERT(!aURL.Contains('#'));
    441    MOZ_ASSERT(mURLList.Length() > 0);
    442 
    443    mURLList.LastElement() = aURL;
    444    mFragment.Assign(aFragment);
    445  }
    446 
    447  nsCString mMethod;
    448  // mURLList: a list of one or more fetch URLs
    449  nsTArray<nsCString> mURLList;
    450  RefPtr<InternalHeaders> mHeaders;
    451  nsCString mBodyBlobURISpec;
    452  nsString mBodyLocalPath;
    453  nsCOMPtr<nsIInputStream> mBodyStream;
    454 
    455  nsCOMPtr<nsIPrincipal> mTriggeringPrincipalOverride;
    456  bool mNeverTaint = false;
    457  int64_t mBodyLength{InternalResponse::UNKNOWN_BODY_SIZE};
    458 
    459  nsCString mPreferredAlternativeDataType;
    460 
    461  nsContentPolicyType mContentPolicyType;
    462 
    463  int32_t mInternalPriority = nsISupportsPriority::PRIORITY_NORMAL;
    464 
    465  // Empty string: no-referrer
    466  // "about:client": client (default)
    467  // URL: an URL
    468  nsCString mReferrer;
    469  ReferrerPolicy mReferrerPolicy;
    470 
    471  // This will be used for request created from Window or Worker contexts
    472  // In case there's no Referrer Policy in Request, this will be passed to
    473  // channel.
    474  ReferrerPolicy mEnvironmentReferrerPolicy;
    475  RequestMode mMode;
    476  RequestCredentials mCredentialsMode;
    477  LoadTainting mResponseTainting = LoadTainting::Basic;
    478  RequestCache mCacheMode;
    479  RequestRedirect mRedirectMode;
    480  RequestPriority mPriorityMode = RequestPriority::Auto;
    481  nsString mIntegrity;
    482  bool mKeepalive = false;
    483  bool mMozErrors = false;
    484  nsCString mFragment;
    485  bool mSkipServiceWorker = false;
    486  bool mSkipWasmCaching = false;
    487  bool mSynchronous = false;
    488  bool mUnsafeRequest = false;
    489  bool mUseURLCredentials = false;
    490  // This is only set when Request.overrideContentPolicyType() has been set.
    491  // It is illegal to pass such a Request object to a fetch() method unless
    492  // if the caller has chrome privileges.
    493  bool mContentPolicyTypeOverridden = false;
    494  nsILoadInfo::CrossOriginEmbedderPolicy mEmbedderPolicy =
    495      nsILoadInfo::EMBEDDER_POLICY_NULL;
    496 
    497  UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
    498 
    499  // Following members are specific for the FetchEvent.request or
    500  // NavigationPreload request which is extracted from the
    501  // InterceptedHttpChannel.
    502  // Notice that these members would not be copied when calling
    503  // InternalRequest::GetRequestConstructorCopy() since these information should
    504  // not be propagated when copying the Request in ServiceWorker script.
    505 
    506  // This is the trigging principalInfo of the InterceptedHttpChannel.
    507  UniquePtr<mozilla::ipc::PrincipalInfo> mInterceptionTriggeringPrincipalInfo;
    508 
    509  // This is the contentPolicyType of the InterceptedHttpChannel.
    510  nsContentPolicyType mInterceptionContentPolicyType{
    511      nsIContentPolicy::TYPE_INVALID};
    512 
    513  // This is the redirect history of the InterceptedHttpChannel.
    514  CopyableTArray<RedirectHistoryEntryInfo> mInterceptionRedirectChain;
    515 
    516  // This indicates that the InterceptedHttpChannel is a third party channel.
    517  bool mInterceptionFromThirdParty{false};
    518 };
    519 
    520 }  // namespace dom
    521 }  // namespace mozilla
    522 
    523 #endif  // mozilla_dom_InternalRequest_h