blob: 744d0353d2f226edf56d8bc183b52f7dee243904 [file] [log] [blame]
// Copyright 2021 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/support_tool/support_tool_util.h"
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/i18n/time_formatting.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h"
#include "chrome/browser/feedback/system_logs/log_sources/crash_ids_source.h"
#include "chrome/browser/feedback/system_logs/log_sources/device_event_log_source.h"
#include "chrome/browser/feedback/system_logs/log_sources/memory_details_log_source.h"
#include "chrome/browser/feedback/system_logs/log_sources/performance_log_source.h"
#include "chrome/browser/support_tool/data_collection_module.pb.h"
#include "chrome/browser/support_tool/policy_data_collector.h"
#include "chrome/browser/support_tool/signin_data_collector.h"
#include "chrome/browser/support_tool/support_tool_handler.h"
#include "chrome/browser/support_tool/system_log_source_data_collector_adaptor.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "build/chromeos_buildflags.h"
#include "chrome/browser/ash/system_logs/app_service_log_source.h"
#include "chrome/browser/ash/system_logs/bluetooth_log_source.h"
#include "chrome/browser/ash/system_logs/command_line_log_source.h"
#include "chrome/browser/ash/system_logs/connected_input_devices_log_source.h"
#include "chrome/browser/ash/system_logs/dbus_log_source.h"
#include "chrome/browser/ash/system_logs/iwlwifi_dump_log_source.h"
#include "chrome/browser/ash/system_logs/touch_log_source.h"
#include "chrome/browser/ash/system_logs/traffic_counters_log_source.h"
#include "chrome/browser/ash/system_logs/virtual_keyboard_log_source.h"
#include "chrome/browser/support_tool/ash/chrome_user_logs_data_collector.h"
#include "chrome/browser/support_tool/ash/network_health_data_collector.h"
#include "chrome/browser/support_tool/ash/network_routes_data_collector.h"
#include "chrome/browser/support_tool/ash/shill_data_collector.h"
#include "chrome/browser/support_tool/ash/system_logs_data_collector.h"
#include "chrome/browser/support_tool/ash/system_state_data_collector.h"
#include "chrome/browser/support_tool/ash/ui_hierarchy_data_collector.h"
#include "chromeos/ash/components/browser_context_helper/browser_context_types.h"
#include "components/user_manager/user_manager.h"
#if BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS)
#include "chrome/browser/ash/system_logs/reven_log_source.h"
#endif // BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS)
#endif // BUILDFLAG(IS_CHROMEOS)
namespace {
// Data collector types that can work on every platform.
constexpr support_tool::DataCollectorType kDataCollectors[] = {
support_tool::CHROME_INTERNAL, support_tool::CRASH_IDS,
support_tool::MEMORY_DETAILS, support_tool::POLICIES,
support_tool::CHROMEOS_DEVICE_EVENT, support_tool::PERFORMANCE,
support_tool::SIGN_IN_STATE};
// Data collector types can only work on Chrome OS Ash.
constexpr support_tool::DataCollectorType kDataCollectorsChromeosAsh[] = {
support_tool::CHROMEOS_UI_HIERARCHY,
support_tool::CHROMEOS_COMMAND_LINE,
support_tool::CHROMEOS_IWL_WIFI_DUMP,
support_tool::CHROMEOS_TOUCH_EVENTS,
support_tool::CHROMEOS_DBUS,
support_tool::CHROMEOS_NETWORK_ROUTES,
support_tool::CHROMEOS_SHILL,
support_tool::CHROMEOS_SYSTEM_STATE,
support_tool::CHROMEOS_SYSTEM_LOGS,
support_tool::CHROMEOS_CHROME_USER_LOGS,
support_tool::CHROMEOS_BLUETOOTH_FLOSS,
support_tool::CHROMEOS_CONNECTED_INPUT_DEVICES,
support_tool::CHROMEOS_TRAFFIC_COUNTERS,
support_tool::CHROMEOS_VIRTUAL_KEYBOARD,
support_tool::CHROMEOS_NETWORK_HEALTH,
support_tool::CHROMEOS_APP_SERVICE};
// Data collector types that can only work on if IS_CHROMEOS_WITH_HW_DETAILS
// flag is turned on. IS_CHROMEOS_WITH_HW_DETAILS flag will be turned on for
// Chrome OS Flex devices.
constexpr support_tool::DataCollectorType kDataCollectorsChromeosHwDetails[] = {
support_tool::CHROMEOS_REVEN};
} // namespace
std::unique_ptr<SupportToolHandler> GetSupportToolHandler(
std::string case_id,
std::string email_address,
std::string issue_description,
std::optional<std::string> upload_id,
Profile* profile,
std::set<support_tool::DataCollectorType> included_data_collectors) {
std::unique_ptr<SupportToolHandler> handler =
std::make_unique<SupportToolHandler>(case_id, email_address,
issue_description, upload_id);
for (const auto& data_collector_type : included_data_collectors) {
switch (data_collector_type) {
case support_tool::CHROME_INTERNAL:
handler->AddDataCollector(
std::make_unique<SystemLogSourceDataCollectorAdaptor>(
"Fetches internal Chrome logs.",
std::make_unique<system_logs::ChromeInternalLogSource>()));
break;
case support_tool::CRASH_IDS:
handler->AddDataCollector(std::make_unique<
SystemLogSourceDataCollectorAdaptor>(
"Extracts the most recent crash IDs (if any) and exports them into "
"crash_report_ids and all_crash_report_ids files.",
std::make_unique<system_logs::CrashIdsSource>()));
break;
case support_tool::MEMORY_DETAILS:
handler->AddDataCollector(std::make_unique<
SystemLogSourceDataCollectorAdaptor>(
"Fetches memory usage details and exports them into mem_usage and "
"mem_usage_with_title files.",
std::make_unique<system_logs::MemoryDetailsLogSource>()));
break;
case support_tool::POLICIES:
// TODO: b/252962974 - Collect device policies even when `profile` is
// nullptr.
if (profile) {
handler->AddDataCollector(
std::make_unique<PolicyDataCollector>(profile));
}
break;
case support_tool::CHROMEOS_DEVICE_EVENT:
handler->AddDataCollector(std::make_unique<
SystemLogSourceDataCollectorAdaptor>(
"Fetches entries for 'network_event_log' and 'device_event_log'.",
std::make_unique<system_logs::DeviceEventLogSource>()));
break;
case support_tool::PERFORMANCE:
handler->AddDataCollector(
std::make_unique<SystemLogSourceDataCollectorAdaptor>(
"Gathers performance relevant data such as if high efficiency "
"or battery saver mode is active and details about current "
"battery state.",
std::make_unique<system_logs::PerformanceLogSource>()));
break;
case support_tool::SIGN_IN_STATE:
// Sign-in data is not available when there's no signed-in user.
if (profile
#if BUILDFLAG(IS_CHROMEOS)
&& user_manager::UserManager::Get()->IsUserLoggedIn()
#endif // BUILDFLAG(IS_CHROMEOS)
) {
handler->AddDataCollector(
std::make_unique<SigninDataCollector>(profile));
}
break;
#if BUILDFLAG(IS_CHROMEOS)
case support_tool::CHROMEOS_UI_HIERARCHY:
handler->AddDataCollector(std::make_unique<UiHierarchyDataCollector>());
break;
case support_tool::CHROMEOS_NETWORK_ROUTES:
handler->AddDataCollector(
std::make_unique<NetworkRoutesDataCollector>());
break;
case support_tool::CHROMEOS_COMMAND_LINE:
handler->AddDataCollector(
std::make_unique<SystemLogSourceDataCollectorAdaptor>(
"Gathers log data from various scripts/programs. Creates and "
"exports data into these files: alsa controls, cras, "
"audio_diagnostics, env, disk_usage.",
std::make_unique<system_logs::CommandLineLogSource>()));
break;
case support_tool::CHROMEOS_IWL_WIFI_DUMP:
handler->AddDataCollector(std::make_unique<
SystemLogSourceDataCollectorAdaptor>(
"Fetches debug dump information from Intel Wi-Fi NICs that will be "
"produced when those NICs have issues such as firmware crashes. "
"Exports the logs into a file named iwlwifi_dump.",
std::make_unique<system_logs::IwlwifiDumpLogSource>()));
break;
case support_tool::CHROMEOS_TOUCH_EVENTS:
handler->AddDataCollector(
std::make_unique<SystemLogSourceDataCollectorAdaptor>(
"Fetches touch events, touchscreen and touchpad logs.",
std::make_unique<system_logs::TouchLogSource>()));
break;
case support_tool::CHROMEOS_DBUS:
handler->AddDataCollector(
std::make_unique<SystemLogSourceDataCollectorAdaptor>(
"Fetches DBus usage statistics. Creates and exports data into "
"these files: dbus_details, dbus_summary.",
std::make_unique<system_logs::DBusLogSource>()));
break;
case support_tool::CHROMEOS_SHILL:
handler->AddDataCollector(std::make_unique<ShillDataCollector>());
break;
case support_tool::CHROMEOS_SYSTEM_STATE:
handler->AddDataCollector(std::make_unique<SystemStateDataCollector>());
break;
case support_tool::CHROMEOS_SYSTEM_LOGS:
// Set `requested_logs` as empty to request all log for now.
handler->AddDataCollector(std::make_unique<SystemLogsDataCollector>(
/*requested_logs=*/std::set<base::FilePath>()));
break;
case support_tool::CHROMEOS_PERIODIC_LOG_UPLOAD_SYSTEM_LOGS: {
// For periodic log upload only a certain subset of system logs is
// necessary.
const std::set<base::FilePath> periodicLogUploadSystemLogs = {
base::FilePath("bios_info"),
base::FilePath("chrome_system_log"),
base::FilePath("chrome_system_log.PREVIOUS"),
base::FilePath("eventlog"),
base::FilePath("extensions.log"),
base::FilePath("netlog"),
base::FilePath("syslog"),
base::FilePath("ui_log"),
base::FilePath("update_engine.log"),
// TODO(b/352028256): the following log is not currently read by
// debugd. Don't forget to add them during the periodic log
// upload migration.
base::FilePath("extensions.1.log"),
};
handler->AddDataCollector(std::make_unique<SystemLogsDataCollector>(
periodicLogUploadSystemLogs));
break;
}
case support_tool::CHROMEOS_CHROME_USER_LOGS:
// User session must be active to read user data from Cryptohome.
if (ash::IsUserBrowserContext(profile)) {
handler->AddDataCollector(
std::make_unique<ChromeUserLogsDataCollector>());
}
break;
case support_tool::CHROMEOS_BLUETOOTH_FLOSS:
handler->AddDataCollector(
std::make_unique<SystemLogSourceDataCollectorAdaptor>(
"Fetches the Bluetooth Floss enabled or disabled information "
"on the device.",
std::make_unique<system_logs::BluetoothLogSource>()));
break;
case support_tool::CHROMEOS_CONNECTED_INPUT_DEVICES:
handler->AddDataCollector(std::make_unique<
SystemLogSourceDataCollectorAdaptor>(
"Fetches the information about connected input devices.",
std::make_unique<system_logs::ConnectedInputDevicesLogSource>()));
break;
case support_tool::CHROMEOS_TRAFFIC_COUNTERS:
handler->AddDataCollector(
std::make_unique<SystemLogSourceDataCollectorAdaptor>(
"Fetches traffic counters information.",
std::make_unique<system_logs::TrafficCountersLogSource>()));
break;
case support_tool::CHROMEOS_VIRTUAL_KEYBOARD:
handler->AddDataCollector(
std::make_unique<SystemLogSourceDataCollectorAdaptor>(
"Fetches the virtual keyboard information.",
std::make_unique<system_logs::VirtualKeyboardLogSource>()));
break;
case support_tool::CHROMEOS_NETWORK_HEALTH:
handler->AddDataCollector(
std::make_unique<NetworkHealthDataCollector>());
break;
case support_tool::CHROMEOS_APP_SERVICE:
handler->AddDataCollector(
std::make_unique<SystemLogSourceDataCollectorAdaptor>(
"Gathers information from app service about installed and "
"running apps.",
std::make_unique<system_logs::AppServiceLogSource>()));
break;
case support_tool::CHROMEOS_REVEN:
#if BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS)
handler->AddDataCollector(
std::make_unique<SystemLogSourceDataCollectorAdaptor>(
"Collect Hardware data for ChromeOS Flex devices via "
"cros_healthd calls.",
std::make_unique<system_logs::RevenLogSource>()));
#endif // BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS)
break;
#endif // BUILDFLAG(IS_CHROMEOS)
default:
break;
}
}
return handler;
}
std::vector<support_tool::DataCollectorType> GetAllDataCollectors() {
std::vector<support_tool::DataCollectorType> data_collectors;
for (const auto& type : kDataCollectors) {
data_collectors.push_back(type);
}
for (const auto& type : kDataCollectorsChromeosAsh) {
data_collectors.push_back(type);
}
for (const auto& type : kDataCollectorsChromeosHwDetails) {
data_collectors.push_back(type);
}
return data_collectors;
}
std::vector<support_tool::DataCollectorType>
GetAllAvailableDataCollectorsOnDevice() {
std::vector<support_tool::DataCollectorType> data_collectors;
for (const auto& type : kDataCollectors) {
data_collectors.push_back(type);
}
#if BUILDFLAG(IS_CHROMEOS)
for (const auto& type : kDataCollectorsChromeosAsh) {
data_collectors.push_back(type);
}
#if BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS)
for (const auto& type : kDataCollectorsChromeosHwDetails) {
data_collectors.push_back(type);
}
#endif // BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS)
#endif // BUILDFLAG(IS_CHROMEOS)
return data_collectors;
}
base::FilePath GetFilepathToExport(base::FilePath target_directory,
const std::string& filename_prefix,
const std::string& case_id,
base::Time timestamp) {
std::string filename = filename_prefix + "_";
if (!case_id.empty()) {
filename += case_id + "_";
}
return target_directory.AppendASCII(
filename + base::UnlocalizedTimeFormatWithPattern(
timestamp, "'UTC'yyyyMMdd_HHmm", icu::TimeZone::getGMT()));
}
std::string SupportToolErrorsToString(
const std::set<SupportToolError>& errors) {
std::vector<std::string_view> error_messages;
error_messages.reserve(errors.size());
for (const auto& error : errors) {
error_messages.push_back(error.error_message);
}
return base::JoinString(error_messages, ", ");
}