• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetUserDataPaths(std::vector<base::FilePath> * paths) const65 void Product::GetUserDataPaths(std::vector<base::FilePath>* paths) const {
66   GetChromeUserDataPaths(distribution_, paths);
67 }
68 
LaunchChrome(const base::FilePath & application_path) const69 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 
LaunchChromeAndWait(const base::FilePath & application_path,const CommandLine & options,int32 * exit_code) const78 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 
SetMsiMarker(bool system_install,bool set) const119 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 
ShouldCreateUninstallEntry() const135 bool Product::ShouldCreateUninstallEntry() const {
136   return operations_->ShouldCreateUninstallEntry(options_);
137 }
138 
AddKeyFiles(std::vector<base::FilePath> * key_files) const139 void Product::AddKeyFiles(std::vector<base::FilePath>* key_files) const {
140   operations_->AddKeyFiles(options_, key_files);
141 }
142 
AddComDllList(std::vector<base::FilePath> * com_dll_list) const143 void Product::AddComDllList(std::vector<base::FilePath>* com_dll_list) const {
144   operations_->AddComDllList(options_, com_dll_list);
145 }
146 
AppendProductFlags(CommandLine * command_line) const147 void Product::AppendProductFlags(CommandLine* command_line) const {
148   operations_->AppendProductFlags(options_, command_line);
149 }
150 
AppendRenameFlags(CommandLine * command_line) const151 void Product::AppendRenameFlags(CommandLine* command_line) const {
152   operations_->AppendRenameFlags(options_, command_line);
153 }
154 
SetChannelFlags(bool set,ChannelInfo * channel_info) const155 bool Product::SetChannelFlags(bool set, ChannelInfo* channel_info) const {
156   return operations_->SetChannelFlags(options_, set, channel_info);
157 }
158 
AddDefaultShortcutProperties(const base::FilePath & target_exe,ShellUtil::ShortcutProperties * properties) const159 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 
LaunchUserExperiment(const base::FilePath & setup_path,InstallStatus status,bool system_level) const166 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