installer_state.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/installer_state.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <functional>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_version_info.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/delete_tree_work_item.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/helper.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/install_util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/installation_state.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/master_preferences.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/master_preferences_constants.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/product.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/work_item.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/work_item_list.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace installer {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::IsMultiInstallUpdate(const MasterPreferences& prefs,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const InstallationState& machine_state) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First, is the package present?
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ProductState* package =
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      machine_state.GetProductState(level_ == SYSTEM_LEVEL,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    BrowserDistribution::CHROME_BINARIES);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (package == NULL) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The multi-install package has not been installed, so it certainly isn't
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // being updated.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserDistribution::Type types[2];
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t num_types = 0;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prefs.install_chrome())
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    types[num_types++] = BrowserDistribution::CHROME_BROWSER;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prefs.install_chrome_frame())
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    types[num_types++] = BrowserDistribution::CHROME_FRAME;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (const BrowserDistribution::Type* scan = &types[0],
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           *end = &types[num_types]; scan != end; ++scan) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProductState* product =
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        machine_state.GetProductState(level_ == SYSTEM_LEVEL, *scan);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (product == NULL) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(2) << "It seems that distribution type " << *scan
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << " is being installed for the first time.";
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!product->channel().Equals(package->channel())) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(2) << "It seems that distribution type " << *scan
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << " is being over installed.";
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << "It seems that the package is being updated.";
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InstallerState::InstallerState()
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : operation_(UNINITIALIZED),
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      state_type_(BrowserDistribution::CHROME_BROWSER),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      multi_package_distribution_(NULL),
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      level_(UNKNOWN_LEVEL),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      package_type_(UNKNOWN_PACKAGE_TYPE),
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_key_(NULL),
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      msi_(false),
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      verbose_logging_(false),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ensure_google_update_present_(false) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InstallerState::InstallerState(Level level)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : operation_(UNINITIALIZED),
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      state_type_(BrowserDistribution::CHROME_BROWSER),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      multi_package_distribution_(NULL),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      level_(UNKNOWN_LEVEL),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      package_type_(UNKNOWN_PACKAGE_TYPE),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_key_(NULL),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      msi_(false),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      verbose_logging_(false),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ensure_google_update_present_(false) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use set_level() so that root_key_ is updated properly.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_level(level);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::Initialize(const CommandLine& command_line,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const MasterPreferences& prefs,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const InstallationState& machine_state) {
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Clear();
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pref_bool;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!prefs.GetBool(master_preferences::kSystemLevel, &pref_bool))
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pref_bool = false;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_level(pref_bool ? SYSTEM_LEVEL : USER_LEVEL);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!prefs.GetBool(master_preferences::kVerboseLogging, &verbose_logging_))
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verbose_logging_ = false;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!prefs.GetBool(master_preferences::kMultiInstall, &pref_bool))
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pref_bool = false;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_package_type(pref_bool ? MULTI_PACKAGE : SINGLE_PACKAGE);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!prefs.GetBool(master_preferences::kMsi, &msi_))
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msi_ = false;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ensure_google_update_present_ =
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.HasSwitch(installer::switches::kEnsureGoogleUpdatePresent);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool is_uninstall = command_line.HasSwitch(switches::kUninstall);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prefs.install_chrome()) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Product* p = AddProductFromPreferences(
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserDistribution::CHROME_BROWSER, prefs, machine_state);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            << " distribution: " << p->distribution()->GetDisplayName();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prefs.install_chrome_frame()) {
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Product* p = AddProductFromPreferences(
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserDistribution::CHROME_FRAME, prefs, machine_state);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            << " distribution: " << p->distribution()->GetDisplayName();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (prefs.install_chrome_app_launcher()) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Product* p = AddProductFromPreferences(
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserDistribution::CHROME_APP_HOST, prefs, machine_state);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            << " distribution: " << p->distribution()->GetDisplayName();
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_uninstall && is_multi_install()) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool need_binaries = false;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FindProduct(BrowserDistribution::CHROME_APP_HOST)) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // App Host will happily use Chrome at system level, or binaries at system
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // level, even if app host is user level.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ProductState* chrome_state = machine_state.GetProductState(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          true,  // system level
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          BrowserDistribution::CHROME_BROWSER);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If Chrome is at system-level, multi- or otherwise. We'll use it.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!chrome_state) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const ProductState* binaries_state = machine_state.GetProductState(
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            true,  // system level
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            BrowserDistribution::CHROME_BINARIES);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!binaries_state)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          need_binaries = true;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Chrome/Chrome Frame multi need Binaries at their own level.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FindProduct(BrowserDistribution::CHROME_BROWSER))
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      need_binaries = true;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FindProduct(BrowserDistribution::CHROME_FRAME))
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      need_binaries = true;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (need_binaries && !FindProduct(BrowserDistribution::CHROME_BINARIES)) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Force binaries to be installed/updated.
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Product* p = AddProductFromPreferences(
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          BrowserDistribution::CHROME_BINARIES, prefs, machine_state);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "Install distribution: "
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              << p->distribution()->GetDisplayName();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_uninstall && prefs.is_multi_install()) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FindProduct(BrowserDistribution::CHROME_BROWSER)) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Uninstall each product of type |type| listed below based on the
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // presence or absence of |switch_name| in that product's uninstall
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // command.
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const struct {
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserDistribution::Type type;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const char* switch_name;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bool switch_expected;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } conditional_additions[] = {
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // If Chrome Frame is installed in Ready Mode, remove it with Chrome.
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        { BrowserDistribution::CHROME_FRAME,
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          switches::kChromeFrameReadyMode,
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          true },
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // If the App Host is installed, but not the App Launcher, remove it
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // with Chrome. Note however that for system-level Chrome uninstalls,
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // any installed user-level App Host will remain even if there is no
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // App Launcher present (the orphaned app_host.exe will prompt the user
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // for further action when executed).
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        { BrowserDistribution::CHROME_APP_HOST,
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          switches::kChromeAppLauncher,
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          false },
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      };
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (size_t i = 0; i < arraysize(conditional_additions); ++i) {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const ProductState* product_state = machine_state.GetProductState(
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            system_install(), conditional_additions[i].type);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (product_state != NULL &&
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            product_state->uninstall_command().HasSwitch(
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                conditional_additions[i].switch_name) ==
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    conditional_additions[i].switch_expected &&
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            !FindProduct(conditional_additions[i].type)) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          Product* p = AddProductFromPreferences(
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              conditional_additions[i].type, prefs, machine_state);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          VLOG(1) << "Uninstall distribution: "
2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                  << p->distribution()->GetDisplayName();
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool keep_binaries = false;
219bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    // Look for a multi-install product that is not the binaries and that is not
220bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    // being uninstalled. If not found, binaries are uninstalled too.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserDistribution::Type type =
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<BrowserDistribution::Type>(i);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (type == BrowserDistribution::CHROME_BINARIES)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
228bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      const ProductState* product_state =
229bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          machine_state.GetProductState(system_install(), type);
230bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      if (product_state == NULL) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The product is not installed.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      if (!product_state->is_multi_install() &&
236bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          type != BrowserDistribution::CHROME_BROWSER) {
237bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // The product is not sharing the binaries. It is ordinarily impossible
238bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // for single-install Chrome to be installed along with any
239bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // multi-install product. Treat single-install Chrome the same as any
240bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // multi-install product just in case the impossible happens.
241bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        continue;
242bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      }
243bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The product is installed.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!FindProduct(type)) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The product is not being uninstalled.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (type != BrowserDistribution::CHROME_APP_HOST) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          keep_binaries = true;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // If binaries/chrome are at system-level, we can discard them at
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // user-level...
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!machine_state.GetProductState(
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  true,  // system-level
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  BrowserDistribution::CHROME_BROWSER) &&
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              !machine_state.GetProductState(
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  true,  // system-level
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  BrowserDistribution::CHROME_BINARIES)) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // ... otherwise keep them.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            keep_binaries = true;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The product is being uninstalled.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!keep_binaries &&
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        machine_state.GetProductState(system_install(),
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      BrowserDistribution::CHROME_BINARIES)) {
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Product* p = AddProductFromPreferences(
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          BrowserDistribution::CHROME_BINARIES, prefs, machine_state);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              << " distribution: " << p->distribution()->GetDisplayName();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserDistribution* operand = NULL;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_uninstall) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operation_ = UNINSTALL;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!prefs.is_multi_install()) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For a single-install, the current browser dist is the operand.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operand = BrowserDistribution::GetDistribution();
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operation_ = SINGLE_INSTALL_OR_UPDATE;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (IsMultiInstallUpdate(prefs, machine_state)) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Updates driven by Google Update take place under the multi-installer's
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // app guid.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operand = multi_package_distribution_;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operation_ = MULTI_UPDATE;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operation_ = MULTI_INSTALL;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initial, over, and un-installs will take place under one of the
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // product app guids (Chrome, Chrome Frame, App Host, or Binaries, in order of
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preference).
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (operand == NULL) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserDistribution::Type operand_distribution_type =
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserDistribution::CHROME_BINARIES;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (prefs.install_chrome())
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operand_distribution_type = BrowserDistribution::CHROME_BROWSER;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (prefs.install_chrome_frame())
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operand_distribution_type = BrowserDistribution::CHROME_FRAME;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (prefs.install_chrome_app_launcher())
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operand_distribution_type = BrowserDistribution::CHROME_APP_HOST;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operand = BrowserDistribution::GetSpecificDistribution(
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        operand_distribution_type);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_key_ = operand->GetStateKey();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_type_ = operand->GetType();
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse --critical-update-version=W.X.Y.Z
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string critical_version_value(
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.GetSwitchValueASCII(switches::kCriticalUpdateVersion));
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  critical_update_version_ = Version(critical_version_value);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::set_level(Level level) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  level_ = level;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (level) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case USER_LEVEL:
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_key_ = HKEY_CURRENT_USER;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYSTEM_LEVEL:
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_key_ = HKEY_LOCAL_MACHINE;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(level == UNKNOWN_LEVEL);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      level_ = UNKNOWN_LEVEL;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_key_ = NULL;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::set_package_type(PackageType type) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  package_type_ = type;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SINGLE_PACKAGE:
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      multi_package_distribution_ = NULL;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MULTI_PACKAGE:
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      multi_package_distribution_ =
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          BrowserDistribution::GetSpecificDistribution(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              BrowserDistribution::CHROME_BINARIES);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(type == UNKNOWN_PACKAGE_TYPE);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      package_type_ = UNKNOWN_PACKAGE_TYPE;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      multi_package_distribution_ = NULL;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the Chrome binaries directory for multi-install or |dist|'s directory
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// otherwise.
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath InstallerState::GetDefaultProductInstallPath(
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserDistribution* dist) const {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(dist);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(package_type_ != UNKNOWN_PACKAGE_TYPE);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (package_type_ == SINGLE_PACKAGE) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetChromeInstallPath(system_install(), dist);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetChromeInstallPath(system_install(),
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserDistribution::GetSpecificDistribution(
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            BrowserDistribution::CHROME_BINARIES));
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Evaluates a product's eligibility for participation in this operation.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We never expect these checks to fail, hence they all terminate the process in
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// debug builds.  See the log messages for details.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::CanAddProduct(const Product& product,
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const base::FilePath* product_dir) const {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (package_type_) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SINGLE_PACKAGE:
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!products_.empty()) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "Cannot process more than one single-install product.";
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MULTI_PACKAGE:
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!product.HasOption(kOptionMultiInstall)) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "Cannot process a single-install product with a "
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       "multi-install state.";
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (FindProduct(product.distribution()->GetType()) != NULL) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "Cannot process more than one product of the same type.";
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!target_path_.empty()) {
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::FilePath default_dir;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (product_dir == NULL)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          default_dir = GetDefaultProductInstallPath(product.distribution());
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!base::FilePath::CompareEqualIgnoreCase(
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (product_dir == NULL ? default_dir : *product_dir).value(),
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                target_path_.value())) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LOG(DFATAL) << "Cannot process products in different directories.";
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_EQ(UNKNOWN_PACKAGE_TYPE, package_type_);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adds |product|, installed in |product_dir| to this object's collection.  If
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |product_dir| is NULL, the product's default install location is used.
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns NULL if |product| is incompatible with this object.  Otherwise,
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returns a pointer to the product (ownership is held by this object).
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Product* InstallerState::AddProductInDirectory(
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath* product_dir,
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<Product>* product) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(product != NULL);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(product->get() != NULL);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Product& the_product = *product->get();
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanAddProduct(the_product, product_dir))
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (package_type_ == UNKNOWN_PACKAGE_TYPE) {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_package_type(the_product.HasOption(kOptionMultiInstall) ?
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         MULTI_PACKAGE : SINGLE_PACKAGE);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (target_path_.empty()) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (product_dir == NULL)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      target_path_ = GetDefaultProductInstallPath(the_product.distribution());
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      target_path_ = *product_dir;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_key_.empty())
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_key_ = the_product.distribution()->GetStateKey();
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  products_.push_back(product->release());
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return products_[products_.size() - 1];
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Product* InstallerState::AddProduct(scoped_ptr<Product>* product) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddProductInDirectory(NULL, product);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adds a product of type |distribution_type| constructed on the basis of
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |prefs|, setting this object's msi flag if the product is represented in
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |machine_state| and is msi-installed.  Returns the product that was added,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or NULL if |state| is incompatible with this object.  Ownership is not passed
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the caller.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Product* InstallerState::AddProductFromPreferences(
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserDistribution::Type distribution_type,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const MasterPreferences& prefs,
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const InstallationState& machine_state) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Product> product_ptr(
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new Product(BrowserDistribution::GetSpecificDistribution(
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          distribution_type)));
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  product_ptr->InitializeFromPreferences(prefs);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Product* product = AddProductInDirectory(NULL, &product_ptr);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (product != NULL && !msi_) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProductState* product_state = machine_state.GetProductState(
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        system_install(), distribution_type);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (product_state != NULL)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      msi_ = product_state->is_msi();
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return product;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Product* InstallerState::AddProductFromState(
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserDistribution::Type type,
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProductState& state) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Product> product_ptr(
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new Product(BrowserDistribution::GetSpecificDistribution(type)));
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  product_ptr->InitializeFromUninstallCommand(state.uninstall_command());
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Strip off <version>/Installer/setup.exe; see GetInstallerDirectory().
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath product_dir =
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      state.GetSetupPath().DirName().DirName().DirName();
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Product* product = AddProductInDirectory(&product_dir, &product_ptr);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (product != NULL)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msi_ |= state.is_msi();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return product;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::system_install() const {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(level_ == USER_LEVEL || level_ == SYSTEM_LEVEL);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return level_ == SYSTEM_LEVEL;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::is_multi_install() const {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(package_type_ == SINGLE_PACKAGE || package_type_ == MULTI_PACKAGE);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return package_type_ != SINGLE_PACKAGE;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::RemoveProduct(const Product* product) {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<Product>::iterator it =
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::find(products_.begin(), products_.end(), product);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != products_.end()) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    products_.weak_erase(it);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Product* InstallerState::FindProduct(
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserDistribution::Type distribution_type) const {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Products::const_iterator scan = products_.begin(), end = products_.end();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       scan != end; ++scan) {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if ((*scan)->is_type(distribution_type))
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       return *scan;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Version* InstallerState::GetCurrentVersion(
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const InstallationState& machine_state) const {
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!products_.empty());
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Version> current_version;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we're doing a multi-install, the current version may be either an
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // existing multi or an existing single product that is being migrated
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in place (i.e., Chrome).  In the latter case, there is no existing
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CHROME_BINARIES installation so we need to search for the product.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserDistribution::Type prod_type;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (package_type_ == MULTI_PACKAGE) {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prod_type = BrowserDistribution::CHROME_BINARIES;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (machine_state.GetProductState(level_ == SYSTEM_LEVEL,
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      prod_type) == NULL) {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Search for a product on which we're operating that is installed in our
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // target directory.
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Products::const_iterator end = products().end();
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (Products::const_iterator scan = products().begin(); scan != end;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ++scan) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserDistribution::Type product_type =
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (*scan)->distribution()->GetType();
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const ProductState* state =
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            machine_state.GetProductState(level_ == SYSTEM_LEVEL, product_type);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (state != NULL && target_path_.IsParent(state->GetSetupPath())) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          prod_type = product_type;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prod_type = products_[0]->distribution()->GetType();
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ProductState* product_state =
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      machine_state.GetProductState(level_ == SYSTEM_LEVEL, prod_type);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (product_state != NULL) {
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Version* version = NULL;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Be aware that there might be a pending "new_chrome.exe" already in the
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // installation path.  If so, we use old_version, which holds the version of
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "chrome.exe" itself.
5687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (base::PathExists(target_path().Append(kChromeNewExe)))
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = product_state->old_version();
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (version == NULL)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = &product_state->version();
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_version.reset(new Version(*version));
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return current_version.release();
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Version InstallerState::DetermineCriticalVersion(
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Version* current_version,
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Version& new_version) const {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(current_version == NULL || current_version->IsValid());
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(new_version.IsValid());
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (critical_update_version_.IsValid() &&
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (current_version == NULL ||
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (current_version->CompareTo(critical_update_version_) < 0)) &&
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_version.CompareTo(critical_update_version_) >= 0) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return critical_update_version_;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Version();
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::IsChromeFrameRunning(
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const InstallationState& machine_state) const {
5964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AnyExistsAndIsInUse(machine_state, CHROME_FRAME_DLL);
5974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
5984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool InstallerState::AreBinariesInUse(
6004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const InstallationState& machine_state) const {
6014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AnyExistsAndIsInUse(
6024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      machine_state,
603a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      (CHROME_FRAME_HELPER_EXE | CHROME_FRAME_HELPER_DLL |
604a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       CHROME_FRAME_DLL | CHROME_DLL));
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath InstallerState::GetInstallerDirectory(
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Version& version) const {
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return target_path().Append(ASCIIToWide(version.GetString()))
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append(kInstallerDir);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool InstallerState::IsFileInUse(const base::FilePath& file) {
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call CreateFile with a share mode of 0 which should cause this to fail
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with ERROR_SHARING_VIOLATION if the file exists and is in-use.
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !base::win::ScopedHandle(CreateFile(file.value().c_str(),
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             GENERIC_WRITE, 0, NULL,
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             OPEN_EXISTING, 0, 0)).IsValid();
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
622a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void InstallerState::Clear() {
623a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  operation_ = UNINITIALIZED;
624a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  target_path_.clear();
625a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  state_key_.clear();
626a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  state_type_ = BrowserDistribution::CHROME_BROWSER;
627a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  products_.clear();
628a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  multi_package_distribution_ = NULL;
629a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  critical_update_version_ = base::Version();
630a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  level_ = UNKNOWN_LEVEL;
631a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  package_type_ = UNKNOWN_PACKAGE_TYPE;
632a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  root_key_ = NULL;
633a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  msi_ = false;
634a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  verbose_logging_ = false;
635a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ensure_google_update_present_ = false;
636a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
637a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
6384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool InstallerState::AnyExistsAndIsInUse(
6394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const InstallationState& machine_state,
6404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    uint32 file_bits) const {
6414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static const wchar_t* const kBinaryFileNames[] = {
642a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    kChromeDll,
6434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    kChromeFrameDll,
644a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    kChromeFrameHelperDll,
6454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    kChromeFrameHelperExe,
6464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  };
6474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_NE(file_bits, 0U);
6484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_LT(file_bits, 1U << NUM_BINARIES);
649a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  COMPILE_ASSERT(CHROME_DLL == 1, no_youre_out_of_order);
650a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  COMPILE_ASSERT(CHROME_FRAME_DLL == 2, no_youre_out_of_order);
651a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  COMPILE_ASSERT(CHROME_FRAME_HELPER_DLL == 4, no_youre_out_of_order);
652a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  COMPILE_ASSERT(CHROME_FRAME_HELPER_EXE == 8, no_youre_out_of_order);
6534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Check only for the current version (i.e., the version we are upgrading
6554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // _from_). Later versions from pending in-use updates need not be checked
6564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // since the current version is guaranteed to be in use if any such are.
6574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool in_use = false;
6584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_ptr<Version> current_version(GetCurrentVersion(machine_state));
6594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!current_version)
6604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
6614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::FilePath directory(
6624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      target_path().AppendASCII(current_version->GetString()));
6634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (int i = 0; i < NUM_BINARIES; ++i) {
6644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!(file_bits & (1U << i)))
6654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      continue;
6664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::FilePath file(directory.Append(kBinaryFileNames[i]));
6674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (base::PathExists(file) && IsFileInUse(file))
6684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return true;
6694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
6704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return false;
6714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
6724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::GetExistingExeVersions(
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<std::string>* existing_versions) const {
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const wchar_t* const kChromeFilenames[] = {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    installer::kChromeExe,
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    installer::kChromeNewExe,
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    installer::kChromeOldExe,
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < arraysize(kChromeFilenames); ++i) {
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath chrome_exe(target_path().Append(kChromeFilenames[i]));
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<FileVersionInfo> file_version_info(
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FileVersionInfo::CreateFileVersionInfo(chrome_exe));
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_version_info) {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string16 version_string = file_version_info->file_version();
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!version_string.empty() && IsStringASCII(version_string))
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        existing_versions->insert(WideToASCII(version_string));
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::RemoveOldVersionDirectories(
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Version& new_version,
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Version* existing_version,
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& temp_path) const {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Version version;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WorkItem> item;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> existing_version_strings;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  existing_version_strings.insert(new_version.GetString());
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (existing_version)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    existing_version_strings.insert(existing_version->GetString());
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure not to delete any version dir that is "referenced" by an existing
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chrome executable.
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetExistingExeVersions(&existing_version_strings);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to delete all directories that are not in the set we care to keep.
711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::FileEnumerator version_enum(target_path(), false,
712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    base::FileEnumerator::DIRECTORIES);
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (base::FilePath next_version = version_enum.Next(); !next_version.empty();
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       next_version = version_enum.Next()) {
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath dir_name(next_version.BaseName());
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    version = Version(WideToASCII(dir_name.value()));
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Delete the version folder if it is less than the new version and not
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // equal to the old version (if we have an old version).
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (version.IsValid() &&
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        existing_version_strings.count(version.GetString()) == 0) {
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note: temporarily log old version deletion at ERROR level to make it
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // more likely we see this in the installer log.
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Deleting old version directory: " << next_version.value();
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Attempt to recursively delete the old version dir.
7267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      bool delete_succeeded = base::DeleteFile(next_version, true);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note: temporarily log old version deletion at ERROR level to make it
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // more likely we see this in the installer log.
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG_IF(ERROR, !delete_succeeded)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "Failed to delete old version directory: " << next_version.value();
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void InstallerState::AddComDllList(
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<base::FilePath>* com_dll_list) const {
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::for_each(products_.begin(), products_.end(),
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                std::bind2nd(std::mem_fun(&Product::AddComDllList),
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             com_dll_list));
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::SetChannelFlags(bool set,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     ChannelInfo* channel_info) const {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool modified = false;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Products::const_iterator scan = products_.begin(), end = products_.end();
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       scan != end; ++scan) {
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     modified |= (*scan)->SetChannelFlags(set, channel_info);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return modified;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::UpdateStage(installer::InstallerStage stage) const {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InstallUtil::UpdateInstallerStage(system_install(), state_key_, stage);
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::UpdateChannels() const {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (operation_ != MULTI_INSTALL && operation_ != MULTI_UPDATE) {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "InstallerState::UpdateChannels noop: " << operation_;
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the "ap" value for the product being installed/updated.  We get the
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // current value from the registry since the InstallationState instance used
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by the bulk of the installer does not track changes made by UpdateStage.
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the app's ClientState key if it doesn't exist.
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChannelInfo channel_info;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::RegKey state_key;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LONG result = state_key.Create(root_key_, state_key_.c_str(),
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 KEY_QUERY_VALUE | KEY_SET_VALUE);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERROR_SUCCESS) {
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_info.Initialize(state_key);
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is a multi-install product.
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool modified = channel_info.SetMultiInstall(true);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add the appropriate modifiers for all products and their options.
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modified |= SetChannelFlags(true, &channel_info);
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "ap: " << channel_info.value();
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Write the results if needed.
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (modified)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_info.Write(&state_key);
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Remove the -stage: modifier since we don't want to propagate that to the
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // other app_guids.
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_info.SetStage(NULL);
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Synchronize the other products and the package with this one.
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChannelInfo other_info;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < BrowserDistribution::NUM_TYPES; ++i) {
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserDistribution::Type type =
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<BrowserDistribution::Type>(i);
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Skip the app_guid we started with.
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (type == state_type_)
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserDistribution* dist = NULL;
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Always operate on the binaries.
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i == BrowserDistribution::CHROME_BINARIES) {
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dist = multi_package_distribution_;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const Product* product = FindProduct(type);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Skip this one if it's for a product we're not operating on.
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (product == NULL)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dist = product->distribution();
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = state_key.Create(root_key_, dist->GetStateKey().c_str(),
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                KEY_QUERY_VALUE | KEY_SET_VALUE);
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result == ERROR_SUCCESS) {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        other_info.Initialize(state_key);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!other_info.Equals(channel_info))
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          channel_info.Write(&state_key);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "Failed opening key " << dist->GetStateKey()
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << " to update app channels; result: " << result;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed opening key " << state_key_
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " to update app channels; result: " << result;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::WriteInstallerResult(
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InstallStatus status,
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int string_resource_id,
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::wstring* const launch_cmd) const {
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use a no-rollback list since this is a best-effort deal.
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WorkItemList> install_list(
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WorkItem::CreateNoRollbackWorkItemList());
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool system_install = this->system_install();
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write the value for all products upon which we're operating.
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Products::const_iterator end = products().end();
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Products::const_iterator scan = products().begin(); scan != end;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++scan) {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InstallUtil::AddInstallerResultItems(
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        system_install, (*scan)->distribution()->GetStateKey(), status,
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string_resource_id, launch_cmd, install_list.get());
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // And for the binaries if this is a multi-install.
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_multi_install()) {
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InstallUtil::AddInstallerResultItems(
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        system_install, multi_package_binaries_distribution()->GetStateKey(),
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        status, string_resource_id, launch_cmd, install_list.get());
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!install_list->Do())
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to record installer error information in registry.";
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool InstallerState::RequiresActiveSetup() const {
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return system_install() && FindProduct(BrowserDistribution::CHROME_BROWSER);
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace installer
857