summaryrefslogtreecommitdiffstats
path: root/chrome/installer/setup/install.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/installer/setup/install.cc')
-rw-r--r--chrome/installer/setup/install.cc694
1 files changed, 28 insertions, 666 deletions
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index dc545a7..0df4e69 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -18,6 +18,7 @@
#include "base/utf_string_conversions.h"
#include "base/win/registry.h"
#include "chrome/installer/setup/setup_constants.h"
+#include "chrome/installer/setup/install_worker.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/channel_info.h"
#include "chrome/installer/util/chrome_frame_distribution.h"
@@ -92,35 +93,6 @@ void AddInstallerCopyTasks(const FilePath& setup_path,
}
}
-void AppendUninstallCommandLineFlags(CommandLine* uninstall_cmd,
- const Product& product) {
- DCHECK(uninstall_cmd);
-
- uninstall_cmd->AppendSwitch(installer::switches::kUninstall);
-
- // Append the product-specific uninstall flags.
- product.distribution()->AppendUninstallCommandLineFlags(uninstall_cmd);
- if (product.IsMsi()) {
- uninstall_cmd->AppendSwitch(installer::switches::kMsi);
- // See comment in uninstall.cc where we check for the kDeleteProfile switch.
- if (product.is_chrome_frame()) {
- uninstall_cmd->AppendSwitch(installer::switches::kDeleteProfile);
- }
- }
- if (product.system_level())
- uninstall_cmd->AppendSwitch(installer::switches::kSystemLevel);
-
- // Propagate switches obtained from preferences as well.
- const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
- if (prefs.is_multi_install()) {
- uninstall_cmd->AppendSwitch(installer::switches::kMultiInstall);
- }
- bool value = false;
- if (prefs.GetBool(installer::master_preferences::kVerboseLogging,
- &value) && value)
- uninstall_cmd->AppendSwitch(installer::switches::kVerboseLogging);
-}
-
// Adds work items that make registry adjustments for Google Update. When a
// product is installed (including overinstall), Google Update will write the
// channel ("ap") value into either Chrome or Chrome Frame's ClientState key.
@@ -395,204 +367,6 @@ bool CreateOrUpdateChromeShortcuts(const FilePath& setup_path,
return ret;
}
-// Local helper to call AddRegisterComDllWorkItems for all DLLs in a set of
-// products managed by a given package.
-void AddRegisterComDllWorkItemsForPackage(const Package& package,
- const Version* old_version,
- const Version& new_version,
- WorkItemList* work_item_list) {
- // First collect the list of DLLs to be registered from each product.
- const Products& products = package.products();
- Products::const_iterator product_iter(products.begin());
- std::vector<FilePath> com_dll_list;
- for (; product_iter != products.end(); ++product_iter) {
- BrowserDistribution* dist = product_iter->get()->distribution();
- std::vector<FilePath> dist_dll_list(dist->GetComDllList());
- com_dll_list.insert(com_dll_list.end(), dist_dll_list.begin(),
- dist_dll_list.end());
- }
-
- // Then, if we got some, attempt to unregister the DLLs from the old
- // version directory and then re-register them in the new one.
- // Note that if we are migrating the install directory then we will not
- // successfully unregister the old DLLs.
- // TODO(robertshield): See whether we need to fix the migration case.
- // TODO(robertshield): If we ever remove a DLL from a product, this will
- // not unregister it on update. We should build the unregistration list from
- // saved state instead of assuming it is the same as the registration list.
- if (!com_dll_list.empty()) {
- if (old_version) {
- FilePath old_dll_path(
- package.path().Append(UTF8ToWide(old_version->GetString())));
-
- installer::AddRegisterComDllWorkItems(old_dll_path,
- com_dll_list,
- package.system_level(),
- false, // Unregister
- true, // May fail
- work_item_list);
- }
-
- FilePath dll_path(
- package.path().Append(UTF8ToWide(new_version.GetString())));
- installer::AddRegisterComDllWorkItems(dll_path,
- com_dll_list,
- package.system_level(),
- true, // Register
- false, // Must succeed.
- work_item_list);
- }
-}
-
-// After a successful copying of all the files, this function is called to
-// do a few post install tasks:
-// - Handle the case of in-use-update by updating "opv" (old version) 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 AppendPostInstallTasks(bool multi_install,
- const FilePath& setup_path,
- const FilePath& new_chrome_exe,
- const Version* current_version,
- const Version& new_version,
- const Package& package,
- WorkItemList* post_install_task_list) {
- DCHECK(post_install_task_list);
- HKEY root = package.system_level() ? HKEY_LOCAL_MACHINE :
- HKEY_CURRENT_USER;
- const Products& products = package.products();
-
-
- // Append work items that will only be executed if this was an update.
- // We update the 'opv' key with the current version that is active and 'cmd'
- // key with the rename command to run.
- {
- scoped_ptr<WorkItemList> in_use_update_work_items(
- WorkItem::CreateConditionalWorkItemList(
- new ConditionRunIfFileExists(new_chrome_exe)));
- in_use_update_work_items->set_log_message("InUseUpdateWorkItemList");
-
- FilePath installer_path(package.GetInstallerDirectory(new_version)
- .Append(setup_path.BaseName()));
-
- CommandLine rename(installer_path);
- rename.AppendSwitch(installer::switches::kRenameChromeExe);
- if (package.system_level())
- rename.AppendSwitch(installer::switches::kSystemLevel);
-
- if (InstallUtil::IsChromeSxSProcess())
- rename.AppendSwitch(installer::switches::kChromeSxS);
-
- if (multi_install)
- rename.AppendSwitch(installer::switches::kMultiInstall);
-
- std::wstring version_key;
- for (size_t i = 0; i < products.size(); ++i) {
- BrowserDistribution* dist = products[i]->distribution();
- version_key = dist->GetVersionKey();
-
- if (current_version != NULL) {
- in_use_update_work_items->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegOldVersionField,
- UTF8ToWide(current_version->GetString()), true);
- }
-
- // Adding this registry entry for all products is overkill.
- // However, as it stands, we don't have a way to know which distribution
- // will check the key and run the command, so we add it for all.
- // After the first run, the subsequent runs should just be noops.
- // (see Upgrade::SwapNewChromeExeIfPresent).
- in_use_update_work_items->AddSetRegValueWorkItem(
- root,
- version_key,
- google_update::kRegRenameCmdField,
- rename.command_line_string(),
- true);
- }
-
- if (multi_install) {
- PackageProperties* props = package.properties();
- if (props->ReceivesUpdates() && current_version != NULL) {
- in_use_update_work_items->AddSetRegValueWorkItem(
- root,
- props->GetVersionKey(),
- google_update::kRegOldVersionField,
- UTF8ToWide(current_version->GetString()),
- true);
- // TODO(tommi): We should move the rename command here. We also need to
- // update Upgrade::SwapNewChromeExeIfPresent.
- }
- }
-
- post_install_task_list->AddWorkItem(in_use_update_work_items.release());
- }
-
-
- // Append work items that will be executed if this was NOT an in-use update.
- {
- scoped_ptr<WorkItemList> regular_update_work_items(
- WorkItem::CreateConditionalWorkItemList(
- new Not(new ConditionRunIfFileExists(new_chrome_exe))));
- regular_update_work_items->set_log_message(
- "RegularUpdateWorkItemList");
-
- // Since this was not an in-use-update, delete 'opv' and 'cmd' keys.
- for (size_t i = 0; i < products.size(); ++i) {
- BrowserDistribution* dist = products[i]->distribution();
- std::wstring version_key(dist->GetVersionKey());
- regular_update_work_items->AddDeleteRegValueWorkItem(root, version_key,
- google_update::kRegOldVersionField,
- REG_SZ);
- regular_update_work_items->AddDeleteRegValueWorkItem(root, version_key,
- google_update::kRegRenameCmdField,
- REG_SZ);
- }
-
- post_install_task_list->AddWorkItem(regular_update_work_items.release());
- }
-
- AddRegisterComDllWorkItemsForPackage(package, current_version, new_version,
- post_install_task_list);
-
- for (size_t i = 0; i < products.size(); ++i) {
- const Product* product = products[i];
- // 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 (product->IsMsi()) {
- AddSetMsiMarkerWorkItem(*product, true, post_install_task_list);
-
- // We want MSI installs to take over the Add/Remove Programs shortcut.
- // Make a best-effort attempt to delete any shortcuts left over from
- // previous non-MSI installations for the same type of install (system or
- // per user).
- AddDeleteUninstallShortcutsForMSIWorkItems(*product,
- post_install_task_list);
- }
- }
-
- return true;
-}
-
-// This method tells if we are running on 64 bit platform so that we can copy
-// one extra exe. If the API call to determine 64 bit fails, we play it safe
-// and return true anyway so that the executable can be copied.
-bool Is64bit() {
- typedef BOOL (WINAPI *WOW_FUNC)(HANDLE, PBOOL);
- BOOL is64 = FALSE;
-
- HANDLE handle = GetCurrentProcess();
- HMODULE module = GetModuleHandle(L"kernel32.dll");
- WOW_FUNC p = reinterpret_cast<WOW_FUNC>(GetProcAddress(module,
- "IsWow64Process"));
- if ((p != NULL) && (!(p)(handle, &is64) || (is64 != FALSE))) {
- return true;
- }
-
- return false;
-}
void RegisterChromeOnMachine(const Product& product,
bool make_chrome_default) {
@@ -620,44 +394,6 @@ void RegisterChromeOnMachine(const Product& product,
}
}
-// Create Version key for a product (if not already present) and sets the new
-// product version as the last step.
-void AddVersionKeyWorkItems(HKEY root,
- const Product& product,
- const Version& new_version,
- WorkItemList* list) {
- // Create Version key for each distribution (if not already present) and set
- // the new product version as the last step.
- std::wstring version_key(product.distribution()->GetVersionKey());
- list->AddCreateRegKeyWorkItem(root, version_key);
-
- std::wstring product_name(product.distribution()->GetAppShortCutName());
- list->AddSetRegValueWorkItem(root, version_key, google_update::kRegNameField,
- product_name, true); // overwrite name also
- list->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegOopcrashesField,
- static_cast<DWORD>(1),
- false); // set during first install
- list->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegVersionField,
- UTF8ToWide(new_version.GetString()),
- true); // overwrite version
-}
-
-void AddProductSpecificWorkItems(bool install,
- const FilePath& setup_path,
- const Version& new_version,
- const Package& package,
- WorkItemList* list) {
- const Products& products = package.products();
- for (size_t i = 0; i < products.size(); ++i) {
- const Product& p = *products[i];
- if (p.is_chrome_frame()) {
- AddChromeFrameWorkItems(install, setup_path, new_version, p, list);
- }
- }
-}
-
// This function installs a new version of Chrome to the specified location.
//
// setup_path: Path to the executable (setup.exe) as it will be copied
@@ -669,7 +405,7 @@ void AddProductSpecificWorkItems(bool install,
// temp_dir: the path of working directory used during installation. This path
// does not need to exist.
// new_version: new Chrome version that needs to be installed
-// oldest_installed_version: returns the oldest active version (if any)
+// current_version: returns the current active version (if any)
//
// This function makes best effort to do installation in a transactional
// manner. If failed it tries to rollback all changes on the file system
@@ -691,119 +427,28 @@ installer::InstallStatus InstallNewVersion(
const Package& package) {
DCHECK(current_version);
- const Products& products = package.products();
- DCHECK(products.size());
-
- if (FindProduct(products, BrowserDistribution::CHROME_FRAME)) {
- // Make sure that we don't end up deleting installed files on next reboot.
- if (!RemoveFromMovesPendingReboot(package.path().value().c_str())) {
- LOG(ERROR) << "Error accessing pending moves value.";
- }
- }
-
current_version->reset(package.GetCurrentVersion());
-
scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
- // A temp directory that work items need and the actual install directory.
- install_list->AddCreateDirWorkItem(temp_dir);
- install_list->AddCreateDirWorkItem(package.path());
- // Delete any new_chrome.exe if present (we will end up creating a new one
- // if required) and then copy chrome.exe
+ AddInstallWorkItems(original_state,
+ installer_state,
+ multi_install,
+ setup_path,
+ archive_path,
+ src_path,
+ temp_dir,
+ new_version,
+ current_version,
+ package,
+ install_list.get());
+
FilePath new_chrome_exe(
package.path().Append(installer::kChromeNewExe));
- install_list->AddDeleteTreeWorkItem(new_chrome_exe);
- install_list->AddCopyTreeWorkItem(
- src_path.Append(installer::kChromeExe).value(),
- package.path().Append(installer::kChromeExe).value(),
- temp_dir.value(), WorkItem::NEW_NAME_IF_IN_USE, new_chrome_exe.value());
-
- // Extra executable for 64 bit systems.
- if (Is64bit()) {
- install_list->AddCopyTreeWorkItem(
- src_path.Append(installer::kWowHelperExe).value(),
- package.path().Append(installer::kWowHelperExe).value(),
- temp_dir.value(), WorkItem::ALWAYS);
- }
-
- // If it is system level install copy the version folder (since we want to
- // take the permissions of %ProgramFiles% folder) otherwise just move it.
- if (package.system_level()) {
- install_list->AddCopyTreeWorkItem(
- src_path.Append(UTF8ToWide(new_version.GetString())).value(),
- package.path().Append(UTF8ToWide(new_version.GetString())).value(),
- temp_dir.value(), WorkItem::ALWAYS);
- } else {
- install_list->AddMoveTreeWorkItem(
- src_path.Append(UTF8ToWide(new_version.GetString())).value(),
- package.path().Append(UTF8ToWide(new_version.GetString())).value(),
- temp_dir.value());
- }
-
- // Copy the default Dictionaries only if the folder doesn't exist already.
- install_list->AddCopyTreeWorkItem(
- src_path.Append(installer::kDictionaries).value(),
- package.path().Append(installer::kDictionaries).value(),
- temp_dir.value(), WorkItem::IF_NOT_PRESENT);
-
- // Delete any old_chrome.exe if present.
- install_list->AddDeleteTreeWorkItem(
- package.path().Append(installer::kChromeOldExe));
-
- // Copy installer in install directory and
- // add shortcut in Control Panel->Add/Remove Programs.
- AddInstallerCopyTasks(setup_path, archive_path, temp_dir, new_version,
- install_list.get(), package);
-
- HKEY root = package.system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
-
- for (size_t i = 0; i < products.size(); ++i) {
- const Product* product = products[i];
-
- AddUninstallShortcutWorkItems(setup_path, new_version, install_list.get(),
- *product);
-
- AddVersionKeyWorkItems(root, *product, new_version, install_list.get());
- }
-
- if (multi_install) {
- PackageProperties* props = package.properties();
- if (props->ReceivesUpdates()) {
- std::wstring version_key(props->GetVersionKey());
- install_list->AddCreateRegKeyWorkItem(root, version_key);
- install_list->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegVersionField,
- UTF8ToWide(new_version.GetString()),
- true); // overwrite version
- install_list->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegNameField,
- ASCIIToWide(installer::PackageProperties::kPackageProductName),
- true); // overwrite name also
- }
- }
-
- // Add any remaining work items that involve special settings for
- // each product.
- AddProductSpecificWorkItems(true, setup_path, new_version, package,
- install_list.get());
-
- AddGoogleUpdateWorkItems(original_state, installer_state, package,
- install_list.get());
-
- // Append the tasks that run after the installation.
- AppendPostInstallTasks(multi_install,
- setup_path,
- new_chrome_exe,
- current_version->get(),
- new_version,
- package,
- install_list.get());
-
if (!install_list->Do()) {
installer::InstallStatus result =
file_util::PathExists(new_chrome_exe) && current_version->get() &&
- new_version.Equals(**current_version) ?
+ new_version.Equals(*current_version->get()) ?
installer::SAME_VERSION_REPAIR_FAILED :
installer::INSTALL_FAILED;
LOG(ERROR) << "Install failed, rolling back... result: " << result;
@@ -853,11 +498,24 @@ installer::InstallStatus InstallOrUpdateProduct(
FilePath src_path(install_temp_path);
src_path = src_path.Append(kInstallSourceDir).Append(kInstallSourceChromeDir);
+ // TODO(robertshield): Removing the pending on-reboot moves should be done
+ // elsewhere.
+ const Products& products = install.products();
+ DCHECK(products.size());
+ if (FindProduct(products, BrowserDistribution::CHROME_FRAME)) {
+ // Make sure that we don't end up deleting installed files on next reboot.
+ if (!RemoveFromMovesPendingReboot(install.path().value().c_str())) {
+ LOG(ERROR) << "Error accessing pending moves value.";
+ }
+ }
+
scoped_ptr<Version> existing_version;
installer::InstallStatus result = InstallNewVersion(original_state,
installer_state, prefs.is_multi_install(), setup_path, archive_path,
src_path, install_temp_path, new_version, &existing_version, install);
+ // TODO(robertshield): Everything below this line should instead be captured
+ // by WorkItems.
if (!InstallUtil::GetInstallReturnCode(result)) {
if (result == installer::FIRST_INSTALL_SUCCESS && !prefs_path.empty())
CopyPreferenceFileForFirstRun(install, prefs_path);
@@ -910,300 +568,4 @@ installer::InstallStatus InstallOrUpdateProduct(
return result;
}
-void AddRegisterComDllWorkItems(const FilePath& dll_folder,
- const std::vector<FilePath>& dll_list,
- bool system_level,
- bool do_register,
- bool ignore_failures,
- WorkItemList* work_item_list) {
- DCHECK(work_item_list);
- if (dll_list.empty()) {
- VLOG(1) << "No COM DLLs to register";
- } else {
- std::vector<FilePath>::const_iterator dll_iter(dll_list.begin());
- for (; dll_iter != dll_list.end(); ++dll_iter) {
- FilePath dll_path = dll_folder.Append(*dll_iter);
- WorkItem* work_item = work_item_list->AddSelfRegWorkItem(
- dll_path.value(), do_register, !system_level);
- DCHECK(work_item);
- work_item->set_ignore_failure(ignore_failures);
- }
- }
-}
-
-void AddSetMsiMarkerWorkItem(const Product& product,
- bool set,
- WorkItemList* work_item_list) {
- DCHECK(work_item_list);
- BrowserDistribution* dist = product.distribution();
- HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE :
- HKEY_CURRENT_USER;
- DWORD msi_value = set ? 1 : 0;
- WorkItem* set_msi_work_item = work_item_list->AddSetRegValueWorkItem(
- reg_root, dist->GetStateKey(), google_update::kRegMSIField,
- msi_value, true);
- DCHECK(set_msi_work_item);
- set_msi_work_item->set_ignore_failure(true);
- set_msi_work_item->set_log_message("Could not write MSI marker!");
-}
-
-void AddUninstallShortcutWorkItems(const FilePath& setup_path,
- const Version& new_version,
- WorkItemList* install_list,
- const Product& product) {
- HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE :
- HKEY_CURRENT_USER;
- BrowserDistribution* browser_dist = product.distribution();
- DCHECK(browser_dist);
-
- // 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.
- FilePath install_path(product.package().path());
- FilePath installer_path(
- product.package().GetInstallerDirectory(new_version));
- installer_path = installer_path.Append(setup_path.BaseName());
-
- CommandLine uninstall_arguments(CommandLine::NO_PROGRAM);
- AppendUninstallCommandLineFlags(&uninstall_arguments, product);
-
- if (product.is_chrome()) {
- // The Chrome uninstallation command serves as the master uninstall
- // command for Chrome + all other products (i.e. Chrome Frame) that do
- // not have an uninstall entry in the Add/Remove Programs dialog.
- const Products& products = product.package().products();
- for (size_t i = 0; i < products.size(); ++i) {
- const Product& p = *products[i];
- if (!p.is_chrome() && !p.ShouldCreateUninstallEntry()) {
- p.distribution()->AppendUninstallCommandLineFlags(&uninstall_arguments);
- }
- }
- }
-
- std::wstring update_state_key(browser_dist->GetStateKey());
- install_list->AddCreateRegKeyWorkItem(reg_root, update_state_key);
- install_list->AddSetRegValueWorkItem(reg_root, update_state_key,
- installer::kUninstallStringField, installer_path.value(), true);
- install_list->AddSetRegValueWorkItem(reg_root, update_state_key,
- installer::kUninstallArgumentsField,
- uninstall_arguments.command_line_string(), true);
-
- if (product.ShouldCreateUninstallEntry()) {
- // We need to quote the command line for the Add/Remove Programs dialog.
- CommandLine quoted_uninstall_cmd(installer_path);
- DCHECK_EQ(quoted_uninstall_cmd.command_line_string()[0], '"');
- quoted_uninstall_cmd.AppendArguments(uninstall_arguments, false);
-
- std::wstring uninstall_reg = browser_dist->GetUninstallRegPath();
- install_list->AddCreateRegKeyWorkItem(reg_root, uninstall_reg);
- install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
- installer::kUninstallDisplayNameField,
- browser_dist->GetAppShortCutName(), true);
- install_list->AddSetRegValueWorkItem(reg_root,
- uninstall_reg, installer::kUninstallStringField,
- quoted_uninstall_cmd.command_line_string(), true);
- install_list->AddSetRegValueWorkItem(reg_root,
- uninstall_reg,
- L"InstallLocation",
- install_path.value(),
- true);
-
- // DisplayIcon, NoModify and NoRepair
- FilePath chrome_icon(install_path.Append(installer::kChromeExe));
- ShellUtil::GetChromeIcon(product.distribution(), chrome_icon.value());
- install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
- L"DisplayIcon", chrome_icon.value(),
- true);
- install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
- L"NoModify", static_cast<DWORD>(1),
- true);
- install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
- L"NoRepair", static_cast<DWORD>(1),
- true);
-
- install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
- L"Publisher",
- browser_dist->GetPublisherName(),
- true);
- install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
- L"Version",
- UTF8ToWide(new_version.GetString()),
- true);
- install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
- L"DisplayVersion",
- UTF8ToWide(new_version.GetString()),
- true);
- time_t rawtime = time(NULL);
- struct tm timeinfo = {0};
- localtime_s(&timeinfo, &rawtime);
- wchar_t buffer[9];
- if (wcsftime(buffer, 9, L"%Y%m%d", &timeinfo) == 8) {
- install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
- L"InstallDate",
- buffer, false);
- }
- }
-}
-
-void AddChromeFrameWorkItems(bool install,
- const FilePath& setup_path,
- const Version& new_version,
- const Product& product,
- WorkItemList* list) {
- DCHECK(product.is_chrome_frame());
- if (!product.package().multi_install()) {
- VLOG(1) << "Not adding GCF specific work items for single install.";
- return;
- }
-
- const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
-
- BrowserDistribution* cf = BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_FRAME, prefs);
- std::wstring version_key(cf->GetVersionKey());
-
- // TODO(tommi): This assumes we know exactly how ShouldCreateUninstallEntry
- // is implemented. Since there is logic in ChromeFrameDistribution for how
- // to determine when this is enabled, this is how we have to figure out if
- // this feature is enabled right now, but it's a hack and we need a cleaner
- // way to figure this out.
- // Note that we cannot just check the master preferences for
- // kChromeFrameReadyMode, since there are other things that need to be correct
- // in the environment in order to enable this feature.
- bool ready_mode = !product.distribution()->ShouldCreateUninstallEntry();
-
- HKEY root = product.package().system_level() ? HKEY_LOCAL_MACHINE :
- HKEY_CURRENT_USER;
- bool update_chrome_uninstall_command = false;
- if (ready_mode) {
- // If GCF is being installed in ready mode, we write an entry to the
- // multi-install state key. If the value already exists, we will not
- // overwrite it since the user might have opted out.
- list->AddCreateRegKeyWorkItem(root,
- product.package().properties()->GetStateKey());
- list->AddSetRegValueWorkItem(root,
- product.package().properties()->GetStateKey(),
- installer::kChromeFrameReadyModeField,
- static_cast<int64>(install ? 1 : 0), // The value we want to set.
- install ? false : true); // Overwrite existing value.
- if (install) {
- FilePath installer_path(product.package()
- .GetInstallerDirectory(new_version).Append(setup_path.BaseName()));
-
- CommandLine basic_cl(installer_path);
- basic_cl.AppendSwitch(installer::switches::kChromeFrame);
- basic_cl.AppendSwitch(installer::switches::kMultiInstall);
-
- if (product.package().system_level())
- basic_cl.AppendSwitch(installer::switches::kSystemLevel);
-
- if (InstallUtil::IsChromeSxSProcess())
- basic_cl.AppendSwitch(installer::switches::kChromeSxS);
-
- CommandLine temp_opt_out(basic_cl);
- temp_opt_out.AppendSwitch(
- installer::switches::kChromeFrameReadyModeTempOptOut);
-
- CommandLine end_temp_opt_out(basic_cl);
- end_temp_opt_out.AppendSwitch(
- installer::switches::kChromeFrameReadyModeEndTempOptOut);
-
- CommandLine opt_out(installer_path);
- AppendUninstallCommandLineFlags(&opt_out, product);
- // Force Uninstall silences the prompt to reboot to complete uninstall.
- opt_out.AppendSwitch(installer::switches::kForceUninstall);
-
- CommandLine opt_in(basic_cl);
- opt_in.AppendSwitch(
- installer::switches::kChromeFrameReadyModeOptIn);
-
- list->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegCFTempOptOutCmdField,
- temp_opt_out.command_line_string(), true);
- list->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegCFEndTempOptOutCmdField,
- end_temp_opt_out.command_line_string(),
- true);
- list->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegCFOptOutCmdField,
- opt_out.command_line_string(), true);
- list->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegCFOptInCmdField,
- opt_in.command_line_string(), true);
- } else {
- // If Chrome is not also being uninstalled, we need to update its command
- // line so that it doesn't include uninstalling Chrome Frame now.
- update_chrome_uninstall_command =
- (installer::FindProduct(product.package().products(),
- BrowserDistribution::CHROME_BROWSER) == NULL);
- }
- } else {
- // It doesn't matter here if we're installing or uninstalling Chrome Frame.
- // If ready mode isn't specified on the command line for installs, we need
- // to delete the ready mode flag from the registry if it exists - this
- // constitutes an opt-in for the user. If we're uninstalling CF and ready
- // mode isn't specified on the command line, that means that CF wasn't
- // installed with ready mode enabled (the --ready-mode switch should be set
- // in the registry) so deleting the value should have no effect.
- // In both cases (install/uninstall), we need to make sure that Chrome's
- // uninstallation command line does not include the --chrome-frame switch
- // so that uninstalling Chrome will no longer uninstall Chrome Frame.
-
- if (RegKey(root, product.package().properties()->GetStateKey().c_str(),
- KEY_QUERY_VALUE).Valid()) {
- list->AddDeleteRegValueWorkItem(root,
- product.package().properties()->GetStateKey(),
- installer::kChromeFrameReadyModeField, REG_QWORD);
- }
-
- const Product* chrome = installer::FindProduct(product.package().products(),
- BrowserDistribution::CHROME_BROWSER);
- if (chrome) {
- // Chrome is already a part of this installation run, so we can assume
- // that the uninstallation arguments will be updated correctly.
- } else {
- // Chrome is not a part of this installation run, so we have to explicitly
- // check if Chrome is installed, and if so, update its uninstallation
- // command lines.
- BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_BROWSER,
- MasterPreferences::ForCurrentProcess());
- update_chrome_uninstall_command =
- IsInstalledAsMulti(product.system_level(), dist);
- }
- }
-
- if (!ready_mode || !install) {
- list->AddDeleteRegValueWorkItem(root, version_key,
- google_update::kRegCFTempOptOutCmdField,
- REG_SZ);
- list->AddDeleteRegValueWorkItem(root, version_key,
- google_update::kRegCFEndTempOptOutCmdField,
- REG_SZ);
- list->AddDeleteRegValueWorkItem(root, version_key,
- google_update::kRegCFOptOutCmdField,
- REG_SZ);
- list->AddDeleteRegValueWorkItem(root, version_key,
- google_update::kRegCFOptInCmdField, REG_SZ);
- }
-
- if (update_chrome_uninstall_command) {
- // Chrome is not a part of this installation run, so we have to explicitly
- // check if Chrome is installed, and if so, update its uninstallation
- // command lines.
- BrowserDistribution* chrome_dist =
- BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_BROWSER, prefs);
- const Package& pack = product.package();
- scoped_refptr<Package> package(new Package(pack.multi_install(),
- pack.system_level(), pack.path(), pack.properties()));
- scoped_refptr<Product> chrome_product(new Product(chrome_dist, package));
- AddUninstallShortcutWorkItems(setup_path, new_version, list,
- *chrome_product.get());
- }
-}
-
} // namespace installer