diff options
author | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-25 23:49:16 +0000 |
---|---|---|
committer | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-25 23:49:16 +0000 |
commit | 57d83182d3280f27f57daa5c1778f1fdf1fbfaee (patch) | |
tree | c63a7aa4c6995b70b0a07dcf13f4b65937f81de8 /chrome/app | |
parent | bf226999cde8c97a64ba6ac39641b46e10b4fc3e (diff) | |
download | chromium_src-57d83182d3280f27f57daa5c1778f1fdf1fbfaee.zip chromium_src-57d83182d3280f27f57daa5c1778f1fdf1fbfaee.tar.gz chromium_src-57d83182d3280f27f57daa5c1778f1fdf1fbfaee.tar.bz2 |
Revert 247151 "Cleanup of windows launch code"
> Cleanup of windows launch code
>
> The windows startup code was handling aura and non-aura cases which
> require different startup logic in metro (immersive mode). Since we
> don't support the non-Aura logic we can get rid of a lot of code.
>
> Tbring gab for the installer constant addition.
>
> R=ananta@chromium.org, scottmg@chromium.org
> TBR=gab
> BUG=none
>
> Review URL: https://codereview.chromium.org/142473002
TBR=cpu@chromium.org
Review URL: https://codereview.chromium.org/140123006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247156 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/app')
-rw-r--r-- | chrome/app/chrome_exe_main_win.cc | 61 | ||||
-rw-r--r-- | chrome/app/client_util.cc | 130 | ||||
-rw-r--r-- | chrome/app/client_util.h | 21 | ||||
-rw-r--r-- | chrome/app/metro_driver_win.cc | 70 | ||||
-rw-r--r-- | chrome/app/metro_driver_win.h | 33 |
5 files changed, 208 insertions, 107 deletions
diff --git a/chrome/app/chrome_exe_main_win.cc b/chrome/app/chrome_exe_main_win.cc index 3c93752..51b1edf 100644 --- a/chrome/app/chrome_exe_main_win.cc +++ b/chrome/app/chrome_exe_main_win.cc @@ -13,6 +13,7 @@ #include "base/lazy_instance.h" #include "chrome/app/chrome_breakpad_client.h" #include "chrome/app/client_util.h" +#include "chrome/app/metro_driver_win.h" #include "chrome/browser/chrome_process_finder_win.h" #include "chrome/browser/policy/policy_path_parser.h" #include "chrome/common/chrome_constants.h" @@ -40,6 +41,36 @@ void CheckSafeModeLaunch() { ::SetEnvironmentVariableA(chrome::kSafeModeEnvVar, "1"); } +int RunChrome(HINSTANCE instance) { + breakpad::SetBreakpadClient(g_chrome_breakpad_client.Pointer()); + + CheckSafeModeLaunch(); + + bool exit_now = true; + // We restarted because of a previous crash. Ask user if we should relaunch. + // Only show this for the browser process. See crbug.com/132119. + const std::string process_type = + CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kProcessType); + if (process_type.empty()) { + if (breakpad::ShowRestartDialogIfCrashed(&exit_now)) { + if (exit_now) + return content::RESULT_CODE_NORMAL_EXIT; + } + } + + // Initialize the sandbox services. + sandbox::SandboxInterfaceInfo sandbox_info = {0}; + content::InitializeSandboxInfo(&sandbox_info); + + // Load and launch the chrome dll. *Everything* happens inside. + MainDllLoader* loader = MakeMainDllLoader(); + int rc = loader->Launch(instance, &sandbox_info); + loader->RelaunchChromeBrowserWithNewCommandLineIfNeeded(); + delete loader; + return rc; +} + // List of switches that it's safe to rendezvous early with. Fast start should // not be done if a command line contains a switch not in this set. // Note this is currently stored as a list of two because it's probably faster @@ -104,29 +135,9 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) { if (AttemptFastNotify(*CommandLine::ForCurrentProcess())) return 0; - breakpad::SetBreakpadClient(g_chrome_breakpad_client.Pointer()); - CheckSafeModeLaunch(); - - bool exit_now = true; - // We restarted because of a previous crash. Ask user if we should relaunch. - // Only show this for the browser process. See crbug.com/132119. - bool const is_browser = - CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kProcessType).empty(); - if (is_browser) { - if (breakpad::ShowRestartDialogIfCrashed(&exit_now)) { - if (exit_now) - return content::RESULT_CODE_NORMAL_EXIT; - } - } - - // Initialize the sandbox services. - sandbox::SandboxInterfaceInfo sandbox_info = {0}; - content::InitializeSandboxInfo(&sandbox_info); - // Load and launch the chrome dll. *Everything* happens inside. - MainDllLoader* loader = MakeMainDllLoader(); - int rc = loader->Launch(instance, &sandbox_info); - loader->RelaunchChromeBrowserWithNewCommandLineIfNeeded(); - delete loader; - return rc; + MetroDriver metro_driver; + if (metro_driver.in_metro_mode()) + return metro_driver.RunInMetro(instance, &RunChrome); + // Not in metro mode, proceed as normal. + return RunChrome(instance); } diff --git a/chrome/app/client_util.cc b/chrome/app/client_util.cc index 054d58f..dd6becd 100644 --- a/chrome/app/client_util.cc +++ b/chrome/app/client_util.cc @@ -6,7 +6,6 @@ #include <shlwapi.h> #include "base/command_line.h" -#include "base/compiler_specific.h" #include "base/debug/trace_event.h" #include "base/environment.h" #include "base/file_version_info.h" @@ -26,6 +25,8 @@ #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/channel_info.h" #include "chrome/installer/util/google_update_constants.h" #include "chrome/installer/util/google_update_settings.h" #include "chrome/installer/util/install_util.h" @@ -147,21 +148,29 @@ size_t InitPreReadPercentage() { // Expects that |dir| has a trailing backslash. |dir| is modified so it // contains the full path that was tried. Caller must check for the return // value not being null to determine if this path contains a valid dll. -HMODULE LoadModuleWithDirectory(base::string16* dir, - const wchar_t* dll_name, - bool pre_read) { +HMODULE LoadChromeWithDirectory(base::string16* dir) { ::SetCurrentDirectoryW(dir->c_str()); + const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); +#if !defined(CHROME_MULTIPLE_DLL) + const wchar_t* dll_name = installer::kChromeDll; +#else + const wchar_t* dll_name = + cmd_line.HasSwitch(switches::kProcessType) && + cmd_line.GetSwitchValueASCII(switches::kProcessType) != "service" + ? installer::kChromeChildDll + : installer::kChromeDll; +#endif dir->append(dll_name); - if (pre_read) { #if !defined(WIN_DISABLE_PREREAD) - // We pre-read the binary to warm the memory caches (fewer hard faults to - // page parts of the binary in). + // We pre-read the binary to warm the memory caches (fewer hard faults to + // page parts of the binary in). + if (!cmd_line.HasSwitch(switches::kProcessType)) { const size_t kStepSize = 1024 * 1024; size_t percentage = InitPreReadPercentage(); ImagePreReader::PartialPreReadImage(dir->c_str(), percentage, kStepSize); -#endif } +#endif return ::LoadLibraryExW(dir->c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); @@ -177,13 +186,6 @@ void ClearDidRun(const base::string16& dll_path) { GoogleUpdateSettings::UpdateDidRunState(false, system_level); } -bool InMetroMode() { - return (wcsstr( - ::GetCommandLineW(), L" -ServerName:DefaultBrowserServer") != NULL); -} - -typedef int (*InitMetro)(); - } // namespace base::string16 GetExecutablePath() { @@ -208,8 +210,7 @@ base::string16 GetCurrentModuleVersion() { //============================================================================= -MainDllLoader::MainDllLoader() - : dll_(NULL), metro_mode_(InMetroMode()) { +MainDllLoader::MainDllLoader() : dll_(NULL) { } MainDllLoader::~MainDllLoader() { @@ -221,16 +222,12 @@ MainDllLoader::~MainDllLoader() { // If that fails then we look at the version resource in the current // module. This is the expected path for chrome.exe browser instances in an // installed build. -HMODULE MainDllLoader::Load(const wchar_t* dll_name, - base::string16* out_version, +HMODULE MainDllLoader::Load(base::string16* out_version, base::string16* out_file) { const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); - const base::string16 executable_dir(GetExecutablePath()); - *out_file = executable_dir; - - const bool pre_read = !metro_mode_; - - HMODULE dll = LoadModuleWithDirectory(out_file, dll_name, pre_read); + const base::string16 dir(GetExecutablePath()); + *out_file = dir; + HMODULE dll = LoadChromeWithDirectory(out_file); if (!dll) { // Loading from same directory (for developers) failed. Look at the version // resource in the current module and try loading that. @@ -240,10 +237,10 @@ HMODULE MainDllLoader::Load(const wchar_t* dll_name, return NULL; } - *out_file = executable_dir; + *out_file = dir; *out_version = version_string; out_file->append(*out_version).append(1, L'\\'); - dll = LoadModuleWithDirectory(out_file, dll_name, pre_read); + dll = LoadChromeWithDirectory(out_file); if (!dll) { PLOG(ERROR) << "Failed to load Chrome DLL from " << *out_file; return NULL; @@ -251,6 +248,7 @@ HMODULE MainDllLoader::Load(const wchar_t* dll_name, } DCHECK(dll); + return dll; } @@ -259,53 +257,34 @@ HMODULE MainDllLoader::Load(const wchar_t* dll_name, // add custom code in the OnBeforeLaunch callback. int MainDllLoader::Launch(HINSTANCE instance, sandbox::SandboxInterfaceInfo* sbox_info) { - const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); - const std::string process_type = - cmd_line.GetSwitchValueASCII(switches::kProcessType); - - const wchar_t* dll_name; - if (metro_mode_) { - dll_name = installer::kChromeMetroDll; - } else { -#if !defined(CHROME_MULTIPLE_DLL) - dll_name = installer::kChromeDll; -#else - dll_name = process_type != "service" ? - installer::kChromeChildDll : installer::kChromeDll; -#endif - } - base::string16 version; base::string16 file; - dll_ = Load(dll_name, &version, &file); + dll_ = Load(&version, &file); if (!dll_) return chrome::RESULT_CODE_MISSING_DATA; - if (metro_mode_) { - InitMetro init_metro_fn = - reinterpret_cast<InitMetro>(::GetProcAddress(dll_, "InitMetro")); - return init_metro_fn(); - } else { - scoped_ptr<base::Environment> env(base::Environment::Create()); - env->SetVar(chrome::kChromeVersionEnvVar, base::WideToUTF8(version)); - // TODO(erikwright): Remove this when http://crbug.com/174953 is fixed and - // widely deployed. - env->UnSetVar(env_vars::kGoogleUpdateIsMachineEnvVar); - - breakpad::InitCrashReporter(process_type); - OnBeforeLaunch(file); - - DLL_MAIN chrome_main = - reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain")); - int rc = chrome_main(instance, sbox_info); - return OnBeforeExit(rc, file); - } + scoped_ptr<base::Environment> env(base::Environment::Create()); + env->SetVar(chrome::kChromeVersionEnvVar, base::WideToUTF8(version)); + // TODO(erikwright): Remove this when http://crbug.com/174953 is fixed and + // widely deployed. + env->UnSetVar(env_vars::kGoogleUpdateIsMachineEnvVar); + + const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); + std::string process_type = + cmd_line.GetSwitchValueASCII(switches::kProcessType); + breakpad::InitCrashReporter(process_type); + OnBeforeLaunch(file); + + DLL_MAIN entry_point = + reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain")); + if (!entry_point) + return chrome::RESULT_CODE_BAD_PROCESS_TYPE; + + int rc = entry_point(instance, sbox_info); + return OnBeforeExit(rc, file); } void MainDllLoader::RelaunchChromeBrowserWithNewCommandLineIfNeeded() { - if (metro_mode_) - return; - RelaunchChromeBrowserWithNewCommandLineIfNeededFunc relaunch_function = reinterpret_cast<RelaunchChromeBrowserWithNewCommandLineIfNeededFunc>( ::GetProcAddress(dll_, @@ -321,7 +300,14 @@ void MainDllLoader::RelaunchChromeBrowserWithNewCommandLineIfNeeded() { //============================================================================= class ChromeDllLoader : public MainDllLoader { - protected: + public: + virtual base::string16 GetRegistryPath() { + base::string16 key(google_update::kRegPathClients); + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + key.append(L"\\").append(dist->GetAppGuid()); + return key; + } + virtual void OnBeforeLaunch(const base::string16& dll_path) { RecordDidRun(dll_path); } @@ -340,12 +326,10 @@ class ChromeDllLoader : public MainDllLoader { //============================================================================= class ChromiumDllLoader : public MainDllLoader { - protected: - virtual void OnBeforeLaunch(const base::string16& dll_path) OVERRIDE { - } - virtual int OnBeforeExit(int return_code, - const base::string16& dll_path) OVERRIDE { - return return_code; + public: + virtual base::string16 GetRegistryPath() { + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + return dist->GetVersionKey(); } }; diff --git a/chrome/app/client_util.h b/chrome/app/client_util.h index 8b6184aa..5b8ebf6 100644 --- a/chrome/app/client_util.h +++ b/chrome/app/client_util.h @@ -23,7 +23,7 @@ base::string16 GetExecutablePath(); // string if none found. base::string16 GetCurrentModuleVersion(); -// Implements the common aspects of loading the main dll for both chrome and +// Implements the common aspects of loading chrome.dll for both chrome and // chromium scenarios, which are in charge of implementing two abstract // methods: GetRegistryPath() and OnBeforeLaunch(). class MainDllLoader { @@ -42,25 +42,28 @@ class MainDllLoader { // persistent mode an upgrade is detected. void RelaunchChromeBrowserWithNewCommandLineIfNeeded(); - protected: // Called after chrome.dll has been loaded but before the entry point // is invoked. Derived classes can implement custom actions here. // |dll_path| refers to the path of the Chrome dll being loaded. - virtual void OnBeforeLaunch(const base::string16& dll_path) = 0; + virtual void OnBeforeLaunch(const base::string16& dll_path) {} // Called after the chrome.dll entry point returns and before terminating // this process. The return value will be used as the process return code. // |dll_path| refers to the path of the Chrome dll being loaded. - virtual int OnBeforeExit(int return_code, const base::string16& dll_path) = 0; + virtual int OnBeforeExit(int return_code, const base::string16& dll_path) { + return return_code; + } - private: - HMODULE Load(const wchar_t* dll_name, - base::string16* out_version, - base::string16* out_file); + protected: + // Derived classes must return the relative registry path that holds the + // most current version of chrome.dll. + virtual base::string16 GetRegistryPath() = 0; + + HMODULE Load(base::string16* out_version, base::string16* out_file); private: + // Chrome.dll handle. HMODULE dll_; - const bool metro_mode_; }; // Factory for the MainDllLoader. Caller owns the pointer and should call diff --git a/chrome/app/metro_driver_win.cc b/chrome/app/metro_driver_win.cc new file mode 100644 index 0000000..faaff88 --- /dev/null +++ b/chrome/app/metro_driver_win.cc @@ -0,0 +1,70 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "metro_driver_win.h" + +#include <string.h> + +#include "chrome/app/client_util.h" +#include "chrome/common/chrome_constants.h" + +namespace { +// This environment variable controls the loading of the metro driver DLL. +const char* kMetroModeEnvVar = "CHROME_METRO_DLL"; + +typedef int (*InitMetro)(LPTHREAD_START_ROUTINE thread_proc, void* context); + +struct Context { + MetroDriver::MainFn fn; + HINSTANCE instance; +}; + +DWORD WINAPI MainThread(void* param) { + Context* context = reinterpret_cast<Context*>(param); + int rv = context->fn(context->instance); + delete context; + return rv; +} + +} // namespace + +MetroDriver::MetroDriver() : init_metro_fn_(NULL) { + if (0 != ::GetEnvironmentVariableA(kMetroModeEnvVar, NULL, 0)) + return; + // The metro activation always has the |ServerName| parameter. If we dont + // see it, we are being launched in desktop mode. + if (!wcsstr(::GetCommandLineW(), L" -ServerName:DefaultBrowserServer")) { + ::SetEnvironmentVariableA(kMetroModeEnvVar, "0"); + return; + } + // We haven't tried to load the metro driver, this probably means we are the + // browser. Find it or not we set the environment variable because we don't + // want to keep trying in the child processes. + HMODULE metro_dll = ::LoadLibraryW(chrome::kMetroDriverDll); + if (!metro_dll) { + // It is not next to the build output, so this must be an actual deployment + // and in that case we need the mainloader to find the current version + // directory. + base::string16 version(GetCurrentModuleVersion()); + if (!version.empty()) { + std::wstring exe_path(GetExecutablePath()); + exe_path.append(version).append(L"\\").append(chrome::kMetroDriverDll); + metro_dll = ::LoadLibraryW(exe_path.c_str()); + } + } + // We set the environment variable always, so we don't keep trying in + // the child processes. + ::SetEnvironmentVariableA(kMetroModeEnvVar, metro_dll ? "1" : "0"); + if (!metro_dll) + return; + init_metro_fn_ = ::GetProcAddress(metro_dll, "InitMetro"); +} + +int MetroDriver::RunInMetro(HINSTANCE instance, MainFn main_fn) { + Context* context = new Context; + context->fn = main_fn; + context->instance = instance; + + return reinterpret_cast<InitMetro>(init_metro_fn_)(&MainThread, context); +} diff --git a/chrome/app/metro_driver_win.h b/chrome/app/metro_driver_win.h new file mode 100644 index 0000000..b99a9af --- /dev/null +++ b/chrome/app/metro_driver_win.h @@ -0,0 +1,33 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_APP_METRO_DRIVER_WIN_H_ +#define CHROME_APP_METRO_DRIVER_WIN_H_ + +#include <Windows.h> + +// Helper class to manage the metro driver dll. When present in the system, +// the main process thread needs to call InitMetro(), normal execution of +// chrome initialization will continue on a second thread while the main +// thread will be servicing the metro message loop. +class MetroDriver { + public: + typedef int (*MainFn)(HINSTANCE instance); + + MetroDriver(); + // returns true if chrome is being launched in metro. If so we should + // call RunInMetro(). If not then we should just run chrome as usual. + bool in_metro_mode() const { return (NULL != init_metro_fn_); } + + // Enter the metro main function, which will only return when chrome metro + // is closed. Once metro has initialized, the dll creates a new thread + // which runs |main_fn|. This method returns when the chrome metro session + // is closed by the user. + int RunInMetro(HINSTANCE instance, MainFn main_fn); + + private: + void* init_metro_fn_; +}; + +#endif // CHROME_APP_METRO_DRIVER_WIN_H_ |