blob: bb20d2de8c9e804b8304077a24acfa6a1ea2ef50 [file] [log] [blame]
// Copyright 2015 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/tracing/chrome_tracing_delegate.h"
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/json/values_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "base/trace_event/named_trigger.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_otr_state.h"
#include "chrome/common/pref_names.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/tracing/common/background_tracing_metrics_provider.h"
#include "components/tracing/common/background_tracing_state_manager.h"
#include "components/tracing/common/background_tracing_utils.h"
#include "components/tracing/common/system_profile_metadata_recorder.h"
#include "components/tracing/common/tracing_scenarios_config.h"
#include "components/variations/active_field_trials.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_thread.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/tracing/public/cpp/tracing_features.h"
#if BUILDFLAG(IS_ANDROID)
#include "chrome/browser/ui/android/tab_model/tab_model.h"
#include "chrome/browser/ui/android/tab_model/tab_model_list.h"
#else
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#endif
#if BUILDFLAG(IS_CHROMEOS)
#include "ash/constants/ash_pref_names.h"
#include "chromeos/dbus/constants/dbus_switches.h" // nogncheck
#endif
#if BUILDFLAG(IS_WIN)
#include "base/task/thread_pool.h"
#include "chrome/installer/util/system_tracing_util.h"
#endif
namespace {
using tracing::BackgroundTracingStateManager;
} // namespace
ChromeTracingDelegate::ChromeTracingDelegate() {
// Ensure that this code is called on the UI thread, except for
// tests where a UI thread might not have been initialized at this point.
DCHECK(
content::BrowserThread::CurrentlyOn(content::BrowserThread::UI) ||
!content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI));
#if !BUILDFLAG(IS_ANDROID)
BrowserList::AddObserver(this);
#else
TabModelList::AddObserver(this);
#endif
}
ChromeTracingDelegate::~ChromeTracingDelegate() {
CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
#if !BUILDFLAG(IS_ANDROID)
BrowserList::RemoveObserver(this);
#else
TabModelList::RemoveObserver(this);
#endif
}
#if BUILDFLAG(IS_ANDROID)
void ChromeTracingDelegate::OnTabModelAdded(TabModel* tab_model) {
for (const TabModel* model : TabModelList::models()) {
if (model->GetProfile()->IsOffTheRecord()) {
latest_incognito_launched_ = base::TimeTicks::Now();
base::trace_event::EmitNamedTrigger("incognito-start");
}
}
}
void ChromeTracingDelegate::OnTabModelRemoved(TabModel* tab_model) {
if (!IsOffTheRecordSessionActive()) {
base::trace_event::EmitNamedTrigger("incognito-end");
}
}
#else
void ChromeTracingDelegate::OnBrowserAdded(Browser* browser) {
if (browser->profile()->IsOffTheRecord()) {
latest_incognito_launched_ = base::TimeTicks::Now();
base::trace_event::EmitNamedTrigger("incognito-start");
}
}
void ChromeTracingDelegate::OnBrowserRemoved(Browser* browser) {
if (!IsOffTheRecordSessionActive()) {
base::trace_event::EmitNamedTrigger("incognito-end");
}
}
#endif // BUILDFLAG(IS_ANDROID)
bool ChromeTracingDelegate::IsRecordingAllowed(
bool requires_anonymized_data,
base::TimeTicks session_start) const {
// If the background tracing is specified on the command-line, we allow
// any scenario to be traced and uploaded.
if (!requires_anonymized_data) {
return true;
}
if (IsOffTheRecordSessionActive() ||
session_start <= latest_incognito_launched_) {
UMA_HISTOGRAM_ENUMERATION(
"Tracing.Background.FinalizationDisallowedReason",
TracingFinalizationDisallowedReason::kIncognitoLaunched);
return false;
}
return true;
}
bool ChromeTracingDelegate::ShouldSaveUnuploadedTrace() const {
return true;
}
std::unique_ptr<tracing::BackgroundTracingStateManager>
ChromeTracingDelegate::CreateStateManager() {
return tracing::BackgroundTracingStateManager::CreateInstance(
g_browser_process->local_state());
}
std::string ChromeTracingDelegate::RecordSerializedSystemProfileMetrics()
const {
metrics::SystemProfileProto system_profile_proto;
auto recorder = tracing::BackgroundTracingMetricsProvider::
GetSystemProfileMetricsRecorder();
if (!recorder) {
return std::string();
}
recorder.Run(system_profile_proto);
std::string serialized_system_profile;
system_profile_proto.SerializeToString(&serialized_system_profile);
return serialized_system_profile;
}
tracing::MetadataDataSource::BundleRecorder
ChromeTracingDelegate::CreateSystemProfileMetadataRecorder() const {
return base::BindRepeating(&tracing::RecordSystemProfileMetadata);
}
#if BUILDFLAG(IS_WIN)
void ChromeTracingDelegate::GetSystemTracingState(
base::OnceCallback<void(bool service_supported, bool service_enabled)>
on_tracing_state) {
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock{}},
base::BindOnce([]() -> std::pair<bool, bool> {
return {installer::IsSystemTracingServiceSupported(),
installer::IsSystemTracingServiceRegistered()};
}),
base::BindOnce(
[](base::OnceCallback<void(bool service_supported,
bool service_enabled)> on_tracing_state,
std::pair<bool, bool> state) {
std::move(on_tracing_state).Run(state.first, state.second);
},
std::move(on_tracing_state)));
}
void ChromeTracingDelegate::EnableSystemTracing(
base::OnceCallback<void(bool success)> on_complete) {
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock{}}, base::BindOnce([]() {
return installer::ElevateAndRegisterSystemTracingService();
}),
std::move(on_complete));
}
void ChromeTracingDelegate::DisableSystemTracing(
base::OnceCallback<void(bool success)> on_complete) {
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock{}}, base::BindOnce([]() {
return installer::ElevateAndDeregisterSystemTracingService();
}),
std::move(on_complete));
}
#endif // BUILDFLAG(IS_WIN)
bool ChromeTracingDelegate::IsSystemWideTracingEnabled() {
#if BUILDFLAG(IS_CHROMEOS)
// Always allow system tracing in dev mode images.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kSystemDevMode)) {
return true;
}
// In non-dev images, honor the pref for system-wide tracing.
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
return local_state->GetBoolean(ash::prefs::kDeviceSystemWideTracingEnabled);
#else
return false;
#endif
}