summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 19:54:02 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 19:54:02 +0000
commit36b6f4f462adc4ff57d65acef4c60939c2dfd8fe (patch)
tree38f40e2fa1773ff67ccb6b2283bf722fa54c9ab5 /chrome
parent15e7eba9c74140f4e976c0d152ba738c36f14bb5 (diff)
downloadchromium_src-36b6f4f462adc4ff57d65acef4c60939c2dfd8fe.zip
chromium_src-36b6f4f462adc4ff57d65acef4c60939c2dfd8fe.tar.gz
chromium_src-36b6f4f462adc4ff57d65acef4c60939c2dfd8fe.tar.bz2
Support for GCF ready-mode.
The installer can now be run in a way that installs both Chrome and Chrome Frame at the same time, into a shared directory. The command line to do this is: mini_installer.exe --multi-install --chrome --chrome-frame --ready-mode --system-level --verbose-logging This installs both products although only Chrome will have an entry in the add/remove programs dialog that serves as an uninstallation command for both products. Chrome Frame will be installed in ready-mode, which means that the user will have to opt-in or opt-out of using it. The installer will create a REG_DWORD value to indicate this mode, here: HKEY_LOCAL_MACHINE\SOFTWARE\Google\Update\ClientState\{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D} Value name: ChromeFrameReadyMode Value: 1 If the user opts-in to use GCF, setup will be run again to remove this value, update Chrome's uninstallation commands to only uninstall Chrome, and add an entry to the Add/Remove Programs dialog for GCF. To do this, the installer needs to be run with this switch: --multi-install --chrome-frame --system-level --ready-mode-opt-in --verbose-logging If the user opts-out, Chrome Frame will be uninstalled by running the installer with these arguments: --uninstall --chrome-frame --ready-mode --system-level --multi-install --verbose-logging In addition to uninstalling GCF, this updates Chrome's uninstallation commands accordingly and sets the ChromeFrameReadyMode value to 0 to avoid enabling ready mode again. Requirements that must currently be met in order to install Chrome and Chrome Frame into the same shared location: - Chrome Frame must not already be installed OR - Chrome Frame must be already installed as multi, into the shared location **** other changes **** The installer does no use the ap value for detecting other multi-install products anymore. Instead we inspect the uninstallation switches to see if --multi-install is present. Updated unit tests accordingly. When uninstalling Chrome Frame along with Chrome, the Chrome Frame uninstallation prompt is not shown. Added safeguards: If we attempt to install Chrome Frame multi over a single, install aborts and returns an error. If we attempt to install Chrome Frame single over a multi, install aborts and returns an error. TEST=See description above. BUG=61609 Review URL: http://codereview.chromium.org/5989007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70083 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/chrome_installer_util.gypi4
-rw-r--r--chrome/installer/setup/install.cc251
-rw-r--r--chrome/installer/setup/install.h15
-rw-r--r--chrome/installer/setup/setup_main.cc88
-rw-r--r--chrome/installer/setup/uninstall.cc91
-rw-r--r--chrome/installer/setup/uninstall.h5
-rw-r--r--chrome/installer/util/browser_distribution.cc4
-rw-r--r--chrome/installer/util/browser_distribution.h4
-rw-r--r--chrome/installer/util/chrome_frame_distribution.cc21
-rw-r--r--chrome/installer/util/chrome_frame_distribution.h5
-rw-r--r--chrome/installer/util/delete_after_reboot_helper.cc6
-rw-r--r--chrome/installer/util/helper.cc77
-rw-r--r--chrome/installer/util/helper.h16
-rw-r--r--chrome/installer/util/install_util.cc6
-rw-r--r--chrome/installer/util/master_preferences.cc2
-rw-r--r--chrome/installer/util/master_preferences_constants.cc1
-rw-r--r--chrome/installer/util/master_preferences_constants.h2
-rw-r--r--chrome/installer/util/package.cc17
-rw-r--r--chrome/installer/util/package_unittest.cc43
-rw-r--r--chrome/installer/util/product.cc31
-rw-r--r--chrome/installer/util/product.h12
-rw-r--r--chrome/installer/util/util_constants.cc10
-rw-r--r--chrome/installer/util/util_constants.h87
23 files changed, 596 insertions, 202 deletions
diff --git a/chrome/chrome_installer_util.gypi b/chrome/chrome_installer_util.gypi
index 946ce9e..3e8cedd 100644
--- a/chrome/chrome_installer_util.gypi
+++ b/chrome/chrome_installer_util.gypi
@@ -33,6 +33,8 @@
'installer/util/google_update_constants.h',
'installer/util/google_update_settings.cc',
'installer/util/google_update_settings.h',
+ 'installer/util/helper.cc',
+ 'installer/util/helper.h',
'installer/util/install_util.cc',
'installer/util/install_util.h',
'installer/util/l10n_string_util.cc',
@@ -93,8 +95,6 @@
'installer/util/delete_after_reboot_helper.h',
'installer/util/google_chrome_distribution.cc',
'installer/util/google_chrome_distribution.h',
- 'installer/util/helper.cc',
- 'installer/util/helper.h',
'installer/util/html_dialog.h',
'installer/util/html_dialog_impl.cc',
'installer/util/logging_installer.cc',
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index 880f3e1..61f0b2c 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -19,12 +19,14 @@
#include "base/win/registry.h"
#include "chrome/installer/setup/setup_constants.h"
#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/channel_info.h"
#include "chrome/installer/util/chrome_frame_distribution.h"
#include "chrome/installer/util/create_reg_key_work_item.h"
#include "chrome/installer/util/delete_after_reboot_helper.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/master_preferences_constants.h"
#include "chrome/installer/util/package.h"
#include "chrome/installer/util/package_properties.h"
@@ -38,13 +40,16 @@
#include "installer_util_strings.h" // NOLINT
#include "registered_dlls.h" // NOLINT
-namespace {
-
+using base::win::RegKey;
+using installer::ChannelInfo;
+using installer::MasterPreferences;
using installer::Products;
using installer::Product;
using installer::Package;
using installer::PackageProperties;
+namespace {
+
void AddChromeToMediaPlayerList() {
std::wstring reg_path(installer::kMediaPlayerRegPath);
// registry paths can also be appended like file system path
@@ -90,14 +95,18 @@ void AppendUninstallCommandLineFlags(CommandLine* uninstall_cmd,
// Append the product-specific uninstall flags.
product.distribution()->AppendUninstallCommandLineFlags(uninstall_cmd);
- if (product.IsMsi())
+ 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 installer::MasterPreferences& prefs =
- installer::MasterPreferences::ForCurrentProcess();
+ const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
if (prefs.is_multi_install()) {
uninstall_cmd->AppendSwitch(installer::switches::kMultiInstall);
}
@@ -133,6 +142,19 @@ void AddUninstallShortcutWorkItems(const FilePath& setup_path,
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,
@@ -141,8 +163,7 @@ void AddUninstallShortcutWorkItems(const FilePath& setup_path,
installer::kUninstallArgumentsField,
uninstall_arguments.command_line_string(), true);
- // MSI installations will manage their own uninstall shortcuts.
- if (!product.IsMsi()) {
+ 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], '"');
@@ -269,8 +290,7 @@ bool CreateOrUpdateChromeShortcuts(const FilePath& setup_path,
bool alt_shortcut) {
// TODO(tommi): Change this function to use WorkItemList.
#ifndef NDEBUG
- const installer::MasterPreferences& prefs =
- installer::MasterPreferences::ForCurrentProcess();
+ const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
DCHECK(prefs.install_chrome());
#endif
@@ -537,10 +557,10 @@ bool DoPostInstallTasks(bool multi_install,
return false;
}
- // 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.
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()) {
if (!product->SetMsiMarker(true))
return false;
@@ -576,8 +596,7 @@ bool Is64bit() {
void RegisterChromeOnMachine(const Product& product,
bool make_chrome_default) {
- DCHECK_EQ(product.distribution()->GetType(),
- BrowserDistribution::CHROME_BROWSER);
+ DCHECK(product.is_chrome());
// Try to add Chrome to Media Player shim inclusion list. We don't do any
// error checking here because this operation will fail if user doesn't
@@ -601,6 +620,43 @@ 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, 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
@@ -699,37 +755,19 @@ installer::InstallStatus InstallNewVersion(
HKEY root = package.system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
- std::wstring version_key;
for (size_t i = 0; i < products.size(); ++i) {
const Product* product = products[i];
AddUninstallShortcutWorkItems(setup_path, new_version, install_list.get(),
*product);
- // Create Version key for each distribution (if not already present) and set
- // the new product version as the last step.
- version_key = product->distribution()->GetVersionKey();
- install_list->AddCreateRegKeyWorkItem(root, version_key);
-
- std::wstring product_name(product->distribution()->GetAppShortCutName());
- install_list->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegNameField,
- product_name,
- true); // overwrite name also
- install_list->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegOopcrashesField,
- 1,
- false); // set during first install
- install_list->AddSetRegValueWorkItem(root, version_key,
- google_update::kRegVersionField,
- UTF8ToWide(new_version.GetString()),
- true); // overwrite version
+ AddVersionKeyWorkItems(root, *product, new_version, install_list.get());
}
if (multi_install) {
PackageProperties* props = package.properties();
if (props->ReceivesUpdates()) {
- version_key = props->GetVersionKey();
+ std::wstring version_key(props->GetVersionKey());
install_list->AddCreateRegKeyWorkItem(root, version_key);
install_list->AddSetRegValueWorkItem(root, version_key,
google_update::kRegVersionField,
@@ -742,6 +780,11 @@ installer::InstallStatus InstallNewVersion(
}
}
+ // Add any remaining work items that involve special settings for
+ // each product.
+ AddProductSpecificWorkItems(true, setup_path, new_version, package,
+ install_list.get());
+
if (!install_list->Do() ||
!DoPostInstallTasks(multi_install, setup_path, new_chrome_exe,
current_version->get(), new_version, package)) {
@@ -787,7 +830,7 @@ installer::InstallStatus InstallNewVersion(
namespace installer {
-installer::InstallStatus InstallOrUpdateChrome(
+installer::InstallStatus InstallOrUpdateProduct(
const FilePath& setup_path, const FilePath& archive_path,
const FilePath& install_temp_path, const FilePath& prefs_path,
const installer::MasterPreferences& prefs, const Version& new_version,
@@ -801,7 +844,7 @@ installer::InstallStatus InstallOrUpdateChrome(
&existing_version, install);
if (!InstallUtil::GetInstallReturnCode(result)) {
- if (result == installer::FIRST_INSTALL_SUCCESS)
+ if (result == installer::FIRST_INSTALL_SUCCESS && !prefs_path.empty())
CopyPreferenceFileForFirstRun(install, prefs_path);
bool do_not_create_shortcuts = false;
@@ -884,5 +927,143 @@ bool RegisterComDllList(const FilePath& dll_folder,
return success;
}
+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();
+ bool ready_mode = false;
+ prefs.GetBool(installer::master_preferences::kChromeFrameReadyMode,
+ &ready_mode);
+ 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,
+ install ? 1 : 0, // The value we want to set.
+ install ? false : true); // Overwrite existing value.
+ if (!install) {
+ // 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.
+
+ list->AddDeleteRegValueWorkItem(root,
+ product.package().properties()->GetStateKey(),
+ installer::kChromeFrameReadyModeField, false);
+
+ 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.
+ update_chrome_uninstall_command = true;
+ }
+ }
+
+ 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());
+ }
+}
+
+InstallStatus ChromeFrameReadyModeOptIn(const CommandLine& cmd_line) {
+ VLOG(1) << "Opting into Chrome Frame";
+ InstallStatus status = INSTALL_REPAIRED;
+
+ const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
+ bool system_install = false;
+ prefs.GetBool(master_preferences::kSystemLevel, &system_install);
+ BrowserDistribution* cf = BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_FRAME, prefs);
+ BrowserDistribution* chrome = BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BROWSER, prefs);
+
+#if defined(GOOGLE_CHROME_BUILD)
+ ChromePackageProperties package_properties;
+#else
+ ChromiumPackageProperties package_properties;
+#endif
+
+ // Remove ChromeFrameReadyMode, update Chrome's uninstallation commands to
+ // only uninstall Chrome, and add an entry to the Add/Remove Programs
+ // dialog for GCF.
+
+ FilePath path(GetChromeFrameInstallPath(true, system_install, cf));
+ if (path.empty()) {
+ LOG(ERROR) << "Conflicting installations";
+ status = NON_MULTI_INSTALLATION_EXISTS;
+ } else {
+ scoped_refptr<Package> package(new Package(prefs.is_multi_install(),
+ system_install, path, &package_properties));
+ scoped_refptr<Product> cf_product(new Product(cf, package));
+ DCHECK(cf_product->ShouldCreateUninstallEntry() || cf_product->IsMsi());
+ scoped_refptr<Product> chrome_product(new Product(chrome, package));
+
+ const Version* version = cf_product->GetInstalledVersion();
+ scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList());
+
+ // This creates the uninstallation entry for GCF.
+ AddUninstallShortcutWorkItems(cmd_line.GetProgram(), *version,
+ item_list.get(), *cf_product.get());
+ // This updates the Chrome uninstallation entries.
+ AddUninstallShortcutWorkItems(cmd_line.GetProgram(), *version,
+ item_list.get(), *chrome_product.get());
+
+ // Add a work item to delete the ChromeFrameReadyMode registry value.
+ HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ item_list->AddDeleteRegValueWorkItem(root, package_properties.GetStateKey(),
+ kChromeFrameReadyModeField, false);
+
+ if (!item_list->Do()) {
+ LOG(ERROR) << "Failed to opt into GCF";
+ item_list->Rollback();
+ status = READY_MODE_OPT_IN_FAILED;
+ }
+ }
+
+ return status;
+}
} // namespace installer
diff --git a/chrome/installer/setup/install.h b/chrome/installer/setup/install.h
index 5b5a4d9..b1ba24c 100644
--- a/chrome/installer/setup/install.h
+++ b/chrome/installer/setup/install.h
@@ -18,6 +18,7 @@
class DictionaryValue;
class FilePath;
+class WorkItemList;
namespace installer {
@@ -40,7 +41,7 @@ class Package;
//
// Note: since caller unpacks Chrome to install_temp_path\source, the caller
// is responsible for cleaning up install_temp_path.
-installer::InstallStatus InstallOrUpdateChrome(
+installer::InstallStatus InstallOrUpdateProduct(
const FilePath& setup_path, const FilePath& archive_path,
const FilePath& install_temp_path, const FilePath& prefs_path,
const installer::MasterPreferences& prefs, const Version& new_version,
@@ -60,6 +61,18 @@ bool RegisterComDllList(const FilePath& dll_folder,
bool do_register,
bool rollback_on_failure);
+// Called for either installation or uninstallation. This method updates the
+// registry according to Chrome Frame specific options for the current
+// installation. This includes handling of the ready-mode option.
+void AddChromeFrameWorkItems(bool install, const FilePath& setup_path,
+ const Version& new_version, const Product& product,
+ WorkItemList* list);
+
+// Removes the ChromeFrameReadyMode flag from the registry, updates Chrome's
+// uninstallation commands to only uninstall Chrome, and adds an entry to the
+// Add/Remove Programs list for GCF.
+InstallStatus ChromeFrameReadyModeOptIn(const CommandLine& cmd_line);
+
} // namespace installer
#endif // CHROME_INSTALLER_SETUP_INSTALL_H_
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 386c023..a3db00d 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -201,7 +201,7 @@ bool CheckPreInstallConditions(const Package& installation,
if (chrome_version.get()) {
LOG(ERROR) << "Already installed version " << chrome_version->GetString()
<< " conflicts with the current install mode.";
- if (!system_level && is_first_install) {
+ if (!system_level && is_first_install && product->is_chrome()) {
// This is user-level install and there is a system-level chrome
// installation. Instruct Omaha to launch the existing one. There
// should be no error dialog.
@@ -323,8 +323,7 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
higher_version_installed = true;
install_status = installer::HIGHER_VERSION_EXISTS;
- if (product->distribution()->GetType() !=
- BrowserDistribution::CHROME_BROWSER) {
+ if (product->is_chrome()) {
// TODO(robertshield): We should take the installer result text
// strings from the Product.
installation.WriteInstallerResult(install_status,
@@ -342,9 +341,9 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
FilePath archive_to_copy(temp_path.Append(installer::kChromeArchive));
FilePath prefs_source_path(cmd_line.GetSwitchValueNative(
installer::switches::kInstallerData));
- install_status = installer::InstallOrUpdateChrome(cmd_line.GetProgram(),
- archive_to_copy, temp_path, prefs_source_path, prefs,
- *installer_version, installation);
+ install_status = installer::InstallOrUpdateProduct(
+ cmd_line.GetProgram(), archive_to_copy, temp_path,
+ prefs_source_path, prefs, *installer_version, installation);
int install_msg_base = IDS_INSTALL_FAILED_BASE;
std::wstring chrome_exe;
@@ -456,10 +455,8 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
return install_status;
}
-installer::InstallStatus UninstallChrome(const CommandLine& cmd_line,
- const Product& product) {
- VLOG(1) << "Uninstalling Chome";
-
+installer::InstallStatus UninstallProduct(const CommandLine& cmd_line,
+ const Product& product) {
bool force = cmd_line.HasSwitch(installer::switches::kForceUninstall);
if (product.IsInstalled()) {
VLOG(1) << "version on the system: "
@@ -474,8 +471,8 @@ installer::InstallStatus UninstallChrome(const CommandLine& cmd_line,
bool remove_all = !cmd_line.HasSwitch(
installer::switches::kDoNotRemoveSharedItems);
- return installer::UninstallChrome(cmd_line.GetProgram(), product, remove_all,
- force, cmd_line);
+ return installer::UninstallProduct(cmd_line.GetProgram(), product, remove_all,
+ force, cmd_line);
}
installer::InstallStatus ShowEULADialog(const std::wstring& inner_frame) {
@@ -513,6 +510,9 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
int& exit_code,
const ProductPackageMapping& installs) {
DCHECK(installs.products().size());
+ bool handled = true;
+ // TODO(tommi): Split these checks up into functions and use a data driven
+ // map of switch->function.
if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) {
installer::InstallStatus status = installer::SETUP_PATCH_FAILED;
// If --update-setup-exe command line option is given, we apply the given
@@ -546,7 +546,6 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
IDS_SETUP_PATCH_FAILED_BASE, NULL);
}
file_util::Delete(temp_path, true);
- return true;
} else if (cmd_line.HasSwitch(installer::switches::kShowEula)) {
// Check if we need to show the EULA. If it is passed as a command line
// then the dialog is shown and regardless of the outcome setup exits here.
@@ -555,7 +554,6 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
exit_code = ShowEULADialog(inner_frame);
if (installer::EULA_REJECTED != exit_code)
GoogleUpdateSettings::SetEULAConsent(*installs.packages()[0].get(), true);
- return true;
} else if (cmd_line.HasSwitch(
installer::switches::kRegisterChromeBrowser)) {
const Product* chrome_install =
@@ -581,7 +579,6 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
LOG(ERROR) << "Can't register browser - Chrome distribution not found";
exit_code = installer::UNKNOWN_STATUS;
}
- return true;
} else if (cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) {
// If --rename-chrome-exe is specified, we want to rename the executables
// and exit.
@@ -589,7 +586,6 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
DCHECK_EQ(1U, packages.size());
for (size_t i = 0; i < packages.size(); ++i)
exit_code = RenameChromeExecutables(*packages[i].get());
- return true;
} else if (cmd_line.HasSwitch(
installer::switches::kRemoveChromeRegistration)) {
// This is almost reverse of --register-chrome-browser option above.
@@ -611,7 +607,6 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
HKEY_LOCAL_MACHINE, suffix, tmp);
}
exit_code = tmp;
- return true;
} else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) {
// Launch the inactive user toast experiment.
int flavor = -1;
@@ -628,7 +623,6 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
browser_dist->InactiveUserToastExperiment(flavor, *product);
}
}
- return true;
} else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) {
const Products& products = installs.products();
for (size_t i = 0; i < products.size(); ++i) {
@@ -641,9 +635,15 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
browser_dist->LaunchUserExperiment(installer::REENTRY_SYS_UPDATE,
*installed_version, *product, true);
}
- return true;
+ } else if (cmd_line.HasSwitch(
+ installer::switches::kChromeFrameReadyModeOptIn)) {
+ exit_code = InstallUtil::GetInstallReturnCode(
+ installer::ChromeFrameReadyModeOptIn(cmd_line));
+ } else {
+ handled = false;
}
- return false;
+
+ return handled;
}
bool ShowRebootDialog() {
@@ -700,18 +700,22 @@ class AutoCom {
bool initialized_;
};
-void PopulateInstallations(const MasterPreferences& prefs,
+bool PopulateInstallations(const MasterPreferences& prefs,
ProductPackageMapping* installations) {
DCHECK(installations);
+ bool success = true;
if (prefs.install_chrome()) {
VLOG(1) << "Install distribution: Chrome";
- installations->AddDistribution(BrowserDistribution::CHROME_BROWSER, prefs);
+ success = installations->AddDistribution(
+ BrowserDistribution::CHROME_BROWSER, prefs);
}
- if (prefs.install_chrome_frame()) {
+ if (success && prefs.install_chrome_frame()) {
VLOG(1) << "Install distribution: Chrome Frame";
- installations->AddDistribution(BrowserDistribution::CHROME_FRAME, prefs);
+ success = installations->AddDistribution(
+ BrowserDistribution::CHROME_FRAME, prefs);
}
+ return success;
}
// Returns the Custom information for the client identified by the exe path
@@ -790,8 +794,7 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
base::AtExitManager exit_manager;
CommandLine::Init(0, NULL);
- const MasterPreferences& prefs =
- installer::MasterPreferences::ForCurrentProcess();
+ const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
installer::InitInstallerLogging(prefs);
const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
@@ -806,7 +809,18 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
InitializeCrashReporting(system_install));
ProductPackageMapping installations(prefs.is_multi_install(), system_install);
- PopulateInstallations(prefs, &installations);
+ if (!PopulateInstallations(prefs, &installations)) {
+ // Currently this can only fail if one of the installations is a multi and
+ // a pre-existing single installation exists or vice versa.
+ installer::InstallStatus status;
+ if (prefs.is_multi_install()) {
+ status = installer::NON_MULTI_INSTALLATION_EXISTS;
+ } else {
+ status = installer::MULTI_INSTALLATION_EXISTS;
+ }
+ LOG(ERROR) << "Failed to populate installations: " << status;
+ return status;
+ }
// Check to make sure current system is WinXP or later. If not, log
// error message and get out.
@@ -869,12 +883,8 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
// If --uninstall option is given, uninstall chrome
if (is_uninstall) {
- DCHECK_EQ(1U, installations.products().size()) <<
- "We currently really only support uninstalling one distribution "
- "at a time";
for (size_t i = 0; i < installations.products().size(); ++i) {
- install_status = UninstallChrome(cmd_line,
- *installations.products()[i]);
+ install_status = UninstallProduct(cmd_line, *installations.products()[i]);
}
} else {
// If --uninstall option is not specified, we assume it is install case.
@@ -893,11 +903,15 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
if (install_status == installer::UNINSTALL_REQUIRES_REBOOT) {
ShowRebootDialog();
} else if (is_uninstall) {
- ::MessageBoxW(NULL,
- installer::GetLocalizedString(
- IDS_UNINSTALL_COMPLETE_BASE).c_str(),
- cf_install->distribution()->GetApplicationName().c_str(),
- MB_OK);
+ // Only show the message box if Chrome Frame was the only product being
+ // uninstalled.
+ if (installations.products().size() == 1U) {
+ ::MessageBoxW(NULL,
+ installer::GetLocalizedString(
+ IDS_UNINSTALL_COMPLETE_BASE).c_str(),
+ cf_install->distribution()->GetApplicationName().c_str(),
+ MB_OK);
+ }
}
}
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index b5b1986..1a623d6 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -20,11 +20,11 @@
#include "chrome/installer/setup/install.h"
#include "chrome/installer/setup/setup_constants.h"
#include "chrome/installer/util/browser_distribution.h"
-#include "chrome/installer/util/channel_info.h"
#include "chrome/installer/util/delete_after_reboot_helper.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/logging_installer.h"
+#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/shell_util.h"
#include "chrome/installer/util/util_constants.h"
@@ -32,7 +32,6 @@
#include "registered_dlls.h" // NOLINT
using base::win::RegKey;
-using installer::ChannelInfo;
using installer::InstallStatus;
namespace installer {
@@ -135,8 +134,7 @@ bool CurrentUserHasDefaultBrowser(const Product& product) {
// to remove the alternate desktop shortcut. Only one of them should be
// present in a given install but at this point we don't know which one.
void DeleteChromeShortcuts(const Product& product) {
- if (product.distribution()->GetType() !=
- BrowserDistribution::CHROME_BROWSER) {
+ if (!product.is_chrome()) {
VLOG(1) << __FUNCTION__ " called for non-CHROME distribution";
return;
}
@@ -251,8 +249,7 @@ DeleteResult DeleteLocalState(const Product& product) {
if (!file_util::Delete(user_local_state, true)) {
LOG(ERROR) << "Failed to delete user profile dir: "
<< user_local_state.value();
- if (product.distribution()->GetType() ==
- BrowserDistribution::CHROME_FRAME) {
+ if (product.is_chrome_frame()) {
ScheduleDirectoryForDeletion(user_local_state.value().c_str());
result = DELETE_REQUIRES_REBOOT;
} else {
@@ -279,7 +276,9 @@ bool MoveSetupOutOfInstallFolder(const Package& package,
if (!file_util::CreateTemporaryFile(&temp_file)) {
LOG(ERROR) << "Failed to create temporary file for setup.exe.";
} else {
+ VLOG(1) << "Attempting to move setup to: " << temp_file.value();
ret = file_util::Move(setup_exe, temp_file);
+ LOG_IF(ERROR, !ret) << "Failed to move setup to " << temp_file.value();
}
return ret;
}
@@ -371,8 +370,7 @@ bool ShouldDeleteProfile(const CommandLine& cmd_line, InstallStatus status,
// 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 (product.distribution()->GetType() !=
- BrowserDistribution::CHROME_BROWSER && !product.IsMsi()) {
+ if (!product.is_chrome() && !product.IsMsi()) {
should_delete = true;
} else {
should_delete =
@@ -478,11 +476,23 @@ const wchar_t kChromeExtProgId[] = L"ChromiumExt";
}
}
-InstallStatus UninstallChrome(const FilePath& setup_path,
- const Product& product,
- bool remove_all,
- bool force_uninstall,
- const CommandLine& cmd_line) {
+bool ProcessChromeFrameWorkItems(const FilePath& setup_path,
+ const Product& product) {
+ if (!product.is_chrome_frame())
+ return false;
+
+ const Version* version = product.GetInstalledVersion();
+ scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList());
+ AddChromeFrameWorkItems(false, setup_path, *version, product,
+ item_list.get());
+ return item_list->Do();
+}
+
+InstallStatus UninstallProduct(const FilePath& setup_path,
+ const Product& product,
+ bool remove_all,
+ bool force_uninstall,
+ const CommandLine& cmd_line) {
InstallStatus status = installer::UNINSTALL_CONFIRMED;
std::wstring suffix;
if (!ShellUtil::GetUserSpecificDefaultBrowserSuffix(product.distribution(),
@@ -490,21 +500,9 @@ InstallStatus UninstallChrome(const FilePath& setup_path,
suffix = L"";
BrowserDistribution* browser_dist = product.distribution();
- bool is_chrome = (browser_dist->GetType() ==
- BrowserDistribution::CHROME_BROWSER);
-
- VLOG(1) << "UninstallChrome: " << browser_dist->GetApplicationName();
-
- // Stash away information about the channel which the product is currently
- // installed on. We'll need this later to determine if we should delete
- // the binaries or not.
- ChannelInfo channel_info;
- {
- HKEY root_key = product.system_level() ? HKEY_LOCAL_MACHINE :
- HKEY_CURRENT_USER;
- RegKey key(root_key, browser_dist->GetStateKey().c_str(), KEY_READ);
- channel_info.Initialize(key);
- }
+ bool is_chrome = product.is_chrome();
+
+ VLOG(1) << "UninstallProduct: " << browser_dist->GetApplicationName();
if (force_uninstall) {
// Since --force-uninstall command line option is used, we are going to
@@ -543,9 +541,6 @@ InstallStatus UninstallChrome(const FilePath& setup_path,
}
}
- // Get the version of installed Chrome (if any)
- const Version* installed_version = product.GetInstalledVersion();
-
// Chrome is not in use so lets uninstall Chrome by deleting various files
// and registry entries. Here we will just make best effort and keep going
// in case of errors.
@@ -576,6 +571,9 @@ InstallStatus UninstallChrome(const FilePath& setup_path,
InstallStatus ret = installer::UNKNOWN_STATUS;
DeleteChromeRegistrationKeys(product.distribution(), reg_root, suffix, ret);
+ if (!is_chrome)
+ ProcessChromeFrameWorkItems(setup_path, product);
+
// For user level install also we end up creating some keys in HKLM if user
// sets Chrome as default browser. So delete those as well (needs admin).
if (remove_all && !product.system_level() &&
@@ -584,6 +582,9 @@ InstallStatus UninstallChrome(const FilePath& setup_path,
suffix, ret);
}
+ // Get the version of the installed product (if any)
+ const Version* installed_version = product.GetInstalledVersion();
+
// Delete shared registry keys as well (these require admin rights) if
// remove_all option is specified.
if (remove_all) {
@@ -610,7 +611,7 @@ InstallStatus UninstallChrome(const FilePath& setup_path,
}
// Close any Chrome Frame helper processes that may be running.
- if (product.distribution()->GetType() == BrowserDistribution::CHROME_FRAME) {
+ if (product.is_chrome_frame()) {
VLOG(1) << "Closing the Chrome Frame helper process";
CloseChromeFrameHelperProcess();
}
@@ -623,33 +624,37 @@ InstallStatus UninstallChrome(const FilePath& setup_path,
bool delete_profile = ShouldDeleteProfile(cmd_line, status, product);
ret = installer::UNINSTALL_SUCCESSFUL;
- // In order to be able to remove the folder in which we're running, we
- // need to move setup.exe out of the install folder.
- // TODO(tommi): What if the temp folder is on a different volume?
- MoveSetupOutOfInstallFolder(product.package(), setup_path,
- *installed_version);
-
- FilePath backup_state_file(BackupLocalStateFile(
- GetLocalStateFolder(product)));
-
// When deleting files, we must make sure that we're either a "single"
// (aka non-multi) installation or, in the case of multi, that no other
// "multi" products share the binaries we are about to delete.
bool can_delete_files;
- if (channel_info.IsMultiInstall()) {
+ if (product.package().multi_install()) {
can_delete_files =
(product.package().GetMultiInstallDependencyCount() == 0);
LOG(INFO) << (can_delete_files ? "Shared binaries will be deleted." :
"Shared binaries still in use.");
+ PackageProperties* props = product.package().properties();
+ if (can_delete_files && props->ReceivesUpdates()) {
+ InstallUtil::DeleteRegistryKey(key, props->GetVersionKey());
+ }
} else {
can_delete_files = true;
}
+ FilePath backup_state_file(BackupLocalStateFile(
+ GetLocalStateFolder(product)));
+
DeleteResult delete_result = DELETE_SUCCEEDED;
- if (can_delete_files)
+ if (can_delete_files) {
+ // In order to be able to remove the folder in which we're running, we
+ // need to move setup.exe out of the install folder.
+ // TODO(tommi): What if the temp folder is on a different volume?
+ MoveSetupOutOfInstallFolder(product.package(), setup_path,
+ *installed_version);
delete_result = DeleteFilesAndFolders(product.package(),
*installed_version);
+ }
if (delete_profile)
DeleteLocalState(product);
diff --git a/chrome/installer/setup/uninstall.h b/chrome/installer/setup/uninstall.h
index 2ec7775..274f55e 100644
--- a/chrome/installer/setup/uninstall.h
+++ b/chrome/installer/setup/uninstall.h
@@ -30,7 +30,8 @@ bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root,
// uninstalls/reinstalls to update.
void RemoveLegacyRegistryKeys(BrowserDistribution* dist);
-// This function uninstalls Chrome.
+// This function uninstalls a product. Hence we came up with this awesome
+// name for it.
//
// setup_path: Path to the executable (setup.exe) as it will be copied
// to temp folder before deleting Chrome folder.
@@ -40,7 +41,7 @@ void RemoveLegacyRegistryKeys(BrowserDistribution* dist);
// any checks for Chrome running.
// cmd_line: CommandLine that contains information about the command that
// was used to launch current uninstaller.
-installer::InstallStatus UninstallChrome(
+installer::InstallStatus UninstallProduct(
const FilePath& setup_path, const Product& dist, bool remove_all,
bool force_uninstall, const CommandLine& cmd_line);
diff --git a/chrome/installer/util/browser_distribution.cc b/chrome/installer/util/browser_distribution.cc
index 3ac4b1c..d684c97 100644
--- a/chrome/installer/util/browser_distribution.cc
+++ b/chrome/installer/util/browser_distribution.cc
@@ -232,3 +232,7 @@ void BrowserDistribution::AppendUninstallCommandLineFlags(
DCHECK(cmd_line);
cmd_line->AppendSwitch(installer::switches::kChrome);
}
+
+bool BrowserDistribution::ShouldCreateUninstallEntry() {
+ return true;
+}
diff --git a/chrome/installer/util/browser_distribution.h b/chrome/installer/util/browser_distribution.h
index 5175656..a967116 100644
--- a/chrome/installer/util/browser_distribution.h
+++ b/chrome/installer/util/browser_distribution.h
@@ -124,6 +124,10 @@ class BrowserDistribution {
// for this distribution will require.
virtual void AppendUninstallCommandLineFlags(CommandLine* cmd_line);
+ // Returns true if install should create an uninstallation entry in the
+ // Add/Remove Programs dialog for this distribution.
+ virtual bool ShouldCreateUninstallEntry();
+
protected:
explicit BrowserDistribution(const installer::MasterPreferences& prefs);
diff --git a/chrome/installer/util/chrome_frame_distribution.cc b/chrome/installer/util/chrome_frame_distribution.cc
index 0798366..c02e643 100644
--- a/chrome/installer/util/chrome_frame_distribution.cc
+++ b/chrome/installer/util/chrome_frame_distribution.cc
@@ -17,6 +17,7 @@
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/master_preferences.h"
+#include "chrome/installer/util/master_preferences_constants.h"
#include "installer_util_strings.h" // NOLINT
@@ -26,9 +27,11 @@ const wchar_t kChromeFrameGuid[] = L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}";
ChromeFrameDistribution::ChromeFrameDistribution(
const installer::MasterPreferences& prefs)
- : BrowserDistribution(prefs) {
+ : BrowserDistribution(prefs), ceee_(prefs.install_ceee()),
+ ready_mode_(false) {
type_ = BrowserDistribution::CHROME_FRAME;
- ceee_ = prefs.install_ceee();
+ prefs.GetBool(installer::master_preferences::kChromeFrameReadyMode,
+ &ready_mode_);
}
std::wstring ChromeFrameDistribution::GetAppGuid() {
@@ -137,9 +140,17 @@ std::vector<FilePath> ChromeFrameDistribution::GetComDllList() {
void ChromeFrameDistribution::AppendUninstallCommandLineFlags(
CommandLine* cmd_line) {
DCHECK(cmd_line);
- cmd_line->AppendSwitch(installer::switches::kDeleteProfile);
cmd_line->AppendSwitch(installer::switches::kChromeFrame);
- if (ceee_) {
+
+ if (ceee_)
cmd_line->AppendSwitch(installer::switches::kCeee);
- }
+
+ if (ready_mode_)
+ cmd_line->AppendSwitch(installer::switches::kChromeFrameReadyMode);
+}
+
+bool ChromeFrameDistribution::ShouldCreateUninstallEntry() {
+ // If Chrome Frame is being installed in ready mode, then we will not
+ // add an entry to the add/remove dialog.
+ return !ready_mode_;
}
diff --git a/chrome/installer/util/chrome_frame_distribution.h b/chrome/installer/util/chrome_frame_distribution.h
index 6bf7e0f..94df4bd 100644
--- a/chrome/installer/util/chrome_frame_distribution.h
+++ b/chrome/installer/util/chrome_frame_distribution.h
@@ -62,6 +62,8 @@ class ChromeFrameDistribution : public BrowserDistribution {
virtual void AppendUninstallCommandLineFlags(CommandLine* cmd_line);
+ virtual bool ShouldCreateUninstallEntry();
+
protected:
friend class BrowserDistribution;
@@ -72,6 +74,9 @@ class ChromeFrameDistribution : public BrowserDistribution {
// Determines whether this Chrome Frame distribution is being used to work
// with CEEE bits as well.
bool ceee_;
+
+ // True when Chrome Frame is installed in ready mode (users have to opt in).
+ bool ready_mode_;
};
#endif // CHROME_INSTALLER_UTIL_CHROME_FRAME_DISTRIBUTION_H_
diff --git a/chrome/installer/util/delete_after_reboot_helper.cc b/chrome/installer/util/delete_after_reboot_helper.cc
index 1c44676..a678c73 100644
--- a/chrome/installer/util/delete_after_reboot_helper.cc
+++ b/chrome/installer/util/delete_after_reboot_helper.cc
@@ -243,11 +243,13 @@ std::wstring GetShortPathName(const wchar_t* path) {
std::wstring short_path;
DWORD length = GetShortPathName(path, WriteInto(&short_path, MAX_PATH),
MAX_PATH);
- DLOG_IF(WARNING, length == 0) << __FUNCTION__ << " gle=" << GetLastError();
+ DWORD last_error = ::GetLastError();
+ DLOG_IF(WARNING, length == 0 && last_error != ERROR_PATH_NOT_FOUND)
+ << __FUNCTION__ << " gle=" << last_error;
if (length == 0) {
// GetShortPathName fails if the path is no longer present. Instead of
// returning an empty string, just return the original string. This will
- // serve for our purposes.
+ // serve our purposes.
return path;
}
diff --git a/chrome/installer/util/helper.cc b/chrome/installer/util/helper.cc
index d0151fd..c1b9d42 100644
--- a/chrome/installer/util/helper.cc
+++ b/chrome/installer/util/helper.cc
@@ -4,9 +4,16 @@
#include "chrome/installer/util/helper.h"
+#include "base/command_line.h"
#include "base/file_path.h"
+#include "base/logging.h"
#include "base/path_service.h"
+#include "base/win/registry.h"
#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/master_preferences.h"
+
+using base::win::RegKey;
namespace {
@@ -30,13 +37,73 @@ FilePath GetChromeInstallBasePath(bool system,
} // namespace
-FilePath installer::GetChromeInstallPath(bool system_install,
- BrowserDistribution* dist) {
+namespace installer {
+
+bool IsInstalledAsMulti(bool system_install, BrowserDistribution* dist) {
+ bool installed_as_multi = false;
+ HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ RegKey key(root, dist->GetStateKey().c_str(), KEY_READ);
+ if (key.Valid()) {
+ std::wstring args;
+ key.ReadValue(installer::kUninstallArgumentsField, &args);
+ if (!args.empty()) {
+ args.insert(0, L"fake.exe ");
+ CommandLine cmd(CommandLine::FromString(args));
+ installed_as_multi = cmd.HasSwitch(installer::switches::kMultiInstall);
+ }
+ }
+ return installed_as_multi;
+}
+
+FilePath GetChromeInstallPath(bool system_install, BrowserDistribution* dist) {
return GetChromeInstallBasePath(system_install, dist,
installer::kInstallBinaryDir);
}
-FilePath installer::GetChromeUserDataPath(BrowserDistribution* dist) {
- return GetChromeInstallBasePath(false, dist,
- installer::kInstallUserDataDir);
+FilePath GetChromeUserDataPath(BrowserDistribution* dist) {
+ return GetChromeInstallBasePath(false, dist, kInstallUserDataDir);
}
+
+FilePath GetChromeFrameInstallPath(bool multi_install, bool system_install,
+ BrowserDistribution* dist) {
+ DCHECK_EQ(BrowserDistribution::CHROME_FRAME, dist->GetType());
+
+ scoped_ptr<Version> installed_version(
+ InstallUtil::GetChromeVersion(dist, system_install));
+
+ if (!multi_install) {
+ // Check if Chrome Frame is installed as multi. If it is, return an empty
+ // path and log an error.
+ if (installed_version.get() && IsInstalledAsMulti(system_install, dist)) {
+ LOG(ERROR) << "Cannot install Chrome Frame in single mode as a multi mode"
+ " installation already exists.";
+ return FilePath();
+ }
+ VLOG(1) << "Chrome Frame will be installed as 'single'";
+ return GetChromeInstallPath(system_install, dist);
+ }
+
+ // TODO(tommi): If Chrome Frame is installed as single and the installed
+ // channel is older than the one we're installing, we should migrate
+ // CF to Chrome's install folder and change its channel.
+
+ // Multi install. Check if Chrome Frame is already installed.
+ // If CF is installed as single (i.e. not multi), we will return an empty
+ // path (for now). Otherwise, if CF is not installed or if it is installed
+ // as multi, we will return Chrome's install folder.
+ if (installed_version.get() && !IsInstalledAsMulti(system_install, dist)) {
+ LOG(ERROR) << "Cannot install Chrome Frame in multi mode as a single mode"
+ " installation already exists.";
+ return FilePath();
+ }
+
+ // Return Chrome's installation folder.
+ VLOG(1) << "Chrome Frame will be installed as 'multi'";
+ const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
+ BrowserDistribution* chrome =
+ BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BROWSER, prefs);
+ return GetChromeInstallPath(system_install, chrome);
+}
+
+} // namespace installer.
diff --git a/chrome/installer/util/helper.h b/chrome/installer/util/helper.h
index 07bc893..3845806 100644
--- a/chrome/installer/util/helper.h
+++ b/chrome/installer/util/helper.h
@@ -13,6 +13,9 @@ class FilePath;
namespace installer {
+// Checks if a distribution is currently installed as part of a multi-install.
+bool IsInstalledAsMulti(bool system_install, BrowserDistribution* dist);
+
// This function returns the install path for Chrome depending on whether its
// system wide install or user specific install.
// system_install: if true, the function returns system wide location
@@ -26,6 +29,19 @@ FilePath GetChromeInstallPath(bool system_install, BrowserDistribution* dist);
// that it can be overriden with a command line parameter.
FilePath GetChromeUserDataPath(BrowserDistribution* dist);
+// This is a workaround while we unify Chrome and Chrome Frame installation
+// folders. Right now, Chrome Frame can be installed into two different
+// folders: 1) A special "Chrome Frame" folder next to Chrome's folder
+// 2) The same folder as Chrome is installed into.
+// Right now this function will only return Chrome's installation folder
+// if Chrome Frame is not already installed or if Chrome Frame is installed
+// in multi_install mode.
+// If multi_install is false or if CF is installed in single mode, then the
+// returned path will be the "Chrome Frame" subfolder of either the user or
+// system default installation folders.
+FilePath GetChromeFrameInstallPath(bool multi_install, bool system_install,
+ BrowserDistribution* dist);
+
} // namespace installer
#endif // CHROME_INSTALLER_UTIL_HELPER_H_
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index db5c17d8..9ba1cec 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -87,12 +87,14 @@ Version* InstallUtil::GetChromeVersion(BrowserDistribution* dist,
HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
if (!key.Open(reg_root, dist->GetVersionKey().c_str(), KEY_READ) ||
!key.ReadValue(google_update::kRegVersionField, &version_str)) {
- VLOG(1) << "No existing Chrome install found.";
+ VLOG(1) << "No existing " << dist->GetApplicationName()
+ << " install found.";
key.Close();
return NULL;
}
key.Close();
- VLOG(1) << "Existing Chrome version found " << version_str;
+ VLOG(1) << "Existing " << dist->GetApplicationName()
+ << " version found " << version_str;
return Version::GetVersionFromString(version_str);
}
diff --git a/chrome/installer/util/master_preferences.cc b/chrome/installer/util/master_preferences.cc
index 2ca1a58..898e370 100644
--- a/chrome/installer/util/master_preferences.cc
+++ b/chrome/installer/util/master_preferences.cc
@@ -140,6 +140,8 @@ void MasterPreferences::InitializeFromCommandLine(const CommandLine& cmd_line) {
installer::master_preferences::kChrome },
{ installer::switches::kChromeFrame,
installer::master_preferences::kChromeFrame },
+ { installer::switches::kChromeFrameReadyMode,
+ installer::master_preferences::kChromeFrameReadyMode },
{ installer::switches::kCreateAllShortcuts,
installer::master_preferences::kCreateAllShortcuts },
{ installer::switches::kDisableLogging,
diff --git a/chrome/installer/util/master_preferences_constants.cc b/chrome/installer/util/master_preferences_constants.cc
index 0b71d9e..cea5b7f 100644
--- a/chrome/installer/util/master_preferences_constants.cc
+++ b/chrome/installer/util/master_preferences_constants.cc
@@ -11,6 +11,7 @@ namespace master_preferences {
const char kCeee[] = "ceee";
const char kChrome[] = "chrome";
const char kChromeFrame[] = "chrome_frame";
+ const char kChromeFrameReadyMode[] = "ready_mode";
const char kChromeShortcutIconIndex[] = "chrome_shortcut_icon_index";
const char kCreateAllShortcuts[] = "create_all_shortcuts";
const char kDisableLogging[] = "disable_logging";
diff --git a/chrome/installer/util/master_preferences_constants.h b/chrome/installer/util/master_preferences_constants.h
index 1220a38..cd3d034 100644
--- a/chrome/installer/util/master_preferences_constants.h
+++ b/chrome/installer/util/master_preferences_constants.h
@@ -27,6 +27,8 @@ extern const char kCeee[];
extern const char kChrome[];
// Boolean. This is to be a Chrome Frame install.
extern const char kChromeFrame[];
+// Boolean. Chrome Frame is to be installed in ready-mode.
+extern const char kChromeFrameReadyMode[];
// Integer. Icon index from chrome.exe to use for shortcuts.
extern const char kChromeShortcutIconIndex[];
// Boolean. Create Desktop and QuickLaunch shortcuts. Cmd line override present.
diff --git a/chrome/installer/util/package.cc b/chrome/installer/util/package.cc
index 5f5ff57..72c819c 100644
--- a/chrome/installer/util/package.cc
+++ b/chrome/installer/util/package.cc
@@ -11,6 +11,7 @@
#include "chrome/installer/util/channel_info.h"
#include "chrome/installer/util/delete_tree_work_item.h"
#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/master_preferences.h"
@@ -200,19 +201,9 @@ size_t Package::GetMultiInstallDependencyCount() const {
if (!version_key.Valid()) {
VLOG(1) << "Product not installed: " << dist->GetApplicationName();
} else {
- RegKey key(root_key, dist->GetStateKey().c_str(), KEY_READ);
- ChannelInfo channel_info;
- if (channel_info.Initialize(key)) {
- if (channel_info.IsMultiInstall()) {
- VLOG(1) << "Product dependency: " << dist->GetApplicationName();
- ret++;
- } else {
- VLOG(1) << "Product is installed, but not multi: "
- << dist->GetApplicationName();
- }
- } else {
- LOG(INFO) << "Product missing 'ap' value: "
- << dist->GetApplicationName();
+ if (installer::IsInstalledAsMulti(system_level_, dist)) {
+ VLOG(1) << "Product dependency: " << dist->GetApplicationName();
+ ++ret;
}
}
}
diff --git a/chrome/installer/util/package_unittest.cc b/chrome/installer/util/package_unittest.cc
index 2bfd44aa..c456482 100644
--- a/chrome/installer/util/package_unittest.cc
+++ b/chrome/installer/util/package_unittest.cc
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/command_line.h"
#include "base/logging.h"
#include "base/scoped_handle.h"
#include "base/utf_string_conversions.h"
#include "chrome/installer/util/browser_distribution.h"
-#include "chrome/installer/util/channel_info.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/package.h"
@@ -17,7 +17,6 @@
using base::win::RegKey;
using base::win::ScopedHandle;
-using installer::ChannelInfo;
using installer::ChromePackageProperties;
using installer::ChromiumPackageProperties;
using installer::Package;
@@ -134,6 +133,21 @@ TEST_F(PackageTest, WithProduct) {
}
}
+namespace {
+bool SetUninstallArguments(HKEY root, BrowserDistribution* dist,
+ const CommandLine& args) {
+ RegKey key(root, dist->GetStateKey().c_str(), KEY_ALL_ACCESS);
+ return key.WriteValue(installer::kUninstallArgumentsField,
+ args.command_line_string().c_str());
+}
+
+bool SetInstalledVersion(HKEY root, BrowserDistribution* dist,
+ const std::wstring& version) {
+ RegKey key(root, dist->GetVersionKey().c_str(), KEY_ALL_ACCESS);
+ return key.WriteValue(google_update::kRegVersionField, version.c_str());
+}
+} // end namespace
+
TEST_F(PackageTest, Dependency) {
const bool multi_install = false;
const bool system_level = true;
@@ -152,26 +166,25 @@ TEST_F(PackageTest, Dependency) {
BrowserDistribution* cf = BrowserDistribution::GetSpecificDistribution(
BrowserDistribution::CHROME_FRAME, prefs);
+ CommandLine multi_uninstall_cmd(CommandLine::NO_PROGRAM);
+ multi_uninstall_cmd.AppendSwitch(installer::switches::kUninstall);
+ multi_uninstall_cmd.AppendSwitch(installer::switches::kMultiInstall);
+
+ CommandLine single_uninstall_cmd(CommandLine::NO_PROGRAM);
+ single_uninstall_cmd.AppendSwitch(installer::switches::kUninstall);
+
// "install" Chrome.
- RegKey chrome_version_key(root, chrome->GetVersionKey().c_str(),
- KEY_ALL_ACCESS);
- RegKey chrome_key(root, chrome->GetStateKey().c_str(), KEY_ALL_ACCESS);
- ChannelInfo channel;
- channel.set_value(L"");
- channel.SetMultiInstall(true);
- channel.Write(&chrome_key);
+ SetUninstallArguments(root, chrome, multi_uninstall_cmd);
+ SetInstalledVersion(root, chrome, L"1.2.3.4");
EXPECT_EQ(1U, package->GetMultiInstallDependencyCount());
// "install" Chrome Frame without multi-install.
- RegKey cf_version_key(root, cf->GetVersionKey().c_str(), KEY_ALL_ACCESS);
- RegKey cf_key(root, cf->GetStateKey().c_str(), KEY_ALL_ACCESS);
- channel.SetMultiInstall(false);
- channel.Write(&cf_key);
+ SetUninstallArguments(root, cf, single_uninstall_cmd);
+ SetInstalledVersion(root, cf, L"1.2.3.4");
EXPECT_EQ(1U, package->GetMultiInstallDependencyCount());
// "install" Chrome Frame with multi-install.
- channel.SetMultiInstall(true);
- channel.Write(&cf_key);
+ SetUninstallArguments(root, cf, multi_uninstall_cmd);
EXPECT_EQ(2U, package->GetMultiInstallDependencyCount());
}
diff --git a/chrome/installer/util/product.cc b/chrome/installer/util/product.cc
index 8d4617a..43f371a 100644
--- a/chrome/installer/util/product.cc
+++ b/chrome/installer/util/product.cc
@@ -117,8 +117,7 @@ bool Product::IsMsi() const {
if ((cache_state_ & MSI_STATE) == 0) {
msi_ = false; // Covers failure cases below.
- const MasterPreferences& prefs =
- installer::MasterPreferences::ForCurrentProcess();
+ const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
bool is_msi = false;
prefs.GetBool(installer::master_preferences::kMsi, &is_msi);
@@ -177,6 +176,15 @@ bool Product::IsInstalled() const {
return GetInstalledVersion() != NULL;
}
+bool Product::ShouldCreateUninstallEntry() const {
+ if (IsMsi()) {
+ // MSI installations will manage their own uninstall shortcuts.
+ return false;
+ }
+
+ return distribution_->ShouldCreateUninstallEntry();
+}
+
///////////////////////////////////////////////////////////////////////////////
ProductPackageMapping::ProductPackageMapping(bool multi_install,
bool system_level)
@@ -202,7 +210,22 @@ bool ProductPackageMapping::AddDistribution(BrowserDistribution* distribution) {
// Each product type can be added exactly once.
DCHECK(FindProduct(products_, distribution->GetType()) == NULL);
- FilePath install_package(GetChromeInstallPath(system_level_, distribution));
+ FilePath install_package;
+ if (distribution->GetType() == BrowserDistribution::CHROME_BROWSER) {
+ install_package = GetChromeInstallPath(system_level_, distribution);
+ } else {
+ DCHECK_EQ(BrowserDistribution::CHROME_FRAME, distribution->GetType());
+ install_package = GetChromeFrameInstallPath(multi_install_, system_level_,
+ distribution);
+ }
+
+ if (install_package.empty()) {
+ LOG(ERROR) << "Got an empty installation path for "
+ << distribution->GetApplicationName()
+ << ". It's likely that there's a conflicting "
+ "installation present";
+ return false;
+ }
scoped_refptr<Package> target_package;
for (size_t i = 0; i < packages_.size(); ++i) {
@@ -234,7 +257,7 @@ bool ProductPackageMapping::AddDistribution(BrowserDistribution* distribution) {
bool ProductPackageMapping::AddDistribution(
BrowserDistribution::Type type,
- const installer::MasterPreferences& prefs) {
+ const MasterPreferences& prefs) {
BrowserDistribution* distribution =
BrowserDistribution::GetSpecificDistribution(type, prefs);
if (!distribution) {
diff --git a/chrome/installer/util/product.h b/chrome/installer/util/product.h
index 4204071..36362af 100644
--- a/chrome/installer/util/product.h
+++ b/chrome/installer/util/product.h
@@ -60,6 +60,14 @@ class Product : public base::RefCounted<Product> {
return package().system_level();
}
+ bool is_chrome() const {
+ return distribution_->GetType() == BrowserDistribution::CHROME_BROWSER;
+ }
+
+ bool is_chrome_frame() const {
+ return distribution_->GetType() == BrowserDistribution::CHROME_FRAME;
+ }
+
// Returns the path to the directory that holds the user data. This is always
// inside "Users\<user>\Local Settings". Note that this is the default user
// data directory and does not take into account that it can be overriden with
@@ -95,6 +103,10 @@ class Product : public base::RefCounted<Product> {
// found. The returned Version object is owned by |this| Product instance.
const Version* GetInstalledVersion() const;
+ // Returns true if setup should create an entry in the Add/Remove list
+ // of installed applications.
+ bool ShouldCreateUninstallEntry() const;
+
// Returns true if the product is already installed.
bool IsInstalled() const;
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc
index f3a062f..cda927d 100644
--- a/chrome/installer/util/util_constants.cc
+++ b/chrome/installer/util/util_constants.cc
@@ -15,9 +15,16 @@ const char kCeee[] = "ceee";
// Currently this is only required when used in combination with kMultiInstall.
const char kChrome[] = "chrome";
-// Run the installer in Chrome Frame mode.
+// Install Chrome Frame.
const char kChromeFrame[] = "chrome-frame";
+// When installing Chrome Frame, install it in ready mode.
+// If --chrome-frame is not on the command line, this switch has no effect.
+const char kChromeFrameReadyMode[] = "ready-mode";
+
+// GCF ready mode opt-in. This enables a full installation of GCF.
+const char kChromeFrameReadyModeOptIn[] = "ready-mode-opt-in";
+
// Run the installer for Chrome SxS.
const char kChromeSxS[] = "chrome-sxs";
@@ -139,6 +146,7 @@ const wchar_t kChromeExe[] = L"chrome.exe";
const wchar_t kChromeFrameDll[] = L"npchrome_frame.dll";
const wchar_t kChromeFrameHelperExe[] = L"chrome_frame_helper.exe";
const wchar_t kChromeFrameHelperWndClass[] = L"ChromeFrameHelperWindowClass";
+const wchar_t kChromeFrameReadyModeField[] = L"ChromeFrameReadyMode";
const wchar_t kChromeNaCl64Dll[] = L"nacl64.dll";
const wchar_t kChromeNewExe[] = L"new_chrome.exe";
const wchar_t kChromeOldExe[] = L"old_chrome.exe";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index 933cab5..0028c78 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -13,47 +13,63 @@ namespace installer {
// Return status of installer
enum InstallStatus {
- FIRST_INSTALL_SUCCESS, // Successfully installed Chrome for the first time
- INSTALL_REPAIRED, // Same version reinstalled for repair
- NEW_VERSION_UPDATED, // Chrome successfully updated to new version
- EXISTING_VERSION_LAUNCHED, // No work done, just launched existing chrome
- HIGHER_VERSION_EXISTS, // Higher version of Chrome already exists
- USER_LEVEL_INSTALL_EXISTS, // User level install already exists
- SYSTEM_LEVEL_INSTALL_EXISTS, // Machine level install already exists
- INSTALL_FAILED, // Install/update failed
- SETUP_PATCH_FAILED, // Failed to patch setup.exe
- OS_NOT_SUPPORTED, // Current OS not supported
- OS_ERROR, // OS API call failed
- TEMP_DIR_FAILED, // Unable to get Temp directory
- UNCOMPRESSION_FAILED, // Failed to uncompress Chrome archive
- INVALID_ARCHIVE, // Something wrong with the installer archive
- INSUFFICIENT_RIGHTS, // User trying system level install is not Admin
- CHROME_NOT_INSTALLED, // Chrome not installed (returned in case of uninstall)
- CHROME_RUNNING, // Chrome currently running (when trying to uninstall)
- UNINSTALL_CONFIRMED, // User has confirmed Chrome uninstall
- UNINSTALL_DELETE_PROFILE, // User confirmed uninstall and profile deletion
- UNINSTALL_SUCCESSFUL, // Chrome successfully uninstalled
- UNINSTALL_FAILED, // Chrome uninstallation failed
- UNINSTALL_CANCELLED, // User cancelled Chrome uninstallation
- UNKNOWN_STATUS, // Unknown status (this should never happen)
- RENAME_SUCCESSFUL, // Rename of new_chrome.exe to chrome.exe worked
- RENAME_FAILED, // Rename of new_chrome.exe failed
- EULA_REJECTED, // EULA dialog was not accepted by user.
- EULA_ACCEPTED, // EULA dialog was accepted by user.
- EULA_ACCEPTED_OPT_IN, // EULA accepted wtih the crash optin selected.
- INSTALL_DIR_IN_USE, // Installation directory is in use by another process
- UNINSTALL_REQUIRES_REBOOT, // Uninstallation required a reboot.
- IN_USE_UPDATED, // Chrome successfully updated but old version running
- SAME_VERSION_REPAIR_FAILED, // Chrome repair failed as Chrome was running
- REENTRY_SYS_UPDATE, // Setup has been re-launched as the interactive user
- SXS_OPTION_NOT_SUPPORTED // The chrome-sxs option provided does not work
- // with other command line options.
+ FIRST_INSTALL_SUCCESS, // 0. Successfully installed Chrome for the first time
+ INSTALL_REPAIRED, // 1. Same version reinstalled for repair
+ NEW_VERSION_UPDATED, // 2. Chrome successfully updated to new version
+ EXISTING_VERSION_LAUNCHED, // 3. No work done, just launched existing chrome
+ HIGHER_VERSION_EXISTS, // 4. Higher version of Chrome already exists
+ USER_LEVEL_INSTALL_EXISTS, // 5. User level install already exists
+ SYSTEM_LEVEL_INSTALL_EXISTS, // 6. Machine level install already exists
+ INSTALL_FAILED, // 7. Install/update failed
+ SETUP_PATCH_FAILED, // 8. Failed to patch setup.exe
+ OS_NOT_SUPPORTED, // 9. Current OS not supported
+ OS_ERROR, // 10. OS API call failed
+ TEMP_DIR_FAILED, // 11. Unable to get Temp directory
+ UNCOMPRESSION_FAILED, // 12. Failed to uncompress Chrome archive
+ INVALID_ARCHIVE, // 13. Something wrong with the installer archive
+ INSUFFICIENT_RIGHTS, // 14. User trying system level install is not Admin
+ CHROME_NOT_INSTALLED, // 15. Chrome not installed (returned in case of
+ // uninstall)
+ CHROME_RUNNING, // 16. Chrome currently running (when trying to
+ // uninstall)
+ UNINSTALL_CONFIRMED, // 17. User has confirmed Chrome uninstall
+ UNINSTALL_DELETE_PROFILE, // 18. User confirmed uninstall and profile deletion
+ UNINSTALL_SUCCESSFUL, // 19. Chrome successfully uninstalled
+ UNINSTALL_FAILED, // 20. Chrome uninstallation failed
+ UNINSTALL_CANCELLED, // 21. User cancelled Chrome uninstallation
+ UNKNOWN_STATUS, // 22. Unknown status (this should never happen)
+ RENAME_SUCCESSFUL, // 23. Rename of new_chrome.exe to chrome.exe worked
+ RENAME_FAILED, // 24. Rename of new_chrome.exe failed
+ EULA_REJECTED, // 25. EULA dialog was not accepted by user.
+ EULA_ACCEPTED, // 26. EULA dialog was accepted by user.
+ EULA_ACCEPTED_OPT_IN, // 27. EULA accepted wtih the crash optin selected.
+ INSTALL_DIR_IN_USE, // 28. Installation directory is in use by another
+ // process
+ UNINSTALL_REQUIRES_REBOOT, // 29. Uninstallation required a reboot.
+ IN_USE_UPDATED, // 30. Chrome successfully updated but old version
+ // running
+ SAME_VERSION_REPAIR_FAILED, // 31. Chrome repair failed as Chrome was running
+ REENTRY_SYS_UPDATE, // 32. Setup has been re-launched as the interactive
+ // user
+ SXS_OPTION_NOT_SUPPORTED, // 33. The chrome-sxs option provided does not work
+ // with other command line options.
+ NON_MULTI_INSTALLATION_EXISTS, // 34. We tried to do a multi-install but
+ // failed because there's an existing
+ // installation of the same product on the
+ // system, but in 'single' mode.
+ MULTI_INSTALLATION_EXISTS, // 35. We tried to do a 'single' install but
+ // failed because there's an existing
+ // multi-install installation of the same product
+ // on the system.
+ READY_MODE_OPT_IN_FAILED, // 36. Failed to opt-into Chrome Frame.
};
namespace switches {
extern const char kCeee[];
extern const char kChrome[];
extern const char kChromeFrame[];
+extern const char kChromeFrameReadyMode[];
+extern const char kChromeFrameReadyModeOptIn[];
extern const char kChromeSxS[];
extern const char kCreateAllShortcuts[];
extern const char kDeleteProfile[];
@@ -95,6 +111,7 @@ extern const wchar_t kChromeExe[];
extern const wchar_t kChromeFrameDll[];
extern const wchar_t kChromeFrameHelperExe[];
extern const wchar_t kChromeFrameHelperWndClass[];
+extern const wchar_t kChromeFrameReadyModeField[];
extern const wchar_t kChromeNaCl64Dll[];
extern const wchar_t kChromeOldExe[];
extern const wchar_t kChromeNewExe[];