1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "components/metrics/persistent_histograms.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include "base/files/file_enumerator.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/metrics/field_trial.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/metrics/field_trial_params.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_functions.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/metrics/persistent_histogram_allocator.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/system/sys_info.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/task/thread_pool.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
19*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
20*6777b538SAndroid Build Coastguard Worker #include "build/chromeos_buildflags.h"
21*6777b538SAndroid Build Coastguard Worker #include "components/metrics/persistent_system_profile.h"
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker namespace {
24*6777b538SAndroid Build Coastguard Worker // Creating a "spare" file for persistent metrics involves a lot of I/O and
25*6777b538SAndroid Build Coastguard Worker // isn't important so delay the operation for a while after startup.
26*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
27*6777b538SAndroid Build Coastguard Worker // Android needs the spare file and also launches faster.
28*6777b538SAndroid Build Coastguard Worker constexpr bool kSpareFileRequired = true;
29*6777b538SAndroid Build Coastguard Worker constexpr int kSpareFileCreateDelaySeconds = 10;
30*6777b538SAndroid Build Coastguard Worker #else
31*6777b538SAndroid Build Coastguard Worker // Desktop may have to restore a lot of tabs so give it more time before doing
32*6777b538SAndroid Build Coastguard Worker // non-essential work. The spare file is still a performance boost but not as
33*6777b538SAndroid Build Coastguard Worker // significant of one so it's not required.
34*6777b538SAndroid Build Coastguard Worker constexpr bool kSpareFileRequired = false;
35*6777b538SAndroid Build Coastguard Worker constexpr int kSpareFileCreateDelaySeconds = 90;
36*6777b538SAndroid Build Coastguard Worker #endif
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker // Windows sometimes creates files of the form MyFile.pma~RF71cb1793.TMP
41*6777b538SAndroid Build Coastguard Worker // when trying to rename a file to something that exists but is in-use, and
42*6777b538SAndroid Build Coastguard Worker // then fails to remove them. See https://crbug.com/934164
DeleteOldWindowsTempFiles(const base::FilePath & dir)43*6777b538SAndroid Build Coastguard Worker void DeleteOldWindowsTempFiles(const base::FilePath& dir) {
44*6777b538SAndroid Build Coastguard Worker // Look for any temp files older than one day and remove them. The time check
45*6777b538SAndroid Build Coastguard Worker // ensures that nothing in active transition gets deleted; these names only
46*6777b538SAndroid Build Coastguard Worker // exists on the order of milliseconds when working properly so "one day" is
47*6777b538SAndroid Build Coastguard Worker // generous but still ensures no big build up of these files. This is an
48*6777b538SAndroid Build Coastguard Worker // I/O intensive task so do it in the background (enforced by "file" calls).
49*6777b538SAndroid Build Coastguard Worker base::Time one_day_ago = base::Time::Now() - base::Days(1);
50*6777b538SAndroid Build Coastguard Worker base::FileEnumerator file_iter(dir, /*recursive=*/false,
51*6777b538SAndroid Build Coastguard Worker base::FileEnumerator::FILES);
52*6777b538SAndroid Build Coastguard Worker for (base::FilePath path = file_iter.Next(); !path.empty();
53*6777b538SAndroid Build Coastguard Worker path = file_iter.Next()) {
54*6777b538SAndroid Build Coastguard Worker if (base::ToUpperASCII(path.FinalExtension()) !=
55*6777b538SAndroid Build Coastguard Worker FILE_PATH_LITERAL(".TMP") ||
56*6777b538SAndroid Build Coastguard Worker base::ToUpperASCII(path.BaseName().value())
57*6777b538SAndroid Build Coastguard Worker .find(FILE_PATH_LITERAL(".PMA~RF")) < 0) {
58*6777b538SAndroid Build Coastguard Worker continue;
59*6777b538SAndroid Build Coastguard Worker }
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker const auto& info = file_iter.GetInfo();
62*6777b538SAndroid Build Coastguard Worker if (info.IsDirectory())
63*6777b538SAndroid Build Coastguard Worker continue;
64*6777b538SAndroid Build Coastguard Worker if (info.GetLastModifiedTime() > one_day_ago)
65*6777b538SAndroid Build Coastguard Worker continue;
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker base::DeleteFile(path);
68*6777b538SAndroid Build Coastguard Worker }
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker
71*6777b538SAndroid Build Coastguard Worker // How much time after startup to run the above function. Two minutes is
72*6777b538SAndroid Build Coastguard Worker // enough for the system to stabilize and get the user what they want before
73*6777b538SAndroid Build Coastguard Worker // spending time on clean-up efforts.
74*6777b538SAndroid Build Coastguard Worker constexpr base::TimeDelta kDeleteOldWindowsTempFilesDelay = base::Minutes(2);
75*6777b538SAndroid Build Coastguard Worker
76*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_WIN)
77*6777b538SAndroid Build Coastguard Worker
78*6777b538SAndroid Build Coastguard Worker // Create persistent/shared memory and allow histograms to be stored in
79*6777b538SAndroid Build Coastguard Worker // it. Memory that is not actually used won't be physically mapped by the
80*6777b538SAndroid Build Coastguard Worker // system. BrowserMetrics usage, as reported in UMA, has the 99.99
81*6777b538SAndroid Build Coastguard Worker // percentile around 3MiB as of 2018-10-22.
82*6777b538SAndroid Build Coastguard Worker // Please update ServicificationBackgroundServiceTest.java if the |kAllocSize|
83*6777b538SAndroid Build Coastguard Worker // is changed.
84*6777b538SAndroid Build Coastguard Worker const size_t kAllocSize = 4 << 20; // 4 MiB
85*6777b538SAndroid Build Coastguard Worker const uint32_t kAllocId = 0x935DDD43; // SHA1(BrowserMetrics)
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Worker // Logged to UMA - keep in sync with enums.xml.
88*6777b538SAndroid Build Coastguard Worker enum InitResult {
89*6777b538SAndroid Build Coastguard Worker kLocalMemorySuccess,
90*6777b538SAndroid Build Coastguard Worker kLocalMemoryFailed,
91*6777b538SAndroid Build Coastguard Worker kMappedFileSuccess,
92*6777b538SAndroid Build Coastguard Worker kMappedFileFailed,
93*6777b538SAndroid Build Coastguard Worker kMappedFileExists,
94*6777b538SAndroid Build Coastguard Worker kNoSpareFile,
95*6777b538SAndroid Build Coastguard Worker kNoUploadDir,
96*6777b538SAndroid Build Coastguard Worker kMaxValue = kNoUploadDir
97*6777b538SAndroid Build Coastguard Worker };
98*6777b538SAndroid Build Coastguard Worker
GetSpareFilePath(const base::FilePath & metrics_dir)99*6777b538SAndroid Build Coastguard Worker base::FilePath GetSpareFilePath(const base::FilePath& metrics_dir) {
100*6777b538SAndroid Build Coastguard Worker return base::GlobalHistogramAllocator::ConstructFilePath(
101*6777b538SAndroid Build Coastguard Worker metrics_dir, kBrowserMetricsName + std::string("-spare"));
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker
104*6777b538SAndroid Build Coastguard Worker // Initializes persistent histograms with a memory-mapped file.
InitWithMappedFile(const base::FilePath & metrics_dir,const base::FilePath & upload_dir)105*6777b538SAndroid Build Coastguard Worker InitResult InitWithMappedFile(const base::FilePath& metrics_dir,
106*6777b538SAndroid Build Coastguard Worker const base::FilePath& upload_dir) {
107*6777b538SAndroid Build Coastguard Worker // The spare file in the user data dir ("BrowserMetrics-spare.pma") would
108*6777b538SAndroid Build Coastguard Worker // have been created in the previous session. We will move it to |upload_dir|
109*6777b538SAndroid Build Coastguard Worker // and rename it with the current time and process id for use as |active_file|
110*6777b538SAndroid Build Coastguard Worker // (e.g. "BrowserMetrics/BrowserMetrics-1234ABCD-12345.pma").
111*6777b538SAndroid Build Coastguard Worker // Any unreported metrics in this file will be uploaded next session.
112*6777b538SAndroid Build Coastguard Worker base::FilePath spare_file = GetSpareFilePath(metrics_dir);
113*6777b538SAndroid Build Coastguard Worker base::FilePath active_file =
114*6777b538SAndroid Build Coastguard Worker base::GlobalHistogramAllocator::ConstructFilePathForUploadDir(
115*6777b538SAndroid Build Coastguard Worker upload_dir, kBrowserMetricsName, base::Time::Now(),
116*6777b538SAndroid Build Coastguard Worker base::GetCurrentProcId());
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker InitResult result;
119*6777b538SAndroid Build Coastguard Worker if (!base::PathExists(upload_dir)) {
120*6777b538SAndroid Build Coastguard Worker // Handle failure to create the directory.
121*6777b538SAndroid Build Coastguard Worker result = kNoUploadDir;
122*6777b538SAndroid Build Coastguard Worker } else if (base::PathExists(active_file)) {
123*6777b538SAndroid Build Coastguard Worker // "active" filename is supposed to be unique so this shouldn't happen.
124*6777b538SAndroid Build Coastguard Worker result = kMappedFileExists;
125*6777b538SAndroid Build Coastguard Worker } else {
126*6777b538SAndroid Build Coastguard Worker // Disallow multiple writers (Windows only). Needed to ensure multiple
127*6777b538SAndroid Build Coastguard Worker // instances of Chrome aren't writing to the same file, which could happen
128*6777b538SAndroid Build Coastguard Worker // in some rare circumstances observed in the wild (e.g. on FAT FS where the
129*6777b538SAndroid Build Coastguard Worker // file name ends up not being unique due to truncation and two processes
130*6777b538SAndroid Build Coastguard Worker // racing on base::PathExists(active_file) above).
131*6777b538SAndroid Build Coastguard Worker const bool exclusive_write = true;
132*6777b538SAndroid Build Coastguard Worker // Move any spare file into the active position.
133*6777b538SAndroid Build Coastguard Worker base::ReplaceFile(spare_file, active_file, nullptr);
134*6777b538SAndroid Build Coastguard Worker // Create global allocator using the |active_file|.
135*6777b538SAndroid Build Coastguard Worker if (kSpareFileRequired && !base::PathExists(active_file)) {
136*6777b538SAndroid Build Coastguard Worker result = kNoSpareFile;
137*6777b538SAndroid Build Coastguard Worker } else if (base::GlobalHistogramAllocator::CreateWithFile(
138*6777b538SAndroid Build Coastguard Worker active_file, kAllocSize, kAllocId, kBrowserMetricsName,
139*6777b538SAndroid Build Coastguard Worker exclusive_write)) {
140*6777b538SAndroid Build Coastguard Worker result = kMappedFileSuccess;
141*6777b538SAndroid Build Coastguard Worker } else {
142*6777b538SAndroid Build Coastguard Worker result = kMappedFileFailed;
143*6777b538SAndroid Build Coastguard Worker }
144*6777b538SAndroid Build Coastguard Worker }
145*6777b538SAndroid Build Coastguard Worker
146*6777b538SAndroid Build Coastguard Worker return result;
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker
149*6777b538SAndroid Build Coastguard Worker enum PersistentHistogramsMode {
150*6777b538SAndroid Build Coastguard Worker kNotEnabled,
151*6777b538SAndroid Build Coastguard Worker kMappedFile,
152*6777b538SAndroid Build Coastguard Worker kLocalMemory,
153*6777b538SAndroid Build Coastguard Worker };
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker // Implementation of InstantiatePersistentHistograms() that does the work after
156*6777b538SAndroid Build Coastguard Worker // the desired |mode| has been determined.
InstantiatePersistentHistogramsImpl(const base::FilePath & metrics_dir,PersistentHistogramsMode mode)157*6777b538SAndroid Build Coastguard Worker void InstantiatePersistentHistogramsImpl(const base::FilePath& metrics_dir,
158*6777b538SAndroid Build Coastguard Worker PersistentHistogramsMode mode) {
159*6777b538SAndroid Build Coastguard Worker // Create a directory for storing completed metrics files. Files in this
160*6777b538SAndroid Build Coastguard Worker // directory must have embedded system profiles. If the directory can't be
161*6777b538SAndroid Build Coastguard Worker // created, the file will just be deleted below.
162*6777b538SAndroid Build Coastguard Worker base::FilePath upload_dir = metrics_dir.AppendASCII(kBrowserMetricsName);
163*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/1183166): Only create the dir in kMappedFile mode.
164*6777b538SAndroid Build Coastguard Worker base::CreateDirectory(upload_dir);
165*6777b538SAndroid Build Coastguard Worker
166*6777b538SAndroid Build Coastguard Worker InitResult result;
167*6777b538SAndroid Build Coastguard Worker
168*6777b538SAndroid Build Coastguard Worker // Create a global histogram allocator using the desired storage type.
169*6777b538SAndroid Build Coastguard Worker switch (mode) {
170*6777b538SAndroid Build Coastguard Worker case kMappedFile:
171*6777b538SAndroid Build Coastguard Worker result = InitWithMappedFile(metrics_dir, upload_dir);
172*6777b538SAndroid Build Coastguard Worker break;
173*6777b538SAndroid Build Coastguard Worker case kLocalMemory:
174*6777b538SAndroid Build Coastguard Worker // Use local memory for storage even though it will not persist across
175*6777b538SAndroid Build Coastguard Worker // an unclean shutdown. This sets the result but the actual creation is
176*6777b538SAndroid Build Coastguard Worker // done below.
177*6777b538SAndroid Build Coastguard Worker result = kLocalMemorySuccess;
178*6777b538SAndroid Build Coastguard Worker break;
179*6777b538SAndroid Build Coastguard Worker case kNotEnabled:
180*6777b538SAndroid Build Coastguard Worker // Persistent metric storage is disabled. Must return here.
181*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/1183166): Log the histogram below in this case too.
182*6777b538SAndroid Build Coastguard Worker return;
183*6777b538SAndroid Build Coastguard Worker }
184*6777b538SAndroid Build Coastguard Worker
185*6777b538SAndroid Build Coastguard Worker // Get the allocator that was just created and report result. Exit if the
186*6777b538SAndroid Build Coastguard Worker // allocator could not be created.
187*6777b538SAndroid Build Coastguard Worker base::UmaHistogramEnumeration("UMA.PersistentHistograms.InitResult", result);
188*6777b538SAndroid Build Coastguard Worker
189*6777b538SAndroid Build Coastguard Worker base::GlobalHistogramAllocator* allocator =
190*6777b538SAndroid Build Coastguard Worker base::GlobalHistogramAllocator::Get();
191*6777b538SAndroid Build Coastguard Worker if (!allocator) {
192*6777b538SAndroid Build Coastguard Worker // If no allocator was created above, try to create a LocalMemory one here.
193*6777b538SAndroid Build Coastguard Worker // This avoids repeating the call many times above. In the case where
194*6777b538SAndroid Build Coastguard Worker // persistence is disabled, an early return is done above.
195*6777b538SAndroid Build Coastguard Worker base::GlobalHistogramAllocator::CreateWithLocalMemory(kAllocSize, kAllocId,
196*6777b538SAndroid Build Coastguard Worker kBrowserMetricsName);
197*6777b538SAndroid Build Coastguard Worker allocator = base::GlobalHistogramAllocator::Get();
198*6777b538SAndroid Build Coastguard Worker if (!allocator) {
199*6777b538SAndroid Build Coastguard Worker return;
200*6777b538SAndroid Build Coastguard Worker }
201*6777b538SAndroid Build Coastguard Worker }
202*6777b538SAndroid Build Coastguard Worker
203*6777b538SAndroid Build Coastguard Worker // Store a copy of the system profile in this allocator.
204*6777b538SAndroid Build Coastguard Worker metrics::GlobalPersistentSystemProfile::GetInstance()
205*6777b538SAndroid Build Coastguard Worker ->RegisterPersistentAllocator(allocator->memory_allocator());
206*6777b538SAndroid Build Coastguard Worker
207*6777b538SAndroid Build Coastguard Worker // Create tracking histograms for the allocator and record storage file.
208*6777b538SAndroid Build Coastguard Worker allocator->CreateTrackingHistograms(kBrowserMetricsName);
209*6777b538SAndroid Build Coastguard Worker }
210*6777b538SAndroid Build Coastguard Worker
211*6777b538SAndroid Build Coastguard Worker } // namespace
212*6777b538SAndroid Build Coastguard Worker
213*6777b538SAndroid Build Coastguard Worker BASE_FEATURE(
214*6777b538SAndroid Build Coastguard Worker kPersistentHistogramsFeature,
215*6777b538SAndroid Build Coastguard Worker "PersistentHistograms",
216*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_FUCHSIA)
217*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/42050425): Enable once writable mmap() is supported. Also
218*6777b538SAndroid Build Coastguard Worker // move the initialization earlier to chrome/app/chrome_main_delegate.cc.
219*6777b538SAndroid Build Coastguard Worker base::FEATURE_DISABLED_BY_DEFAULT
220*6777b538SAndroid Build Coastguard Worker #else
221*6777b538SAndroid Build Coastguard Worker base::FEATURE_ENABLED_BY_DEFAULT
222*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_FUCHSIA)
223*6777b538SAndroid Build Coastguard Worker );
224*6777b538SAndroid Build Coastguard Worker
225*6777b538SAndroid Build Coastguard Worker const char kPersistentHistogramStorageMappedFile[] = "MappedFile";
226*6777b538SAndroid Build Coastguard Worker const char kPersistentHistogramStorageLocalMemory[] = "LocalMemory";
227*6777b538SAndroid Build Coastguard Worker
228*6777b538SAndroid Build Coastguard Worker const base::FeatureParam<std::string> kPersistentHistogramsStorage{
229*6777b538SAndroid Build Coastguard Worker &kPersistentHistogramsFeature, "storage",
230*6777b538SAndroid Build Coastguard Worker kPersistentHistogramStorageMappedFile};
231*6777b538SAndroid Build Coastguard Worker
232*6777b538SAndroid Build Coastguard Worker const char kBrowserMetricsName[] = "BrowserMetrics";
233*6777b538SAndroid Build Coastguard Worker const char kDeferredBrowserMetricsName[] = "DeferredBrowserMetrics";
234*6777b538SAndroid Build Coastguard Worker
InstantiatePersistentHistograms(const base::FilePath & metrics_dir,bool persistent_histograms_enabled,base::StringPiece storage)235*6777b538SAndroid Build Coastguard Worker void InstantiatePersistentHistograms(const base::FilePath& metrics_dir,
236*6777b538SAndroid Build Coastguard Worker bool persistent_histograms_enabled,
237*6777b538SAndroid Build Coastguard Worker base::StringPiece storage) {
238*6777b538SAndroid Build Coastguard Worker PersistentHistogramsMode mode = kNotEnabled;
239*6777b538SAndroid Build Coastguard Worker // Note: The extra feature check is needed so that we don't use the default
240*6777b538SAndroid Build Coastguard Worker // value of the storage param if the feature is disabled.
241*6777b538SAndroid Build Coastguard Worker if (persistent_histograms_enabled) {
242*6777b538SAndroid Build Coastguard Worker if (storage == kPersistentHistogramStorageMappedFile) {
243*6777b538SAndroid Build Coastguard Worker mode = kMappedFile;
244*6777b538SAndroid Build Coastguard Worker } else if (storage == kPersistentHistogramStorageLocalMemory) {
245*6777b538SAndroid Build Coastguard Worker mode = kLocalMemory;
246*6777b538SAndroid Build Coastguard Worker }
247*6777b538SAndroid Build Coastguard Worker }
248*6777b538SAndroid Build Coastguard Worker
249*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
250*6777b538SAndroid Build Coastguard Worker // of lacros-chrome is complete.
251*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
252*6777b538SAndroid Build Coastguard Worker // Linux kernel 4.4.0.* shows a huge number of SIGBUS crashes with persistent
253*6777b538SAndroid Build Coastguard Worker // histograms enabled using a mapped file. Change this to use local memory.
254*6777b538SAndroid Build Coastguard Worker // https://bugs.chromium.org/p/chromium/issues/detail?id=753741
255*6777b538SAndroid Build Coastguard Worker if (mode == kMappedFile) {
256*6777b538SAndroid Build Coastguard Worker int major, minor, bugfix;
257*6777b538SAndroid Build Coastguard Worker base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
258*6777b538SAndroid Build Coastguard Worker if (major == 4 && minor == 4 && bugfix == 0)
259*6777b538SAndroid Build Coastguard Worker mode = kLocalMemory;
260*6777b538SAndroid Build Coastguard Worker }
261*6777b538SAndroid Build Coastguard Worker #endif
262*6777b538SAndroid Build Coastguard Worker
263*6777b538SAndroid Build Coastguard Worker InstantiatePersistentHistogramsImpl(metrics_dir, mode);
264*6777b538SAndroid Build Coastguard Worker }
265*6777b538SAndroid Build Coastguard Worker
PersistentHistogramsCleanup(const base::FilePath & metrics_dir)266*6777b538SAndroid Build Coastguard Worker void PersistentHistogramsCleanup(const base::FilePath& metrics_dir) {
267*6777b538SAndroid Build Coastguard Worker base::FilePath spare_file = GetSpareFilePath(metrics_dir);
268*6777b538SAndroid Build Coastguard Worker
269*6777b538SAndroid Build Coastguard Worker // Schedule the creation of a "spare" file for use on the next run.
270*6777b538SAndroid Build Coastguard Worker base::ThreadPool::PostDelayedTask(
271*6777b538SAndroid Build Coastguard Worker FROM_HERE,
272*6777b538SAndroid Build Coastguard Worker {base::MayBlock(), base::TaskPriority::LOWEST,
273*6777b538SAndroid Build Coastguard Worker base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
274*6777b538SAndroid Build Coastguard Worker base::BindOnce(
275*6777b538SAndroid Build Coastguard Worker base::IgnoreResult(&base::GlobalHistogramAllocator::CreateSpareFile),
276*6777b538SAndroid Build Coastguard Worker std::move(spare_file), kAllocSize),
277*6777b538SAndroid Build Coastguard Worker base::Seconds(kSpareFileCreateDelaySeconds));
278*6777b538SAndroid Build Coastguard Worker
279*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
280*6777b538SAndroid Build Coastguard Worker // Post a best effort task that will delete files. Unlike SKIP_ON_SHUTDOWN,
281*6777b538SAndroid Build Coastguard Worker // which will block on the deletion if the task already started,
282*6777b538SAndroid Build Coastguard Worker // CONTINUE_ON_SHUTDOWN will not block shutdown on the task completing. It's
283*6777b538SAndroid Build Coastguard Worker // not a *necessity* to delete the files the same session they are "detected".
284*6777b538SAndroid Build Coastguard Worker // On shutdown, the deletion will be interrupted.
285*6777b538SAndroid Build Coastguard Worker base::ThreadPool::PostDelayedTask(
286*6777b538SAndroid Build Coastguard Worker FROM_HERE,
287*6777b538SAndroid Build Coastguard Worker {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
288*6777b538SAndroid Build Coastguard Worker base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
289*6777b538SAndroid Build Coastguard Worker base::BindOnce(&DeleteOldWindowsTempFiles, metrics_dir),
290*6777b538SAndroid Build Coastguard Worker kDeleteOldWindowsTempFilesDelay);
291*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_WIN)
292*6777b538SAndroid Build Coastguard Worker }
293*6777b538SAndroid Build Coastguard Worker
InstantiatePersistentHistogramsWithFeaturesAndCleanup(const base::FilePath & metrics_dir)294*6777b538SAndroid Build Coastguard Worker void InstantiatePersistentHistogramsWithFeaturesAndCleanup(
295*6777b538SAndroid Build Coastguard Worker const base::FilePath& metrics_dir) {
296*6777b538SAndroid Build Coastguard Worker InstantiatePersistentHistograms(
297*6777b538SAndroid Build Coastguard Worker metrics_dir, base::FeatureList::IsEnabled(kPersistentHistogramsFeature),
298*6777b538SAndroid Build Coastguard Worker kPersistentHistogramsStorage.Get());
299*6777b538SAndroid Build Coastguard Worker PersistentHistogramsCleanup(metrics_dir);
300*6777b538SAndroid Build Coastguard Worker }
301*6777b538SAndroid Build Coastguard Worker
DeferBrowserMetrics(const base::FilePath & metrics_dir)302*6777b538SAndroid Build Coastguard Worker bool DeferBrowserMetrics(const base::FilePath& metrics_dir) {
303*6777b538SAndroid Build Coastguard Worker base::GlobalHistogramAllocator* allocator =
304*6777b538SAndroid Build Coastguard Worker base::GlobalHistogramAllocator::Get();
305*6777b538SAndroid Build Coastguard Worker
306*6777b538SAndroid Build Coastguard Worker if (!allocator || !allocator->HasPersistentLocation()) {
307*6777b538SAndroid Build Coastguard Worker return false;
308*6777b538SAndroid Build Coastguard Worker }
309*6777b538SAndroid Build Coastguard Worker
310*6777b538SAndroid Build Coastguard Worker base::FilePath deferred_metrics_dir =
311*6777b538SAndroid Build Coastguard Worker metrics_dir.AppendASCII(kDeferredBrowserMetricsName);
312*6777b538SAndroid Build Coastguard Worker
313*6777b538SAndroid Build Coastguard Worker if (!base::CreateDirectory(deferred_metrics_dir)) {
314*6777b538SAndroid Build Coastguard Worker return false;
315*6777b538SAndroid Build Coastguard Worker }
316*6777b538SAndroid Build Coastguard Worker
317*6777b538SAndroid Build Coastguard Worker return allocator->MovePersistentFile(deferred_metrics_dir);
318*6777b538SAndroid Build Coastguard Worker }
319