Cause chrome.exe to introspect to find the version of chrome.dll to load. This...

Cause chrome.exe to introspect to find the version of chrome.dll to load. This should ensure that mismatched exe and dll versions never occur.

Also, wstring -> string16.

BUG=140779
TEST=Install Chrome, smash Omaha registry keys, Chrome still runs.


Review URL: https://chromiumcodereview.appspot.com/10825213

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150282 0039d316-1c4b-4281-b951-d872f2087c98
parent f3857c8a
...@@ -9,10 +9,12 @@ ...@@ -9,10 +9,12 @@
#include "base/debug/trace_event.h" #include "base/debug/trace_event.h"
#include "base/environment.h" #include "base/environment.h"
#include "base/file_util.h" #include "base/file_util.h"
#include "base/file_version_info.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/rand_util.h" // For PreRead experiment. #include "base/rand_util.h" // For PreRead experiment.
#include "base/sha1.h" // For PreRead experiment. #include "base/sha1.h" // For PreRead experiment.
#include "base/string16.h"
#include "base/string_util.h" #include "base/string_util.h"
#include "base/stringprintf.h" #include "base/stringprintf.h"
#include "base/utf_string_conversions.h" #include "base/utf_string_conversions.h"
...@@ -40,7 +42,7 @@ typedef void (*RelaunchChromeBrowserWithNewCommandLineIfNeededFunc)(); ...@@ -40,7 +42,7 @@ typedef void (*RelaunchChromeBrowserWithNewCommandLineIfNeededFunc)();
// Gets chrome version according to the load path. |exe_path| must be the // Gets chrome version according to the load path. |exe_path| must be the
// backslash terminated directory of the current chrome.exe. // backslash terminated directory of the current chrome.exe.
bool GetChromeVersion(const wchar_t* exe_dir, const wchar_t* key_path, bool GetChromeVersion(const wchar_t* exe_dir, const wchar_t* key_path,
std::wstring* version) { string16* version) {
HKEY reg_root = InstallUtil::IsPerUserInstall(exe_dir) ? HKEY_CURRENT_USER : HKEY reg_root = InstallUtil::IsPerUserInstall(exe_dir) ? HKEY_CURRENT_USER :
HKEY_LOCAL_MACHINE; HKEY_LOCAL_MACHINE;
bool success = false; bool success = false;
...@@ -51,7 +53,7 @@ bool GetChromeVersion(const wchar_t* exe_dir, const wchar_t* key_path, ...@@ -51,7 +53,7 @@ bool GetChromeVersion(const wchar_t* exe_dir, const wchar_t* key_path,
// running. We need to consult the opv value so we can load the old dll. // running. We need to consult the opv value so we can load the old dll.
// TODO(cpu) : This is solving the same problem as the environment variable // TODO(cpu) : This is solving the same problem as the environment variable
// so one of them will eventually be deprecated. // so one of them will eventually be deprecated.
std::wstring new_chrome_exe(exe_dir); string16 new_chrome_exe(exe_dir);
new_chrome_exe.append(installer::kChromeNewExe); new_chrome_exe.append(installer::kChromeNewExe);
if (::PathFileExistsW(new_chrome_exe.c_str()) && if (::PathFileExistsW(new_chrome_exe.c_str()) &&
key.ReadValue(google_update::kRegOldVersionField, key.ReadValue(google_update::kRegOldVersionField,
...@@ -67,7 +69,7 @@ bool GetChromeVersion(const wchar_t* exe_dir, const wchar_t* key_path, ...@@ -67,7 +69,7 @@ bool GetChromeVersion(const wchar_t* exe_dir, const wchar_t* key_path,
} }
// Not generic, we only handle strings up to 128 chars. // Not generic, we only handle strings up to 128 chars.
bool EnvQueryStr(const wchar_t* key_name, std::wstring* value) { bool EnvQueryStr(const wchar_t* key_name, string16* value) {
wchar_t out[128]; wchar_t out[128];
DWORD count = sizeof(out)/sizeof(out[0]); DWORD count = sizeof(out)/sizeof(out[0]);
DWORD rv = ::GetEnvironmentVariableW(key_name, out, count); DWORD rv = ::GetEnvironmentVariableW(key_name, out, count);
...@@ -166,7 +168,7 @@ bool GetPreReadExperimentGroup(DWORD* pre_read_percentage) { ...@@ -166,7 +168,7 @@ bool GetPreReadExperimentGroup(DWORD* pre_read_percentage) {
// Get the MetricsId of the installation. This is only set if the user has // Get the MetricsId of the installation. This is only set if the user has
// opted in to reporting. Doing things this way ensures that we only enable // opted in to reporting. Doing things this way ensures that we only enable
// the experiment if its results are actually going to be reported. // the experiment if its results are actually going to be reported.
std::wstring metrics_id; string16 metrics_id;
if (!GoogleUpdateSettings::GetMetricsId(&metrics_id) || metrics_id.empty()) if (!GoogleUpdateSettings::GetMetricsId(&metrics_id) || metrics_id.empty())
return false; return false;
...@@ -198,7 +200,7 @@ bool GetPreReadExperimentGroup(DWORD* pre_read_percentage) { ...@@ -198,7 +200,7 @@ bool GetPreReadExperimentGroup(DWORD* pre_read_percentage) {
// Expects that |dir| has a trailing backslash. |dir| is modified so it // 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 // 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. // value not being null to determine if this path contains a valid dll.
HMODULE LoadChromeWithDirectory(std::wstring* dir) { HMODULE LoadChromeWithDirectory(string16* dir) {
::SetCurrentDirectoryW(dir->c_str()); ::SetCurrentDirectoryW(dir->c_str());
const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
dir->append(installer::kChromeDll); dir->append(installer::kChromeDll);
...@@ -307,24 +309,24 @@ HMODULE LoadChromeWithDirectory(std::wstring* dir) { ...@@ -307,24 +309,24 @@ HMODULE LoadChromeWithDirectory(std::wstring* dir) {
LOAD_WITH_ALTERED_SEARCH_PATH); LOAD_WITH_ALTERED_SEARCH_PATH);
} }
void RecordDidRun(const std::wstring& dll_path) { void RecordDidRun(const string16& dll_path) {
bool system_level = !InstallUtil::IsPerUserInstall(dll_path.c_str()); bool system_level = !InstallUtil::IsPerUserInstall(dll_path.c_str());
GoogleUpdateSettings::UpdateDidRunState(true, system_level); GoogleUpdateSettings::UpdateDidRunState(true, system_level);
} }
void ClearDidRun(const std::wstring& dll_path) { void ClearDidRun(const string16& dll_path) {
bool system_level = !InstallUtil::IsPerUserInstall(dll_path.c_str()); bool system_level = !InstallUtil::IsPerUserInstall(dll_path.c_str());
GoogleUpdateSettings::UpdateDidRunState(false, system_level); GoogleUpdateSettings::UpdateDidRunState(false, system_level);
} }
} // namespace } // namespace
std::wstring GetExecutablePath() { string16 GetExecutablePath() {
wchar_t path[MAX_PATH]; wchar_t path[MAX_PATH];
::GetModuleFileNameW(NULL, path, MAX_PATH); ::GetModuleFileNameW(NULL, path, MAX_PATH);
if (!::PathRemoveFileSpecW(path)) if (!::PathRemoveFileSpecW(path))
return std::wstring(); return string16();
std::wstring exe_path(path); string16 exe_path(path);
return exe_path.append(1, L'\\'); return exe_path.append(1, L'\\');
} }
...@@ -346,14 +348,14 @@ MainDllLoader::~MainDllLoader() { ...@@ -346,14 +348,14 @@ MainDllLoader::~MainDllLoader() {
// If that fails then finally we look at the registry which should point us // If that fails then finally we look at the registry which should point us
// to the latest version. This is the expected path for the first chrome.exe // to the latest version. This is the expected path for the first chrome.exe
// browser instance in an installed build. // browser instance in an installed build.
HMODULE MainDllLoader::Load(std::wstring* out_version, std::wstring* out_file) { HMODULE MainDllLoader::Load(string16* out_version, string16* out_file) {
const std::wstring dir(GetExecutablePath()); const string16 dir(GetExecutablePath());
*out_file = dir; *out_file = dir;
HMODULE dll = LoadChromeWithDirectory(out_file); HMODULE dll = LoadChromeWithDirectory(out_file);
if (dll) if (dll)
return dll; return dll;
std::wstring version_string; string16 version_string;
Version version; Version version;
const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
if (cmd_line.HasSwitch(switches::kChromeVersion)) { if (cmd_line.HasSwitch(switches::kChromeVersion)) {
...@@ -367,7 +369,22 @@ HMODULE MainDllLoader::Load(std::wstring* out_version, std::wstring* out_file) { ...@@ -367,7 +369,22 @@ HMODULE MainDllLoader::Load(std::wstring* out_version, std::wstring* out_file) {
} }
} }
// If no version on the command line, then look in the environment. // If no version on the command line, then look at the version resource in
// the current module and try loading that.
if (!version.IsValid()) {
scoped_ptr<FileVersionInfo> file_version_info(
FileVersionInfo::CreateFileVersionInfoForCurrentModule());
if (file_version_info.get()) {
version_string = file_version_info->file_version();
version = Version(WideToASCII(version_string));
}
}
// TODO(robertshield): in theory, these next two checks (env and registry)
// should never be needed. Remove them when I become 100% certain this is
// also true in practice.
// If no version in the current module, then look in the environment.
if (!version.IsValid()) { if (!version.IsValid()) {
if (EnvQueryStr(ASCIIToWide(chrome::kChromeVersionEnvVar).c_str(), if (EnvQueryStr(ASCIIToWide(chrome::kChromeVersionEnvVar).c_str(),
&version_string)) { &version_string)) {
...@@ -403,8 +420,8 @@ HMODULE MainDllLoader::Load(std::wstring* out_version, std::wstring* out_file) { ...@@ -403,8 +420,8 @@ HMODULE MainDllLoader::Load(std::wstring* out_version, std::wstring* out_file) {
// add custom code in the OnBeforeLaunch callback. // add custom code in the OnBeforeLaunch callback.
int MainDllLoader::Launch(HINSTANCE instance, int MainDllLoader::Launch(HINSTANCE instance,
sandbox::SandboxInterfaceInfo* sbox_info) { sandbox::SandboxInterfaceInfo* sbox_info) {
std::wstring version; string16 version;
std::wstring file; string16 file;
dll_ = Load(&version, &file); dll_ = Load(&version, &file);
if (!dll_) if (!dll_)
return chrome::RESULT_CODE_MISSING_DATA; return chrome::RESULT_CODE_MISSING_DATA;
...@@ -424,12 +441,12 @@ int MainDllLoader::Launch(HINSTANCE instance, ...@@ -424,12 +441,12 @@ int MainDllLoader::Launch(HINSTANCE instance,
return OnBeforeExit(rc, file); return OnBeforeExit(rc, file);
} }
std::wstring MainDllLoader::GetVersion() { string16 MainDllLoader::GetVersion() {
std::wstring reg_path(GetRegistryPath()); string16 reg_path(GetRegistryPath());
std::wstring version_string; string16 version_string;
std::wstring dir(GetExecutablePath()); string16 dir(GetExecutablePath());
if (!GetChromeVersion(dir.c_str(), reg_path.c_str(), &version_string)) if (!GetChromeVersion(dir.c_str(), reg_path.c_str(), &version_string))
return std::wstring(); return string16();
return version_string; return version_string;
} }
...@@ -450,18 +467,18 @@ void MainDllLoader::RelaunchChromeBrowserWithNewCommandLineIfNeeded() { ...@@ -450,18 +467,18 @@ void MainDllLoader::RelaunchChromeBrowserWithNewCommandLineIfNeeded() {
class ChromeDllLoader : public MainDllLoader { class ChromeDllLoader : public MainDllLoader {
public: public:
virtual std::wstring GetRegistryPath() { virtual string16 GetRegistryPath() {
std::wstring key(google_update::kRegPathClients); string16 key(google_update::kRegPathClients);
BrowserDistribution* dist = BrowserDistribution::GetDistribution(); BrowserDistribution* dist = BrowserDistribution::GetDistribution();
key.append(L"\\").append(dist->GetAppGuid()); key.append(L"\\").append(dist->GetAppGuid());
return key; return key;
} }
virtual void OnBeforeLaunch(const std::wstring& dll_path) { virtual void OnBeforeLaunch(const string16& dll_path) {
RecordDidRun(dll_path); RecordDidRun(dll_path);
} }
virtual int OnBeforeExit(int return_code, const std::wstring& dll_path) { virtual int OnBeforeExit(int return_code, const string16& dll_path) {
// NORMAL_EXIT_CANCEL is used for experiments when the user cancels // NORMAL_EXIT_CANCEL is used for experiments when the user cancels
// so we need to reset the did_run signal so omaha does not count // so we need to reset the did_run signal so omaha does not count
// this run as active usage. // this run as active usage.
...@@ -476,7 +493,7 @@ class ChromeDllLoader : public MainDllLoader { ...@@ -476,7 +493,7 @@ class ChromeDllLoader : public MainDllLoader {
class ChromiumDllLoader : public MainDllLoader { class ChromiumDllLoader : public MainDllLoader {
public: public:
virtual std::wstring GetRegistryPath() { virtual string16 GetRegistryPath() {
BrowserDistribution* dist = BrowserDistribution::GetDistribution(); BrowserDistribution* dist = BrowserDistribution::GetDistribution();
return dist->GetVersionKey(); return dist->GetVersionKey();
} }
......
...@@ -9,14 +9,15 @@ ...@@ -9,14 +9,15 @@
#define CHROME_APP_CLIENT_UTIL_H_ #define CHROME_APP_CLIENT_UTIL_H_
#include <windows.h> #include <windows.h>
#include <string>
#include "base/string16.h"
namespace sandbox { namespace sandbox {
struct SandboxInterfaceInfo; struct SandboxInterfaceInfo;
} }
// Gets the path of the current exe with a trailing backslash. // Gets the path of the current exe with a trailing backslash.
std::wstring GetExecutablePath(); string16 GetExecutablePath();
// Implements the common aspects of loading chrome.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 // chromium scenarios, which are in charge of implementing two abstract
...@@ -34,7 +35,7 @@ class MainDllLoader { ...@@ -34,7 +35,7 @@ class MainDllLoader {
int Launch(HINSTANCE instance, sandbox::SandboxInterfaceInfo* sbox_info); int Launch(HINSTANCE instance, sandbox::SandboxInterfaceInfo* sbox_info);
// Look into the registry to find the latest version. // Look into the registry to find the latest version.
std::wstring GetVersion(); string16 GetVersion();
// Launches a new instance of the browser if the current instance in // Launches a new instance of the browser if the current instance in
// persistent mode an upgrade is detected. // persistent mode an upgrade is detected.
...@@ -43,21 +44,21 @@ class MainDllLoader { ...@@ -43,21 +44,21 @@ class MainDllLoader {
// Called after chrome.dll has been loaded but before the entry point // Called after chrome.dll has been loaded but before the entry point
// is invoked. Derived classes can implement custom actions here. // is invoked. Derived classes can implement custom actions here.
// |dll_path| refers to the path of the Chrome dll being loaded. // |dll_path| refers to the path of the Chrome dll being loaded.
virtual void OnBeforeLaunch(const std::wstring& dll_path) {} virtual void OnBeforeLaunch(const string16& dll_path) {}
// Called after the chrome.dll entry point returns and before terminating // Called after the chrome.dll entry point returns and before terminating
// this process. The return value will be used as the process return code. // 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. // |dll_path| refers to the path of the Chrome dll being loaded.
virtual int OnBeforeExit(int return_code, const std::wstring& dll_path) { virtual int OnBeforeExit(int return_code, const string16& dll_path) {
return return_code; return return_code;
} }
protected: protected:
// Derived classes must return the relative registry path that holds the // Derived classes must return the relative registry path that holds the
// most current version of chrome.dll. // most current version of chrome.dll.
virtual std::wstring GetRegistryPath() = 0; virtual string16 GetRegistryPath() = 0;
HMODULE Load(std::wstring* out_version, std::wstring* out_file); HMODULE Load(string16* out_version, string16* out_file);
private: private:
// Chrome.dll handle. // Chrome.dll handle.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment