product.cc revision a3f7b4e666c476898878fa745f637129375cd889
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/product.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/process/launch.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/chrome_app_host_operations.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/chrome_binaries_operations.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/chrome_browser_operations.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/chrome_browser_sxs_operations.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/chrome_frame_operations.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/google_update_constants.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/helper.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/install_util.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/master_preferences.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/master_preferences_constants.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/product_operations.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::RegKey;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using installer::MasterPreferences;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace installer {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Product::Product(BrowserDistribution* distribution)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : distribution_(distribution) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (distribution->GetType()) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BrowserDistribution::CHROME_BROWSER:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operations_.reset(InstallUtil::IsChromeSxSProcess() ?
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new ChromeBrowserSxSOperations() :
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new ChromeBrowserOperations());
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BrowserDistribution::CHROME_FRAME:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operations_.reset(new ChromeFrameOperations());
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BrowserDistribution::CHROME_APP_HOST:
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operations_.reset(new ChromeAppHostOperations());
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BrowserDistribution::CHROME_BINARIES:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operations_.reset(new ChromeBinariesOperations());
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unsupported BrowserDistribution::Type: "
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << distribution->GetType();
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Product::~Product() {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Product::InitializeFromPreferences(const MasterPreferences& prefs) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_->ReadOptions(prefs, &options_);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Product::InitializeFromUninstallCommand(
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CommandLine& uninstall_command) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_->ReadOptions(uninstall_command, &options_);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Product::GetUserDataPaths(std::vector<base::FilePath>* paths) const {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetChromeUserDataPaths(distribution_, paths);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Product::LaunchChrome(const base::FilePath& application_path) const {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = !application_path.empty();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine cmd(application_path.Append(installer::kChromeExe));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success = base::LaunchProcess(cmd, base::LaunchOptions(), NULL);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Product::LaunchChromeAndWait(const base::FilePath& application_path,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const CommandLine& options,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int32* exit_code) const {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (application_path.empty())
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine cmd(application_path.Append(installer::kChromeExe));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd.AppendArguments(options, false);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = false;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STARTUPINFOW si = { sizeof(si) };
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PROCESS_INFORMATION pi = {0};
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a writable copy of the command line string, since CreateProcess may
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // modify the string (insert \0 to separate the program from the arguments).
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring writable_command_line_string(cmd.GetCommandLineString());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::CreateProcess(cmd.GetProgram().value().c_str(),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       &writable_command_line_string[0],
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       &si, &pi)) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLOG(ERROR) << "Failed to launch: " << cmd.GetCommandLineString();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(pi.hThread);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD ret = ::WaitForSingleObject(pi.hProcess, INFINITE);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG_IF(ERROR, ret != WAIT_OBJECT_0)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Unexpected return value from WaitForSingleObject: " << ret;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (::GetExitCodeProcess(pi.hProcess, &ret)) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(ret != STILL_ACTIVE);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      success = true;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (exit_code)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *exit_code = ret;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PLOG(ERROR) << "GetExitCodeProcess failed";
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(pi.hProcess);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Product::SetMsiMarker(bool system_install, bool set) const {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegKey client_state_key;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LONG result = client_state_key.Open(reg_root,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      distribution_->GetStateKey().c_str(), KEY_READ | KEY_WRITE);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERROR_SUCCESS) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = client_state_key.WriteValue(google_update::kRegMSIField,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         set ? 1 : 0);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LOG_IF(ERROR, result != ERROR_SUCCESS) << "Failed to Open or Write MSI value"
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      "to client state key. error: " << result;
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return (result == ERROR_SUCCESS);
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Product::ShouldCreateUninstallEntry() const {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return operations_->ShouldCreateUninstallEntry(options_);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Product::AddKeyFiles(std::vector<base::FilePath>* key_files) const {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_->AddKeyFiles(options_, key_files);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Product::AddComDllList(std::vector<base::FilePath>* com_dll_list) const {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_->AddComDllList(options_, com_dll_list);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Product::AppendProductFlags(CommandLine* command_line) const {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_->AppendProductFlags(options_, command_line);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Product::AppendRenameFlags(CommandLine* command_line) const {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_->AppendRenameFlags(options_, command_line);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Product::SetChannelFlags(bool set, ChannelInfo* channel_info) const {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return operations_->SetChannelFlags(options_, set, channel_info);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Product::AddDefaultShortcutProperties(
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::FilePath& target_exe,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShellUtil::ShortcutProperties* properties) const {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return operations_->AddDefaultShortcutProperties(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      distribution_, target_exe, properties);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Product::LaunchUserExperiment(const base::FilePath& setup_path,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   InstallStatus status,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   bool system_level) const {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (distribution_->HasUserExperiments()) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "LaunchUserExperiment status: " << status << " product: "
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << distribution_->GetAppShortCutName()
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            << " system_level: " << system_level;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operations_->LaunchUserExperiment(
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        setup_path, options_, status, system_level);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace installer
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci