chromium/chrome/browser/net/network_annotation_monitor.cc

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/net/network_annotation_monitor.h"

#include <utility>

#include "base/metrics/histogram_functions.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/common/pref_names.h"
#include "chromeos/dbus/regmon/regmon_client.h"
#include "chromeos/dbus/regmon/regmon_service.pb.h"
#include "components/prefs/pref_service.h"

NetworkAnnotationMonitor::NetworkAnnotationMonitor() = default;
NetworkAnnotationMonitor::~NetworkAnnotationMonitor() = default;

void NetworkAnnotationMonitor::Report(int32_t hash_code) {
  // Multi-profile is not currently supported, so only run on ChromeOS for now.
  static_assert(BUILDFLAG(IS_CHROMEOS));

#if BUILDFLAG(IS_CHROMEOS_LACROS)
  // Lacros allows multi-profile if enabled by policy, so skip reporting in this
  // case. In the future we could consider using ProfileNetworkContext for this.
  if (profiles::AreSecondaryProfilesAllowed()) {
    return;
  }
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

  // Get blocklist prefs from the current active profile, which on ChromeOS
  // should be the only profile based on the above check.
  const base::Value::Dict& blocklist =
      ProfileManager::GetActiveUserProfile()->GetPrefs()->GetDict(
          prefs::kNetworkAnnotationBlocklist);

  // Ignore any network calls not in the blocklist.
  if (!blocklist.contains(base::NumberToString(hash_code))) {
    return;
  }

  chromeos::RegmonClient* client = chromeos::RegmonClient::Get();
  if (!client) {
    return;
  }

  regmon::PolicyViolation policy_violation;
  policy_violation.set_policy(::regmon::PolicyViolation::POLICY_UNSPECIFIED);
  policy_violation.set_annotation_hash(hash_code);

  regmon::RecordPolicyViolationRequest request =
      regmon::RecordPolicyViolationRequest();
  *request.mutable_violation() = policy_violation;
  client->RecordPolicyViolation(request);
}

mojo::PendingRemote<network::mojom::NetworkAnnotationMonitor>
NetworkAnnotationMonitor::GetClient() {
  // Reset receiver if already bound. This can happen if the Network Service
  // crashed and has been restarted.
  if (receiver_.is_bound()) {
    receiver_.reset();
  }

  mojo::PendingRemote<network::mojom::NetworkAnnotationMonitor> client;
  receiver_.Bind(client.InitWithNewPipeAndPassReceiver());
  return client;
}

void NetworkAnnotationMonitor::FlushForTesting() {
  receiver_.FlushForTesting();  // IN-TEST
}