1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/installer/setup/chrome_frame_quick_enable.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/win/registry.h"
13 #include "chrome/installer/setup/install_worker.h"
14 #include "chrome/installer/util/google_update_constants.h"
15 #include "chrome/installer/util/google_update_settings.h"
16 #include "chrome/installer/util/install_util.h"
17 #include "chrome/installer/util/installation_state.h"
18 #include "chrome/installer/util/installer_state.h"
19 #include "chrome/installer/util/product.h"
20 #include "chrome/installer/util/work_item.h"
21 #include "chrome/installer/util/work_item_list.h"
23 using base::win::RegKey;
29 InstallStatus CheckQuickEnablePreconditions(
30 const InstallationState& machine_state,
31 const InstallerState& installer_state) {
32 // Make sure Chrome is multi-installed.
33 const ProductState* chrome_state =
34 machine_state.GetProductState(installer_state.system_install(),
35 BrowserDistribution::CHROME_BROWSER);
36 if (chrome_state == NULL) {
37 LOG(ERROR) << "Chrome Frame quick enable requires Chrome to be installed.";
38 return CHROME_NOT_INSTALLED;
39 } else if (!chrome_state->is_multi_install()) {
40 LOG(ERROR) << "Chrome Frame quick enable requires multi-install of Chrome.";
41 return NON_MULTI_INSTALLATION_EXISTS;
44 // Chrome Frame must not be installed (ready-mode doesn't count).
45 const ProductState* cf_state =
46 machine_state.GetProductState(installer_state.system_install(),
47 BrowserDistribution::CHROME_FRAME);
48 // Make sure we check both user and system installations.
50 cf_state = machine_state.GetProductState(!installer_state.system_install(),
51 BrowserDistribution::CHROME_FRAME);
54 if (cf_state != NULL &&
55 !cf_state->uninstall_command().HasSwitch(
56 switches::kChromeFrameReadyMode)) {
57 LOG(ERROR) << "Chrome Frame already installed.";
58 return installer_state.system_install() ?
59 SYSTEM_LEVEL_INSTALL_EXISTS : USER_LEVEL_INSTALL_EXISTS;
62 return FIRST_INSTALL_SUCCESS;
67 InstallStatus ChromeFrameQuickEnable(const InstallationState& machine_state,
68 InstallerState* installer_state) {
69 DCHECK(installer_state);
70 VLOG(1) << "Chrome Frame Quick Enable";
71 InstallStatus status = CheckQuickEnablePreconditions(machine_state,
74 if (status == FIRST_INSTALL_SUCCESS) {
75 scoped_ptr<Product> multi_cf(new Product(
76 BrowserDistribution::GetSpecificDistribution(
77 BrowserDistribution::CHROME_FRAME)));
78 multi_cf->SetOption(installer::kOptionMultiInstall, true);
79 Product* cf = installer_state->AddProduct(&multi_cf);
81 LOG(ERROR) << "AddProduct failed";
82 status = INSTALL_FAILED;
84 base::ScopedTempDir temp_path;
85 if (!temp_path.CreateUniqueTempDir()) {
86 PLOG(ERROR) << "Failed to create Temp directory";
87 return INSTALL_FAILED;
89 scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList());
90 const ProductState* chrome_state =
91 machine_state.GetProductState(installer_state->system_install(),
92 BrowserDistribution::CHROME_BROWSER);
93 DCHECK(chrome_state); // Checked in CheckQuickEnablePreconditions.
95 // Temporarily remove Chrome from the product list.
96 // This is so that the operations below do not affect the installation
98 installer_state->RemoveProduct(
99 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER));
101 base::FilePath setup_path(chrome_state->GetSetupPath());
102 const Version& new_version = chrome_state->version();
104 // This creates the uninstallation entry for GCF.
105 AddUninstallShortcutWorkItems(*installer_state, setup_path, new_version,
106 *cf, item_list.get());
107 // Always set the "lang" value since quick-enable always happens in the
108 // context of an interactive session with a user.
109 AddVersionKeyWorkItems(installer_state->root_key(), cf->distribution(),
110 new_version, true, item_list.get());
111 AddChromeFrameWorkItems(machine_state, *installer_state, setup_path,
112 new_version, *cf, item_list.get());
114 const Version* opv = chrome_state->old_version();
115 AppendPostInstallTasks(*installer_state, setup_path, opv,
116 new_version, temp_path.path(), item_list.get());
118 // Before updating the channel values, add Chrome back to the mix so that
119 // all multi-installed products' channel values get updated.
120 installer_state->AddProductFromState(BrowserDistribution::CHROME_BROWSER,
122 AddGoogleUpdateWorkItems(machine_state, *installer_state,
125 // Add the items to remove the quick-enable-cf command from the registry.
126 AddQuickEnableChromeFrameWorkItems(
127 *installer_state, machine_state,
128 chrome_state->uninstall_command().GetProgram(),
132 if (!item_list->Do()) {
133 item_list->Rollback();
134 status = INSTALL_FAILED;
136 DCHECK_EQ(FIRST_INSTALL_SUCCESS, status);
137 VLOG(1) << "Chrome Frame successfully activated.";
142 // If quick-enable succeeded, check to see if the EULA has not yet been
143 // accepted for the binaries. If this is the case, we must also flip the
144 // eulaaccepted bit for them. Otherwise, Google Update would not update
145 // Chrome Frame, and that would be bad. Don't flip the EULA bit for Chrome
146 // itself, as it will show the EULA on first-run and mark its acceptance
148 if (!InstallUtil::GetInstallReturnCode(status)) {
149 const bool system_level = installer_state->system_install();
150 const ProductState* binaries =
151 machine_state.GetProductState(system_level,
152 BrowserDistribution::CHROME_BINARIES);
156 if (binaries != NULL &&
157 binaries->GetEulaAccepted(&eula_accepted) &&
158 eula_accepted == 0 &&
159 !GoogleUpdateSettings::SetEULAConsent(
161 BrowserDistribution::GetSpecificDistribution(
162 BrowserDistribution::CHROME_BINARIES),
164 LOG(ERROR) << "Failed to set EULA consent for multi-install binaries.";
171 } // namespace installer