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
Product(BrowserDistribution * distribution)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
~Product()53 Product::~Product() {
54 }
55
InitializeFromPreferences(const MasterPreferences & prefs)56 void Product::InitializeFromPreferences(const MasterPreferences& prefs) {
57 operations_->ReadOptions(prefs, &options_);
58 }
59
InitializeFromUninstallCommand(const CommandLine & uninstall_command)60 void Product::InitializeFromUninstallCommand(
61 const CommandLine& uninstall_command) {
62 operations_->ReadOptions(uninstall_command, &options_);
63 }
64
LaunchChrome(const base::FilePath & application_path) const65 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
LaunchChromeAndWait(const base::FilePath & application_path,const CommandLine & options,int32 * exit_code) const74 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
SetMsiMarker(bool system_install,bool set) const115 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
ShouldCreateUninstallEntry() const132 bool Product::ShouldCreateUninstallEntry() const {
133 return operations_->ShouldCreateUninstallEntry(options_);
134 }
135
AddKeyFiles(std::vector<base::FilePath> * key_files) const136 void Product::AddKeyFiles(std::vector<base::FilePath>* key_files) const {
137 operations_->AddKeyFiles(options_, key_files);
138 }
139
AddComDllList(std::vector<base::FilePath> * com_dll_list) const140 void Product::AddComDllList(std::vector<base::FilePath>* com_dll_list) const {
141 operations_->AddComDllList(options_, com_dll_list);
142 }
143
AppendProductFlags(CommandLine * command_line) const144 void Product::AppendProductFlags(CommandLine* command_line) const {
145 operations_->AppendProductFlags(options_, command_line);
146 }
147
AppendRenameFlags(CommandLine * command_line) const148 void Product::AppendRenameFlags(CommandLine* command_line) const {
149 operations_->AppendRenameFlags(options_, command_line);
150 }
151
SetChannelFlags(bool set,ChannelInfo * channel_info) const152 bool Product::SetChannelFlags(bool set, ChannelInfo* channel_info) const {
153 return operations_->SetChannelFlags(options_, set, channel_info);
154 }
155
AddDefaultShortcutProperties(const base::FilePath & target_exe,ShellUtil::ShortcutProperties * properties) const156 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
LaunchUserExperiment(const base::FilePath & setup_path,InstallStatus status,bool system_level) const163 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