blob: 10fee32d6ef5a296fb5e473d4edfe62f2025f156 [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 <set>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "build/chromeos_buildflags.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/support_tool_handler.h"
#include "chrome/browser/support_tool/system_log_source_data_collector_adaptor.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/crosapi/browser_manager.h"
#include "chrome/browser/ash/crosapi/browser_util.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/crosapi_system_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/feedback/system_logs/log_sources/lacros_log_files_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"
#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_ASH)
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};
// 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};
// 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};
// Data collector types that may be available on the device depending on other
// components or flags. Currently consists of data collactors that collect
// logs for Lacros.
constexpr support_tool::DataCollectorType kOptionalDataCollectors[] = {
support_tool::CHROMEOS_CROS_API, support_tool::CHROMEOS_LACROS};
// Returns the current time in UTCYYYY_MM_DD_HH_mm format.
std::string GetTimestampString(base::Time timestamp) {
base::Time::Exploded tex;
timestamp.UTCExplode(&tex);
return base::StringPrintf("UTC%04d%02d%02d_%02d%02d", tex.year, tex.month,
tex.day_of_month, tex.hour, tex.minute);
}
} // namespace
std::unique_ptr<SupportToolHandler> GetSupportToolHandler(
std::string case_id,
std::string email_address,
std::string issue_description,
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);
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:
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;
#if BUILDFLAG(IS_CHROMEOS_ASH)
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_CROS_API:
if (crosapi::BrowserManager::Get()->IsRunning() &&
crosapi::BrowserManager::Get()->GetFeedbackDataSupported()) {
handler->AddDataCollector(std::make_unique<
SystemLogSourceDataCollectorAdaptor>(
"Gets Lacros system information log data if Lacros is running "
"and the crosapi version supports the Lacros remote data source.",
std::make_unique<system_logs::CrosapiSystemLogSource>()));
}
break;
case support_tool::CHROMEOS_LACROS:
if (crosapi::browser_util::IsLacrosEnabled()) {
// Lacros logs are saved in the user data directory, so we provide
// that path to the LacrosLogFilesLogSource.
base::FilePath log_base_path =
crosapi::browser_util::GetUserDataDir();
std::string lacrosUserLogKey = "lacros_user_log";
handler->AddDataCollector(std::make_unique<
SystemLogSourceDataCollectorAdaptor>(
"Gets Lacros system information log data if Lacros is running "
"and the crosapi version supports the Lacros remote data source.",
std::make_unique<system_logs::LacrosLogFilesLogSource>(
log_base_path, lacrosUserLogKey)));
}
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_CHROME_USER_LOGS:
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_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_ASH)
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);
}
for (const auto& type : kOptionalDataCollectors) {
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_ASH)
for (const auto& type : kDataCollectorsChromeosAsh) {
data_collectors.push_back(type);
}
if (crosapi::browser_util::IsLacrosEnabled())
data_collectors.push_back(support_tool::CHROMEOS_LACROS);
if (crosapi::BrowserManager::Get()->IsRunning() &&
crosapi::BrowserManager::Get()->GetFeedbackDataSupported())
data_collectors.push_back(support_tool::CHROMEOS_CROS_API);
#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_ASH)
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 timestamp_string = GetTimestampString(timestamp);
std::string filename =
case_id.empty()
? base::StringPrintf("%s_%s", filename_prefix.c_str(),
timestamp_string.c_str())
: base::StringPrintf("%s_%s_%s", filename_prefix.c_str(),
case_id.c_str(), timestamp_string.c_str());
return target_directory.AppendASCII(filename);
}