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 bool Product::LaunchChrome(const base::FilePath& application_path) const {
     66   bool success = !application_path.empty();
     67   if (success) {
     68     CommandLine cmd(application_path.Append(installer::kChromeExe));
     69     success = base::LaunchProcess(cmd, base::LaunchOptions(), NULL);
     70   }
     71   return success;
     72 }
     73 
     74 bool Product::LaunchChromeAndWait(const base::FilePath& application_path,
     75                                   const CommandLine& options,
     76                                   int32* exit_code) const {
     77   if (application_path.empty())
     78     return false;
     79 
     80   CommandLine cmd(application_path.Append(installer::kChromeExe));
     81   cmd.AppendArguments(options, false);
     82 
     83   bool success = false;
     84   STARTUPINFOW si = { sizeof(si) };
     85   PROCESS_INFORMATION pi = {0};
     86   // Create a writable copy of the command line string, since CreateProcess may
     87   // modify the string (insert \0 to separate the program from the arguments).
     88   std::wstring writable_command_line_string(cmd.GetCommandLineString());
     89   if (!::CreateProcess(cmd.GetProgram().value().c_str(),
     90                        &writable_command_line_string[0],
     91                        NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL,
     92                        &si, &pi)) {
     93     PLOG(ERROR) << "Failed to launch: " << cmd.GetCommandLineString();
     94   } else {
     95     ::CloseHandle(pi.hThread);
     96 
     97     DWORD ret = ::WaitForSingleObject(pi.hProcess, INFINITE);
     98     DLOG_IF(ERROR, ret != WAIT_OBJECT_0)
     99         << "Unexpected return value from WaitForSingleObject: " << ret;
    100     if (::GetExitCodeProcess(pi.hProcess, &ret)) {
    101       DCHECK(ret != STILL_ACTIVE);
    102       success = true;
    103       if (exit_code)
    104         *exit_code = ret;
    105     } else {
    106       PLOG(ERROR) << "GetExitCodeProcess failed";
    107     }
    108 
    109     ::CloseHandle(pi.hProcess);
    110   }
    111 
    112   return success;
    113 }
    114 
    115 bool Product::SetMsiMarker(bool system_install, bool set) const {
    116   HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
    117   RegKey client_state_key;
    118   LONG result = client_state_key.Open(reg_root,
    119                                       distribution_->GetStateKey().c_str(),
    120                                       KEY_SET_VALUE | KEY_WOW64_32KEY);
    121   if (result == ERROR_SUCCESS) {
    122     result = client_state_key.WriteValue(google_update::kRegMSIField,
    123                                          set ? 1 : 0);
    124   }
    125   if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
    126     LOG(ERROR)
    127         << "Failed to Open or Write MSI value to client state key. error: "
    128         << result;
    129     return false;
    130   }
    131   return true;
    132 }
    133 
    134 bool Product::ShouldCreateUninstallEntry() const {
    135   return operations_->ShouldCreateUninstallEntry(options_);
    136 }
    137 
    138 void Product::AddKeyFiles(std::vector<base::FilePath>* key_files) const {
    139   operations_->AddKeyFiles(options_, key_files);
    140 }
    141 
    142 void Product::AddComDllList(std::vector<base::FilePath>* com_dll_list) const {
    143   operations_->AddComDllList(options_, com_dll_list);
    144 }
    145 
    146 void Product::AppendProductFlags(CommandLine* command_line) const {
    147   operations_->AppendProductFlags(options_, command_line);
    148 }
    149 
    150 void Product::AppendRenameFlags(CommandLine* command_line) const {
    151   operations_->AppendRenameFlags(options_, command_line);
    152 }
    153 
    154 bool Product::SetChannelFlags(bool set, ChannelInfo* channel_info) const {
    155   return operations_->SetChannelFlags(options_, set, channel_info);
    156 }
    157 
    158 void Product::AddDefaultShortcutProperties(
    159     const base::FilePath& target_exe,
    160     ShellUtil::ShortcutProperties* properties) const {
    161   return operations_->AddDefaultShortcutProperties(
    162       distribution_, target_exe, properties);
    163 }
    164 
    165 void Product::LaunchUserExperiment(const base::FilePath& setup_path,
    166                                    InstallStatus status,
    167                                    bool system_level) const {
    168   if (distribution_->HasUserExperiments()) {
    169     VLOG(1) << "LaunchUserExperiment status: " << status << " product: "
    170             << distribution_->GetDisplayName()
    171             << " system_level: " << system_level;
    172     operations_->LaunchUserExperiment(
    173         setup_path, options_, status, system_level);
    174   }
    175 }
    176 
    177 }  // namespace installer
    178