summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/client_util.cc15
-rw-r--r--chrome/app/client_util.h3
-rw-r--r--chrome/app/google_update_client.cc3
-rw-r--r--chrome/browser/google_update.cc101
-rw-r--r--chrome/installer/util/install_util.cc22
-rwxr-xr-xchrome/installer/util/install_util.h7
6 files changed, 113 insertions, 38 deletions
diff --git a/chrome/app/client_util.cc b/chrome/app/client_util.cc
index 333a525..a8841cd 100644
--- a/chrome/app/client_util.cc
+++ b/chrome/app/client_util.cc
@@ -3,8 +3,7 @@
// found in the LICENSE file.
#include "chrome/app/client_util.h"
-
-#include <shlobj.h>
+#include "chrome/installer/util/install_util.h"
namespace client_util {
const wchar_t kProductVersionKey[] = L"pv";
@@ -17,7 +16,7 @@ bool FileExists(const wchar_t* const file_path) {
bool GetChromiumVersion(const wchar_t* const exe_path,
const wchar_t* const reg_key_path,
wchar_t** version) {
- HKEY reg_root = IsUserModeInstall(exe_path) ? HKEY_CURRENT_USER :
+ HKEY reg_root = InstallUtil::IsPerUserInstall(exe_path) ? HKEY_CURRENT_USER :
HKEY_LOCAL_MACHINE;
HKEY reg_key;
if (::RegOpenKeyEx(reg_root, reg_key_path, 0,
@@ -69,15 +68,5 @@ void GetExecutablePath(wchar_t* exe_path) {
}
}
-bool IsUserModeInstall(const wchar_t* const exe_path) {
- wchar_t buffer[MAX_PATH] = {0};
- if (!FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
- SHGFP_TYPE_CURRENT, buffer))) {
- if (exe_path == wcsstr(exe_path, buffer)) {
- return false;
- }
- }
- return true;
-}
} // namespace client_util
diff --git a/chrome/app/client_util.h b/chrome/app/client_util.h
index e4b479e..f0b75bb 100644
--- a/chrome/app/client_util.h
+++ b/chrome/app/client_util.h
@@ -40,9 +40,6 @@ std::wstring GetDLLPath(const std::wstring dll_name,
// function. The buffer should already be allocated (ideally of MAX_PATH size).
void GetExecutablePath(wchar_t* exe_path);
-// Returns false if this is system level install (exe_path is same as
-// Program Files path) else returns true.
-bool IsUserModeInstall(const wchar_t* const exe_path);
} // namespace client_util
#endif // CHROME_APP_CLIENT_UTIL_H_
diff --git a/chrome/app/google_update_client.cc b/chrome/app/google_update_client.cc
index b691ec5..8ae8aee 100644
--- a/chrome/app/google_update_client.cc
+++ b/chrome/app/google_update_client.cc
@@ -9,6 +9,7 @@
#include "chrome/app/client_util.h"
#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/install_util.h"
namespace {
const wchar_t kEnvProductVersionKey[] = L"CHROME_VERSION";
@@ -108,7 +109,7 @@ bool GoogleUpdateClient::Launch(HINSTANCE instance,
bool GoogleUpdateClient::Init(const wchar_t* client_guid,
const wchar_t* client_dll) {
client_util::GetExecutablePath(dll_path_);
- user_mode_ = client_util::IsUserModeInstall(dll_path_);
+ user_mode_ = InstallUtil::IsPerUserInstall(dll_path_);
guid_.assign(client_guid);
dll_.assign(client_dll);
diff --git a/chrome/browser/google_update.cc b/chrome/browser/google_update.cc
index 0269e4c..a609fb4 100644
--- a/chrome/browser/google_update.cc
+++ b/chrome/browser/google_update.cc
@@ -9,40 +9,73 @@
#include "base/message_loop.h"
#include "base/path_service.h"
+#include "base/string_util.h"
#include "base/task.h"
#include "base/thread.h"
+#include "base/win_util.h"
+
+#include "chrome/app/client_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/helper.h"
+#include "chrome/installer/util/install_util.h"
#include "google_update_idl_i.c"
namespace {
// Check if the currently running Chrome can be updated by Google Update by
// checking if it is running from the standard location. Return true if running
// from the standard location, otherwise return false.
-bool CanUpdateCurrentChrome() {
- std::wstring current_exe_path;
- if (PathService::Get(base::DIR_EXE, &current_exe_path)) {
- std::wstring user_exe_path = installer::GetChromeInstallPath(false);
- std::wstring machine_exe_path = installer::GetChromeInstallPath(true);
- std::transform(current_exe_path.begin(), current_exe_path.end(),
- current_exe_path.begin(), tolower);
- std::transform(user_exe_path.begin(), user_exe_path.end(),
- user_exe_path.begin(), tolower);
- std::transform(machine_exe_path.begin(), machine_exe_path.end(),
- machine_exe_path.begin(), tolower);
- if (current_exe_path != user_exe_path &&
- current_exe_path != machine_exe_path ) {
- LOG(ERROR) << L"Google Update cannot update Chrome installed in a "
- << L"non-standard location: " << current_exe_path.c_str()
- << L". The standard location is: " << user_exe_path.c_str()
- << L" or " << machine_exe_path.c_str() << L".";
- return false;
- }
+bool CanUpdateCurrentChrome(const std::wstring& chrome_exe_path) {
+ std::wstring user_exe_path = installer::GetChromeInstallPath(false);
+ std::wstring machine_exe_path = installer::GetChromeInstallPath(true);
+ std::transform(user_exe_path.begin(), user_exe_path.end(),
+ user_exe_path.begin(), tolower);
+ std::transform(machine_exe_path.begin(), machine_exe_path.end(),
+ machine_exe_path.begin(), tolower);
+ if (chrome_exe_path != user_exe_path &&
+ chrome_exe_path != machine_exe_path ) {
+ LOG(ERROR) << L"Google Update cannot update Chrome installed in a "
+ << L"non-standard location: " << chrome_exe_path.c_str()
+ << L". The standard location is: " << user_exe_path.c_str()
+ << L" or " << machine_exe_path.c_str() << L".";
+ return false;
}
return true;
}
+
+// Creates an instance of a COM Local Server class using either plain vanilla
+// CoCreateInstance, or using the Elevation moniker if running on Vista.
+HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id,
+ void** interface_ptr) {
+ if (!interface_ptr)
+ return E_POINTER;
+
+ // For Vista we need to instantiate the COM server via the elevation
+ // moniker. This ensures that the UAC dialog shows up.
+ if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA) {
+ wchar_t class_id_as_string[MAX_PATH] = {0};
+ StringFromGUID2(class_id, class_id_as_string,
+ arraysize(class_id_as_string));
+
+ std::wstring elevation_moniker_name =
+ StringPrintf(L"Elevation:Administrator!new:%s", class_id_as_string);
+
+ BIND_OPTS3 bind_opts;
+ memset(&bind_opts, 0, sizeof(bind_opts));
+
+ bind_opts.cbStruct = sizeof(bind_opts);
+ bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER;
+ return CoGetObject(elevation_moniker_name.c_str(), &bind_opts,
+ interface_id, reinterpret_cast<void**>(interface_ptr));
+ }
+
+ return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER,
+ interface_id,
+ reinterpret_cast<void**>(interface_ptr));
+}
+
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -188,12 +221,23 @@ void GoogleUpdate::RemoveStatusChangeListener() {
bool GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer,
MessageLoop* main_loop) {
- if (!CanUpdateCurrentChrome()) {
+
+ std::wstring chrome_exe_path;
+ if (!PathService::Get(base::DIR_EXE, &chrome_exe_path)) {
+ NOTREACHED();
+ return false;
+ }
+
+ std::transform(chrome_exe_path.begin(), chrome_exe_path.end(),
+ chrome_exe_path.begin(), tolower);
+
+ if (!CanUpdateCurrentChrome(chrome_exe_path)) {
main_loop->PostTask(FROM_HERE, NewRunnableMethod(this,
&GoogleUpdate::ReportResults, UPGRADE_ERROR,
CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY));
return false;
}
+
CComObject<GoogleUpdateJobObserver>* job_observer;
HRESULT hr =
CComObject<GoogleUpdateJobObserver>::CreateInstance(&job_observer);
@@ -205,7 +249,22 @@ bool GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer,
CComPtr<IJobObserver> job_holder(job_observer);
CComPtr<IGoogleUpdate> on_demand;
- hr = on_demand.CoCreateInstance(CLSID_OnDemandUserAppsClass);
+
+ if (InstallUtil::IsPerUserInstall(chrome_exe_path.c_str())) {
+ hr = on_demand.CoCreateInstance(CLSID_OnDemandUserAppsClass);
+ } else {
+ // The Update operation needs Admin privileges for writing
+ // to %ProgramFiles%. On Vista we need to elevate before instantiating
+ // the updater instance.
+ if (!install_if_newer) {
+ hr = on_demand.CoCreateInstance(CLSID_OnDemandMachineAppsClass);
+ } else {
+ hr = CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass,
+ IID_IGoogleUpdate,
+ reinterpret_cast<void**>(&on_demand));
+ }
+ }
+
if (hr != S_OK)
return ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND, main_loop);
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index a372070..bec4af8 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -7,12 +7,15 @@
#include "install_util.h"
+#include <algorithm>
#include <shellapi.h>
+#include <shlobj.h>
#include "base/logging.h"
#include "base/registry.h"
#include "base/string_util.h"
#include "base/win_util.h"
+
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/l10n_string_util.h"
@@ -109,3 +112,22 @@ void InstallUtil::WriteInstallerResult(bool system_install,
if (!install_list->Do())
LOG(ERROR) << "Failed to record installer error information in registry.";
}
+
+bool InstallUtil::IsPerUserInstall(const wchar_t* const exe_path) {
+ std::wstring exe_path_copy = exe_path;
+
+ wchar_t program_files_path[MAX_PATH] = {0};
+ if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
+ SHGFP_TYPE_CURRENT, program_files_path))) {
+ std::wstring program_files_path_copy = program_files_path;
+
+ if (std::equal(program_files_path_copy.begin(),
+ program_files_path_copy.end(), exe_path_copy.begin(),
+ CaseInsensitiveCompare<wchar_t>())) {
+ return false;
+ }
+ } else {
+ NOTREACHED();
+ }
+ return true;
+} \ No newline at end of file
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h
index 95c4bf9..ee6e2ff 100755
--- a/chrome/installer/util/install_util.h
+++ b/chrome/installer/util/install_util.h
@@ -10,6 +10,7 @@
#define CHROME_INSTALLER_UTIL_INSTALL_UTIL_H__
#include <string>
+#include <tchar.h>
#include <windows.h>
#include "base/basictypes.h"
@@ -46,6 +47,12 @@ class InstallUtil {
installer_util::InstallStatus status,
int string_resource_id,
const std::wstring* const launch_cmd);
+
+ // Returns true if this installation path is per user, otherwise returns
+ // false (per machine install, meaning: the exe_path contains path to
+ // Program Files).
+ static bool IsPerUserInstall(const wchar_t* const exe_path);
+
private:
DISALLOW_EVIL_CONSTRUCTORS(InstallUtil);
};