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