Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Side by Side Diff: chrome/installer/util/installer_state.cc

Issue 6288009: More installer refactoring in the interest of fixing some bugs and cleaning t... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/installer_state.h" 5 #include "chrome/installer/util/installer_state.h"
6 6
7 #include <algorithm>
8 #include <functional>
9 #include <utility>
10
11 #include "base/command_line.h"
12 #include "base/file_util.h"
7 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/scoped_ptr.h"
15 #include "base/string_util.h"
16 #include "base/utf_string_conversions.h"
17 #include "chrome/installer/util/delete_tree_work_item.h"
18 #include "chrome/installer/util/helper.h"
8 #include "chrome/installer/util/installation_state.h" 19 #include "chrome/installer/util/installation_state.h"
9 #include "chrome/installer/util/master_preferences.h" 20 #include "chrome/installer/util/master_preferences.h"
10 #include "chrome/installer/util/master_preferences_constants.h" 21 #include "chrome/installer/util/master_preferences_constants.h"
11 #include "chrome/installer/util/package_properties.h" 22 #include "chrome/installer/util/product.h"
23 #include "chrome/installer/util/work_item.h"
12 24
13 namespace installer { 25 namespace installer {
14 26
15 bool InstallerState::IsMultiInstallUpdate(const MasterPreferences& prefs, 27 bool InstallerState::IsMultiInstallUpdate(const MasterPreferences& prefs,
16 const InstallationState& machine_state) { 28 const InstallationState& machine_state) {
17 // First, is the package present? 29 // First, is the package present?
18 const ProductState* package = 30 const ProductState* package =
19 machine_state.GetMultiPackageState(system_install_); 31 machine_state.GetProductState(level_ == SYSTEM_LEVEL,
32 BrowserDistribution::CHROME_BINARIES);
20 if (package == NULL) { 33 if (package == NULL) {
21 // The multi-install package has not been installed, so it certainly isn't 34 // The multi-install package has not been installed, so it certainly isn't
22 // being updated. 35 // being updated.
23 return false; 36 return false;
24 } 37 }
25 38
26 BrowserDistribution::Type types[2]; 39 BrowserDistribution::Type types[2];
27 size_t num_types = 0; 40 size_t num_types = 0;
28 if (prefs.install_chrome()) 41 if (prefs.install_chrome())
29 types[num_types++] = BrowserDistribution::CHROME_BROWSER; 42 types[num_types++] = BrowserDistribution::CHROME_BROWSER;
30 if (prefs.install_chrome_frame()) 43 if (prefs.install_chrome_frame())
31 types[num_types++] = BrowserDistribution::CHROME_FRAME; 44 types[num_types++] = BrowserDistribution::CHROME_FRAME;
32 45
33 for (const BrowserDistribution::Type* scan = &types[0], 46 for (const BrowserDistribution::Type* scan = &types[0],
34 *end = &types[num_types]; scan != end; ++scan) { 47 *end = &types[num_types]; scan != end; ++scan) {
35 const ProductState* product = 48 const ProductState* product =
36 machine_state.GetProductState(system_install_, *scan); 49 machine_state.GetProductState(level_ == SYSTEM_LEVEL, *scan);
37 if (product == NULL) { 50 if (product == NULL) {
38 VLOG(2) << "It seems that distribution type " << *scan 51 VLOG(2) << "It seems that distribution type " << *scan
39 << " is being installed for the first time."; 52 << " is being installed for the first time.";
40 return false; 53 return false;
41 } 54 }
42 if (!product->channel().Equals(package->channel())) { 55 if (!product->channel().Equals(package->channel())) {
43 VLOG(2) << "It seems that distribution type " << *scan 56 VLOG(2) << "It seems that distribution type " << *scan
44 << " is being over installed."; 57 << " is being over installed.";
45 return false; 58 return false;
46 } 59 }
47 } 60 }
48 61
49 VLOG(2) << "It seems that the package is being updated."; 62 VLOG(2) << "It seems that the package is being updated.";
50 63
51 return true; 64 return true;
52 } 65 }
53 66
54 InstallerState::InstallerState() : operation_(UNINITIALIZED) { 67 InstallerState::InstallerState()
55 } 68 : operation_(UNINITIALIZED),
56 69 level_(UNKNOWN_LEVEL),
57 void InstallerState::Initialize(const MasterPreferences& prefs, 70 package_type_(UNKNOWN_PACKAGE_TYPE),
71 root_key_(NULL),
72 msi_(false),
73 verbose_logging_(false) {
74 }
75
76 void InstallerState::Initialize(const CommandLine& command_line,
77 const MasterPreferences& prefs,
58 const InstallationState& machine_state) { 78 const InstallationState& machine_state) {
59 if (!prefs.GetBool(installer::master_preferences::kSystemLevel, 79 bool pref_bool;
60 &system_install_)) 80 if (!prefs.GetBool(master_preferences::kSystemLevel, &pref_bool))
61 system_install_ = false; 81 pref_bool = false;
82 level_ = (pref_bool ? SYSTEM_LEVEL : USER_LEVEL);
83
84 root_key_ = (level_ == SYSTEM_LEVEL ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER);
85
86 if (!prefs.GetBool(master_preferences::kVerboseLogging, &verbose_logging_))
87 verbose_logging_ = false;
88
89 if (!prefs.GetBool(master_preferences::kMultiInstall, &pref_bool))
90 pref_bool = false;
91 package_type_ = (pref_bool ? MULTI_PACKAGE : SINGLE_PACKAGE);
92
93 if (!prefs.GetBool(master_preferences::kMsi, &msi_))
94 msi_ = false;
95
96 const bool is_uninstall = command_line.HasSwitch(switches::kUninstall);
97
98 if (prefs.install_chrome()) {
99 const Product& p =
100 AddProductFromPreferences(BrowserDistribution::CHROME_BROWSER, prefs,
101 machine_state);
102 VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
103 << " distribution: " << p.distribution()->GetApplicationName();
104 }
105 if (prefs.install_chrome_frame()) {
106 const Product& p =
107 AddProductFromPreferences(BrowserDistribution::CHROME_FRAME, prefs,
108 machine_state);
109 VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
110 << " distribution: " << p.distribution()->GetApplicationName();
111 }
112
113 // Operate in the Chrome Frame directory iff single install and installing
114 // CF. Otherwise, install in Chrome binaries directory.
115 if (package_type_ == SINGLE_PACKAGE && prefs.install_chrome_frame())
116 target_path_ = GetChromeInstallPath(
117 level_ == SYSTEM_LEVEL,
118 BrowserDistribution::GetSpecificDistribution(
119 BrowserDistribution::CHROME_FRAME));
120 else
121 target_path_ = GetChromeInstallPath(
122 level_ == SYSTEM_LEVEL,
123 BrowserDistribution::GetSpecificDistribution(
124 BrowserDistribution::CHROME_BINARIES));
125
126 if (package_type_ == MULTI_PACKAGE)
127 multi_package_distribution_ =
128 BrowserDistribution::GetSpecificDistribution(
129 BrowserDistribution::CHROME_BINARIES);
62 130
63 BrowserDistribution* operand = NULL; 131 BrowserDistribution* operand = NULL;
64 132
65 if (!prefs.is_multi_install()) { 133 if (is_uninstall) {
134 operation_ = UNINSTALL;
135 } else if (!prefs.is_multi_install()) {
66 // For a single-install, the current browser dist is the operand. 136 // For a single-install, the current browser dist is the operand.
67 operand = BrowserDistribution::GetDistribution(); 137 operand = BrowserDistribution::GetDistribution();
68 operation_ = SINGLE_INSTALL_OR_UPDATE; 138 operation_ = SINGLE_INSTALL_OR_UPDATE;
69 } else if (IsMultiInstallUpdate(prefs, machine_state)) { 139 } else if (IsMultiInstallUpdate(prefs, machine_state)) {
70 // Updates driven by Google Update take place under the multi-installer's 140 // Updates driven by Google Update take place under the multi-installer's
71 // app guid. 141 // app guid.
72 installer::ActivePackageProperties package_properties; 142 operand = multi_package_distribution_;
73 operation_ = MULTI_UPDATE; 143 operation_ = MULTI_UPDATE;
74 state_key_ = package_properties.GetStateKey();
75 } else { 144 } else {
76 // Initial and over installs will always take place under one of the 145 // Initial and over installs will always take place under one of the
77 // product app guids. Chrome Frame's will be used if only Chrome Frame 146 // product app guids. Chrome Frame's will be used if only Chrome Frame
78 // is being installed. In all other cases, Chrome's is used. 147 // is being installed. In all other cases, Chrome's is used.
148 operation_ = MULTI_INSTALL;
149 }
150
151 if (operand == NULL) {
79 operand = BrowserDistribution::GetSpecificDistribution( 152 operand = BrowserDistribution::GetSpecificDistribution(
80 prefs.install_chrome() ? 153 prefs.install_chrome() ?
81 BrowserDistribution::CHROME_BROWSER : 154 BrowserDistribution::CHROME_BROWSER :
82 BrowserDistribution::CHROME_FRAME, 155 BrowserDistribution::CHROME_FRAME);
83 prefs); 156 }
84 operation_ = MULTI_INSTALL; 157
85 } 158 state_key_ = operand->GetStateKey();
86 159 }
87 if (operand != NULL) { 160
88 state_key_ = operand->GetStateKey(); 161 void InstallerState::ResetProducts() {
89 } 162 operation_ = UNINITIALIZED;
163 target_path_.clear();
164 products_.reset();
165 multi_package_distribution_ = NULL;
166 package_type_ = UNKNOWN_PACKAGE_TYPE;
167 msi_ = false;
168 }
169
170 const Product& InstallerState::AddProductFromPreferences(
171 BrowserDistribution::Type distribution_type,
172 const MasterPreferences& prefs,
173 const InstallationState& machine_state) {
174 scoped_ptr<Product> product(
175 new Product(BrowserDistribution::GetSpecificDistribution(
176 distribution_type)));
177 if (!msi_) {
178 const ProductState* product_state = machine_state.GetProductState(
179 level_ == SYSTEM_LEVEL, distribution_type);
180 if (product_state != NULL)
181 msi_ = product_state->msi();
182 }
183 product->InitializeFromPreferences(prefs);
184 products_.push_back(product.release());
185 return *products_[products_.size() - 1];
186 }
187
188 Product* InstallerState::AddProductFromState(
189 BrowserDistribution::Type type,
190 const ProductState& state) {
191 DCHECK_NE(SINGLE_PACKAGE, package_type_)
192 << "Cannot process more than one single-install product at a time.";
193 scoped_ptr<Product> product(
194 new Product(BrowserDistribution::GetSpecificDistribution(type)));
195 product->InitializeFromUninstallCommand(state.uninstall_command());
196 products_.push_back(product.release());
197 if (package_type_ == UNKNOWN_PACKAGE_TYPE) {
198 package_type_ = state.multi_install() ? MULTI_PACKAGE : SINGLE_PACKAGE;
199 if (package_type_ == MULTI_PACKAGE)
200 multi_package_distribution_ =
201 BrowserDistribution::GetSpecificDistribution(
202 BrowserDistribution::CHROME_BINARIES);
203 // Strip off <version>/Installer/setup.exe; see GetInstallerDirectory().
204 target_path_ = state.GetSetupPath().DirName().DirName().DirName();
205 // Use the ClientState key of the first product added.
206 state_key_ = product->distribution()->GetStateKey();
207 } else {
208 DCHECK_EQ(MULTI_PACKAGE, package_type_);
209 DCHECK(state.multi_install());
210 DCHECK_EQ(target_path_.value(),
211 state.GetSetupPath().DirName().DirName().DirName().value());
212 }
213 msi_ |= state.msi();
214 return products_[products_.size() - 1];
215 }
216
217 bool InstallerState::RemoveProduct(const Product* product) {
218 ScopedVector<Product>::iterator it =
219 std::find(products_.begin(), products_.end(), product);
220 if (it != products_.end()) {
221 products_->erase(it);
222 return true;
223 }
224 return false;
225 }
226
227 const Product* InstallerState::FindProduct(
228 BrowserDistribution::Type distribution_type) const {
229 const Products::const_iterator it =
230 std::find_if(products_.begin(), products_.end(),
231 std::bind2nd(std::mem_fun(&Product::is_type),
232 distribution_type));
233 return it == products_.end() ? NULL : *it;
234 }
235
236 Version* InstallerState::GetCurrentVersion(
237 const InstallationState& machine_state) const {
238 DCHECK(!products_.empty());
239 scoped_ptr<Version> current_version;
240 const BrowserDistribution::Type prod_type = (package_type_ == MULTI_PACKAGE) ?
241 BrowserDistribution::CHROME_BINARIES :
242 products_[0]->distribution()->GetType();
243 const ProductState* product_state =
244 machine_state.GetProductState(level_ == SYSTEM_LEVEL, prod_type);
245
246 if (product_state != NULL) {
247 const Version* version = NULL;
248
249 // Be aware that there might be a pending "new_chrome.exe" already in the
250 // installation path. If so, we use old_version, which holds the version of
251 // "chrome.exe" itself.
252 if (file_util::PathExists(target_path().Append(kChromeNewExe)))
253 version = product_state->old_version();
254
255 if (version == NULL)
256 version = &product_state->version();
257
258 current_version.reset(version->Clone());
259 }
260
261 return current_version.release();
262 }
263
264 FilePath InstallerState::GetInstallerDirectory(const Version& version) const {
265 return target_path().Append(ASCIIToWide(version.GetString()))
266 .Append(kInstallerDir);
267 }
268
269 void InstallerState::RemoveOldVersionDirectories(
270 const Version& latest_version) const {
271 file_util::FileEnumerator version_enum(target_path(), false,
272 file_util::FileEnumerator::DIRECTORIES);
273 scoped_ptr<Version> version;
274 std::vector<FilePath> key_files;
275
276 // We try to delete all directories whose versions are lower than
277 // latest_version.
278 FilePath next_version = version_enum.Next();
279 while (!next_version.empty()) {
280 file_util::FileEnumerator::FindInfo find_data = {0};
281 version_enum.GetFindInfo(&find_data);
282 VLOG(1) << "directory found: " << find_data.cFileName;
283 version.reset(Version::GetVersionFromString(
284 WideToASCII(find_data.cFileName)));
285 if (version.get() && (latest_version.CompareTo(*version) > 0)) {
286 key_files.clear();
287 std::for_each(products_.begin(), products_.end(),
288 std::bind2nd(std::mem_fun(&Product::AddKeyFiles),
289 &key_files));
290 const std::vector<FilePath>::iterator end = key_files.end();
291 for (std::vector<FilePath>::iterator scan = key_files.begin();
292 scan != end; ++scan) {
293 *scan = next_version.Append(*scan);
294 }
295
296 VLOG(1) << "Deleting directory: " << next_version.value();
297
298 scoped_ptr<WorkItem> item(
299 WorkItem::CreateDeleteTreeWorkItem(next_version, key_files));
300 if (!item->Do())
301 item->Rollback();
302 }
303
304 next_version = version_enum.Next();
305 }
306 }
307
308 void InstallerState::AddComDllList(std::vector<FilePath>* com_dll_list) const {
309 std::for_each(products_.begin(), products_.end(),
310 std::bind2nd(std::mem_fun(&Product::AddComDllList),
311 com_dll_list));
312 }
313
314 bool InstallerState::SetChannelFlags(bool set,
315 ChannelInfo* channel_info) const {
316 bool modified = false;
317
318 // We don't have access to lambdas yet, but we can sure fake it!.
319 struct SetChannelFlagsFunc
320 : public std::unary_function<const Product*, void> {
321 public:
322 SetChannelFlagsFunc(bool set, ChannelInfo* channel_info, bool* modified)
323 : channel_info_(channel_info), modified_(modified), set_(set) {}
324 result_type operator()(argument_type product) const {
325 *modified_ |= product->SetChannelFlags(set_, channel_info_);
326 }
327 private:
328 ChannelInfo* channel_info_;
329 bool* modified_;
330 bool set_;
331 };
332
333 std::for_each(products_.begin(), products_.end(),
334 SetChannelFlagsFunc(set, channel_info, &modified));
335 return modified;
90 } 336 }
91 337
92 } // namespace installer 338 } // namespace installer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698