diff options
Diffstat (limited to 'chrome/installer/setup/install.cc')
-rw-r--r-- | chrome/installer/setup/install.cc | 694 |
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 |