forked from mirrors/gecko-dev
For WebDriver BiDi network interception we need to be able to modify the request as late as possible. This changeset exposes RequestObserversCalled to JS so that we can update it from the webdriver bidi codebase. Differential Revision: https://phabricator.services.mozilla.com/D208011
870 lines
26 KiB
C++
870 lines
26 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set sw=2 ts=8 et tw=80 : */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
// HttpLog.h should generally be included first
|
|
#include "HttpLog.h"
|
|
|
|
#include "ObliviousHttpChannel.h"
|
|
|
|
#include "BinaryHttpRequest.h"
|
|
#include "nsIHttpHeaderVisitor.h"
|
|
#include "nsStringStream.h"
|
|
|
|
namespace mozilla::net {
|
|
|
|
NS_IMPL_ISUPPORTS(ObliviousHttpChannel, nsIChannel, nsIHttpChannel,
|
|
nsIObliviousHttpChannel, nsIHttpChannelInternal,
|
|
nsIIdentChannel, nsIRequest, nsIRequestObserver,
|
|
nsIStreamListener, nsIUploadChannel2, nsITimedChannel)
|
|
|
|
ObliviousHttpChannel::ObliviousHttpChannel(
|
|
nsIURI* targetURI, const nsTArray<uint8_t>& encodedConfig,
|
|
nsIHttpChannel* innerChannel)
|
|
: mTargetURI(targetURI),
|
|
mEncodedConfig(encodedConfig.Clone()),
|
|
mInnerChannel(innerChannel),
|
|
mInnerChannelInternal(do_QueryInterface(innerChannel)),
|
|
mInnerChannelTimed(do_QueryInterface(innerChannel)) {
|
|
LOG(("ObliviousHttpChannel ctor [this=%p]", this));
|
|
MOZ_ASSERT(mInnerChannel);
|
|
MOZ_ASSERT(mInnerChannelInternal);
|
|
MOZ_ASSERT(mInnerChannelTimed);
|
|
}
|
|
|
|
ObliviousHttpChannel::~ObliviousHttpChannel() {
|
|
LOG(("ObliviousHttpChannel dtor [this=%p]", this));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ObliviousHttpChannel::nsIHttpChannel
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetTopLevelContentWindowId(uint64_t* aWindowId) {
|
|
return mInnerChannel->GetTopLevelContentWindowId(aWindowId);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetTopLevelContentWindowId(uint64_t aWindowId) {
|
|
return mInnerChannel->SetTopLevelContentWindowId(aWindowId);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetBrowserId(uint64_t* aWindowId) {
|
|
return mInnerChannel->GetBrowserId(aWindowId);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetBrowserId(uint64_t aId) {
|
|
return mInnerChannel->SetBrowserId(aId);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetTransferSize(uint64_t* aTransferSize) {
|
|
return mInnerChannel->GetTransferSize(aTransferSize);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetRequestSize(uint64_t* aRequestSize) {
|
|
return mInnerChannel->GetRequestSize(aRequestSize);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetDecodedBodySize(uint64_t* aDecodedBodySize) {
|
|
return mInnerChannel->GetDecodedBodySize(aDecodedBodySize);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetRequestMethod(nsACString& aRequestMethod) {
|
|
aRequestMethod.Assign(mMethod);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetRequestMethod(const nsACString& aRequestMethod) {
|
|
mMethod.Assign(aRequestMethod);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetReferrerInfo(nsIReferrerInfo** aReferrerInfo) {
|
|
return mInnerChannel->GetReferrerInfo(aReferrerInfo);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
|
|
return mInnerChannel->SetReferrerInfo(aReferrerInfo);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetReferrerInfoWithoutClone(
|
|
nsIReferrerInfo* aReferrerInfo) {
|
|
return mInnerChannel->SetReferrerInfoWithoutClone(aReferrerInfo);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetRequestHeader(const nsACString& aHeader,
|
|
nsACString& _retval) {
|
|
_retval.Truncate();
|
|
auto value = mHeaders.Lookup(aHeader);
|
|
if (!value) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
_retval.Assign(*value);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetRequestHeader(const nsACString& aHeader,
|
|
const nsACString& aValue, bool aMerge) {
|
|
mHeaders.WithEntryHandle(aHeader, [&aValue, aMerge](auto&& entry) {
|
|
if (!entry) {
|
|
entry.Insert(aValue);
|
|
return;
|
|
}
|
|
if (!aMerge) {
|
|
entry.Update(aValue);
|
|
return;
|
|
}
|
|
nsAutoCString newValue(*entry);
|
|
newValue.AppendLiteral(", ");
|
|
newValue.Append(aValue);
|
|
entry.Update(newValue);
|
|
});
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetNewReferrerInfo(
|
|
const nsACString& aUrl, nsIReferrerInfo::ReferrerPolicyIDL aPolicy,
|
|
bool aSendReferrer) {
|
|
return mInnerChannel->SetNewReferrerInfo(aUrl, aPolicy, aSendReferrer);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetEmptyRequestHeader(const nsACString& aHeader) {
|
|
return SetRequestHeader(aHeader, EmptyCString(), false);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::VisitRequestHeaders(nsIHttpHeaderVisitor* aVisitor) {
|
|
for (auto iter = mHeaders.ConstIter(); !iter.Done(); iter.Next()) {
|
|
nsresult rv = aVisitor->VisitHeader(iter.Key(), iter.Data());
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::VisitNonDefaultRequestHeaders(
|
|
nsIHttpHeaderVisitor* aVisitor) {
|
|
return mInnerChannel->VisitNonDefaultRequestHeaders(aVisitor);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetAllowSTS(bool* aAllowSTS) {
|
|
return mInnerChannel->GetAllowSTS(aAllowSTS);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetAllowSTS(bool aAllowSTS) {
|
|
return mInnerChannel->SetAllowSTS(aAllowSTS);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetRedirectionLimit(uint32_t* aRedirectionLimit) {
|
|
return mInnerChannel->GetRedirectionLimit(aRedirectionLimit);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetRedirectionLimit(uint32_t aRedirectionLimit) {
|
|
return mInnerChannel->SetRedirectionLimit(aRedirectionLimit);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetResponseStatus(uint32_t* aResponseStatus) {
|
|
if (!mBinaryHttpResponse) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
uint16_t responseStatus;
|
|
nsresult rv = mBinaryHttpResponse->GetStatus(&responseStatus);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
*aResponseStatus = responseStatus;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetResponseStatusText(nsACString& aResponseStatusText) {
|
|
LOG(("ObliviousHttpChannel::GetResponseStatusText NOT IMPLEMENTED [this=%p]",
|
|
this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetRequestSucceeded(bool* aRequestSucceeded) {
|
|
uint32_t responseStatus;
|
|
nsresult rv = GetResponseStatus(&responseStatus);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
*aRequestSucceeded = (responseStatus / 100) == 2;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetIsMainDocumentChannel(bool* aValue) {
|
|
return mInnerChannel->GetIsMainDocumentChannel(aValue);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetIsMainDocumentChannel(bool aValue) {
|
|
return mInnerChannel->SetIsMainDocumentChannel(aValue);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetResponseHeader(const nsACString& header,
|
|
nsACString& _retval) {
|
|
if (!mBinaryHttpResponse) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
nsTArray<nsCString> responseHeaderNames;
|
|
nsTArray<nsCString> responseHeaderValues;
|
|
nsresult rv = mBinaryHttpResponse->GetHeaderNames(responseHeaderNames);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
rv = mBinaryHttpResponse->GetHeaderValues(responseHeaderValues);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
for (size_t i = 0;
|
|
i < responseHeaderNames.Length() && i < responseHeaderValues.Length();
|
|
i++) {
|
|
if (responseHeaderNames[i].EqualsIgnoreCase(header)) {
|
|
_retval.Assign(responseHeaderValues[i]);
|
|
return NS_OK;
|
|
}
|
|
}
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetResponseHeader(const nsACString& header,
|
|
const nsACString& value, bool merge) {
|
|
LOG(("ObliviousHttpChannel::SetResponseHeader NOT IMPLEMENTED [this=%p]",
|
|
this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::VisitResponseHeaders(nsIHttpHeaderVisitor* aVisitor) {
|
|
if (!mBinaryHttpResponse) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
nsTArray<nsCString> responseHeaderNames;
|
|
nsTArray<nsCString> responseHeaderValues;
|
|
nsresult rv = mBinaryHttpResponse->GetHeaderNames(responseHeaderNames);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
rv = mBinaryHttpResponse->GetHeaderValues(responseHeaderValues);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
for (size_t i = 0;
|
|
i < responseHeaderNames.Length() && i < responseHeaderValues.Length();
|
|
i++) {
|
|
rv = aVisitor->VisitHeader(responseHeaderNames[i], responseHeaderValues[i]);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetOriginalResponseHeader(
|
|
const nsACString& header, nsIHttpHeaderVisitor* aVisitor) {
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::VisitOriginalResponseHeaders(
|
|
nsIHttpHeaderVisitor* aVisitor) {
|
|
LOG(
|
|
("ObliviousHttpChannel::VisitOriginalResponseHeaders NOT IMPLEMENTED "
|
|
"[this=%p]",
|
|
this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::ShouldStripRequestBodyHeader(const nsACString& aMethod,
|
|
bool* aResult) {
|
|
LOG(
|
|
("ObliviousHttpChannel::ShouldStripRequestBodyHeader NOT IMPLEMENTED "
|
|
"[this=%p]",
|
|
this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::IsNoStoreResponse(bool* _retval) {
|
|
LOG(("ObliviousHttpChannel::IsNoStoreResponse NOT IMPLEMENTED [this=%p]",
|
|
this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::IsNoCacheResponse(bool* _retval) {
|
|
LOG(("ObliviousHttpChannel::IsNoCacheResponse NOT IMPLEMENTED [this=%p]",
|
|
this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::IsPrivateResponse(bool* _retval) {
|
|
LOG(("ObliviousHttpChannel::IsPrivateResponse NOT IMPLEMENTED [this=%p]",
|
|
this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::RedirectTo(nsIURI* aNewURI) {
|
|
LOG(("ObliviousHttpChannel::RedirectTo NOT IMPLEMENTED [this=%p]", this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::UpgradeToSecure() {
|
|
LOG(("ObliviousHttpChannel::UpgradeToSecure NOT IMPLEMENTED [this=%p]",
|
|
this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetRequestObserversCalled(bool* aCalled) {
|
|
return mInnerChannel->GetRequestObserversCalled(aCalled);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetRequestObserversCalled(bool aCalled) {
|
|
return mInnerChannel->SetRequestObserversCalled(aCalled);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetRequestContextID(uint64_t* _retval) {
|
|
return mInnerChannel->GetRequestContextID(_retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetRequestContextID(uint64_t rcID) {
|
|
return mInnerChannel->SetRequestContextID(rcID);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetProtocolVersion(nsACString& aProtocolVersion) {
|
|
return mInnerChannel->GetProtocolVersion(aProtocolVersion);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) {
|
|
LOG(("ObliviousHttpChannel::GetEncodedBodySize NOT IMPLEMENTED [this=%p]",
|
|
this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::LogBlockedCORSRequest(const nsAString& aMessage,
|
|
const nsACString& aCategory,
|
|
bool aIsWarning) {
|
|
return mInnerChannel->LogBlockedCORSRequest(aMessage, aCategory, aIsWarning);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::LogMimeTypeMismatch(const nsACString& aMessageName,
|
|
bool aWarning, const nsAString& aURL,
|
|
const nsAString& aContentType) {
|
|
return mInnerChannel->LogMimeTypeMismatch(aMessageName, aWarning, aURL,
|
|
aContentType);
|
|
}
|
|
|
|
void ObliviousHttpChannel::SetSource(
|
|
mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource) {
|
|
LOG(("ObliviousHttpChannel::SetSource NOT IMPLEMENTED [this=%p]", this));
|
|
// NS_ERROR_NOT_IMPLEMENTED
|
|
}
|
|
|
|
void ObliviousHttpChannel::SetConnectionInfo(nsHttpConnectionInfo* aCi) {
|
|
if (mInnerChannelInternal) {
|
|
mInnerChannelInternal->SetConnectionInfo(aCi);
|
|
}
|
|
}
|
|
|
|
void ObliviousHttpChannel::DoDiagnosticAssertWhenOnStopNotCalledOnDestroy() {
|
|
if (mInnerChannelInternal) {
|
|
mInnerChannelInternal->DoDiagnosticAssertWhenOnStopNotCalledOnDestroy();
|
|
}
|
|
}
|
|
|
|
void ObliviousHttpChannel::DisableAltDataCache() {
|
|
if (mInnerChannelInternal) {
|
|
mInnerChannelInternal->DisableAltDataCache();
|
|
}
|
|
}
|
|
|
|
void ObliviousHttpChannel::SetAltDataForChild(bool aIsForChild) {
|
|
if (mInnerChannelInternal) {
|
|
mInnerChannelInternal->SetAltDataForChild(aIsForChild);
|
|
}
|
|
}
|
|
|
|
void ObliviousHttpChannel::SetCorsPreflightParameters(
|
|
nsTArray<nsTString<char>> const& aUnsafeHeaders,
|
|
bool aShouldStripRequestBodyHeader, bool aShouldStripAuthHeader) {
|
|
if (mInnerChannelInternal) {
|
|
mInnerChannelInternal->SetCorsPreflightParameters(
|
|
aUnsafeHeaders, aShouldStripRequestBodyHeader, aShouldStripAuthHeader);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ObliviousHttpChannel::nsIChannel
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetOriginalURI(nsIURI** aOriginalURI) {
|
|
return mInnerChannel->GetOriginalURI(aOriginalURI);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetOriginalURI(nsIURI* aOriginalURI) {
|
|
return mInnerChannel->SetOriginalURI(aOriginalURI);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetURI(nsIURI** aURI) {
|
|
*aURI = do_AddRef(mTargetURI).take();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetOwner(nsISupports** aOwner) {
|
|
return mInnerChannel->GetOwner(aOwner);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetOwner(nsISupports* aOwner) {
|
|
return mInnerChannel->SetOwner(aOwner);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetNotificationCallbacks(
|
|
nsIInterfaceRequestor** aNotificationCallbacks) {
|
|
return mInnerChannel->GetNotificationCallbacks(aNotificationCallbacks);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetNotificationCallbacks(
|
|
nsIInterfaceRequestor* aNotificationCallbacks) {
|
|
return mInnerChannel->SetNotificationCallbacks(aNotificationCallbacks);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetSecurityInfo(
|
|
nsITransportSecurityInfo** aSecurityInfo) {
|
|
return mInnerChannel->GetSecurityInfo(aSecurityInfo);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetContentType(nsACString& aContentType) {
|
|
return GetResponseHeader("content-type"_ns, aContentType);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetContentType(const nsACString& aContentType) {
|
|
mContentType = aContentType;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetContentCharset(nsACString& aContentCharset) {
|
|
return mInnerChannel->GetContentCharset(aContentCharset);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetContentCharset(const nsACString& aContentCharset) {
|
|
return mInnerChannel->SetContentCharset(aContentCharset);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetContentLength(int64_t* aContentLength) {
|
|
return mInnerChannel->GetContentLength(aContentLength);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetContentLength(int64_t aContentLength) {
|
|
return mInnerChannel->SetContentLength(aContentLength);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::Open(nsIInputStream** aStream) {
|
|
LOG(("ObliviousHttpChannel::Open NOT IMPLEMENTED [this=%p]", this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::AsyncOpen(nsIStreamListener* aListener) {
|
|
LOG(("ObliviousHttpChannel::AsyncOpen [this=%p, listener=%p]", this,
|
|
aListener));
|
|
mStreamListener = aListener;
|
|
nsresult rv = mInnerChannel->SetRequestMethod("POST"_ns);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
rv = mInnerChannel->SetRequestHeader("Content-Type"_ns,
|
|
"message/ohttp-req"_ns, false);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
nsAutoCString scheme;
|
|
if (!mTargetURI) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
rv = mTargetURI->GetScheme(scheme);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
nsAutoCString authority;
|
|
rv = mTargetURI->GetHostPort(authority);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
nsAutoCString path;
|
|
rv = mTargetURI->GetPathQueryRef(path);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
nsTArray<nsCString> headerNames;
|
|
nsTArray<nsCString> headerValues;
|
|
for (auto iter = mHeaders.ConstIter(); !iter.Done(); iter.Next()) {
|
|
headerNames.AppendElement(iter.Key());
|
|
headerValues.AppendElement(iter.Data());
|
|
}
|
|
if (!mContentType.IsEmpty() && !headerNames.Contains("Content-Type")) {
|
|
headerNames.AppendElement("Content-Type"_ns);
|
|
headerValues.AppendElement(mContentType);
|
|
}
|
|
nsCOMPtr<nsIBinaryHttp> bhttp(
|
|
do_GetService("@mozilla.org/network/binary-http;1"));
|
|
nsCOMPtr<nsIBinaryHttpRequest> bhttpRequest(new BinaryHttpRequest(
|
|
mMethod, scheme, authority, path, std::move(headerNames),
|
|
std::move(headerValues), std::move(mContent)));
|
|
nsTArray<uint8_t> encodedRequest;
|
|
rv = bhttp->EncodeRequest(bhttpRequest, encodedRequest);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
nsCOMPtr<nsIObliviousHttp> obliviousHttp(
|
|
do_GetService("@mozilla.org/network/oblivious-http;1"));
|
|
if (!obliviousHttp) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
rv = obliviousHttp->EncapsulateRequest(mEncodedConfig, encodedRequest,
|
|
getter_AddRefs(mEncapsulatedRequest));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
nsTArray<uint8_t> encRequest;
|
|
rv = mEncapsulatedRequest->GetEncRequest(encRequest);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
nsCOMPtr<nsIUploadChannel2> uploadChannel(do_QueryInterface(mInnerChannel));
|
|
if (!uploadChannel) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
nsCOMPtr<nsIInputStream> uploadStream;
|
|
uint32_t streamLength = encRequest.Length();
|
|
rv = NS_NewByteInputStream(getter_AddRefs(uploadStream),
|
|
std::move(encRequest));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
rv = uploadChannel->ExplicitSetUploadStream(
|
|
uploadStream, "message/ohttp-req"_ns, streamLength, "POST"_ns, false);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
return mInnerChannel->AsyncOpen(this);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetCanceled(bool* aCanceled) {
|
|
return mInnerChannel->GetCanceled(aCanceled);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetContentDisposition(uint32_t* aContentDisposition) {
|
|
return mInnerChannel->GetContentDisposition(aContentDisposition);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetContentDisposition(uint32_t aContentDisposition) {
|
|
return mInnerChannel->SetContentDisposition(aContentDisposition);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetContentDispositionFilename(
|
|
nsAString& aContentDispositionFilename) {
|
|
return mInnerChannel->GetContentDispositionFilename(
|
|
aContentDispositionFilename);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetContentDispositionFilename(
|
|
const nsAString& aContentDispositionFilename) {
|
|
return mInnerChannel->SetContentDispositionFilename(
|
|
aContentDispositionFilename);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetContentDispositionHeader(
|
|
nsACString& aContentDispositionHeader) {
|
|
return mInnerChannel->GetContentDispositionHeader(aContentDispositionHeader);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) {
|
|
return mInnerChannel->GetLoadInfo(aLoadInfo);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) {
|
|
return mInnerChannel->SetLoadInfo(aLoadInfo);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetIsDocument(bool* aIsDocument) {
|
|
return mInnerChannel->GetIsDocument(aIsDocument);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ObliviousHttpChannel::nsIStreamListener
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::OnDataAvailable(nsIRequest* aRequest,
|
|
nsIInputStream* aStream, uint64_t aOffset,
|
|
uint32_t aCount) {
|
|
LOG(
|
|
("ObliviousHttpChannel::OnDataAvailable [this=%p, request=%p, stream=%p, "
|
|
"offset=%" PRIu64 ", count=%u]",
|
|
this, aRequest, aStream, aOffset, aCount));
|
|
MOZ_ASSERT(aOffset == mRawResponse.Length());
|
|
size_t oldLength = mRawResponse.Length();
|
|
size_t newLength = oldLength + aCount;
|
|
if (newLength < oldLength) { // i.e., overflow
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mRawResponse.SetCapacity(newLength);
|
|
mRawResponse.SetLengthAndRetainStorage(newLength);
|
|
void* dest = mRawResponse.Elements() + oldLength;
|
|
uint64_t written = 0;
|
|
nsresult rv = NS_ReadInputStreamToBuffer(aStream, &dest, aCount, &written);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
if (written != aCount) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ObliviousHttpChannel::nsIRequestObserver
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::OnStartRequest(nsIRequest* aRequest) {
|
|
LOG(("ObliviousHttpChannel::OnStartRequest [this=%p, request=%p]", this,
|
|
aRequest));
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult ObliviousHttpChannel::ProcessOnStopRequest() {
|
|
if (mRawResponse.IsEmpty()) {
|
|
return NS_OK;
|
|
}
|
|
nsCOMPtr<nsIObliviousHttp> obliviousHttp(
|
|
do_GetService("@mozilla.org/network/oblivious-http;1"));
|
|
if (!obliviousHttp) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
nsCOMPtr<nsIObliviousHttpClientResponse> response;
|
|
nsresult rv = mEncapsulatedRequest->GetResponse(getter_AddRefs(response));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
nsTArray<uint8_t> decapsulated;
|
|
rv = response->Decapsulate(mRawResponse, decapsulated);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
nsCOMPtr<nsIBinaryHttp> bhttp(
|
|
do_GetService("@mozilla.org/network/binary-http;1"));
|
|
if (!bhttp) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return bhttp->DecodeResponse(decapsulated,
|
|
getter_AddRefs(mBinaryHttpResponse));
|
|
}
|
|
|
|
void ObliviousHttpChannel::EmitOnDataAvailable() {
|
|
if (!mBinaryHttpResponse) {
|
|
return;
|
|
}
|
|
nsTArray<uint8_t> content;
|
|
nsresult rv = mBinaryHttpResponse->GetContent(content);
|
|
if (NS_FAILED(rv)) {
|
|
return;
|
|
}
|
|
if (content.IsEmpty()) {
|
|
return;
|
|
}
|
|
if (content.Length() > std::numeric_limits<uint32_t>::max()) {
|
|
return;
|
|
}
|
|
uint32_t contentLength = (uint32_t)content.Length();
|
|
nsCOMPtr<nsIInputStream> contentStream;
|
|
rv = NS_NewByteInputStream(getter_AddRefs(contentStream), std::move(content));
|
|
if (NS_FAILED(rv)) {
|
|
return;
|
|
}
|
|
rv = mStreamListener->OnDataAvailable(this, contentStream, 0, contentLength);
|
|
Unused << rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::OnStopRequest(nsIRequest* aRequest,
|
|
nsresult aStatusCode) {
|
|
LOG(("ObliviousHttpChannel::OnStopRequest [this=%p, request=%p, status=%u]",
|
|
this, aRequest, (uint32_t)aStatusCode));
|
|
|
|
auto releaseStreamListener = MakeScopeExit(
|
|
[self = RefPtr{this}]() mutable { self->mStreamListener = nullptr; });
|
|
|
|
if (NS_SUCCEEDED(aStatusCode)) {
|
|
bool requestSucceeded;
|
|
nsresult rv = mInnerChannel->GetRequestSucceeded(&requestSucceeded);
|
|
if (NS_SUCCEEDED(rv) && requestSucceeded) {
|
|
aStatusCode = ProcessOnStopRequest();
|
|
}
|
|
}
|
|
Unused << mStreamListener->OnStartRequest(this);
|
|
if (NS_SUCCEEDED(aStatusCode)) {
|
|
EmitOnDataAvailable();
|
|
}
|
|
Unused << mStreamListener->OnStopRequest(this, aStatusCode);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ObliviousHttpChannel::nsIObliviousHttpChannel
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
ObliviousHttpChannel::GetRelayChannel(nsIHttpChannel** aChannel) {
|
|
if (!aChannel) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
*aChannel = do_AddRef(mInnerChannel).take();
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ObliviousHttpChannel::nsIUploadChannel2
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP ObliviousHttpChannel::ExplicitSetUploadStream(
|
|
nsIInputStream* aStream, const nsACString& aContentType,
|
|
int64_t aContentLength, const nsACString& aMethod, bool aStreamHasHeaders) {
|
|
// This function should only be called before AsyncOpen.
|
|
if (mStreamListener) {
|
|
return NS_ERROR_IN_PROGRESS;
|
|
}
|
|
if (aMethod != "POST"_ns || aStreamHasHeaders) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
mMethod.Assign(aMethod);
|
|
uint64_t available;
|
|
if (aContentLength < 0) {
|
|
nsresult rv = aStream->Available(&available);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
} else {
|
|
available = aContentLength;
|
|
}
|
|
if (available > std::numeric_limits<int64_t>::max()) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mContent.SetCapacity(available);
|
|
mContent.SetLengthAndRetainStorage(available);
|
|
void* dest = mContent.Elements();
|
|
uint64_t written = 0;
|
|
nsresult rv =
|
|
NS_ReadInputStreamToBuffer(aStream, &dest, (int64_t)available, &written);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
if (written != available) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mContentType = aContentType;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP ObliviousHttpChannel::GetUploadStreamHasHeaders(
|
|
bool* aUploadStreamHasHeaders) {
|
|
*aUploadStreamHasHeaders = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP ObliviousHttpChannel::CloneUploadStream(
|
|
int64_t* aContentLength, nsIInputStream** _retval) {
|
|
LOG(("ObliviousHttpChannel::CloneUploadStream NOT IMPLEMENTED [this=%p]",
|
|
this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP ObliviousHttpChannel::SetClassicScriptHintCharset(
|
|
const nsAString& aClassicScriptHintCharset) {
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP ObliviousHttpChannel::GetClassicScriptHintCharset(
|
|
nsAString& aClassicScriptHintCharset) {
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP ObliviousHttpChannel::SetDocumentCharacterSet(
|
|
const nsAString& aDocumentCharacterSet) {
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP ObliviousHttpChannel::GetDocumentCharacterSet(
|
|
nsAString& aDocumenharacterSet) {
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
} // namespace mozilla::net
|