OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/installer/util/product.h" | 5 #include "chrome/installer/util/product.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/process_util.h" | 11 #include "base/process_util.h" |
12 #include "base/win/registry.h" | 12 #include "base/win/registry.h" |
| 13 #include "chrome/installer/util/chrome_browser_operations.h" |
| 14 #include "chrome/installer/util/chrome_browser_sxs_operations.h" |
| 15 #include "chrome/installer/util/chrome_frame_operations.h" |
13 #include "chrome/installer/util/google_update_constants.h" | 16 #include "chrome/installer/util/google_update_constants.h" |
14 #include "chrome/installer/util/helper.h" | 17 #include "chrome/installer/util/helper.h" |
15 #include "chrome/installer/util/install_util.h" | 18 #include "chrome/installer/util/install_util.h" |
16 #include "chrome/installer/util/master_preferences.h" | 19 #include "chrome/installer/util/master_preferences.h" |
17 #include "chrome/installer/util/master_preferences_constants.h" | 20 #include "chrome/installer/util/master_preferences_constants.h" |
18 #include "chrome/installer/util/package_properties.h" | 21 #include "chrome/installer/util/product_operations.h" |
19 | 22 |
20 using base::win::RegKey; | 23 using base::win::RegKey; |
21 using installer::MasterPreferences; | 24 using installer::MasterPreferences; |
22 | 25 |
23 namespace { | |
24 class ProductIsOfType { | |
25 public: | |
26 explicit ProductIsOfType(BrowserDistribution::Type type) | |
27 : type_(type) { } | |
28 bool operator()( | |
29 const scoped_refptr<const installer::Product>& pi) const { | |
30 return pi->distribution()->GetType() == type_; | |
31 } | |
32 private: | |
33 BrowserDistribution::Type type_; | |
34 }; // class ProductIsOfType | |
35 } // end namespace | |
36 | |
37 namespace installer { | 26 namespace installer { |
38 | 27 |
39 const Product* FindProduct(const Products& products, | 28 Product::Product(BrowserDistribution* distribution) |
40 BrowserDistribution::Type type) { | 29 : distribution_(distribution) { |
41 Products::const_iterator i = | 30 switch (distribution->GetType()) { |
42 std::find_if(products.begin(), products.end(), ProductIsOfType(type)); | 31 case BrowserDistribution::CHROME_BROWSER: |
43 return i == products.end() ? NULL : *i; | 32 operations_.reset(InstallUtil::IsChromeSxSProcess() ? |
| 33 new ChromeBrowserSxSOperations() : |
| 34 new ChromeBrowserOperations()); |
| 35 break; |
| 36 case BrowserDistribution::CHROME_FRAME: |
| 37 operations_.reset(new ChromeFrameOperations()); |
| 38 break; |
| 39 default: |
| 40 NOTREACHED() << "Unsupported BrowserDistribution::Type: " |
| 41 << distribution->GetType(); |
| 42 } |
44 } | 43 } |
45 | 44 |
46 //////////////////////////////////////////////////////////////////////////////// | 45 Product::~Product() { |
47 | |
48 Product::Product(BrowserDistribution* distribution, Package* package) | |
49 : distribution_(distribution), | |
50 package_(package), | |
51 msi_(false), | |
52 cache_state_(0) { | |
53 package_->AssociateProduct(this); | |
54 } | 46 } |
55 | 47 |
56 const Package& Product::package() const { | 48 void Product::InitializeFromPreferences(const MasterPreferences& prefs) { |
57 return *package_.get(); | 49 operations_->ReadOptions(prefs, &options_); |
| 50 } |
| 51 |
| 52 void Product::InitializeFromUninstallCommand( |
| 53 const CommandLine& uninstall_command) { |
| 54 operations_->ReadOptions(uninstall_command, &options_); |
58 } | 55 } |
59 | 56 |
60 FilePath Product::GetUserDataPath() const { | 57 FilePath Product::GetUserDataPath() const { |
61 return GetChromeUserDataPath(distribution_); | 58 return GetChromeUserDataPath(distribution_); |
62 } | 59 } |
63 | 60 |
64 bool Product::LaunchChrome() const { | 61 bool Product::LaunchChrome(const FilePath& application_path) const { |
65 const FilePath& install_package = package_->path(); | 62 bool success = !application_path.empty(); |
66 bool success = !install_package.empty(); | |
67 if (success) { | 63 if (success) { |
68 CommandLine cmd(install_package.Append(installer::kChromeExe)); | 64 CommandLine cmd(application_path.Append(installer::kChromeExe)); |
69 success = base::LaunchApp(cmd, false, false, NULL); | 65 success = base::LaunchApp(cmd, false, false, NULL); |
70 } | 66 } |
71 return success; | 67 return success; |
72 } | 68 } |
73 | 69 |
74 bool Product::LaunchChromeAndWait(const CommandLine& options, | 70 bool Product::LaunchChromeAndWait(const FilePath& application_path, |
| 71 const CommandLine& options, |
75 int32* exit_code) const { | 72 int32* exit_code) const { |
76 const FilePath& install_package = package_->path(); | 73 if (application_path.empty()) |
77 if (install_package.empty()) | |
78 return false; | 74 return false; |
79 | 75 |
80 CommandLine cmd(install_package.Append(installer::kChromeExe)); | 76 CommandLine cmd(application_path.Append(installer::kChromeExe)); |
81 cmd.AppendArguments(options, false); | 77 cmd.AppendArguments(options, false); |
82 | 78 |
83 bool success = false; | 79 bool success = false; |
84 STARTUPINFOW si = { sizeof(si) }; | 80 STARTUPINFOW si = { sizeof(si) }; |
85 PROCESS_INFORMATION pi = {0}; | 81 PROCESS_INFORMATION pi = {0}; |
86 // Cast away constness of the command_line_string() since CreateProcess | 82 // Cast away constness of the command_line_string() since CreateProcess |
87 // might modify the string (insert \0 to separate the program from the | 83 // might modify the string (insert \0 to separate the program from the |
88 // arguments). Since we're not using the cmd variable beyond this point | 84 // arguments). Since we're not using the cmd variable beyond this point |
89 // we don't care. | 85 // we don't care. |
90 if (!::CreateProcess(cmd.GetProgram().value().c_str(), | 86 if (!::CreateProcess(cmd.GetProgram().value().c_str(), |
(...skipping 15 matching lines...) Expand all Loading... |
106 } else { | 102 } else { |
107 PLOG(ERROR) << "GetExitCodeProcess failed"; | 103 PLOG(ERROR) << "GetExitCodeProcess failed"; |
108 } | 104 } |
109 | 105 |
110 ::CloseHandle(pi.hProcess); | 106 ::CloseHandle(pi.hProcess); |
111 } | 107 } |
112 | 108 |
113 return success; | 109 return success; |
114 } | 110 } |
115 | 111 |
116 bool Product::IsMsi() const { | 112 bool Product::SetMsiMarker(bool system_install, bool set) const { |
117 if ((cache_state_ & MSI_STATE) == 0) { | 113 HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; |
118 msi_ = false; // Covers failure cases below. | |
119 | |
120 const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess(); | |
121 | |
122 bool is_msi = false; | |
123 prefs.GetBool(installer::master_preferences::kMsi, &is_msi); | |
124 | |
125 if (!is_msi) { | |
126 // We didn't find it in the preferences, try looking in the registry. | |
127 HKEY reg_root = system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | |
128 RegKey key; | |
129 if (key.Open(reg_root, distribution_->GetStateKey().c_str(), | |
130 KEY_READ) == ERROR_SUCCESS) { | |
131 DWORD msi_value = 0; | |
132 key.ReadValueDW(google_update::kRegMSIField, &msi_value); | |
133 msi_ = msi_value != 0; | |
134 } | |
135 } else { | |
136 msi_ = true; | |
137 } | |
138 cache_state_ |= MSI_STATE; | |
139 } | |
140 | |
141 return msi_; | |
142 } | |
143 | |
144 bool Product::SetMsiMarker(bool set) const { | |
145 HKEY reg_root = system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | |
146 RegKey client_state_key; | 114 RegKey client_state_key; |
147 LONG result = client_state_key.Open(reg_root, | 115 LONG result = client_state_key.Open(reg_root, |
148 distribution_->GetStateKey().c_str(), KEY_READ | KEY_WRITE); | 116 distribution_->GetStateKey().c_str(), KEY_READ | KEY_WRITE); |
149 if (result == ERROR_SUCCESS) { | 117 if (result == ERROR_SUCCESS) { |
150 result = client_state_key.WriteValue(google_update::kRegMSIField, | 118 result = client_state_key.WriteValue(google_update::kRegMSIField, |
151 set ? 1 : 0); | 119 set ? 1 : 0); |
152 } | 120 } |
153 | 121 |
154 LOG_IF(ERROR, result != ERROR_SUCCESS) << "Failed to Open or Write MSI value" | 122 LOG_IF(ERROR, result != ERROR_SUCCESS) << "Failed to Open or Write MSI value" |
155 "to client state key. error: " << result; | 123 "to client state key. error: " << result; |
156 | 124 |
157 return (result == ERROR_SUCCESS); | 125 return (result == ERROR_SUCCESS); |
158 } | 126 } |
159 | 127 |
160 bool Product::ShouldCreateUninstallEntry() const { | 128 bool Product::ShouldCreateUninstallEntry() const { |
161 if (IsMsi()) { | 129 return operations_->ShouldCreateUninstallEntry(options_); |
162 // MSI installations will manage their own uninstall shortcuts. | |
163 return false; | |
164 } | |
165 | |
166 return distribution_->ShouldCreateUninstallEntry(); | |
167 } | 130 } |
168 | 131 |
169 /////////////////////////////////////////////////////////////////////////////// | 132 void Product::AddKeyFiles(std::vector<FilePath>* key_files) const { |
170 ProductPackageMapping::ProductPackageMapping(bool multi_install, | 133 operations_->AddKeyFiles(options_, key_files); |
171 bool system_level) | |
172 : package_properties_(new ActivePackageProperties()), | |
173 multi_install_(multi_install), | |
174 system_level_(system_level) { | |
175 } | 134 } |
176 | 135 |
177 const Packages& ProductPackageMapping::packages() const { | 136 void Product::AddComDllList(std::vector<FilePath>* com_dll_list) const { |
178 return packages_; | 137 operations_->AddComDllList(options_, com_dll_list); |
179 } | 138 } |
180 | 139 |
181 const Products& ProductPackageMapping::products() const { | 140 void Product::AppendProductFlags(CommandLine* command_line) const { |
182 return products_; | 141 operations_->AppendProductFlags(options_, command_line); |
183 } | 142 } |
184 | 143 |
185 bool ProductPackageMapping::AddDistribution(BrowserDistribution* distribution) { | 144 bool Product::SetChannelFlags(bool set, ChannelInfo* channel_info) const { |
186 DCHECK(distribution); | 145 return operations_->SetChannelFlags(options_, set, channel_info); |
187 // Each product type can be added exactly once. | |
188 DCHECK(FindProduct(products_, distribution->GetType()) == NULL); | |
189 | |
190 FilePath install_package; | |
191 if (distribution->GetType() == BrowserDistribution::CHROME_BROWSER) { | |
192 install_package = GetChromeInstallPath(system_level_, distribution); | |
193 } else { | |
194 DCHECK_EQ(BrowserDistribution::CHROME_FRAME, distribution->GetType()); | |
195 install_package = GetChromeFrameInstallPath(multi_install_, system_level_, | |
196 distribution); | |
197 } | |
198 | |
199 if (install_package.empty()) { | |
200 LOG(ERROR) << "Got an empty installation path for " | |
201 << distribution->GetApplicationName() | |
202 << ". It's likely that there's a conflicting " | |
203 "installation present"; | |
204 return false; | |
205 } | |
206 | |
207 scoped_refptr<Package> target_package; | |
208 for (size_t i = 0; i < packages_.size(); ++i) { | |
209 if (packages_[i]->IsEqual(install_package)) { | |
210 // Use an existing Package. | |
211 target_package = packages_[i]; | |
212 break; | |
213 } | |
214 } | |
215 | |
216 if (!target_package.get()) { | |
217 DCHECK(packages_.empty()) << "Multiple packages per run unsupported."; | |
218 // create new one and add. | |
219 target_package = new Package(multi_install_, system_level_, install_package, | |
220 package_properties_.get()); | |
221 packages_.push_back(target_package); | |
222 } | |
223 | |
224 scoped_refptr<Product> product(new Product(distribution, target_package)); | |
225 #ifndef NDEBUG | |
226 for (size_t i = 0; i < products_.size(); ++i) { | |
227 DCHECK_EQ(product->IsMsi(), products_[i]->IsMsi()); | |
228 } | |
229 #endif | |
230 products_.push_back(product); | |
231 | |
232 return true; | |
233 } | |
234 | |
235 bool ProductPackageMapping::AddDistribution( | |
236 BrowserDistribution::Type type, | |
237 const MasterPreferences& prefs) { | |
238 BrowserDistribution* distribution = | |
239 BrowserDistribution::GetSpecificDistribution(type, prefs); | |
240 if (!distribution) { | |
241 NOTREACHED(); | |
242 return false; | |
243 } | |
244 | |
245 return AddDistribution(distribution); | |
246 } | 146 } |
247 | 147 |
248 } // namespace installer | 148 } // namespace installer |
249 | |
OLD | NEW |