| // 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/system_logs/network_health_source.h" |
| |
| #include <sstream> |
| #include <string> |
| |
| #include "base/functional/bind.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_util.h" |
| #include "chrome/browser/ash/net/network_health/network_health_manager.h" |
| #include "chromeos/ash/components/network/network_event_log.h" |
| #include "content/public/browser/browser_thread.h" |
| |
| namespace system_logs { |
| |
| namespace { |
| |
| constexpr char kNetworkDiagnosticsEntry[] = "network-diagnostics"; |
| |
| std::string FormatNetworkHealth( |
| const chromeos::network_health::mojom::NetworkHealthStatePtr& |
| network_health, |
| bool scrub, |
| bool include_guid_when_not_scrub) { |
| std::ostringstream output; |
| |
| for (const auto& net : network_health->networks) { |
| if (scrub) { |
| output << "Name: " << ash::NetworkGuidId(net->guid.value_or("N/A")) |
| << "\n"; |
| } else { |
| output << "Name: " << net->name.value_or("N/A") << "\n"; |
| } |
| |
| if (!scrub && include_guid_when_not_scrub) { |
| output << "GUID: " << net->guid.value_or("N/A") << "\n"; |
| } |
| |
| output << "Type: " << net->type << "\n"; |
| output << "State: " << net->state << "\n"; |
| output << "Portal State: " << net->portal_state << "\n"; |
| if (net->signal_strength) { |
| output << "Signal Strength: " |
| << base::NumberToString(net->signal_strength->value) << "\n"; |
| } |
| if (net->signal_strength_stats) { |
| output << "Signal Strength (Average): " |
| << base::NumberToString(net->signal_strength_stats->average) |
| << "\n"; |
| output << "Signal Strength (Deviation): " |
| << base::NumberToString(net->signal_strength_stats->deviation) |
| << "\n"; |
| output << "Signal Strength (Samples): ["; |
| auto& samples = net->signal_strength_stats->samples; |
| for (uint16_t i = 0; i < samples.size(); i++) { |
| output << base::NumberToString(samples[i]); |
| if (i < samples.size() - 1) |
| output << ","; |
| } |
| |
| output << "]\n"; |
| } |
| output << "MAC Address: " << net->mac_address.value_or("N/A") << "\n"; |
| |
| // Automatic PII scrubbing does not work for IP addresses so manually scrub |
| // them. |
| if (!scrub) { |
| output << "IPV4 Address: " << net->ipv4_address.value_or("N/A") << "\n"; |
| output << "IPV6 Addresses: " |
| << (net->ipv6_addresses.size() |
| ? base::JoinString(net->ipv6_addresses, ", ") |
| : "N/A") |
| << "\n"; |
| } |
| |
| output << "\n"; |
| } |
| return output.str(); |
| } |
| |
| template <typename T> |
| std::string ProblemsToStr(T problems) { |
| if (problems.size() == 0) { |
| return ""; |
| } |
| |
| std::ostringstream output; |
| for (uint16_t i = 0; i < problems.size(); i++) { |
| output << problems[i]; |
| if (i != problems.size() - 1) |
| output << ", "; |
| } |
| return output.str(); |
| } |
| |
| std::string GetProblemsString( |
| const chromeos::network_diagnostics::mojom::RoutineProblemsPtr& problems) { |
| using chromeos::network_diagnostics::mojom::RoutineProblems; |
| std::string problemsStr; |
| switch (problems->which()) { |
| case RoutineProblems::Tag::kLanConnectivityProblems: |
| problemsStr = ProblemsToStr(problems->get_lan_connectivity_problems()); |
| break; |
| case RoutineProblems::Tag::kSignalStrengthProblems: |
| problemsStr = ProblemsToStr(problems->get_signal_strength_problems()); |
| break; |
| case RoutineProblems::Tag::kGatewayCanBePingedProblems: |
| problemsStr = |
| ProblemsToStr(problems->get_gateway_can_be_pinged_problems()); |
| break; |
| case RoutineProblems::Tag::kHasSecureWifiConnectionProblems: |
| problemsStr = |
| ProblemsToStr(problems->get_has_secure_wifi_connection_problems()); |
| break; |
| case RoutineProblems::Tag::kDnsResolverPresentProblems: |
| problemsStr = |
| ProblemsToStr(problems->get_dns_resolver_present_problems()); |
| break; |
| case RoutineProblems::Tag::kDnsLatencyProblems: |
| problemsStr = ProblemsToStr(problems->get_dns_latency_problems()); |
| break; |
| case RoutineProblems::Tag::kDnsResolutionProblems: |
| problemsStr = ProblemsToStr(problems->get_dns_resolution_problems()); |
| break; |
| case RoutineProblems::Tag::kCaptivePortalProblems: |
| problemsStr = ProblemsToStr(problems->get_captive_portal_problems()); |
| break; |
| case RoutineProblems::Tag::kHttpFirewallProblems: |
| problemsStr = ProblemsToStr(problems->get_http_firewall_problems()); |
| break; |
| case RoutineProblems::Tag::kHttpsFirewallProblems: |
| problemsStr = ProblemsToStr(problems->get_https_firewall_problems()); |
| break; |
| case RoutineProblems::Tag::kHttpsLatencyProblems: |
| problemsStr = ProblemsToStr(problems->get_https_latency_problems()); |
| break; |
| case RoutineProblems::Tag::kVideoConferencingProblems: |
| problemsStr = ProblemsToStr(problems->get_video_conferencing_problems()); |
| break; |
| case RoutineProblems::Tag::kArcHttpProblems: |
| problemsStr = ProblemsToStr(problems->get_arc_http_problems()); |
| break; |
| case RoutineProblems::Tag::kArcDnsResolutionProblems: |
| problemsStr = ProblemsToStr(problems->get_arc_dns_resolution_problems()); |
| break; |
| case RoutineProblems::Tag::kArcPingProblems: |
| problemsStr = ProblemsToStr(problems->get_arc_ping_problems()); |
| break; |
| } |
| return problemsStr; |
| } |
| |
| } // namespace |
| |
| const char kNetworkHealthSnapshotEntry[] = "network-health-snapshot"; |
| |
| std::string FormatNetworkDiagnosticResults( |
| const base::flat_map< |
| chromeos::network_diagnostics::mojom::RoutineType, |
| chromeos::network_diagnostics::mojom::RoutineResultPtr>& results, |
| bool scrub) { |
| std::ostringstream output; |
| |
| for (const auto& result : results) { |
| output << "Routine: " << result.first << "\n"; |
| output << "Verdict: " << result.second->verdict << "\n"; |
| output << "Timestamp: " << result.second->timestamp << "\n"; |
| output << "Source: " << result.second->source << "\n"; |
| |
| auto problems = GetProblemsString(result.second->problems); |
| if (!problems.empty()) |
| output << "Problems: " << problems << "\n"; |
| |
| output << "\n"; |
| } |
| return output.str(); |
| } |
| |
| NetworkHealthSource::NetworkHealthSource(bool scrub, |
| bool include_guid_when_not_scrub) |
| : SystemLogsSource("NetworkHealth"), |
| scrub_(scrub), |
| include_guid_when_not_scrub_(include_guid_when_not_scrub) { |
| ash::network_health::NetworkHealthManager::GetInstance()->BindHealthReceiver( |
| network_health_service_.BindNewPipeAndPassReceiver()); |
| ash::network_health::NetworkHealthManager::GetInstance() |
| ->BindDiagnosticsReceiver( |
| network_diagnostics_service_.BindNewPipeAndPassReceiver()); |
| } |
| |
| NetworkHealthSource::~NetworkHealthSource() = default; |
| |
| void NetworkHealthSource::Fetch(SysLogsSourceCallback callback) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| DCHECK(!callback.is_null()); |
| callback_ = std::move(callback); |
| network_health_service_->GetHealthSnapshot( |
| base::BindOnce(&NetworkHealthSource::OnNetworkHealthReceived, |
| weak_factory_.GetWeakPtr())); |
| network_diagnostics_service_->GetAllResults( |
| base::BindOnce(&NetworkHealthSource::OnNetworkDiagnosticResultsReceived, |
| weak_factory_.GetWeakPtr())); |
| } |
| |
| void NetworkHealthSource::OnNetworkHealthReceived( |
| chromeos::network_health::mojom::NetworkHealthStatePtr network_health) { |
| network_health_response_ = |
| FormatNetworkHealth(network_health, scrub_, include_guid_when_not_scrub_); |
| CheckIfDone(); |
| } |
| |
| void NetworkHealthSource::OnNetworkDiagnosticResultsReceived( |
| base::flat_map<chromeos::network_diagnostics::mojom::RoutineType, |
| chromeos::network_diagnostics::mojom::RoutineResultPtr> |
| results) { |
| network_diagnostics_response_ = |
| FormatNetworkDiagnosticResults(results, scrub_); |
| CheckIfDone(); |
| } |
| |
| void NetworkHealthSource::CheckIfDone() { |
| if (!network_health_response_.has_value() || |
| !network_diagnostics_response_.has_value()) { |
| return; |
| } |
| |
| auto response = std::make_unique<SystemLogsResponse>(); |
| (*response)[kNetworkHealthSnapshotEntry] = |
| std::move(network_health_response_.value()); |
| (*response)[kNetworkDiagnosticsEntry] = |
| std::move(network_diagnostics_response_.value()); |
| |
| network_health_response_.reset(); |
| network_diagnostics_response_.reset(); |
| |
| std::move(callback_).Run(std::move(response)); |
| } |
| |
| } // namespace system_logs |