1 // Copyright 2012 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/child_histogram_fetcher_impl.h"
6
7 #include <memory>
8
9 #include "base/functional/bind.h"
10 #include "base/location.h"
11 #include "base/metrics/histogram_delta_serialization.h"
12 #include "base/metrics/histogram_functions.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/metrics/histogram_macros_local.h"
15 #include "base/metrics/persistent_histogram_allocator.h"
16 #include "components/metrics/public/mojom/histogram_fetcher.mojom.h"
17 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
18 #include "mojo/public/cpp/system/platform_handle.h"
19
20 namespace metrics {
21
22 ChildHistogramFetcherFactoryImpl::ChildHistogramFetcherFactoryImpl() = default;
23
24 ChildHistogramFetcherFactoryImpl::~ChildHistogramFetcherFactoryImpl() = default;
25
Create(mojo::PendingReceiver<mojom::ChildHistogramFetcherFactory> receiver)26 void ChildHistogramFetcherFactoryImpl::Create(
27 mojo::PendingReceiver<mojom::ChildHistogramFetcherFactory> receiver) {
28 mojo::MakeSelfOwnedReceiver(
29 std::make_unique<ChildHistogramFetcherFactoryImpl>(),
30 std::move(receiver));
31 }
32
CreateFetcher(base::UnsafeSharedMemoryRegion shared_memory,mojo::PendingReceiver<mojom::ChildHistogramFetcher> receiver)33 void ChildHistogramFetcherFactoryImpl::CreateFetcher(
34 base::UnsafeSharedMemoryRegion shared_memory,
35 mojo::PendingReceiver<mojom::ChildHistogramFetcher> receiver) {
36 // This message must be received only once.
37 static bool already_called = false;
38 CHECK(!already_called);
39 already_called = true;
40
41 // If the shared memory region was passed via the command line, then the
42 // global histogram allocator should already by setup. Otherwise, the region
43 // is being passed via this IPC. We need to initialize the global histogram
44 // allocator and the tracking histograms here.
45 if (shared_memory.IsValid() && !base::GlobalHistogramAllocator::Get()) {
46 base::GlobalHistogramAllocator::CreateWithSharedMemoryRegion(shared_memory);
47 // Emit a local histogram, which should not be reported to servers. This is
48 // monitored from the serverside.
49 LOCAL_HISTOGRAM_BOOLEAN("UMA.LocalHistogram", true);
50
51 base::PersistentHistogramAllocator* global_allocator =
52 base::GlobalHistogramAllocator::Get();
53 if (global_allocator) {
54 global_allocator->CreateTrackingHistograms(global_allocator->Name());
55 }
56 }
57
58 // Setup the Mojo receiver.
59 mojo::MakeSelfOwnedReceiver(std::make_unique<ChildHistogramFetcherImpl>(),
60 std::move(receiver));
61 }
62
63 ChildHistogramFetcherImpl::ChildHistogramFetcherImpl() = default;
64
65 ChildHistogramFetcherImpl::~ChildHistogramFetcherImpl() = default;
66
67 // Extract snapshot data and then send it off to the Browser process.
68 // Send only a delta to what we have already sent.
GetChildNonPersistentHistogramData(GetChildNonPersistentHistogramDataCallback callback)69 void ChildHistogramFetcherImpl::GetChildNonPersistentHistogramData(
70 GetChildNonPersistentHistogramDataCallback callback) {
71 // If a persistent allocator is in use, it needs to occasionally update
72 // some internal histograms. An upload is happening so this is a good time.
73 base::PersistentHistogramAllocator* global_allocator =
74 base::GlobalHistogramAllocator::Get();
75 if (global_allocator) {
76 global_allocator->UpdateTrackingHistograms();
77 }
78
79 if (!histogram_delta_serialization_) {
80 histogram_delta_serialization_ =
81 std::make_unique<base::HistogramDeltaSerialization>("ChildProcess");
82 }
83
84 std::vector<std::string> deltas;
85 // "false" to PerpareAndSerializeDeltas() indicates to *not* include
86 // histograms held in persistent storage on the assumption that they will be
87 // visible to the recipient through other means.
88 histogram_delta_serialization_->PrepareAndSerializeDeltas(&deltas, false);
89
90 std::move(callback).Run(deltas);
91
92 #ifndef NDEBUG
93 static int count = 0;
94 count++;
95 LOCAL_HISTOGRAM_COUNTS("Histogram.ChildProcessHistogramSentCount", count);
96 #endif
97 }
98
Ping(mojom::UmaPingCallSource call_source,PingCallback callback)99 void ChildHistogramFetcherImpl::Ping(mojom::UmaPingCallSource call_source,
100 PingCallback callback) {
101 // Since the ChildHistogramFetcherImpl instance was created after setting up
102 // the shared memory (if there was one -- see CreateFetcher()), this histogram
103 // will live in it (i.e., it should have the |kIsPersistent| flag).
104 const char* histogram_name = nullptr;
105 switch (call_source) {
106 case mojom::UmaPingCallSource::PERIODIC:
107 histogram_name = "UMA.ChildProcess.Ping.Periodic";
108 break;
109 case mojom::UmaPingCallSource::SHARED_MEMORY_SET_UP:
110 histogram_name = "UMA.ChildProcess.Ping.SharedMemorySetUp";
111 break;
112 }
113 base::UmaHistogramEnumeration(histogram_name,
114 mojom::UmaChildPingStatus::CHILD_RECEIVED_IPC);
115
116 std::move(callback).Run();
117 }
118
119 } // namespace metrics
120