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), 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) multi_package_distribution_(NULL), 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) level_(UNKNOWN_LEVEL), 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) package_type_(UNKNOWN_PACKAGE_TYPE), 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_type_(BrowserDistribution::CHROME_BROWSER), 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), 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) multi_package_distribution_(NULL), 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) level_(UNKNOWN_LEVEL), 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) package_type_(UNKNOWN_PACKAGE_TYPE), 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_type_(BrowserDistribution::CHROME_BROWSER), 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) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool pref_bool; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!prefs.GetBool(master_preferences::kSystemLevel, &pref_bool)) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pref_bool = false; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_level(pref_bool ? SYSTEM_LEVEL : USER_LEVEL); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!prefs.GetBool(master_preferences::kVerboseLogging, &verbose_logging_)) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verbose_logging_ = false; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!prefs.GetBool(master_preferences::kMultiInstall, &pref_bool)) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pref_bool = false; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_package_type(pref_bool ? MULTI_PACKAGE : SINGLE_PACKAGE); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!prefs.GetBool(master_preferences::kMsi, &msi_)) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msi_ = false; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ensure_google_update_present_ = 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.HasSwitch(installer::switches::kEnsureGoogleUpdatePresent); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_uninstall = command_line.HasSwitch(switches::kUninstall); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prefs.install_chrome()) { 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Product* p = AddProductFromPreferences( 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution::CHROME_BROWSER, prefs, machine_state); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << (is_uninstall ? "Uninstall" : "Install") 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " distribution: " << p->distribution()->GetAppShortCutName(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prefs.install_chrome_frame()) { 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Product* p = AddProductFromPreferences( 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution::CHROME_FRAME, prefs, machine_state); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << (is_uninstall ? "Uninstall" : "Install") 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " distribution: " << p->distribution()->GetAppShortCutName(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (prefs.install_chrome_app_launcher()) { 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Product* p = AddProductFromPreferences( 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution::CHROME_APP_HOST, prefs, machine_state); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << (is_uninstall ? "Uninstall" : "Install") 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " distribution: " << p->distribution()->GetAppShortCutName(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_uninstall && is_multi_install()) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool need_binaries = false; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FindProduct(BrowserDistribution::CHROME_APP_HOST)) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // App Host will happily use Chrome at system level, or binaries at system 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // level, even if app host is user level. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* chrome_state = machine_state.GetProductState( 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, // system level 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BROWSER); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If Chrome is at system-level, multi- or otherwise. We'll use it. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!chrome_state) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* binaries_state = machine_state.GetProductState( 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, // system level 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BINARIES); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!binaries_state) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_binaries = true; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome/Chrome Frame multi need Binaries at their own level. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FindProduct(BrowserDistribution::CHROME_BROWSER)) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_binaries = true; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FindProduct(BrowserDistribution::CHROME_FRAME)) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_binaries = true; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (need_binaries && !FindProduct(BrowserDistribution::CHROME_BINARIES)) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force binaries to be installed/updated. 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Product* p = AddProductFromPreferences( 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution::CHROME_BINARIES, prefs, machine_state); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Install distribution: " 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << p->distribution()->GetAppShortCutName(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_uninstall && prefs.is_multi_install()) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FindProduct(BrowserDistribution::CHROME_BROWSER)) { 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Uninstall each product of type |type| listed below based on the 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // presence or absence of |switch_name| in that product's uninstall 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // command. 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const struct { 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution::Type type; 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* switch_name; 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool switch_expected; 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } conditional_additions[] = { 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If Chrome Frame is installed in Ready Mode, remove it with Chrome. 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { BrowserDistribution::CHROME_FRAME, 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switches::kChromeFrameReadyMode, 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) true }, 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the App Host is installed, but not the App Launcher, remove it 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // with Chrome. Note however that for system-level Chrome uninstalls, 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // any installed user-level App Host will remain even if there is no 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // App Launcher present (the orphaned app_host.exe will prompt the user 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for further action when executed). 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { BrowserDistribution::CHROME_APP_HOST, 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switches::kChromeAppLauncher, 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false }, 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < arraysize(conditional_additions); ++i) { 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ProductState* product_state = machine_state.GetProductState( 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) system_install(), conditional_additions[i].type); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (product_state != NULL && 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) product_state->uninstall_command().HasSwitch( 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) conditional_additions[i].switch_name) == 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) conditional_additions[i].switch_expected && 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !FindProduct(conditional_additions[i].type)) { 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Product* p = AddProductFromPreferences( 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) conditional_additions[i].type, prefs, machine_state); 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(1) << "Uninstall distribution: " 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << p->distribution()->GetAppShortCutName(); 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool keep_binaries = false; 217bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Look for a multi-install product that is not the binaries and that is not 218bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // being uninstalled. If not found, binaries are uninstalled too. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::Type type = 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<BrowserDistribution::Type>(i); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == BrowserDistribution::CHROME_BINARIES) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 226bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch const ProductState* product_state = 227bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch machine_state.GetProductState(system_install(), type); 228bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch if (product_state == NULL) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The product is not installed. 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 233bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch if (!product_state->is_multi_install() && 234bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch type != BrowserDistribution::CHROME_BROWSER) { 235bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // The product is not sharing the binaries. It is ordinarily impossible 236bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // for single-install Chrome to be installed along with any 237bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // multi-install product. Treat single-install Chrome the same as any 238bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // multi-install product just in case the impossible happens. 239bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch continue; 240bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 241bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The product is installed. 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FindProduct(type)) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The product is not being uninstalled. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type != BrowserDistribution::CHROME_APP_HOST) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keep_binaries = true; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If binaries/chrome are at system-level, we can discard them at 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // user-level... 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!machine_state.GetProductState( 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, // system-level 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BROWSER) && 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !machine_state.GetProductState( 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, // system-level 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BINARIES)) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ... otherwise keep them. 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keep_binaries = true; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The product is being uninstalled. 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!keep_binaries && 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) machine_state.GetProductState(system_install(), 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution::CHROME_BINARIES)) { 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Product* p = AddProductFromPreferences( 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution::CHROME_BINARIES, prefs, machine_state); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << (is_uninstall ? "Uninstall" : "Install") 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " distribution: " << p->distribution()->GetAppShortCutName(); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* operand = NULL; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_uninstall) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operation_ = UNINSTALL; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!prefs.is_multi_install()) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For a single-install, the current browser dist is the operand. 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operand = BrowserDistribution::GetDistribution(); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operation_ = SINGLE_INSTALL_OR_UPDATE; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (IsMultiInstallUpdate(prefs, machine_state)) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Updates driven by Google Update take place under the multi-installer's 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // app guid. 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operand = multi_package_distribution_; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operation_ = MULTI_UPDATE; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operation_ = MULTI_INSTALL; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initial, over, and un-installs will take place under one of the 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // product app guids (Chrome, Chrome Frame, App Host, or Binaries, in order of 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // preference). 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (operand == NULL) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::Type operand_distribution_type = 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BINARIES; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prefs.install_chrome()) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operand_distribution_type = BrowserDistribution::CHROME_BROWSER; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (prefs.install_chrome_frame()) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operand_distribution_type = BrowserDistribution::CHROME_FRAME; 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else if (prefs.install_chrome_app_launcher()) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operand_distribution_type = BrowserDistribution::CHROME_APP_HOST; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operand = BrowserDistribution::GetSpecificDistribution( 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operand_distribution_type); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_key_ = operand->GetStateKey(); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_type_ = operand->GetType(); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse --critical-update-version=W.X.Y.Z 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string critical_version_value( 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.GetSwitchValueASCII(switches::kCriticalUpdateVersion)); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) critical_update_version_ = Version(critical_version_value); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::set_level(Level level) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) level_ = level; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (level) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case USER_LEVEL: 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root_key_ = HKEY_CURRENT_USER; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYSTEM_LEVEL: 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root_key_ = HKEY_LOCAL_MACHINE; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(level == UNKNOWN_LEVEL); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) level_ = UNKNOWN_LEVEL; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root_key_ = NULL; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::set_package_type(PackageType type) { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) package_type_ = type; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SINGLE_PACKAGE: 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) multi_package_distribution_ = NULL; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MULTI_PACKAGE: 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) multi_package_distribution_ = 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::GetSpecificDistribution( 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BINARIES); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(type == UNKNOWN_PACKAGE_TYPE); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) package_type_ = UNKNOWN_PACKAGE_TYPE; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) multi_package_distribution_ = NULL; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the Chrome binaries directory for multi-install or |dist|'s directory 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// otherwise. 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath InstallerState::GetDefaultProductInstallPath( 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* dist) const { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(dist); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(package_type_ != UNKNOWN_PACKAGE_TYPE); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (package_type_ == SINGLE_PACKAGE) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetChromeInstallPath(system_install(), dist); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetChromeInstallPath(system_install(), 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::GetSpecificDistribution( 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BINARIES)); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Evaluates a product's eligibility for participation in this operation. 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We never expect these checks to fail, hence they all terminate the process in 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// debug builds. See the log messages for details. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::CanAddProduct(const Product& product, 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath* product_dir) const { 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (package_type_) { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SINGLE_PACKAGE: 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!products_.empty()) { 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Cannot process more than one single-install product."; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MULTI_PACKAGE: 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!product.HasOption(kOptionMultiInstall)) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Cannot process a single-install product with a " 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "multi-install state."; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FindProduct(product.distribution()->GetType()) != NULL) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Cannot process more than one product of the same type."; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!target_path_.empty()) { 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath default_dir; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (product_dir == NULL) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_dir = GetDefaultProductInstallPath(product.distribution()); 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!base::FilePath::CompareEqualIgnoreCase( 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (product_dir == NULL ? default_dir : *product_dir).value(), 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_path_.value())) { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Cannot process products in different directories."; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(UNKNOWN_PACKAGE_TYPE, package_type_); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adds |product|, installed in |product_dir| to this object's collection. If 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |product_dir| is NULL, the product's default install location is used. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns NULL if |product| is incompatible with this object. Otherwise, 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returns a pointer to the product (ownership is held by this object). 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Product* InstallerState::AddProductInDirectory( 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath* product_dir, 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<Product>* product) { 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(product != NULL); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(product->get() != NULL); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product& the_product = *product->get(); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CanAddProduct(the_product, product_dir)) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (package_type_ == UNKNOWN_PACKAGE_TYPE) { 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_package_type(the_product.HasOption(kOptionMultiInstall) ? 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MULTI_PACKAGE : SINGLE_PACKAGE); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (target_path_.empty()) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (product_dir == NULL) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_path_ = GetDefaultProductInstallPath(the_product.distribution()); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_path_ = *product_dir; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_key_.empty()) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_key_ = the_product.distribution()->GetStateKey(); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) products_.push_back(product->release()); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return products_[products_.size() - 1]; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Product* InstallerState::AddProduct(scoped_ptr<Product>* product) { 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddProductInDirectory(NULL, product); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adds a product of type |distribution_type| constructed on the basis of 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |prefs|, setting this object's msi flag if the product is represented in 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |machine_state| and is msi-installed. Returns the product that was added, 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or NULL if |state| is incompatible with this object. Ownership is not passed 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the caller. 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Product* InstallerState::AddProductFromPreferences( 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::Type distribution_type, 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const MasterPreferences& prefs, 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const InstallationState& machine_state) { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Product> product_ptr( 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new Product(BrowserDistribution::GetSpecificDistribution( 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) distribution_type))); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) product_ptr->InitializeFromPreferences(prefs); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Product* product = AddProductInDirectory(NULL, &product_ptr); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (product != NULL && !msi_) { 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* product_state = machine_state.GetProductState( 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_install(), distribution_type); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (product_state != NULL) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msi_ = product_state->is_msi(); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return product; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Product* InstallerState::AddProductFromState( 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::Type type, 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState& state) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Product> product_ptr( 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new Product(BrowserDistribution::GetSpecificDistribution(type))); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) product_ptr->InitializeFromUninstallCommand(state.uninstall_command()); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Strip off <version>/Installer/setup.exe; see GetInstallerDirectory(). 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath product_dir = 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.GetSetupPath().DirName().DirName().DirName(); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Product* product = AddProductInDirectory(&product_dir, &product_ptr); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (product != NULL) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msi_ |= state.is_msi(); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return product; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::system_install() const { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(level_ == USER_LEVEL || level_ == SYSTEM_LEVEL); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return level_ == SYSTEM_LEVEL; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::is_multi_install() const { 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(package_type_ == SINGLE_PACKAGE || package_type_ == MULTI_PACKAGE); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return package_type_ != SINGLE_PACKAGE; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::RemoveProduct(const Product* product) { 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<Product>::iterator it = 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find(products_.begin(), products_.end(), product); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != products_.end()) { 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) products_.weak_erase(it); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Product* InstallerState::FindProduct( 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::Type distribution_type) const { 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Products::const_iterator scan = products_.begin(), end = products_.end(); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scan != end; ++scan) { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*scan)->is_type(distribution_type)) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *scan; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Version* InstallerState::GetCurrentVersion( 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const InstallationState& machine_state) const { 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!products_.empty()); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Version> current_version; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're doing a multi-install, the current version may be either an 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // existing multi or an existing single product that is being migrated 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in place (i.e., Chrome). In the latter case, there is no existing 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CHROME_BINARIES installation so we need to search for the product. 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::Type prod_type; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (package_type_ == MULTI_PACKAGE) { 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prod_type = BrowserDistribution::CHROME_BINARIES; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (machine_state.GetProductState(level_ == SYSTEM_LEVEL, 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prod_type) == NULL) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Search for a product on which we're operating that is installed in our 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // target directory. 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Products::const_iterator end = products().end(); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Products::const_iterator scan = products().begin(); scan != end; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++scan) { 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::Type product_type = 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*scan)->distribution()->GetType(); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* state = 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) machine_state.GetProductState(level_ == SYSTEM_LEVEL, product_type); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state != NULL && target_path_.IsParent(state->GetSetupPath())) { 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prod_type = product_type; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prod_type = products_[0]->distribution()->GetType(); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* product_state = 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) machine_state.GetProductState(level_ == SYSTEM_LEVEL, prod_type); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (product_state != NULL) { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Version* version = NULL; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Be aware that there might be a pending "new_chrome.exe" already in the 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // installation path. If so, we use old_version, which holds the version of 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "chrome.exe" itself. 5667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (base::PathExists(target_path().Append(kChromeNewExe))) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version = product_state->old_version(); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version == NULL) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version = &product_state->version(); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_version.reset(new Version(*version)); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current_version.release(); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Version InstallerState::DetermineCriticalVersion( 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Version* current_version, 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Version& new_version) const { 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(current_version == NULL || current_version->IsValid()); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(new_version.IsValid()); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (critical_update_version_.IsValid() && 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (current_version == NULL || 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (current_version->CompareTo(critical_update_version_) < 0)) && 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_version.CompareTo(critical_update_version_) >= 0) { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return critical_update_version_; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Version(); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::IsChromeFrameRunning( 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const InstallationState& machine_state) const { 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We check only for the current version (e.g. the version we are upgrading 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // _from_). We don't need to check interstitial versions if any (as would 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // occur in the case of multiple updates) since if they are in use, we are 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // guaranteed that the current version is in use too. 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool in_use = false; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Version> current_version(GetCurrentVersion(machine_state)); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_version != NULL) { 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath cf_install_path( 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_path().AppendASCII(current_version->GetString()) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Append(kChromeFrameDll)); 6047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch in_use = base::PathExists(cf_install_path) && 6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsFileInUse(cf_install_path); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return in_use; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath InstallerState::GetInstallerDirectory( 6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Version& version) const { 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return target_path().Append(ASCIIToWide(version.GetString())) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Append(kInstallerDir); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool InstallerState::IsFileInUse(const base::FilePath& file) { 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call CreateFile with a share mode of 0 which should cause this to fail 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with ERROR_SHARING_VIOLATION if the file exists and is in-use. 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !base::win::ScopedHandle(CreateFile(file.value().c_str(), 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GENERIC_WRITE, 0, NULL, 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OPEN_EXISTING, 0, 0)).IsValid(); 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::GetExistingExeVersions( 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string>* existing_versions) const { 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const wchar_t* const kChromeFilenames[] = { 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::kChromeExe, 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::kChromeNewExe, 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::kChromeOldExe, 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < arraysize(kChromeFilenames); ++i) { 6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_exe(target_path().Append(kChromeFilenames[i])); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<FileVersionInfo> file_version_info( 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileVersionInfo::CreateFileVersionInfo(chrome_exe)); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file_version_info) { 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 version_string = file_version_info->file_version(); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!version_string.empty() && IsStringASCII(version_string)) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) existing_versions->insert(WideToASCII(version_string)); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::RemoveOldVersionDirectories( 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Version& new_version, 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Version* existing_version, 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& temp_path) const { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Version version; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<WorkItem> item; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string> existing_version_strings; 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) existing_version_strings.insert(new_version.GetString()); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (existing_version) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) existing_version_strings.insert(existing_version->GetString()); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure not to delete any version dir that is "referenced" by an existing 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome executable. 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetExistingExeVersions(&existing_version_strings); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to delete all directories that are not in the set we care to keep. 663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator version_enum(target_path(), false, 664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator::DIRECTORIES); 6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (base::FilePath next_version = version_enum.Next(); !next_version.empty(); 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_version = version_enum.Next()) { 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath dir_name(next_version.BaseName()); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version = Version(WideToASCII(dir_name.value())); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the version folder if it is less than the new version and not 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // equal to the old version (if we have an old version). 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version.IsValid() && 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) existing_version_strings.count(version.GetString()) == 0) { 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: temporarily log old version deletion at ERROR level to make it 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // more likely we see this in the installer log. 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Deleting old version directory: " << next_version.value(); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Attempt to recursively delete the old version dir. 6787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool delete_succeeded = base::DeleteFile(next_version, true); 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: temporarily log old version deletion at ERROR level to make it 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // more likely we see this in the installer log. 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, !delete_succeeded) 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Failed to delete old version directory: " << next_version.value(); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void InstallerState::AddComDllList( 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::FilePath>* com_dll_list) const { 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::for_each(products_.begin(), products_.end(), 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::bind2nd(std::mem_fun(&Product::AddComDllList), 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) com_dll_list)); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InstallerState::SetChannelFlags(bool set, 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelInfo* channel_info) const { 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool modified = false; 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Products::const_iterator scan = products_.begin(), end = products_.end(); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scan != end; ++scan) { 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modified |= (*scan)->SetChannelFlags(set, channel_info); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return modified; 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::UpdateStage(installer::InstallerStage stage) const { 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallUtil::UpdateInstallerStage(system_install(), state_key_, stage); 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::UpdateChannels() const { 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (operation_ != MULTI_INSTALL && operation_ != MULTI_UPDATE) { 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "InstallerState::UpdateChannels noop: " << operation_; 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the "ap" value for the product being installed/updated. We get the 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current value from the registry since the InstallationState instance used 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by the bulk of the installer does not track changes made by UpdateStage. 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the app's ClientState key if it doesn't exist. 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelInfo channel_info; 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::RegKey state_key; 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LONG result = state_key.Create(root_key_, state_key_.c_str(), 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_QUERY_VALUE | KEY_SET_VALUE); 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == ERROR_SUCCESS) { 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_info.Initialize(state_key); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is a multi-install product. 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool modified = channel_info.SetMultiInstall(true); 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the appropriate modifiers for all products and their options. 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modified |= SetChannelFlags(true, &channel_info); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "ap: " << channel_info.value(); 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write the results if needed. 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (modified) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_info.Write(&state_key); 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the -stage: modifier since we don't want to propagate that to the 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other app_guids. 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_info.SetStage(NULL); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Synchronize the other products and the package with this one. 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelInfo other_info; 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::Type type = 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<BrowserDistribution::Type>(i); 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip the app_guid we started with. 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == state_type_) 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* dist = NULL; 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Always operate on the binaries. 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == BrowserDistribution::CHROME_BINARIES) { 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dist = multi_package_distribution_; 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product* product = FindProduct(type); 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip this one if it's for a product we're not operating on. 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (product == NULL) 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dist = product->distribution(); 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = state_key.Create(root_key_, dist->GetStateKey().c_str(), 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_QUERY_VALUE | KEY_SET_VALUE); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == ERROR_SUCCESS) { 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_info.Initialize(state_key); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!other_info.Equals(channel_info)) 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_info.Write(&state_key); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed opening key " << dist->GetStateKey() 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " to update app channels; result: " << result; 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed opening key " << state_key_ 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " to update app channels; result: " << result; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallerState::WriteInstallerResult( 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallStatus status, 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int string_resource_id, 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring* const launch_cmd) const { 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD installer_result = 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (InstallUtil::GetInstallReturnCode(status) == 0) ? 0 : 1; 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use a no-rollback list since this is a best-effort deal. 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<WorkItemList> install_list( 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkItem::CreateNoRollbackWorkItemList()); 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool system_install = this->system_install(); 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write the value for all products upon which we're operating. 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Products::const_iterator end = products().end(); 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Products::const_iterator scan = products().begin(); scan != end; 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++scan) { 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallUtil::AddInstallerResultItems( 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_install, (*scan)->distribution()->GetStateKey(), status, 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_resource_id, launch_cmd, install_list.get()); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And for the binaries if this is a multi-install. 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_multi_install()) { 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallUtil::AddInstallerResultItems( 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_install, multi_package_binaries_distribution()->GetStateKey(), 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status, string_resource_id, launch_cmd, install_list.get()); 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!install_list->Do()) 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to record installer error information in registry."; 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool InstallerState::RequiresActiveSetup() const { 8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return system_install() && FindProduct(BrowserDistribution::CHROME_BROWSER); 8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace installer 811