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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/app/client_util.h ('k') | chrome/app/google_update_client.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <windows.h>
6 #include <shlwapi.h>
7
8 #include "chrome/app/breakpad_win.h"
5 #include "chrome/app/client_util.h" 9 #include "chrome/app/client_util.h"
10 #include "chrome/common/result_codes.h"
6 #include "chrome/installer/util/install_util.h" 11 #include "chrome/installer/util/install_util.h"
7
8 #include "chrome/installer/util/google_update_constants.h" 12 #include "chrome/installer/util/google_update_constants.h"
9 #include "chrome/installer/util/util_constants.h" 13 #include "chrome/installer/util/util_constants.h"
10 14
11 namespace { 15 namespace {
12 bool ReadStrValueFromRegistry(const HKEY reg_key, 16 // The entry point signature of chrome.dll.
13 const wchar_t* const value_name, 17 typedef int (*DLL_MAIN)(HINSTANCE, sandbox::SandboxInterfaceInfo*, wchar_t*);
14 wchar_t** value) { 18
15 DWORD size = 0; 19 // Not generic, we only handle strings up to 128 chars.
16 if (::RegQueryValueEx(reg_key, value_name, NULL, NULL, NULL, 20 bool ReadRegistryStr(HKEY key, const wchar_t* name, std::wstring* value) {
17 &size) != ERROR_SUCCESS) { 21 BYTE out[128 * sizeof(wchar_t)];
18 return false; 22 DWORD size = sizeof(out);
19 } 23 DWORD type = 0;
20 24 if (ERROR_SUCCESS != ::RegQueryValueExW(key, name, NULL, &type, out, &size))
21 *value = new wchar_t[1 + (size / sizeof(wchar_t))]; 25 return false;
22 if (::RegQueryValueEx(reg_key, value_name, NULL, NULL, 26 if (type != REG_SZ)
23 reinterpret_cast<BYTE*>(*value), 27 return false;
24 &size) != ERROR_SUCCESS) { 28 value->assign(reinterpret_cast<wchar_t*>(out));
25 delete[] *value;
26 return false;
27 }
28
29 return true; 29 return true;
30 } 30 }
31 } 31
32 32 // Gets chrome version according to the load path. |exe_path| must be the
33 namespace client_util { 33 // backslash terminated directory of the current chrome.exe.
34 bool FileExists(const std::wstring& file_path) { 34 bool GetVersion(const wchar_t* exe_path, const wchar_t* key_path,
35 WIN32_FILE_ATTRIBUTE_DATA attrs; 35 std::wstring* version) {
36 return ::GetFileAttributesEx(
37 file_path.c_str(), GetFileExInfoStandard, &attrs) != 0;
38 }
39
40 bool GetChromiumVersion(const wchar_t* const exe_path,
41 const wchar_t* const reg_key_path,
42 wchar_t** version) {
43 HKEY reg_root = InstallUtil::IsPerUserInstall(exe_path) ? HKEY_CURRENT_USER : 36 HKEY reg_root = InstallUtil::IsPerUserInstall(exe_path) ? HKEY_CURRENT_USER :
44 HKEY_LOCAL_MACHINE; 37 HKEY_LOCAL_MACHINE;
45 HKEY reg_key; 38 HKEY key;
46 if (::RegOpenKeyEx(reg_root, reg_key_path, 0, 39 if (::RegOpenKeyEx(reg_root, key_path, 0, KEY_READ, &key) != ERROR_SUCCESS)
47 KEY_READ, &reg_key) != ERROR_SUCCESS) { 40 return false;
48 return false; 41
49 } 42 // If 'new_chrome.exe' is present it means chrome was auto-updated while
50 43 // running. We need to consult the opv value so we can load the old dll.
44 // TODO(cpu) : This is solving the same problem as the environment variable
45 // so one of them will eventually be deprecated.
51 std::wstring new_chrome_exe(exe_path); 46 std::wstring new_chrome_exe(exe_path);
52 new_chrome_exe.append(installer_util::kChromeNewExe); 47 new_chrome_exe.append(installer_util::kChromeNewExe);
53 if (FileExists(new_chrome_exe) && 48 if (::PathFileExistsW(new_chrome_exe.c_str()) &&
54 ReadStrValueFromRegistry(reg_key, google_update::kRegOldVersionField, 49 ReadRegistryStr(key, google_update::kRegOldVersionField, version)) {
55 version)) { 50 ::RegCloseKey(key);
51 return true;
52 }
53
54 bool ret = ReadRegistryStr(key, google_update::kRegVersionField, version);
55 ::RegCloseKey(key);
56 return ret;
57 }
58
59 // Gets the path of the current exe with a trailing backslash.
60 std::wstring GetExecutablePath() {
61 wchar_t path[MAX_PATH];
62 ::GetModuleFileNameW(NULL, path, MAX_PATH);
63 if (!::PathRemoveFileSpecW(path))
64 return std::wstring();
65 std::wstring exe_path(path);
66 return exe_path.append(L"\\");
67 }
68
69 // Not generic, we only handle strings up to 128 chars.
70 bool EnvQueryStr(const wchar_t* key_name, std::wstring* value) {
71 wchar_t out[128];
72 DWORD count = sizeof(out)/sizeof(out[0]);
73 DWORD rv = ::GetEnvironmentVariableW(key_name, out, count);
74 if ((rv == 0) || (rv >= count))
75 return false;
76 *value = out;
77 return true;
78 }
79
80 // Expects that |dir| has a trailing backslash. |dir| is modified so it
81 // contains the full path that was tried. Caller must check for the return
82 // value not being null to dermine if this path contains a valid dll.
83 HMODULE LoadChromeWithDirectory(std::wstring* dir) {
84 ::SetCurrentDirectoryW(dir->c_str());
85 dir->append(installer_util::kChromeDll);
86 return ::LoadLibraryExW(dir->c_str(), NULL,
87 LOAD_WITH_ALTERED_SEARCH_PATH);
88 }
89
90 // record did_run "dr" in client state.
91 bool RecordDidRun(const wchar_t* guid) {
92 std::wstring key_path(google_update::kRegPathClientState);
93 key_path.append(L"\\").append(guid);
94 HKEY reg_key;
95 if (::RegCreateKeyExW(HKEY_CURRENT_USER, key_path.c_str(), 0, NULL,
96 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
97 &reg_key, NULL) == ERROR_SUCCESS) {
98 const wchar_t kVal[] = L"1";
99 ::RegSetValueExW(reg_key, google_update::kRegDidRunField, 0, REG_SZ,
100 reinterpret_cast<const BYTE *>(kVal), sizeof(kVal));
56 ::RegCloseKey(reg_key); 101 ::RegCloseKey(reg_key);
57 return true; 102 return true;
58 } 103 }
59 104 return false;
60 bool ret = ReadStrValueFromRegistry(reg_key, 105 }
61 google_update::kRegVersionField, 106 }
62 version); 107
63 ::RegCloseKey(reg_key); 108 //=============================================================================
64 return ret; 109
65 } 110 MainDllLoader::MainDllLoader() : dll_(NULL) {
66 111 }
67 std::wstring GetDLLPath(const std::wstring& dll_name, 112
68 const std::wstring& dll_path) { 113 MainDllLoader::~MainDllLoader() {
69 if (!dll_path.empty() && FileExists(dll_path)) 114 #ifdef PURIFY
70 return dll_path + L"\\" + dll_name; 115 // We should never unload the dll. There is only risk and no gain from
71 116 // doing so. The singleton dtors have been already run by AtExitManager.
72 // This is not an official build. Find the dll using the default 117 ::FreeLibrary(dll_);
73 // path order in LoadLibrary. 118 #endif
74 wchar_t path[MAX_PATH] = {0}; 119 }
75 wchar_t* file_part = NULL; 120
76 DWORD result = ::SearchPath(NULL, dll_name.c_str(), NULL, MAX_PATH, 121 // Loading chrome is an interesting afair. First we try loading from the current
77 path, &file_part); 122 // directory to support run-what-you-compile and other development scenarios.
78 if (result == 0 || result > MAX_PATH) 123 // If that fails then we look at the 'CHROME_VERSION' env variable to determine
79 return std::wstring(); 124 // if we should stick with an older dll version even if a new one is available
80 125 // to support upgrade-in-place scenarios, and if that fails we finally we look
81 return path; 126 // at the registry which should point us to the latest version.
82 } 127 HMODULE MainDllLoader::Load(std::wstring* version, std::wstring* file) {
83 128 std::wstring dir(GetExecutablePath());
84 std::wstring GetExecutablePath() { 129 *file = dir;
85 wchar_t exe_path[MAX_PATH]; 130 HMODULE dll = LoadChromeWithDirectory(file);
86 DWORD len = ::GetModuleFileName(NULL, exe_path, MAX_PATH); 131 if (dll)
87 wchar_t* tmp = exe_path + len - 1; 132 return dll;
88 while (tmp >= exe_path && *tmp != L'\\') 133
89 tmp--; 134 if (!EnvQueryStr(google_update::kEnvProductVersionKey, version)) {
90 if (tmp > exe_path) { 135 std::wstring reg_path(GetRegistryPath());
91 tmp++; 136 // Look into the registry to find the latest version.
92 *tmp = 0; 137 if (!GetVersion(dir.c_str(), reg_path.c_str(), version))
93 } 138 return NULL;
94 return exe_path; 139 }
95 } 140
96 141 *file = dir;
97 } // namespace client_util 142 file->append(*version);
143 return LoadChromeWithDirectory(file);
144 }
145
146 // Launching is a matter of loading the right dll, setting the CHROME_VERSION
147 // environment variable and just calling the entry point. Derived classes can
148 // add custom code in the OnBeforeLaunch callback.
149 int MainDllLoader::Launch(HINSTANCE instance,
150 sandbox::SandboxInterfaceInfo* sbox_info) {
151 std::wstring version;
152 std::wstring file;
153 dll_ = Load(&version, &file);
154 if (!dll_)
155 return ResultCodes::MISSING_DATA;
156
157 ::SetEnvironmentVariableW(google_update::kEnvProductVersionKey,
158 version.c_str());
159
160 InitCrashReporterWithDllPath(file);
161
162 OnBeforeLaunch(version);
163
164 DLL_MAIN entry_point =
165 reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain"));
166 if (!entry_point)
167 return ResultCodes::BAD_PROCESS_TYPE;
168
169 return entry_point(instance, sbox_info, ::GetCommandLineW());
170 }
171
172 //=============================================================================
173
174 class ChromeDllLoader : public MainDllLoader {
175 public:
176 virtual std::wstring GetRegistryPath() {
177 std::wstring key(google_update::kRegPathClients);
178 key.append(L"\\").append(google_update::kChromeGuid);
179 return key;
180 }
181
182 virtual void OnBeforeLaunch(const std::wstring& version) {
183 RecordDidRun(google_update::kChromeGuid);
184 }
185 };
186
187 //=============================================================================
188
189 class ChromiumDllLoader : public MainDllLoader {
190 public:
191 virtual std::wstring GetRegistryPath() {
192 return L"Software\\Chromium";
193 }
194 };
195
196 MainDllLoader* MakeMainDllLoader() {
197 #if defined(GOOGLE_CHROME_BUILD)
198 return new ChromeDllLoader();
199 #else
200 return new ChromiumDllLoader();
201 #endif
202 }
OLDNEW
« 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