summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhuangs@chromium.org <huangs@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-05 06:07:34 +0000
committerhuangs@chromium.org <huangs@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-05 06:07:34 +0000
commitc4e3a43ae24051c429ab75646f9cd134622620a8 (patch)
tree4ac0ef7ddced6fe64cde029b454b3faf0830d123
parentc347c436757c3e37179854861107e1de9ee510a3 (diff)
downloadchromium_src-c4e3a43ae24051c429ab75646f9cd134622620a8.zip
chromium_src-c4e3a43ae24051c429ab75646f9cd134622620a8.tar.gz
chromium_src-c4e3a43ae24051c429ab75646f9cd134622620a8.tar.bz2
Adding uninstaller flow to demote App Launcher to App Host (AKA opt-out).
Here is when the flow is triggered: - Chrome and App Launcher are installed. - Uninstalling App Launcher only, but keeping Chrome. The result is that the App Launcher would disappear, BUT user can still use V2 apps, and V2 app shortcuts continue to work. Eventually App Launcher will replace App Host. When this happens, this flow should be removed. Main implementation idea: DO NOT pass App Launcher through regular uninstall flow. We do a complete separate flow in one location, to avoid polluting common code, and to simplify removal. BUG=162418 Review URL: https://chromiumcodereview.appspot.com/11416165 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171181 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/installer/setup/setup_main.cc5
-rw-r--r--chrome/installer/setup/uninstall.cc138
-rw-r--r--chrome/installer/setup/uninstall.h5
-rw-r--r--chrome/installer/util/installer_state.cc35
-rw-r--r--chrome/installer/util/installer_state.h7
-rw-r--r--chrome/installer/util/master_preferences.cc19
-rw-r--r--chrome/installer/util/master_preferences.h5
7 files changed, 176 insertions, 38 deletions
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index d90c9a5..fba018e 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -1032,6 +1032,11 @@ installer::InstallStatus UninstallProducts(
install_status = prod_status;
}
+ if (install_status != installer::UNINSTALL_CANCELLED &&
+ installer_state.demote_app_launcher_to_app_host()) {
+ installer::DemoteAppLauncherToAppHost(original_state, installer_state);
+ }
+
// Tell Google Update that an uninstall has taken place.
// Ignore the return value: success or failure of Google Update
// has no bearing on the success or failure of Chrome's uninstallation.
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index a84b49f..ead0795 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -70,6 +70,41 @@ void DeleteInstallTempDir(const FilePath& target_path) {
}
}
+// Iterates over the list of distribution types in |dist_types|, and
+// adds to |update_list| the work item to update the corresponding "ap"
+// registry value specified in |channel_info|.
+void AddChannelValueUpdateWorkItems(
+ const installer::InstallationState& original_state,
+ const installer::InstallerState& installer_state,
+ const installer::ChannelInfo& channel_info,
+ const std::vector<BrowserDistribution::Type>& dist_types,
+ WorkItemList* update_list) {
+ const bool system_level = installer_state.system_install();
+ const HKEY reg_root = installer_state.root_key();
+ for (size_t i = 0; i < dist_types.size(); ++i) {
+ BrowserDistribution::Type dist_type = dist_types[i];
+ const installer::ProductState* product_state =
+ original_state.GetProductState(system_level, dist_type);
+ // Only modify other products if they're installed and multi.
+ if (product_state != NULL &&
+ product_state->is_multi_install() &&
+ !product_state->channel().Equals(channel_info)) {
+ BrowserDistribution* other_dist =
+ BrowserDistribution::GetSpecificDistribution(dist_type);
+ update_list->AddSetRegValueWorkItem(reg_root, other_dist->GetStateKey(),
+ google_update::kRegApField, channel_info.value(), true);
+ } else {
+ LOG_IF(ERROR,
+ product_state != NULL && product_state->is_multi_install())
+ << "Channel value for "
+ << BrowserDistribution::GetSpecificDistribution(
+ dist_type)->GetAppShortCutName()
+ << " is somehow already set to the desired new value of "
+ << channel_info.value();
+ }
+ }
+}
+
// Makes appropriate changes to the Google Update "ap" value in the registry.
// Specifically, removes the flags associated with this product ("-chrome" or
// "-chromeframe[-readymode]") from the "ap" values for all other
@@ -81,7 +116,6 @@ void ProcessGoogleUpdateItems(
DCHECK(installer_state.is_multi_install());
const bool system_level = installer_state.system_install();
BrowserDistribution* distribution = product.distribution();
- const HKEY reg_root = installer_state.root_key();
const installer::ProductState* product_state =
original_state.GetProductState(system_level, distribution->GetType());
DCHECK(product_state != NULL);
@@ -95,34 +129,16 @@ void ProcessGoogleUpdateItems(
if (modified) {
scoped_ptr<WorkItemList>
update_list(WorkItem::CreateNoRollbackWorkItemList());
-
+ std::vector<BrowserDistribution::Type> dist_types;
for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) {
BrowserDistribution::Type other_dist_type =
static_cast<BrowserDistribution::Type>(i);
- if (distribution->GetType() == other_dist_type)
- continue;
-
- product_state =
- original_state.GetProductState(system_level, other_dist_type);
- // Only modify other products if they're installed and multi.
- if (product_state != NULL &&
- product_state->is_multi_install() &&
- !product_state->channel().Equals(channel_info)) {
- BrowserDistribution* other_dist =
- BrowserDistribution::GetSpecificDistribution(other_dist_type);
- update_list->AddSetRegValueWorkItem(reg_root, other_dist->GetStateKey(),
- google_update::kRegApField, channel_info.value(), true);
- } else {
- LOG_IF(ERROR,
- product_state != NULL && product_state->is_multi_install())
- << "Channel value for "
- << BrowserDistribution::GetSpecificDistribution(
- other_dist_type)->GetAppShortCutName()
- << " is somehow already set to the desired new value of "
- << channel_info.value();
- }
+ if (distribution->GetType() != other_dist_type)
+ dist_types.push_back(other_dist_type);
}
-
+ AddChannelValueUpdateWorkItems(original_state, installer_state,
+ channel_info, dist_types,
+ update_list.get());
bool success = update_list->Do();
LOG_IF(ERROR, !success) << "Failed updating channel values.";
}
@@ -1254,4 +1270,76 @@ InstallStatus UninstallProduct(const InstallationState& original_state,
return ret;
}
+// Eventually App Launcher will be the only way to run V2 apps, and this flow
+// will become obsolete. That's why we concentrate all the changes here,
+// to reduce polluting common code, and to simplify future removal.
+void DemoteAppLauncherToAppHost(
+ const InstallationState& original_state,
+ const InstallerState& installer_state) {
+ VLOG(1) << "Demoting App Launcher to App Host.";
+ InstallStatus ret = installer::UNKNOWN_STATUS;
+ // App Host can only be present if Chrome is present (unlike App Launcher).
+ DCHECK(original_state.GetProductState(false,
+ BrowserDistribution::CHROME_BROWSER) ||
+ original_state.GetProductState(true,
+ BrowserDistribution::CHROME_BROWSER));
+ const ProductState* app_host_state = original_state.GetProductState(
+ installer_state.system_install(), BrowserDistribution::CHROME_APP_HOST);
+ if (!app_host_state || !app_host_state->uninstall_command().HasSwitch(
+ switches::kChromeAppLauncher)) {
+ NOTREACHED();
+ return;
+ }
+
+ BrowserDistribution* app_host_dist =
+ BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_APP_HOST);
+ Product app_host_product(app_host_dist);
+ app_host_product.InitializeFromUninstallCommand(
+ app_host_state->uninstall_command());
+ app_host_product.SetOption(installer::kOptionAppHostIsLauncher, false);
+
+ scoped_ptr<WorkItemList>
+ work_item_list(WorkItem::CreateNoRollbackWorkItemList());
+
+ // Update the App Host uninstall string in Google Update Client.
+ // This is extracted from AddUninstallShortcutWorkItems().
+ HKEY reg_root = installer_state.root_key();
+ string16 update_state_key(app_host_dist->GetStateKey());
+ CommandLine uninstall_arguments(CommandLine::NO_PROGRAM);
+ AppendUninstallCommandLineFlags(
+ installer_state, app_host_product, &uninstall_arguments);
+ work_item_list->AddSetRegValueWorkItem(reg_root, update_state_key,
+ installer::kUninstallArgumentsField,
+ uninstall_arguments.GetCommandLineString(), true);
+
+ // Change the "ap" keys in Google Update registry.
+ // This is extracted from ProcessGoogleUpdateItems().
+ installer::ChannelInfo channel_info;
+ channel_info.set_value(app_host_state->channel().value());
+ bool modified_app_launcher = channel_info.SetAppLauncher(false);
+ bool modified_app_host = channel_info.SetAppHost(true);
+ DCHECK(modified_app_host && modified_app_launcher);
+ std::vector<BrowserDistribution::Type> dist_types;
+ for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) {
+ dist_types.push_back(static_cast<BrowserDistribution::Type>(i));
+ }
+ AddChannelValueUpdateWorkItems(original_state, installer_state, channel_info,
+ dist_types, work_item_list.get());
+
+ // Remove Control Panel uninstall link.
+ work_item_list->AddDeleteRegKeyWorkItem(
+ reg_root, app_host_dist->GetUninstallRegPath());
+
+ // Execute task list.
+ if (!work_item_list->Do())
+ LOG(ERROR) << "Failed to demote App Launcher to App Host.";
+
+ // Delete shortcuts.
+ FilePath app_host_exe(installer::GetChromeInstallPath(
+ installer_state.system_install(), app_host_dist)
+ .Append(kChromeAppHostExe));
+ DeleteShortcuts(installer_state, app_host_product, app_host_exe.value());
+}
+
} // namespace installer
diff --git a/chrome/installer/setup/uninstall.h b/chrome/installer/setup/uninstall.h
index be10efb..843f0b7 100644
--- a/chrome/installer/setup/uninstall.h
+++ b/chrome/installer/setup/uninstall.h
@@ -60,6 +60,11 @@ installer::InstallStatus UninstallProduct(
bool force_uninstall,
const CommandLine& cmd_line);
+// Makes all the proper changes to demote App Launcher to App Host.
+void DemoteAppLauncherToAppHost(
+ const InstallationState& original_state,
+ const InstallerState& installer_state);
+
} // namespace installer
#endif // CHROME_INSTALLER_SETUP_UNINSTALL_H_
diff --git a/chrome/installer/util/installer_state.cc b/chrome/installer/util/installer_state.cc
index dc0f2ac..b04214b 100644
--- a/chrome/installer/util/installer_state.cc
+++ b/chrome/installer/util/installer_state.cc
@@ -78,7 +78,8 @@ InstallerState::InstallerState()
root_key_(NULL),
msi_(false),
verbose_logging_(false),
- ensure_google_update_present_(false) {
+ ensure_google_update_present_(false),
+ demote_app_launcher_to_app_host_(false) {
}
InstallerState::InstallerState(Level level)
@@ -90,7 +91,8 @@ InstallerState::InstallerState(Level level)
root_key_(NULL),
msi_(false),
verbose_logging_(false),
- ensure_google_update_present_(false) {
+ ensure_google_update_present_(false),
+ demote_app_launcher_to_app_host_(false) {
// Use set_level() so that root_key_ is updated properly.
set_level(level);
}
@@ -118,6 +120,24 @@ void InstallerState::Initialize(const CommandLine& command_line,
const bool is_uninstall = command_line.HasSwitch(switches::kUninstall);
+ demote_app_launcher_to_app_host_ = false;
+ // true iff Uninstalling App Launcher && Chrome will be present afterward.
+ if (is_uninstall && prefs.install_chrome_app_launcher() &&
+ !prefs.install_chrome()) {
+ const bool chrome_is_present =
+ machine_state.GetProductState(false,
+ BrowserDistribution::CHROME_BROWSER) ||
+ machine_state.GetProductState(true,
+ BrowserDistribution::CHROME_BROWSER);
+ if (chrome_is_present) {
+ const ProductState* app_host_state = machine_state.GetProductState(
+ level_ == SYSTEM_LEVEL, BrowserDistribution::CHROME_APP_HOST);
+ demote_app_launcher_to_app_host_ = app_host_state &&
+ app_host_state->uninstall_command().HasSwitch(
+ switches::kChromeAppLauncher);
+ }
+ }
+
if (prefs.install_chrome()) {
Product* p = AddProductFromPreferences(
BrowserDistribution::CHROME_BROWSER, prefs, machine_state);
@@ -131,7 +151,8 @@ void InstallerState::Initialize(const CommandLine& command_line,
<< " distribution: " << p->distribution()->GetAppShortCutName();
}
- if (prefs.install_chrome_app_host()) {
+ if (prefs.install_chrome_app_host() || (prefs.install_chrome_app_launcher() &&
+ !demote_app_launcher_to_app_host_)) {
Product* p = AddProductFromPreferences(
BrowserDistribution::CHROME_APP_HOST, prefs, machine_state);
VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
@@ -286,12 +307,14 @@ void InstallerState::Initialize(const CommandLine& command_line,
if (operand == NULL) {
BrowserDistribution::Type operand_distribution_type =
BrowserDistribution::CHROME_BINARIES;
- if (prefs.install_chrome())
+ if (prefs.install_chrome()) {
operand_distribution_type = BrowserDistribution::CHROME_BROWSER;
- else if (prefs.install_chrome_frame())
+ } else if (prefs.install_chrome_frame()) {
operand_distribution_type = BrowserDistribution::CHROME_FRAME;
- else if (prefs.install_chrome_app_host())
+ } else if (prefs.install_chrome_app_host() ||
+ prefs.install_chrome_app_launcher()) {
operand_distribution_type = BrowserDistribution::CHROME_APP_HOST;
+ }
operand = BrowserDistribution::GetSpecificDistribution(
operand_distribution_type);
diff --git a/chrome/installer/util/installer_state.h b/chrome/installer/util/installer_state.h
index 2fb0c0d..a8cbb6c 100644
--- a/chrome/installer/util/installer_state.h
+++ b/chrome/installer/util/installer_state.h
@@ -118,6 +118,12 @@ class InstallerState {
return ensure_google_update_present_;
}
+ // A convenient method returning the intent to demote App Launcher into
+ // App Host.
+ bool demote_app_launcher_to_app_host() const {
+ return demote_app_launcher_to_app_host_;
+ }
+
// The full path to the place where the operand resides.
const FilePath& target_path() const { return target_path_; }
@@ -248,6 +254,7 @@ class InstallerState {
bool msi_;
bool verbose_logging_;
bool ensure_google_update_present_;
+ bool demote_app_launcher_to_app_host_;
private:
DISALLOW_COPY_AND_ASSIGN(InstallerState);
diff --git a/chrome/installer/util/master_preferences.cc b/chrome/installer/util/master_preferences.cc
index 0999b0a..776a3c8 100644
--- a/chrome/installer/util/master_preferences.cc
+++ b/chrome/installer/util/master_preferences.cc
@@ -77,6 +77,7 @@ MasterPreferences::MasterPreferences() : distribution_(NULL),
preferences_read_from_file_(false),
chrome_(true),
chrome_app_host_(false),
+ chrome_app_launcher_(false),
chrome_frame_(false),
multi_install_(false) {
InitializeFromCommandLine(*CommandLine::ForCurrentProcess());
@@ -87,6 +88,7 @@ MasterPreferences::MasterPreferences(const CommandLine& cmd_line)
preferences_read_from_file_(false),
chrome_(true),
chrome_app_host_(false),
+ chrome_app_launcher_(false),
chrome_frame_(false),
multi_install_(false) {
InitializeFromCommandLine(cmd_line);
@@ -97,6 +99,7 @@ MasterPreferences::MasterPreferences(const FilePath& prefs_path)
preferences_read_from_file_(false),
chrome_(true),
chrome_app_host_(false),
+ chrome_app_launcher_(false),
chrome_frame_(false),
multi_install_(false) {
std::string json_data;
@@ -113,8 +116,12 @@ MasterPreferences::MasterPreferences(const FilePath& prefs_path)
}
MasterPreferences::MasterPreferences(const std::string& prefs)
- : distribution_(NULL), preferences_read_from_file_(false),
- chrome_(true), chrome_app_host_(false), chrome_frame_(false),
+ : distribution_(NULL),
+ preferences_read_from_file_(false),
+ chrome_(true),
+ chrome_app_host_(false),
+ chrome_app_launcher_(false),
+ chrome_frame_(false),
multi_install_(false) {
InitializeFromString(prefs);
}
@@ -230,21 +237,19 @@ bool MasterPreferences::InitializeFromString(const std::string& json_data) {
}
void MasterPreferences::InitializeProductFlags() {
- bool pref_chrome_app_host = false;
- bool pref_chrome_app_launcher = false;
// Make sure we start out with the correct defaults.
multi_install_ = false;
chrome_frame_ = false;
chrome_app_host_ = false;
+ chrome_app_launcher_ = false;
chrome_ = true;
GetBool(installer::master_preferences::kMultiInstall, &multi_install_);
GetBool(installer::master_preferences::kChromeFrame, &chrome_frame_);
- GetBool(installer::master_preferences::kChromeAppHost, &pref_chrome_app_host);
+ GetBool(installer::master_preferences::kChromeAppHost, &chrome_app_host_);
GetBool(installer::master_preferences::kChromeAppLauncher,
- &pref_chrome_app_launcher);
- chrome_app_host_ = pref_chrome_app_host || pref_chrome_app_launcher;
+ &chrome_app_launcher_);
// When multi-install is specified, the checks are pretty simple (in theory):
// In order to be installed/uninstalled, each product must have its switch
diff --git a/chrome/installer/util/master_preferences.h b/chrome/installer/util/master_preferences.h
index 3d445fa..46dc7c9 100644
--- a/chrome/installer/util/master_preferences.h
+++ b/chrome/installer/util/master_preferences.h
@@ -172,6 +172,10 @@ class MasterPreferences {
return chrome_app_host_;
}
+ bool install_chrome_app_launcher() const {
+ return chrome_app_launcher_;
+ }
+
bool install_chrome_frame() const {
return chrome_frame_;
}
@@ -205,6 +209,7 @@ class MasterPreferences {
bool preferences_read_from_file_;
bool chrome_;
bool chrome_app_host_;
+ bool chrome_app_launcher_;
bool chrome_frame_;
bool multi_install_;