chromium/chrome/browser/ash/net/network_diagnostics/network_diagnostics.cc

// Copyright 2020 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/ash/net/network_diagnostics/network_diagnostics.h"

#include <memory>
#include <optional>
#include <utility>

#include "base/functional/bind.h"
#include "chrome/browser/ash/net/network_diagnostics/arc_dns_resolution_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/arc_http_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/arc_ping_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/captive_portal_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/dns_latency_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/dns_resolution_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/dns_resolver_present_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/gateway_can_be_pinged_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/has_secure_wifi_connection_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/http_firewall_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/https_firewall_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/https_latency_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/lan_connectivity_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/signal_strength_routine.h"
#include "chrome/browser/ash/net/network_diagnostics/video_conferencing_routine.h"
#include "chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.h"
#include "chromeos/ash/components/mojo_service_manager/connection.h"
#include "components/device_event_log/device_event_log.h"
#include "third_party/cros_system_api/mojo/service_constants.h"

namespace ash {
namespace network_diagnostics {

namespace mojom = ::chromeos::network_diagnostics::mojom;

NetworkDiagnostics::NetworkDiagnostics(DebugDaemonClient* debug_daemon_client) {
  DCHECK(debug_daemon_client);
  if (debug_daemon_client) {
    debug_daemon_client_ = debug_daemon_client;
  }
  if (mojo_service_manager::IsServiceManagerBound()) {
    mojo_service_manager::GetServiceManagerProxy()->Register(
        chromeos::mojo_services::kChromiumNetworkDiagnosticsRoutines,
        provider_receiver_.BindNewPipeAndPassRemote());
  }
}

NetworkDiagnostics::~NetworkDiagnostics() {}

void NetworkDiagnostics::BindReceiver(
    mojo::PendingReceiver<mojom::NetworkDiagnosticsRoutines> receiver) {
  NET_LOG(EVENT) << "NetworkDiagnostics::BindReceiver()";
  receivers_.Add(this, std::move(receiver));
}

void NetworkDiagnostics::GetResult(mojom::RoutineType type,
                                   GetResultCallback callback) {
  mojom::RoutineResultPtr result;
  if (results_.count(type)) {
    result = results_[type].Clone();
  }
  std::move(callback).Run(std::move(result));
}

void NetworkDiagnostics::GetAllResults(GetAllResultsCallback callback) {
  base::flat_map<mojom::RoutineType, mojom::RoutineResultPtr> response;
  for (auto& r : results_) {
    response[r.first] = r.second.Clone();
  }
  std::move(callback).Run(std::move(response));
}

void NetworkDiagnostics::RunLanConnectivity(
    std::optional<mojom::RoutineCallSource> source,
    RunLanConnectivityCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<LanConnectivityRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunSignalStrength(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunSignalStrengthCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<SignalStrengthRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunGatewayCanBePinged(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunGatewayCanBePingedCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine =
      std::make_unique<GatewayCanBePingedRoutine>(src, debug_daemon_client_);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunHttpFirewall(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunHttpFirewallCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<HttpFirewallRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunHttpsFirewall(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunHttpsFirewallCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<HttpsFirewallRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunHasSecureWiFiConnection(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunHasSecureWiFiConnectionCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<HasSecureWiFiConnectionRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunDnsResolverPresent(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunDnsResolverPresentCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<DnsResolverPresentRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunDnsLatency(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunDnsLatencyCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<DnsLatencyRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunDnsResolution(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunDnsResolutionCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<DnsResolutionRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunCaptivePortal(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunCaptivePortalCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<CaptivePortalRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunHttpsLatency(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunHttpsLatencyCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<HttpsLatencyRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunVideoConferencing(
    const std::optional<std::string>& stun_server_name,
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunVideoConferencingCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  std::unique_ptr<NetworkDiagnosticsRoutine> routine;
  if (stun_server_name) {
    routine = std::make_unique<VideoConferencingRoutine>(
        src, stun_server_name.value());
  } else {
    routine = std::make_unique<VideoConferencingRoutine>(src);
  }
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunArcHttp(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunArcHttpCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<ArcHttpRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunArcDnsResolution(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunArcDnsResolutionCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<ArcDnsResolutionRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::RunArcPing(
    std::optional<chromeos::network_diagnostics::mojom::RoutineCallSource>
        source,
    RunArcPingCallback callback) {
  mojom::RoutineCallSource src = mojom::RoutineCallSource::kUnknown;
  if (source.has_value()) {
    src = source.value();
  }
  auto routine = std::make_unique<ArcPingRoutine>(src);
  RunRoutine(std::move(routine), std::move(callback));
}

void NetworkDiagnostics::Request(
    chromeos::mojo_service_manager::mojom::ProcessIdentityPtr identity,
    mojo::ScopedMessagePipeHandle receiver) {
  BindReceiver(mojo::PendingReceiver<mojom::NetworkDiagnosticsRoutines>(
      std::move(receiver)));
}

void NetworkDiagnostics::RunRoutine(
    std::unique_ptr<NetworkDiagnosticsRoutine> routine,
    RoutineResultCallback callback) {
  auto* const routine_ptr = routine.get();
  routine_ptr->RunRoutine(base::BindOnce(
      &NetworkDiagnostics::HandleResult, weak_ptr_factory_.GetWeakPtr(),
      std::move(routine), std::move(callback)));
}

void NetworkDiagnostics::HandleResult(
    std::unique_ptr<NetworkDiagnosticsRoutine> routine,
    RoutineResultCallback callback,
    mojom::RoutineResultPtr result) {
  results_[routine->Type()] = result->Clone();
  std::move(callback).Run(std::move(result));
}

}  // namespace network_diagnostics
}  // namespace ash