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.
5 #include "chrome/installer/util/product.h"
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"
25 using base::win::RegKey
;
26 using installer::MasterPreferences
;
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());
38 case BrowserDistribution::CHROME_FRAME
:
39 operations_
.reset(new ChromeFrameOperations());
41 case BrowserDistribution::CHROME_APP_HOST
:
42 operations_
.reset(new ChromeAppHostOperations());
44 case BrowserDistribution::CHROME_BINARIES
:
45 operations_
.reset(new ChromeBinariesOperations());
48 NOTREACHED() << "Unsupported BrowserDistribution::Type: "
49 << distribution
->GetType();
56 void Product::InitializeFromPreferences(const MasterPreferences
& prefs
) {
57 operations_
->ReadOptions(prefs
, &options_
);
60 void Product::InitializeFromUninstallCommand(
61 const CommandLine
& uninstall_command
) {
62 operations_
->ReadOptions(uninstall_command
, &options_
);
65 void Product::GetUserDataPaths(std::vector
<base::FilePath
>* paths
) const {
66 GetChromeUserDataPaths(distribution_
, paths
);
69 bool Product::LaunchChrome(const base::FilePath
& application_path
) const {
70 bool success
= !application_path
.empty();
72 CommandLine
cmd(application_path
.Append(installer::kChromeExe
));
73 success
= base::LaunchProcess(cmd
, base::LaunchOptions(), NULL
);
78 bool Product::LaunchChromeAndWait(const base::FilePath
& application_path
,
79 const CommandLine
& options
,
80 int32
* exit_code
) const {
81 if (application_path
.empty())
84 CommandLine
cmd(application_path
.Append(installer::kChromeExe
));
85 cmd
.AppendArguments(options
, 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
,
97 PLOG(ERROR
) << "Failed to launch: " << cmd
.GetCommandLineString();
99 ::CloseHandle(pi
.hThread
);
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
);
110 PLOG(ERROR
) << "GetExitCodeProcess failed";
113 ::CloseHandle(pi
.hProcess
);
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
,
129 LOG_IF(ERROR
, result
!= ERROR_SUCCESS
) << "Failed to Open or Write MSI value"
130 "to client state key. error: " << result
;
132 return (result
== ERROR_SUCCESS
);
135 bool Product::ShouldCreateUninstallEntry() const {
136 return operations_
->ShouldCreateUninstallEntry(options_
);
139 void Product::AddKeyFiles(std::vector
<base::FilePath
>* key_files
) const {
140 operations_
->AddKeyFiles(options_
, key_files
);
143 void Product::AddComDllList(std::vector
<base::FilePath
>* com_dll_list
) const {
144 operations_
->AddComDllList(options_
, com_dll_list
);
147 void Product::AppendProductFlags(CommandLine
* command_line
) const {
148 operations_
->AppendProductFlags(options_
, command_line
);
151 void Product::AppendRenameFlags(CommandLine
* command_line
) const {
152 operations_
->AppendRenameFlags(options_
, command_line
);
155 bool Product::SetChannelFlags(bool set
, ChannelInfo
* channel_info
) const {
156 return operations_
->SetChannelFlags(options_
, set
, channel_info
);
159 void Product::AddDefaultShortcutProperties(
160 const base::FilePath
& target_exe
,
161 ShellUtil::ShortcutProperties
* properties
) const {
162 return operations_
->AddDefaultShortcutProperties(
163 distribution_
, target_exe
, properties
);
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
);
178 } // namespace installer