Home | History | Annotate | Download | only in setup
      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.
      4 
      5 #include "chrome/installer/setup/chrome_frame_quick_enable.h"
      6 
      7 #include <windows.h>
      8 
      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"
     22 
     23 using base::win::RegKey;
     24 
     25 namespace installer {
     26 
     27 namespace {
     28 
     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;
     42   }
     43 
     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.
     49   if (!cf_state) {
     50     cf_state = machine_state.GetProductState(!installer_state.system_install(),
     51                                              BrowserDistribution::CHROME_FRAME);
     52   }
     53 
     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;
     60   }
     61 
     62   return FIRST_INSTALL_SUCCESS;
     63 }
     64 
     65 }  // end namespace
     66 
     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,
     72                                                        *installer_state);
     73 
     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);
     80     if (!cf) {
     81       LOG(ERROR) << "AddProduct failed";
     82       status = INSTALL_FAILED;
     83     } else {
     84       base::ScopedTempDir temp_path;
     85       if (!temp_path.CreateUniqueTempDir()) {
     86         PLOG(ERROR) << "Failed to create Temp directory";
     87         return INSTALL_FAILED;
     88       }
     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.
     94 
     95       // Temporarily remove Chrome from the product list.
     96       // This is so that the operations below do not affect the installation
     97       // state of Chrome.
     98       installer_state->RemoveProduct(
     99           installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER));
    100 
    101       base::FilePath setup_path(chrome_state->GetSetupPath());
    102       const Version& new_version = chrome_state->version();
    103 
    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());
    113 
    114       const Version* opv = chrome_state->old_version();
    115       AppendPostInstallTasks(*installer_state, setup_path, opv,
    116                              new_version, temp_path.path(), item_list.get());
    117 
    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,
    121                                            *chrome_state);
    122       AddGoogleUpdateWorkItems(machine_state, *installer_state,
    123                                item_list.get());
    124 
    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(),
    129           new_version,
    130           item_list.get());
    131 
    132       if (!item_list->Do()) {
    133         item_list->Rollback();
    134         status = INSTALL_FAILED;
    135       } else {
    136         DCHECK_EQ(FIRST_INSTALL_SUCCESS, status);
    137         VLOG(1) << "Chrome Frame successfully activated.";
    138       }
    139     }
    140   }
    141 
    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
    147   // accordingly.
    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);
    153     DCHECK(binaries);
    154     DWORD eula_accepted;
    155 
    156     if (binaries != NULL &&
    157         binaries->GetEulaAccepted(&eula_accepted) &&
    158         eula_accepted == 0 &&
    159         !GoogleUpdateSettings::SetEULAConsent(
    160             machine_state,
    161             BrowserDistribution::GetSpecificDistribution(
    162                 BrowserDistribution::CHROME_BINARIES),
    163             true)) {
    164       LOG(ERROR) << "Failed to set EULA consent for multi-install binaries.";
    165     }
    166   }
    167 
    168   return status;
    169 }
    170 
    171 }  // namespace installer
    172