tor-browser

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

ObliviousHttpChannel.cpp (26699B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set sw=2 ts=8 et tw=80 : */
      3 
      4 /* This Source Code Form is subject to the terms of the Mozilla Public
      5 * License, v. 2.0. If a copy of the MPL was not distributed with this
      6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      7 
      8 // HttpLog.h should generally be included first
      9 #include "HttpLog.h"
     10 
     11 #include "ObliviousHttpChannel.h"
     12 
     13 #include "BinaryHttpRequest.h"
     14 #include "nsIHttpHeaderVisitor.h"
     15 #include "nsStringStream.h"
     16 
     17 namespace mozilla::net {
     18 
     19 NS_IMPL_ISUPPORTS(ObliviousHttpChannel, nsIChannel, nsIHttpChannel,
     20                  nsIObliviousHttpChannel, nsIHttpChannelInternal,
     21                  nsIIdentChannel, nsIRequest, nsIRequestObserver,
     22                  nsIStreamListener, nsIUploadChannel2, nsITimedChannel)
     23 
     24 ObliviousHttpChannel::ObliviousHttpChannel(
     25    nsIURI* targetURI, const nsTArray<uint8_t>& encodedConfig,
     26    nsIHttpChannel* innerChannel)
     27    : mTargetURI(targetURI),
     28      mEncodedConfig(encodedConfig.Clone()),
     29      mInnerChannel(innerChannel),
     30      mInnerChannelInternal(do_QueryInterface(innerChannel)),
     31      mInnerChannelTimed(do_QueryInterface(innerChannel)) {
     32  LOG(("ObliviousHttpChannel ctor [this=%p]", this));
     33  MOZ_ASSERT(mInnerChannel);
     34  MOZ_ASSERT(mInnerChannelInternal);
     35  MOZ_ASSERT(mInnerChannelTimed);
     36 }
     37 
     38 ObliviousHttpChannel::~ObliviousHttpChannel() {
     39  LOG(("ObliviousHttpChannel dtor [this=%p]", this));
     40 }
     41 
     42 //-----------------------------------------------------------------------------
     43 // ObliviousHttpChannel::nsIHttpChannel
     44 //-----------------------------------------------------------------------------
     45 
     46 NS_IMETHODIMP
     47 ObliviousHttpChannel::GetTopLevelContentWindowId(uint64_t* aWindowId) {
     48  return mInnerChannel->GetTopLevelContentWindowId(aWindowId);
     49 }
     50 
     51 NS_IMETHODIMP
     52 ObliviousHttpChannel::SetTopLevelContentWindowId(uint64_t aWindowId) {
     53  return mInnerChannel->SetTopLevelContentWindowId(aWindowId);
     54 }
     55 
     56 NS_IMETHODIMP
     57 ObliviousHttpChannel::GetBrowserId(uint64_t* aWindowId) {
     58  return mInnerChannel->GetBrowserId(aWindowId);
     59 }
     60 
     61 NS_IMETHODIMP
     62 ObliviousHttpChannel::SetBrowserId(uint64_t aId) {
     63  return mInnerChannel->SetBrowserId(aId);
     64 }
     65 
     66 NS_IMETHODIMP
     67 ObliviousHttpChannel::GetTransferSize(uint64_t* aTransferSize) {
     68  return mInnerChannel->GetTransferSize(aTransferSize);
     69 }
     70 
     71 NS_IMETHODIMP
     72 ObliviousHttpChannel::GetRequestSize(uint64_t* aRequestSize) {
     73  return mInnerChannel->GetRequestSize(aRequestSize);
     74 }
     75 
     76 NS_IMETHODIMP
     77 ObliviousHttpChannel::GetDecodedBodySize(uint64_t* aDecodedBodySize) {
     78  return mInnerChannel->GetDecodedBodySize(aDecodedBodySize);
     79 }
     80 
     81 NS_IMETHODIMP
     82 ObliviousHttpChannel::GetRequestMethod(nsACString& aRequestMethod) {
     83  aRequestMethod.Assign(mMethod);
     84  return NS_OK;
     85 }
     86 
     87 NS_IMETHODIMP
     88 ObliviousHttpChannel::SetRequestMethod(const nsACString& aRequestMethod) {
     89  mMethod.Assign(aRequestMethod);
     90  return NS_OK;
     91 }
     92 
     93 NS_IMETHODIMP
     94 ObliviousHttpChannel::GetReferrerInfo(nsIReferrerInfo** aReferrerInfo) {
     95  return mInnerChannel->GetReferrerInfo(aReferrerInfo);
     96 }
     97 
     98 NS_IMETHODIMP
     99 ObliviousHttpChannel::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
    100  return mInnerChannel->SetReferrerInfo(aReferrerInfo);
    101 }
    102 
    103 NS_IMETHODIMP
    104 ObliviousHttpChannel::SetReferrerInfoWithoutClone(
    105    nsIReferrerInfo* aReferrerInfo) {
    106  return mInnerChannel->SetReferrerInfoWithoutClone(aReferrerInfo);
    107 }
    108 
    109 NS_IMETHODIMP
    110 ObliviousHttpChannel::GetRequestHeader(const nsACString& aHeader,
    111                                       nsACString& _retval) {
    112  _retval.Truncate();
    113  auto value = mHeaders.Lookup(aHeader);
    114  if (!value) {
    115    return NS_ERROR_NOT_AVAILABLE;
    116  }
    117  _retval.Assign(*value);
    118  return NS_OK;
    119 }
    120 
    121 NS_IMETHODIMP
    122 ObliviousHttpChannel::SetRequestHeader(const nsACString& aHeader,
    123                                       const nsACString& aValue, bool aMerge) {
    124  mHeaders.WithEntryHandle(aHeader, [&aValue, aMerge](auto&& entry) {
    125    if (!entry) {
    126      entry.Insert(aValue);
    127      return;
    128    }
    129    if (!aMerge) {
    130      entry.Update(aValue);
    131      return;
    132    }
    133    nsAutoCString newValue(*entry);
    134    newValue.AppendLiteral(", ");
    135    newValue.Append(aValue);
    136    entry.Update(newValue);
    137  });
    138  return NS_OK;
    139 }
    140 
    141 NS_IMETHODIMP
    142 ObliviousHttpChannel::SetNewReferrerInfo(
    143    const nsACString& aUrl, nsIReferrerInfo::ReferrerPolicyIDL aPolicy,
    144    bool aSendReferrer) {
    145  return mInnerChannel->SetNewReferrerInfo(aUrl, aPolicy, aSendReferrer);
    146 }
    147 
    148 NS_IMETHODIMP
    149 ObliviousHttpChannel::SetEmptyRequestHeader(const nsACString& aHeader) {
    150  return SetRequestHeader(aHeader, EmptyCString(), false);
    151 }
    152 
    153 NS_IMETHODIMP
    154 ObliviousHttpChannel::VisitRequestHeaders(nsIHttpHeaderVisitor* aVisitor) {
    155  for (auto iter = mHeaders.ConstIter(); !iter.Done(); iter.Next()) {
    156    nsresult rv = aVisitor->VisitHeader(iter.Key(), iter.Data());
    157    if (NS_FAILED(rv)) {
    158      return rv;
    159    }
    160  }
    161  return NS_OK;
    162 }
    163 
    164 NS_IMETHODIMP
    165 ObliviousHttpChannel::VisitNonDefaultRequestHeaders(
    166    nsIHttpHeaderVisitor* aVisitor) {
    167  return mInnerChannel->VisitNonDefaultRequestHeaders(aVisitor);
    168 }
    169 
    170 NS_IMETHODIMP
    171 ObliviousHttpChannel::GetAllowSTS(bool* aAllowSTS) {
    172  return mInnerChannel->GetAllowSTS(aAllowSTS);
    173 }
    174 
    175 NS_IMETHODIMP
    176 ObliviousHttpChannel::SetAllowSTS(bool aAllowSTS) {
    177  return mInnerChannel->SetAllowSTS(aAllowSTS);
    178 }
    179 
    180 NS_IMETHODIMP
    181 ObliviousHttpChannel::GetRedirectionLimit(uint32_t* aRedirectionLimit) {
    182  return mInnerChannel->GetRedirectionLimit(aRedirectionLimit);
    183 }
    184 
    185 NS_IMETHODIMP
    186 ObliviousHttpChannel::SetRedirectionLimit(uint32_t aRedirectionLimit) {
    187  return mInnerChannel->SetRedirectionLimit(aRedirectionLimit);
    188 }
    189 
    190 NS_IMETHODIMP
    191 ObliviousHttpChannel::GetResponseStatus(uint32_t* aResponseStatus) {
    192  if (!mBinaryHttpResponse) {
    193    return NS_ERROR_NOT_AVAILABLE;
    194  }
    195  uint16_t responseStatus;
    196  nsresult rv = mBinaryHttpResponse->GetStatus(&responseStatus);
    197  if (NS_FAILED(rv)) {
    198    return rv;
    199  }
    200  *aResponseStatus = responseStatus;
    201  return NS_OK;
    202 }
    203 
    204 NS_IMETHODIMP
    205 ObliviousHttpChannel::GetResponseStatusText(nsACString& aResponseStatusText) {
    206  LOG(("ObliviousHttpChannel::GetResponseStatusText NOT IMPLEMENTED [this=%p]",
    207       this));
    208  return NS_ERROR_NOT_IMPLEMENTED;
    209 }
    210 
    211 NS_IMETHODIMP
    212 ObliviousHttpChannel::GetRequestSucceeded(bool* aRequestSucceeded) {
    213  uint32_t responseStatus;
    214  nsresult rv = GetResponseStatus(&responseStatus);
    215  if (NS_FAILED(rv)) {
    216    return rv;
    217  }
    218  *aRequestSucceeded = (responseStatus / 100) == 2;
    219  return NS_OK;
    220 }
    221 
    222 NS_IMETHODIMP
    223 ObliviousHttpChannel::GetIsMainDocumentChannel(bool* aValue) {
    224  return mInnerChannel->GetIsMainDocumentChannel(aValue);
    225 }
    226 
    227 NS_IMETHODIMP
    228 ObliviousHttpChannel::SetIsMainDocumentChannel(bool aValue) {
    229  return mInnerChannel->SetIsMainDocumentChannel(aValue);
    230 }
    231 
    232 NS_IMETHODIMP
    233 ObliviousHttpChannel::GetResponseHeader(const nsACString& header,
    234                                        nsACString& _retval) {
    235  if (!mBinaryHttpResponse) {
    236    return NS_ERROR_NOT_AVAILABLE;
    237  }
    238  nsTArray<nsCString> responseHeaderNames;
    239  nsTArray<nsCString> responseHeaderValues;
    240  nsresult rv = mBinaryHttpResponse->GetHeaderNames(responseHeaderNames);
    241  if (NS_FAILED(rv)) {
    242    return rv;
    243  }
    244  rv = mBinaryHttpResponse->GetHeaderValues(responseHeaderValues);
    245  if (NS_FAILED(rv)) {
    246    return rv;
    247  }
    248  for (size_t i = 0;
    249       i < responseHeaderNames.Length() && i < responseHeaderValues.Length();
    250       i++) {
    251    if (responseHeaderNames[i].EqualsIgnoreCase(header)) {
    252      _retval.Assign(responseHeaderValues[i]);
    253      return NS_OK;
    254    }
    255  }
    256  return NS_ERROR_NOT_AVAILABLE;
    257 }
    258 
    259 NS_IMETHODIMP
    260 ObliviousHttpChannel::SetResponseHeader(const nsACString& header,
    261                                        const nsACString& value, bool merge) {
    262  LOG(("ObliviousHttpChannel::SetResponseHeader NOT IMPLEMENTED [this=%p]",
    263       this));
    264  return NS_ERROR_NOT_IMPLEMENTED;
    265 }
    266 
    267 NS_IMETHODIMP
    268 ObliviousHttpChannel::VisitResponseHeaders(nsIHttpHeaderVisitor* aVisitor) {
    269  if (!mBinaryHttpResponse) {
    270    return NS_ERROR_NOT_AVAILABLE;
    271  }
    272  nsTArray<nsCString> responseHeaderNames;
    273  nsTArray<nsCString> responseHeaderValues;
    274  nsresult rv = mBinaryHttpResponse->GetHeaderNames(responseHeaderNames);
    275  if (NS_FAILED(rv)) {
    276    return rv;
    277  }
    278  rv = mBinaryHttpResponse->GetHeaderValues(responseHeaderValues);
    279  if (NS_FAILED(rv)) {
    280    return rv;
    281  }
    282  for (size_t i = 0;
    283       i < responseHeaderNames.Length() && i < responseHeaderValues.Length();
    284       i++) {
    285    rv = aVisitor->VisitHeader(responseHeaderNames[i], responseHeaderValues[i]);
    286    if (NS_FAILED(rv)) {
    287      return rv;
    288    }
    289  }
    290  return rv;
    291 }
    292 
    293 NS_IMETHODIMP
    294 ObliviousHttpChannel::GetOriginalResponseHeader(
    295    const nsACString& header, nsIHttpHeaderVisitor* aVisitor) {
    296  return NS_ERROR_NOT_IMPLEMENTED;
    297 }
    298 
    299 NS_IMETHODIMP
    300 ObliviousHttpChannel::VisitOriginalResponseHeaders(
    301    nsIHttpHeaderVisitor* aVisitor) {
    302  LOG(
    303      ("ObliviousHttpChannel::VisitOriginalResponseHeaders NOT IMPLEMENTED "
    304       "[this=%p]",
    305       this));
    306  return NS_ERROR_NOT_IMPLEMENTED;
    307 }
    308 
    309 NS_IMETHODIMP
    310 ObliviousHttpChannel::ShouldStripRequestBodyHeader(const nsACString& aMethod,
    311                                                   bool* aResult) {
    312  LOG(
    313      ("ObliviousHttpChannel::ShouldStripRequestBodyHeader NOT IMPLEMENTED "
    314       "[this=%p]",
    315       this));
    316  return NS_ERROR_NOT_IMPLEMENTED;
    317 }
    318 
    319 NS_IMETHODIMP
    320 ObliviousHttpChannel::IsNoStoreResponse(bool* _retval) {
    321  LOG(("ObliviousHttpChannel::IsNoStoreResponse NOT IMPLEMENTED [this=%p]",
    322       this));
    323  return NS_ERROR_NOT_IMPLEMENTED;
    324 }
    325 
    326 NS_IMETHODIMP
    327 ObliviousHttpChannel::IsNoCacheResponse(bool* _retval) {
    328  LOG(("ObliviousHttpChannel::IsNoCacheResponse NOT IMPLEMENTED [this=%p]",
    329       this));
    330  return NS_ERROR_NOT_IMPLEMENTED;
    331 }
    332 
    333 NS_IMETHODIMP
    334 ObliviousHttpChannel::RedirectTo(nsIURI* aNewURI) {
    335  LOG(("ObliviousHttpChannel::RedirectTo NOT IMPLEMENTED [this=%p]", this));
    336  return NS_ERROR_NOT_IMPLEMENTED;
    337 }
    338 
    339 NS_IMETHODIMP
    340 ObliviousHttpChannel::UpgradeToSecure() {
    341  LOG(("ObliviousHttpChannel::UpgradeToSecure NOT IMPLEMENTED [this=%p]",
    342       this));
    343  return NS_ERROR_NOT_IMPLEMENTED;
    344 }
    345 
    346 NS_IMETHODIMP
    347 ObliviousHttpChannel::GetRequestObserversCalled(bool* aCalled) {
    348  return mInnerChannel->GetRequestObserversCalled(aCalled);
    349 }
    350 
    351 NS_IMETHODIMP
    352 ObliviousHttpChannel::SetRequestObserversCalled(bool aCalled) {
    353  return mInnerChannel->SetRequestObserversCalled(aCalled);
    354 }
    355 
    356 NS_IMETHODIMP
    357 ObliviousHttpChannel::GetRequestContextID(uint64_t* _retval) {
    358  return mInnerChannel->GetRequestContextID(_retval);
    359 }
    360 
    361 NS_IMETHODIMP
    362 ObliviousHttpChannel::SetRequestContextID(uint64_t rcID) {
    363  return mInnerChannel->SetRequestContextID(rcID);
    364 }
    365 
    366 NS_IMETHODIMP
    367 ObliviousHttpChannel::GetIsUserAgentHeaderOutdated(bool* aValue) {
    368  return mInnerChannel->GetIsUserAgentHeaderOutdated(aValue);
    369 }
    370 
    371 NS_IMETHODIMP
    372 ObliviousHttpChannel::SetIsUserAgentHeaderOutdated(bool aValue) {
    373  return mInnerChannel->SetIsUserAgentHeaderOutdated(aValue);
    374 }
    375 
    376 NS_IMETHODIMP
    377 ObliviousHttpChannel::GetProtocolVersion(nsACString& aProtocolVersion) {
    378  return mInnerChannel->GetProtocolVersion(aProtocolVersion);
    379 }
    380 
    381 NS_IMETHODIMP
    382 ObliviousHttpChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) {
    383  LOG(("ObliviousHttpChannel::GetEncodedBodySize NOT IMPLEMENTED [this=%p]",
    384       this));
    385  return NS_ERROR_NOT_IMPLEMENTED;
    386 }
    387 
    388 NS_IMETHODIMP
    389 ObliviousHttpChannel::LogBlockedCORSRequest(const nsAString& aMessage,
    390                                            const nsACString& aCategory,
    391                                            bool aIsWarning) {
    392  return mInnerChannel->LogBlockedCORSRequest(aMessage, aCategory, aIsWarning);
    393 }
    394 
    395 NS_IMETHODIMP
    396 ObliviousHttpChannel::LogMimeTypeMismatch(const nsACString& aMessageName,
    397                                          bool aWarning, const nsAString& aURL,
    398                                          const nsAString& aContentType) {
    399  return mInnerChannel->LogMimeTypeMismatch(aMessageName, aWarning, aURL,
    400                                            aContentType);
    401 }
    402 
    403 void ObliviousHttpChannel::SetSource(
    404    mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource) {
    405  LOG(("ObliviousHttpChannel::SetSource NOT IMPLEMENTED [this=%p]", this));
    406  // NS_ERROR_NOT_IMPLEMENTED
    407 }
    408 
    409 void ObliviousHttpChannel::SetConnectionInfo(nsHttpConnectionInfo* aCi) {
    410  if (mInnerChannelInternal) {
    411    mInnerChannelInternal->SetConnectionInfo(aCi);
    412  }
    413 }
    414 
    415 void ObliviousHttpChannel::DoDiagnosticAssertWhenOnStopNotCalledOnDestroy() {
    416  if (mInnerChannelInternal) {
    417    mInnerChannelInternal->DoDiagnosticAssertWhenOnStopNotCalledOnDestroy();
    418  }
    419 }
    420 
    421 void ObliviousHttpChannel::DisableAltDataCache() {
    422  if (mInnerChannelInternal) {
    423    mInnerChannelInternal->DisableAltDataCache();
    424  }
    425 }
    426 
    427 void ObliviousHttpChannel::SetAltDataForChild(bool aIsForChild) {
    428  if (mInnerChannelInternal) {
    429    mInnerChannelInternal->SetAltDataForChild(aIsForChild);
    430  }
    431 }
    432 
    433 void ObliviousHttpChannel::SetCorsPreflightParameters(
    434    nsTArray<nsTString<char>> const& aUnsafeHeaders,
    435    bool aShouldStripRequestBodyHeader, bool aShouldStripAuthHeader) {
    436  if (mInnerChannelInternal) {
    437    mInnerChannelInternal->SetCorsPreflightParameters(
    438        aUnsafeHeaders, aShouldStripRequestBodyHeader, aShouldStripAuthHeader);
    439  }
    440 }
    441 
    442 //-----------------------------------------------------------------------------
    443 // ObliviousHttpChannel::nsIChannel
    444 //-----------------------------------------------------------------------------
    445 
    446 NS_IMETHODIMP
    447 ObliviousHttpChannel::GetOriginalURI(nsIURI** aOriginalURI) {
    448  return mInnerChannel->GetOriginalURI(aOriginalURI);
    449 }
    450 
    451 NS_IMETHODIMP
    452 ObliviousHttpChannel::SetOriginalURI(nsIURI* aOriginalURI) {
    453  return mInnerChannel->SetOriginalURI(aOriginalURI);
    454 }
    455 
    456 NS_IMETHODIMP
    457 ObliviousHttpChannel::GetURI(nsIURI** aURI) {
    458  *aURI = do_AddRef(mTargetURI).take();
    459  return NS_OK;
    460 }
    461 
    462 NS_IMETHODIMP
    463 ObliviousHttpChannel::GetOwner(nsISupports** aOwner) {
    464  return mInnerChannel->GetOwner(aOwner);
    465 }
    466 
    467 NS_IMETHODIMP
    468 ObliviousHttpChannel::SetOwner(nsISupports* aOwner) {
    469  return mInnerChannel->SetOwner(aOwner);
    470 }
    471 
    472 NS_IMETHODIMP
    473 ObliviousHttpChannel::GetNotificationCallbacks(
    474    nsIInterfaceRequestor** aNotificationCallbacks) {
    475  return mInnerChannel->GetNotificationCallbacks(aNotificationCallbacks);
    476 }
    477 
    478 NS_IMETHODIMP
    479 ObliviousHttpChannel::SetNotificationCallbacks(
    480    nsIInterfaceRequestor* aNotificationCallbacks) {
    481  return mInnerChannel->SetNotificationCallbacks(aNotificationCallbacks);
    482 }
    483 
    484 NS_IMETHODIMP
    485 ObliviousHttpChannel::GetSecurityInfo(
    486    nsITransportSecurityInfo** aSecurityInfo) {
    487  return mInnerChannel->GetSecurityInfo(aSecurityInfo);
    488 }
    489 
    490 NS_IMETHODIMP
    491 ObliviousHttpChannel::GetContentType(nsACString& aContentType) {
    492  return GetResponseHeader("content-type"_ns, aContentType);
    493 }
    494 
    495 NS_IMETHODIMP
    496 ObliviousHttpChannel::SetContentType(const nsACString& aContentType) {
    497  mContentType = aContentType;
    498  return NS_OK;
    499 }
    500 
    501 NS_IMETHODIMP
    502 ObliviousHttpChannel::GetContentCharset(nsACString& aContentCharset) {
    503  return mInnerChannel->GetContentCharset(aContentCharset);
    504 }
    505 
    506 NS_IMETHODIMP
    507 ObliviousHttpChannel::SetContentCharset(const nsACString& aContentCharset) {
    508  return mInnerChannel->SetContentCharset(aContentCharset);
    509 }
    510 
    511 NS_IMETHODIMP
    512 ObliviousHttpChannel::GetContentLength(int64_t* aContentLength) {
    513  return mInnerChannel->GetContentLength(aContentLength);
    514 }
    515 
    516 NS_IMETHODIMP
    517 ObliviousHttpChannel::SetContentLength(int64_t aContentLength) {
    518  return mInnerChannel->SetContentLength(aContentLength);
    519 }
    520 
    521 NS_IMETHODIMP
    522 ObliviousHttpChannel::Open(nsIInputStream** aStream) {
    523  LOG(("ObliviousHttpChannel::Open NOT IMPLEMENTED [this=%p]", this));
    524  return NS_ERROR_NOT_IMPLEMENTED;
    525 }
    526 
    527 NS_IMETHODIMP
    528 ObliviousHttpChannel::AsyncOpen(nsIStreamListener* aListener) {
    529  LOG(("ObliviousHttpChannel::AsyncOpen [this=%p, listener=%p]", this,
    530       aListener));
    531  mStreamListener = aListener;
    532  nsresult rv = mInnerChannel->SetRequestMethod("POST"_ns);
    533  if (NS_FAILED(rv)) {
    534    return rv;
    535  }
    536  rv = mInnerChannel->SetRequestHeader("Content-Type"_ns,
    537                                       "message/ohttp-req"_ns, false);
    538  if (NS_FAILED(rv)) {
    539    return rv;
    540  }
    541  nsAutoCString scheme;
    542  if (!mTargetURI) {
    543    return NS_ERROR_NULL_POINTER;
    544  }
    545  rv = mTargetURI->GetScheme(scheme);
    546  if (NS_FAILED(rv)) {
    547    return rv;
    548  }
    549  nsAutoCString authority;
    550  rv = mTargetURI->GetHostPort(authority);
    551  if (NS_FAILED(rv)) {
    552    return rv;
    553  }
    554  nsAutoCString path;
    555  rv = mTargetURI->GetPathQueryRef(path);
    556  if (NS_FAILED(rv)) {
    557    return rv;
    558  }
    559  nsTArray<nsCString> headerNames;
    560  nsTArray<nsCString> headerValues;
    561  for (auto iter = mHeaders.ConstIter(); !iter.Done(); iter.Next()) {
    562    headerNames.AppendElement(iter.Key());
    563    headerValues.AppendElement(iter.Data());
    564  }
    565  if (!mContentType.IsEmpty() && !headerNames.Contains("Content-Type")) {
    566    headerNames.AppendElement("Content-Type"_ns);
    567    headerValues.AppendElement(mContentType);
    568  }
    569  nsCOMPtr<nsIBinaryHttp> bhttp(
    570      do_GetService("@mozilla.org/network/binary-http;1"));
    571  nsCOMPtr<nsIBinaryHttpRequest> bhttpRequest(new BinaryHttpRequest(
    572      mMethod, scheme, authority, path, std::move(headerNames),
    573      std::move(headerValues), std::move(mContent)));
    574  nsTArray<uint8_t> encodedRequest;
    575  rv = bhttp->EncodeRequest(bhttpRequest, encodedRequest);
    576  if (NS_FAILED(rv)) {
    577    return rv;
    578  }
    579  nsCOMPtr<nsIObliviousHttp> obliviousHttp(
    580      do_GetService("@mozilla.org/network/oblivious-http;1"));
    581  if (!obliviousHttp) {
    582    return NS_ERROR_FAILURE;
    583  }
    584  rv = obliviousHttp->EncapsulateRequest(mEncodedConfig, encodedRequest,
    585                                         getter_AddRefs(mEncapsulatedRequest));
    586  if (NS_FAILED(rv)) {
    587    return rv;
    588  }
    589  nsTArray<uint8_t> encRequest;
    590  rv = mEncapsulatedRequest->GetEncRequest(encRequest);
    591  if (NS_FAILED(rv)) {
    592    return rv;
    593  }
    594  nsCOMPtr<nsIUploadChannel2> uploadChannel(do_QueryInterface(mInnerChannel));
    595  if (!uploadChannel) {
    596    return NS_ERROR_UNEXPECTED;
    597  }
    598  nsCOMPtr<nsIInputStream> uploadStream;
    599  uint32_t streamLength = encRequest.Length();
    600  rv = NS_NewByteInputStream(getter_AddRefs(uploadStream),
    601                             std::move(encRequest));
    602  if (NS_FAILED(rv)) {
    603    return rv;
    604  }
    605  rv = uploadChannel->ExplicitSetUploadStream(
    606      uploadStream, "message/ohttp-req"_ns, streamLength, "POST"_ns, false);
    607  if (NS_FAILED(rv)) {
    608    return rv;
    609  }
    610  return mInnerChannel->AsyncOpen(this);
    611 }
    612 
    613 NS_IMETHODIMP
    614 ObliviousHttpChannel::GetCanceled(bool* aCanceled) {
    615  return mInnerChannel->GetCanceled(aCanceled);
    616 }
    617 
    618 NS_IMETHODIMP
    619 ObliviousHttpChannel::GetContentDisposition(uint32_t* aContentDisposition) {
    620  return mInnerChannel->GetContentDisposition(aContentDisposition);
    621 }
    622 
    623 NS_IMETHODIMP
    624 ObliviousHttpChannel::SetContentDisposition(uint32_t aContentDisposition) {
    625  return mInnerChannel->SetContentDisposition(aContentDisposition);
    626 }
    627 
    628 NS_IMETHODIMP
    629 ObliviousHttpChannel::GetContentDispositionFilename(
    630    nsAString& aContentDispositionFilename) {
    631  return mInnerChannel->GetContentDispositionFilename(
    632      aContentDispositionFilename);
    633 }
    634 
    635 NS_IMETHODIMP
    636 ObliviousHttpChannel::SetContentDispositionFilename(
    637    const nsAString& aContentDispositionFilename) {
    638  return mInnerChannel->SetContentDispositionFilename(
    639      aContentDispositionFilename);
    640 }
    641 
    642 NS_IMETHODIMP
    643 ObliviousHttpChannel::GetContentDispositionHeader(
    644    nsACString& aContentDispositionHeader) {
    645  return mInnerChannel->GetContentDispositionHeader(aContentDispositionHeader);
    646 }
    647 
    648 NS_IMETHODIMP
    649 ObliviousHttpChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) {
    650  return mInnerChannel->GetLoadInfo(aLoadInfo);
    651 }
    652 
    653 NS_IMETHODIMP
    654 ObliviousHttpChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) {
    655  return mInnerChannel->SetLoadInfo(aLoadInfo);
    656 }
    657 
    658 NS_IMETHODIMP
    659 ObliviousHttpChannel::GetIsDocument(bool* aIsDocument) {
    660  return mInnerChannel->GetIsDocument(aIsDocument);
    661 }
    662 
    663 //-----------------------------------------------------------------------------
    664 // ObliviousHttpChannel::nsIStreamListener
    665 //-----------------------------------------------------------------------------
    666 
    667 NS_IMETHODIMP
    668 ObliviousHttpChannel::OnDataAvailable(nsIRequest* aRequest,
    669                                      nsIInputStream* aStream, uint64_t aOffset,
    670                                      uint32_t aCount) {
    671  LOG(
    672      ("ObliviousHttpChannel::OnDataAvailable [this=%p, request=%p, stream=%p, "
    673       "offset=%" PRIu64 ", count=%u]",
    674       this, aRequest, aStream, aOffset, aCount));
    675  MOZ_ASSERT(aOffset == mRawResponse.Length());
    676  size_t oldLength = mRawResponse.Length();
    677  size_t newLength = oldLength + aCount;
    678  if (newLength < oldLength) {  // i.e., overflow
    679    return NS_ERROR_FAILURE;
    680  }
    681  mRawResponse.SetCapacity(newLength);
    682  mRawResponse.SetLengthAndRetainStorage(newLength);
    683  void* dest = mRawResponse.Elements() + oldLength;
    684  uint64_t written = 0;
    685  nsresult rv = NS_ReadInputStreamToBuffer(aStream, &dest, aCount, &written);
    686  if (NS_FAILED(rv)) {
    687    return rv;
    688  }
    689  if (written != aCount) {
    690    return NS_ERROR_FAILURE;
    691  }
    692  return NS_OK;
    693 }
    694 
    695 //-----------------------------------------------------------------------------
    696 // ObliviousHttpChannel::nsIRequestObserver
    697 //-----------------------------------------------------------------------------
    698 
    699 NS_IMETHODIMP
    700 ObliviousHttpChannel::OnStartRequest(nsIRequest* aRequest) {
    701  LOG(("ObliviousHttpChannel::OnStartRequest [this=%p, request=%p]", this,
    702       aRequest));
    703  return NS_OK;
    704 }
    705 
    706 nsresult ObliviousHttpChannel::ProcessOnStopRequest() {
    707  if (mRawResponse.IsEmpty()) {
    708    return NS_OK;
    709  }
    710  nsCOMPtr<nsIObliviousHttp> obliviousHttp(
    711      do_GetService("@mozilla.org/network/oblivious-http;1"));
    712  if (!obliviousHttp) {
    713    return NS_ERROR_FAILURE;
    714  }
    715  nsCOMPtr<nsIObliviousHttpClientResponse> response;
    716  nsresult rv = mEncapsulatedRequest->GetResponse(getter_AddRefs(response));
    717  if (NS_FAILED(rv)) {
    718    return rv;
    719  }
    720  nsTArray<uint8_t> decapsulated;
    721  rv = response->Decapsulate(mRawResponse, decapsulated);
    722  if (NS_FAILED(rv)) {
    723    return rv;
    724  }
    725  nsCOMPtr<nsIBinaryHttp> bhttp(
    726      do_GetService("@mozilla.org/network/binary-http;1"));
    727  if (!bhttp) {
    728    return NS_ERROR_FAILURE;
    729  }
    730  return bhttp->DecodeResponse(decapsulated,
    731                               getter_AddRefs(mBinaryHttpResponse));
    732 }
    733 
    734 void ObliviousHttpChannel::EmitOnDataAvailable() {
    735  if (!mBinaryHttpResponse) {
    736    return;
    737  }
    738  nsTArray<uint8_t> content;
    739  nsresult rv = mBinaryHttpResponse->GetContent(content);
    740  if (NS_FAILED(rv)) {
    741    return;
    742  }
    743  if (content.IsEmpty()) {
    744    return;
    745  }
    746  if (content.Length() > std::numeric_limits<uint32_t>::max()) {
    747    return;
    748  }
    749  uint32_t contentLength = (uint32_t)content.Length();
    750  nsCOMPtr<nsIInputStream> contentStream;
    751  rv = NS_NewByteInputStream(getter_AddRefs(contentStream), std::move(content));
    752  if (NS_FAILED(rv)) {
    753    return;
    754  }
    755  rv = mStreamListener->OnDataAvailable(this, contentStream, 0, contentLength);
    756  (void)rv;
    757 }
    758 
    759 NS_IMETHODIMP
    760 ObliviousHttpChannel::OnStopRequest(nsIRequest* aRequest,
    761                                    nsresult aStatusCode) {
    762  LOG(("ObliviousHttpChannel::OnStopRequest [this=%p, request=%p, status=%u]",
    763       this, aRequest, (uint32_t)aStatusCode));
    764 
    765  auto releaseStreamListener = MakeScopeExit(
    766      [self = RefPtr{this}]() mutable { self->mStreamListener = nullptr; });
    767 
    768  if (NS_SUCCEEDED(aStatusCode)) {
    769    bool requestSucceeded;
    770    nsresult rv = mInnerChannel->GetRequestSucceeded(&requestSucceeded);
    771    if (NS_SUCCEEDED(rv) && requestSucceeded) {
    772      aStatusCode = ProcessOnStopRequest();
    773    }
    774  }
    775  (void)mStreamListener->OnStartRequest(this);
    776  if (NS_SUCCEEDED(aStatusCode)) {
    777    EmitOnDataAvailable();
    778  }
    779  (void)mStreamListener->OnStopRequest(this, aStatusCode);
    780 
    781  return NS_OK;
    782 }
    783 
    784 //-----------------------------------------------------------------------------
    785 // ObliviousHttpChannel::nsIObliviousHttpChannel
    786 //-----------------------------------------------------------------------------
    787 
    788 NS_IMETHODIMP
    789 ObliviousHttpChannel::GetRelayChannel(nsIHttpChannel** aChannel) {
    790  if (!aChannel) {
    791    return NS_ERROR_INVALID_ARG;
    792  }
    793  *aChannel = do_AddRef(mInnerChannel).take();
    794  return NS_OK;
    795 }
    796 
    797 //-----------------------------------------------------------------------------
    798 // ObliviousHttpChannel::nsIUploadChannel2
    799 //-----------------------------------------------------------------------------
    800 
    801 NS_IMETHODIMP ObliviousHttpChannel::ExplicitSetUploadStream(
    802    nsIInputStream* aStream, const nsACString& aContentType,
    803    int64_t aContentLength, const nsACString& aMethod, bool aStreamHasHeaders) {
    804  // This function should only be called before AsyncOpen.
    805  if (mStreamListener) {
    806    return NS_ERROR_IN_PROGRESS;
    807  }
    808  if (aMethod != "POST"_ns && aMethod != "PUT" && aMethod != "DELETE") {
    809    return NS_ERROR_INVALID_ARG;
    810  }
    811  if (aStreamHasHeaders) {
    812    return NS_ERROR_INVALID_ARG;
    813  }
    814  mMethod.Assign(aMethod);
    815  uint64_t available;
    816  if (aContentLength < 0) {
    817    nsresult rv = aStream->Available(&available);
    818    if (NS_FAILED(rv)) {
    819      return rv;
    820    }
    821  } else {
    822    available = aContentLength;
    823  }
    824  if (available > std::numeric_limits<int64_t>::max()) {
    825    return NS_ERROR_FAILURE;
    826  }
    827  mContent.SetCapacity(available);
    828  mContent.SetLengthAndRetainStorage(available);
    829  void* dest = mContent.Elements();
    830  uint64_t written = 0;
    831  nsresult rv =
    832      NS_ReadInputStreamToBuffer(aStream, &dest, (int64_t)available, &written);
    833  if (NS_FAILED(rv)) {
    834    return rv;
    835  }
    836  if (written != available) {
    837    return NS_ERROR_FAILURE;
    838  }
    839  mContentType = aContentType;
    840  return NS_OK;
    841 }
    842 
    843 NS_IMETHODIMP ObliviousHttpChannel::GetUploadStreamHasHeaders(
    844    bool* aUploadStreamHasHeaders) {
    845  *aUploadStreamHasHeaders = false;
    846  return NS_OK;
    847 }
    848 
    849 NS_IMETHODIMP ObliviousHttpChannel::CloneUploadStream(
    850    int64_t* aContentLength, nsIInputStream** _retval) {
    851  LOG(("ObliviousHttpChannel::CloneUploadStream NOT IMPLEMENTED [this=%p]",
    852       this));
    853  return NS_ERROR_NOT_IMPLEMENTED;
    854 }
    855 
    856 NS_IMETHODIMP ObliviousHttpChannel::SetClassicScriptHintCharset(
    857    const nsAString& aClassicScriptHintCharset) {
    858  return NS_ERROR_NOT_IMPLEMENTED;
    859 }
    860 
    861 NS_IMETHODIMP ObliviousHttpChannel::GetClassicScriptHintCharset(
    862    nsAString& aClassicScriptHintCharset) {
    863  return NS_ERROR_NOT_IMPLEMENTED;
    864 }
    865 
    866 NS_IMETHODIMP ObliviousHttpChannel::SetDocumentCharacterSet(
    867    const nsAString& aDocumentCharacterSet) {
    868  return NS_ERROR_NOT_IMPLEMENTED;
    869 }
    870 
    871 NS_IMETHODIMP ObliviousHttpChannel::GetDocumentCharacterSet(
    872    nsAString& aDocumenharacterSet) {
    873  return NS_ERROR_NOT_IMPLEMENTED;
    874 }
    875 
    876 NS_IMETHODIMP ObliviousHttpChannel::GetDecompressDictionary(
    877    DictionaryCacheEntry** aDictionary) {
    878  *aDictionary = nullptr;
    879  return NS_OK;
    880 }
    881 
    882 NS_IMETHODIMP ObliviousHttpChannel::SetDecompressDictionary(
    883    DictionaryCacheEntry* aDictionary) {
    884  return NS_OK;
    885 }
    886 
    887 }  // namespace mozilla::net