Bug 1753703 - P2: Move HttpActivityDistributor to nsHttpHandler, r=necko-reviewers,dragana

Since both DnsAndConnectSocket and nsHttpTransaction use HttpActivityDistributor, let's refactor this a bit by moving some duplicate code to nsHttpHandler.
This patch also makes it possible to test ECH activity for Http3 case.

Differential Revision: https://phabricator.services.mozilla.com/D138893
This commit is contained in:
Kershaw Chang 2022-02-18 09:30:18 +00:00
Родитель c97e0907d3
Коммит 45a4bb9143
11 изменённых файлов: 178 добавлений и 168 удалений

Просмотреть файл

@ -50,21 +50,13 @@ NS_INTERFACE_MAP_BEGIN(DnsAndConnectSocket)
NS_INTERFACE_MAP_ENTRY_CONCRETE(DnsAndConnectSocket) NS_INTERFACE_MAP_ENTRY_CONCRETE(DnsAndConnectSocket)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
static void NotifyActivity(nsIHttpActivityObserver* aActivityDistributor, static void NotifyActivity(nsHttpConnectionInfo* aConnInfo, uint32_t aSubtype) {
nsHttpConnectionInfo* aConnInfo, uint32_t aSubtype) {
nsCOMPtr<nsIHttpActivityObserver> activityDistributor(aActivityDistributor);
HttpConnectionActivity activity( HttpConnectionActivity activity(
aConnInfo->HashKey(), aConnInfo->GetOrigin(), aConnInfo->OriginPort(), aConnInfo->HashKey(), aConnInfo->GetOrigin(), aConnInfo->OriginPort(),
aConnInfo->EndToEndSSL(), !aConnInfo->GetEchConfig().IsEmpty(), aConnInfo->EndToEndSSL(), !aConnInfo->GetEchConfig().IsEmpty(),
aConnInfo->IsHttp3()); aConnInfo->IsHttp3());
NS_DispatchToMainThread(NS_NewRunnableFunction( gHttpHandler->ObserveHttpActivityWithArgs(
"ObserveActivityWithArgs", activity, NS_ACTIVITY_TYPE_HTTP_CONNECTION, aSubtype, PR_Now(), 0, ""_ns);
[activityDistributor, activity = std::move(activity),
subType(aSubtype)]() {
Unused << activityDistributor->ObserveActivityWithArgs(
HttpActivityArgs(activity), NS_ACTIVITY_TYPE_HTTP_CONNECTION,
subType, PR_Now(), 0, ""_ns);
}));
} }
DnsAndConnectSocket::DnsAndConnectSocket(nsHttpConnectionInfo* ci, DnsAndConnectSocket::DnsAndConnectSocket(nsHttpConnectionInfo* ci,
@ -95,27 +87,10 @@ DnsAndConnectSocket::DnsAndConnectSocket(nsHttpConnectionInfo* ci,
} }
MOZ_ASSERT(mConnInfo); MOZ_ASSERT(mConnInfo);
NotifyActivity(mConnInfo,
mActivityDistributor = components::HttpActivityDistributor::Service(); mSpeculative
if (mActivityDistributor) { ? NS_HTTP_ACTIVITY_SUBTYPE_SPECULATIVE_DNSANDSOCKET_CREATED
bool activityDistributorActive = false; : NS_HTTP_ACTIVITY_SUBTYPE_DNSANDSOCKET_CREATED);
Unused << mActivityDistributor->GetIsActive(&activityDistributorActive);
bool observeConnection = false;
nsCOMPtr<nsIHttpActivityDistributor> distributor =
do_QueryInterface(mActivityDistributor);
if (distributor) {
Unused << distributor->GetObserveConnection(&observeConnection);
}
if (!activityDistributorActive || !observeConnection) {
mActivityDistributor = nullptr;
} else {
NotifyActivity(
mActivityDistributor, mConnInfo,
mSpeculative
? NS_HTTP_ACTIVITY_SUBTYPE_SPECULATIVE_DNSANDSOCKET_CREATED
: NS_HTTP_ACTIVITY_SUBTYPE_DNSANDSOCKET_CREATED);
}
}
} }
void DnsAndConnectSocket::CheckIsDone() { void DnsAndConnectSocket::CheckIsDone() {
@ -584,10 +559,10 @@ nsresult DnsAndConnectSocket::SetupConn(bool isPrimary, nsresult status) {
nsresult rv = NS_OK; nsresult rv = NS_OK;
if (isPrimary) { if (isPrimary) {
rv = mPrimaryTransport.SetupConn(mTransaction, ent, status, mCaps, this, rv = mPrimaryTransport.SetupConn(mTransaction, ent, status, mCaps,
getter_AddRefs(conn)); getter_AddRefs(conn));
} else { } else {
rv = mBackupTransport.SetupConn(mTransaction, ent, status, mCaps, this, rv = mBackupTransport.SetupConn(mTransaction, ent, status, mCaps,
getter_AddRefs(conn)); getter_AddRefs(conn));
} }
@ -1021,8 +996,7 @@ nsresult DnsAndConnectSocket::TransportSetup::CheckConnectedResult(
nsresult DnsAndConnectSocket::TransportSetup::SetupConn( nsresult DnsAndConnectSocket::TransportSetup::SetupConn(
nsAHttpTransaction* transaction, ConnectionEntry* ent, nsresult status, nsAHttpTransaction* transaction, ConnectionEntry* ent, nsresult status,
uint32_t cap, DnsAndConnectSocket* dnsAndSock, uint32_t cap, HttpConnectionBase** connection) {
HttpConnectionBase** connection) {
RefPtr<HttpConnectionBase> conn; RefPtr<HttpConnectionBase> conn;
if (!ent->mConnInfo->IsHttp3()) { if (!ent->mConnInfo->IsHttp3()) {
conn = new nsHttpConnection(); conn = new nsHttpConnection();
@ -1030,10 +1004,7 @@ nsresult DnsAndConnectSocket::TransportSetup::SetupConn(
conn = new HttpConnectionUDP(); conn = new HttpConnectionUDP();
} }
if (dnsAndSock->mActivityDistributor) { NotifyActivity(ent->mConnInfo, NS_HTTP_ACTIVITY_SUBTYPE_CONNECTION_CREATED);
NotifyActivity(dnsAndSock->mActivityDistributor, ent->mConnInfo,
NS_HTTP_ACTIVITY_SUBTYPE_CONNECTION_CREATED);
}
LOG( LOG(
("DnsAndConnectSocket::SocketTransport::SetupConn " ("DnsAndConnectSocket::SocketTransport::SetupConn "
@ -1249,10 +1220,8 @@ nsresult DnsAndConnectSocket::TransportSetup::SetupStreams(
LOG(("Setting ECH")); LOG(("Setting ECH"));
rv = socketTransport->SetEchConfig(ci->GetEchConfig()); rv = socketTransport->SetEchConfig(ci->GetEchConfig());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (dnsAndSock->mActivityDistributor) {
NotifyActivity(dnsAndSock->mActivityDistributor, dnsAndSock->mConnInfo, NotifyActivity(dnsAndSock->mConnInfo, NS_HTTP_ACTIVITY_SUBTYPE_ECH_SET);
NS_HTTP_ACTIVITY_SUBTYPE_ECH_SET);
}
} }
RefPtr<ConnectionEntry> ent = RefPtr<ConnectionEntry> ent =

Просмотреть файл

@ -19,8 +19,6 @@
#include "nsITransport.h" #include "nsITransport.h"
#include "nsWeakReference.h" #include "nsWeakReference.h"
class nsIHttpActivityObserver;
namespace mozilla { namespace mozilla {
namespace net { namespace net {
@ -177,7 +175,6 @@ class DnsAndConnectSocket final : public nsIOutputStreamCallback,
void CloseAll(); void CloseAll();
nsresult SetupConn(nsAHttpTransaction* transaction, ConnectionEntry* ent, nsresult SetupConn(nsAHttpTransaction* transaction, ConnectionEntry* ent,
nsresult status, uint32_t cap, nsresult status, uint32_t cap,
DnsAndConnectSocket* dnsAndSock,
HttpConnectionBase** connection); HttpConnectionBase** connection);
[[nodiscard]] nsresult SetupStreams(DnsAndConnectSocket* dnsAndSock); [[nodiscard]] nsresult SetupStreams(DnsAndConnectSocket* dnsAndSock);
nsresult ResolveHost(DnsAndConnectSocket* dnsAndSock); nsresult ResolveHost(DnsAndConnectSocket* dnsAndSock);
@ -266,7 +263,6 @@ class DnsAndConnectSocket final : public nsIOutputStreamCallback,
bool mSkipDnsResolution = false; bool mSkipDnsResolution = false;
bool mProxyNotTransparent = false; bool mProxyNotTransparent = false;
bool mProxyTransparentResolvesHost = false; bool mProxyTransparentResolvesHost = false;
nsCOMPtr<nsIHttpActivityObserver> mActivityDistributor;
}; };
NS_DEFINE_STATIC_IID_ACCESSOR(DnsAndConnectSocket, NS_DNSANDCONNECTSOCKET_IID) NS_DEFINE_STATIC_IID_ACCESSOR(DnsAndConnectSocket, NS_DNSANDCONNECTSOCKET_IID)

Просмотреть файл

@ -12,6 +12,7 @@
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "ASpdySession.h" // because of SoftStreamError() #include "ASpdySession.h" // because of SoftStreamError()
#include "nsIHttpActivityObserver.h"
#include "nsIOService.h" #include "nsIOService.h"
#include "nsISSLSocketControl.h" #include "nsISSLSocketControl.h"
#include "ScopedNSSTypes.h" #include "ScopedNSSTypes.h"
@ -160,6 +161,13 @@ nsresult Http3Session::Init(const nsHttpConnectionInfo* aConnInfo,
if (gHttpHandler->EchConfigEnabled(true)) { if (gHttpHandler->EchConfigEnabled(true)) {
mSocketControl->SetEchConfig(mConnInfo->GetEchConfig()); mSocketControl->SetEchConfig(mConnInfo->GetEchConfig());
HttpConnectionActivity activity(
mConnInfo->HashKey(), mConnInfo->GetOrigin(), mConnInfo->OriginPort(),
mConnInfo->EndToEndSSL(), !mConnInfo->GetEchConfig().IsEmpty(),
mConnInfo->IsHttp3());
gHttpHandler->ObserveHttpActivityWithArgs(
activity, NS_ACTIVITY_TYPE_HTTP_CONNECTION,
NS_HTTP_ACTIVITY_SUBTYPE_ECH_SET, PR_Now(), 0, ""_ns);
} }
// After this line, Http3Session and HttpConnectionUDP become a cycle. We put // After this line, Http3Session and HttpConnectionUDP become a cycle. We put

Просмотреть файл

@ -139,16 +139,26 @@ nsHttpActivityDistributor::ObserveActivityWithArgs(
return NS_OK; return NS_OK;
} }
bool nsHttpActivityDistributor::Activated() { return mActivated; }
bool nsHttpActivityDistributor::ObserveProxyResponseEnabled() {
return mObserveProxyResponse;
}
bool nsHttpActivityDistributor::ObserveConnectionEnabled() {
return mObserveConnection;
}
NS_IMETHODIMP NS_IMETHODIMP
nsHttpActivityDistributor::GetIsActive(bool* isActive) { nsHttpActivityDistributor::GetIsActive(bool* isActive) {
NS_ENSURE_ARG_POINTER(isActive); NS_ENSURE_ARG_POINTER(isActive);
MutexAutoLock lock(mLock);
if (XRE_IsSocketProcess()) { if (XRE_IsSocketProcess()) {
*isActive = mActivated; *isActive = mActivated;
return NS_OK; return NS_OK;
} }
*isActive = !!mObservers.Length(); MutexAutoLock lock(mLock);
*isActive = mActivated = !!mObservers.Length();
return NS_OK; return NS_OK;
} }
@ -162,6 +172,10 @@ NS_IMETHODIMP nsHttpActivityDistributor::SetIsActive(bool aActived) {
NS_IMETHODIMP NS_IMETHODIMP
nsHttpActivityDistributor::AddObserver(nsIHttpActivityObserver* aObserver) { nsHttpActivityDistributor::AddObserver(nsIHttpActivityObserver* aObserver) {
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
if (!NS_IsMainThread()) {
// We only support calling this from the main thread.
return NS_ERROR_FAILURE;
}
ObserverHandle observer( ObserverHandle observer(
new ObserverHolder("nsIHttpActivityObserver", aObserver)); new ObserverHolder("nsIHttpActivityObserver", aObserver));
@ -175,14 +189,17 @@ nsHttpActivityDistributor::AddObserver(nsIHttpActivityObserver* aObserver) {
mObservers.AppendElement(observer); mObservers.AppendElement(observer);
} }
if (nsIOService::UseSocketProcess() && wasEmpty) { if (wasEmpty) {
auto task = []() { mActivated = true;
SocketProcessParent* parent = SocketProcessParent::GetSingleton(); if (nsIOService::UseSocketProcess()) {
if (parent && parent->CanSend()) { auto task = []() {
Unused << parent->SendOnHttpActivityDistributorActivated(true); SocketProcessParent* parent = SocketProcessParent::GetSingleton();
} if (parent && parent->CanSend()) {
}; Unused << parent->SendOnHttpActivityDistributorActivated(true);
gIOService->CallOrWaitForSocketProcess(task); }
};
gIOService->CallOrWaitForSocketProcess(task);
}
} }
return NS_OK; return NS_OK;
} }
@ -190,18 +207,23 @@ nsHttpActivityDistributor::AddObserver(nsIHttpActivityObserver* aObserver) {
NS_IMETHODIMP NS_IMETHODIMP
nsHttpActivityDistributor::RemoveObserver(nsIHttpActivityObserver* aObserver) { nsHttpActivityDistributor::RemoveObserver(nsIHttpActivityObserver* aObserver) {
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
if (!NS_IsMainThread()) {
// We only support calling this from the main thread.
return NS_ERROR_FAILURE;
}
ObserverHandle observer( ObserverHandle observer(
new ObserverHolder("nsIHttpActivityObserver", aObserver)); new ObserverHolder("nsIHttpActivityObserver", aObserver));
bool isEmpty = false;
{ {
MutexAutoLock lock(mLock); MutexAutoLock lock(mLock);
if (!mObservers.RemoveElement(observer)) return NS_ERROR_FAILURE; if (!mObservers.RemoveElement(observer)) {
isEmpty = mObservers.IsEmpty(); return NS_ERROR_FAILURE;
}
mActivated = mObservers.IsEmpty();
} }
if (nsIOService::UseSocketProcess() && isEmpty) { if (nsIOService::UseSocketProcess() && !mActivated) {
auto task = []() { auto task = []() {
SocketProcessParent* parent = SocketProcessParent::GetSingleton(); SocketProcessParent* parent = SocketProcessParent::GetSingleton();
if (parent && parent->CanSend()) { if (parent && parent->CanSend()) {
@ -217,15 +239,18 @@ NS_IMETHODIMP
nsHttpActivityDistributor::GetObserveProxyResponse( nsHttpActivityDistributor::GetObserveProxyResponse(
bool* aObserveProxyResponse) { bool* aObserveProxyResponse) {
NS_ENSURE_ARG_POINTER(aObserveProxyResponse); NS_ENSURE_ARG_POINTER(aObserveProxyResponse);
bool result = mObserveProxyResponse;
MutexAutoLock lock(mLock); *aObserveProxyResponse = result;
*aObserveProxyResponse = mObserveProxyResponse;
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHttpActivityDistributor::SetObserveProxyResponse(bool aObserveProxyResponse) { nsHttpActivityDistributor::SetObserveProxyResponse(bool aObserveProxyResponse) {
MutexAutoLock lock(mLock); if (!NS_IsMainThread()) {
// We only support calling this from the main thread.
return NS_ERROR_FAILURE;
}
mObserveProxyResponse = aObserveProxyResponse; mObserveProxyResponse = aObserveProxyResponse;
if (nsIOService::UseSocketProcess()) { if (nsIOService::UseSocketProcess()) {
auto task = [aObserveProxyResponse]() { auto task = [aObserveProxyResponse]() {
@ -244,14 +269,17 @@ NS_IMETHODIMP
nsHttpActivityDistributor::GetObserveConnection(bool* aObserveConnection) { nsHttpActivityDistributor::GetObserveConnection(bool* aObserveConnection) {
NS_ENSURE_ARG_POINTER(aObserveConnection); NS_ENSURE_ARG_POINTER(aObserveConnection);
MutexAutoLock lock(mLock);
*aObserveConnection = mObserveConnection; *aObserveConnection = mObserveConnection;
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHttpActivityDistributor::SetObserveConnection(bool aObserveConnection) { nsHttpActivityDistributor::SetObserveConnection(bool aObserveConnection) {
MutexAutoLock lock(mLock); if (!NS_IsMainThread()) {
// We only support calling this from the main thread.
return NS_ERROR_FAILURE;
}
mObserveConnection = aObserveConnection; mObserveConnection = aObserveConnection;
if (nsIOService::UseSocketProcess()) { if (nsIOService::UseSocketProcess()) {
auto task = [aObserveConnection]() { auto task = [aObserveConnection]() {

Просмотреть файл

@ -8,6 +8,7 @@
#include "nsIHttpActivityObserver.h" #include "nsIHttpActivityObserver.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsProxyRelease.h" #include "nsProxyRelease.h"
#include "mozilla/Atomics.h"
#include "mozilla/Mutex.h" #include "mozilla/Mutex.h"
namespace mozilla { namespace mozilla {
@ -28,9 +29,9 @@ class nsHttpActivityDistributor : public nsIHttpActivityDistributor {
ObserverArray mObservers; ObserverArray mObservers;
Mutex mLock{"nsHttpActivityDistributor.mLock"}; Mutex mLock{"nsHttpActivityDistributor.mLock"};
bool mActivated{false}; Atomic<bool, Relaxed> mActivated{false};
bool mObserveProxyResponse{false}; Atomic<bool, Relaxed> mObserveProxyResponse{false};
bool mObserveConnection{false}; Atomic<bool, Relaxed> mObserveConnection{false};
}; };
} // namespace net } // namespace net

Просмотреть файл

@ -27,6 +27,7 @@
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsNetCID.h" #include "nsNetCID.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
#include "mozilla/Components.h"
#include "mozilla/Printf.h" #include "mozilla/Printf.h"
#include "mozilla/Sprintf.h" #include "mozilla/Sprintf.h"
#include "mozilla/StaticPrefs_general.h" #include "mozilla/StaticPrefs_general.h"
@ -47,6 +48,7 @@
#include "nsCRT.h" #include "nsCRT.h"
#include "nsIParentalControlsService.h" #include "nsIParentalControlsService.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "nsIHttpActivityObserver.h"
#include "nsHttpChannelAuthProvider.h" #include "nsHttpChannelAuthProvider.h"
#include "nsINetworkLinkService.h" #include "nsINetworkLinkService.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
@ -393,6 +395,7 @@ nsresult nsHttpHandler::Init() {
usageOfHTTPSRRPrefs[2] = StaticPrefs::network_dns_echconfig_enabled(); usageOfHTTPSRRPrefs[2] = StaticPrefs::network_dns_echconfig_enabled();
Telemetry::ScalarSet(Telemetry::ScalarID::NETWORKING_HTTPS_RR_PREFS_USAGE, Telemetry::ScalarSet(Telemetry::ScalarID::NETWORKING_HTTPS_RR_PREFS_USAGE,
static_cast<uint32_t>(usageOfHTTPSRRPrefs.to_ulong())); static_cast<uint32_t>(usageOfHTTPSRRPrefs.to_ulong()));
mActivityDistributor = components::HttpActivityDistributor::Service();
} }
auto initQLogDir = [&]() { auto initQLogDir = [&]() {
@ -2222,6 +2225,8 @@ nsHttpHandler::Observe(nsISupports* subject, const char* topic,
Telemetry::Accumulate(Telemetry::DNT_USAGE, 1); Telemetry::Accumulate(Telemetry::DNT_USAGE, 1);
} }
} }
mActivityDistributor = nullptr;
} else if (!strcmp(topic, "profile-change-net-restore")) { } else if (!strcmp(topic, "profile-change-net-restore")) {
// initialize connection manager // initialize connection manager
rv = InitConnectionMgr(); rv = InitConnectionMgr();
@ -2994,4 +2999,35 @@ bool nsHttpHandler::Is0RttTcpExcluded(const nsHttpConnectionInfo* ci) {
return mExcluded0RttTcpOrigins.Contains(ci->GetOrigin()); return mExcluded0RttTcpOrigins.Contains(ci->GetOrigin());
} }
bool nsHttpHandler::HttpActivityDistributorActivated() {
if (!mActivityDistributor) {
return false;
}
return mActivityDistributor->Activated();
}
void nsHttpHandler::ObserveHttpActivityWithArgs(
const HttpActivityArgs& aArgs, uint32_t aActivityType,
uint32_t aActivitySubtype, PRTime aTimestamp, uint64_t aExtraSizeData,
const nsACString& aExtraStringData) {
if (!HttpActivityDistributorActivated()) {
return;
}
if (aActivitySubtype == NS_HTTP_ACTIVITY_SUBTYPE_PROXY_RESPONSE_HEADER &&
!mActivityDistributor->ObserveProxyResponseEnabled()) {
return;
}
if (aActivityType == NS_ACTIVITY_TYPE_HTTP_CONNECTION &&
!mActivityDistributor->ObserveConnectionEnabled()) {
return;
}
Unused << mActivityDistributor->ObserveActivityWithArgs(
aArgs, aActivityType, aActivitySubtype, aTimestamp, aExtraSizeData,
aExtraStringData);
}
} // namespace mozilla::net } // namespace mozilla::net

Просмотреть файл

@ -36,6 +36,7 @@
#include "nsIChannel.h" #include "nsIChannel.h"
#include "nsIHttpChannel.h" #include "nsIHttpChannel.h"
class nsIHttpActivityDistributor;
class nsIHttpUpgradeListener; class nsIHttpUpgradeListener;
class nsIPrefBranch; class nsIPrefBranch;
class nsICancelable; class nsICancelable;
@ -499,6 +500,13 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
// avoid first-use overhead // avoid first-use overhead
static void PresetAcceptLanguages(); static void PresetAcceptLanguages();
bool HttpActivityDistributorActivated();
void ObserveHttpActivityWithArgs(const HttpActivityArgs& aArgs,
uint32_t aActivityType,
uint32_t aActivitySubtype, PRTime aTimestamp,
uint64_t aExtraSizeData,
const nsACString& aExtraStringData);
private: private:
nsHttpHandler(); nsHttpHandler();
@ -849,6 +857,8 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
// The pref set artificial altSvc-s for origin for testing. // The pref set artificial altSvc-s for origin for testing.
// This maps an origin to an altSvc. // This maps an origin to an altSvc.
nsClassHashtable<nsCStringHashKey, nsCString> mAltSvcMappingTemptativeMap; nsClassHashtable<nsCStringHashKey, nsCString> mAltSvcMappingTemptativeMap;
nsCOMPtr<nsIHttpActivityDistributor> mActivityDistributor;
}; };
extern StaticRefPtr<nsHttpHandler> gHttpHandler; extern StaticRefPtr<nsHttpHandler> gHttpHandler;

Просмотреть файл

@ -226,27 +226,6 @@ nsresult nsHttpTransaction::Init(
mTrafficCategory = trafficCategory; mTrafficCategory = trafficCategory;
mActivityDistributor = components::HttpActivityDistributor::Service();
if (!mActivityDistributor) {
return NS_ERROR_NOT_AVAILABLE;
}
bool activityDistributorActive;
rv = mActivityDistributor->GetIsActive(&activityDistributorActive);
if (NS_SUCCEEDED(rv) && activityDistributorActive) {
// there are some observers registered at activity distributor, gather
// nsISupports for the channel that called Init()
LOG(
("nsHttpTransaction::Init() "
"mActivityDistributor is active "
"this=%p",
this));
} else {
// there is no observer, so don't use it
activityDistributorActive = false;
mActivityDistributor = nullptr;
}
LOG1(("nsHttpTransaction %p SetRequestContext %p\n", this, requestContext)); LOG1(("nsHttpTransaction %p SetRequestContext %p\n", this, requestContext));
mRequestContext = requestContext; mRequestContext = requestContext;
@ -284,18 +263,17 @@ nsresult nsHttpTransaction::Init(
} }
// report the request header // report the request header
if (mActivityDistributor) { if (gHttpHandler->HttpActivityDistributorActivated()) {
RefPtr<nsHttpTransaction> self = this;
nsCString requestBuf(mReqHeaderBuf); nsCString requestBuf(mReqHeaderBuf);
NS_DispatchToMainThread( NS_DispatchToMainThread(NS_NewRunnableFunction(
NS_NewRunnableFunction("ObserveActivityWithArgs", [self, requestBuf]() { "ObserveHttpActivityWithArgs", [channelId(mChannelId), requestBuf]() {
nsresult rv = self->mActivityDistributor->ObserveActivityWithArgs( if (!gHttpHandler) {
HttpActivityArgs(self->mChannelId), return;
}
gHttpHandler->ObserveHttpActivityWithArgs(
HttpActivityArgs(channelId),
NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION, NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER, PR_Now(), 0, requestBuf); NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER, PR_Now(), 0, requestBuf);
if (NS_FAILED(rv)) {
LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
}
})); }));
} }
@ -643,26 +621,19 @@ void nsHttpTransaction::OnTransportStatus(nsITransport* transport,
// Need to do this before the STATUS_RECEIVING_FROM check below, to make // Need to do this before the STATUS_RECEIVING_FROM check below, to make
// sure that the activity distributor gets told about all status events. // sure that the activity distributor gets told about all status events.
if (mActivityDistributor) {
// upon STATUS_WAITING_FOR; report request body sent
if ((mHasRequestBody) && (status == NS_NET_STATUS_WAITING_FOR)) {
nsresult rv = mActivityDistributor->ObserveActivityWithArgs(
HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_BODY_SENT, PR_Now(), 0, ""_ns);
if (NS_FAILED(rv)) {
LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
}
}
// report the status and progress // upon STATUS_WAITING_FOR; report request body sent
nsresult rv = mActivityDistributor->ObserveActivityWithArgs( if ((mHasRequestBody) && (status == NS_NET_STATUS_WAITING_FOR)) {
HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT, gHttpHandler->ObserveHttpActivityWithArgs(
static_cast<uint32_t>(status), PR_Now(), progress, ""_ns); HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
if (NS_FAILED(rv)) { NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_BODY_SENT, PR_Now(), 0, ""_ns);
LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
}
} }
// report the status and progress
gHttpHandler->ObserveHttpActivityWithArgs(
HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT,
static_cast<uint32_t>(status), PR_Now(), progress, ""_ns);
// nsHttpChannel synthesizes progress events in OnDataAvailable // nsHttpChannel synthesizes progress events in OnDataAvailable
if (status == NS_NET_STATUS_RECEIVING_FROM) return; if (status == NS_NET_STATUS_RECEIVING_FROM) return;
@ -1408,27 +1379,19 @@ void nsHttpTransaction::Close(nsresult reason) {
mTokenBucketCancel = nullptr; mTokenBucketCancel = nullptr;
} }
if (mActivityDistributor) { // report the reponse is complete if not already reported
// report the reponse is complete if not already reported if (!mResponseIsComplete) {
if (!mResponseIsComplete) { gHttpHandler->ObserveHttpActivityWithArgs(
nsresult rv = mActivityDistributor->ObserveActivityWithArgs(
HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_COMPLETE, PR_Now(),
static_cast<uint64_t>(mContentRead), ""_ns);
if (NS_FAILED(rv)) {
LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
}
}
// report that this transaction is closing
nsresult rv = mActivityDistributor->ObserveActivityWithArgs(
HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION, HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
NS_HTTP_ACTIVITY_SUBTYPE_TRANSACTION_CLOSE, PR_Now(), 0, ""_ns); NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_COMPLETE, PR_Now(),
if (NS_FAILED(rv)) { static_cast<uint64_t>(mContentRead), ""_ns);
LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
}
} }
// report that this transaction is closing
gHttpHandler->ObserveHttpActivityWithArgs(
HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
NS_HTTP_ACTIVITY_SUBTYPE_TRANSACTION_CLOSE, PR_Now(), 0, ""_ns);
// we must no longer reference the connection! find out if the // we must no longer reference the connection! find out if the
// connection was being reused before letting it go. // connection was being reused before letting it go.
bool connReused = false; bool connReused = false;
@ -2040,14 +2003,11 @@ nsresult nsHttpTransaction::ParseHead(char* buf, uint32_t count,
if (!mResponseHead) return NS_ERROR_OUT_OF_MEMORY; if (!mResponseHead) return NS_ERROR_OUT_OF_MEMORY;
// report that we have a least some of the response // report that we have a least some of the response
if (mActivityDistributor && !mReportedStart) { if (!mReportedStart) {
mReportedStart = true; mReportedStart = true;
rv = mActivityDistributor->ObserveActivityWithArgs( gHttpHandler->ObserveHttpActivityWithArgs(
HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION, HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_START, PR_Now(), 0, ""_ns); NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_START, PR_Now(), 0, ""_ns);
if (NS_FAILED(rv)) {
LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
}
} }
} }
@ -2392,15 +2352,10 @@ nsresult nsHttpTransaction::HandleContent(char* buf, uint32_t count,
} }
// report the entire response has arrived // report the entire response has arrived
if (mActivityDistributor) { gHttpHandler->ObserveHttpActivityWithArgs(
rv = mActivityDistributor->ObserveActivityWithArgs( HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION, NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_COMPLETE, PR_Now(),
NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_COMPLETE, PR_Now(), static_cast<uint64_t>(mContentRead), ""_ns);
static_cast<uint64_t>(mContentRead), ""_ns);
if (NS_FAILED(rv)) {
LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
}
}
} }
return NS_OK; return NS_OK;
@ -2440,32 +2395,19 @@ nsresult nsHttpTransaction::ProcessData(char* buf, uint32_t count,
// if buf has some content in it, shift bytes to top of buf. // if buf has some content in it, shift bytes to top of buf.
if (count && bytesConsumed) memmove(buf, buf + bytesConsumed, count); if (count && bytesConsumed) memmove(buf, buf + bytesConsumed, count);
// report the completed response header if (mResponseHead && mHaveAllHeaders) {
if (mActivityDistributor && mResponseHead && mHaveAllHeaders) {
auto reportResponseHeader = [&](uint32_t aSubType) { auto reportResponseHeader = [&](uint32_t aSubType) {
nsAutoCString completeResponseHeaders; nsAutoCString completeResponseHeaders;
mResponseHead->Flatten(completeResponseHeaders, false); mResponseHead->Flatten(completeResponseHeaders, false);
completeResponseHeaders.AppendLiteral("\r\n"); completeResponseHeaders.AppendLiteral("\r\n");
rv = mActivityDistributor->ObserveActivityWithArgs( gHttpHandler->ObserveHttpActivityWithArgs(
HttpActivityArgs(mChannelId), HttpActivityArgs(mChannelId),
NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION, aSubType, PR_Now(), 0, NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION, aSubType, PR_Now(), 0,
completeResponseHeaders); completeResponseHeaders);
if (NS_FAILED(rv)) {
LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
}
}; };
if (mConnection->IsProxyConnectInProgress()) { if (mConnection->IsProxyConnectInProgress()) {
nsCOMPtr<nsIHttpActivityDistributor> distributor = reportResponseHeader(NS_HTTP_ACTIVITY_SUBTYPE_PROXY_RESPONSE_HEADER);
do_QueryInterface(mActivityDistributor);
bool observeProxyResponse = false;
if (distributor) {
Unused << distributor->GetObserveProxyResponse(&observeProxyResponse);
if (observeProxyResponse) {
reportResponseHeader(
NS_HTTP_ACTIVITY_SUBTYPE_PROXY_RESPONSE_HEADER);
}
}
} else if (!mReportedResponseHeader) { } else if (!mReportedResponseHeader) {
mReportedResponseHeader = true; mReportedResponseHeader = true;
reportResponseHeader(NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_HEADER); reportResponseHeader(NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_HEADER);

Просмотреть файл

@ -27,7 +27,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class nsIHttpActivityObserver;
class nsIDNSHTTPSSVCRecord; class nsIDNSHTTPSSVCRecord;
class nsIEventTarget; class nsIEventTarget;
class nsIInputStream; class nsIInputStream;
@ -312,7 +311,6 @@ class nsHttpTransaction final : public nsAHttpTransaction,
nsCOMPtr<nsIRequestContext> mRequestContext; nsCOMPtr<nsIRequestContext> mRequestContext;
uint64_t mChannelId{0}; uint64_t mChannelId{0};
nsCOMPtr<nsIHttpActivityObserver> mActivityDistributor;
nsCString mReqHeaderBuf; // flattened request headers nsCString mReqHeaderBuf; // flattened request headers
nsCOMPtr<nsIInputStream> mRequestStream; nsCOMPtr<nsIInputStream> mRequestStream;

Просмотреть файл

@ -193,6 +193,13 @@ interface nsIHttpActivityDistributor : nsIHttpActivityObserver
void addObserver(in nsIHttpActivityObserver aObserver); void addObserver(in nsIHttpActivityObserver aObserver);
void removeObserver(in nsIHttpActivityObserver aObserver); void removeObserver(in nsIHttpActivityObserver aObserver);
/**
* C++ friendly getter
*/
[noscript, notxpcom] bool Activated();
[noscript, notxpcom] bool ObserveProxyResponseEnabled();
[noscript, notxpcom] bool ObserveConnectionEnabled();
/** /**
* When true, the ACTIVITY_SUBTYPE_PROXY_RESPONSE_HEADER will be sent to * When true, the ACTIVITY_SUBTYPE_PROXY_RESPONSE_HEADER will be sent to
* the observers. * the observers.

Просмотреть файл

@ -300,6 +300,13 @@ async function H3ECHTest(echConfig) {
`https://foo.example.com:${trrServer.port}/dns-query` `https://foo.example.com:${trrServer.port}/dns-query`
); );
let observerService = Cc[
"@mozilla.org/network/http-activity-distributor;1"
].getService(Ci.nsIHttpActivityDistributor);
let observer = new ActivityObserver();
observerService.addObserver(observer);
observerService.observeConnection = true;
// Only the last record is valid to use. // Only the last record is valid to use.
await trrServer.registerDoHAnswers("public.example.com", "HTTPS", { await trrServer.registerDoHAnswers("public.example.com", "HTTPS", {
answers: [ answers: [
@ -351,6 +358,14 @@ async function H3ECHTest(echConfig) {
Assert.ok(securityInfo.isAcceptedEch, "This host should have accepted ECH"); Assert.ok(securityInfo.isAcceptedEch, "This host should have accepted ECH");
await trrServer.stop(); await trrServer.stop();
observerService.removeObserver(observer);
observerService.observeConnection = false;
let filtered = observer.activites.filter(
activity => activity.host === "public.example.com"
);
checkHttpActivities(filtered);
} }
add_task(async function testH3ConnectWithECH() { add_task(async function testH3ConnectWithECH() {