diff options
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, 107 insertions, 208 deletions
diff --git a/chrome/app/chrome_exe_main_win.cc b/chrome/app/chrome_exe_main_win.cc index 51b1edf..3c93752 100644 --- a/chrome/app/chrome_exe_main_win.cc +++ b/chrome/app/chrome_exe_main_win.cc @@ -13,7 +13,6 @@ #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" @@ -41,36 +40,6 @@ 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 @@ -135,9 +104,29 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) { if (AttemptFastNotify(*CommandLine::ForCurrentProcess())) return 0; - 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); + 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; } diff --git a/chrome/app/client_util.cc b/chrome/app/client_util.cc index dd6becd..054d58f 100644 --- a/chrome/app/client_util.cc +++ b/chrome/app/client_util.cc @@ -6,6 +6,7 @@ #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" @@ -25,8 +26,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/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" @@ -148,29 +147,21 @@ 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 LoadChromeWithDirectory(base::string16* dir) { +HMODULE LoadModuleWithDirectory(base::string16* dir, + const wchar_t* dll_name, + bool pre_read) { ::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). - if (!cmd_line.HasSwitch(switches::kProcessType)) { + // We pre-read the binary to warm the memory caches (fewer hard faults to + // page parts of the binary in). const size_t kStepSize = 1024 * 1024; size_t percentage = InitPreReadPercentage(); ImagePreReader::PartialPreReadImage(dir->c_str(), percentage, kStepSize); - } #endif + } return ::LoadLibraryExW(dir->c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); @@ -186,6 +177,13 @@ 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() { @@ -210,7 +208,8 @@ base::string16 GetCurrentModuleVersion() { //============================================================================= -MainDllLoader::MainDllLoader() : dll_(NULL) { +MainDllLoader::MainDllLoader() + : dll_(NULL), metro_mode_(InMetroMode()) { } MainDllLoader::~MainDllLoader() { @@ -222,12 +221,16 @@ 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(base::string16* out_version, +HMODULE MainDllLoader::Load(const wchar_t* dll_name, + base::string16* out_version, base::string16* out_file) { const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); - const base::string16 dir(GetExecutablePath()); - *out_file = dir; - HMODULE dll = LoadChromeWithDirectory(out_file); + 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); if (!dll) { // Loading from same directory (for developers) failed. Look at the version // resource in the current module and try loading that. @@ -237,10 +240,10 @@ HMODULE MainDllLoader::Load(base::string16* out_version, return NULL; } - *out_file = dir; + *out_file = executable_dir; *out_version = version_string; out_file->append(*out_version).append(1, L'\\'); - dll = LoadChromeWithDirectory(out_file); + dll = LoadModuleWithDirectory(out_file, dll_name, pre_read); if (!dll) { PLOG(ERROR) << "Failed to load Chrome DLL from " << *out_file; return NULL; @@ -248,7 +251,6 @@ HMODULE MainDllLoader::Load(base::string16* out_version, } DCHECK(dll); - return dll; } @@ -257,34 +259,53 @@ HMODULE MainDllLoader::Load(base::string16* out_version, // 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(&version, &file); + dll_ = Load(dll_name, &version, &file); if (!dll_) return chrome::RESULT_CODE_MISSING_DATA; - 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); + 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); + } } void MainDllLoader::RelaunchChromeBrowserWithNewCommandLineIfNeeded() { + if (metro_mode_) + return; + RelaunchChromeBrowserWithNewCommandLineIfNeededFunc relaunch_function = reinterpret_cast<RelaunchChromeBrowserWithNewCommandLineIfNeededFunc>( ::GetProcAddress(dll_, @@ -300,14 +321,7 @@ void MainDllLoader::RelaunchChromeBrowserWithNewCommandLineIfNeeded() { //============================================================================= class ChromeDllLoader : public MainDllLoader { - public: - virtual base::string16 GetRegistryPath() { - base::string16 key(google_update::kRegPathClients); - BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - key.append(L"\\").append(dist->GetAppGuid()); - return key; - } - + protected: virtual void OnBeforeLaunch(const base::string16& dll_path) { RecordDidRun(dll_path); } @@ -326,10 +340,12 @@ class ChromeDllLoader : public MainDllLoader { //============================================================================= class ChromiumDllLoader : public MainDllLoader { - public: - virtual base::string16 GetRegistryPath() { - BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - return dist->GetVersionKey(); + 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; } }; diff --git a/chrome/app/client_util.h b/chrome/app/client_util.h index 5b8ebf6..8b6184aa 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 chrome.dll for both chrome and +// Implements the common aspects of loading the main dll for both chrome and // chromium scenarios, which are in charge of implementing two abstract // methods: GetRegistryPath() and OnBeforeLaunch(). class MainDllLoader { @@ -42,28 +42,25 @@ 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) {} + virtual void OnBeforeLaunch(const base::string16& dll_path) = 0; // 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) { - return return_code; - } - - protected: - // Derived classes must return the relative registry path that holds the - // most current version of chrome.dll. - virtual base::string16 GetRegistryPath() = 0; + virtual int OnBeforeExit(int return_code, const base::string16& dll_path) = 0; - HMODULE Load(base::string16* out_version, base::string16* out_file); + private: + HMODULE Load(const wchar_t* dll_name, + 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 deleted file mode 100644 index faaff88..0000000 --- a/chrome/app/metro_driver_win.cc +++ /dev/null @@ -1,70 +0,0 @@ -// 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 deleted file mode 100644 index b99a9af..0000000 --- a/chrome/app/metro_driver_win.h +++ /dev/null @@ -1,33 +0,0 @@ -// 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_ |