forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			269 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			269 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- 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"
 | 
						|
 | 
						|
#include "mozilla/StaticPrefs_network.h"
 | 
						|
#include "mozilla/Telemetry.h"
 | 
						|
#include "mozilla/Unused.h"
 | 
						|
#include "nsSocketTransportService2.h"
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
namespace net {
 | 
						|
 | 
						|
constexpr auto kInvalidCategory = "INVALID_CATEGORY"_ns;
 | 
						|
 | 
						|
#define DEFINE_CATEGORY(_name, _idx) nsLiteralCString("Y" #_idx "_" #_name),
 | 
						|
static const nsCString gKeyName[] = {
 | 
						|
#include "HttpTrafficAnalyzer.inc"
 | 
						|
    kInvalidCategory,
 | 
						|
};
 | 
						|
#undef DEFINE_CATEGORY
 | 
						|
 | 
						|
#define DEFINE_CATEGORY(_name, _idx) \
 | 
						|
  Telemetry::LABELS_HTTP_TRAFFIC_ANALYSIS_3::Y##_idx##_##_name,
 | 
						|
static const Telemetry::LABELS_HTTP_TRAFFIC_ANALYSIS_3 gTelemetryLabel[] = {
 | 
						|
#include "HttpTrafficAnalyzer.inc"
 | 
						|
};
 | 
						|
#undef DEFINE_CATEGORY
 | 
						|
 | 
						|
// ----------------------------------------------------
 | 
						|
// | Flags                           |   Load Type    |
 | 
						|
// ----------------------------------------------------
 | 
						|
// | nsIClassOfService::Leader       |       A        |
 | 
						|
// | w/o nsIRequest::LOAD_BACKGROUND |       B        |
 | 
						|
// | w/ nsIRequest::LOAD_BACKGROUND  |       C        |
 | 
						|
// ----------------------------------------------------
 | 
						|
// | Category                        | List Category  |
 | 
						|
// ----------------------------------------------------
 | 
						|
// | Basic Disconnected List         |       I        |
 | 
						|
// | Content                         |      II        |
 | 
						|
// | Fingerprinting                  |     III        |
 | 
						|
// ----------------------------------------------------
 | 
						|
// ====================================================
 | 
						|
// | Normal Mode                                      |
 | 
						|
// ----------------------------------------------------
 | 
						|
// | Y = 0 for system principals                      |
 | 
						|
// | Y = 1 for first party                            |
 | 
						|
// | Y = 2 for non-listed third party type            |
 | 
						|
// ----------------------------------------------------
 | 
						|
// |          \Y\          | Type A | Type B | Type C |
 | 
						|
// ----------------------------------------------------
 | 
						|
// | Category I            |    3   |    4   |    5   |
 | 
						|
// | Category II           |    6   |    7   |    8   |
 | 
						|
// | Category III          |    9   |   10   |   11   |
 | 
						|
// ====================================================
 | 
						|
// | Private Mode                                     |
 | 
						|
// ----------------------------------------------------
 | 
						|
// | Y = 12 for system principals                     |
 | 
						|
// | Y = 13 for first party                           |
 | 
						|
// | Y = 14 for non-listed third party type           |
 | 
						|
// ----------------------------------------------------
 | 
						|
// |          \Y\          | Type A | Type B | Type C |
 | 
						|
// ----------------------------------------------------
 | 
						|
// | Category I            |   15   |   16   |   17   |
 | 
						|
// | Category II           |   18   |   19   |   20   |
 | 
						|
// | Category III          |   21   |   22   |   23   |
 | 
						|
// ====================================================
 | 
						|
 | 
						|
HttpTrafficCategory HttpTrafficAnalyzer::CreateTrafficCategory(
 | 
						|
    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;
 | 
						|
 | 
						|
  if (!aIsThirdParty) {
 | 
						|
    MOZ_ASSERT_IF(!aIsPrivateMode, gKeyName[category].EqualsLiteral("Y1_N1"));
 | 
						|
    MOZ_ASSERT_IF(aIsPrivateMode, gKeyName[category].EqualsLiteral("Y13_P1"));
 | 
						|
    return static_cast<HttpTrafficCategory>(category);
 | 
						|
  }
 | 
						|
 | 
						|
  switch (aClassification) {
 | 
						|
    case TrackingClassification::eNone:
 | 
						|
      ++category;
 | 
						|
      MOZ_ASSERT_IF(!aIsPrivateMode,
 | 
						|
                    gKeyName[category].EqualsLiteral("Y2_N3Oth"));
 | 
						|
      MOZ_ASSERT_IF(aIsPrivateMode,
 | 
						|
                    gKeyName[category].EqualsLiteral("Y14_P3Oth"));
 | 
						|
      return static_cast<HttpTrafficCategory>(category);
 | 
						|
    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:
 | 
						|
      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")));
 | 
						|
      return static_cast<HttpTrafficCategory>(category);
 | 
						|
    case ClassOfService::eBackground:
 | 
						|
      ++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);
 | 
						|
    case ClassOfService::eOther:
 | 
						|
      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);
 | 
						|
  }
 | 
						|
 | 
						|
  MOZ_ASSERT(false, "incorrect class of service");
 | 
						|
  return HttpTrafficCategory::eInvalid;
 | 
						|
}
 | 
						|
 | 
						|
void HttpTrafficAnalyzer::IncrementHttpTransaction(
 | 
						|
    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));
 | 
						|
 | 
						|
  Telemetry::AccumulateCategoricalKeyed("Transaction"_ns,
 | 
						|
                                        gTelemetryLabel[aCategory]);
 | 
						|
}
 | 
						|
 | 
						|
void HttpTrafficAnalyzer::IncrementHttpConnection(
 | 
						|
    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));
 | 
						|
 | 
						|
  Telemetry::AccumulateCategoricalKeyed("Connection"_ns,
 | 
						|
                                        gTelemetryLabel[aCategory]);
 | 
						|
}
 | 
						|
 | 
						|
void HttpTrafficAnalyzer::IncrementHttpConnection(
 | 
						|
    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:
 | 
						|
  //   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)
 | 
						|
  // Normal and private transaction should not share the same connection,
 | 
						|
  // and we choose 3rd-party prior than 1st-party.
 | 
						|
  HttpTrafficCategory best = categories[0];
 | 
						|
  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;
 | 
						|
  }
 | 
						|
 | 
						|
  IncrementHttpConnection(best);
 | 
						|
}
 | 
						|
 | 
						|
#define CLAMP_U32(num) \
 | 
						|
  Clamp<uint32_t>(num, 0, std::numeric_limits<uint32_t>::max())
 | 
						|
 | 
						|
void HttpTrafficAnalyzer::AccumulateHttpTransferredSize(
 | 
						|
    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));
 | 
						|
 | 
						|
  // Telemetry supports uint32_t only, and we send KB here.
 | 
						|
  auto total = CLAMP_U32((aBytesRead >> 10) + (aBytesSent >> 10));
 | 
						|
  if (aBytesRead || aBytesSent) {
 | 
						|
    Telemetry::ScalarAdd(Telemetry::ScalarID::NETWORKING_DATA_TRANSFERRED_V3_KB,
 | 
						|
                         NS_ConvertUTF8toUTF16(gKeyName[aCategory]), total);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace net
 | 
						|
}  // namespace mozilla
 |