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_READ | KEY_WRITE | KEY_WOW64_32KEY); 121 if (result == ERROR_SUCCESS) { 122 result = client_state_key.WriteValue(google_update::kRegMSIField, 123 set ? 1 : 0); 124 } 125 126 LOG_IF(ERROR, result != ERROR_SUCCESS) << "Failed to Open or Write MSI value" 127 "to client state key. error: " << result; 128 129 return (result == ERROR_SUCCESS); 130 } 131 132 bool Product::ShouldCreateUninstallEntry() const { 133 return operations_->ShouldCreateUninstallEntry(options_); 134 } 135 136 void Product::AddKeyFiles(std::vector<base::FilePath>* key_files) const { 137 operations_->AddKeyFiles(options_, key_files); 138 } 139 140 void Product::AddComDllList(std::vector<base::FilePath>* com_dll_list) const { 141 operations_->AddComDllList(options_, com_dll_list); 142 } 143 144 void Product::AppendProductFlags(CommandLine* command_line) const { 145 operations_->AppendProductFlags(options_, command_line); 146 } 147 148 void Product::AppendRenameFlags(CommandLine* command_line) const { 149 operations_->AppendRenameFlags(options_, command_line); 150 } 151 152 bool Product::SetChannelFlags(bool set, ChannelInfo* channel_info) const { 153 return operations_->SetChannelFlags(options_, set, channel_info); 154 } 155 156 void Product::AddDefaultShortcutProperties( 157 const base::FilePath& target_exe, 158 ShellUtil::ShortcutProperties* properties) const { 159 return operations_->AddDefaultShortcutProperties( 160 distribution_, target_exe, properties); 161 } 162 163 void Product::LaunchUserExperiment(const base::FilePath& setup_path, 164 InstallStatus status, 165 bool system_level) const { 166 if (distribution_->HasUserExperiments()) { 167 VLOG(1) << "LaunchUserExperiment status: " << status << " product: " 168 << distribution_->GetDisplayName() 169 << " system_level: " << system_level; 170 operations_->LaunchUserExperiment( 171 setup_path, options_, status, system_level); 172 } 173 } 174 175 } // namespace installer 176