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 @@
#include "base/debug/trace_event.h"
#include "base/environment.h"
#include "base/file_util.h"
#include "base/file_version_info.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/rand_util.h" // For PreRead experiment.
#include "base/sha1.h" // For PreRead experiment.
#include "base/string16.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
......@@ -40,7 +42,7 @@ typedef void (*RelaunchChromeBrowserWithNewCommandLineIfNeededFunc)();
// Gets chrome version according to the load path. |exe_path| must be the
// backslash terminated directory of the current chrome.exe.
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_LOCAL_MACHINE;
bool success = false;
......@@ -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.
// TODO(cpu) : This is solving the same problem as the environment variable
// 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);
if (::PathFileExistsW(new_chrome_exe.c_str()) &&
key.ReadValue(google_update::kRegOldVersionField,
......@@ -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.
bool EnvQueryStr(const wchar_t* key_name, std::wstring* value) {
bool EnvQueryStr(const wchar_t* key_name, string16* value) {
wchar_t out[128];
DWORD count = sizeof(out)/sizeof(out[0]);
DWORD rv = ::GetEnvironmentVariableW(key_name, out, count);
......@@ -166,7 +168,7 @@ bool GetPreReadExperimentGroup(DWORD* pre_read_percentage) {
// 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
// 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())
return false;
......@@ -198,7 +200,7 @@ bool GetPreReadExperimentGroup(DWORD* pre_read_percentage) {
// 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(std::wstring* dir) {
HMODULE LoadChromeWithDirectory(string16* dir) {
::SetCurrentDirectoryW(dir->c_str());
const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
dir->append(installer::kChromeDll);
......@@ -307,24 +309,24 @@ HMODULE LoadChromeWithDirectory(std::wstring* dir) {
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());
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());
GoogleUpdateSettings::UpdateDidRunState(false, system_level);
}
} // namespace
std::wstring GetExecutablePath() {
string16 GetExecutablePath() {
wchar_t path[MAX_PATH];
::GetModuleFileNameW(NULL, path, MAX_PATH);
if (!::PathRemoveFileSpecW(path))
return std::wstring();
std::wstring exe_path(path);
return string16();
string16 exe_path(path);
return exe_path.append(1, L'\\');
}
......@@ -346,14 +348,14 @@ MainDllLoader::~MainDllLoader() {
// 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
// browser instance in an installed build.
HMODULE MainDllLoader::Load(std::wstring* out_version, std::wstring* out_file) {
const std::wstring dir(GetExecutablePath());
HMODULE MainDllLoader::Load(string16* out_version, string16* out_file) {
const string16 dir(GetExecutablePath());
*out_file = dir;
HMODULE dll = LoadChromeWithDirectory(out_file);
if (dll)
return dll;
std::wstring version_string;
string16 version_string;
Version version;
const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
if (cmd_line.HasSwitch(switches::kChromeVersion)) {
......@@ -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 (EnvQueryStr(ASCIIToWide(chrome::kChromeVersionEnvVar).c_str(),
&version_string)) {
......@@ -403,8 +420,8 @@ HMODULE MainDllLoader::Load(std::wstring* out_version, std::wstring* out_file) {
// add custom code in the OnBeforeLaunch callback.
int MainDllLoader::Launch(HINSTANCE instance,
sandbox::SandboxInterfaceInfo* sbox_info) {
std::wstring version;
std::wstring file;
string16 version;
string16 file;
dll_ = Load(&version, &file);
if (!dll_)
return chrome::RESULT_CODE_MISSING_DATA;
......@@ -424,12 +441,12 @@ int MainDllLoader::Launch(HINSTANCE instance,
return OnBeforeExit(rc, file);
}
std::wstring MainDllLoader::GetVersion() {
std::wstring reg_path(GetRegistryPath());
std::wstring version_string;
std::wstring dir(GetExecutablePath());
string16 MainDllLoader::GetVersion() {
string16 reg_path(GetRegistryPath());
string16 version_string;
string16 dir(GetExecutablePath());
if (!GetChromeVersion(dir.c_str(), reg_path.c_str(), &version_string))
return std::wstring();
return string16();
return version_string;
}
......@@ -450,18 +467,18 @@ void MainDllLoader::RelaunchChromeBrowserWithNewCommandLineIfNeeded() {
class ChromeDllLoader : public MainDllLoader {
public:
virtual std::wstring GetRegistryPath() {
std::wstring key(google_update::kRegPathClients);
virtual string16 GetRegistryPath() {
string16 key(google_update::kRegPathClients);
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
key.append(L"\\").append(dist->GetAppGuid());
return key;
}
virtual void OnBeforeLaunch(const std::wstring& dll_path) {
virtual void OnBeforeLaunch(const string16& 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
// so we need to reset the did_run signal so omaha does not count
// this run as active usage.
......@@ -476,7 +493,7 @@ class ChromeDllLoader : public MainDllLoader {
class ChromiumDllLoader : public MainDllLoader {
public:
virtual std::wstring GetRegistryPath() {
virtual string16 GetRegistryPath() {
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
return dist->GetVersionKey();
}
......
......@@ -9,14 +9,15 @@
#define CHROME_APP_CLIENT_UTIL_H_
#include <windows.h>
#include <string>
#include "base/string16.h"
namespace sandbox {
struct SandboxInterfaceInfo;
}
// 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
// chromium scenarios, which are in charge of implementing two abstract
......@@ -34,7 +35,7 @@ class MainDllLoader {
int Launch(HINSTANCE instance, sandbox::SandboxInterfaceInfo* sbox_info);
// 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
// persistent mode an upgrade is detected.
......@@ -43,21 +44,21 @@ class MainDllLoader {
// 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 std::wstring& dll_path) {}
virtual void OnBeforeLaunch(const 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 std::wstring& dll_path) {
virtual int OnBeforeExit(int return_code, const 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 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:
// 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