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

Side by Side Diff: chrome/installer/setup/install.cc

Issue 6153003: Refactor install.cc into the work item parts and the non-work item parts. (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/setup/install.h" 5 #include "chrome/installer/setup/install.h"
6 6
7 #include <shlobj.h> 7 #include <shlobj.h>
8 #include <time.h> 8 #include <time.h>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/file_path.h" 12 #include "base/file_path.h"
13 #include "base/file_util.h" 13 #include "base/file_util.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/path_service.h" 15 #include "base/path_service.h"
16 #include "base/scoped_ptr.h" 16 #include "base/scoped_ptr.h"
17 #include "base/string_util.h" 17 #include "base/string_util.h"
18 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
19 #include "base/win/registry.h" 19 #include "base/win/registry.h"
20 #include "chrome/installer/setup/setup_constants.h" 20 #include "chrome/installer/setup/setup_constants.h"
21 #include "chrome/installer/setup/install_worker.h"
21 #include "chrome/installer/util/browser_distribution.h" 22 #include "chrome/installer/util/browser_distribution.h"
22 #include "chrome/installer/util/channel_info.h" 23 #include "chrome/installer/util/channel_info.h"
23 #include "chrome/installer/util/chrome_frame_distribution.h" 24 #include "chrome/installer/util/chrome_frame_distribution.h"
24 #include "chrome/installer/util/conditional_work_item_list.h" 25 #include "chrome/installer/util/conditional_work_item_list.h"
25 #include "chrome/installer/util/create_reg_key_work_item.h" 26 #include "chrome/installer/util/create_reg_key_work_item.h"
26 #include "chrome/installer/util/delete_after_reboot_helper.h" 27 #include "chrome/installer/util/delete_after_reboot_helper.h"
27 #include "chrome/installer/util/google_update_constants.h" 28 #include "chrome/installer/util/google_update_constants.h"
28 #include "chrome/installer/util/helper.h" 29 #include "chrome/installer/util/helper.h"
29 #include "chrome/installer/util/install_util.h" 30 #include "chrome/installer/util/install_util.h"
30 #include "chrome/installer/util/installation_state.h" 31 #include "chrome/installer/util/installation_state.h"
(...skipping 30 matching lines...) Expand all
61 file_util::AppendToPath(&reg_path, installer::kChromeExe); 62 file_util::AppendToPath(&reg_path, installer::kChromeExe);
62 VLOG(1) << "Adding Chrome to Media player list at " << reg_path; 63 VLOG(1) << "Adding Chrome to Media player list at " << reg_path;
63 scoped_ptr<WorkItem> work_item(WorkItem::CreateCreateRegKeyWorkItem( 64 scoped_ptr<WorkItem> work_item(WorkItem::CreateCreateRegKeyWorkItem(
64 HKEY_LOCAL_MACHINE, reg_path)); 65 HKEY_LOCAL_MACHINE, reg_path));
65 66
66 // if the operation fails we log the error but still continue 67 // if the operation fails we log the error but still continue
67 if (!work_item.get()->Do()) 68 if (!work_item.get()->Do())
68 LOG(ERROR) << "Could not add Chrome to media player inclusion list."; 69 LOG(ERROR) << "Could not add Chrome to media player inclusion list.";
69 } 70 }
70 71
71 void AddInstallerCopyTasks(const FilePath& setup_path,
72 const FilePath& archive_path,
73 const FilePath& temp_path,
74 const Version& new_version,
75 WorkItemList* install_list,
76 const Package& package) {
77 DCHECK(install_list);
78 FilePath installer_dir(package.GetInstallerDirectory(new_version));
79 install_list->AddCreateDirWorkItem(installer_dir);
80
81 FilePath exe_dst(installer_dir.Append(setup_path.BaseName()));
82 FilePath archive_dst(installer_dir.Append(archive_path.BaseName()));
83
84 install_list->AddCopyTreeWorkItem(setup_path.value(), exe_dst.value(),
85 temp_path.value(), WorkItem::ALWAYS);
86 if (package.system_level()) {
87 install_list->AddCopyTreeWorkItem(archive_path.value(), archive_dst.value(),
88 temp_path.value(), WorkItem::ALWAYS);
89 } else {
90 install_list->AddMoveTreeWorkItem(archive_path.value(), archive_dst.value(),
91 temp_path.value());
92 }
93 }
94
95 void AppendUninstallCommandLineFlags(CommandLine* uninstall_cmd,
96 const Product& product) {
97 DCHECK(uninstall_cmd);
98
99 uninstall_cmd->AppendSwitch(installer::switches::kUninstall);
100
101 // Append the product-specific uninstall flags.
102 product.distribution()->AppendUninstallCommandLineFlags(uninstall_cmd);
103 if (product.IsMsi()) {
104 uninstall_cmd->AppendSwitch(installer::switches::kMsi);
105 // See comment in uninstall.cc where we check for the kDeleteProfile switch.
106 if (product.is_chrome_frame()) {
107 uninstall_cmd->AppendSwitch(installer::switches::kDeleteProfile);
108 }
109 }
110 if (product.system_level())
111 uninstall_cmd->AppendSwitch(installer::switches::kSystemLevel);
112
113 // Propagate switches obtained from preferences as well.
114 const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
115 if (prefs.is_multi_install()) {
116 uninstall_cmd->AppendSwitch(installer::switches::kMultiInstall);
117 }
118 bool value = false;
119 if (prefs.GetBool(installer::master_preferences::kVerboseLogging,
120 &value) && value)
121 uninstall_cmd->AppendSwitch(installer::switches::kVerboseLogging);
122 }
123
124 // This method adds work items to create (or update) Chrome uninstall entry in
125 // either the Control Panel->Add/Remove Programs list or in the Omaha client
126 // state key if running under an MSI installer.
127 void AddUninstallShortcutWorkItems(const FilePath& setup_path,
128 const Version& new_version,
129 WorkItemList* install_list,
130 const Product& product) {
131 HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE :
132 HKEY_CURRENT_USER;
133 BrowserDistribution* browser_dist = product.distribution();
134 DCHECK(browser_dist);
135
136 // When we are installed via an MSI, we need to store our uninstall strings
137 // in the Google Update client state key. We do this even for non-MSI
138 // managed installs to avoid breaking the edge case whereby an MSI-managed
139 // install is updated by a non-msi installer (which would confuse the MSI
140 // machinery if these strings were not also updated).
141 // Do not quote the command line for the MSI invocation.
142 FilePath install_path(product.package().path());
143 FilePath installer_path(
144 product.package().GetInstallerDirectory(new_version));
145 installer_path = installer_path.Append(setup_path.BaseName());
146
147 CommandLine uninstall_arguments(CommandLine::NO_PROGRAM);
148 AppendUninstallCommandLineFlags(&uninstall_arguments, product);
149
150 if (product.is_chrome()) {
151 // The Chrome uninstallation command serves as the master uninstall
152 // command for Chrome + all other products (i.e. Chrome Frame) that do
153 // not have an uninstall entry in the Add/Remove Programs dialog.
154 const Products& products = product.package().products();
155 for (size_t i = 0; i < products.size(); ++i) {
156 const Product& p = *products[i];
157 if (!p.is_chrome() && !p.ShouldCreateUninstallEntry()) {
158 p.distribution()->AppendUninstallCommandLineFlags(&uninstall_arguments);
159 }
160 }
161 }
162
163 std::wstring update_state_key(browser_dist->GetStateKey());
164 install_list->AddCreateRegKeyWorkItem(reg_root, update_state_key);
165 install_list->AddSetRegValueWorkItem(reg_root, update_state_key,
166 installer::kUninstallStringField, installer_path.value(), true);
167 install_list->AddSetRegValueWorkItem(reg_root, update_state_key,
168 installer::kUninstallArgumentsField,
169 uninstall_arguments.command_line_string(), true);
170
171 if (product.ShouldCreateUninstallEntry()) {
172 // We need to quote the command line for the Add/Remove Programs dialog.
173 CommandLine quoted_uninstall_cmd(installer_path);
174 DCHECK_EQ(quoted_uninstall_cmd.command_line_string()[0], '"');
175 quoted_uninstall_cmd.AppendArguments(uninstall_arguments, false);
176
177 std::wstring uninstall_reg = browser_dist->GetUninstallRegPath();
178 install_list->AddCreateRegKeyWorkItem(reg_root, uninstall_reg);
179 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
180 installer::kUninstallDisplayNameField,
181 browser_dist->GetAppShortCutName(), true);
182 install_list->AddSetRegValueWorkItem(reg_root,
183 uninstall_reg, installer::kUninstallStringField,
184 quoted_uninstall_cmd.command_line_string(), true);
185 install_list->AddSetRegValueWorkItem(reg_root,
186 uninstall_reg,
187 L"InstallLocation",
188 install_path.value(),
189 true);
190
191 // DisplayIcon, NoModify and NoRepair
192 FilePath chrome_icon(install_path.Append(installer::kChromeExe));
193 ShellUtil::GetChromeIcon(product.distribution(), chrome_icon.value());
194 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
195 L"DisplayIcon", chrome_icon.value(),
196 true);
197 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
198 L"NoModify", 1, true);
199 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
200 L"NoRepair", 1, true);
201
202 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
203 L"Publisher",
204 browser_dist->GetPublisherName(),
205 true);
206 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
207 L"Version",
208 UTF8ToWide(new_version.GetString()),
209 true);
210 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
211 L"DisplayVersion",
212 UTF8ToWide(new_version.GetString()),
213 true);
214 time_t rawtime = time(NULL);
215 struct tm timeinfo = {0};
216 localtime_s(&timeinfo, &rawtime);
217 wchar_t buffer[9];
218 if (wcsftime(buffer, 9, L"%Y%m%d", &timeinfo) == 8) {
219 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg,
220 L"InstallDate",
221 buffer, false);
222 }
223 }
224 }
225
226 // Adds work items that make registry adjustments for Google Update. When a
227 // product is installed (including overinstall), Google Update will write the
228 // channel ("ap") value into either Chrome or Chrome Frame's ClientState key.
229 // In the multi-install case, this value is used as the basis upon which the
230 // package's channel value is built (by adding the ordered list of installed
231 // products and their options).
232 void AddGoogleUpdateWorkItems(const InstallationState& original_state,
233 const InstallerState& installer_state,
234 const Package& package,
235 WorkItemList* install_list) {
236 // Is a multi-install product being installed or over-installed?
237 if (installer_state.operation() != InstallerState::MULTI_INSTALL)
238 return;
239
240 const HKEY reg_root = package.system_level() ? HKEY_LOCAL_MACHINE :
241 HKEY_CURRENT_USER;
242 const std::wstring key_path = installer_state.state_key();
243 ChannelInfo channel_info;
244
245 // Update the "ap" value for the product being installed/updated.
246 // It is completely acceptable for there to be no "ap" value or even no
247 // ClientState key. Note that we check the registry rather than
248 // original_state since on a fresh install the "ap" value will be present
249 // sans "pv" value.
250 channel_info.Initialize(RegKey(reg_root, key_path.c_str(), KEY_QUERY_VALUE));
251
252 // This is a multi-install product.
253 bool modified = channel_info.SetMultiInstall(true);
254
255 // Add the appropriate modifiers for all products and their options.
256 Products::const_iterator scan = package.products().begin();
257 const Products::const_iterator end = package.products().end();
258 for (; scan != end; ++scan) {
259 modified |= scan->get()->distribution()->SetChannelFlags(true,
260 &channel_info);
261 }
262
263 // Write the results if needed.
264 if (modified) {
265 install_list->AddSetRegValueWorkItem(reg_root, key_path,
266 google_update::kRegApField,
267 channel_info.value(), true);
268 }
269
270 // Synchronize the other products and the package with this one.
271 std::wstring other_key;
272 std::vector<std::wstring> keys;
273
274 keys.reserve(package.products().size());
275 other_key = package.properties()->GetStateKey();
276 if (other_key != key_path)
277 keys.push_back(other_key);
278 scan = package.products().begin();
279 for (; scan != end; ++scan) {
280 other_key = scan->get()->distribution()->GetStateKey();
281 if (other_key != key_path)
282 keys.push_back(other_key);
283 }
284
285 RegKey key;
286 ChannelInfo other_info;
287 std::vector<std::wstring>::const_iterator kscan = keys.begin();
288 std::vector<std::wstring>::const_iterator kend = keys.end();
289 for (; kscan != kend; ++kscan) {
290 // Handle the case where the ClientState key doesn't exist by creating it.
291 // This takes care of the multi-installer's package key, which is not
292 // created by Google Update for us.
293 if (!key.Open(reg_root, kscan->c_str(), KEY_QUERY_VALUE) ||
294 !other_info.Initialize(key)) {
295 other_info.set_value(std::wstring());
296 }
297 if (!other_info.Equals(channel_info)) {
298 if (!key.Valid())
299 install_list->AddCreateRegKeyWorkItem(reg_root, *kscan);
300 install_list->AddSetRegValueWorkItem(reg_root, *kscan,
301 google_update::kRegApField,
302 channel_info.value(), true);
303 }
304 }
305 // TODO(grt): check for other keys/values we should put in the package's
306 // ClientState and/or Clients key.
307 }
308
309 // This is called when an MSI installation is run. It may be that a user is
310 // attempting to install the MSI on top of a non-MSI managed installation.
311 // If so, try and remove any existing uninstallation shortcuts, as we want the
312 // uninstall to be managed entirely by the MSI machinery (accessible via the
313 // Add/Remove programs dialog).
314 void AddDeleteUninstallShortcutsForMSIWorkItems(const Product& product,
315 WorkItemList* work_item_list) {
316 DCHECK(product.IsMsi()) << "This must only be called for MSI installations!";
317
318 // First attempt to delete the old installation's ARP dialog entry.
319 HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE :
320 HKEY_CURRENT_USER;
321 base::win::RegKey root_key(reg_root, L"", KEY_ALL_ACCESS);
322 std::wstring uninstall_reg(product.distribution()->GetUninstallRegPath());
323
324 WorkItem* delete_reg_key = work_item_list->AddDeleteRegKeyWorkItem(
325 reg_root, uninstall_reg);
326 delete_reg_key->set_ignore_failure(true);
327
328 // Then attempt to delete the old installation's start menu shortcut.
329 FilePath uninstall_link;
330 if (product.system_level()) {
331 PathService::Get(base::DIR_COMMON_START_MENU, &uninstall_link);
332 } else {
333 PathService::Get(base::DIR_START_MENU, &uninstall_link);
334 }
335
336 if (uninstall_link.empty()) {
337 LOG(ERROR) << "Failed to get location for shortcut.";
338 } else {
339 uninstall_link = uninstall_link.Append(
340 product.distribution()->GetAppShortCutName());
341 uninstall_link = uninstall_link.Append(
342 product.distribution()->GetUninstallLinkName() + L".lnk");
343 VLOG(1) << "Deleting old uninstall shortcut (if present): "
344 << uninstall_link.value();
345 WorkItem* delete_link = work_item_list->AddDeleteTreeWorkItem(
346 uninstall_link);
347 delete_link->set_ignore_failure(true);
348 delete_link->set_log_message(
349 "Failed to delete old uninstall shortcut.");
350 }
351 }
352
353 // Copy master preferences file provided to installer, in the same folder 72 // Copy master preferences file provided to installer, in the same folder
354 // as chrome.exe so Chrome first run can find it. This function will be called 73 // as chrome.exe so Chrome first run can find it. This function will be called
355 // only on the first install of Chrome. 74 // only on the first install of Chrome.
356 void CopyPreferenceFileForFirstRun(const Package& package, 75 void CopyPreferenceFileForFirstRun(const Package& package,
357 const FilePath& prefs_source_path) { 76 const FilePath& prefs_source_path) {
358 FilePath prefs_dest_path(package.path().AppendASCII( 77 FilePath prefs_dest_path(package.path().AppendASCII(
359 installer::kDefaultMasterPrefs)); 78 installer::kDefaultMasterPrefs));
360 if (!file_util::CopyFile(prefs_source_path, prefs_dest_path)) { 79 if (!file_util::CopyFile(prefs_source_path, prefs_dest_path)) {
361 VLOG(1) << "Failed to copy master preferences from:" 80 VLOG(1) << "Failed to copy master preferences from:"
362 << prefs_source_path.value() << " gle: " << ::GetLastError(); 81 << prefs_source_path.value() << " gle: " << ::GetLastError();
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 ret = ShellUtil::CreateChromeQuickLaunchShortcut( 209 ret = ShellUtil::CreateChromeQuickLaunchShortcut(
491 product.distribution(), chrome_exe.value(), ShellUtil::CURRENT_USER, 210 product.distribution(), chrome_exe.value(), ShellUtil::CURRENT_USER,
492 create_all_shortcut); 211 create_all_shortcut);
493 } 212 }
494 } 213 }
495 } 214 }
496 215
497 return ret; 216 return ret;
498 } 217 }
499 218
500 // Local helper to call AddRegisterComDllWorkItems for all DLLs in a set of
501 // products managed by a given package.
502 void AddRegisterComDllWorkItemsForPackage(const Package& package,
503 const Version* old_version,
504 const Version& new_version,
505 WorkItemList* work_item_list) {
506 // First collect the list of DLLs to be registered from each product.
507 const Products& products = package.products();
508 Products::const_iterator product_iter(products.begin());
509 std::vector<FilePath> com_dll_list;
510 for (; product_iter != products.end(); ++product_iter) {
511 BrowserDistribution* dist = product_iter->get()->distribution();
512 std::vector<FilePath> dist_dll_list(dist->GetComDllList());
513 com_dll_list.insert(com_dll_list.end(), dist_dll_list.begin(),
514 dist_dll_list.end());
515 }
516
517 // Then, if we got some, attempt to unregister the DLLs from the old
518 // version directory and then re-register them in the new one.
519 // Note that if we are migrating the install directory then we will not
520 // successfully unregister the old DLLs.
521 // TODO(robertshield): See whether we need to fix the migration case.
522 // TODO(robertshield): If we ever remove a DLL from a product, this will
523 // not unregister it on update. We should build the unregistration list from
524 // saved state instead of assuming it is the same as the registration list.
525 if (!com_dll_list.empty()) {
526 if (old_version) {
527 FilePath old_dll_path(
528 package.path().Append(UTF8ToWide(old_version->GetString())));
529
530 installer::AddRegisterComDllWorkItems(old_dll_path,
531 com_dll_list,
532 package.system_level(),
533 false, // Unregister
534 true, // May fail
535 work_item_list);
536 }
537
538 FilePath dll_path(
539 package.path().Append(UTF8ToWide(new_version.GetString())));
540 installer::AddRegisterComDllWorkItems(dll_path,
541 com_dll_list,
542 package.system_level(),
543 true, // Register
544 false, // Must succeed.
545 work_item_list);
546 }
547 }
548
549 // After a successful copying of all the files, this function is called to
550 // do a few post install tasks:
551 // - Handle the case of in-use-update by updating "opv" (old version) key or
552 // deleting it if not required.
553 // - Register any new dlls and unregister old dlls.
554 // - If this is an MSI install, ensures that the MSI marker is set, and sets
555 // it if not.
556 // If these operations are successful, the function returns true, otherwise
557 // false.
558 bool AppendPostInstallTasks(bool multi_install,
559 const FilePath& setup_path,
560 const FilePath& new_chrome_exe,
561 const Version* current_version,
562 const Version& new_version,
563 const Package& package,
564 WorkItemList* post_install_task_list) {
565 DCHECK(post_install_task_list);
566 HKEY root = package.system_level() ? HKEY_LOCAL_MACHINE :
567 HKEY_CURRENT_USER;
568 const Products& products = package.products();
569
570
571 // Append work items that will only be executed if this was an update.
572 // We update the 'opv' key with the current version that is active and 'cmd'
573 // key with the rename command to run.
574 {
575 scoped_ptr<WorkItemList> in_use_update_work_items(
576 WorkItem::CreateConditionalWorkItemList(
577 new ConditionRunIfFileExists(new_chrome_exe)));
578 in_use_update_work_items->set_log_message("InUseUpdateWorkItemList");
579
580 FilePath installer_path(package.GetInstallerDirectory(new_version)
581 .Append(setup_path.BaseName()));
582
583 CommandLine rename(installer_path);
584 rename.AppendSwitch(installer::switches::kRenameChromeExe);
585 if (package.system_level())
586 rename.AppendSwitch(installer::switches::kSystemLevel);
587
588 if (InstallUtil::IsChromeSxSProcess())
589 rename.AppendSwitch(installer::switches::kChromeSxS);
590
591 if (multi_install)
592 rename.AppendSwitch(installer::switches::kMultiInstall);
593
594 std::wstring version_key;
595 for (size_t i = 0; i < products.size(); ++i) {
596 BrowserDistribution* dist = products[i]->distribution();
597 version_key = dist->GetVersionKey();
598
599 if (current_version != NULL) {
600 in_use_update_work_items->AddSetRegValueWorkItem(root, version_key,
601 google_update::kRegOldVersionField,
602 UTF8ToWide(current_version->GetString()), true);
603 }
604
605 // Adding this registry entry for all products is overkill.
606 // However, as it stands, we don't have a way to know which distribution
607 // will check the key and run the command, so we add it for all.
608 // After the first run, the subsequent runs should just be noops.
609 // (see Upgrade::SwapNewChromeExeIfPresent).
610 in_use_update_work_items->AddSetRegValueWorkItem(
611 root,
612 version_key,
613 google_update::kRegRenameCmdField,
614 rename.command_line_string(),
615 true);
616 }
617
618 if (multi_install) {
619 PackageProperties* props = package.properties();
620 if (props->ReceivesUpdates() && current_version != NULL) {
621 in_use_update_work_items->AddSetRegValueWorkItem(
622 root,
623 props->GetVersionKey(),
624 google_update::kRegOldVersionField,
625 UTF8ToWide(current_version->GetString()),
626 true);
627 // TODO(tommi): We should move the rename command here. We also need to
628 // update Upgrade::SwapNewChromeExeIfPresent.
629 }
630 }
631
632 post_install_task_list->AddWorkItem(in_use_update_work_items.release());
633 }
634
635
636 // Append work items that will be executed if this was NOT an in-use update.
637 {
638 scoped_ptr<WorkItemList> regular_update_work_items(
639 WorkItem::CreateConditionalWorkItemList(
640 new Not(new ConditionRunIfFileExists(new_chrome_exe))));
641 regular_update_work_items->set_log_message(
642 "RegularUpdateWorkItemList");
643
644 // Since this was not an in-use-update, delete 'opv' and 'cmd' keys.
645 for (size_t i = 0; i < products.size(); ++i) {
646 BrowserDistribution* dist = products[i]->distribution();
647 std::wstring version_key(dist->GetVersionKey());
648 regular_update_work_items->AddDeleteRegValueWorkItem(root, version_key,
649 google_update::kRegOldVersionField,
650 true);
651 regular_update_work_items->AddDeleteRegValueWorkItem(root, version_key,
652 google_update::kRegRenameCmdField,
653 true);
654 }
655
656 post_install_task_list->AddWorkItem(regular_update_work_items.release());
657 }
658
659 AddRegisterComDllWorkItemsForPackage(package, current_version, new_version,
660 post_install_task_list);
661
662 for (size_t i = 0; i < products.size(); ++i) {
663 const Product* product = products[i];
664 // If we're told that we're an MSI install, make sure to set the marker
665 // in the client state key so that future updates do the right thing.
666 if (product->IsMsi()) {
667 AddSetMsiMarkerWorkItem(*product, true, post_install_task_list);
668
669 // We want MSI installs to take over the Add/Remove Programs shortcut.
670 // Make a best-effort attempt to delete any shortcuts left over from
671 // previous non-MSI installations for the same type of install (system or
672 // per user).
673 AddDeleteUninstallShortcutsForMSIWorkItems(*product,
674 post_install_task_list);
675 }
676 }
677
678 return true;
679 }
680
681 // This method tells if we are running on 64 bit platform so that we can copy
682 // one extra exe. If the API call to determine 64 bit fails, we play it safe
683 // and return true anyway so that the executable can be copied.
684 bool Is64bit() {
685 typedef BOOL (WINAPI *WOW_FUNC)(HANDLE, PBOOL);
686 BOOL is64 = FALSE;
687
688 HANDLE handle = GetCurrentProcess();
689 HMODULE module = GetModuleHandle(L"kernel32.dll");
690 WOW_FUNC p = reinterpret_cast<WOW_FUNC>(GetProcAddress(module,
691 "IsWow64Process"));
692 if ((p != NULL) && (!(p)(handle, &is64) || (is64 != FALSE))) {
693 return true;
694 }
695
696 return false;
697 }
698 219
699 void RegisterChromeOnMachine(const Product& product, 220 void RegisterChromeOnMachine(const Product& product,
700 bool make_chrome_default) { 221 bool make_chrome_default) {
701 DCHECK(product.is_chrome()); 222 DCHECK(product.is_chrome());
702 223
703 // Try to add Chrome to Media Player shim inclusion list. We don't do any 224 // Try to add Chrome to Media Player shim inclusion list. We don't do any
704 // error checking here because this operation will fail if user doesn't 225 // error checking here because this operation will fail if user doesn't
705 // have admin rights and we want to ignore the error. 226 // have admin rights and we want to ignore the error.
706 AddChromeToMediaPlayerList(); 227 AddChromeToMediaPlayerList();
707 228
708 // Is --make-chrome-default option is given we make Chrome default browser 229 // Is --make-chrome-default option is given we make Chrome default browser
709 // otherwise we only register it on the machine as a valid browser. 230 // otherwise we only register it on the machine as a valid browser.
710 FilePath chrome_exe( 231 FilePath chrome_exe(
711 product.package().path().Append(installer::kChromeExe)); 232 product.package().path().Append(installer::kChromeExe));
712 VLOG(1) << "Registering Chrome as browser: " << chrome_exe.value(); 233 VLOG(1) << "Registering Chrome as browser: " << chrome_exe.value();
713 if (make_chrome_default) { 234 if (make_chrome_default) {
714 int level = ShellUtil::CURRENT_USER; 235 int level = ShellUtil::CURRENT_USER;
715 if (product.system_level()) 236 if (product.system_level())
716 level = level | ShellUtil::SYSTEM_LEVEL; 237 level = level | ShellUtil::SYSTEM_LEVEL;
717 ShellUtil::MakeChromeDefault(product.distribution(), level, 238 ShellUtil::MakeChromeDefault(product.distribution(), level,
718 chrome_exe.value(), true); 239 chrome_exe.value(), true);
719 } else { 240 } else {
720 ShellUtil::RegisterChromeBrowser(product.distribution(), chrome_exe.value(), 241 ShellUtil::RegisterChromeBrowser(product.distribution(), chrome_exe.value(),
721 L"", false); 242 L"", false);
722 } 243 }
723 } 244 }
724 245
725 // Create Version key for a product (if not already present) and sets the new
726 // product version as the last step.
727 void AddVersionKeyWorkItems(HKEY root,
728 const Product& product,
729 const Version& new_version,
730 WorkItemList* list) {
731 // Create Version key for each distribution (if not already present) and set
732 // the new product version as the last step.
733 std::wstring version_key(product.distribution()->GetVersionKey());
734 list->AddCreateRegKeyWorkItem(root, version_key);
735
736 std::wstring product_name(product.distribution()->GetAppShortCutName());
737 list->AddSetRegValueWorkItem(root, version_key, google_update::kRegNameField,
738 product_name, true); // overwrite name also
739 list->AddSetRegValueWorkItem(root, version_key,
740 google_update::kRegOopcrashesField, 1,
741 false); // set during first install
742 list->AddSetRegValueWorkItem(root, version_key,
743 google_update::kRegVersionField,
744 UTF8ToWide(new_version.GetString()),
745 true); // overwrite version
746 }
747
748 void AddProductSpecificWorkItems(bool install,
749 const FilePath& setup_path,
750 const Version& new_version,
751 const Package& package,
752 WorkItemList* list) {
753 const Products& products = package.products();
754 for (size_t i = 0; i < products.size(); ++i) {
755 const Product& p = *products[i];
756 if (p.is_chrome_frame()) {
757 AddChromeFrameWorkItems(install, setup_path, new_version, p, list);
758 }
759 }
760 }
761
762 // This function installs a new version of Chrome to the specified location. 246 // This function installs a new version of Chrome to the specified location.
763 // 247 //
764 // setup_path: Path to the executable (setup.exe) as it will be copied 248 // setup_path: Path to the executable (setup.exe) as it will be copied
765 // to Chrome install folder after install is complete 249 // to Chrome install folder after install is complete
766 // archive_path: Path to the archive (chrome.7z) as it will be copied 250 // archive_path: Path to the archive (chrome.7z) as it will be copied
767 // to Chrome install folder after install is complete 251 // to Chrome install folder after install is complete
768 // src_path: the path that contains a complete and unpacked Chrome package 252 // src_path: the path that contains a complete and unpacked Chrome package
769 // to be installed. 253 // to be installed.
770 // temp_dir: the path of working directory used during installation. This path 254 // temp_dir: the path of working directory used during installation. This path
771 // does not need to exist. 255 // does not need to exist.
772 // new_version: new Chrome version that needs to be installed 256 // new_version: new Chrome version that needs to be installed
773 // oldest_installed_version: returns the oldest active version (if any) 257 // current_version: returns the current active version (if any)
774 // 258 //
775 // This function makes best effort to do installation in a transactional 259 // This function makes best effort to do installation in a transactional
776 // manner. If failed it tries to rollback all changes on the file system 260 // manner. If failed it tries to rollback all changes on the file system
777 // and registry. For example, if package exists before calling the 261 // and registry. For example, if package exists before calling the
778 // function, it rolls back all new file and directory changes under 262 // function, it rolls back all new file and directory changes under
779 // package. If package does not exist before calling the function 263 // package. If package does not exist before calling the function
780 // (typical new install), the function creates package during install 264 // (typical new install), the function creates package during install
781 // and removes the whole directory during rollback. 265 // and removes the whole directory during rollback.
782 installer::InstallStatus InstallNewVersion( 266 installer::InstallStatus InstallNewVersion(
783 const InstallationState& original_state, 267 const InstallationState& original_state,
784 const InstallerState& installer_state, 268 const InstallerState& installer_state,
785 bool multi_install, 269 bool multi_install,
786 const FilePath& setup_path, 270 const FilePath& setup_path,
787 const FilePath& archive_path, 271 const FilePath& archive_path,
788 const FilePath& src_path, 272 const FilePath& src_path,
789 const FilePath& temp_dir, 273 const FilePath& temp_dir,
790 const Version& new_version, 274 const Version& new_version,
791 scoped_ptr<Version>* current_version, 275 scoped_ptr<Version>* current_version,
792 const Package& package) { 276 const Package& package) {
793 DCHECK(current_version); 277 DCHECK(current_version);
794 278
795 const Products& products = package.products(); 279 current_version->reset(package.GetCurrentVersion());
796 DCHECK(products.size()); 280 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
797 281
798 if (FindProduct(products, BrowserDistribution::CHROME_FRAME)) { 282 AddInstallWorkItems(original_state,
799 // Make sure that we don't end up deleting installed files on next reboot. 283 installer_state,
800 if (!RemoveFromMovesPendingReboot(package.path().value().c_str())) { 284 multi_install,
801 LOG(ERROR) << "Error accessing pending moves value."; 285 setup_path,
802 } 286 archive_path,
803 } 287 src_path,
288 temp_dir,
289 new_version,
290 current_version,
291 package,
292 install_list.get());
804 293
805 current_version->reset(package.GetCurrentVersion());
806
807 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
808 // A temp directory that work items need and the actual install directory.
809 install_list->AddCreateDirWorkItem(temp_dir);
810 install_list->AddCreateDirWorkItem(package.path());
811
812 // Delete any new_chrome.exe if present (we will end up creating a new one
813 // if required) and then copy chrome.exe
814 FilePath new_chrome_exe( 294 FilePath new_chrome_exe(
815 package.path().Append(installer::kChromeNewExe)); 295 package.path().Append(installer::kChromeNewExe));
816 296
817 install_list->AddDeleteTreeWorkItem(new_chrome_exe);
818 install_list->AddCopyTreeWorkItem(
819 src_path.Append(installer::kChromeExe).value(),
820 package.path().Append(installer::kChromeExe).value(),
821 temp_dir.value(), WorkItem::NEW_NAME_IF_IN_USE, new_chrome_exe.value());
822
823 // Extra executable for 64 bit systems.
824 if (Is64bit()) {
825 install_list->AddCopyTreeWorkItem(
826 src_path.Append(installer::kWowHelperExe).value(),
827 package.path().Append(installer::kWowHelperExe).value(),
828 temp_dir.value(), WorkItem::ALWAYS);
829 }
830
831 // If it is system level install copy the version folder (since we want to
832 // take the permissions of %ProgramFiles% folder) otherwise just move it.
833 if (package.system_level()) {
834 install_list->AddCopyTreeWorkItem(
835 src_path.Append(UTF8ToWide(new_version.GetString())).value(),
836 package.path().Append(UTF8ToWide(new_version.GetString())).value(),
837 temp_dir.value(), WorkItem::ALWAYS);
838 } else {
839 install_list->AddMoveTreeWorkItem(
840 src_path.Append(UTF8ToWide(new_version.GetString())).value(),
841 package.path().Append(UTF8ToWide(new_version.GetString())).value(),
842 temp_dir.value());
843 }
844
845 // Copy the default Dictionaries only if the folder doesn't exist already.
846 install_list->AddCopyTreeWorkItem(
847 src_path.Append(installer::kDictionaries).value(),
848 package.path().Append(installer::kDictionaries).value(),
849 temp_dir.value(), WorkItem::IF_NOT_PRESENT);
850
851 // Delete any old_chrome.exe if present.
852 install_list->AddDeleteTreeWorkItem(
853 package.path().Append(installer::kChromeOldExe));
854
855 // Copy installer in install directory and
856 // add shortcut in Control Panel->Add/Remove Programs.
857 AddInstallerCopyTasks(setup_path, archive_path, temp_dir, new_version,
858 install_list.get(), package);
859
860 HKEY root = package.system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
861
862 for (size_t i = 0; i < products.size(); ++i) {
863 const Product* product = products[i];
864
865 AddUninstallShortcutWorkItems(setup_path, new_version, install_list.get(),
866 *product);
867
868 AddVersionKeyWorkItems(root, *product, new_version, install_list.get());
869 }
870
871 if (multi_install) {
872 PackageProperties* props = package.properties();
873 if (props->ReceivesUpdates()) {
874 std::wstring version_key(props->GetVersionKey());
875 install_list->AddCreateRegKeyWorkItem(root, version_key);
876 install_list->AddSetRegValueWorkItem(root, version_key,
877 google_update::kRegVersionField,
878 UTF8ToWide(new_version.GetString()),
879 true); // overwrite version
880 install_list->AddSetRegValueWorkItem(root, version_key,
881 google_update::kRegNameField,
882 ASCIIToWide(installer::PackageProperties::kPackageProductName),
883 true); // overwrite name also
884 }
885 }
886
887 // Add any remaining work items that involve special settings for
888 // each product.
889 AddProductSpecificWorkItems(true, setup_path, new_version, package,
890 install_list.get());
891
892 AddGoogleUpdateWorkItems(original_state, installer_state, package,
893 install_list.get());
894
895 // Append the tasks that run after the installation.
896 AppendPostInstallTasks(multi_install,
897 setup_path,
898 new_chrome_exe,
899 current_version->get(),
900 new_version,
901 package,
902 install_list.get());
903
904 if (!install_list->Do()) { 297 if (!install_list->Do()) {
905 installer::InstallStatus result = 298 installer::InstallStatus result =
906 file_util::PathExists(new_chrome_exe) && current_version->get() && 299 file_util::PathExists(new_chrome_exe) && current_version->get() &&
907 new_version.Equals(**current_version) ? 300 new_version.Equals(*current_version->get()) ?
908 installer::SAME_VERSION_REPAIR_FAILED : 301 installer::SAME_VERSION_REPAIR_FAILED :
909 installer::INSTALL_FAILED; 302 installer::INSTALL_FAILED;
910 LOG(ERROR) << "Install failed, rolling back... result: " << result; 303 LOG(ERROR) << "Install failed, rolling back... result: " << result;
911 install_list->Rollback(); 304 install_list->Rollback();
912 LOG(ERROR) << "Rollback complete. "; 305 LOG(ERROR) << "Rollback complete. ";
913 return result; 306 return result;
914 } 307 }
915 308
916 if (!current_version->get()) { 309 if (!current_version->get()) {
917 VLOG(1) << "First install of version " << new_version.GetString(); 310 VLOG(1) << "First install of version " << new_version.GetString();
(...skipping 29 matching lines...) Expand all
947 installer::InstallStatus InstallOrUpdateProduct( 340 installer::InstallStatus InstallOrUpdateProduct(
948 const InstallationState& original_state, 341 const InstallationState& original_state,
949 const InstallerState& installer_state, 342 const InstallerState& installer_state,
950 const FilePath& setup_path, const FilePath& archive_path, 343 const FilePath& setup_path, const FilePath& archive_path,
951 const FilePath& install_temp_path, const FilePath& prefs_path, 344 const FilePath& install_temp_path, const FilePath& prefs_path,
952 const installer::MasterPreferences& prefs, const Version& new_version, 345 const installer::MasterPreferences& prefs, const Version& new_version,
953 const Package& install) { 346 const Package& install) {
954 FilePath src_path(install_temp_path); 347 FilePath src_path(install_temp_path);
955 src_path = src_path.Append(kInstallSourceDir).Append(kInstallSourceChromeDir); 348 src_path = src_path.Append(kInstallSourceDir).Append(kInstallSourceChromeDir);
956 349
350 // TODO(robertshield): Removing the pending on-reboot moves should be done
351 // elsewhere.
352 const Products& products = install.products();
353 DCHECK(products.size());
354 if (FindProduct(products, BrowserDistribution::CHROME_FRAME)) {
355 // Make sure that we don't end up deleting installed files on next reboot.
356 if (!RemoveFromMovesPendingReboot(install.path().value().c_str())) {
357 LOG(ERROR) << "Error accessing pending moves value.";
358 }
359 }
360
957 scoped_ptr<Version> existing_version; 361 scoped_ptr<Version> existing_version;
958 installer::InstallStatus result = InstallNewVersion(original_state, 362 installer::InstallStatus result = InstallNewVersion(original_state,
959 installer_state, prefs.is_multi_install(), setup_path, archive_path, 363 installer_state, prefs.is_multi_install(), setup_path, archive_path,
960 src_path, install_temp_path, new_version, &existing_version, install); 364 src_path, install_temp_path, new_version, &existing_version, install);
961 365
366 // TODO(robertshield): Everything below this line should instead be captured
367 // by WorkItems.
962 if (!InstallUtil::GetInstallReturnCode(result)) { 368 if (!InstallUtil::GetInstallReturnCode(result)) {
963 if (result == installer::FIRST_INSTALL_SUCCESS && !prefs_path.empty()) 369 if (result == installer::FIRST_INSTALL_SUCCESS && !prefs_path.empty())
964 CopyPreferenceFileForFirstRun(install, prefs_path); 370 CopyPreferenceFileForFirstRun(install, prefs_path);
965 371
966 bool do_not_create_shortcuts = false; 372 bool do_not_create_shortcuts = false;
967 prefs.GetBool(installer::master_preferences::kDoNotCreateShortcuts, 373 prefs.GetBool(installer::master_preferences::kDoNotCreateShortcuts,
968 &do_not_create_shortcuts); 374 &do_not_create_shortcuts);
969 375
970 // Currently this only creates shortcuts for Chrome, but for other products 376 // Currently this only creates shortcuts for Chrome, but for other products
971 // we might want to create shortcuts. 377 // we might want to create shortcuts.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 make_chrome_default || force_chrome_default_for_user); 410 make_chrome_default || force_chrome_default_for_user);
1005 } 411 }
1006 412
1007 install.RemoveOldVersionDirectories(existing_version.get() ? 413 install.RemoveOldVersionDirectories(existing_version.get() ?
1008 *existing_version.get() : new_version); 414 *existing_version.get() : new_version);
1009 } 415 }
1010 416
1011 return result; 417 return result;
1012 } 418 }
1013 419
1014 void AddRegisterComDllWorkItems(const FilePath& dll_folder,
1015 const std::vector<FilePath>& dll_list,
1016 bool system_level,
1017 bool do_register,
1018 bool ignore_failures,
1019 WorkItemList* work_item_list) {
1020 DCHECK(work_item_list);
1021 if (dll_list.empty()) {
1022 VLOG(1) << "No COM DLLs to register";
1023 } else {
1024 std::vector<FilePath>::const_iterator dll_iter(dll_list.begin());
1025 for (; dll_iter != dll_list.end(); ++dll_iter) {
1026 FilePath dll_path = dll_folder.Append(*dll_iter);
1027 WorkItem* work_item = work_item_list->AddSelfRegWorkItem(
1028 dll_path.value(), do_register, !system_level);
1029 DCHECK(work_item);
1030 work_item->set_ignore_failure(ignore_failures);
1031 }
1032 }
1033 }
1034
1035 void AddSetMsiMarkerWorkItem(const Product& product,
1036 bool set,
1037 WorkItemList* work_item_list) {
1038 DCHECK(work_item_list);
1039 BrowserDistribution* dist = product.distribution();
1040 HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE :
1041 HKEY_CURRENT_USER;
1042 DWORD msi_value = set ? 1 : 0;
1043 WorkItem* set_msi_work_item = work_item_list->AddSetRegValueWorkItem(
1044 reg_root, dist->GetStateKey(), google_update::kRegMSIField,
1045 msi_value, true);
1046 DCHECK(set_msi_work_item);
1047 set_msi_work_item->set_ignore_failure(true);
1048 set_msi_work_item->set_log_message("Could not write MSI marker!");
1049 }
1050
1051 void AddChromeFrameWorkItems(bool install,
1052 const FilePath& setup_path,
1053 const Version& new_version,
1054 const Product& product,
1055 WorkItemList* list) {
1056 DCHECK(product.is_chrome_frame());
1057 if (!product.package().multi_install()) {
1058 VLOG(1) << "Not adding GCF specific work items for single install.";
1059 return;
1060 }
1061
1062 // TODO(tommi): This assumes we know exactly how ShouldCreateUninstallEntry
1063 // is implemented. Since there is logic in ChromeFrameDistribution for how
1064 // to determine when this is enabled, this is how we have to figure out if
1065 // this feature is enabled right now, but it's a hack and we need a cleaner
1066 // way to figure this out.
1067 // Note that we cannot just check the master preferences for
1068 // kChromeFrameReadyMode, since there are other things that need to be correct
1069 // in the environment in order to enable this feature.
1070 bool ready_mode = !product.distribution()->ShouldCreateUninstallEntry();
1071
1072 HKEY root = product.package().system_level() ? HKEY_LOCAL_MACHINE :
1073 HKEY_CURRENT_USER;
1074 bool update_chrome_uninstall_command = false;
1075 if (ready_mode) {
1076 // If GCF is being installed in ready mode, we write an entry to the
1077 // multi-install state key. If the value already exists, we will not
1078 // overwrite it since the user might have opted out.
1079 list->AddCreateRegKeyWorkItem(root,
1080 product.package().properties()->GetStateKey());
1081 list->AddSetRegValueWorkItem(root,
1082 product.package().properties()->GetStateKey(),
1083 installer::kChromeFrameReadyModeField,
1084 install ? 1 : 0, // The value we want to set.
1085 install ? false : true); // Overwrite existing value.
1086 if (!install) {
1087 // If Chrome is not also being uninstalled, we need to update its command
1088 // line so that it doesn't include uninstalling Chrome Frame now.
1089 update_chrome_uninstall_command =
1090 (installer::FindProduct(product.package().products(),
1091 BrowserDistribution::CHROME_BROWSER) == NULL);
1092 }
1093 } else {
1094 // It doesn't matter here if we're installing or uninstalling Chrome Frame.
1095 // If ready mode isn't specified on the command line for installs, we need
1096 // to delete the ready mode flag from the registry if it exists - this
1097 // constitutes an opt-in for the user. If we're uninstalling CF and ready
1098 // mode isn't specified on the command line, that means that CF wasn't
1099 // installed with ready mode enabled (the --ready-mode switch should be set
1100 // in the registry) so deleting the value should have no effect.
1101 // In both cases (install/uninstall), we need to make sure that Chrome's
1102 // uninstallation command line does not include the --chrome-frame switch
1103 // so that uninstalling Chrome will no longer uninstall Chrome Frame.
1104
1105 if (RegKey(root, product.package().properties()->GetStateKey().c_str(),
1106 KEY_QUERY_VALUE).Valid()) {
1107 list->AddDeleteRegValueWorkItem(root,
1108 product.package().properties()->GetStateKey(),
1109 installer::kChromeFrameReadyModeField, false);
1110 }
1111
1112 const Product* chrome = installer::FindProduct(product.package().products(),
1113 BrowserDistribution::CHROME_BROWSER);
1114 if (chrome) {
1115 // Chrome is already a part of this installation run, so we can assume
1116 // that the uninstallation arguments will be updated correctly.
1117 } else {
1118 // Chrome is not a part of this installation run, so we have to explicitly
1119 // check if Chrome is installed, and if so, update its uninstallation
1120 // command lines.
1121 BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
1122 BrowserDistribution::CHROME_BROWSER,
1123 MasterPreferences::ForCurrentProcess());
1124 update_chrome_uninstall_command =
1125 IsInstalledAsMulti(product.system_level(), dist);
1126 }
1127 }
1128
1129 if (update_chrome_uninstall_command) {
1130 // Chrome is not a part of this installation run, so we have to explicitly
1131 // check if Chrome is installed, and if so, update its uninstallation
1132 // command lines.
1133 const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
1134 BrowserDistribution* chrome_dist =
1135 BrowserDistribution::GetSpecificDistribution(
1136 BrowserDistribution::CHROME_BROWSER, prefs);
1137 const Package& pack = product.package();
1138 scoped_refptr<Package> package(new Package(pack.multi_install(),
1139 pack.system_level(), pack.path(), pack.properties()));
1140 scoped_refptr<Product> chrome_product(new Product(chrome_dist, package));
1141 AddUninstallShortcutWorkItems(setup_path, new_version, list,
1142 *chrome_product.get());
1143 }
1144 }
1145
1146 InstallStatus ChromeFrameReadyModeOptIn(const InstallerState& installer_state, 420 InstallStatus ChromeFrameReadyModeOptIn(const InstallerState& installer_state,
1147 const CommandLine& cmd_line) { 421 const CommandLine& cmd_line) {
1148 VLOG(1) << "Opting into Chrome Frame"; 422 VLOG(1) << "Opting into Chrome Frame";
1149 InstallStatus status = INSTALL_REPAIRED; 423 InstallStatus status = INSTALL_REPAIRED;
1150 424
1151 const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess(); 425 const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
1152 bool system_install = false; 426 bool system_install = false;
1153 prefs.GetBool(master_preferences::kSystemLevel, &system_install); 427 prefs.GetBool(master_preferences::kSystemLevel, &system_install);
1154 BrowserDistribution* cf = BrowserDistribution::GetSpecificDistribution( 428 BrowserDistribution* cf = BrowserDistribution::GetSpecificDistribution(
1155 BrowserDistribution::CHROME_FRAME, prefs); 429 BrowserDistribution::CHROME_FRAME, prefs);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1201 LOG(ERROR) << "Failed to opt into GCF"; 475 LOG(ERROR) << "Failed to opt into GCF";
1202 item_list->Rollback(); 476 item_list->Rollback();
1203 status = READY_MODE_OPT_IN_FAILED; 477 status = READY_MODE_OPT_IN_FAILED;
1204 } 478 }
1205 } 479 }
1206 480
1207 return status; 481 return status;
1208 } 482 }
1209 483
1210 } // namespace installer 484 } // namespace installer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698