blob: 055edd679ecdd6312a7727f978187d44cb95fb37 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2015 The Chromium Authors
simonhatch0b016192015-05-22 19:14:022// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/tracing/background_tracing_manager_impl.h"
6
Arthur Sonzognic686e8f2024-01-11 08:36:377#include <optional>
dcheng36b6aec92015-12-26 06:16:368#include <utility>
9
oysteineb02d18092015-10-27 23:29:4210#include "base/command_line.h"
Alex Attar63ab3bd2023-07-11 19:31:4411#include "base/files/file_path.h"
Etienne Pierre-doray8563c892025-01-03 14:27:0512#include "base/functional/callback_helpers.h"
Oksana Zhuravlovae02027902020-10-27 18:44:3213#include "base/json/json_reader.h"
simonhatch0cc9fee2015-06-15 22:26:1914#include "base/json/json_writer.h"
fdoray7a8954a42016-06-07 04:28:3815#include "base/location.h"
Alex Attar63ab3bd2023-07-11 19:31:4416#include "base/memory/weak_ptr.h"
Yash Joshid3da59f02023-03-23 22:24:4817#include "base/metrics/field_trial_params.h"
Etienne Pierre-doray97f2a832024-04-05 15:55:5518#include "base/metrics/histogram_functions.h"
oysteine341f2fb2015-06-11 03:53:5319#include "base/metrics/histogram_macros.h"
Oystein Eftevaagf80452b2019-03-19 16:30:2220#include "base/no_destructor.h"
Alex Attar63ab3bd2023-07-11 19:31:4421#include "base/path_service.h"
Etienne Pierre-doray88cce9f2024-03-21 01:22:1722#include "base/strings/stringprintf.h"
Etienne Pierre-doray8563c892025-01-03 14:27:0523#include "base/task/bind_post_task.h"
Patrick Monette643cdf62021-10-15 19:13:4224#include "base/task/single_thread_task_runner.h"
Alex Attar63ab3bd2023-07-11 19:31:4425#include "base/threading/sequence_bound.h"
fmeawad743fcdf2015-06-03 23:55:3426#include "base/time/time.h"
Etienne Pierre-doray67d80192024-11-14 21:52:4727#include "base/tracing/trace_time.h"
Alex Attar63ab3bd2023-07-11 19:31:4428#include "base/uuid.h"
Ehsan Chiniforooshanc77b44e2017-10-10 18:12:1029#include "base/values.h"
ssid3e8879002020-06-11 08:23:5630#include "build/build_config.h"
Etienne Pierre-doray3dc2c7dc2025-06-12 12:06:3331#include "components/tracing/common/background_tracing_state_manager.h"
Etienne Pierre-doray358170f2024-01-09 17:01:2032#include "components/variations/hashing.h"
Darin Fisherc23ee1a2019-06-05 23:26:3033#include "content/browser/tracing/background_tracing_agent_client_impl.h"
oysteinef4ce0b062015-08-26 01:33:0634#include "content/browser/tracing/background_tracing_rule.h"
Etienne Pierre-doray6db6af4f2025-06-05 14:20:5935#include "content/browser/tracing/trace_report_database.h"
36#include "content/browser/tracing/trace_upload_list.h"
caseq2fe929b2016-07-13 20:23:1237#include "content/browser/tracing/tracing_controller_impl.h"
Etienne Pierre-doray23fe82c52024-11-25 17:57:4638#include "content/browser/tracing/triggers_data_source.h"
Ken Rockot62fb4352019-07-18 16:03:3839#include "content/common/child_process.mojom.h"
Darin Fisherc23ee1a2019-06-05 23:26:3040#include "content/public/browser/browser_child_process_host.h"
Eric Seckler8652dcd52018-09-20 10:42:2841#include "content/public/browser/browser_task_traits.h"
simonhatch0b016192015-05-22 19:14:0242#include "content/public/browser/browser_thread.h"
Darin Fisherc23ee1a2019-06-05 23:26:3043#include "content/public/browser/child_process_data.h"
Will Harriscd57b832023-01-05 20:03:1044#include "content/public/browser/child_process_host.h"
oysteine386fc9e2015-06-07 18:45:4145#include "content/public/browser/content_browser_client.h"
Darin Fisherc23ee1a2019-06-05 23:26:3046#include "content/public/browser/render_process_host.h"
oysteine386fc9e2015-06-07 18:45:4147#include "content/public/common/content_client.h"
oysteineb02d18092015-10-27 23:29:4248#include "content/public/common/content_switches.h"
Etienne Pierre-doray917135d2023-08-01 19:11:3849#include "net/base/network_change_notifier.h"
Etienne Pierre-dorayf3fd9e82024-06-12 16:40:3550#include "services/tracing/public/cpp/trace_startup_config.h"
Oystein Eftevaag2f3043e2019-03-12 18:25:3251#include "services/tracing/public/cpp/tracing_features.h"
Etienne Pierre-doraybd38b0752023-09-05 22:42:4652#include "third_party/zlib/google/compression_utils.h"
simonhatch0b016192015-05-22 19:14:0253
54namespace content {
55
Chris Hamilton4ec6fd312021-03-16 01:02:4056namespace {
Etienne Pierre-dorayd05d46c2024-05-24 17:13:1057// The time to live of a trace report is currently 14 days.
Etienne Pierre-dorayf8f587c2024-12-06 19:39:0058constexpr base::TimeDelta kTraceReportTimeToLive = base::Days(14);
59// The time to live of uploaded trace content is 2 days.
60constexpr base::TimeDelta kUploadedTraceContentTimeToLive = base::Days(2);
Etienne Pierre-doray064c03402024-08-22 20:17:1761// We limit the overall number of traces.
Etienne Pierre-dorayf8f587c2024-12-06 19:39:0062constexpr size_t kMaxTraceContent = 200;
Etienne Pierre-doray98ecab42023-09-25 17:35:5863// We limit uploads of 1 trace per scenario over a period of 7 days. Since
64// traces live in the database for longer than 7 days, their TTL doesn't affect
65// this unless the database is manually cleared.
Etienne Pierre-dorayf8f587c2024-12-06 19:39:0066constexpr base::TimeDelta kMinTimeUntilNextUpload = base::Days(7);
Etienne Pierre-doray98ecab42023-09-25 17:35:5867// We limit the overall number of traces per scenario saved to the database at
Etienne Pierre-doray064c03402024-08-22 20:17:1768// 100 per day.
Etienne Pierre-dorayf8f587c2024-12-06 19:39:0069constexpr size_t kMaxTracesPerScenario = 100;
70constexpr base::TimeDelta kMaxTracesPerScenarioDuration = base::Days(1);
Chris Hamilton4ec6fd312021-03-16 01:02:4071
Etienne Pierre-doray44477e152023-07-05 14:18:2772// |g_background_tracing_manager| is intentionally leaked on shutdown.
73BackgroundTracingManager* g_background_tracing_manager = nullptr;
74BackgroundTracingManagerImpl* g_background_tracing_manager_impl = nullptr;
75
Etienne Pierre-doraybd38b0752023-09-05 22:42:4676void OpenDatabaseOnDatabaseTaskRunner(
77 TraceReportDatabase* database,
Arthur Sonzognic686e8f2024-01-11 08:36:3778 std::optional<base::FilePath> database_dir,
Etienne Pierre-doray3bb781fd82023-09-18 14:55:0979 base::OnceCallback<void(BackgroundTracingManagerImpl::ScenarioCountMap,
Arthur Sonzognic686e8f2024-01-11 08:36:3780 std::optional<BaseTraceReport>,
Etienne Pierre-doray3bb781fd82023-09-18 14:55:0981 bool)> on_database_created) {
Etienne Pierre-doray6fe98bd2023-09-06 19:41:1882 if (database->is_initialized()) {
83 return;
84 }
Etienne Pierre-doraybd38b0752023-09-05 22:42:4685 bool success;
86 if (!database_dir) {
87 success = database->OpenDatabaseInMemoryForTesting(); // IN-TEST
88 } else {
89 success = database->OpenDatabase(*database_dir);
90 }
Etienne Pierre-dorayb47f90712024-10-31 16:38:0091 std::optional<NewTraceReport> report_to_upload =
92 database->GetNextReportPendingUpload();
Etienne Pierre-doraybd38b0752023-09-05 22:42:4693 GetUIThreadTaskRunner({})->PostTask(
Etienne Pierre-dorayd05d46c2024-05-24 17:13:1094 FROM_HERE,
95 base::BindOnce(std::move(on_database_created),
96 database->GetScenarioCountsSince(
97 base::Time::Now() - kMaxTracesPerScenarioDuration),
98 std::move(report_to_upload), success));
Etienne Pierre-doraybd38b0752023-09-05 22:42:4699}
100
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09101void AddTraceOnDatabaseTaskRunner(
Etienne Pierre-doraybd38b0752023-09-05 22:42:46102 TraceReportDatabase* database,
103 std::string&& serialized_trace,
Etienne Pierre-dorayf56901822023-09-22 19:54:12104 std::string&& serialized_system_profile,
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09105 BaseTraceReport base_report,
Etienne Pierre-doray98ecab42023-09-25 17:35:58106 bool should_save_trace,
Etienne Pierre-doray749ed49c2024-10-15 18:19:13107 bool force_upload,
Etienne Pierre-doray8563c892025-01-03 14:27:05108 base::OnceCallback<void(std::optional<BaseTraceReport>, bool)>
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09109 on_trace_saved) {
110 if (!database->is_initialized()) {
111 return;
112 }
Etienne Pierre-doray98ecab42023-09-25 17:35:58113 base::Time since = base::Time::Now() - kMinTimeUntilNextUpload;
Etienne Pierre-doray1415b38932025-02-07 15:39:44114 auto upload_count = database->UploadCountSince(
115 base_report.scenario_name, base_report.upload_rule_name, since);
Etienne Pierre-doray749ed49c2024-10-15 18:19:13116 if (base_report.skip_reason == SkipUploadReason::kNoSkip && !force_upload &&
117 upload_count && *upload_count > 0) {
Etienne Pierre-doray98ecab42023-09-25 17:35:58118 base_report.skip_reason = SkipUploadReason::kScenarioQuotaExceeded;
119 if (!should_save_trace) {
120 return;
121 }
122 }
123
Etienne Pierre-doraybd38b0752023-09-05 22:42:46124 std::string compressed_trace;
125 bool success = compression::GzipCompress(serialized_trace, &compressed_trace);
126 if (success) {
Etienne Pierre-dorayb47f90712024-10-31 16:38:00127 NewTraceReport trace_report = base_report;
128 trace_report.trace_content = std::move(compressed_trace);
129 trace_report.system_profile = std::move(serialized_system_profile);
130 success = database->AddTrace(trace_report);
Etienne Pierre-doray98ecab42023-09-25 17:35:58131 }
Etienne Pierre-dorayb47f90712024-10-31 16:38:00132 auto report_to_upload = database->GetNextReportPendingUpload();
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09133 GetUIThreadTaskRunner({})->PostTask(
Etienne Pierre-doray98ecab42023-09-25 17:35:58134 FROM_HERE, base::BindOnce(std::move(on_trace_saved),
135 std::move(report_to_upload), success));
Etienne Pierre-doraybd38b0752023-09-05 22:42:46136}
137
Etienne Pierre-doray8563c892025-01-03 14:27:05138void OnUploadCompleteOnDatabaseTaskRunner(
139 TraceReportDatabase* database,
140 BaseTraceReport base_report,
141 base::OnceCallback<void(std::optional<BaseTraceReport>, bool)>
142 on_finalize_complete) {
143 base::Token uuid = base_report.uuid;
144 base::UmaHistogramSparse("Tracing.Background.Scenario.Upload",
145 variations::HashName(base_report.scenario_name));
146 std::optional<ClientTraceReport> next_report;
147 if (database->UploadComplete(uuid, base::Time::Now())) {
148 next_report = database->GetNextReportPendingUpload();
149 }
150 GetUIThreadTaskRunner({})->PostTask(
151 FROM_HERE, base::BindOnce(std::move(on_finalize_complete),
152 std::move(next_report), true));
153}
154
Etienne Pierre-doraybd38b0752023-09-05 22:42:46155void GetProtoValueOnDatabaseTaskRunner(
156 TraceReportDatabase* database,
Etienne Pierre-doray3d11c68d2024-11-15 17:51:57157 BaseTraceReport base_report,
Arthur Sonzognic686e8f2024-01-11 08:36:37158 base::OnceCallback<void(std::optional<std::string>,
Etienne Pierre-doray8563c892025-01-03 14:27:05159 std::optional<std::string>,
160 base::OnceClosure)> receive_callback,
161 base::OnceClosure upload_complete) {
Etienne Pierre-doray3d11c68d2024-11-15 17:51:57162 base::Token uuid = base_report.uuid;
Etienne Pierre-doray8563c892025-01-03 14:27:05163 auto compressed_trace_content = database->GetTraceContent(uuid);
164 if (!compressed_trace_content) {
165 std::move(receive_callback)
166 .Run(std::nullopt, std::nullopt, base::NullCallback());
167 } else {
168 auto serialized_system_profile = database->GetSystemProfile(uuid);
169 std::move(receive_callback)
170 .Run(std::move(compressed_trace_content),
171 std::move(serialized_system_profile), std::move(upload_complete));
Etienne Pierre-doraybd38b0752023-09-05 22:42:46172 }
Etienne Pierre-doraybd38b0752023-09-05 22:42:46173}
174
Etienne Pierre-doray0af80e72024-06-28 18:25:29175class PreferenceManagerImpl
176 : public BackgroundTracingManagerImpl::PreferenceManager {
177 public:
178 bool GetBackgroundStartupTracingEnabled() const override {
179 return tracing::TraceStartupConfig::GetInstance().IsEnabled() &&
180 tracing::TraceStartupConfig::GetInstance().GetSessionOwner() ==
181 tracing::TraceStartupConfig::SessionOwner::kBackgroundTracing;
182 }
183};
184
Etienne Pierre-doray67d80192024-11-14 21:52:47185// Emits background tracing metadata as a data source.
186class BackgroundMetadataDataSource
187 : public perfetto::DataSource<BackgroundMetadataDataSource> {
188 public:
Etienne Pierre-dorayf5a089b2025-03-03 15:16:19189 static constexpr bool kRequiresCallbacksUnderLock = false;
190
Etienne Pierre-doray67d80192024-11-14 21:52:47191 static void Register() {
192 perfetto::DataSourceDescriptor desc;
193 desc.set_name("org.chromium.background_scenario_metadata");
Etienne Pierre-doray9676d6032025-01-21 16:44:25194 CHECK(perfetto::DataSource<BackgroundMetadataDataSource>::Register(desc));
Etienne Pierre-doray67d80192024-11-14 21:52:47195 }
196
197 static void EmitMetadata(TracingScenario* scenario) {
198 Trace([&](TraceContext ctx) {
199 auto packet = ctx.NewTracePacket();
200 packet->set_timestamp(
201 TRACE_TIME_TICKS_NOW().since_origin().InNanoseconds());
202 packet->set_timestamp_clock_id(base::tracing::kTraceClockId);
203 auto* chrome_metadata = packet->set_chrome_metadata();
204 scenario->GenerateMetadataProto(chrome_metadata);
Etienne Pierre-dorayf5a089b2025-03-03 15:16:19205 packet->Finalize();
206 ctx.Flush();
Etienne Pierre-doray67d80192024-11-14 21:52:47207 });
208 }
209};
210
Chris Hamilton4ec6fd312021-03-16 01:02:40211} // namespace
212
213// static
Etienne Pierre-doray44477e152023-07-05 14:18:27214std::unique_ptr<BackgroundTracingManager>
Etienne Pierre-doray3dc2c7dc2025-06-12 12:06:33215BackgroundTracingManager::CreateInstance(TracingDelegate* delegate) {
216 return std::make_unique<BackgroundTracingManagerImpl>(delegate);
Etienne Pierre-doray44477e152023-07-05 14:18:27217}
218
219// static
Oksana Zhuravlova872a5a6f2022-06-08 18:15:29220BackgroundTracingManager& BackgroundTracingManager::GetInstance() {
Etienne Pierre-doray44477e152023-07-05 14:18:27221 CHECK_NE(nullptr, g_background_tracing_manager);
222 return *g_background_tracing_manager;
223}
224
225// static
226void BackgroundTracingManager::SetInstance(
227 BackgroundTracingManager* tracing_manager) {
228 DCHECK(g_background_tracing_manager == nullptr || tracing_manager == nullptr);
229 g_background_tracing_manager = tracing_manager;
230}
231
232// static
Oystein Eftevaagf80452b2019-03-19 16:30:22233void BackgroundTracingManagerImpl::RecordMetric(Metrics metric) {
oysteine341f2fb2015-06-11 03:53:53234 UMA_HISTOGRAM_ENUMERATION("Tracing.Background.ScenarioState", metric,
Oystein Eftevaagf80452b2019-03-19 16:30:22235 Metrics::NUMBER_OF_BACKGROUND_TRACING_METRICS);
oysteine341f2fb2015-06-11 03:53:53236}
237
Oystein Eftevaagf80452b2019-03-19 16:30:22238// static
Oksana Zhuravlova872a5a6f2022-06-08 18:15:29239BackgroundTracingManagerImpl& BackgroundTracingManagerImpl::GetInstance() {
Etienne Pierre-doray44477e152023-07-05 14:18:27240 CHECK_NE(nullptr, g_background_tracing_manager_impl);
241 return *g_background_tracing_manager_impl;
simonhatch0b016192015-05-22 19:14:02242}
243
Darin Fisherc23ee1a2019-06-05 23:26:30244// static
245void BackgroundTracingManagerImpl::ActivateForProcess(
Darin Fisher0e4fc2e2019-06-13 02:19:18246 int child_process_id,
Ken Rockot62fb4352019-07-18 16:03:38247 mojom::ChildProcess* child_process) {
Darin Fisher53ceb18292019-06-21 22:26:15248 // NOTE: Called from any thread.
249
Darin Fisher0e4fc2e2019-06-13 02:19:18250 mojo::PendingRemote<tracing::mojom::BackgroundTracingAgentProvider>
251 pending_provider;
Ken Rockot62fb4352019-07-18 16:03:38252 child_process->GetBackgroundTracingAgentProvider(
Darin Fisher0e4fc2e2019-06-13 02:19:18253 pending_provider.InitWithNewPipeAndPassReceiver());
Darin Fisherc23ee1a2019-06-05 23:26:30254
Gabriel Charettee7cdc5cd2020-05-27 23:35:05255 GetUIThreadTaskRunner({})->PostTask(
256 FROM_HERE, base::BindOnce(&BackgroundTracingManagerImpl::AddPendingAgent,
Wanchang Ryu342162a2020-02-27 19:31:25257 child_process_id, std::move(pending_provider)));
Darin Fisherc23ee1a2019-06-05 23:26:30258}
259
Etienne Pierre-doray3dc2c7dc2025-06-12 12:06:33260BackgroundTracingManagerImpl::BackgroundTracingManagerImpl(
261 TracingDelegate* delegate)
262 : delegate_(delegate),
263 state_manager_(delegate_->CreateStateManager()),
Alex Attar9e640b22023-08-25 14:44:06264 database_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
Alex Attar63ab3bd2023-07-11 19:31:44265 {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
Alex Attar9e640b22023-08-25 14:44:06266 base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
Etienne Pierre-doray6fe98bd2023-09-06 19:41:18267 trace_database_(nullptr,
Alex Attar9e640b22023-08-25 14:44:06268 base::OnTaskRunnerDeleter(database_task_runner_)) {
Etienne Pierre-doray6b4f7842024-02-15 18:34:01269 BackgroundTracingManager::SetInstance(this);
270 NamedTriggerManager::SetInstance(this);
Etienne Pierre-doray44477e152023-07-05 14:18:27271 g_background_tracing_manager_impl = this;
Etienne Pierre-doray0af80e72024-06-28 18:25:29272 preferences_ = std::make_unique<PreferenceManagerImpl>();
Etienne Pierre-doray9676d6032025-01-21 16:44:25273 if (perfetto::Tracing::IsInitialized()) {
274 AddMetadataGeneratorFunction();
275 }
ssideb549622017-03-29 21:46:00276}
simonhatch0b016192015-05-22 19:14:02277
Etienne Pierre-doray44477e152023-07-05 14:18:27278BackgroundTracingManagerImpl::~BackgroundTracingManagerImpl() {
279 DCHECK_EQ(this, g_background_tracing_manager_impl);
Etienne Pierre-doray45af1502025-02-26 15:57:05280 DisableScenarios();
Etienne Pierre-doray6b4f7842024-02-15 18:34:01281 BackgroundTracingManager::SetInstance(nullptr);
282 NamedTriggerManager::SetInstance(nullptr);
Etienne Pierre-doray44477e152023-07-05 14:18:27283 g_background_tracing_manager_impl = nullptr;
284}
simonhatch0b016192015-05-22 19:14:02285
Alex Attarb962f1a2023-09-06 17:12:23286void BackgroundTracingManagerImpl::OpenDatabaseIfExists() {
Etienne Pierre-doray6fe98bd2023-09-06 19:41:18287 if (trace_database_) {
Alex Attarb962f1a2023-09-06 17:12:23288 return;
289 }
Arthur Sonzognic686e8f2024-01-11 08:36:37290 std::optional<base::FilePath> database_dir =
Etienne Pierre-doray6fe98bd2023-09-06 19:41:18291 GetContentClient()->browser()->GetLocalTracesDirectory();
292 if (!database_dir.has_value()) {
293 return;
Alex Attarb962f1a2023-09-06 17:12:23294 }
Etienne Pierre-doray6fe98bd2023-09-06 19:41:18295 trace_database_ = {new TraceReportDatabase,
296 base::OnTaskRunnerDeleter(database_task_runner_)};
297 database_task_runner_->PostTask(
298 FROM_HERE,
299 base::BindOnce(
300 [](TraceReportDatabase* trace_database, base::FilePath path) {
301 trace_database->OpenDatabaseIfExists(path);
302 },
303 base::Unretained(trace_database_.get()), database_dir.value()));
Alex Attarb962f1a2023-09-06 17:12:23304}
305
306void BackgroundTracingManagerImpl::GetAllTraceReports(
307 GetReportsCallback callback) {
308 if (!trace_database_) {
309 std::move(callback).Run({});
310 return;
311 }
312
313 database_task_runner_->PostTaskAndReplyWithResult(
314 FROM_HERE,
315 base::BindOnce(&TraceReportDatabase::GetAllReports,
316 base::Unretained(trace_database_.get())),
317 std::move(callback));
318}
319
320void BackgroundTracingManagerImpl::DeleteSingleTrace(
Alex Attar3c0b1af02023-09-21 15:16:53321 const base::Token& trace_uuid,
322 FinishedProcessingCallback callback) {
Alex Attarb962f1a2023-09-06 17:12:23323 if (!trace_database_) {
324 std::move(callback).Run(false);
325 return;
326 }
327
328 database_task_runner_->PostTaskAndReplyWithResult(
329 FROM_HERE,
330 base::BindOnce(&TraceReportDatabase::DeleteTrace,
331 base::Unretained(trace_database_.get()), trace_uuid),
332 std::move(callback));
333}
334
335void BackgroundTracingManagerImpl::DeleteAllTraces(
Jose Dapena Pazb19e9662023-09-15 06:47:24336 TraceUploadList::FinishedProcessingCallback callback) {
Alex Attarb962f1a2023-09-06 17:12:23337 if (!trace_database_) {
338 std::move(callback).Run(false);
339 return;
340 }
341
342 database_task_runner_->PostTaskAndReplyWithResult(
343 FROM_HERE,
344 base::BindOnce(&TraceReportDatabase::DeleteAllTraces,
345 base::Unretained(trace_database_.get())),
346 std::move(callback));
347}
348
349void BackgroundTracingManagerImpl::UserUploadSingleTrace(
Alex Attar3c0b1af02023-09-21 15:16:53350 const base::Token& trace_uuid,
Jose Dapena Pazb19e9662023-09-15 06:47:24351 TraceUploadList::FinishedProcessingCallback callback) {
Alex Attarb962f1a2023-09-06 17:12:23352 if (!trace_database_) {
353 std::move(callback).Run(false);
354 return;
355 }
356
357 database_task_runner_->PostTaskAndReplyWithResult(
358 FROM_HERE,
359 base::BindOnce(&TraceReportDatabase::UserRequestedUpload,
360 base::Unretained(trace_database_.get()), trace_uuid),
361 std::move(callback));
362}
363
Alex Attar3c0b1af02023-09-21 15:16:53364void BackgroundTracingManagerImpl::DownloadTrace(const base::Token& trace_uuid,
Alex Attarb962f1a2023-09-06 17:12:23365 GetProtoCallback callback) {
366 if (!trace_database_) {
Arthur Sonzognic686e8f2024-01-11 08:36:37367 std::move(callback).Run(std::nullopt);
Alex Attarb962f1a2023-09-06 17:12:23368 return;
369 }
370
371 database_task_runner_->PostTaskAndReplyWithResult(
372 FROM_HERE,
Etienne Pierre-dorayf56901822023-09-22 19:54:12373 base::BindOnce(&TraceReportDatabase::GetTraceContent,
Alex Attarb962f1a2023-09-06 17:12:23374 base::Unretained(trace_database_.get()), trace_uuid),
Alex Attar3d5802d2023-09-13 14:47:44375 base::BindOnce(
376 [](GetProtoCallback callback,
Arthur Sonzognic686e8f2024-01-11 08:36:37377 const std::optional<std::string>& result) {
Alex Attar3d5802d2023-09-13 14:47:44378 if (result) {
379 std::move(callback).Run(base::span<const char>(*result));
380 } else {
Arthur Sonzognic686e8f2024-01-11 08:36:37381 std::move(callback).Run(std::nullopt);
Alex Attar3d5802d2023-09-13 14:47:44382 }
383 },
384 std::move(callback)));
Alex Attarb962f1a2023-09-06 17:12:23385}
386
Alex Attar63ab3bd2023-07-11 19:31:44387void BackgroundTracingManagerImpl::OnTraceDatabaseCreated(
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09388 ScenarioCountMap scenario_saved_counts,
Arthur Sonzognic686e8f2024-01-11 08:36:37389 std::optional<BaseTraceReport> trace_to_upload,
Alex Attar63ab3bd2023-07-11 19:31:44390 bool creation_result) {
391 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09392 scenario_saved_counts_ = std::move(scenario_saved_counts);
Etienne Pierre-doraybd38b0752023-09-05 22:42:46393 trace_report_to_upload_ = std::move(trace_to_upload);
Alex Attar63ab3bd2023-07-11 19:31:44394 if (!creation_result) {
395 RecordMetric(Metrics::DATABASE_INITIALIZATION_FAILED);
Alex Attarcc5eebb2023-08-11 16:35:55396 return;
Alex Attar63ab3bd2023-07-11 19:31:44397 }
Etienne Pierre-dorayd05d46c2024-05-24 17:13:10398 CleanDatabase();
Alex Attarcc5eebb2023-08-11 16:35:55399 clean_database_timer_.Start(
400 FROM_HERE, base::Days(1),
401 base::BindRepeating(&BackgroundTracingManagerImpl::CleanDatabase,
402 weak_factory_.GetWeakPtr()));
Alex Attar63ab3bd2023-07-11 19:31:44403}
404
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09405void BackgroundTracingManagerImpl::OnTraceDatabaseUpdated(
406 ScenarioCountMap scenario_saved_counts) {
Etienne Pierre-doraybd38b0752023-09-05 22:42:46407 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09408 scenario_saved_counts_ = std::move(scenario_saved_counts);
409}
410
411void BackgroundTracingManagerImpl::OnTraceSaved(
412 const std::string& scenario_name,
Etienne Pierre-doray8563c892025-01-03 14:27:05413 std::optional<BaseTraceReport> trace_to_upload,
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09414 bool success) {
415 DCHECK_CURRENTLY_ON(BrowserThread::UI);
416 RecordMetric(success ? Metrics::SAVE_TRACE_SUCCEEDED
417 : Metrics::SAVE_TRACE_FAILED);
Etienne Pierre-doraybd38b0752023-09-05 22:42:46418 trace_report_to_upload_ = std::move(trace_to_upload);
Etienne Pierre-doray98ecab42023-09-25 17:35:58419 if (success) {
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09420 ++scenario_saved_counts_[scenario_name];
421 }
Ali Hijazi133b2d92024-02-09 14:01:52422 for (EnabledStateTestObserver* observer : background_tracing_observers_) {
Etienne Pierre-doraybd38b0752023-09-05 22:42:46423 observer->OnTraceSaved();
424 }
425}
426
Ehsan Chiniforooshanc77b44e2017-10-10 18:12:10427void BackgroundTracingManagerImpl::AddMetadataGeneratorFunction() {
Etienne Pierre-doray67d80192024-11-14 21:52:47428 BackgroundMetadataDataSource::Register();
Etienne Pierre-doray23fe82c52024-11-25 17:57:46429 TriggersDataSource::Register();
Ehsan Chiniforooshanc77b44e2017-10-10 18:12:10430}
431
Etienne Pierre-doray825d20a12023-07-10 18:24:44432bool BackgroundTracingManagerImpl::RequestActivateScenario() {
433 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Etienne Pierre-doray825d20a12023-07-10 18:24:44434 // Multi-scenarios sessions can't be initialized twice.
Etienne Pierre-doray89055052024-04-02 19:51:39435 DCHECK(field_scenarios_.empty());
Etienne Pierre-doray45af1502025-02-26 15:57:05436 DCHECK(enabled_scenarios_.empty());
437 RecordMetric(Metrics::SCENARIO_ACTIVATION_REQUESTED);
Etienne Pierre-doray825d20a12023-07-10 18:24:44438
Etienne Pierre-doraya83afef2024-04-17 16:49:38439 // Bail on scenario activation if trigger rules are already setup to be
440 // forwarded to system tracing.
441 if (!trigger_rules_.empty()) {
442 return false;
443 }
Etienne Pierre-doray825d20a12023-07-10 18:24:44444
445 // If we don't have a high resolution timer available, traces will be
446 // too inaccurate to be useful.
447 if (!base::TimeTicks::IsHighResolution()) {
448 RecordMetric(Metrics::SCENARIO_ACTION_FAILED_LOWRES_CLOCK);
449 return false;
450 }
451 return true;
452}
453
Etienne Pierre-doray45af1502025-02-26 15:57:05454void BackgroundTracingManagerImpl::DisableScenarios() {
455 if (active_scenario_) {
456 enabled_scenarios_.clear();
457 active_scenario_->Abort();
458 } else {
459 for (auto& scenario : enabled_scenarios_) {
460 scenario->Disable();
461 }
462 enabled_scenarios_.clear();
463 }
464 for (auto& rule : trigger_rules_) {
465 rule->Uninstall();
466 }
467 trigger_rules_.clear();
468}
469
Etienne Pierre-doray69e93612023-09-18 21:39:33470void BackgroundTracingManagerImpl::SetReceiveCallback(
471 ReceiveCallback receive_callback) {
472 receive_callback_ = std::move(receive_callback);
473}
474
Etienne Pierre-doraya83afef2024-04-17 16:49:38475bool BackgroundTracingManagerImpl::InitializePerfettoTriggerRules(
476 const perfetto::protos::gen::TracingTriggerRulesConfig& config) {
477 DCHECK_CURRENTLY_ON(BrowserThread::UI);
478 // Trigger rules can't be initialized twice.
479 DCHECK(trigger_rules_.empty());
Etienne Pierre-doraya83afef2024-04-17 16:49:38480
481 // Bail on setting up trigger rules if scenarios are already enabled.
482 if (!enabled_scenarios_.empty()) {
483 return false;
484 }
485
486 if (!BackgroundTracingRule::Append(config.rules(), trigger_rules_)) {
487 return false;
488 }
489 for (auto& rule : trigger_rules_) {
490 rule->Install(base::BindRepeating([](const BackgroundTracingRule* rule) {
Etienne Pierre-dorayb1a3a802024-07-16 16:33:54491 base::UmaHistogramSparse("Tracing.Background.Perfetto.Trigger",
Etienne Pierre-doraycf6f2442024-12-03 18:23:47492 variations::HashName(rule->rule_name()));
493 perfetto::Tracing::ActivateTriggers({rule->rule_name()},
Etienne Pierre-doraya83afef2024-04-17 16:49:38494 /*ttl_ms=*/0);
495 return true;
496 }));
497 }
498 return true;
499}
500
Etienne Pierre-doray89055052024-04-02 19:51:39501bool BackgroundTracingManagerImpl::InitializeFieldScenarios(
Etienne Pierre-doray825d20a12023-07-10 18:24:44502 const perfetto::protos::gen::ChromeFieldTracingConfig& config,
Etienne Pierre-doray749ed49c2024-10-15 18:19:13503 DataFiltering data_filtering,
504 bool force_uploads,
505 size_t upload_limit_kb) {
Etienne Pierre-doray825d20a12023-07-10 18:24:44506 DCHECK_CURRENTLY_ON(BrowserThread::UI);
507 if (!RequestActivateScenario()) {
508 return false;
509 }
Etienne Pierre-doray749ed49c2024-10-15 18:19:13510 force_uploads_ = force_uploads;
511 if (upload_limit_kb > 0) {
512 upload_limit_kb_ = upload_limit_kb;
513 }
Etienne Pierre-doray825d20a12023-07-10 18:24:44514
Etienne Pierre-doray89055052024-04-02 19:51:39515 bool requires_anonymized_data = (data_filtering != NO_DATA_FILTERING);
Etienne Pierre-doray72caf352023-09-28 04:05:06516 bool enable_package_name_filter =
517 (data_filtering == ANONYMIZE_DATA_AND_FILTER_PACKAGE_NAME);
Alex Attar63ab3bd2023-07-11 19:31:44518 InitializeTraceReportDatabase();
519
Etienne Pierre-doray0af80e72024-06-28 18:25:29520 if (preferences_->GetBackgroundStartupTracingEnabled()) {
521 perfetto::protos::gen::ScenarioConfig scenario_config;
522 scenario_config.set_scenario_name("Startup");
523 *scenario_config.mutable_trace_config() =
524 tracing::TraceStartupConfig::GetDefaultBackgroundStartupConfig();
525 scenario_config.add_start_rules()->set_manual_trigger_name(
526 base::trace_event::kStartupTracingTriggerName);
527 scenario_config.add_upload_rules()->set_delay_ms(30000);
528
529 // Startup tracing was already requested earlier for this scenario.
530 auto startup_scenario = TracingScenario::Create(
531 scenario_config, requires_anonymized_data, enable_package_name_filter,
Etienne Pierre-dorayffeda342024-11-05 21:47:47532 /*is_local_scenario=*/false,
Etienne Pierre-doray0af80e72024-06-28 18:25:29533 /*request_startup_tracing=*/false, this);
534 field_scenarios_.push_back(std::move(startup_scenario));
535 enabled_scenarios_.push_back(field_scenarios_.back().get());
536 enabled_scenarios_.back()->Enable();
537 }
538
Etienne Pierre-doraye2c7dd82025-04-17 16:57:37539 bool result = true;
Etienne Pierre-doray825d20a12023-07-10 18:24:44540 for (const auto& scenario_config : config.scenarios()) {
Etienne Pierre-dorayffeda342024-11-05 21:47:47541 auto scenario = TracingScenario::Create(
542 scenario_config, requires_anonymized_data,
543 /*is_local_scenario=*/false, enable_package_name_filter, true, this);
Etienne Pierre-doray825d20a12023-07-10 18:24:44544 if (!scenario) {
Etienne Pierre-doraye2c7dd82025-04-17 16:57:37545 base::UmaHistogramSparse(
546 "Tracing.Background.Scenario.Invalid",
547 variations::HashName(scenario_config.scenario_name()));
548 result = false;
549 continue;
Etienne Pierre-doray825d20a12023-07-10 18:24:44550 }
Etienne Pierre-doray89055052024-04-02 19:51:39551 field_scenarios_.push_back(std::move(scenario));
552 enabled_scenarios_.push_back(field_scenarios_.back().get());
553 enabled_scenarios_.back()->Enable();
Etienne Pierre-doray825d20a12023-07-10 18:24:44554 }
Etienne Pierre-doray09609102024-10-11 13:16:04555 MaybeConstructPendingAgents();
Etienne Pierre-doray825d20a12023-07-10 18:24:44556 RecordMetric(Metrics::SCENARIO_ACTIVATED_SUCCESSFULLY);
Etienne Pierre-doraye2c7dd82025-04-17 16:57:37557 return result;
Etienne Pierre-doray825d20a12023-07-10 18:24:44558}
559
Etienne Pierre-doray89055052024-04-02 19:51:39560std::vector<std::string> BackgroundTracingManagerImpl::AddPresetScenarios(
561 const perfetto::protos::gen::ChromeFieldTracingConfig& config,
562 DataFiltering data_filtering) {
Etienne Pierre-doraybc32597e2025-04-22 14:12:57563 return AddPresetScenariosImpl(config, data_filtering, false);
564}
565
566std::vector<std::string> BackgroundTracingManagerImpl::OverwritePresetScenarios(
567 const perfetto::protos::gen::ChromeFieldTracingConfig& config,
568 DataFiltering data_filtering) {
569 return AddPresetScenariosImpl(config, data_filtering, true);
570}
571
572std::vector<std::string> BackgroundTracingManagerImpl::AddPresetScenariosImpl(
573 const perfetto::protos::gen::ChromeFieldTracingConfig& config,
574 DataFiltering data_filtering,
575 bool overwrite_conflicts) {
Etienne Pierre-doray89055052024-04-02 19:51:39576 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Etienne Pierre-doray45af1502025-02-26 15:57:05577
Etienne Pierre-doray89055052024-04-02 19:51:39578 bool enable_privacy_filter = (data_filtering != NO_DATA_FILTERING);
579 bool enable_package_name_filter =
580 (data_filtering == ANONYMIZE_DATA_AND_FILTER_PACKAGE_NAME);
581
582 std::vector<std::string> added_scenarios;
Etienne Pierre-dorayb693f722025-06-18 21:50:03583 std::set<raw_ptr<TracingScenario>> conflicting_scenarios_set;
584 std::vector<std::unique_ptr<TracingScenario>> conflicting_scenarios;
Etienne Pierre-doray89055052024-04-02 19:51:39585 for (const auto& scenario_config : config.scenarios()) {
Etienne Pierre-doraybc32597e2025-04-22 14:12:57586 auto scenario = TracingScenario::Create(
587 scenario_config, enable_privacy_filter, /*is_local_scenario=*/true,
588 enable_package_name_filter, true, this);
589 if (!scenario) {
590 base::UmaHistogramSparse(
591 "Tracing.Background.Scenario.Invalid",
592 variations::HashName(scenario_config.scenario_name()));
593 continue;
594 }
595
Etienne Pierre-dorayb693f722025-06-18 21:50:03596 if (auto it = preset_scenarios_.find(scenario_config.scenario_name());
597 it != preset_scenarios_.end()) {
598 if (!overwrite_conflicts) {
599 continue;
600 }
601 if (active_scenario_ == it->second.get()) {
602 active_scenario_->Abort();
603 active_scenario_ = nullptr;
604 conflicting_scenarios_set.insert(it->second.get());
605 conflicting_scenarios.emplace_back(std::move(it->second));
606 } else if (it->second->current_state() !=
607 TracingScenario::State::kDisabled) {
608 it->second->Disable();
609 conflicting_scenarios_set.insert(it->second.get());
610 conflicting_scenarios.emplace_back(std::move(it->second));
611 }
612 }
613
Etienne Pierre-doray64748062025-01-28 21:15:34614 added_scenarios.push_back(scenario->scenario_name());
Etienne Pierre-doray45af1502025-02-26 15:57:05615 preset_scenarios_[scenario->scenario_name()] = std::move(scenario);
Etienne Pierre-doray89055052024-04-02 19:51:39616 }
Etienne Pierre-doray38837fbc2025-03-24 19:35:48617 if (!conflicting_scenarios.empty()) {
618 std::erase_if(enabled_scenarios_, [&](raw_ptr<TracingScenario> scenario) {
Etienne Pierre-dorayb693f722025-06-18 21:50:03619 return conflicting_scenarios_set.contains(scenario);
Etienne Pierre-doray38837fbc2025-03-24 19:35:48620 });
621 }
Etienne Pierre-dorayb693f722025-06-18 21:50:03622 conflicting_scenarios_set.clear();
Etienne Pierre-doray38837fbc2025-03-24 19:35:48623
Etienne Pierre-doray89055052024-04-02 19:51:39624 return added_scenarios;
625}
626
Etienne Pierre-doray6db6af4f2025-06-05 14:20:59627std::vector<traces_internals::mojom::ScenarioPtr>
Etienne Pierre-dorayc5029de2025-05-27 15:48:54628BackgroundTracingManagerImpl::GetAllScenarios() const {
Etienne Pierre-doray6db6af4f2025-06-05 14:20:59629 std::vector<traces_internals::mojom::ScenarioPtr> result;
Etienne Pierre-dorayc5029de2025-05-27 15:48:54630 auto toMojoScenario = [this](TracingScenario* scenario) {
Etienne Pierre-doray6db6af4f2025-06-05 14:20:59631 auto new_scenario = traces_internals::mojom::Scenario::New();
Etienne Pierre-doray48040912024-08-20 19:12:35632 new_scenario->scenario_name = scenario->scenario_name();
Etienne Pierre-dorayc5029de2025-05-27 15:48:54633 new_scenario->description = scenario->description();
634 new_scenario->is_local_scenario = scenario->is_local_scenario();
635 new_scenario->is_enabled = base::Contains(enabled_scenarios_, scenario);
636 new_scenario->current_state = scenario->current_state();
637 return new_scenario;
638 };
Etienne Pierre-doray89055052024-04-02 19:51:39639 for (const auto& scenario : preset_scenarios_) {
Etienne Pierre-dorayc5029de2025-05-27 15:48:54640 result.push_back(toMojoScenario(scenario.second.get()));
641 }
642 for (const auto& scenario : field_scenarios_) {
643 result.push_back(toMojoScenario(scenario.get()));
Etienne Pierre-doray89055052024-04-02 19:51:39644 }
645 return result;
646}
647
648bool BackgroundTracingManagerImpl::SetEnabledScenarios(
649 std::vector<std::string> enabled_scenarios) {
Etienne Pierre-doray45af1502025-02-26 15:57:05650 DisableScenarios();
Etienne Pierre-doray89055052024-04-02 19:51:39651 InitializeTraceReportDatabase();
652 for (const std::string& hash : enabled_scenarios) {
653 auto it = preset_scenarios_.find(hash);
654 if (it == preset_scenarios_.end()) {
655 return false;
656 }
657 enabled_scenarios_.push_back(it->second.get());
658 if (!active_scenario_) {
659 it->second->Enable();
660 }
661 }
Etienne Pierre-doray09609102024-10-11 13:16:04662 MaybeConstructPendingAgents();
Etienne Pierre-doray89055052024-04-02 19:51:39663 return true;
664}
665
666std::vector<std::string> BackgroundTracingManagerImpl::GetEnabledScenarios()
667 const {
668 std::vector<std::string> scenario_hashes;
669 for (auto scenario : enabled_scenarios_) {
Etienne Pierre-doray64748062025-01-28 21:15:34670 scenario_hashes.push_back(scenario->scenario_name());
Etienne Pierre-doray89055052024-04-02 19:51:39671 }
672 return scenario_hashes;
673}
674
Etienne Pierre-doraybd38b0752023-09-05 22:42:46675void BackgroundTracingManagerImpl::InitializeTraceReportDatabase(
676 bool open_in_memory) {
Arthur Sonzognic686e8f2024-01-11 08:36:37677 std::optional<base::FilePath> database_dir;
Etienne Pierre-doray6fe98bd2023-09-06 19:41:18678 if (!trace_database_) {
679 trace_database_ = {new TraceReportDatabase,
680 base::OnTaskRunnerDeleter(database_task_runner_)};
681 if (!open_in_memory) {
682 database_dir = GetContentClient()->browser()->GetLocalTracesDirectory();
683 if (!database_dir.has_value()) {
Arthur Sonzognic686e8f2024-01-11 08:36:37684 OnTraceDatabaseCreated({}, std::nullopt, false);
Etienne Pierre-doray6fe98bd2023-09-06 19:41:18685 return;
686 }
687 }
Alex Attar63ab3bd2023-07-11 19:31:44688 }
Etienne Pierre-doray6fe98bd2023-09-06 19:41:18689 database_task_runner_->PostTask(
690 FROM_HERE,
691 base::BindOnce(
692 OpenDatabaseOnDatabaseTaskRunner,
693 base::Unretained(trace_database_.get()), std::move(database_dir),
694 base::BindOnce(&BackgroundTracingManagerImpl::OnTraceDatabaseCreated,
695 weak_factory_.GetWeakPtr())));
Alex Attar63ab3bd2023-07-11 19:31:44696}
697
Etienne Pierre-doray98ecab42023-09-25 17:35:58698bool BackgroundTracingManagerImpl::OnScenarioActive(
Etienne Pierre-doray825d20a12023-07-10 18:24:44699 TracingScenario* active_scenario) {
700 DCHECK_EQ(active_scenario_, nullptr);
Etienne Pierre-doray98ecab42023-09-25 17:35:58701 if (GetScenarioSavedCount(active_scenario->scenario_name()) >=
702 kMaxTracesPerScenario) {
703 return false;
704 }
Etienne Pierre-dorayf704b172025-06-17 23:49:44705 auto now = base::TimeTicks::Now();
706 if (!delegate_->IsRecordingAllowed(active_scenario->privacy_filter_enabled(),
707 now)) {
Etienne Pierre-doray98ecab42023-09-25 17:35:58708 return false;
709 }
Etienne Pierre-dorayf704b172025-06-17 23:49:44710 scenario_start_time_ = now;
Etienne Pierre-doray825d20a12023-07-10 18:24:44711 active_scenario_ = active_scenario;
Etienne Pierre-doray97f2a832024-04-05 15:55:55712 base::UmaHistogramSparse(
713 "Tracing.Background.Scenario.Active",
714 variations::HashName(active_scenario->scenario_name()));
Ali Hijazi133b2d92024-02-09 14:01:52715 for (EnabledStateTestObserver* observer : background_tracing_observers_) {
Etienne Pierre-doray825d20a12023-07-10 18:24:44716 observer->OnScenarioActive(active_scenario_->scenario_name());
717 }
Etienne Pierre-doray89055052024-04-02 19:51:39718 for (auto& scenario : enabled_scenarios_) {
Etienne Pierre-doray825d20a12023-07-10 18:24:44719 if (scenario.get() == active_scenario) {
720 continue;
721 }
722 scenario->Disable();
723 }
Etienne Pierre-doray98ecab42023-09-25 17:35:58724 return true;
Etienne Pierre-doray825d20a12023-07-10 18:24:44725}
726
Etienne Pierre-doray98ecab42023-09-25 17:35:58727bool BackgroundTracingManagerImpl::OnScenarioIdle(
Etienne Pierre-doray825d20a12023-07-10 18:24:44728 TracingScenario* idle_scenario) {
729 DCHECK_EQ(active_scenario_, idle_scenario);
730 active_scenario_ = nullptr;
Etienne Pierre-doray97f2a832024-04-05 15:55:55731 base::UmaHistogramSparse(
732 "Tracing.Background.Scenario.Idle",
733 variations::HashName(idle_scenario->scenario_name()));
Ali Hijazi133b2d92024-02-09 14:01:52734 for (EnabledStateTestObserver* observer : background_tracing_observers_) {
Etienne Pierre-doray825d20a12023-07-10 18:24:44735 observer->OnScenarioIdle(idle_scenario->scenario_name());
736 }
Etienne Pierre-doray89055052024-04-02 19:51:39737 for (auto& scenario : enabled_scenarios_) {
Etienne Pierre-doray825d20a12023-07-10 18:24:44738 scenario->Enable();
739 }
Etienne Pierre-dorayf704b172025-06-17 23:49:44740 return delegate_->IsRecordingAllowed(idle_scenario->privacy_filter_enabled(),
741 scenario_start_time_);
Etienne Pierre-doray9c0b4c62024-11-08 14:00:16742}
743
Etienne Pierre-doray9653cf82025-02-07 17:08:50744void BackgroundTracingManagerImpl::OnScenarioError(
745 TracingScenario* scenario,
746 perfetto::TracingError error) {
747 base::UmaHistogramSparse("Tracing.Background.Scenario.Error",
748 variations::HashName(scenario->scenario_name()));
749 DLOG(ERROR) << "Background tracing error: " << error.message;
750}
751
Etienne Pierre-doray9c0b4c62024-11-08 14:00:16752bool BackgroundTracingManagerImpl::OnScenarioCloned(
753 TracingScenario* cloned_scenario) {
754 DCHECK_EQ(active_scenario_, cloned_scenario);
755 base::UmaHistogramSparse(
756 "Tracing.Background.Scenario.Clone",
757 variations::HashName(cloned_scenario->scenario_name()));
Etienne Pierre-doray3dc2c7dc2025-06-12 12:06:33758 return delegate_->IsRecordingAllowed(
Etienne Pierre-dorayf704b172025-06-17 23:49:44759 cloned_scenario->privacy_filter_enabled(), scenario_start_time_);
Etienne Pierre-doray825d20a12023-07-10 18:24:44760}
761
762void BackgroundTracingManagerImpl::OnScenarioRecording(
763 TracingScenario* scenario) {
764 DCHECK_EQ(active_scenario_, scenario);
Etienne Pierre-doray97f2a832024-04-05 15:55:55765 base::UmaHistogramSparse("Tracing.Background.Scenario.Recording",
766 variations::HashName(scenario->scenario_name()));
Etienne Pierre-doray67d80192024-11-14 21:52:47767 BackgroundMetadataDataSource::EmitMetadata(scenario);
Etienne Pierre-doray825d20a12023-07-10 18:24:44768 OnStartTracingDone();
769}
770
Etienne Pierre-doraybd38b0752023-09-05 22:42:46771void BackgroundTracingManagerImpl::SaveTrace(
772 TracingScenario* scenario,
Etienne Pierre-doray14445052023-12-08 17:46:22773 base::Token trace_uuid,
Etienne Pierre-doraybd38b0752023-09-05 22:42:46774 const BackgroundTracingRule* triggered_rule,
775 std::string&& trace_data) {
Etienne Pierre-doray21315d32025-01-29 22:13:19776 OnProtoDataComplete(
777 std::move(trace_data), scenario->scenario_name(),
778 triggered_rule->rule_name(), triggered_rule->triggered_value(),
779 scenario->privacy_filter_enabled(), scenario->is_local_scenario(),
780 /*force_upload=*/force_uploads_, trace_uuid);
Etienne Pierre-doray825d20a12023-07-10 18:24:44781}
782
oysteine53772602015-11-02 22:41:27783bool BackgroundTracingManagerImpl::HasActiveScenario() {
Etienne Pierre-dorayaec3d572024-10-29 15:13:33784 return active_scenario_ != nullptr;
ssideb549622017-03-29 21:46:00785}
786
Siddhartha S52314f22019-03-27 20:07:16787bool BackgroundTracingManagerImpl::HasTraceToUpload() {
Oystein Eftevaag3460b6b12019-05-15 16:40:15788 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Etienne Pierre-doraybd38b0752023-09-05 22:42:46789 if (!trace_report_to_upload_) {
Siddhartha Sd1f4e972019-06-18 14:27:21790 return false;
791 }
Etienne Pierre-doray4234b212025-06-03 19:04:56792#if BUILDFLAG(IS_ANDROID)
793 // Send the logs only when the trace size is within limits. If the connection
794 // type changes and we have a bigger than expected trace, then the next time
795 // service asks us when wifi is available, the trace will be sent.
796 auto type = net::NetworkChangeNotifier::GetConnectionType();
797 if (net::NetworkChangeNotifier::IsConnectionCellular(type) &&
798 trace_report_to_upload_->total_size > upload_limit_network_kb_ * 1000) {
799 RecordMetric(Metrics::LARGE_UPLOAD_WAITING_TO_RETRY);
800 return false;
Siddhartha Sd1f4e972019-06-18 14:27:21801 }
Etienne Pierre-doray4234b212025-06-03 19:04:56802#endif
803 return true;
Siddhartha S52314f22019-03-27 20:07:16804}
805
Etienne Pierre-doraybd38b0752023-09-05 22:42:46806void BackgroundTracingManagerImpl::GetTraceToUpload(
Arthur Sonzognic686e8f2024-01-11 08:36:37807 base::OnceCallback<void(std::optional<std::string>,
Etienne Pierre-doray8563c892025-01-03 14:27:05808 std::optional<std::string>,
809 base::OnceClosure)> receive_callback) {
Oystein Eftevaag3460b6b12019-05-15 16:40:15810 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Etienne Pierre-doraybd38b0752023-09-05 22:42:46811 if (!trace_report_to_upload_) {
Etienne Pierre-doray8563c892025-01-03 14:27:05812 std::move(receive_callback)
813 .Run(std::nullopt, std::nullopt, base::NullCallback());
Etienne Pierre-doraybd38b0752023-09-05 22:42:46814 return;
815 }
Oystein Eftevaag3460b6b12019-05-15 16:40:15816
Etienne Pierre-doraybd38b0752023-09-05 22:42:46817 DCHECK(trace_database_);
Alex Attarb962f1a2023-09-06 17:12:23818 BaseTraceReport trace_report = *std::move(trace_report_to_upload_);
Etienne Pierre-doray8563c892025-01-03 14:27:05819 trace_report_to_upload_.reset();
820 auto upload_complete_callback = base::BindPostTask(
821 database_task_runner_,
Etienne Pierre-doraybd38b0752023-09-05 22:42:46822 base::BindOnce(
Etienne Pierre-doray8563c892025-01-03 14:27:05823 OnUploadCompleteOnDatabaseTaskRunner,
Etienne Pierre-doray3d11c68d2024-11-15 17:51:57824 base::Unretained(trace_database_.get()), trace_report,
Etienne Pierre-doraybd38b0752023-09-05 22:42:46825 base::BindOnce(&BackgroundTracingManagerImpl::OnFinalizeComplete,
826 weak_factory_.GetWeakPtr())));
Etienne Pierre-doray8563c892025-01-03 14:27:05827 database_task_runner_->PostTask(
828 FROM_HERE, base::BindOnce(GetProtoValueOnDatabaseTaskRunner,
829 base::Unretained(trace_database_.get()),
830 trace_report, std::move(receive_callback),
831 std::move(upload_complete_callback)));
Etienne Pierre-doray825d20a12023-07-10 18:24:44832}
833
Etienne Pierre-doraybd38b0752023-09-05 22:42:46834void BackgroundTracingManagerImpl::OnFinalizeComplete(
Arthur Sonzognic686e8f2024-01-11 08:36:37835 std::optional<BaseTraceReport> trace_to_upload,
Etienne Pierre-doraybd38b0752023-09-05 22:42:46836 bool success) {
837 trace_report_to_upload_ = std::move(trace_to_upload);
Etienne Pierre-doray825d20a12023-07-10 18:24:44838 if (success) {
839 BackgroundTracingManagerImpl::RecordMetric(Metrics::UPLOAD_SUCCEEDED);
840 } else {
841 BackgroundTracingManagerImpl::RecordMetric(Metrics::UPLOAD_FAILED);
Oystein Eftevaag3460b6b12019-05-15 16:40:15842 }
Siddhartha S52314f22019-03-27 20:07:16843}
844
Etienne Pierre-dorayb57b73942023-03-20 21:34:43845void BackgroundTracingManagerImpl::AddEnabledStateObserverForTesting(
846 BackgroundTracingManager::EnabledStateTestObserver* observer) {
Oksana Zhuravlovae02027902020-10-27 18:44:32847 // Ensure that this code is called on the UI thread, except for
848 // tests where a UI thread might not have been initialized at this point.
849 DCHECK(
850 content::BrowserThread::CurrentlyOn(content::BrowserThread::UI) ||
851 !content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI));
Ehsan Chiniforooshana09fc882017-06-14 16:24:38852 background_tracing_observers_.insert(observer);
ssideb549622017-03-29 21:46:00853}
854
Etienne Pierre-dorayb57b73942023-03-20 21:34:43855void BackgroundTracingManagerImpl::RemoveEnabledStateObserverForTesting(
856 BackgroundTracingManager::EnabledStateTestObserver* observer) {
Oystein Eftevaagf80452b2019-03-19 16:30:22857 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Ehsan Chiniforooshana09fc882017-06-14 16:24:38858 background_tracing_observers_.erase(observer);
859}
860
Darin Fisherc23ee1a2019-06-05 23:26:30861void BackgroundTracingManagerImpl::AddAgent(
862 tracing::mojom::BackgroundTracingAgent* agent) {
Oystein Eftevaagf80452b2019-03-19 16:30:22863 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Darin Fisherc23ee1a2019-06-05 23:26:30864 agents_.insert(agent);
Ehsan Chiniforooshana09fc882017-06-14 16:24:38865
Ali Hijazi133b2d92024-02-09 14:01:52866 for (AgentObserver* observer : agent_observers_) {
Darin Fisherc23ee1a2019-06-05 23:26:30867 observer->OnAgentAdded(agent);
Oystein Eftevaagf80452b2019-03-19 16:30:22868 }
Ehsan Chiniforooshana09fc882017-06-14 16:24:38869}
870
Darin Fisherc23ee1a2019-06-05 23:26:30871void BackgroundTracingManagerImpl::RemoveAgent(
872 tracing::mojom::BackgroundTracingAgent* agent) {
Oystein Eftevaagf80452b2019-03-19 16:30:22873 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Ali Hijazi133b2d92024-02-09 14:01:52874 for (AgentObserver* observer : agent_observers_) {
Darin Fisherc23ee1a2019-06-05 23:26:30875 observer->OnAgentRemoved(agent);
Oystein Eftevaagf80452b2019-03-19 16:30:22876 }
Ehsan Chiniforooshana09fc882017-06-14 16:24:38877
Darin Fisherc23ee1a2019-06-05 23:26:30878 agents_.erase(agent);
Ehsan Chiniforooshana09fc882017-06-14 16:24:38879}
880
Darin Fisherc23ee1a2019-06-05 23:26:30881void BackgroundTracingManagerImpl::AddAgentObserver(AgentObserver* observer) {
Oystein Eftevaagf80452b2019-03-19 16:30:22882 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Darin Fisherc23ee1a2019-06-05 23:26:30883 agent_observers_.insert(observer);
Ehsan Chiniforooshana09fc882017-06-14 16:24:38884
Darin Fisher53ceb18292019-06-21 22:26:15885 MaybeConstructPendingAgents();
886
Ali Hijazi133b2d92024-02-09 14:01:52887 for (tracing::mojom::BackgroundTracingAgent* agent : agents_) {
Darin Fisherc23ee1a2019-06-05 23:26:30888 observer->OnAgentAdded(agent);
Oystein Eftevaagf80452b2019-03-19 16:30:22889 }
Ehsan Chiniforooshana09fc882017-06-14 16:24:38890}
891
Darin Fisherc23ee1a2019-06-05 23:26:30892void BackgroundTracingManagerImpl::RemoveAgentObserver(
893 AgentObserver* observer) {
Ehsan Chiniforooshana09fc882017-06-14 16:24:38894 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Darin Fisherc23ee1a2019-06-05 23:26:30895 agent_observers_.erase(observer);
Ehsan Chiniforooshana09fc882017-06-14 16:24:38896
Ali Hijazi133b2d92024-02-09 14:01:52897 for (tracing::mojom::BackgroundTracingAgent* agent : agents_) {
Darin Fisherc23ee1a2019-06-05 23:26:30898 observer->OnAgentRemoved(agent);
Oystein Eftevaagf80452b2019-03-19 16:30:22899 }
900}
901
oysteinea7d2d842015-10-21 20:57:07902bool BackgroundTracingManagerImpl::IsTracingForTesting() {
Etienne Pierre-dorayaec3d572024-10-29 15:13:33903 return active_scenario_->current_state() ==
904 TracingScenario::State::kRecording;
oysteinea7d2d842015-10-21 20:57:07905}
906
Etienne Pierre-doraybd38b0752023-09-05 22:42:46907void BackgroundTracingManagerImpl::SaveTraceForTesting(
908 std::string&& serialized_trace,
909 const std::string& scenario_name,
Alex Attarf62d4e22023-09-26 16:49:43910 const std::string& rule_name,
911 const base::Token& uuid) {
Etienne Pierre-doraybd38b0752023-09-05 22:42:46912 InitializeTraceReportDatabase(true);
Etienne Pierre-doray98ecab42023-09-25 17:35:58913 OnProtoDataComplete(std::move(serialized_trace), scenario_name, rule_name,
Etienne Pierre-doray21315d32025-01-29 22:13:19914 /*rule_value=*/std::nullopt,
Etienne Pierre-doray89055052024-04-02 19:51:39915 /*privacy_filter_enabled*/ true,
Etienne Pierre-dorayffeda342024-11-05 21:47:47916 /*is_local_scenario=*/false,
Etienne Pierre-doray749ed49c2024-10-15 18:19:13917 /*force_upload=*/force_uploads_, uuid);
Oystein Eftevaag3460b6b12019-05-15 16:40:15918}
919
Etienne Pierre-dorayaec3d572024-10-29 15:13:33920void BackgroundTracingManagerImpl::SetUploadLimitsForTesting(
921 size_t upload_limit_kb,
922 size_t upload_limit_network_kb) {
923 upload_limit_kb_ = upload_limit_kb;
924 upload_limit_network_kb_ = upload_limit_network_kb;
925}
926
Etienne Pierre-doray0af80e72024-06-28 18:25:29927void BackgroundTracingManagerImpl::SetPreferenceManagerForTesting(
928 std::unique_ptr<PreferenceManager> preferences) {
929 preferences_ = std::move(preferences);
930}
931
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09932size_t BackgroundTracingManagerImpl::GetScenarioSavedCount(
933 const std::string& scenario_name) {
934 auto it = scenario_saved_counts_.find(scenario_name);
935 if (it != scenario_saved_counts_.end()) {
936 return it->second;
937 }
938 return 0;
939}
940
Etienne Pierre-doraybd38b0752023-09-05 22:42:46941void BackgroundTracingManagerImpl::OnProtoDataComplete(
942 std::string&& serialized_trace,
943 const std::string& scenario_name,
Etienne Pierre-doray98ecab42023-09-25 17:35:58944 const std::string& rule_name,
Etienne Pierre-doray21315d32025-01-29 22:13:19945 std::optional<int32_t> rule_value,
Etienne Pierre-doray89055052024-04-02 19:51:39946 bool privacy_filter_enabled,
Etienne Pierre-dorayffeda342024-11-05 21:47:47947 bool is_local_scenario,
Etienne Pierre-doray749ed49c2024-10-15 18:19:13948 bool force_upload,
Alex Attarf62d4e22023-09-26 16:49:43949 const base::Token& uuid) {
Oystein Eftevaag3460b6b12019-05-15 16:40:15950 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Etienne Pierre-doray825d20a12023-07-10 18:24:44951
Ali Hijazi133b2d92024-02-09 14:01:52952 for (EnabledStateTestObserver* observer : background_tracing_observers_) {
Etienne Pierre-doraybd38b0752023-09-05 22:42:46953 observer->OnTraceReceived(serialized_trace);
Oystein Eftevaag3460b6b12019-05-15 16:40:15954 }
Etienne Pierre-doray825d20a12023-07-10 18:24:44955 if (!receive_callback_) {
Etienne Pierre-doray98ecab42023-09-25 17:35:58956 DCHECK(trace_database_);
957
Etienne Pierre-doray97f2a832024-04-05 15:55:55958 base::UmaHistogramSparse("Tracing.Background.Scenario.SaveTrace",
959 variations::HashName(scenario_name));
Etienne Pierre-doray358170f2024-01-09 17:01:20960
Alex Attarb962f1a2023-09-06 17:12:23961 SkipUploadReason skip_reason = SkipUploadReason::kNoSkip;
Etienne Pierre-doray89055052024-04-02 19:51:39962 if (!privacy_filter_enabled) {
Etienne Pierre-doray56a2a49b2023-09-13 18:16:45963 skip_reason = SkipUploadReason::kNotAnonymized;
Etienne Pierre-dorayffeda342024-11-05 21:47:47964 } else if (is_local_scenario) {
965 skip_reason = SkipUploadReason::kLocalScenario;
Etienne Pierre-doray5b928142023-10-06 14:49:57966 } else if (serialized_trace.size() > upload_limit_kb_ * 1024) {
Alex Attarb962f1a2023-09-06 17:12:23967 skip_reason = SkipUploadReason::kSizeLimitExceeded;
Etienne Pierre-doraybd38b0752023-09-05 22:42:46968 }
Etienne Pierre-doray3dc2c7dc2025-06-12 12:06:33969 bool should_save_trace = delegate_->ShouldSaveUnuploadedTrace();
Etienne Pierre-doray98ecab42023-09-25 17:35:58970 if (skip_reason != SkipUploadReason::kNoSkip && !should_save_trace) {
Etienne Pierre-doraybd38b0752023-09-05 22:42:46971 return;
972 }
Etienne Pierre-doray825d20a12023-07-10 18:24:44973 BackgroundTracingManagerImpl::RecordMetric(Metrics::FINALIZATION_STARTED);
Etienne Pierre-doraybd38b0752023-09-05 22:42:46974
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09975 BaseTraceReport base_report;
Alex Attarf62d4e22023-09-26 16:49:43976 base_report.uuid = uuid;
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09977 base_report.creation_time = base::Time::Now();
978 base_report.scenario_name = scenario_name;
979 base_report.upload_rule_name = rule_name;
Etienne Pierre-doray21315d32025-01-29 22:13:19980 base_report.upload_rule_value = rule_value;
Etienne Pierre-doray3bb781fd82023-09-18 14:55:09981 base_report.total_size = serialized_trace.size();
982 base_report.skip_reason = skip_reason;
Etienne Pierre-dorayf56901822023-09-22 19:54:12983
Etienne Pierre-doraya9d9c412025-06-18 15:33:41984 std::string serialized_system_profile =
985 delegate_->RecordSerializedSystemProfileMetrics();
Etienne Pierre-doray98ecab42023-09-25 17:35:58986
987 database_task_runner_->PostTask(
988 FROM_HERE,
989 base::BindOnce(
990 AddTraceOnDatabaseTaskRunner,
991 base::Unretained(trace_database_.get()),
992 std::move(serialized_trace), std::move(serialized_system_profile),
Etienne Pierre-doray749ed49c2024-10-15 18:19:13993 std::move(base_report), should_save_trace, force_upload,
Etienne Pierre-doray98ecab42023-09-25 17:35:58994 base::BindOnce(&BackgroundTracingManagerImpl::OnTraceSaved,
995 weak_factory_.GetWeakPtr(), scenario_name)));
Etienne Pierre-doray825d20a12023-07-10 18:24:44996 } else {
997 BackgroundTracingManagerImpl::RecordMetric(
998 Metrics::FINALIZATION_STARTED_WITH_LOCAL_OUTPUT);
999 receive_callback_.Run(
Etienne Pierre-doray34967f42024-04-17 16:42:541000 uuid.ToString() + ".perfetto.gz", std::move(serialized_trace),
Etienne Pierre-doray825d20a12023-07-10 18:24:441001 base::BindOnce(&BackgroundTracingManagerImpl::OnFinalizeComplete,
Arthur Sonzognic686e8f2024-01-11 08:36:371002 weak_factory_.GetWeakPtr(), std::nullopt));
Etienne Pierre-doray825d20a12023-07-10 18:24:441003 }
1004}
1005
Etienne Pierre-doray840a1172024-03-18 22:57:001006void BackgroundTracingManagerImpl::AddNamedTriggerObserver(
Etienne Pierre-dorayb57b73942023-03-20 21:34:431007 const std::string& trigger_name,
Etienne Pierre-doray840a1172024-03-18 22:57:001008 BackgroundTracingRule* observer) {
1009 named_trigger_observers_[trigger_name].AddObserver(observer);
1010}
1011
1012void BackgroundTracingManagerImpl::RemoveNamedTriggerObserver(
1013 const std::string& trigger_name,
1014 BackgroundTracingRule* observer) {
1015 named_trigger_observers_[trigger_name].RemoveObserver(observer);
oysteinea7d2d842015-10-21 20:57:071016}
1017
Etienne Pierre-doray44477e152023-07-05 14:18:271018bool BackgroundTracingManagerImpl::DoEmitNamedTrigger(
Etienne Pierre-doray88cce9f2024-03-21 01:22:171019 const std::string& trigger_name,
Etienne Pierre-doray226632b2025-02-11 20:51:211020 std::optional<int32_t> value,
1021 uint64_t flow_id) {
Oystein Eftevaagf80452b2019-03-19 16:30:221022 DCHECK_CURRENTLY_ON(BrowserThread::UI);
simonhatch0b016192015-05-22 19:14:021023
Etienne Pierre-doray840a1172024-03-18 22:57:001024 auto it = named_trigger_observers_.find(trigger_name);
1025 if (it == named_trigger_observers_.end()) {
Etienne Pierre-dorayb57b73942023-03-20 21:34:431026 return false;
1027 }
Etienne Pierre-doray840a1172024-03-18 22:57:001028 for (BackgroundTracingRule& obs : it->second) {
Etienne Pierre-doray226632b2025-02-11 20:51:211029 if (obs.OnRuleTriggered(value, flow_id)) {
Etienne Pierre-dorayb5e78be2025-08-18 18:30:131030 TRACE_EVENT_INSTANT("tracing.background", "NamedTrigger",
Etienne Pierre-doray226632b2025-02-11 20:51:211031 perfetto::Flow::Global(flow_id));
Etienne Pierre-doray840a1172024-03-18 22:57:001032 return true;
1033 }
1034 }
1035 return false;
simonhatch0b016192015-05-22 19:14:021036}
Oystein Eftevaagff998452019-05-13 20:47:061037
Etienne Pierre-dorayb57b73942023-03-20 21:34:431038void BackgroundTracingManagerImpl::InvalidateTriggersCallbackForTesting() {
Etienne Pierre-doray840a1172024-03-18 22:57:001039 named_trigger_observers_.clear();
simonhatch0b016192015-05-22 19:14:021040}
1041
Etienne Pierre-doraye62bc2e2022-12-03 14:02:541042void BackgroundTracingManagerImpl::OnStartTracingDone() {
Oystein Eftevaagf80452b2019-03-19 16:30:221043 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Ali Hijazi133b2d92024-02-09 14:01:521044 for (EnabledStateTestObserver* observer : background_tracing_observers_) {
Etienne Pierre-doray825d20a12023-07-10 18:24:441045 observer->OnTraceStarted();
Oystein Eftevaagf80452b2019-03-19 16:30:221046 }
Oystein Eftevaag7655e3cfd12018-12-19 18:20:191047}
oysteinea7d2d842015-10-21 20:57:071048
Siddhartha S7d37b8d42019-06-07 23:53:121049void BackgroundTracingManagerImpl::GenerateMetadataProto(
ssidf28a73d2019-08-21 20:09:261050 perfetto::protos::pbzero::ChromeMetadataPacket* metadata,
1051 bool privacy_filtering_enabled) {
Siddhartha S7d37b8d42019-06-07 23:53:121052 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Etienne Pierre-dorayaec3d572024-10-29 15:13:331053 if (active_scenario_) {
Etienne Pierre-dorayb4d088dd2023-09-27 12:40:511054 active_scenario_->GenerateMetadataProto(metadata);
Siddhartha S7d37b8d42019-06-07 23:53:121055 }
1056}
1057
Oystein Eftevaag3460b6b12019-05-15 16:40:151058void BackgroundTracingManagerImpl::AbortScenarioForTesting() {
Etienne Pierre-dorayaec3d572024-10-29 15:13:331059 if (active_scenario_) {
Etienne Pierre-doray825d20a12023-07-10 18:24:441060 active_scenario_->Abort();
Etienne Bergeron4d0ea2d2019-01-11 16:28:181061 }
1062}
1063
Alex Attarcc5eebb2023-08-11 16:35:551064void BackgroundTracingManagerImpl::CleanDatabase() {
1065 DCHECK(trace_database_);
1066
Etienne Pierre-doray3bb781fd82023-09-18 14:55:091067 database_task_runner_->PostTaskAndReplyWithResult(
Alex Attar9e640b22023-08-25 14:44:061068 FROM_HERE,
1069 base::BindOnce(
Etienne Pierre-doray3bb781fd82023-09-18 14:55:091070 [](TraceReportDatabase* trace_database) {
Etienne Pierre-dorayd05d46c2024-05-24 17:13:101071 // Trace payload is cleared on a more frequent basis.
Etienne Pierre-doray064c03402024-08-22 20:17:171072 trace_database->DeleteOldTraceContent(kMaxTraceContent);
Etienne Pierre-dorayd05d46c2024-05-24 17:13:101073 // The reports entries are kept (without the payload) for longer to
1074 // track upload quotas.
1075 trace_database->DeleteTraceReportsOlderThan(kTraceReportTimeToLive);
Etienne Pierre-dorayf8f587c2024-12-06 19:39:001076 trace_database->DeleteUploadedTraceContentOlderThan(
1077 kUploadedTraceContentTimeToLive);
Etienne Pierre-dorayd05d46c2024-05-24 17:13:101078 return trace_database->GetScenarioCountsSince(
1079 base::Time::Now() - kMaxTracesPerScenarioDuration);
Etienne Pierre-doray3bb781fd82023-09-18 14:55:091080 },
1081 base::Unretained(trace_database_.get())),
1082 base::BindOnce(&BackgroundTracingManagerImpl::OnTraceDatabaseUpdated,
1083 weak_factory_.GetWeakPtr()));
Alex Attarcc5eebb2023-08-11 16:35:551084}
1085
1086void BackgroundTracingManagerImpl::DeleteTracesInDateRange(base::Time start,
1087 base::Time end) {
Alex Attar9e640b22023-08-25 14:44:061088 // The trace report database needs to exist for clean up. Avoid creating or
1089 // initializing the trace report database to perform a database clean up.
Arthur Sonzognic686e8f2024-01-11 08:36:371090 std::optional<base::FilePath> database_dir;
Etienne Pierre-doray6fe98bd2023-09-06 19:41:181091 if (!trace_database_) {
1092 database_dir = GetContentClient()->browser()->GetLocalTracesDirectory();
Etienne Pierre-doray3bb781fd82023-09-18 14:55:091093 if (database_dir.has_value()) {
Etienne Pierre-doray6fe98bd2023-09-06 19:41:181094 return;
1095 }
1096 trace_database_ = {new TraceReportDatabase,
1097 base::OnTaskRunnerDeleter(database_task_runner_)};
Alex Attar9e640b22023-08-25 14:44:061098 }
Etienne Pierre-doray3bb781fd82023-09-18 14:55:091099 auto on_database_updated =
1100 base::BindOnce(&BackgroundTracingManagerImpl::OnTraceDatabaseUpdated,
1101 weak_factory_.GetWeakPtr());
Etienne Pierre-doray6fe98bd2023-09-06 19:41:181102 database_task_runner_->PostTask(
1103 FROM_HERE,
1104 base::BindOnce(
1105 [](TraceReportDatabase* trace_database,
Arthur Sonzognic686e8f2024-01-11 08:36:371106 std::optional<base::FilePath> database_dir, base::Time start,
Etienne Pierre-doray3bb781fd82023-09-18 14:55:091107 base::Time end,
1108 base::OnceCallback<void(ScenarioCountMap)> on_database_updated) {
Etienne Pierre-doray6fe98bd2023-09-06 19:41:181109 if (database_dir.has_value() &&
1110 !trace_database->OpenDatabaseIfExists(database_dir.value())) {
1111 return;
1112 }
1113 if (!trace_database->is_initialized()) {
1114 return;
1115 }
Etienne Pierre-doray3bb781fd82023-09-18 14:55:091116 if (trace_database->DeleteTracesInDateRange(start, end)) {
1117 GetUIThreadTaskRunner({})->PostTask(
1118 FROM_HERE,
Etienne Pierre-dorayd05d46c2024-05-24 17:13:101119 base::BindOnce(
1120 std::move(on_database_updated),
1121 trace_database->GetScenarioCountsSince(
1122 base::Time::Now() - kMaxTracesPerScenarioDuration)));
Etienne Pierre-doray3bb781fd82023-09-18 14:55:091123 } else {
Etienne Pierre-doray6fe98bd2023-09-06 19:41:181124 RecordMetric(Metrics::DATABASE_CLEANUP_FAILED);
1125 }
1126 },
Etienne Pierre-doray3bb781fd82023-09-18 14:55:091127 base::Unretained(trace_database_.get()), database_dir, start, end,
1128 std::move(on_database_updated)));
Alex Attarcc5eebb2023-08-11 16:35:551129}
1130
Darin Fisher53ceb18292019-06-21 22:26:151131// static
Wanchang Ryu342162a2020-02-27 19:31:251132void BackgroundTracingManagerImpl::AddPendingAgent(
1133 int child_process_id,
1134 mojo::PendingRemote<tracing::mojom::BackgroundTracingAgentProvider>
1135 pending_provider) {
Darin Fisher53ceb18292019-06-21 22:26:151136 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Wanchang Ryu342162a2020-02-27 19:31:251137 // Delay agent initialization until we have an interested AgentObserver.
1138 // We set disconnect handler for cleanup when the tracing target is closed.
1139 mojo::Remote<tracing::mojom::BackgroundTracingAgentProvider> provider(
1140 std::move(pending_provider));
Darin Fisher53ceb18292019-06-21 22:26:151141
Wanchang Ryu342162a2020-02-27 19:31:251142 provider.set_disconnect_handler(base::BindOnce(
1143 &BackgroundTracingManagerImpl::ClearPendingAgent, child_process_id));
1144
Oksana Zhuravlova872a5a6f2022-06-08 18:15:291145 GetInstance().pending_agents_[child_process_id] = std::move(provider);
1146 GetInstance().MaybeConstructPendingAgents();
Darin Fisher53ceb18292019-06-21 22:26:151147}
1148
Wanchang Ryu342162a2020-02-27 19:31:251149// static
1150void BackgroundTracingManagerImpl::ClearPendingAgent(int child_process_id) {
1151 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Oksana Zhuravlova872a5a6f2022-06-08 18:15:291152 GetInstance().pending_agents_.erase(child_process_id);
Wanchang Ryu342162a2020-02-27 19:31:251153}
1154
Darin Fisher53ceb18292019-06-21 22:26:151155void BackgroundTracingManagerImpl::MaybeConstructPendingAgents() {
1156 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1157
Etienne Pierre-doray09609102024-10-11 13:16:041158 if (agent_observers_.empty() && enabled_scenarios_.empty()) {
Darin Fisher53ceb18292019-06-21 22:26:151159 return;
Etienne Pierre-doray09609102024-10-11 13:16:041160 }
Darin Fisher53ceb18292019-06-21 22:26:151161
Wanchang Ryu342162a2020-02-27 19:31:251162 for (auto& pending_agent : pending_agents_) {
1163 pending_agent.second.set_disconnect_handler(base::OnceClosure());
1164 BackgroundTracingAgentClientImpl::Create(pending_agent.first,
1165 std::move(pending_agent.second));
1166 }
1167 pending_agents_.clear();
Darin Fisher53ceb18292019-06-21 22:26:151168}
1169
Etienne Bergeron32d2c242018-07-27 21:17:291170} // namespace content
Etienne Pierre-doray67d80192024-11-14 21:52:471171
1172PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(
1173 COMPONENT_EXPORT(TRACING_CPP),
1174 content::BackgroundMetadataDataSource);