tor-browser

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

InternalResponse.h (12272B)


      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_InternalResponse_h
      8 #define mozilla_dom_InternalResponse_h
      9 
     10 #include "mozilla/UniquePtr.h"
     11 #include "mozilla/dom/ChannelInfo.h"
     12 #include "mozilla/dom/FetchTypes.h"
     13 #include "mozilla/dom/InternalHeaders.h"
     14 #include "mozilla/dom/RequestBinding.h"
     15 #include "mozilla/dom/ResponseBinding.h"
     16 #include "mozilla/dom/SafeRefPtr.h"
     17 #include "nsICacheInfoChannel.h"
     18 #include "nsIInputStream.h"
     19 #include "nsISupportsImpl.h"
     20 #include "nsProxyRelease.h"
     21 
     22 namespace mozilla {
     23 namespace ipc {
     24 class PBackgroundChild;
     25 class PBackgroundParent;
     26 class PrincipalInfo;
     27 }  // namespace ipc
     28 
     29 namespace dom {
     30 
     31 class ChildToParentInternalResponse;
     32 class InternalHeaders;
     33 class ParentToChildInternalResponse;
     34 class ParentToParentInternalResponse;
     35 
     36 class InternalResponse final : public AtomicSafeRefCounted<InternalResponse> {
     37  friend class FetchDriver;
     38 
     39 public:
     40  MOZ_DECLARE_REFCOUNTED_TYPENAME(InternalResponse)
     41 
     42  InternalResponse(
     43      uint16_t aStatus, const nsACString& aStatusText,
     44      RequestCredentials aCredentialsMode = RequestCredentials::Omit);
     45 
     46  static SafeRefPtr<InternalResponse> FromIPC(
     47      const ParentToChildInternalResponse& aIPCResponse);
     48 
     49  static SafeRefPtr<InternalResponse> FromIPC(
     50      const ParentToParentInternalResponse& aIPCResponse);
     51 
     52  void ToChildToParentInternalResponse(
     53      ChildToParentInternalResponse* aIPCResponse,
     54      mozilla::ipc::PBackgroundChild* aManager);
     55 
     56  ParentToParentInternalResponse ToParentToParentInternalResponse();
     57 
     58  ParentToChildInternalResponse ToParentToChildInternalResponse();
     59 
     60  enum CloneType {
     61    eCloneInputStream,
     62    eDontCloneInputStream,
     63  };
     64 
     65  SafeRefPtr<InternalResponse> Clone(CloneType aCloneType);
     66 
     67  static SafeRefPtr<InternalResponse> NetworkError(nsresult aRv) {
     68    MOZ_DIAGNOSTIC_ASSERT(NS_FAILED(aRv));
     69    SafeRefPtr<InternalResponse> response =
     70        MakeSafeRefPtr<InternalResponse>(0, ""_ns);
     71    ErrorResult result;
     72    response->Headers()->SetGuard(HeadersGuardEnum::Immutable, result);
     73    MOZ_ASSERT(!result.Failed());
     74    response->mType = ResponseType::Error;
     75    response->mErrorCode = aRv;
     76    return response;
     77  }
     78 
     79  SafeRefPtr<InternalResponse> OpaqueResponse();
     80 
     81  SafeRefPtr<InternalResponse> OpaqueRedirectResponse();
     82 
     83  SafeRefPtr<InternalResponse> BasicResponse();
     84 
     85  SafeRefPtr<InternalResponse> CORSResponse();
     86 
     87  ResponseType Type() const {
     88    MOZ_ASSERT_IF(mType == ResponseType::Error, !mWrappedResponse);
     89    MOZ_ASSERT_IF(mType == ResponseType::Default, !mWrappedResponse);
     90    MOZ_ASSERT_IF(mType == ResponseType::Basic, mWrappedResponse);
     91    MOZ_ASSERT_IF(mType == ResponseType::Cors, mWrappedResponse);
     92    MOZ_ASSERT_IF(mType == ResponseType::Opaque, mWrappedResponse);
     93    MOZ_ASSERT_IF(mType == ResponseType::Opaqueredirect, mWrappedResponse);
     94    return mType;
     95  }
     96 
     97  bool IsError() const { return Type() == ResponseType::Error; }
     98  // GetUrl should return last fetch URL in response's url list and null if
     99  // response's url list is the empty list.
    100  const nsCString& GetURL() const {
    101    // Empty urlList when response is a synthetic response.
    102    if (mURLList.IsEmpty()) {
    103      return EmptyCString();
    104    }
    105    return mURLList.LastElement();
    106  }
    107  void GetURLList(nsTArray<nsCString>& aURLList) const {
    108    aURLList.Assign(mURLList);
    109  }
    110  const nsCString& GetUnfilteredURL() const {
    111    if (mWrappedResponse) {
    112      return mWrappedResponse->GetURL();
    113    }
    114    return GetURL();
    115  }
    116  void GetUnfilteredURLList(nsTArray<nsCString>& aURLList) const {
    117    if (mWrappedResponse) {
    118      return mWrappedResponse->GetURLList(aURLList);
    119    }
    120 
    121    return GetURLList(aURLList);
    122  }
    123 
    124  nsTArray<nsCString> GetUnfilteredURLList() const {
    125    nsTArray<nsCString> list;
    126    GetUnfilteredURLList(list);
    127    return list;
    128  }
    129 
    130  void SetURLList(const nsTArray<nsCString>& aURLList) {
    131    mURLList.Assign(aURLList);
    132 
    133 #ifdef DEBUG
    134    for (uint32_t i = 0; i < mURLList.Length(); ++i) {
    135      MOZ_ASSERT(mURLList[i].Find("#"_ns) == kNotFound);
    136    }
    137 #endif
    138  }
    139 
    140  uint16_t GetStatus() const { return mStatus; }
    141 
    142  uint16_t GetUnfilteredStatus() const {
    143    if (mWrappedResponse) {
    144      return mWrappedResponse->GetStatus();
    145    }
    146 
    147    return GetStatus();
    148  }
    149 
    150  const nsCString& GetStatusText() const { return mStatusText; }
    151 
    152  const nsCString& GetUnfilteredStatusText() const {
    153    if (mWrappedResponse) {
    154      return mWrappedResponse->GetStatusText();
    155    }
    156 
    157    return GetStatusText();
    158  }
    159 
    160  InternalHeaders* Headers() { return mHeaders; }
    161 
    162  InternalHeaders* UnfilteredHeaders() {
    163    if (mWrappedResponse) {
    164      return mWrappedResponse->Headers();
    165    };
    166 
    167    return Headers();
    168  }
    169 
    170  void GetUnfilteredBody(nsIInputStream** aStream,
    171                         int64_t* aBodySize = nullptr) {
    172    if (mWrappedResponse) {
    173      MOZ_ASSERT(!mBody);
    174      return mWrappedResponse->GetBody(aStream, aBodySize);
    175    }
    176    nsCOMPtr<nsIInputStream> stream = mBody;
    177    stream.forget(aStream);
    178    if (aBodySize) {
    179      *aBodySize = mBodySize;
    180    }
    181  }
    182 
    183  void GetBody(nsIInputStream** aStream, int64_t* aBodySize = nullptr) {
    184    if (Type() == ResponseType::Opaque ||
    185        Type() == ResponseType::Opaqueredirect) {
    186      *aStream = nullptr;
    187      if (aBodySize) {
    188        *aBodySize = UNKNOWN_BODY_SIZE;
    189      }
    190      return;
    191    }
    192 
    193    GetUnfilteredBody(aStream, aBodySize);
    194  }
    195 
    196  void SetBodyBlobURISpec(nsACString& aBlobURISpec) {
    197    mBodyBlobURISpec = aBlobURISpec;
    198  }
    199 
    200  const nsACString& BodyBlobURISpec() const {
    201    if (mWrappedResponse) {
    202      return mWrappedResponse->BodyBlobURISpec();
    203    }
    204    return mBodyBlobURISpec;
    205  }
    206 
    207  void SetBodyLocalPath(nsAString& aLocalPath) { mBodyLocalPath = aLocalPath; }
    208 
    209  const nsAString& BodyLocalPath() const {
    210    if (mWrappedResponse) {
    211      return mWrappedResponse->BodyLocalPath();
    212    }
    213    return mBodyLocalPath;
    214  }
    215 
    216  void SetBody(nsIInputStream* aBody, int64_t aBodySize) {
    217    if (mWrappedResponse) {
    218      return mWrappedResponse->SetBody(aBody, aBodySize);
    219    }
    220    // A request's body may not be reset once set.
    221    MOZ_ASSERT(!mBody);
    222    MOZ_ASSERT(mBodySize == UNKNOWN_BODY_SIZE);
    223    // Check arguments.
    224    MOZ_ASSERT(aBodySize == UNKNOWN_BODY_SIZE || aBodySize >= 0);
    225    // If body is not given, then size must be unknown.
    226    MOZ_ASSERT_IF(!aBody, aBodySize == UNKNOWN_BODY_SIZE);
    227 
    228    mBody = aBody;
    229    mBodySize = aBodySize;
    230  }
    231 
    232  uint32_t GetPaddingInfo();
    233 
    234  nsresult GeneratePaddingInfo();
    235 
    236  int64_t GetPaddingSize();
    237 
    238  void SetPaddingSize(int64_t aPaddingSize);
    239 
    240  void SetAlternativeDataType(const nsACString& aAltDataType) {
    241    if (mWrappedResponse) {
    242      return mWrappedResponse->SetAlternativeDataType(aAltDataType);
    243    }
    244 
    245    MOZ_DIAGNOSTIC_ASSERT(mAlternativeDataType.IsEmpty());
    246 
    247    mAlternativeDataType.Assign(aAltDataType);
    248  }
    249 
    250  const nsCString& GetAlternativeDataType() {
    251    if (mWrappedResponse) {
    252      return mWrappedResponse->GetAlternativeDataType();
    253    }
    254 
    255    return mAlternativeDataType;
    256  }
    257 
    258  void SetAlternativeBody(nsIInputStream* aAlternativeBody) {
    259    if (mWrappedResponse) {
    260      return mWrappedResponse->SetAlternativeBody(aAlternativeBody);
    261    }
    262    // A request's body may not be reset once set.
    263    MOZ_DIAGNOSTIC_ASSERT(!mAlternativeBody);
    264 
    265    mAlternativeBody = aAlternativeBody;
    266  }
    267 
    268  already_AddRefed<nsIInputStream> TakeAlternativeBody() {
    269    if (mWrappedResponse) {
    270      return mWrappedResponse->TakeAlternativeBody();
    271    }
    272 
    273    if (!mAlternativeBody) {
    274      return nullptr;
    275    }
    276 
    277    // cleanup the non-alternative body here.
    278    // Once alternative data is used, the real body is no need anymore.
    279    mBody = nullptr;
    280    mBodySize = UNKNOWN_BODY_SIZE;
    281    return mAlternativeBody.forget();
    282  }
    283 
    284  void SetCacheInfoChannel(
    285      const nsMainThreadPtrHandle<nsICacheInfoChannel>& aCacheInfoChannel) {
    286    if (mWrappedResponse) {
    287      return mWrappedResponse->SetCacheInfoChannel(aCacheInfoChannel);
    288    }
    289    MOZ_ASSERT(!mCacheInfoChannel);
    290    mCacheInfoChannel = aCacheInfoChannel;
    291  }
    292 
    293  nsMainThreadPtrHandle<nsICacheInfoChannel> TakeCacheInfoChannel() {
    294    if (mWrappedResponse) {
    295      return mWrappedResponse->TakeCacheInfoChannel();
    296    }
    297    nsMainThreadPtrHandle<nsICacheInfoChannel> rtn = mCacheInfoChannel;
    298    mCacheInfoChannel = nullptr;
    299    return rtn;
    300  }
    301 
    302  bool HasCacheInfoChannel() const {
    303    if (mWrappedResponse) {
    304      return !!mWrappedResponse->HasCacheInfoChannel();
    305    }
    306    return !!mCacheInfoChannel;
    307  }
    308 
    309  bool HasBeenCloned() const { return mCloned; }
    310 
    311  void SetSerializeAsLazy(bool aAllow) { mSerializeAsLazy = aAllow; }
    312  bool CanSerializeAsLazy() const { return mSerializeAsLazy; }
    313 
    314  void InitChannelInfo(nsIChannel* aChannel) {
    315    mChannelInfo.InitFromChannel(aChannel);
    316  }
    317 
    318  void InitChannelInfo(nsITransportSecurityInfo* aSecurityInfo) {
    319    mChannelInfo.InitFromTransportSecurityInfo(aSecurityInfo);
    320  }
    321 
    322  void InitChannelInfo(const ChannelInfo& aChannelInfo) {
    323    mChannelInfo = aChannelInfo;
    324  }
    325 
    326  const ChannelInfo& GetChannelInfo() const { return mChannelInfo; }
    327 
    328  const UniquePtr<mozilla::ipc::PrincipalInfo>& GetPrincipalInfo() const {
    329    return mPrincipalInfo;
    330  }
    331 
    332  bool IsRedirected() const { return mURLList.Length() > 1; }
    333 
    334  nsresult GetErrorCode() const { return mErrorCode; }
    335 
    336  // Takes ownership of the principal info.
    337  void SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo);
    338 
    339  LoadTainting GetTainting() const;
    340 
    341  SafeRefPtr<InternalResponse> Unfiltered();
    342 
    343  InternalResponseMetadata GetMetadata();
    344 
    345  RequestCredentials GetCredentialsMode() const {
    346    if (mWrappedResponse) {
    347      return mWrappedResponse->GetCredentialsMode();
    348    }
    349    return mCredentialsMode;
    350  }
    351 
    352  ~InternalResponse();
    353 
    354 private:
    355  explicit InternalResponse(const InternalResponse& aOther) = delete;
    356  InternalResponse& operator=(const InternalResponse&) = delete;
    357 
    358  // Returns an instance of InternalResponse which is a copy of this
    359  // InternalResponse, except headers, body and wrapped response (if any) which
    360  // are left uninitialized. Used for cloning and filtering.
    361  SafeRefPtr<InternalResponse> CreateIncompleteCopy();
    362 
    363  template <typename T>
    364  static SafeRefPtr<InternalResponse> FromIPCTemplate(const T& aIPCResponse);
    365 
    366  ResponseType mType;
    367  // A response has an associated url list (a list of zero or more fetch URLs).
    368  // Unless stated otherwise, it is the empty list. The current url is the last
    369  // element in mURLlist
    370  nsTArray<nsCString> mURLList;
    371  const uint16_t mStatus;
    372  const nsCString mStatusText;
    373  RefPtr<InternalHeaders> mHeaders;
    374  nsCOMPtr<nsIInputStream> mBody;
    375  nsCString mBodyBlobURISpec;
    376  nsString mBodyLocalPath;
    377  int64_t mBodySize;
    378  // It's used to passed to the CacheResponse to generate padding size. Once, we
    379  // generate the padding size for resposne, we don't need it anymore.
    380  Maybe<uint32_t> mPaddingInfo;
    381  int64_t mPaddingSize;
    382  nsresult mErrorCode;
    383  RequestCredentials mCredentialsMode;
    384 
    385  // For alternative data such as JS Bytecode cached in the HTTP cache.
    386  nsCString mAlternativeDataType;
    387  nsCOMPtr<nsIInputStream> mAlternativeBody;
    388  nsMainThreadPtrHandle<nsICacheInfoChannel> mCacheInfoChannel;
    389  bool mCloned;
    390  // boolean to indicate the body/alternativeBody will be serialized as a
    391  // RemoteLazyInputStream.
    392  bool mSerializeAsLazy{true};
    393 
    394 public:
    395  static constexpr int64_t UNKNOWN_BODY_SIZE = -1;
    396  static constexpr int64_t UNKNOWN_PADDING_SIZE = -1;
    397 
    398 private:
    399  ChannelInfo mChannelInfo;
    400  UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
    401 
    402  // For filtered responses.
    403  // Cache, and SW interception should always serialize/access the underlying
    404  // unfiltered headers and when deserializing, create an InternalResponse
    405  // with the unfiltered headers followed by wrapping it.
    406  SafeRefPtr<InternalResponse> mWrappedResponse;
    407 };
    408 
    409 ParentToChildInternalResponse ToParentToChild(
    410    const ParentToParentInternalResponse& aResponse);
    411 
    412 }  // namespace dom
    413 }  // namespace mozilla
    414 
    415 #endif  // mozilla_dom_InternalResponse_h