Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Unified Diff: chrome/app/client_util.cc

Issue 345036: Rewrite of chrome.exe startup code... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/app/client_util.h ('k') | chrome/app/google_update_client.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/app/client_util.cc
===================================================================
--- chrome/app/client_util.cc (revision 29840)
+++ chrome/app/client_util.cc (working copy)
@@ -2,96 +2,201 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <windows.h>
+#include <shlwapi.h>
+
+#include "chrome/app/breakpad_win.h"
#include "chrome/app/client_util.h"
+#include "chrome/common/result_codes.h"
#include "chrome/installer/util/install_util.h"
-
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/util_constants.h"
namespace {
-bool ReadStrValueFromRegistry(const HKEY reg_key,
- const wchar_t* const value_name,
- wchar_t** value) {
- DWORD size = 0;
- if (::RegQueryValueEx(reg_key, value_name, NULL, NULL, NULL,
- &size) != ERROR_SUCCESS) {
- return false;
- }
+// The entry point signature of chrome.dll.
+typedef int (*DLL_MAIN)(HINSTANCE, sandbox::SandboxInterfaceInfo*, wchar_t*);
- *value = new wchar_t[1 + (size / sizeof(wchar_t))];
- if (::RegQueryValueEx(reg_key, value_name, NULL, NULL,
- reinterpret_cast<BYTE*>(*value),
- &size) != ERROR_SUCCESS) {
- delete[] *value;
+// Not generic, we only handle strings up to 128 chars.
+bool ReadRegistryStr(HKEY key, const wchar_t* name, std::wstring* value) {
+ BYTE out[128 * sizeof(wchar_t)];
+ DWORD size = sizeof(out);
+ DWORD type = 0;
+ if (ERROR_SUCCESS != ::RegQueryValueExW(key, name, NULL, &type, out, &size))
return false;
- }
-
+ if (type != REG_SZ)
+ return false;
+ value->assign(reinterpret_cast<wchar_t*>(out));
return true;
}
-}
-namespace client_util {
-bool FileExists(const std::wstring& file_path) {
- WIN32_FILE_ATTRIBUTE_DATA attrs;
- return ::GetFileAttributesEx(
- file_path.c_str(), GetFileExInfoStandard, &attrs) != 0;
-}
-
-bool GetChromiumVersion(const wchar_t* const exe_path,
- const wchar_t* const reg_key_path,
- wchar_t** version) {
+// Gets chrome version according to the load path. |exe_path| must be the
+// backslash terminated directory of the current chrome.exe.
+bool GetVersion(const wchar_t* exe_path, const wchar_t* key_path,
+ std::wstring* version) {
HKEY reg_root = InstallUtil::IsPerUserInstall(exe_path) ? HKEY_CURRENT_USER :
HKEY_LOCAL_MACHINE;
- HKEY reg_key;
- if (::RegOpenKeyEx(reg_root, reg_key_path, 0,
- KEY_READ, &reg_key) != ERROR_SUCCESS) {
+ HKEY key;
+ if (::RegOpenKeyEx(reg_root, key_path, 0, KEY_READ, &key) != ERROR_SUCCESS)
return false;
- }
+ // If 'new_chrome.exe' is present it means chrome was auto-updated while
+ // 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_path);
new_chrome_exe.append(installer_util::kChromeNewExe);
- if (FileExists(new_chrome_exe) &&
- ReadStrValueFromRegistry(reg_key, google_update::kRegOldVersionField,
- version)) {
- ::RegCloseKey(reg_key);
+ if (::PathFileExistsW(new_chrome_exe.c_str()) &&
+ ReadRegistryStr(key, google_update::kRegOldVersionField, version)) {
+ ::RegCloseKey(key);
return true;
}
- bool ret = ReadStrValueFromRegistry(reg_key,
- google_update::kRegVersionField,
- version);
- ::RegCloseKey(reg_key);
+ bool ret = ReadRegistryStr(key, google_update::kRegVersionField, version);
+ ::RegCloseKey(key);
return ret;
}
-std::wstring GetDLLPath(const std::wstring& dll_name,
- const std::wstring& dll_path) {
- if (!dll_path.empty() && FileExists(dll_path))
- return dll_path + L"\\" + dll_name;
-
- // This is not an official build. Find the dll using the default
- // path order in LoadLibrary.
- wchar_t path[MAX_PATH] = {0};
- wchar_t* file_part = NULL;
- DWORD result = ::SearchPath(NULL, dll_name.c_str(), NULL, MAX_PATH,
- path, &file_part);
- if (result == 0 || result > MAX_PATH)
+// Gets the path of the current exe with a trailing backslash.
+std::wstring GetExecutablePath() {
+ wchar_t path[MAX_PATH];
+ ::GetModuleFileNameW(NULL, path, MAX_PATH);
+ if (!::PathRemoveFileSpecW(path))
return std::wstring();
+ std::wstring exe_path(path);
+ return exe_path.append(L"\\");
+}
- return path;
+// Not generic, we only handle strings up to 128 chars.
+bool EnvQueryStr(const wchar_t* key_name, std::wstring* value) {
+ wchar_t out[128];
+ DWORD count = sizeof(out)/sizeof(out[0]);
+ DWORD rv = ::GetEnvironmentVariableW(key_name, out, count);
+ if ((rv == 0) || (rv >= count))
+ return false;
+ *value = out;
+ return true;
}
-std::wstring GetExecutablePath() {
- wchar_t exe_path[MAX_PATH];
- DWORD len = ::GetModuleFileName(NULL, exe_path, MAX_PATH);
- wchar_t* tmp = exe_path + len - 1;
- while (tmp >= exe_path && *tmp != L'\\')
- tmp--;
- if (tmp > exe_path) {
- tmp++;
- *tmp = 0;
+// 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 dermine if this path contains a valid dll.
+HMODULE LoadChromeWithDirectory(std::wstring* dir) {
+ ::SetCurrentDirectoryW(dir->c_str());
+ dir->append(installer_util::kChromeDll);
+ return ::LoadLibraryExW(dir->c_str(), NULL,
+ LOAD_WITH_ALTERED_SEARCH_PATH);
+}
+
+// record did_run "dr" in client state.
+bool RecordDidRun(const wchar_t* guid) {
+ std::wstring key_path(google_update::kRegPathClientState);
+ key_path.append(L"\\").append(guid);
+ HKEY reg_key;
+ if (::RegCreateKeyExW(HKEY_CURRENT_USER, key_path.c_str(), 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
+ &reg_key, NULL) == ERROR_SUCCESS) {
+ const wchar_t kVal[] = L"1";
+ ::RegSetValueExW(reg_key, google_update::kRegDidRunField, 0, REG_SZ,
+ reinterpret_cast<const BYTE *>(kVal), sizeof(kVal));
+ ::RegCloseKey(reg_key);
+ return true;
}
- return exe_path;
+ return false;
}
+}
-} // namespace client_util
+//=============================================================================
+
+MainDllLoader::MainDllLoader() : dll_(NULL) {
+}
+
+MainDllLoader::~MainDllLoader() {
+#ifdef PURIFY
+ // We should never unload the dll. There is only risk and no gain from
+ // doing so. The singleton dtors have been already run by AtExitManager.
+ ::FreeLibrary(dll_);
+#endif
+}
+
+// Loading chrome is an interesting afair. First we try loading from the current
+// directory to support run-what-you-compile and other development scenarios.
+// If that fails then we look at the 'CHROME_VERSION' env variable to determine
+// if we should stick with an older dll version even if a new one is available
+// to support upgrade-in-place scenarios, and if that fails we finally we look
+// at the registry which should point us to the latest version.
+HMODULE MainDllLoader::Load(std::wstring* version, std::wstring* file) {
+ std::wstring dir(GetExecutablePath());
+ *file = dir;
+ HMODULE dll = LoadChromeWithDirectory(file);
+ if (dll)
+ return dll;
+
+ if (!EnvQueryStr(google_update::kEnvProductVersionKey, version)) {
+ std::wstring reg_path(GetRegistryPath());
+ // Look into the registry to find the latest version.
+ if (!GetVersion(dir.c_str(), reg_path.c_str(), version))
+ return NULL;
+ }
+
+ *file = dir;
+ file->append(*version);
+ return LoadChromeWithDirectory(file);
+}
+
+// Launching is a matter of loading the right dll, setting the CHROME_VERSION
+// environment variable and just calling the entry point. Derived classes can
+// add custom code in the OnBeforeLaunch callback.
+int MainDllLoader::Launch(HINSTANCE instance,
+ sandbox::SandboxInterfaceInfo* sbox_info) {
+ std::wstring version;
+ std::wstring file;
+ dll_ = Load(&version, &file);
+ if (!dll_)
+ return ResultCodes::MISSING_DATA;
+
+ ::SetEnvironmentVariableW(google_update::kEnvProductVersionKey,
+ version.c_str());
+
+ InitCrashReporterWithDllPath(file);
+
+ OnBeforeLaunch(version);
+
+ DLL_MAIN entry_point =
+ reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain"));
+ if (!entry_point)
+ return ResultCodes::BAD_PROCESS_TYPE;
+
+ return entry_point(instance, sbox_info, ::GetCommandLineW());
+}
+
+//=============================================================================
+
+class ChromeDllLoader : public MainDllLoader {
+ public:
+ virtual std::wstring GetRegistryPath() {
+ std::wstring key(google_update::kRegPathClients);
+ key.append(L"\\").append(google_update::kChromeGuid);
+ return key;
+ }
+
+ virtual void OnBeforeLaunch(const std::wstring& version) {
+ RecordDidRun(google_update::kChromeGuid);
+ }
+};
+
+//=============================================================================
+
+class ChromiumDllLoader : public MainDllLoader {
+ public:
+ virtual std::wstring GetRegistryPath() {
+ return L"Software\\Chromium";
+ }
+};
+
+MainDllLoader* MakeMainDllLoader() {
+#if defined(GOOGLE_CHROME_BUILD)
+ return new ChromeDllLoader();
+#else
+ return new ChromiumDllLoader();
+#endif
+}
« no previous file with comments | « chrome/app/client_util.h ('k') | chrome/app/google_update_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698