blob: 8708b89d72f5f296512aa13f5c4886fa61ebb3c7 [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.
#ifndef CONTENT_BROWSER_TRACING_BACKGROUND_TRACING_MANAGER_IMPL_H_
#define CONTENT_BROWSER_TRACING_BACKGROUND_TRACING_MANAGER_IMPL_H_
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/no_destructor.h"
#include "base/observer_list.h"
#include "base/threading/sequence_bound.h"
#include "base/timer/timer.h"
#include "base/token.h"
#include "base/trace_event/named_trigger.h"
#include "content/browser/tracing/trace_report_database.h"
#include "content/browser/tracing/trace_upload_list.h"
#include "content/browser/tracing/traces_internals/traces_internals.mojom.h"
#include "content/browser/tracing/tracing_scenario.h"
#include "content/common/content_export.h"
#include "content/public/browser/background_tracing_manager.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/tracing/public/cpp/perfetto/trace_event_metadata_source.h"
#include "services/tracing/public/mojom/background_tracing_agent.mojom.h"
namespace tracing::mojom {
class BackgroundTracingAgent;
class BackgroundTracingAgentProvider;
} // namespace tracing::mojom
namespace content {
namespace mojom {
class ChildProcess;
} // namespace mojom
class TracingDelegate;
class BackgroundTracingManagerImpl
: public BackgroundTracingManager,
public base::trace_event::NamedTriggerManager,
public TraceUploadList,
public TracingScenario::Delegate {
public:
class AgentObserver {
public:
virtual void OnAgentAdded(
tracing::mojom::BackgroundTracingAgent* agent) = 0;
virtual void OnAgentRemoved(
tracing::mojom::BackgroundTracingAgent* agent) = 0;
};
// Delegate to store and read application preferences for startup tracing, to
// isolate the feature for testing.
class PreferenceManager {
public:
virtual bool GetBackgroundStartupTracingEnabled() const = 0;
virtual ~PreferenceManager() = default;
};
using ScenarioCountMap = base::flat_map<std::string, size_t>;
using FinishedProcessingCallback =
TraceUploadList::FinishedProcessingCallback;
// These values are used for a histogram. Do not reorder.
enum class Metrics {
SCENARIO_ACTIVATION_REQUESTED = 0,
SCENARIO_ACTIVATED_SUCCESSFULLY = 1,
// RECORDING_ENABLED = 2, Obsolete
// PREEMPTIVE_TRIGGERED = 3, Obsolete
// REACTIVE_TRIGGERED = 4, Obsolete
// FINALIZATION_ALLOWED = 5, Obsolete
// FINALIZATION_DISALLOWED = 6, Obsolete
FINALIZATION_STARTED = 7,
// OBSOLETE_FINALIZATION_COMPLETE = 8, Obsolete
SCENARIO_ACTION_FAILED_LOWRES_CLOCK = 9,
UPLOAD_FAILED = 10,
UPLOAD_SUCCEEDED = 11,
// STARTUP_SCENARIO_TRIGGERED = 12, Obsolete
LARGE_UPLOAD_WAITING_TO_RETRY = 13,
// SYSTEM_TRIGGERED = 14, Obsolete
// REACHED_CODE_SCENARIO_TRIGGERED = 15, Obsolete
FINALIZATION_STARTED_WITH_LOCAL_OUTPUT = 16,
DATABASE_INITIALIZATION_FAILED = 17,
DATABASE_CLEANUP_FAILED = 18,
SAVE_TRACE_FAILED = 19,
SAVE_TRACE_SUCCEEDED = 20,
NUMBER_OF_BACKGROUND_TRACING_METRICS,
};
static void RecordMetric(Metrics metric);
CONTENT_EXPORT static BackgroundTracingManagerImpl& GetInstance();
explicit CONTENT_EXPORT BackgroundTracingManagerImpl(
TracingDelegate* delegate);
~BackgroundTracingManagerImpl() override;
BackgroundTracingManagerImpl(const BackgroundTracingManagerImpl&) = delete;
BackgroundTracingManagerImpl& operator=(const BackgroundTracingManagerImpl&) =
delete;
// Callable from any thread.
static void ActivateForProcess(int child_process_id,
mojom::ChildProcess* child_process);
void SetReceiveCallback(ReceiveCallback receive_callback) override;
bool InitializePerfettoTriggerRules(
const perfetto::protos::gen::TracingTriggerRulesConfig& config) override;
bool InitializeFieldScenarios(
const perfetto::protos::gen::ChromeFieldTracingConfig& config,
DataFiltering data_filtering,
bool force_upload,
size_t upload_limit_kb) override;
std::vector<std::string> AddPresetScenarios(
const perfetto::protos::gen::ChromeFieldTracingConfig& config,
DataFiltering data_filtering) override;
bool SetEnabledScenarios(
std::vector<std::string> enabled_scenarios_hashes) override;
bool HasActiveScenario() override;
void DeleteTracesInDateRange(base::Time start, base::Time end) override;
// TracingScenario::Delegate:
bool OnScenarioActive(TracingScenario* scenario) override;
bool OnScenarioIdle(TracingScenario* scenario) override;
void OnScenarioError(TracingScenario* scenario,
perfetto::TracingError error) override;
bool OnScenarioCloned(TracingScenario* scenario) override;
void OnScenarioRecording(TracingScenario* scenario) override;
void SaveTrace(TracingScenario* scenario,
base::Token trace_uuid,
const BackgroundTracingRule* triggered_rule,
std::string&& serialized_trace) override;
void AddNamedTriggerObserver(const std::string& trigger_name,
BackgroundTracingRule* observer);
void RemoveNamedTriggerObserver(const std::string& trigger_name,
BackgroundTracingRule* observer);
// Returns the list of scenario hashes and names that were saved,
// whether or not enabled.
CONTENT_EXPORT std::vector<traces_internals::mojom::ScenarioPtr>
GetAllScenarios() const;
std::vector<std::string> OverwritePresetScenarios(
const perfetto::protos::gen::ChromeFieldTracingConfig& config,
DataFiltering data_filtering);
// Returns the list of scenario hashes that are currently enabled. These are
// either all preset scenarios or all field scenarios.
CONTENT_EXPORT std::vector<std::string> GetEnabledScenarios() const;
bool HasTraceToUpload() override;
void GetTraceToUpload(base::OnceCallback<void(std::optional<std::string>,
std::optional<std::string>,
base::OnceClosure)>) override;
CONTENT_EXPORT size_t GetScenarioSavedCount(const std::string& scenario_name);
CONTENT_EXPORT void InitializeTraceReportDatabase(
bool open_in_memory = false);
// TraceUploadList
void OpenDatabaseIfExists() override;
void GetAllTraceReports(GetReportsCallback callback) override;
void DeleteSingleTrace(const base::Token& trace_uuid,
FinishedProcessingCallback callback) override;
void DeleteAllTraces(FinishedProcessingCallback callback) override;
void UserUploadSingleTrace(const base::Token& trace_uuid,
FinishedProcessingCallback callback) override;
void DownloadTrace(const base::Token& trace_uuid,
GetProtoCallback callback) override;
// Add/remove EnabledStateTestObserver.
CONTENT_EXPORT void AddEnabledStateObserverForTesting(
BackgroundTracingManager::EnabledStateTestObserver* observer);
CONTENT_EXPORT void RemoveEnabledStateObserverForTesting(
BackgroundTracingManager::EnabledStateTestObserver* observer);
// Add/remove Agent{Observer}.
void AddAgent(tracing::mojom::BackgroundTracingAgent* agent);
void RemoveAgent(tracing::mojom::BackgroundTracingAgent* agent);
void AddAgentObserver(AgentObserver* observer);
void RemoveAgentObserver(AgentObserver* observer);
void OnStartTracingDone();
void OnProtoDataComplete(std::string&& serialized_trace,
const std::string& scenario_name,
const std::string& rule_name,
std::optional<int32_t> rule_value,
bool privacy_filter_enabled,
bool is_local_scenario,
bool force_upload,
const base::Token& uuid);
// For tests
CONTENT_EXPORT void InvalidateTriggersCallbackForTesting();
CONTENT_EXPORT bool IsTracingForTesting();
CONTENT_EXPORT void AbortScenarioForTesting() override;
CONTENT_EXPORT void SaveTraceForTesting(std::string&& serialized_trace,
const std::string& scenario_name,
const std::string& rule_name,
const base::Token& uuid) override;
CONTENT_EXPORT void SetUploadLimitsForTesting(size_t upload_limit_kb,
size_t upload_limit_network_kb);
CONTENT_EXPORT void SetPreferenceManagerForTesting(
std::unique_ptr<PreferenceManager> preferences);
void GenerateMetadataProto(
perfetto::protos::pbzero::ChromeMetadataPacket* metadata,
bool privacy_filtering_enabled);
private:
#if BUILDFLAG(IS_ANDROID)
// ~1MB compressed size.
constexpr static int kDefaultUploadLimitKb = 5 * 1024;
#else
// Less than 10MB compressed size.
constexpr static int kDefaultUploadLimitKb = 30 * 1024;
#endif
bool RequestActivateScenario();
void DisableScenarios();
void AddMetadataGeneratorFunction();
std::vector<std::string> AddPresetScenariosImpl(
const perfetto::protos::gen::ChromeFieldTracingConfig& config,
DataFiltering data_filtering,
bool overwrite_conflicts);
// Named triggers
bool DoEmitNamedTrigger(const std::string& trigger_name,
std::optional<int32_t>,
uint64_t) override;
void OnScenarioAborted();
static void AddPendingAgent(
int child_process_id,
mojo::PendingRemote<tracing::mojom::BackgroundTracingAgentProvider>
provider);
static void ClearPendingAgent(int child_process_id);
void MaybeConstructPendingAgents();
void OnFinalizeComplete(std::optional<BaseTraceReport> trace_to_upload,
bool success);
void OnTraceDatabaseCreated(ScenarioCountMap scenario_saved_counts,
std::optional<BaseTraceReport> trace_to_upload,
bool success);
void OnTraceDatabaseUpdated(ScenarioCountMap scenario_saved_counts);
void OnTraceSaved(const std::string& scenario_name,
std::optional<BaseTraceReport> trace_to_upload,
bool success);
void CleanDatabase();
raw_ptr<TracingDelegate> delegate_;
std::unique_ptr<tracing::BackgroundTracingStateManager> state_manager_;
std::vector<std::unique_ptr<TracingScenario>> field_scenarios_;
base::flat_map<std::string, std::unique_ptr<TracingScenario>>
preset_scenarios_;
std::vector<raw_ptr<TracingScenario>> enabled_scenarios_;
raw_ptr<TracingScenario> active_scenario_{nullptr};
base::TimeTicks scenario_start_time_;
std::vector<std::unique_ptr<BackgroundTracingRule>> trigger_rules_;
ReceiveCallback receive_callback_;
std::map<std::string, base::ObserverList<BackgroundTracingRule>>
named_trigger_observers_;
// Note, these sets are not mutated during iteration so it is okay to not use
// base::ObserverList.
std::set<raw_ptr<EnabledStateTestObserver, SetExperimental>>
background_tracing_observers_;
std::set<raw_ptr<tracing::mojom::BackgroundTracingAgent, SetExperimental>>
agents_;
std::set<raw_ptr<AgentObserver, SetExperimental>> agent_observers_;
std::unique_ptr<PreferenceManager> preferences_;
std::map<int, mojo::Remote<tracing::mojom::BackgroundTracingAgentProvider>>
pending_agents_;
ScenarioCountMap scenario_saved_counts_;
// Task runner on which |trace_database_| lives.
scoped_refptr<base::SequencedTaskRunner> database_task_runner_;
// This contains all the traces saved locally.
std::unique_ptr<TraceReportDatabase, base::OnTaskRunnerDeleter>
trace_database_;
std::optional<BaseTraceReport> trace_report_to_upload_;
// Timer to delete traces older than 2 weeks.
base::RepeatingTimer clean_database_timer_;
// All the upload limits below are set for uncompressed trace log. On
// compression the data size usually reduces by 3x for size < 10MB, and the
// compression ratio grows up to 8x if the buffer size is around 100MB.
size_t upload_limit_network_kb_ = 1024;
size_t upload_limit_kb_ = kDefaultUploadLimitKb;
bool force_uploads_ = false;
base::WeakPtrFactory<BackgroundTracingManagerImpl> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_TRACING_BACKGROUND_TRACING_MANAGER_IMPL_H_