summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-04 23:38:32 +0000
committerananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-04 23:38:32 +0000
commit48d4387babfc1e9a78028bce546bdccddb2e542b (patch)
tree6283b88d67a92b63d1e6db74862dbdf58de23e7e /chrome
parentaaa73ccc7ba5a44ce12160bfbb17a04743c2add5 (diff)
downloadchromium_src-48d4387babfc1e9a78028bce546bdccddb2e542b.zip
chromium_src-48d4387babfc1e9a78028bce546bdccddb2e542b.tar.gz
chromium_src-48d4387babfc1e9a78028bce546bdccddb2e542b.tar.bz2
This fixes the following bugs1. http://b/issue?id=1447957 For machine installs we need to use a different version of the Omaha updater.2. http://b/issue?id=1447951 For Vista we need to elevate while performing the update operation. This only applies to machine installs. Update checks also instantiate the same COM object. However it does not need elevation.Bug=1447957, 1447951R=finnur, kuchhal
Review URL: http://codereview.chromium.org/8221 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4705 0039d316-1c4b-4281-b951-d872f2087c98
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);
};