summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancois Doray <fdoray@chromium.org>2016-02-23 18:50:30 -0500
committerFrancois Doray <fdoray@chromium.org>2016-02-23 23:53:56 +0000
commit97ae8295dfda25dc394112cb84741df9949a65f9 (patch)
tree643a6747f9e83fdcda7226039afd4e5166791df0
parent489f16983f03efade031d3fec1f4b4ce849052ad (diff)
downloadchromium_src-97ae8295dfda25dc394112cb84741df9949a65f9.zip
chromium_src-97ae8295dfda25dc394112cb84741df9949a65f9.tar.gz
chromium_src-97ae8295dfda25dc394112cb84741df9949a65f9.tar.bz2
Use a valid /prefetch argument when launching a process.
The /prefetch:# argument that is currently added to the command line of processes launched with content::StartSandboxedProcess is ignored by Windows because # doesn't respect the [1, 8] constraint. This CL ensures that a valid /prefetch:# argument is used for every process launch (except when the feature is disabled by the PreRead field trial). BUG=577698 Review URL: https://codereview.chromium.org/1612663002 Cr-Commit-Position: refs/heads/master@{#373241} (cherry picked from commit 343068c41c299e65a87d935654f0b81a9935250f) Conflicts: chrome/service/DEPS TBR=gab@chromium.org Review URL: https://codereview.chromium.org/1727983002 . Cr-Commit-Position: refs/branch-heads/2623@{#484} Cr-Branched-From: 92d77538a86529ca35f9220bd3cd512cbea1f086-refs/heads/master@{#369907}
-rw-r--r--chrome/app/chrome_exe_main_win.cc54
-rw-r--r--chrome/app/chrome_watcher_command_line_win.cc7
-rw-r--r--chrome/app/main_dll_loader_win.cc5
-rw-r--r--chrome/browser/BUILD.gn4
-rw-r--r--chrome/browser/browser_process_impl.cc6
-rw-r--r--chrome/browser/chrome_browser_main.cc5
-rw-r--r--chrome/browser/chrome_content_browser_client.cc5
-rw-r--r--chrome/browser/chrome_content_browser_client.h1
-rw-r--r--chrome/chrome.gyp11
-rw-r--r--chrome/chrome_browser.gypi3
-rw-r--r--chrome/chrome_common.gypi3
-rw-r--r--chrome/chrome_installer_util.gypi3
-rw-r--r--chrome/common/BUILD.gn8
-rw-r--r--chrome/common/DEPS3
-rw-r--r--chrome/common/chrome_switches.cc8
-rw-r--r--chrome/common/chrome_switches.h2
-rw-r--r--chrome/common/service_process_util.cc10
-rw-r--r--chrome/installer/util/BUILD.gn4
-rw-r--r--chrome/installer/util/DEPS5
-rw-r--r--chrome/installer/util/auto_launch_util.cc4
-rw-r--r--chrome/service/BUILD.gn5
-rw-r--r--chrome/service/DEPS5
-rw-r--r--chrome/service/service_utility_process_host.cc9
-rw-r--r--cloud_print/service/win/chrome_launcher.cc4
-rw-r--r--components/crash.gypi7
-rw-r--r--components/crash/content/app/BUILD.gn7
-rw-r--r--components/crash/content/app/DEPS5
-rw-r--r--components/crash/content/app/crashpad_win.cc8
-rw-r--r--components/nacl.gyp7
-rw-r--r--components/nacl/browser/BUILD.gn8
-rw-r--r--components/nacl/browser/DEPS3
-rw-r--r--components/nacl/browser/nacl_process_host.cc8
-rw-r--r--components/startup_metric_utils/common/pre_read_field_trial_utils_win.cc40
-rw-r--r--components/startup_metric_utils/common/pre_read_field_trial_utils_win.h7
-rw-r--r--content/browser/gpu/gpu_process_host.cc5
-rw-r--r--content/browser/plugin_process_host.cc5
-rw-r--r--content/browser/ppapi_plugin_process_host.cc7
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc5
-rw-r--r--content/browser/utility_process_host_impl.cc5
-rw-r--r--content/common/sandbox_win.cc5
-rw-r--r--content/public/browser/content_browser_client.cc6
-rw-r--r--content/public/browser/content_browser_client.h4
-rw-r--r--content/public/common/content_switches.cc24
-rw-r--r--content/public/common/content_switches.h5
44 files changed, 298 insertions, 47 deletions
diff --git a/chrome/app/chrome_exe_main_win.cc b/chrome/app/chrome_exe_main_win.cc
index 2102ae1..089ca12 100644
--- a/chrome/app/chrome_exe_main_win.cc
+++ b/chrome/app/chrome_exe_main_win.cc
@@ -17,6 +17,8 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/win/windows_version.h"
@@ -26,10 +28,12 @@
#include "chrome/browser/policy/policy_path_parser.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/installer/util/browser_distribution.h"
#include "chrome_elf/chrome_elf_main.h"
#include "components/crash/content/app/crash_reporter_client.h"
#include "components/crash/content/app/crashpad.h"
#include "components/startup_metric_utils/browser/startup_metric_utils.h"
+#include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "third_party/crashpad/crashpad/handler/handler_main.h"
@@ -152,15 +156,39 @@ int RunAsCrashpadHandler(const base::CommandLine& command_line) {
scoped_ptr<char* []> argv_as_utf8(new char*[argv.size() + 1]);
std::vector<std::string> storage;
storage.reserve(argv.size());
+
+ size_t arg_append_index = 0;
for (size_t i = 0; i < argv.size(); ++i) {
+ // Remove arguments starting with '/' as they are not supported by crashpad.
+ if (!argv[i].empty() && argv[i].front() == L'/')
+ continue;
+
storage.push_back(base::UTF16ToUTF8(argv[i]));
- argv_as_utf8[i] = &storage[i][0];
+ argv_as_utf8[arg_append_index] = &storage[arg_append_index][0];
+ ++arg_append_index;
}
- argv_as_utf8[argv.size()] = nullptr;
- return crashpad::HandlerMain(static_cast<int>(argv.size()),
+ argv_as_utf8[arg_append_index] = nullptr;
+
+ return crashpad::HandlerMain(static_cast<int>(storage.size()),
argv_as_utf8.get());
}
+// Returns true if |command_line| contains a /prefetch:# argument where # is in
+// [1, 8].
+bool HasValidWindowsPrefetchArgument(const base::CommandLine& command_line) {
+ const base::char16 kPrefetchArgumentPrefix[] = L"/prefetch:";
+
+ for (const auto& arg : command_line.argv()) {
+ if (arg.size() == arraysize(kPrefetchArgumentPrefix) &&
+ base::StartsWith(arg, kPrefetchArgumentPrefix,
+ base::CompareCase::SENSITIVE)) {
+ return arg[arraysize(kPrefetchArgumentPrefix) - 1] >= L'1' &&
+ arg[arraysize(kPrefetchArgumentPrefix) - 1] <= L'8';
+ }
+ }
+ return false;
+}
+
} // namespace
// This helper is looked up in the browser to retrieve the crash reports. See
@@ -183,10 +211,22 @@ int main() {
#endif
// Initialize the CommandLine singleton from the environment.
base::CommandLine::Init(0, nullptr);
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+
+ const std::string process_type =
+ command_line->GetSwitchValueASCII(switches::kProcessType);
+
+ startup_metric_utils::InitializePreReadOptions(
+ BrowserDistribution::GetDistribution()->GetRegistryPath());
- std::string process_type =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kProcessType);
+ // Confirm that an explicit prefetch profile is used for all process types
+ // except for the browser process. Any new process type will have to assign
+ // itself a prefetch id. See kPrefetchArgument* constants in
+ // content_switches.cc for details.
+ DCHECK(!startup_metric_utils::GetPreReadOptions().use_prefetch_argument ||
+ process_type.empty() ||
+ HasValidWindowsPrefetchArgument(*command_line));
if (process_type == switches::kCrashpadHandler)
return RunAsCrashpadHandler(*base::CommandLine::ForCurrentProcess());
@@ -210,7 +250,7 @@ int main() {
if (base::win::GetVersion() >= base::win::VERSION_WIN7)
EnableHighDPISupport();
- if (AttemptFastNotify(*base::CommandLine::ForCurrentProcess()))
+ if (AttemptFastNotify(*command_line))
return 0;
// Load and launch the chrome dll. *Everything* happens inside.
diff --git a/chrome/app/chrome_watcher_command_line_win.cc b/chrome/app/chrome_watcher_command_line_win.cc
index 9c8106b..2f79dbc 100644
--- a/chrome/app/chrome_watcher_command_line_win.cc
+++ b/chrome/app/chrome_watcher_command_line_win.cc
@@ -15,6 +15,7 @@
#include "base/strings/stringprintf.h"
#include "base/win/win_util.h"
#include "chrome/common/chrome_switches.h"
+#include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.h"
#include "content/public/common/content_switches.h"
namespace {
@@ -154,6 +155,12 @@ base::CommandLine GenerateChromeWatcherCommandLine(
AppendHandleSwitch(kOnIninitializedEventHandleSwitch, on_initialized_event,
&command_line);
AppendHandleSwitch(kParentHandleSwitch, parent_process, &command_line);
+
+#if defined(OS_WIN)
+ if (startup_metric_utils::GetPreReadOptions().use_prefetch_argument)
+ command_line.AppendArg(switches::kPrefetchArgumentWatcher);
+#endif // defined(OS_WIN)
+
return command_line;
}
diff --git a/chrome/app/main_dll_loader_win.cc b/chrome/app/main_dll_loader_win.cc
index f28d301..1c24da1 100644
--- a/chrome/app/main_dll_loader_win.cc
+++ b/chrome/app/main_dll_loader_win.cc
@@ -39,7 +39,6 @@
#include "chrome/common/chrome_result_codes.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/env_vars.h"
-#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/google_update_settings.h"
#include "chrome/installer/util/install_util.h"
@@ -64,13 +63,11 @@ HMODULE LoadModuleWithDirectory(const base::FilePath& module) {
::SetCurrentDirectoryW(module.DirName().value().c_str());
// Get pre-read options from the PreRead field trial.
- startup_metric_utils::InitializePreReadOptions(
- BrowserDistribution::GetDistribution()->GetRegistryPath());
const startup_metric_utils::PreReadOptions pre_read_options =
startup_metric_utils::GetPreReadOptions();
// Pre-read the binary to warm the memory caches (avoids a lot of random IO).
- if (!pre_read_options.no_pre_read) {
+ if (pre_read_options.pre_read) {
base::ThreadPriority previous_priority = base::ThreadPriority::NORMAL;
if (pre_read_options.high_priority) {
previous_priority = base::PlatformThread::GetCurrentThreadPriority();
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 3b535ce..a66cec3 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -163,6 +163,10 @@ source_set("browser") {
"//components/ssl_errors",
"//components/startup_metric_utils/browser:lib",
"//components/startup_metric_utils/browser:message_filter_lib",
+
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ "//components/startup_metric_utils/common",
"//components/strings",
"//components/suggestions",
"//components/sync_bookmarks",
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 4dff7d2..2a2c668 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -111,6 +111,7 @@
#if defined(OS_WIN)
#include "base/win/windows_version.h"
+#include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.h"
#include "ui/views/focus/view_storage.h"
#elif defined(OS_MACOSX)
#include "chrome/browser/chrome_browser_main_mac.h"
@@ -1268,6 +1269,11 @@ void BrowserProcessImpl::RestartBackgroundInstance() {
new_cl->AppendSwitch(kSwitchesToAddOnAutorestart[i]);
}
+#if defined(OS_WIN)
+ if (startup_metric_utils::GetPreReadOptions().use_prefetch_argument)
+ new_cl->AppendArg(switches::kPrefetchArgumentBrowserBackground);
+#endif // defined(OS_WIN)
+
DLOG(WARNING) << "Shutting down current instance of the browser.";
chrome::AttemptExit();
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 75aefe8..512df64 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -583,7 +583,10 @@ void SetupPreReadFieldTrial() {
registry_path,
base::Bind(&ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial));
- // After startup is complete, update the pre-read group in the registry. The
+ // Initialize the PreRead options for the current process.
+ startup_metric_utils::InitializePreReadOptions(registry_path);
+
+ // After startup is complete, update the PreRead group in the registry. The
// group written in the registry will be used for the next startup.
BrowserThread::PostAfterStartupTask(
FROM_HERE, content::BrowserThread::GetBlockingPool(),
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index c3bf71a..21f7f95 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -168,6 +168,7 @@
#include "base/strings/string_tokenizer.h"
#include "base/win/windows_version.h"
#include "chrome/browser/chrome_browser_main_win.h"
+#include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.h"
#include "sandbox/win/src/sandbox_policy.h"
#elif defined(OS_MACOSX)
#include "chrome/browser/chrome_browser_main_mac.h"
@@ -2690,6 +2691,10 @@ bool ChromeContentBrowserClient::IsWin32kLockdownEnabledForMimeType(
return false;
}
+
+bool ChromeContentBrowserClient::ShouldUseWindowsPrefetchArgument() const {
+ return startup_metric_utils::GetPreReadOptions().use_prefetch_argument;
+}
#endif // defined(OS_WIN)
void ChromeContentBrowserClient::RegisterFrameMojoShellServices(
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 6d88e71..060501a 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -281,6 +281,7 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
int sandbox_type) const override;
bool IsWin32kLockdownEnabledForMimeType(
const std::string& mime_type) const override;
+ bool ShouldUseWindowsPrefetchArgument() const override;
#endif
void RegisterFrameMojoShellServices(
content::ServiceRegistry* registry,
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 5a16c54..1f5fd54 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -753,8 +753,6 @@
'service/service_process.h',
'service/service_process_prefs.cc',
'service/service_process_prefs.h',
- 'service/service_utility_process_host.cc',
- 'service/service_utility_process_host.h',
],
'include_dirs': [
'..',
@@ -773,11 +771,16 @@
'service/cloud_print/print_system_dummy.cc',
],
}],
- ['OS!="win"', {
- 'sources!': [
+ ['OS=="win"', {
+ 'sources': [
'service/service_utility_process_host.cc',
'service/service_utility_process_host.h',
],
+ 'deps': [
+ # TODO(fdoray): Remove this once the PreRead field trial has
+ # expired. crbug.com/577698
+ '../components/components.gyp:startup_metric_utils_common',
+ ],
}],
],
},
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index d21934f..1e31929 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -3179,6 +3179,9 @@
'../components/components.gyp:signin_core_browser',
'../components/components.gyp:startup_metric_utils_browser',
'../components/components.gyp:startup_metric_utils_browser_message_filter',
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ '../components/components.gyp:startup_metric_utils_common',
'../components/components.gyp:sync_bookmarks',
'../components/components.gyp:sync_driver',
'../components/components.gyp:sync_sessions',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index bb4e2c3..87b7387 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -340,6 +340,9 @@
'<(DEPTH)/components/components.gyp:metrics_net',
'<(DEPTH)/components/components.gyp:omnibox_common',
'<(DEPTH)/components/components.gyp:policy_component_common',
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ '<(DEPTH)/components/components.gyp:startup_metric_utils_common',
'<(DEPTH)/components/components.gyp:translate_core_common',
'<(DEPTH)/components/components.gyp:variations',
'<(DEPTH)/components/components.gyp:version_info',
diff --git a/chrome/chrome_installer_util.gypi b/chrome/chrome_installer_util.gypi
index 757f4d8..e21ccbd 100644
--- a/chrome/chrome_installer_util.gypi
+++ b/chrome/chrome_installer_util.gypi
@@ -122,6 +122,9 @@
'<(DEPTH)/chrome/chrome_resources.gyp:chrome_strings',
'<(DEPTH)/chrome/common_constants.gyp:common_constants',
'<(DEPTH)/components/components.gyp:metrics',
+ # TODO(fdoray): Remove this once the PreRead field trial has
+ # expired. crbug.com/577698
+ '<(DEPTH)/components/components.gyp:startup_metric_utils_common',
'<(DEPTH)/components/components.gyp:variations',
'<(DEPTH)/courgette/courgette.gyp:courgette_lib',
'<(DEPTH)/crypto/crypto.gyp:crypto',
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index fb57a95..015ede6 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -211,6 +211,14 @@ static_library("common") {
sources += rebase_path(gypi_values.chrome_common_service_process_sources,
".",
"//chrome")
+
+ if (is_win) {
+ deps = [
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ "//components/startup_metric_utils/common",
+ ]
+ }
}
}
diff --git a/chrome/common/DEPS b/chrome/common/DEPS
index ead1d81..52cf585 100644
--- a/chrome/common/DEPS
+++ b/chrome/common/DEPS
@@ -21,6 +21,9 @@ include_rules = [
"+components/printing/common",
"+components/policy/core/common",
"+components/signin/core/common",
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ "+components/startup_metric_utils/common",
"+components/strings/grit",
"+components/translate/core/common",
"+components/url_formatter",
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 1b9d664..c154752 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -1254,6 +1254,14 @@ const char kForceImmersive[] = "force-immersive";
// This flag is only relevant for Windows currently.
const char kNoNetworkProfileWarning[] = "no-network-profile-warning";
+// /prefetch:# arguments for the browser process launched in background mode and
+// for the watcher process. Use profiles 5, 6 and 7 as documented on
+// kPrefetchArgument* in content_switches.cc.
+const char kPrefetchArgumentBrowserBackground[] = "/prefetch:5";
+const char kPrefetchArgumentWatcher[] = "/prefetch:6";
+// /prefetch:7 is used by crashpad, which can't depend on constants defined
+// here. See crashpad_win.cc for more details.
+
// For the DelegateExecute verb handler to launch Chrome in desktop mode on
// Windows 8 and higher. Used when relaunching metro Chrome.
const char kForceDesktop[] = "force-desktop";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 71aac50..4194ae0 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -360,6 +360,8 @@ extern const char kForceDesktop[];
extern const char kForceImmersive[];
extern const char kHideIcons[];
extern const char kNoNetworkProfileWarning[];
+extern const char kPrefetchArgumentBrowserBackground[];
+extern const char kPrefetchArgumentWatcher[];
extern const char kRelaunchShortcut[];
extern const char kShowIcons[];
extern const char kUninstall[];
diff --git a/chrome/common/service_process_util.cc b/chrome/common/service_process_util.cc
index 336c011..cd0724b 100644
--- a/chrome/common/service_process_util.cc
+++ b/chrome/common/service_process_util.cc
@@ -31,6 +31,10 @@
#include "google_apis/gaia/gaia_switches.h"
#include "ui/base/ui_base_switches.h"
+#if defined(OS_WIN)
+#include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.h"
+#endif // defined(OS_WIN)
+
#if !defined(OS_MACOSX)
namespace {
@@ -160,6 +164,12 @@ scoped_ptr<base::CommandLine> CreateServiceProcessCommandLine() {
scoped_ptr<base::CommandLine> command_line(new base::CommandLine(exe_path));
command_line->AppendSwitchASCII(switches::kProcessType,
switches::kServiceProcess);
+
+#if defined(OS_WIN)
+ if (startup_metric_utils::GetPreReadOptions().use_prefetch_argument)
+ command_line->AppendArg(switches::kPrefetchArgumentOther);
+#endif // defined(OS_WIN)
+
static const char* const kSwitchesToCopy[] = {
switches::kCloudPrintSetupProxy,
switches::kCloudPrintURL,
diff --git a/chrome/installer/util/BUILD.gn b/chrome/installer/util/BUILD.gn
index 0faa59e..45a8579 100644
--- a/chrome/installer/util/BUILD.gn
+++ b/chrome/installer/util/BUILD.gn
@@ -109,6 +109,10 @@ static_library("with_no_strings") {
":generate_strings",
"//base/third_party/dynamic_annotations",
"//components/metrics",
+
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ "//components/startup_metric_utils/common",
"//courgette:courgette_lib",
"//crypto",
"//third_party/bspatch",
diff --git a/chrome/installer/util/DEPS b/chrome/installer/util/DEPS
index 448e750..2e7e849 100644
--- a/chrome/installer/util/DEPS
+++ b/chrome/installer/util/DEPS
@@ -4,5 +4,10 @@ include_rules = [
"+chrome/grit/chromium_strings.h",
"+components/metrics",
+
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ "+components/startup_metric_utils/common",
+
"+third_party/crashpad",
]
diff --git a/chrome/installer/util/auto_launch_util.cc b/chrome/installer/util/auto_launch_util.cc
index e61cf76..9fbeab7 100644
--- a/chrome/installer/util/auto_launch_util.cc
+++ b/chrome/installer/util/auto_launch_util.cc
@@ -21,6 +21,7 @@
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/installer/util/util_constants.h"
+#include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.h"
#include "crypto/sha2.h"
namespace {
@@ -59,6 +60,9 @@ void EnableBackgroundStartAtLogin() {
base::CommandLine cmd_line(application_dir.Append(installer::kChromeExe));
cmd_line.AppendSwitch(switches::kNoStartupWindow);
+ if (startup_metric_utils::GetPreReadOptions().use_prefetch_argument)
+ cmd_line.AppendArg(switches::kPrefetchArgumentBrowserBackground);
+
base::win::AddCommandToAutoRun(HKEY_CURRENT_USER, GetAutoLaunchKeyName(),
cmd_line.GetCommandLineString());
}
diff --git a/chrome/service/BUILD.gn b/chrome/service/BUILD.gn
index bb741209..a1ef809 100644
--- a/chrome/service/BUILD.gn
+++ b/chrome/service/BUILD.gn
@@ -71,6 +71,11 @@ static_library("service") {
"service_utility_process_host.cc",
"service_utility_process_host.h",
]
+ deps += [
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ "//components/startup_metric_utils/common",
+ ]
} else {
sources += [ "cloud_print/print_system_dummy.cc" ]
}
diff --git a/chrome/service/DEPS b/chrome/service/DEPS
index 989d2ce..54a3081 100644
--- a/chrome/service/DEPS
+++ b/chrome/service/DEPS
@@ -1,5 +1,10 @@
include_rules = [
"+chrome/grit", # For generated headers.
+
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ "+components/startup_metric_utils/common",
+
"+components/version_info",
"+sandbox/win/src",
]
diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc
index 3ed91b4..3dad747 100644
--- a/chrome/service/service_utility_process_host.cc
+++ b/chrome/service/service_utility_process_host.cc
@@ -34,6 +34,10 @@
#include "sandbox/win/src/sandbox_types.h"
#include "ui/base/ui_base_switches.h"
+#if defined(OS_WIN)
+#include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.h"
+#endif // defined(OS_WIN)
+
namespace {
using content::ChildProcessHost;
@@ -225,6 +229,11 @@ bool ServiceUtilityProcessHost::StartProcess(bool no_sandbox) {
cmd_line.AppendSwitchASCII(switches::kProcessChannelID, channel_id);
cmd_line.AppendSwitch(switches::kLang);
+#if defined(OS_WIN)
+ if (startup_metric_utils::GetPreReadOptions().use_prefetch_argument)
+ cmd_line.AppendArg(switches::kPrefetchArgumentOther);
+#endif // defined(OS_WIN)
+
if (Launch(&cmd_line, no_sandbox)) {
ReportUmaEvent(SERVICE_UTILITY_STARTED);
return true;
diff --git a/cloud_print/service/win/chrome_launcher.cc b/cloud_print/service/win/chrome_launcher.cc
index 5c9013a..d386342 100644
--- a/cloud_print/service/win/chrome_launcher.cc
+++ b/cloud_print/service/win/chrome_launcher.cc
@@ -214,6 +214,10 @@ void ChromeLauncher::Run() {
cmd.AppendSwitchPath(switches::kUserDataDir, user_data_);
cmd.AppendSwitch(switches::kNoServiceAutorun);
+#if defined(OS_WIN)
+ cmd.AppendArg(switches::kPrefetchArgumentOther);
+#endif // defined(OS_WIN)
+
// Optional.
cmd.AppendSwitch(switches::kDisableDefaultApps);
cmd.AppendSwitch(switches::kDisableExtensions);
diff --git a/components/crash.gypi b/components/crash.gypi
index 00ee69c..8ef86ad 100644
--- a/components/crash.gypi
+++ b/components/crash.gypi
@@ -217,6 +217,13 @@
],
'defines': ['CRASH_IMPLEMENTATION'],
'conditions': [
+ ['OS=="win"', {
+ 'dependencies': [
+ # TODO(fdoray): Remove this once the PreRead field trial has
+ # expired. crbug.com/577698
+ '<(DEPTH)/components/components.gyp:startup_metric_utils_common',
+ ],
+ }],
['OS=="mac" or OS=="win"', {
'dependencies': [
'../third_party/crashpad/crashpad/client/client.gyp:crashpad_client',
diff --git a/components/crash/content/app/BUILD.gn b/components/crash/content/app/BUILD.gn
index 52140ce..3def677 100644
--- a/components/crash/content/app/BUILD.gn
+++ b/components/crash/content/app/BUILD.gn
@@ -49,6 +49,13 @@ source_set("app") {
]
deps += [ ":lib" ]
+ if (is_win) {
+ deps += [
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ "//components/startup_metric_utils/common",
+ ]
+ }
if (is_mac || is_win) {
deps += [ "//third_party/crashpad/crashpad/client" ]
}
diff --git a/components/crash/content/app/DEPS b/components/crash/content/app/DEPS
index 80bc21a..01c710b 100644
--- a/components/crash/content/app/DEPS
+++ b/components/crash/content/app/DEPS
@@ -3,6 +3,11 @@ include_rules = [
"+content/public/common/content_descriptors.h",
"+content/public/common/result_codes.h",
+
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ "+components/startup_metric_utils/common/pre_read_field_trial_utils_win.h",
+
"+third_party/crashpad",
"+third_party/kasko",
"+third_party/lss/linux_syscall_support.h",
diff --git a/components/crash/content/app/crashpad_win.cc b/components/crash/content/app/crashpad_win.cc
index 1c241ca..95e53e2 100644
--- a/components/crash/content/app/crashpad_win.cc
+++ b/components/crash/content/app/crashpad_win.cc
@@ -16,6 +16,7 @@
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/crash/content/app/crash_reporter_client.h"
+#include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.h"
#include "third_party/crashpad/crashpad/client/crashpad_client.h"
#include "third_party/crashpad/crashpad/client/crashpad_info.h"
#include "third_party/crashpad/crashpad/client/simulate_crash_win.h"
@@ -75,6 +76,13 @@ base::FilePath PlatformCrashpadInitialization(bool initial_client,
exe_file = exe_dir.Append(FILE_PATH_LITERAL("crashpad_handler.exe"));
} else {
arguments.push_back("--type=crashpad-handler");
+
+ if (startup_metric_utils::GetPreReadOptions().use_prefetch_argument) {
+ // The prefetch argument added here has to be documented in
+ // chrome_switches.cc, below the kPrefetchArgument* constants. A
+ // constant can't be used here because crashpad can't depend on Chrome.
+ arguments.push_back("/prefetch:7");
+ }
}
// TODO(scottmg): See https://crashpad.chromium.org/bug/23.
diff --git a/components/nacl.gyp b/components/nacl.gyp
index a9ed69c..2fd7aba 100644
--- a/components/nacl.gyp
+++ b/components/nacl.gyp
@@ -139,6 +139,13 @@
'../sandbox/sandbox.gyp:sandbox_services',
]
}],
+ ['OS=="win"', {
+ 'dependencies': [
+ # TODO(fdoray): Remove this once the PreRead field trial has
+ # expired. crbug.com/577698
+ '../components/components.gyp:startup_metric_utils_common',
+ ]
+ }],
],
},
{
diff --git a/components/nacl/browser/BUILD.gn b/components/nacl/browser/BUILD.gn
index 63c2c9d..9b247f4 100644
--- a/components/nacl/browser/BUILD.gn
+++ b/components/nacl/browser/BUILD.gn
@@ -63,6 +63,14 @@ source_set("browser") {
data_deps += [ "//components/nacl/loader:helper_nonsfi" ]
}
+ if (is_win) {
+ deps += [
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ "//components/startup_metric_utils/common",
+ ]
+ }
+
if (is_win && current_cpu == "x86") {
data_deps += [ "//components/nacl/broker:nacl64" ]
}
diff --git a/components/nacl/browser/DEPS b/components/nacl/browser/DEPS
index efbdb131..2e1a96b 100644
--- a/components/nacl/browser/DEPS
+++ b/components/nacl/browser/DEPS
@@ -1,4 +1,7 @@
include_rules = [
+ # TODO(fdoray): Remove this once the PreRead field trial has expired.
+ # crbug.com/577698
+ "+components/startup_metric_utils/common",
"+components/url_formatter",
"+content/public/browser",
"+content/public/test",
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc
index aa4f4c5..2ade0f7 100644
--- a/components/nacl/browser/nacl_process_host.cc
+++ b/components/nacl/browser/nacl_process_host.cc
@@ -76,6 +76,7 @@
#include "base/win/scoped_handle.h"
#include "components/nacl/browser/nacl_broker_service_win.h"
#include "components/nacl/common/nacl_debug_exception_handler_win.h"
+#include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.h"
#include "content/public/common/sandbox_init.h"
#endif
@@ -625,7 +626,12 @@ bool NaClProcessHost::LaunchSelLdr() {
if (NaClBrowser::GetDelegate()->DialogsAreSuppressed())
cmd_line->AppendSwitch(switches::kNoErrorDialogs);
- // On Windows we might need to start the broker process to launch a new loader
+#if defined(OS_WIN)
+ if (startup_metric_utils::GetPreReadOptions().use_prefetch_argument)
+ cmd_line->AppendArg(switches::kPrefetchArgumentOther);
+#endif // defined(OS_WIN)
+
+// On Windows we might need to start the broker process to launch a new loader
#if defined(OS_WIN)
if (RunningOnWOW64()) {
if (!NaClBrokerService::GetInstance()->LaunchLoader(
diff --git a/components/startup_metric_utils/common/pre_read_field_trial_utils_win.cc b/components/startup_metric_utils/common/pre_read_field_trial_utils_win.cc
index a75a81c..dbb32bf 100644
--- a/components/startup_metric_utils/common/pre_read_field_trial_utils_win.cc
+++ b/components/startup_metric_utils/common/pre_read_field_trial_utils_win.cc
@@ -25,12 +25,16 @@ const char kPreReadFieldTrialName[] = "PreRead";
// annotated with the pre-read group that is actually used during this startup.
const char kPreReadSyntheticFieldTrialName[] = "SyntheticPreRead";
-// Variation names for the PreRead field trial.
+// Variation names for the PreRead field trial. All variations change the
+// default behavior, i.e. the default is the inverse of the variation. Thus,
+// variations that cancel something that is done by default have a negative
+// name.
const base::char16 kNoPreReadVariationName[] = L"NoPreRead";
const base::char16 kHighPriorityVariationName[] = L"HighPriority";
const base::char16 kOnlyIfColdVariationName[] = L"OnlyIfCold";
const base::char16 kPrefetchVirtualMemoryVariationName[] =
L"PrefetchVirtualMemory";
+const base::char16 kNoPrefetchArgumentVariationName[] = L"NoPrefetchArgument";
// Registry key in which the PreRead field trial group is stored.
const base::char16 kPreReadFieldTrialRegistryKey[] = L"\\PreReadFieldTrial";
@@ -45,6 +49,12 @@ base::string16 GetPreReadRegistryPath(
return product_registry_path + kPreReadFieldTrialRegistryKey;
}
+// Returns true if |key| has a value named |name| which is not zero.
+bool ReadBool(const base::win::RegKey& key, const base::char16* name) {
+ DWORD value = 0;
+ return key.ReadValueDW(name, &value) == ERROR_SUCCESS && value != 0;
+}
+
} // namespace
void InitializePreReadOptions(const base::string16& product_registry_path) {
@@ -57,27 +67,13 @@ void InitializePreReadOptions(const base::string16& product_registry_path) {
KEY_QUERY_VALUE);
// Set the PreRead field trial's options.
- struct {
- const base::char16* name;
- bool* option;
- } const variations_mappings[] = {
- {kNoPreReadVariationName, &g_pre_read_options.no_pre_read},
- {kHighPriorityVariationName, &g_pre_read_options.high_priority},
- {kOnlyIfColdVariationName, &g_pre_read_options.only_if_cold},
- {kPrefetchVirtualMemoryVariationName,
- &g_pre_read_options.prefetch_virtual_memory},
- };
-
- for (const auto& mapping : variations_mappings) {
- // Set the option variable to true if the corresponding value is found in
- // the registry. Set to false otherwise (default behavior).
- DWORD value = 0;
- if (key.ReadValueDW(mapping.name, &value) == ERROR_SUCCESS) {
- DCHECK_EQ(1U, value);
- DCHECK(!*mapping.option);
- *mapping.option = true;
- }
- }
+ g_pre_read_options.pre_read = !ReadBool(key, kNoPreReadVariationName);
+ g_pre_read_options.high_priority = ReadBool(key, kHighPriorityVariationName);
+ g_pre_read_options.only_if_cold = ReadBool(key, kOnlyIfColdVariationName);
+ g_pre_read_options.prefetch_virtual_memory =
+ ReadBool(key, kPrefetchVirtualMemoryVariationName);
+ g_pre_read_options.use_prefetch_argument =
+ !ReadBool(key, kNoPrefetchArgumentVariationName);
}
PreReadOptions GetPreReadOptions() {
diff --git a/components/startup_metric_utils/common/pre_read_field_trial_utils_win.h b/components/startup_metric_utils/common/pre_read_field_trial_utils_win.h
index cacf4b3..a2aaf4a 100644
--- a/components/startup_metric_utils/common/pre_read_field_trial_utils_win.h
+++ b/components/startup_metric_utils/common/pre_read_field_trial_utils_win.h
@@ -21,8 +21,8 @@ using RegisterPreReadSyntheticFieldTrialCallback =
// The options controlled by the PreRead field trial.
struct PreReadOptions {
- // No explicit DLL pre-reading.
- bool no_pre_read;
+ // Pre-read DLLs explicitly.
+ bool pre_read;
// Pre-read DLLs with a high thread priority.
bool high_priority;
@@ -32,6 +32,9 @@ struct PreReadOptions {
// Pre-read DLLs using the ::PrefetchVirtualMemory function, if available.
bool prefetch_virtual_memory;
+
+ // Use a /prefetch argument when launching a process.
+ bool use_prefetch_argument;
};
// Initializes DLL pre-reading options from the registry.
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index ad9cafe..b3bd310 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -1030,6 +1030,11 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess);
cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
+#if defined(OS_WIN)
+ if (GetContentClient()->browser()->ShouldUseWindowsPrefetchArgument())
+ cmd_line->AppendArg(switches::kPrefetchArgumentGpu);
+#endif // defined(OS_WIN)
+
if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED)
cmd_line->AppendSwitch(switches::kDisableGpuSandbox);
diff --git a/content/browser/plugin_process_host.cc b/content/browser/plugin_process_host.cc
index 9ede7a2..cb14fa7 100644
--- a/content/browser/plugin_process_host.cc
+++ b/content/browser/plugin_process_host.cc
@@ -209,6 +209,11 @@ bool PluginProcessHost::Init(const WebPluginInfo& info) {
cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kPluginProcess);
cmd_line->AppendSwitchPath(switches::kPluginPath, info.path);
+#if defined(OS_WIN)
+ if (GetContentClient()->browser()->ShouldUseWindowsPrefetchArgument())
+ cmd_line->AppendArg(switches::kPrefetchArgumentOther);
+#endif // defined(OS_WIN)
+
// Propagate the following switches to the plugin command line (along with
// any associated values) if present in the browser command line
static const char* const kSwitchNames[] = {
diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc
index e17b694..3523fc1 100644
--- a/content/browser/ppapi_plugin_process_host.cc
+++ b/content/browser/ppapi_plugin_process_host.cc
@@ -373,6 +373,13 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
: switches::kPpapiPluginProcess);
cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
+#if defined(OS_WIN)
+ if (GetContentClient()->browser()->ShouldUseWindowsPrefetchArgument()) {
+ cmd_line->AppendArg(is_broker_ ? switches::kPrefetchArgumentPpapiBroker
+ : switches::kPrefetchArgumentPpapi);
+ }
+#endif // defined(OS_WIN)
+
// These switches are forwarded to both plugin and broker pocesses.
static const char* kCommonForwardSwitches[] = {
switches::kVModule
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index bfba388..667dc22 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1291,6 +1291,11 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
command_line->AppendSwitchASCII(switches::kProcessType,
switches::kRendererProcess);
+#if defined(OS_WIN)
+ if (GetContentClient()->browser()->ShouldUseWindowsPrefetchArgument())
+ command_line->AppendArg(switches::kPrefetchArgumentRenderer);
+#endif // defined(OS_WIN)
+
// Now send any options from our own command line we want to propagate.
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
diff --git a/content/browser/utility_process_host_impl.cc b/content/browser/utility_process_host_impl.cc
index db67d60..42c31bd 100644
--- a/content/browser/utility_process_host_impl.cc
+++ b/content/browser/utility_process_host_impl.cc
@@ -286,6 +286,11 @@ bool UtilityProcessHostImpl::StartProcess() {
std::string locale = GetContentClient()->browser()->GetApplicationLocale();
cmd_line->AppendSwitchASCII(switches::kLang, locale);
+#if defined(OS_WIN)
+ if (GetContentClient()->browser()->ShouldUseWindowsPrefetchArgument())
+ cmd_line->AppendArg(switches::kPrefetchArgumentOther);
+#endif // defined(OS_WIN)
+
if (no_sandbox_)
cmd_line->AppendSwitch(switches::kNoSandbox);
diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc
index 5230738..92a5a24 100644
--- a/content/common/sandbox_win.cc
+++ b/content/common/sandbox_win.cc
@@ -681,11 +681,6 @@ base::Process StartSandboxedProcess(
ProcessDebugFlags(cmd_line);
- // Prefetch hints on windows:
- // Using a different prefetch profile per process type will allow Windows
- // to create separate pretetch settings for browser, renderer etc.
- cmd_line->AppendArg(base::StringPrintf("/prefetch:%d", base::Hash(type_str)));
-
if ((!delegate->ShouldSandbox()) ||
browser_command_line.HasSwitch(switches::kNoSandbox) ||
cmd_line->HasSwitch(switches::kNoSandbox)) {
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 121f7c2..3f6d970 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -418,7 +418,11 @@ bool ContentBrowserClient::IsWin32kLockdownEnabledForMimeType(
// is enabled by default in Chrome. See crbug.com/523278.
return false;
}
-#endif
+
+bool ContentBrowserClient::ShouldUseWindowsPrefetchArgument() const {
+ return true;
+}
+#endif // defined(OS_WIN)
#if defined(VIDEO_HOLE)
ExternalVideoSurfaceContainer*
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index b19adfb..5ecc56e 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -756,6 +756,10 @@ class CONTENT_EXPORT ContentBrowserClient {
// a process hosting a plugin with the specified |mime_type|.
virtual bool IsWin32kLockdownEnabledForMimeType(
const std::string& mime_type) const;
+
+ // Returns true if processes should be launched with a /prefetch:# argument.
+ // See the kPrefetchArgument* constants in content_switches.cc for details.
+ virtual bool ShouldUseWindowsPrefetchArgument() const;
#endif
#if defined(VIDEO_HOLE)
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 1fe03b0..094ecf1 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -968,6 +968,30 @@ const char kDisableCoreAnimationPlugins[] =
#endif
#if defined(OS_WIN)
+// /prefetch:# arguments to use when launching various process types. It has
+// been observed that when file reads are consistent for 3 process launches with
+// the same /prefetch:# argument, the Windows prefetcher starts issuing reads in
+// batch at process launch. Because reads depend on the process type, the
+// prefetcher wouldn't be able to observe consistent reads if no /prefetch:#
+// arguments were used. Note that the browser process has no /prefetch:#
+// argument; as such all other processes must have one in order to avoid
+// polluting its profile. Note: # must always be in [1, 8]; otherwise it is
+// ignored by the Windows prefetcher.
+const char kPrefetchArgumentRenderer[] = "/prefetch:1";
+const char kPrefetchArgumentGpu[] = "/prefetch:2";
+const char kPrefetchArgumentPpapi[] = "/prefetch:3";
+const char kPrefetchArgumentPpapiBroker[] = "/prefetch:4";
+// /prefetch:5, /prefetch:6 and /prefetch:7 are reserved for content embedders
+// and are not to be used by content itself.
+
+// /prefetch:# argument shared by all process types that don't have their own.
+// It is likely that the prefetcher won't work for these process types as it
+// won't be able to observe consistent file reads across launches. However,
+// having a valid prefetch argument for these process types is required to
+// prevent them from interfering with the prefetch profile of the browser
+// process.
+const char kPrefetchArgumentOther[] = "/prefetch:8";
+
// Device scale factor passed to certain processes like renderers, etc.
const char kDeviceScaleFactor[] = "device-scale-factor";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 1174c61..f45e539 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -291,6 +291,11 @@ extern const char kDisableThreadedEventHandlingMac[];
#endif
#if defined(OS_WIN)
+CONTENT_EXPORT extern const char kPrefetchArgumentRenderer[];
+CONTENT_EXPORT extern const char kPrefetchArgumentGpu[];
+CONTENT_EXPORT extern const char kPrefetchArgumentPpapi[];
+CONTENT_EXPORT extern const char kPrefetchArgumentPpapiBroker[];
+CONTENT_EXPORT extern const char kPrefetchArgumentOther[];
// This switch contains the device scale factor passed to certain processes
// like renderers, etc.
CONTENT_EXPORT extern const char kDeviceScaleFactor[];