Home | History | Annotate | Download | only in util
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/installer/util/product.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/command_line.h"
     10 #include "base/logging.h"
     11 #include "base/process/launch.h"
     12 #include "base/win/registry.h"
     13 #include "chrome/installer/util/chrome_app_host_operations.h"
     14 #include "chrome/installer/util/chrome_binaries_operations.h"
     15 #include "chrome/installer/util/chrome_browser_operations.h"
     16 #include "chrome/installer/util/chrome_browser_sxs_operations.h"
     17 #include "chrome/installer/util/chrome_frame_operations.h"
     18 #include "chrome/installer/util/google_update_constants.h"
     19 #include "chrome/installer/util/helper.h"
     20 #include "chrome/installer/util/install_util.h"
     21 #include "chrome/installer/util/master_preferences.h"
     22 #include "chrome/installer/util/master_preferences_constants.h"
     23 #include "chrome/installer/util/product_operations.h"
     24 
     25 using base::win::RegKey;
     26 using installer::MasterPreferences;
     27 
     28 namespace installer {
     29 
     30 Product::Product(BrowserDistribution* distribution)
     31     : distribution_(distribution) {
     32   switch (distribution->GetType()) {
     33     case BrowserDistribution::CHROME_BROWSER:
     34       operations_.reset(InstallUtil::IsChromeSxSProcess() ?
     35           new ChromeBrowserSxSOperations() :
     36           new ChromeBrowserOperations());
     37       break;
     38     case BrowserDistribution::CHROME_FRAME:
     39       operations_.reset(new ChromeFrameOperations());
     40       break;
     41     case BrowserDistribution::CHROME_APP_HOST:
     42       operations_.reset(new ChromeAppHostOperations());
     43       break;
     44     case BrowserDistribution::CHROME_BINARIES:
     45       operations_.reset(new ChromeBinariesOperations());
     46       break;
     47     default:
     48       NOTREACHED() << "Unsupported BrowserDistribution::Type: "
     49                    << distribution->GetType();
     50   }
     51 }
     52 
     53 Product::~Product() {
     54 }
     55 
     56 void Product::InitializeFromPreferences(const MasterPreferences& prefs) {
     57   operations_->ReadOptions(prefs, &options_);
     58 }
     59 
     60 void Product::InitializeFromUninstallCommand(
     61     const CommandLine& uninstall_command) {
     62   operations_->ReadOptions(uninstall_command, &options_);
     63 }
     64 
     65 void Product::GetUserDataPaths(std::vector<base::FilePath>* paths) const {
     66   GetChromeUserDataPaths(distribution_, paths);
     67 }
     68 
     69 bool Product::LaunchChrome(const base::FilePath& application_path) const {
     70   bool success = !application_path.empty();
     71   if (success) {
     72     CommandLine cmd(application_path.Append(installer::kChromeExe));
     73     success = base::LaunchProcess(cmd, base::LaunchOptions(), NULL);
     74   }
     75   return success;
     76 }
     77 
     78 bool Product::LaunchChromeAndWait(const base::FilePath& application_path,
     79                                   const CommandLine& options,
     80                                   int32* exit_code) const {
     81   if (application_path.empty())
     82     return false;
     83 
     84   CommandLine cmd(application_path.Append(installer::kChromeExe));
     85   cmd.AppendArguments(options, false);
     86 
     87   bool success = false;
     88   STARTUPINFOW si = { sizeof(si) };
     89   PROCESS_INFORMATION pi = {0};
     90   // Create a writable copy of the command line string, since CreateProcess may
     91   // modify the string (insert \0 to separate the program from the arguments).
     92   std::wstring writable_command_line_string(cmd.GetCommandLineString());
     93   if (!::CreateProcess(cmd.GetProgram().value().c_str(),
     94                        &writable_command_line_string[0],
     95                        NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL,
     96                        &si, &pi)) {
     97     PLOG(ERROR) << "Failed to launch: " << cmd.GetCommandLineString();
     98   } else {
     99     ::CloseHandle(pi.hThread);
    100 
    101     DWORD ret = ::WaitForSingleObject(pi.hProcess, INFINITE);
    102     DLOG_IF(ERROR, ret != WAIT_OBJECT_0)
    103         << "Unexpected return value from WaitForSingleObject: " << ret;
    104     if (::GetExitCodeProcess(pi.hProcess, &ret)) {
    105       DCHECK(ret != STILL_ACTIVE);
    106       success = true;
    107       if (exit_code)
    108         *exit_code = ret;
    109     } else {
    110       PLOG(ERROR) << "GetExitCodeProcess failed";
    111     }
    112 
    113     ::CloseHandle(pi.hProcess);
    114   }
    115 
    116   return success;
    117 }
    118 
    119 bool Product::SetMsiMarker(bool system_install, bool set) const {
    120   HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
    121   RegKey client_state_key;
    122   LONG result = client_state_key.Open(reg_root,
    123       distribution_->GetStateKey().c_str(), KEY_READ | KEY_WRITE);
    124   if (result == ERROR_SUCCESS) {
    125     result = client_state_key.WriteValue(google_update::kRegMSIField,
    126                                          set ? 1 : 0);
    127   }
    128 
    129   LOG_IF(ERROR, result != ERROR_SUCCESS) << "Failed to Open or Write MSI value"
    130       "to client state key. error: " << result;
    131 
    132   return (result == ERROR_SUCCESS);
    133 }
    134 
    135 bool Product::ShouldCreateUninstallEntry() const {
    136   return operations_->ShouldCreateUninstallEntry(options_);
    137 }
    138 
    139 void Product::AddKeyFiles(std::vector<base::FilePath>* key_files) const {
    140   operations_->AddKeyFiles(options_, key_files);
    141 }
    142 
    143 void Product::AddComDllList(std::vector<base::FilePath>* com_dll_list) const {
    144   operations_->AddComDllList(options_, com_dll_list);
    145 }
    146 
    147 void Product::AppendProductFlags(CommandLine* command_line) const {
    148   operations_->AppendProductFlags(options_, command_line);
    149 }
    150 
    151 void Product::AppendRenameFlags(CommandLine* command_line) const {
    152   operations_->AppendRenameFlags(options_, command_line);
    153 }
    154 
    155 bool Product::SetChannelFlags(bool set, ChannelInfo* channel_info) const {
    156   return operations_->SetChannelFlags(options_, set, channel_info);
    157 }
    158 
    159 void Product::AddDefaultShortcutProperties(
    160     const base::FilePath& target_exe,
    161     ShellUtil::ShortcutProperties* properties) const {
    162   return operations_->AddDefaultShortcutProperties(
    163       distribution_, target_exe, properties);
    164 }
    165 
    166 void Product::LaunchUserExperiment(const base::FilePath& setup_path,
    167                                    InstallStatus status,
    168                                    bool system_level) const {
    169   if (distribution_->HasUserExperiments()) {
    170     VLOG(1) << "LaunchUserExperiment status: " << status << " product: "
    171             << distribution_->GetDisplayName()
    172             << " system_level: " << system_level;
    173     operations_->LaunchUserExperiment(
    174         setup_path, options_, status, system_level);
    175   }
    176 }
    177 
    178 }  // namespace installer
    179