2019-04-05 00:38:28 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* 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/. */
|
|
|
|
|
|
|
|
#include "HttpTrafficAnalyzer.h"
|
|
|
|
#include "HttpLog.h"
|
|
|
|
|
2019-07-26 04:10:23 +03:00
|
|
|
#include "mozilla/StaticPrefs_network.h"
|
2019-04-05 00:36:39 +03:00
|
|
|
#include "mozilla/Telemetry.h"
|
2019-04-05 00:38:28 +03:00
|
|
|
#include "mozilla/Unused.h"
|
2020-03-10 19:28:47 +03:00
|
|
|
#include "nsSocketTransportService2.h"
|
2019-04-05 00:38:28 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace net {
|
|
|
|
|
2019-05-21 17:41:58 +03:00
|
|
|
constexpr auto kInvalidCategory = "INVALID_CATEGORY"_ns;
|
|
|
|
|
2019-04-26 18:01:58 +03:00
|
|
|
#define DEFINE_CATEGORY(_name, _idx) nsLiteralCString("Y" #_idx "_" #_name),
|
2019-04-05 00:38:28 +03:00
|
|
|
static const nsCString gKeyName[] = {
|
|
|
|
#include "HttpTrafficAnalyzer.inc"
|
2019-05-21 17:41:58 +03:00
|
|
|
kInvalidCategory,
|
2019-04-05 00:38:28 +03:00
|
|
|
};
|
|
|
|
#undef DEFINE_CATEGORY
|
|
|
|
|
2019-04-26 18:01:58 +03:00
|
|
|
#define DEFINE_CATEGORY(_name, _idx) \
|
2019-05-16 16:24:18 +03:00
|
|
|
Telemetry::LABELS_HTTP_TRAFFIC_ANALYSIS_3::Y##_idx##_##_name,
|
|
|
|
static const Telemetry::LABELS_HTTP_TRAFFIC_ANALYSIS_3 gTelemetryLabel[] = {
|
2019-04-26 18:01:58 +03:00
|
|
|
#include "HttpTrafficAnalyzer.inc"
|
|
|
|
};
|
|
|
|
#undef DEFINE_CATEGORY
|
|
|
|
|
2019-04-05 00:38:28 +03:00
|
|
|
// ----------------------------------------------------
|
|
|
|
// | Flags | Load Type |
|
|
|
|
// ----------------------------------------------------
|
|
|
|
// | nsIClassOfService::Leader | A |
|
|
|
|
// | w/o nsIRequest::LOAD_BACKGROUND | B |
|
|
|
|
// | w/ nsIRequest::LOAD_BACKGROUND | C |
|
|
|
|
// ----------------------------------------------------
|
|
|
|
// | Category | List Category |
|
|
|
|
// ----------------------------------------------------
|
2019-04-26 18:01:58 +03:00
|
|
|
// | Basic Disconnected List | I |
|
|
|
|
// | Content | II |
|
2019-04-05 00:38:28 +03:00
|
|
|
// | Fingerprinting | III |
|
|
|
|
// ----------------------------------------------------
|
|
|
|
// ====================================================
|
|
|
|
// | Normal Mode |
|
|
|
|
// ----------------------------------------------------
|
2019-05-16 16:24:18 +03:00
|
|
|
// | Y = 0 for system principals |
|
|
|
|
// | Y = 1 for first party |
|
|
|
|
// | Y = 2 for non-listed third party type |
|
2019-04-05 00:38:28 +03:00
|
|
|
// ----------------------------------------------------
|
|
|
|
// | \Y\ | Type A | Type B | Type C |
|
|
|
|
// ----------------------------------------------------
|
2019-05-16 16:24:18 +03:00
|
|
|
// | Category I | 3 | 4 | 5 |
|
|
|
|
// | Category II | 6 | 7 | 8 |
|
|
|
|
// | Category III | 9 | 10 | 11 |
|
2019-04-05 00:38:28 +03:00
|
|
|
// ====================================================
|
|
|
|
// | Private Mode |
|
|
|
|
// ----------------------------------------------------
|
2019-05-16 16:24:18 +03:00
|
|
|
// | Y = 12 for system principals |
|
|
|
|
// | Y = 13 for first party |
|
|
|
|
// | Y = 14 for non-listed third party type |
|
2019-04-05 00:38:28 +03:00
|
|
|
// ----------------------------------------------------
|
|
|
|
// | \Y\ | Type A | Type B | Type C |
|
|
|
|
// ----------------------------------------------------
|
2019-05-16 16:24:18 +03:00
|
|
|
// | Category I | 15 | 16 | 17 |
|
|
|
|
// | Category II | 18 | 19 | 20 |
|
|
|
|
// | Category III | 21 | 22 | 23 |
|
2019-04-05 00:38:28 +03:00
|
|
|
// ====================================================
|
|
|
|
|
|
|
|
HttpTrafficCategory HttpTrafficAnalyzer::CreateTrafficCategory(
|
2019-05-16 16:24:18 +03:00
|
|
|
bool aIsPrivateMode, bool aIsSystemPrincipal, bool aIsThirdParty,
|
|
|
|
ClassOfService aClassOfService, TrackingClassification aClassification) {
|
|
|
|
uint8_t category = aIsPrivateMode ? 12 : 0;
|
|
|
|
if (aIsSystemPrincipal) {
|
|
|
|
MOZ_ASSERT_IF(!aIsPrivateMode,
|
|
|
|
gKeyName[category].EqualsLiteral("Y0_N1Sys"));
|
|
|
|
MOZ_ASSERT_IF(aIsPrivateMode,
|
|
|
|
gKeyName[category].EqualsLiteral("Y12_P1Sys"));
|
|
|
|
return static_cast<HttpTrafficCategory>(category);
|
|
|
|
}
|
|
|
|
++category;
|
|
|
|
|
2019-04-05 00:38:28 +03:00
|
|
|
if (!aIsThirdParty) {
|
2019-05-16 16:24:18 +03:00
|
|
|
MOZ_ASSERT_IF(!aIsPrivateMode, gKeyName[category].EqualsLiteral("Y1_N1"));
|
|
|
|
MOZ_ASSERT_IF(aIsPrivateMode, gKeyName[category].EqualsLiteral("Y13_P1"));
|
2019-04-05 00:38:28 +03:00
|
|
|
return static_cast<HttpTrafficCategory>(category);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (aClassification) {
|
|
|
|
case TrackingClassification::eNone:
|
2019-05-16 16:24:18 +03:00
|
|
|
++category;
|
|
|
|
MOZ_ASSERT_IF(!aIsPrivateMode,
|
|
|
|
gKeyName[category].EqualsLiteral("Y2_N3Oth"));
|
|
|
|
MOZ_ASSERT_IF(aIsPrivateMode,
|
|
|
|
gKeyName[category].EqualsLiteral("Y14_P3Oth"));
|
|
|
|
return static_cast<HttpTrafficCategory>(category);
|
2019-04-05 00:38:28 +03:00
|
|
|
case TrackingClassification::eBasic:
|
|
|
|
category += 2;
|
|
|
|
break;
|
|
|
|
case TrackingClassification::eContent:
|
|
|
|
category += 5;
|
|
|
|
break;
|
|
|
|
case TrackingClassification::eFingerprinting:
|
|
|
|
category += 8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
MOZ_ASSERT(false, "incorrect classification");
|
|
|
|
return HttpTrafficCategory::eInvalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (aClassOfService) {
|
|
|
|
case ClassOfService::eLeader:
|
2019-05-16 16:24:18 +03:00
|
|
|
MOZ_ASSERT_IF(
|
|
|
|
!aIsPrivateMode,
|
|
|
|
(aClassification == TrackingClassification::eBasic &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y3_N3BasicLead")) ||
|
|
|
|
(aClassification == TrackingClassification::eContent &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y6_N3ContentLead")) ||
|
|
|
|
(aClassification == TrackingClassification::eFingerprinting &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y9_N3FpLead")));
|
|
|
|
MOZ_ASSERT_IF(
|
|
|
|
aIsPrivateMode,
|
|
|
|
(aClassification == TrackingClassification::eBasic &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y15_P3BasicLead")) ||
|
|
|
|
(aClassification == TrackingClassification::eContent &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y18_P3ContentLead")) ||
|
|
|
|
(aClassification == TrackingClassification::eFingerprinting &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y21_P3FpLead")));
|
2019-04-05 00:38:28 +03:00
|
|
|
return static_cast<HttpTrafficCategory>(category);
|
|
|
|
case ClassOfService::eBackground:
|
2019-05-16 16:24:18 +03:00
|
|
|
++category;
|
|
|
|
|
|
|
|
MOZ_ASSERT_IF(
|
|
|
|
!aIsPrivateMode,
|
|
|
|
(aClassification == TrackingClassification::eBasic &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y4_N3BasicBg")) ||
|
|
|
|
(aClassification == TrackingClassification::eContent &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y7_N3ContentBg")) ||
|
|
|
|
(aClassification == TrackingClassification::eFingerprinting &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y10_N3FpBg")));
|
|
|
|
MOZ_ASSERT_IF(
|
|
|
|
aIsPrivateMode,
|
|
|
|
(aClassification == TrackingClassification::eBasic &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y16_P3BasicBg")) ||
|
|
|
|
(aClassification == TrackingClassification::eContent &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y19_P3ContentBg")) ||
|
|
|
|
(aClassification == TrackingClassification::eFingerprinting &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y22_P3FpBg")));
|
|
|
|
|
|
|
|
return static_cast<HttpTrafficCategory>(category);
|
2019-04-05 00:38:28 +03:00
|
|
|
case ClassOfService::eOther:
|
2019-05-16 16:24:18 +03:00
|
|
|
category += 2;
|
|
|
|
|
|
|
|
MOZ_ASSERT_IF(
|
|
|
|
!aIsPrivateMode,
|
|
|
|
(aClassification == TrackingClassification::eBasic &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y5_N3BasicOth")) ||
|
|
|
|
(aClassification == TrackingClassification::eContent &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y8_N3ContentOth")) ||
|
|
|
|
(aClassification == TrackingClassification::eFingerprinting &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y11_N3FpOth")));
|
|
|
|
MOZ_ASSERT_IF(
|
|
|
|
aIsPrivateMode,
|
|
|
|
(aClassification == TrackingClassification::eBasic &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y17_P3BasicOth")) ||
|
|
|
|
(aClassification == TrackingClassification::eContent &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y20_P3ContentOth")) ||
|
|
|
|
(aClassification == TrackingClassification::eFingerprinting &&
|
|
|
|
gKeyName[category].EqualsLiteral("Y23_P3FpOth")));
|
|
|
|
|
|
|
|
return static_cast<HttpTrafficCategory>(category);
|
2019-04-05 00:38:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(false, "incorrect class of service");
|
|
|
|
return HttpTrafficCategory::eInvalid;
|
|
|
|
}
|
|
|
|
|
2019-12-02 16:21:06 +03:00
|
|
|
void HttpTrafficAnalyzer::IncrementHttpTransaction(
|
2019-04-05 00:38:28 +03:00
|
|
|
HttpTrafficCategory aCategory) {
|
|
|
|
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
|
|
|
MOZ_ASSERT(StaticPrefs::network_traffic_analyzer_enabled());
|
|
|
|
MOZ_ASSERT(aCategory != HttpTrafficCategory::eInvalid, "invalid category");
|
|
|
|
|
|
|
|
LOG(("HttpTrafficAnalyzer::IncrementHttpTransaction [%s] [this=%p]\n",
|
|
|
|
gKeyName[aCategory].get(), this));
|
|
|
|
|
2019-04-26 18:01:58 +03:00
|
|
|
Telemetry::AccumulateCategoricalKeyed("Transaction"_ns,
|
|
|
|
gTelemetryLabel[aCategory]);
|
2019-04-05 00:38:28 +03:00
|
|
|
}
|
|
|
|
|
2019-12-02 16:21:06 +03:00
|
|
|
void HttpTrafficAnalyzer::IncrementHttpConnection(
|
2019-04-05 00:38:28 +03:00
|
|
|
HttpTrafficCategory aCategory) {
|
|
|
|
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
|
|
|
MOZ_ASSERT(StaticPrefs::network_traffic_analyzer_enabled());
|
|
|
|
MOZ_ASSERT(aCategory != HttpTrafficCategory::eInvalid, "invalid category");
|
|
|
|
|
|
|
|
LOG(("HttpTrafficAnalyzer::IncrementHttpConnection [%s] [this=%p]\n",
|
|
|
|
gKeyName[aCategory].get(), this));
|
|
|
|
|
2019-04-26 18:01:58 +03:00
|
|
|
Telemetry::AccumulateCategoricalKeyed("Connection"_ns,
|
|
|
|
gTelemetryLabel[aCategory]);
|
2019-04-05 00:38:28 +03:00
|
|
|
}
|
|
|
|
|
2019-12-02 16:21:06 +03:00
|
|
|
void HttpTrafficAnalyzer::IncrementHttpConnection(
|
2019-04-05 00:38:28 +03:00
|
|
|
nsTArray<HttpTrafficCategory>&& aCategories) {
|
|
|
|
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
|
|
|
MOZ_ASSERT(StaticPrefs::network_traffic_analyzer_enabled());
|
|
|
|
MOZ_ASSERT(!aCategories.IsEmpty(), "empty category");
|
|
|
|
|
|
|
|
nsTArray<HttpTrafficCategory> categories(std::move(aCategories));
|
|
|
|
|
|
|
|
LOG(("HttpTrafficAnalyzer::IncrementHttpConnection size=%" PRIuPTR
|
|
|
|
" [this=%p]\n",
|
|
|
|
categories.Length(), this));
|
|
|
|
|
|
|
|
// divide categories into 4 parts:
|
2019-05-21 17:41:58 +03:00
|
|
|
// 1) normal 1st-party (Y in {0, 1})
|
|
|
|
// 2) normal 3rd-party (1 < Y < 12)
|
|
|
|
// 3) private 1st-party (Y in {12, 13})
|
|
|
|
// 4) private 3rd-party (13 < Y < 24)
|
2019-04-05 00:38:28 +03:00
|
|
|
// Normal and private transaction should not share the same connection,
|
|
|
|
// and we choose 3rd-party prior than 1st-party.
|
|
|
|
HttpTrafficCategory best = categories[0];
|
2019-05-21 17:41:58 +03:00
|
|
|
for (auto category : categories) {
|
|
|
|
MOZ_ASSERT(category != HttpTrafficCategory::eInvalid, "invalid category");
|
|
|
|
|
|
|
|
if (category == 0 || category == 1 || category == 12 || category == 13) {
|
|
|
|
// first party
|
|
|
|
MOZ_ASSERT(gKeyName[category].EqualsLiteral("Y0_N1Sys") ||
|
|
|
|
gKeyName[category].EqualsLiteral("Y1_N1") ||
|
|
|
|
gKeyName[category].EqualsLiteral("Y12_P1Sys") ||
|
|
|
|
gKeyName[category].EqualsLiteral("Y13_P1"));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// third party
|
|
|
|
MOZ_ASSERT(gKeyName[24].Equals(kInvalidCategory),
|
|
|
|
"category definition isn't consistent");
|
|
|
|
best = category;
|
|
|
|
break;
|
2019-04-05 00:38:28 +03:00
|
|
|
}
|
|
|
|
|
2019-12-02 16:21:06 +03:00
|
|
|
IncrementHttpConnection(best);
|
2019-04-05 00:38:28 +03:00
|
|
|
}
|
|
|
|
|
2019-04-05 00:36:39 +03:00
|
|
|
#define CLAMP_U32(num) \
|
|
|
|
Clamp<uint32_t>(num, 0, std::numeric_limits<uint32_t>::max())
|
|
|
|
|
2019-12-02 16:21:06 +03:00
|
|
|
void HttpTrafficAnalyzer::AccumulateHttpTransferredSize(
|
2019-04-05 00:38:28 +03:00
|
|
|
HttpTrafficCategory aCategory, uint64_t aBytesRead, uint64_t aBytesSent) {
|
|
|
|
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
|
|
|
MOZ_ASSERT(StaticPrefs::network_traffic_analyzer_enabled());
|
|
|
|
MOZ_ASSERT(aCategory != HttpTrafficCategory::eInvalid, "invalid category");
|
|
|
|
|
|
|
|
LOG(("HttpTrafficAnalyzer::AccumulateHttpTransferredSize [%s] rb=%" PRIu64 " "
|
|
|
|
"sb=%" PRIu64 " [this=%p]\n",
|
|
|
|
gKeyName[aCategory].get(), aBytesRead, aBytesSent, this));
|
|
|
|
|
2019-04-26 12:39:31 +03:00
|
|
|
// Telemetry supports uint32_t only, and we send KB here.
|
|
|
|
auto total = CLAMP_U32((aBytesRead >> 10) + (aBytesSent >> 10));
|
|
|
|
if (aBytesRead || aBytesSent) {
|
2019-05-16 16:24:18 +03:00
|
|
|
Telemetry::ScalarAdd(Telemetry::ScalarID::NETWORKING_DATA_TRANSFERRED_V3_KB,
|
2019-04-26 12:39:31 +03:00
|
|
|
NS_ConvertUTF8toUTF16(gKeyName[aCategory]), total);
|
|
|
|
}
|
2019-04-05 00:38:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace net
|
|
|
|
} // namespace mozilla
|