summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/installer/setup/install.cc97
-rw-r--r--chrome/installer/setup/setup_main.cc2
-rw-r--r--chrome/installer/setup/uninstall.cc8
-rw-r--r--chrome/installer/util/google_update_constants.cc1
-rw-r--r--chrome/installer/util/google_update_constants.h1
-rw-r--r--chrome/installer/util/install_util.cc82
-rw-r--r--chrome/installer/util/install_util.h19
-rw-r--r--chrome/installer/util/master_preferences.cc4
-rw-r--r--chrome/installer/util/master_preferences_constants.cc1
-rw-r--r--chrome/installer/util/master_preferences_constants.h2
10 files changed, 160 insertions, 57 deletions
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index 71ad8ae..cdeb22b 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -99,7 +99,7 @@ void AppendUninstallCommandLineFlags(std::wstring* uninstall_cmd_line,
uninstall_cmd_line->append(installer_util::switches::kChromeSxS);
}
- if (InstallUtil::IsMSIProcess()) {
+ if (InstallUtil::IsMSIProcess(is_system)) {
uninstall_cmd_line->append(L" --");
uninstall_cmd_line->append(installer_util::switches::kMsi);
}
@@ -126,25 +126,23 @@ void AddUninstallShortcutWorkItems(HKEY reg_root,
const std::wstring& product_name,
const std::wstring& new_version,
WorkItemList* install_list) {
- std::wstring uninstall_cmd(L"\"");
- uninstall_cmd.append(installer::GetInstallerPathUnderChrome(install_path,
- new_version));
- file_util::AppendToPath(&uninstall_cmd,
- file_util::GetFilenameFromPath(exe_path));
- uninstall_cmd.append(L"\"");
-
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-
// When we are installed via an MSI, we need to store our uninstall strings
// in the Google Update client state key. We do this even for non-MSI
// managed installs to avoid breaking the edge case whereby an MSI-managed
// install is updated by a non-msi installer (which would confuse the MSI
// machinery if these strings were not also updated).
+ // Do not quote the command line for the MSI invocation.
+ std::wstring uninstall_cmd(
+ installer::GetInstallerPathUnderChrome(install_path, new_version));
+ file_util::AppendToPath(&uninstall_cmd,
+ file_util::GetFilenameFromPath(exe_path));
std::wstring uninstall_arguments;
AppendUninstallCommandLineFlags(&uninstall_arguments,
reg_root == HKEY_LOCAL_MACHINE);
+
std::wstring update_state_key = dist->GetStateKey();
install_list->AddCreateRegKeyWorkItem(reg_root, update_state_key);
install_list->AddSetRegValueWorkItem(reg_root, update_state_key,
@@ -153,8 +151,13 @@ void AddUninstallShortcutWorkItems(HKEY reg_root,
installer_util::kUninstallArgumentsField, uninstall_arguments, true);
// MSI installations will manage their own uninstall shortcuts.
- if (!InstallUtil::IsMSIProcess()) {
- AppendUninstallCommandLineFlags(&uninstall_cmd,
+ if (!InstallUtil::IsMSIProcess(reg_root == HKEY_LOCAL_MACHINE)) {
+ // We need to quote the command line for the Add/Remove Programs dialog.
+ std::wstring quoted_uninstall_cmd(L"\"");
+ quoted_uninstall_cmd += uninstall_cmd;
+ quoted_uninstall_cmd += L"\"";
+
+ AppendUninstallCommandLineFlags(&quoted_uninstall_cmd,
reg_root == HKEY_LOCAL_MACHINE);
std::wstring uninstall_reg = dist->GetUninstallRegPath();
install_list->AddCreateRegKeyWorkItem(reg_root, uninstall_reg);
@@ -163,7 +166,8 @@ void AddUninstallShortcutWorkItems(HKEY reg_root,
install_list->AddSetRegValueWorkItem(reg_root,
uninstall_reg,
installer_util::kUninstallStringField,
- uninstall_cmd, true);
+ quoted_uninstall_cmd,
+ true);
install_list->AddSetRegValueWorkItem(reg_root,
uninstall_reg,
L"InstallLocation",
@@ -282,31 +286,37 @@ bool CreateOrUpdateChromeShortcuts(const std::wstring& exe_path,
product_desc, false);
}
- // Create/update uninstall link
- FilePath uninstall_link(shortcut_path); // Uninstall Chrome link
- uninstall_link = uninstall_link.Append(
- dist->GetUninstallLinkName() + L".lnk");
- if ((install_status == installer_util::FIRST_INSTALL_SUCCESS) ||
- (install_status == installer_util::INSTALL_REPAIRED) ||
- (file_util::PathExists(uninstall_link))) {
- if (!file_util::PathExists(shortcut_path))
- file_util::CreateDirectoryW(shortcut_path);
- std::wstring setup_exe(installer::GetInstallerPathUnderChrome(install_path,
- new_version));
- file_util::AppendToPath(&setup_exe,
- file_util::GetFilenameFromPath(exe_path));
-
- std::wstring arguments;
- AppendUninstallCommandLineFlags(&arguments, system_install);
-
- LOG(INFO) << "Creating/updating uninstall link at "
- << uninstall_link.value();
- ret = ret && file_util::CreateShortcutLink(setup_exe.c_str(),
- uninstall_link.value().c_str(),
- NULL,
- arguments.c_str(),
- NULL, setup_exe.c_str(), 0,
- NULL);
+ // Create/update uninstall link if we are not an MSI install. MSI
+ // installations are, for the time being, managed only through the
+ // Add/Remove Programs dialog.
+ // TODO(robertshield): We could add a shortcut to msiexec /X {GUID} here.
+ if (!InstallUtil::IsMSIProcess(system_install)) {
+ FilePath uninstall_link(shortcut_path); // Uninstall Chrome link
+ uninstall_link = uninstall_link.Append(
+ dist->GetUninstallLinkName() + L".lnk");
+ if ((install_status == installer_util::FIRST_INSTALL_SUCCESS) ||
+ (install_status == installer_util::INSTALL_REPAIRED) ||
+ (file_util::PathExists(uninstall_link))) {
+ if (!file_util::PathExists(shortcut_path))
+ file_util::CreateDirectoryW(shortcut_path);
+ std::wstring setup_exe(installer::GetInstallerPathUnderChrome(
+ install_path, new_version));
+ file_util::AppendToPath(&setup_exe,
+ file_util::GetFilenameFromPath(exe_path));
+
+ std::wstring arguments;
+ AppendUninstallCommandLineFlags(&arguments, system_install);
+ LOG(INFO) << "Creating/updating uninstall link at "
+ << uninstall_link.value();
+ ret = ret && file_util::CreateShortcutLink(setup_exe.c_str(),
+ uninstall_link.value().c_str(),
+ NULL,
+ arguments.c_str(),
+ NULL,
+ setup_exe.c_str(),
+ 0,
+ NULL);
+ }
}
// Update Desktop and Quick Launch shortcuts. If --create-new-shortcuts
@@ -334,6 +344,8 @@ bool CreateOrUpdateChromeShortcuts(const std::wstring& exe_path,
// - Handle the case of in-use-update by updating "opv" key or deleting it if
// not required.
// - Register any new dlls and unregister old dlls.
+// - If this is an MSI install, ensures that the MSI marker is set, and sets
+// it if not.
// If these operations are successful, the function returns true, otherwise
// false.
bool DoPostInstallTasks(HKEY reg_root,
@@ -345,6 +357,8 @@ bool DoPostInstallTasks(HKEY reg_root,
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
std::wstring version_key = dist->GetVersionKey();
+ bool is_system_install = (reg_root == HKEY_LOCAL_MACHINE);
+
if (file_util::PathExists(FilePath::FromWStringHack(new_chrome_exe))) {
// Looks like this was in use update. So make sure we update the 'opv' key
// with the current version that is active and 'cmd' key with the rename
@@ -366,7 +380,7 @@ bool DoPostInstallTasks(HKEY reg_root,
file_util::GetFilenameFromPath(exe_path));
rename_cmd = L"\"" + rename_cmd +
L"\" --" + installer_util::switches::kRenameChromeExe;
- if (reg_root == HKEY_LOCAL_MACHINE)
+ if (is_system_install)
rename_cmd = rename_cmd + L" --" + installer_util::switches::kSystemLevel;
if (InstallUtil::IsChromeFrameProcess()) {
@@ -441,6 +455,13 @@ bool DoPostInstallTasks(HKEY reg_root,
}
}
+ // If we're told that we're an MSI install, make sure to set the marker
+ // in the client state key so that future updates do the right thing.
+ if (InstallUtil::IsMSIProcess(is_system_install)) {
+ if (!InstallUtil::SetMSIMarker(is_system_install, true))
+ return false;
+ }
+
return true;
}
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 6b039ed..53d0918 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -722,7 +722,7 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
// MSI demands that custom actions always return 0 (ERROR_SUCCESS) or it will
// rollback the action. If we're uninstalling we want to avoid this, so always
// report success, squashing any more informative return codes.
- if (!(InstallUtil::IsMSIProcess() &&
+ if (!(InstallUtil::IsMSIProcess(system_install) &&
parsed_command_line.HasSwitch(installer_util::switches::kUninstall))) {
// Note that we allow the status installer_util::UNINSTALL_REQUIRES_REBOOT
// to pass through, since this is only returned on uninstall which is never
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index 3ce98d6..79ccdbe 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -339,14 +339,16 @@ installer_util::InstallStatus IsChromeActiveOrUserCancelled(
}
bool ShouldDeleteProfile(const CommandLine& cmd_line,
- installer_util::InstallStatus status) {
+ installer_util::InstallStatus status,
+ bool system_uninstall) {
bool should_delete = false;
// Chrome Frame uninstallations always want to delete the profile (we have no
// UI to prompt otherwise and the profile stores no useful data anyway)
// unless they are managed by MSI. MSI uninstalls will explicitly include
// the --delete-profile flag to distinguish them from MSI upgrades.
- if (InstallUtil::IsChromeFrameProcess() && !InstallUtil::IsMSIProcess()) {
+ if (InstallUtil::IsChromeFrameProcess() &&
+ !InstallUtil::IsMSIProcess(system_uninstall)) {
should_delete = true;
} else {
should_delete =
@@ -569,7 +571,7 @@ installer_util::InstallStatus installer_setup::UninstallChrome(
// Finally delete all the files from Chrome folder after moving setup.exe
// and the user's Local State to a temp location.
- bool delete_profile = ShouldDeleteProfile(cmd_line, status);
+ bool delete_profile = ShouldDeleteProfile(cmd_line, status, system_uninstall);
std::wstring local_state_path;
ret = installer_util::UNINSTALL_SUCCESSFUL;
diff --git a/chrome/installer/util/google_update_constants.cc b/chrome/installer/util/google_update_constants.cc
index 496c530..a904a74 100644
--- a/chrome/installer/util/google_update_constants.cc
+++ b/chrome/installer/util/google_update_constants.cc
@@ -21,6 +21,7 @@ const wchar_t kRegDidRunField[] = L"dr";
const wchar_t kRegLangField[] = L"lang";
const wchar_t kRegLastCheckedField[] = L"LastChecked";
const wchar_t kRegMetricsId[] = L"metricsid";
+const wchar_t kRegMSIField[] = L"msi";
const wchar_t kRegNameField[] = L"name";
const wchar_t kRegOldVersionField[] = L"opv";
const wchar_t kRegRenameCmdField[] = L"cmd";
diff --git a/chrome/installer/util/google_update_constants.h b/chrome/installer/util/google_update_constants.h
index 4479d66..79100a6 100644
--- a/chrome/installer/util/google_update_constants.h
+++ b/chrome/installer/util/google_update_constants.h
@@ -31,6 +31,7 @@ extern const wchar_t kRegDidRunField[];
extern const wchar_t kRegLangField[];
extern const wchar_t kRegLastCheckedField[];
extern const wchar_t kRegMetricsId[];
+extern const wchar_t kRegMSIField[];
extern const wchar_t kRegNameField[];
extern const wchar_t kRegOldVersionField[];
extern const wchar_t kRegRenameCmdField[];
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index a3f32d1..6d87869 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -136,14 +136,20 @@ bool InstallUtil::IsChromeFrameProcess() {
DCHECK(command_line)
<< "IsChromeFrameProcess() called before ComamandLine::Init()";
- // Also assume this to be a ChromeFrame process if we are running inside
- // the Chrome Frame DLL.
FilePath module_path;
PathService::Get(base::FILE_MODULE, &module_path);
std::wstring module_name(module_path.BaseName().value());
- return command_line->HasSwitch(installer_util::switches::kChromeFrame) ||
- module_name == installer_util::kChromeFrameDll;
+ scoped_ptr<DictionaryValue> prefs(installer_util::GetInstallPreferences(
+ *command_line));
+ DCHECK(prefs.get());
+ bool is_cf = false;
+ installer_util::GetDistroBooleanPreference(prefs.get(),
+ installer_util::master_preferences::kChromeFrame, &is_cf);
+
+ // Also assume this to be a ChromeFrame process if we are running inside
+ // the Chrome Frame DLL.
+ return is_cf || module_name == installer_util::kChromeFrameDll;
}
bool InstallUtil::IsChromeSxSProcess() {
@@ -164,18 +170,72 @@ bool InstallUtil::IsChromeSxSProcess() {
chrome_sxs_dir);
}
-bool InstallUtil::IsMSIProcess() {
+bool InstallUtil::IsMSIProcess(bool system_level) {
+ // Initialize the static msi flags.
+ static bool is_msi_ = false;
+ static bool msi_checked_ = false;
+
CommandLine* command_line = CommandLine::ForCurrentProcess();
CHECK(command_line);
- scoped_ptr<DictionaryValue> prefs(installer_util::GetInstallPreferences(
- *command_line));
- bool value = false;
- return (installer_util::GetDistroBooleanPreference(prefs.get(),
- installer_util::master_preferences::kMsi, &value) &&
- value);
+ if (!msi_checked_) {
+ msi_checked_ = true;
+
+ scoped_ptr<DictionaryValue> prefs(installer_util::GetInstallPreferences(
+ *command_line));
+ DCHECK(prefs.get());
+ bool is_msi = false;
+ installer_util::GetDistroBooleanPreference(prefs.get(),
+ installer_util::master_preferences::kMsi, &is_msi);
+
+ if (!is_msi) {
+ // We didn't find it in the preferences, try looking in the registry.
+ HKEY reg_root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ RegKey key;
+ DWORD msi_value;
+
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ DCHECK(dist);
+
+ bool success = false;
+ std::wstring reg_key(dist->GetStateKey());
+ if (key.Open(reg_root, reg_key.c_str(), KEY_READ | KEY_WRITE)) {
+ if (key.ReadValueDW(google_update::kRegMSIField, &msi_value)) {
+ is_msi = (msi_value == 1);
+ }
+ }
+ }
+
+ is_msi_ = is_msi;
+ }
+
+ return is_msi_;
+}
+
+bool InstallUtil::SetMSIMarker(bool system_level, bool set) {
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ DCHECK(dist);
+ std::wstring client_state_path(dist->GetStateKey());
+
+ bool success = false;
+ HKEY reg_root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ RegKey client_state_key;
+ if (client_state_key.Open(reg_root, client_state_path.c_str(),
+ KEY_READ | KEY_WRITE)) {
+ DWORD msi_value = set ? 1 : 0;
+ if (client_state_key.WriteValue(google_update::kRegMSIField, msi_value)) {
+ success = true;
+ } else {
+ LOG(ERROR) << "Could not write msi value to client state key.";
+ }
+ } else {
+ LOG(ERROR) << "Could not open client state key!";
+ }
+
+ return success;
}
+
bool InstallUtil::BuildDLLRegistrationList(const std::wstring& install_path,
const wchar_t** const dll_names,
int dll_names_count,
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h
index 8a2854a..f2ccb42 100644
--- a/chrome/installer/util/install_util.h
+++ b/chrome/installer/util/install_util.h
@@ -57,7 +57,8 @@ class InstallUtil {
// Returns true if this is a Chrome Frame installation (as indicated by the
// presence of --chrome-frame on the command line) or if this is running
- // inside of the Chrome Frame dll.
+ // inside of the Chrome Frame dll. Also returns true if a master.preferences
+ // file containing chrome_frame: true is specified on the command line.
static bool IsChromeFrameProcess();
// Returns true if this is running setup process for Chrome SxS (as
@@ -67,9 +68,19 @@ class InstallUtil {
static bool IsChromeSxSProcess();
// Returns true if this setup process is running as an install managed by an
- // MSI wrapper. This is indicated by the presence of --msi on the command line
- // or the presence of "msi": true in the master preferences file.
- static bool IsMSIProcess();
+ // MSI wrapper. There are three things that are checked:
+ // 1) the presence of --msi on the command line
+ // 2) the presence of "msi": true in the master preferences file
+ // 3) the presence of a DWORD value in the ClientState key called msi with
+ // value 1
+ // NOTE: This method is NOT thread safe.
+ static bool IsMSIProcess(bool system_level);
+
+
+ // Sets the boolean MSI marker for this installation if set is true or clears
+ // it otherwise. The MSI marker is stored in the registry under the
+ // ClientState key.
+ static bool SetMSIMarker(bool system_level, bool set);
// Adds all DLLs in install_path whose names are given by dll_names to a
// work item list containing registration or unregistration actions.
diff --git a/chrome/installer/util/master_preferences.cc b/chrome/installer/util/master_preferences.cc
index e78872e..053dc45 100644
--- a/chrome/installer/util/master_preferences.cc
+++ b/chrome/installer/util/master_preferences.cc
@@ -114,6 +114,10 @@ DictionaryValue* GetInstallPreferences(const CommandLine& cmd_line) {
if (!prefs)
prefs = new DictionaryValue();
+ if (cmd_line.HasSwitch(installer_util::switches::kChromeFrame))
+ installer_util::SetDistroBooleanPreference(
+ prefs, installer_util::master_preferences::kChromeFrame, true);
+
if (cmd_line.HasSwitch(installer_util::switches::kCreateAllShortcuts))
installer_util::SetDistroBooleanPreference(
prefs, installer_util::master_preferences::kCreateAllShortcuts, true);
diff --git a/chrome/installer/util/master_preferences_constants.cc b/chrome/installer/util/master_preferences_constants.cc
index 77c60d9..aa7c900 100644
--- a/chrome/installer/util/master_preferences_constants.cc
+++ b/chrome/installer/util/master_preferences_constants.cc
@@ -8,6 +8,7 @@ namespace installer_util {
namespace master_preferences {
const wchar_t kAltFirstRunBubble[] = L"oem_bubble";
const wchar_t kAltShortcutText[] = L"alternate_shortcut_text";
+ const wchar_t kChromeFrame[] = L"chrome_frame";
const wchar_t kChromeShortcutIconIndex[] = L"chrome_shortcut_icon_index";
const wchar_t kCreateAllShortcuts[] = L"create_all_shortcuts";
const wchar_t kDistroImportBookmarksPref[] = L"import_bookmarks";
diff --git a/chrome/installer/util/master_preferences_constants.h b/chrome/installer/util/master_preferences_constants.h
index e08d1e4..6c5843a 100644
--- a/chrome/installer/util/master_preferences_constants.h
+++ b/chrome/installer/util/master_preferences_constants.h
@@ -19,6 +19,8 @@ namespace master_preferences {
extern const wchar_t kAltShortcutText[];
// Boolean. Use alternate smaller first run info bubble.
extern const wchar_t kAltFirstRunBubble[];
+// Boolean. This is to be a Chrome Frame install.
+extern const wchar_t kChromeFrame[];
// Integer. Icon index from chrome.exe to use for shortcuts.
extern const wchar_t kChromeShortcutIconIndex[];
// Boolean. Create Desktop and QuickLaunch shortcuts. Cmd line override present.