1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chrome_process_singleton.h"
#include <utility>
#include "build/build_config.h"
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#include "base/compiler_specific.h"
#include "base/metrics/histogram_functions.h"
#include "chrome/common/chrome_features.h"
#include "components/app_launch_prefetch/app_launch_prefetch.h"
#endif
namespace {
ChromeProcessSingleton* g_chrome_process_singleton_ = nullptr;
} // namespace
ChromeProcessSingleton::ChromeProcessSingleton(
const base::FilePath& user_data_dir)
: startup_lock_(
base::BindRepeating(&ChromeProcessSingleton::NotificationCallback,
base::Unretained(this))),
process_singleton_(user_data_dir,
startup_lock_.AsNotificationCallback()) {}
ChromeProcessSingleton::~ChromeProcessSingleton() = default;
ProcessSingleton::NotifyResult
ChromeProcessSingleton::NotifyOtherProcessOrCreate() {
CHECK(!is_singleton_instance_);
ProcessSingleton::NotifyResult result =
process_singleton_.NotifyOtherProcessOrCreate();
if (result == ProcessSingleton::PROCESS_NONE) {
is_singleton_instance_ = true;
}
return result;
}
void ChromeProcessSingleton::StartWatching() {
process_singleton_.StartWatching();
}
void ChromeProcessSingleton::Cleanup() {
if (is_singleton_instance_) {
process_singleton_.Cleanup();
}
}
void ChromeProcessSingleton::Unlock(
const ProcessSingleton::NotificationCallback& notification_callback) {
notification_callback_ = notification_callback;
startup_lock_.Unlock();
}
#if BUILDFLAG(IS_WIN)
void ChromeProcessSingleton::InitializeFeatures() {
// On Windows, App Launch Prefetch (ALPF) will monitor the disk accesses done
// by processes launched, and load the resources used into memory before the
// process needs them, if possible. Different Chrome process types use
// different resources, and this is signaled to ALPF via the command line:
// passing "/prefetch:N" on the command line with different numbers causes
// ALPF to treat two launches placed in different buckets as separarate
// applications for its purposes.
//
// Short lived browser processes occur on notification and rendezvous, both
// cases where nearly nothing will be used from disk, and which are not
// launched with `/prefetch`, and are thus considered "browser" processes
// according to ALPF. This may be polluting the ALPF cache.
//
// The `::ProcessOverrideSubsequentPrefetchParameter` process information
// attribute will change the behavior of ALPF to explicitly consider
// subsequent launches while this singleton process is running (rendezvous,
// toast) of Chrome which do not specify a prefetch bucket as if they had
// specified the `kCatchAll` bucket.
//
// It is expected that this will overall improve the behavior of ALPF on
// Windows, which should decrease startup time for ordinary browser processes.
if (is_singleton_instance_ &&
(UNSAFE_TODO(wcsstr(::GetCommandLineW(), L"/prefetch:")) == nullptr) &&
base::FeatureList::IsEnabled(features::kOverridePrefetchOnSingleton)) {
OVERRIDE_PREFETCH_PARAMETER prefetch_parameter = {};
prefetch_parameter.Value = app_launch_prefetch::GetPrefetchBucket(
app_launch_prefetch::SubprocessType::kCatchAll);
// This is not fatal because it is an optimization and has no bearing on the
// functionality of the browser. See crbug.com/380088804 for details. It has
// been seen that occasionally (in CQ), this call fails with
// ERROR_INTERNAL_ERROR.
base::UmaHistogramSparse(
"Startup.PrefetchOverrideErrorCode",
::SetProcessInformation(::GetCurrentProcess(),
::ProcessOverrideSubsequentPrefetchParameter,
&prefetch_parameter, sizeof(prefetch_parameter))
? ERROR_SUCCESS
: ::GetLastError());
}
}
#endif
// static
void ChromeProcessSingleton::CreateInstance(
const base::FilePath& user_data_dir) {
DCHECK(!g_chrome_process_singleton_);
DCHECK(!user_data_dir.empty());
g_chrome_process_singleton_ = new ChromeProcessSingleton(user_data_dir);
}
// static
void ChromeProcessSingleton::DeleteInstance() {
if (g_chrome_process_singleton_) {
delete g_chrome_process_singleton_;
g_chrome_process_singleton_ = nullptr;
}
}
// static
ChromeProcessSingleton* ChromeProcessSingleton::GetInstance() {
CHECK(g_chrome_process_singleton_);
return g_chrome_process_singleton_;
}
// static
bool ChromeProcessSingleton::IsSingletonInstance() {
return g_chrome_process_singleton_ &&
g_chrome_process_singleton_->is_singleton_instance_;
}
bool ChromeProcessSingleton::NotificationCallback(
base::CommandLine command_line,
const base::FilePath& current_directory) {
DCHECK(notification_callback_);
return notification_callback_.Run(std::move(command_line), current_directory);
}
|