1 // Copyright 2019 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "components/metrics/structured/recorder.h" 6 7 #include <utility> 8 9 #include "base/no_destructor.h" 10 #include "base/task/current_thread.h" 11 #include "base/task/sequenced_task_runner.h" 12 #include "components/metrics/structured/histogram_util.h" 13 #include "components/metrics/structured/structured_metrics_features.h" 14 15 namespace metrics::structured { 16 17 Recorder::Recorder() = default; 18 19 Recorder::~Recorder() = default; 20 GetInstance()21Recorder* Recorder::GetInstance() { 22 static base::NoDestructor<Recorder> recorder; 23 return recorder.get(); 24 } 25 RecordEvent(Event && event)26void Recorder::RecordEvent(Event&& event) { 27 // All calls to StructuredMetricsProvider (the observer) must be on the UI 28 // sequence, so re-call Record if needed. If a UI task runner hasn't been set 29 // yet, ignore this Record. 30 if (!ui_task_runner_) { 31 LogInternalError(StructuredMetricsError::kUninitializedClient); 32 return; 33 } 34 35 if (!ui_task_runner_->RunsTasksInCurrentSequence()) { 36 ui_task_runner_->PostTask( 37 FROM_HERE, base::BindOnce(&Recorder::RecordEvent, 38 base::Unretained(this), std::move(event))); 39 return; 40 } 41 42 DCHECK(base::CurrentUIThread::IsSet()); 43 44 delegating_events_processor_.OnEventsRecord(&event); 45 46 // Make a copy of an event that all observers can share. 47 const auto event_clone = event.Clone(); 48 for (auto& observer : observers_) { 49 observer.OnEventRecord(event_clone); 50 } 51 52 if (observers_.empty()) { 53 // Other values of EventRecordingState are recorded in 54 // StructuredMetricsProvider::OnRecord. 55 LogEventRecordingState(EventRecordingState::kProviderMissing); 56 } 57 } 58 ProfileAdded(const base::FilePath & profile_path)59void Recorder::ProfileAdded(const base::FilePath& profile_path) { 60 // All calls to the StructuredMetricsProvider (the observer) must be on the UI 61 // sequence. 62 DCHECK(base::CurrentUIThread::IsSet()); 63 // TODO(crbug.com/1016655 ): investigate whether we can verify that 64 // |profile_path| corresponds to a valid (non-guest, non-signin) profile. 65 for (auto& observer : observers_) { 66 observer.OnProfileAdded(profile_path); 67 } 68 69 // Notify the event processors. 70 delegating_events_processor_.OnProfileAdded(profile_path); 71 } 72 OnReportingStateChanged(bool enabled)73void Recorder::OnReportingStateChanged(bool enabled) { 74 for (auto& observer : observers_) { 75 observer.OnReportingStateChanged(enabled); 76 } 77 } 78 OnSystemProfileInitialized()79void Recorder::OnSystemProfileInitialized() { 80 for (auto& observer : observers_) { 81 observer.OnSystemProfileInitialized(); 82 } 83 } 84 SetUiTaskRunner(const scoped_refptr<base::SequencedTaskRunner> ui_task_runner)85void Recorder::SetUiTaskRunner( 86 const scoped_refptr<base::SequencedTaskRunner> ui_task_runner) { 87 ui_task_runner_ = ui_task_runner; 88 } 89 AddObserver(RecorderImpl * observer)90void Recorder::AddObserver(RecorderImpl* observer) { 91 observers_.AddObserver(observer); 92 } 93 RemoveObserver(RecorderImpl * observer)94void Recorder::RemoveObserver(RecorderImpl* observer) { 95 observers_.RemoveObserver(observer); 96 } 97 AddEventsProcessor(std::unique_ptr<EventsProcessorInterface> events_processor)98void Recorder::AddEventsProcessor( 99 std::unique_ptr<EventsProcessorInterface> events_processor) { 100 delegating_events_processor_.AddEventsProcessor(std::move(events_processor)); 101 } 102 OnProvideIndependentMetrics(ChromeUserMetricsExtension * uma_proto)103void Recorder::OnProvideIndependentMetrics( 104 ChromeUserMetricsExtension* uma_proto) { 105 delegating_events_processor_.OnProvideIndependentMetrics(uma_proto); 106 } 107 OnEventRecorded(StructuredEventProto * event)108void Recorder::OnEventRecorded(StructuredEventProto* event) { 109 delegating_events_processor_.OnEventRecorded(event); 110 } 111 112 } // namespace metrics::structured 113