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/setup/install_worker.h"
7 #include "base/win/registry.h"
8 #include "base/version.h"
9 #include "chrome/common/chrome_constants.h"
10 #include "chrome/installer/setup/setup_util.h"
11 #include "chrome/installer/util/delete_reg_key_work_item.h"
12 #include "chrome/installer/util/create_reg_key_work_item.h"
13 #include "chrome/installer/util/helper.h"
14 #include "chrome/installer/util/google_update_constants.h"
15 #include "chrome/installer/util/installation_state.h"
16 #include "chrome/installer/util/installer_state.h"
17 #include "chrome/installer/util/set_reg_value_work_item.h"
18 #include "chrome/installer/util/util_constants.h"
19 #include "chrome/installer/util/work_item_list.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "testing/gmock/include/gmock/gmock.h"
24 using base::win::RegKey;
25 using installer::InstallationState;
26 using installer::InstallerState;
27 using installer::Product;
28 using installer::ProductState;
31 using ::testing::AtLeast;
32 using ::testing::AtMost;
33 using ::testing::Bool;
34 using ::testing::Combine;
35 using ::testing::HasSubstr;
37 using ::testing::Return;
38 using ::testing::StrCaseEq;
39 using ::testing::StrEq;
40 using ::testing::StrictMock;
41 using ::testing::Values;
43 // Mock classes to help with testing
44 //------------------------------------------------------------------------------
46 class MockWorkItemList : public WorkItemList {
50 MOCK_METHOD4(AddCopyRegKeyWorkItem, WorkItem* (HKEY,
53 CopyOverWriteOption));
54 MOCK_METHOD5(AddCopyTreeWorkItem, WorkItem*(const std::wstring&,
58 const std::wstring&));
59 MOCK_METHOD1(AddCreateDirWorkItem, WorkItem* (const base::FilePath&));
60 MOCK_METHOD2(AddCreateRegKeyWorkItem, WorkItem* (HKEY, const std::wstring&));
61 MOCK_METHOD2(AddDeleteRegKeyWorkItem, WorkItem* (HKEY, const std::wstring&));
62 MOCK_METHOD3(AddDeleteRegValueWorkItem, WorkItem* (HKEY,
64 const std::wstring&));
65 MOCK_METHOD2(AddDeleteTreeWorkItem, WorkItem* (
66 const base::FilePath&,
67 const std::vector<base::FilePath>&));
68 MOCK_METHOD1(AddDeleteTreeWorkItem, WorkItem* (const base::FilePath&));
69 MOCK_METHOD3(AddMoveTreeWorkItem, WorkItem* (const std::wstring&,
71 const std::wstring&));
72 // Workaround for gmock problems with disambiguating between string pointers
74 virtual WorkItem* AddSetRegValueWorkItem(HKEY a1, const std::wstring& a2,
75 const std::wstring& a3, const std::wstring& a4, bool a5) {
76 return AddSetRegStringValueWorkItem(a1, a2, a3, a4, a5);
79 virtual WorkItem* AddSetRegValueWorkItem(HKEY a1, const std::wstring& a2,
80 const std::wstring& a3,
82 return AddSetRegDwordValueWorkItem(a1, a2, a3, a4, a5);
85 MOCK_METHOD5(AddSetRegStringValueWorkItem, WorkItem*(HKEY,
90 MOCK_METHOD5(AddSetRegDwordValueWorkItem, WorkItem* (HKEY,
95 MOCK_METHOD3(AddSelfRegWorkItem, WorkItem* (const std::wstring&,
100 class MockProductState : public ProductState {
102 // Takes ownership of |version|.
103 void set_version(Version* version) { version_.reset(version); }
104 void set_multi_install(bool multi) { multi_install_ = multi; }
105 void set_brand(const std::wstring& brand) { brand_ = brand; }
106 void set_eula_accepted(DWORD eula_accepted) {
107 has_eula_accepted_ = true;
108 eula_accepted_ = eula_accepted;
110 void clear_eula_accepted() { has_eula_accepted_ = false; }
111 void set_usagestats(DWORD usagestats) {
112 has_usagestats_ = true;
113 usagestats_ = usagestats;
115 void clear_usagestats() { has_usagestats_ = false; }
116 void set_oem_install(const std::wstring& oem_install) {
117 has_oem_install_ = true;
118 oem_install_ = oem_install;
120 void clear_oem_install() { has_oem_install_ = false; }
121 void SetUninstallProgram(const base::FilePath& setup_exe) {
122 uninstall_command_ = CommandLine(setup_exe);
124 void AddUninstallSwitch(const std::string& option) {
125 uninstall_command_.AppendSwitch(option);
129 // Okay, so this isn't really a mock as such, but it does add setter methods
130 // to make it easier to build custom InstallationStates.
131 class MockInstallationState : public InstallationState {
133 // Included for testing.
134 void SetProductState(bool system_install,
135 BrowserDistribution::Type type,
136 const ProductState& product_state) {
137 ProductState& target = (system_install ? system_products_ :
138 user_products_)[IndexFromDistType(type)];
139 target.CopyFrom(product_state);
143 class MockInstallerState : public InstallerState {
145 void set_level(Level level) {
146 InstallerState::set_level(level);
149 void set_operation(Operation operation) { operation_ = operation; }
151 void set_state_key(const std::wstring& state_key) {
152 state_key_ = state_key;
155 void set_state_type(BrowserDistribution::Type state_type) {
156 state_type_ = state_type;
159 void set_package_type(PackageType type) {
160 InstallerState::set_package_type(type);
165 //------------------------------------------------------------------------------
167 class InstallWorkerTest : public testing::Test {
169 virtual void SetUp() {
170 current_version_.reset(new Version("1.0.0.0"));
171 new_version_.reset(new Version("42.0.0.0"));
173 // Don't bother ensuring that these paths exist. Since we're just
174 // building the work item lists and not running them, they shouldn't
175 // actually be touched.
177 base::FilePath(L"C:\\UnlikelyPath\\Temp\\chrome_123\\chrome.7z");
178 // TODO(robertshield): Take this from the BrowserDistribution once that
179 // no longer depends on MasterPreferences.
181 base::FilePath(L"C:\\Program Files\\Google\\Chrome\\");
182 src_path_ = base::FilePath(
183 L"C:\\UnlikelyPath\\Temp\\chrome_123\\source\\Chrome-bin");
184 setup_path_ = base::FilePath(
185 L"C:\\UnlikelyPath\\Temp\\CR_123.tmp\\setup.exe");
186 temp_dir_ = base::FilePath(L"C:\\UnlikelyPath\\Temp\\chrome_123");
189 virtual void TearDown() {
192 void MaybeAddBinariesToInstallationState(
194 MockInstallationState* installation_state) {
195 if (installation_state->GetProductState(
196 system_level, BrowserDistribution::CHROME_BINARIES) == NULL) {
197 MockProductState product_state;
198 product_state.set_version(new Version(*current_version_));
199 product_state.set_brand(L"TEST");
200 product_state.set_multi_install(true);
201 BrowserDistribution* dist =
202 BrowserDistribution::GetSpecificDistribution(
203 BrowserDistribution::CHROME_BINARIES);
204 base::FilePath install_path =
205 installer::GetChromeInstallPath(system_level, dist);
206 product_state.SetUninstallProgram(
207 install_path.AppendASCII(current_version_->GetString())
208 .Append(installer::kInstallerDir)
209 .Append(installer::kSetupExe));
210 product_state.AddUninstallSwitch(installer::switches::kUninstall);
211 product_state.AddUninstallSwitch(installer::switches::kMultiInstall);
213 product_state.AddUninstallSwitch(installer::switches::kSystemLevel);
214 installation_state->SetProductState(system_level,
215 BrowserDistribution::CHROME_BINARIES,
220 void AddChromeToInstallationState(
223 bool with_chrome_frame_ready_mode,
224 MockInstallationState* installation_state) {
226 MaybeAddBinariesToInstallationState(system_level, installation_state);
227 MockProductState product_state;
228 product_state.set_version(new Version(*current_version_));
229 product_state.set_multi_install(multi_install);
230 product_state.set_brand(L"TEST");
231 product_state.set_eula_accepted(1);
232 BrowserDistribution* dist =
233 BrowserDistribution::GetSpecificDistribution(
234 BrowserDistribution::CHROME_BROWSER);
235 base::FilePath install_path =
236 installer::GetChromeInstallPath(system_level, dist);
237 product_state.SetUninstallProgram(
238 install_path.AppendASCII(current_version_->GetString())
239 .Append(installer::kInstallerDir)
240 .Append(installer::kSetupExe));
241 product_state.AddUninstallSwitch(installer::switches::kUninstall);
243 product_state.AddUninstallSwitch(installer::switches::kSystemLevel);
245 product_state.AddUninstallSwitch(installer::switches::kMultiInstall);
246 product_state.AddUninstallSwitch(installer::switches::kChrome);
247 if (with_chrome_frame_ready_mode) {
248 product_state.AddUninstallSwitch(installer::switches::kChromeFrame);
249 product_state.AddUninstallSwitch(
250 installer::switches::kChromeFrameReadyMode);
254 installation_state->SetProductState(system_level,
255 BrowserDistribution::CHROME_BROWSER,
259 void AddChromeFrameToInstallationState(
263 MockInstallationState* installation_state) {
265 MaybeAddBinariesToInstallationState(system_level, installation_state);
266 MockProductState product_state;
267 product_state.set_version(new Version(*current_version_));
268 product_state.set_multi_install(multi_install);
269 BrowserDistribution* dist =
270 BrowserDistribution::GetSpecificDistribution(
271 multi_install ? BrowserDistribution::CHROME_BINARIES :
272 BrowserDistribution::CHROME_FRAME);
273 base::FilePath install_path =
274 installer::GetChromeInstallPath(system_level, dist);
275 product_state.SetUninstallProgram(
276 install_path.AppendASCII(current_version_->GetString())
277 .Append(installer::kInstallerDir)
278 .Append(installer::kSetupExe));
279 product_state.AddUninstallSwitch(installer::switches::kUninstall);
280 product_state.AddUninstallSwitch(installer::switches::kChromeFrame);
282 product_state.AddUninstallSwitch(installer::switches::kSystemLevel);
284 product_state.AddUninstallSwitch(installer::switches::kMultiInstall);
286 product_state.AddUninstallSwitch(
287 installer::switches::kChromeFrameReadyMode);
291 installation_state->SetProductState(system_level,
292 BrowserDistribution::CHROME_FRAME,
296 MockInstallationState* BuildChromeInstallationState(bool system_level,
297 bool multi_install) {
298 scoped_ptr<MockInstallationState> installation_state(
299 new MockInstallationState());
300 AddChromeToInstallationState(system_level, multi_install, false,
301 installation_state.get());
302 return installation_state.release();
305 static MockInstallerState* BuildBasicInstallerState(
308 const InstallationState& machine_state,
309 InstallerState::Operation operation) {
310 scoped_ptr<MockInstallerState> installer_state(new MockInstallerState());
312 InstallerState::Level level = system_install ?
313 InstallerState::SYSTEM_LEVEL : InstallerState::USER_LEVEL;
314 installer_state->set_level(level);
315 installer_state->set_operation(operation);
316 // Hope this next one isn't checked for now.
317 installer_state->set_state_key(L"PROBABLY_INVALID_REG_PATH");
318 installer_state->set_state_type(BrowserDistribution::CHROME_BROWSER);
319 installer_state->set_package_type(multi_install ?
320 InstallerState::MULTI_PACKAGE :
321 InstallerState::SINGLE_PACKAGE);
322 return installer_state.release();
325 static void AddChromeBinariesToInstallerState(
326 const InstallationState& machine_state,
327 MockInstallerState* installer_state) {
328 if (!installer_state->is_multi_install()) {
332 if (installer_state->FindProduct(BrowserDistribution::CHROME_BINARIES))
335 // Fresh install or upgrade?
336 const ProductState* chrome_binaries =
337 machine_state.GetProductState(installer_state->system_install(),
338 BrowserDistribution::CHROME_BINARIES);
339 if (chrome_binaries != NULL) {
340 installer_state->AddProductFromState(BrowserDistribution::CHROME_BINARIES,
343 BrowserDistribution* dist =
344 BrowserDistribution::GetSpecificDistribution(
345 BrowserDistribution::CHROME_BINARIES);
346 scoped_ptr<Product> product(new Product(dist));
347 product->SetOption(installer::kOptionMultiInstall, true);
348 installer_state->AddProduct(&product);
352 static void AddChromeToInstallerState(
353 const InstallationState& machine_state,
354 MockInstallerState* installer_state) {
355 // Fresh install or upgrade?
356 const ProductState* chrome =
357 machine_state.GetProductState(installer_state->system_install(),
358 BrowserDistribution::CHROME_BROWSER);
359 if (chrome != NULL &&
360 chrome->is_multi_install() == installer_state->is_multi_install()) {
361 installer_state->AddProductFromState(BrowserDistribution::CHROME_BROWSER,
364 BrowserDistribution* dist =
365 BrowserDistribution::GetSpecificDistribution(
366 BrowserDistribution::CHROME_BROWSER);
367 scoped_ptr<Product> product(new Product(dist));
368 if (installer_state->is_multi_install())
369 product->SetOption(installer::kOptionMultiInstall, true);
370 installer_state->AddProduct(&product);
374 static void AddChromeFrameToInstallerState(
375 const InstallationState& machine_state,
377 MockInstallerState* installer_state) {
378 // Fresh install or upgrade?
379 const ProductState* cf =
380 machine_state.GetProductState(installer_state->system_install(),
381 BrowserDistribution::CHROME_FRAME);
383 installer_state->AddProductFromState(BrowserDistribution::CHROME_FRAME,
386 BrowserDistribution* dist =
387 BrowserDistribution::GetSpecificDistribution(
388 BrowserDistribution::CHROME_FRAME);
389 scoped_ptr<Product> product(new Product(dist));
390 if (installer_state->is_multi_install()) {
391 product->SetOption(installer::kOptionMultiInstall, true);
393 product->SetOption(installer::kOptionReadyMode, true);
395 installer_state->AddProduct(&product);
399 static MockInstallerState* BuildChromeInstallerState(
402 const InstallationState& machine_state,
403 InstallerState::Operation operation) {
404 scoped_ptr<MockInstallerState> installer_state(
405 BuildBasicInstallerState(system_install, multi_install, machine_state,
408 // We don't want to include Chrome Binaries for uninstall if the machine
409 // has other products. For simplicity, we check Chrome Frame only.
410 bool machine_has_other_products =
411 machine_state.GetProductState(system_install,
412 BrowserDistribution::CHROME_FRAME) != NULL;
413 if (operation != InstallerState::UNINSTALL || !machine_has_other_products)
414 AddChromeBinariesToInstallerState(machine_state, installer_state.get());
416 AddChromeToInstallerState(machine_state, installer_state.get());
417 return installer_state.release();
420 static MockInstallerState* BuildChromeFrameInstallerState(
424 const InstallationState& machine_state,
425 InstallerState::Operation operation) {
426 // This method only works for installation/upgrade.
427 DCHECK(operation != InstallerState::UNINSTALL);
428 scoped_ptr<MockInstallerState> installer_state(
429 BuildBasicInstallerState(system_install, multi_install, machine_state,
432 AddChromeBinariesToInstallerState(machine_state, installer_state.get());
433 AddChromeFrameToInstallerState(machine_state, ready_mode,
434 installer_state.get());
435 return installer_state.release();
439 scoped_ptr<Version> current_version_;
440 scoped_ptr<Version> new_version_;
441 base::FilePath archive_path_;
442 base::FilePath installation_path_;
443 base::FilePath setup_path_;
444 base::FilePath src_path_;
445 base::FilePath temp_dir_;
449 //------------------------------------------------------------------------------
451 TEST_F(InstallWorkerTest, TestInstallChromeSingleSystem) {
452 const bool system_level = true;
453 const bool multi_install = false;
454 MockWorkItemList work_item_list;
456 scoped_ptr<InstallationState> installation_state(
457 BuildChromeInstallationState(system_level, multi_install));
459 scoped_ptr<InstallerState> installer_state(
460 BuildChromeInstallerState(system_level, multi_install,
462 InstallerState::SINGLE_INSTALL_OR_UPDATE));
464 // Set up some expectations.
465 // TODO(robertshield): Set up some real expectations.
466 EXPECT_CALL(work_item_list, AddCopyTreeWorkItem(_, _, _, _, _))
469 AddInstallWorkItems(*installation_state.get(),
470 *installer_state.get(),
475 current_version_.get(),
482 const wchar_t elevation_key[] =
483 L"SOFTWARE\\Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\\"
484 L"{E0A900DF-9611-4446-86BD-4B1D47E7DB2A}";
485 const wchar_t old_elevation_key[] =
486 L"SOFTWARE\\Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\\"
487 L"{6C288DD7-76FB-4721-B628-56FAC252E199}";
491 // A test class for worker functions that manipulate the old IE low rights
494 // bool : system_level_
495 // bool : multi_install_
496 class OldIELowRightsTests : public InstallWorkerTest,
497 public ::testing::WithParamInterface<std::tr1::tuple<bool, bool> > {
499 virtual void SetUp() OVERRIDE {
500 InstallWorkerTest::SetUp();
502 const ParamType& param = GetParam();
503 system_level_ = std::tr1::get<0>(param);
504 multi_install_ = std::tr1::get<1>(param);
505 root_key_ = system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
507 installation_state_.reset(new MockInstallationState());
508 AddChromeFrameToInstallationState(system_level_, multi_install_, false,
509 installation_state_.get());
510 installer_state_.reset(BuildBasicInstallerState(
511 system_level_, multi_install_, *installation_state_,
512 multi_install_ ? InstallerState::MULTI_UPDATE :
513 InstallerState::SINGLE_INSTALL_OR_UPDATE));
515 AddChromeBinariesToInstallerState(*installation_state_,
516 installer_state_.get());
517 AddChromeFrameToInstallerState(*installation_state_, false,
518 installer_state_.get());
521 scoped_ptr<MockInstallationState> installation_state_;
522 scoped_ptr<MockInstallerState> installer_state_;
528 TEST_P(OldIELowRightsTests, AddDeleteOldIELowRightsPolicyWorkItems) {
529 StrictMock<MockWorkItemList> work_item_list;
531 EXPECT_CALL(work_item_list,
532 AddDeleteRegKeyWorkItem(root_key_, StrEq(old_elevation_key)))
535 AddDeleteOldIELowRightsPolicyWorkItems(*installer_state_.get(),
539 TEST_P(OldIELowRightsTests, AddCopyIELowRightsPolicyWorkItems) {
540 StrictMock<MockWorkItemList> work_item_list;
542 // The old elevation policy key should only be copied when there's no old
544 EXPECT_CALL(work_item_list,
545 AddCopyRegKeyWorkItem(root_key_, StrEq(elevation_key),
546 StrEq(old_elevation_key),
547 Eq(WorkItem::IF_NOT_PRESENT))).Times(1);
549 AddCopyIELowRightsPolicyWorkItems(*installer_state_.get(), &work_item_list);
552 INSTANTIATE_TEST_CASE_P(Variations, OldIELowRightsTests,
553 Combine(Bool(), Bool()));
555 TEST_F(InstallWorkerTest, GoogleUpdateWorkItemsTest) {
556 const bool system_level = true;
557 const bool multi_install = true;
558 MockWorkItemList work_item_list;
560 scoped_ptr<MockInstallationState> installation_state(
561 BuildChromeInstallationState(system_level, false));
563 MockProductState cf_state;
564 cf_state.set_version(new Version(*current_version_));
565 cf_state.set_multi_install(false);
567 installation_state->SetProductState(system_level,
568 BrowserDistribution::CHROME_FRAME, cf_state);
570 scoped_ptr<MockInstallerState> installer_state(
571 BuildChromeInstallerState(system_level, multi_install,
573 InstallerState::MULTI_INSTALL));
575 // Expect the multi Client State key to be created.
576 BrowserDistribution* multi_dist =
577 BrowserDistribution::GetSpecificDistribution(
578 BrowserDistribution::CHROME_BINARIES);
579 std::wstring multi_app_guid(multi_dist->GetAppGuid());
580 std::wstring multi_client_state_suffix(L"ClientState\\" + multi_app_guid);
581 EXPECT_CALL(work_item_list,
582 AddCreateRegKeyWorkItem(_, HasSubstr(multi_client_state_suffix)))
583 .Times(testing::AnyNumber());
585 // Expect ClientStateMedium to be created for system-level installs.
586 EXPECT_CALL(work_item_list,
587 AddCreateRegKeyWorkItem(_, HasSubstr(L"ClientStateMedium\\" +
589 .Times(system_level ? 1 : 0);
591 // Expect to see a set value for the "TEST" brand code in the multi Client
593 EXPECT_CALL(work_item_list,
594 AddSetRegStringValueWorkItem(_,
595 HasSubstr(multi_client_state_suffix),
596 StrEq(google_update::kRegBrandField),
600 // There may also be some calls to set 'ap' values.
601 EXPECT_CALL(work_item_list,
602 AddSetRegStringValueWorkItem(_, _,
603 StrEq(google_update::kRegApField),
604 _, _)).Times(testing::AnyNumber());
606 // Expect "oeminstall" to be cleared.
607 EXPECT_CALL(work_item_list,
608 AddDeleteRegValueWorkItem(
610 HasSubstr(multi_client_state_suffix),
611 StrEq(google_update::kRegOemInstallField))).Times(1);
613 // Expect "eulaaccepted" to set.
614 EXPECT_CALL(work_item_list,
615 AddSetRegDwordValueWorkItem(
617 HasSubstr(multi_client_state_suffix),
618 StrEq(google_update::kRegEULAAceptedField),
619 Eq(static_cast<DWORD>(1)),
622 AddGoogleUpdateWorkItems(*installation_state.get(),
623 *installer_state.get(),
627 // Test that usagestats values are migrated properly.
628 TEST_F(InstallWorkerTest, AddUsageStatsWorkItems) {
629 const bool system_level = true;
630 const bool multi_install = true;
631 MockWorkItemList work_item_list;
633 scoped_ptr<MockInstallationState> installation_state(
634 BuildChromeInstallationState(system_level, multi_install));
636 MockProductState chrome_state;
637 chrome_state.set_version(new Version(*current_version_));
638 chrome_state.set_multi_install(false);
639 chrome_state.set_usagestats(1);
641 installation_state->SetProductState(system_level,
642 BrowserDistribution::CHROME_BROWSER, chrome_state);
644 scoped_ptr<MockInstallerState> installer_state(
645 BuildChromeInstallerState(system_level, multi_install,
647 InstallerState::MULTI_INSTALL));
649 // Expect the multi Client State key to be created.
650 BrowserDistribution* multi_dist =
651 BrowserDistribution::GetSpecificDistribution(
652 BrowserDistribution::CHROME_BINARIES);
653 std::wstring multi_app_guid(multi_dist->GetAppGuid());
654 EXPECT_CALL(work_item_list,
655 AddCreateRegKeyWorkItem(_, HasSubstr(multi_app_guid))).Times(1);
657 // Expect to see a set value for the usagestats in the multi Client State key.
658 EXPECT_CALL(work_item_list,
659 AddSetRegDwordValueWorkItem(
661 HasSubstr(multi_app_guid),
662 StrEq(google_update::kRegUsageStatsField),
663 Eq(static_cast<DWORD>(1)),
666 // Expect to see some values cleaned up from Chrome's keys.
667 BrowserDistribution* chrome_dist =
668 BrowserDistribution::GetSpecificDistribution(
669 BrowserDistribution::CHROME_BROWSER);
671 EXPECT_CALL(work_item_list,
672 AddDeleteRegValueWorkItem(
674 StrEq(chrome_dist->GetStateMediumKey()),
675 StrEq(google_update::kRegUsageStatsField))).Times(1);
676 EXPECT_CALL(work_item_list,
677 AddDeleteRegValueWorkItem(
678 Eq(HKEY_CURRENT_USER),
679 StrEq(chrome_dist->GetStateKey()),
680 StrEq(google_update::kRegUsageStatsField))).Times(1);
682 EXPECT_CALL(work_item_list,
683 AddDeleteRegValueWorkItem(
684 Eq(installer_state->root_key()),
685 StrEq(chrome_dist->GetStateKey()),
686 StrEq(google_update::kRegUsageStatsField))).Times(1);
688 AddUsageStatsWorkItems(*installation_state.get(),
689 *installer_state.get(),
693 // The Quick Enable tests only make sense for the Google Chrome build as it
694 // interacts with registry values that are specific to Google Update.
695 #if defined(GOOGLE_CHROME_BUILD)
697 // Test scenarios under which the quick-enable-cf command should not exist after
698 // the run. We're permissive in that we allow the DeleteRegKeyWorkItem even if
699 // it isn't strictly needed.
700 class QuickEnableAbsentTest : public InstallWorkerTest {
702 virtual void SetUp() {
703 InstallWorkerTest::SetUp();
704 root_key_ = system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
705 delete_reg_key_item_.reset(
706 WorkItem::CreateDeleteRegKeyWorkItem(root_key_, kRegKeyPath));
707 machine_state_.reset(new MockInstallationState());
708 EXPECT_CALL(work_item_list_,
709 AddDeleteRegKeyWorkItem(Eq(root_key_), StrCaseEq(kRegKeyPath)))
711 .WillRepeatedly(Return(delete_reg_key_item_.get()));
713 virtual void TearDown() {
714 machine_state_.reset();
715 delete_reg_key_item_.reset();
717 InstallWorkerTest::TearDown();
720 static const bool system_level_ = false;
721 static const wchar_t kRegKeyPath[];
723 scoped_ptr<DeleteRegKeyWorkItem> delete_reg_key_item_;
724 scoped_ptr<MockInstallationState> machine_state_;
725 StrictMock<MockWorkItemList> work_item_list_;
728 const wchar_t QuickEnableAbsentTest::kRegKeyPath[] =
729 L"Software\\Google\\Update\\Clients\\"
730 L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}\\Commands\\quick-enable-cf";
732 TEST_F(QuickEnableAbsentTest, CleanInstallSingleChrome) {
733 // Install single Chrome on a clean system.
734 scoped_ptr<MockInstallerState> installer_state(
735 BuildChromeInstallerState(system_level_, false, *machine_state_,
736 InstallerState::SINGLE_INSTALL_OR_UPDATE));
737 AddQuickEnableChromeFrameWorkItems(*installer_state,
744 TEST_F(QuickEnableAbsentTest, CleanInstallSingleChromeFrame) {
745 // Install single Chrome Frame on a clean system.
746 scoped_ptr<MockInstallerState> installer_state(
747 BuildChromeFrameInstallerState(system_level_, false, false,
749 InstallerState::SINGLE_INSTALL_OR_UPDATE));
750 AddQuickEnableChromeFrameWorkItems(*installer_state,
757 TEST_F(QuickEnableAbsentTest, CleanInstallMultiChromeFrame) {
758 // Install multi Chrome Frame on a clean system.
759 scoped_ptr<MockInstallerState> installer_state(
760 BuildChromeFrameInstallerState(system_level_, true, false,
762 InstallerState::MULTI_INSTALL));
763 AddQuickEnableChromeFrameWorkItems(*installer_state,
770 TEST_F(QuickEnableAbsentTest, CleanInstallMultiChromeChromeFrame) {
771 // Install multi Chrome and Chrome Frame on a clean system.
772 scoped_ptr<MockInstallerState> installer_state(
773 BuildBasicInstallerState(system_level_, true, *machine_state_,
774 InstallerState::MULTI_INSTALL));
775 AddChromeBinariesToInstallerState(*machine_state_, installer_state.get());
776 AddChromeToInstallerState(*machine_state_, installer_state.get());
777 AddChromeFrameToInstallerState(*machine_state_, false,
778 installer_state.get());
779 AddQuickEnableChromeFrameWorkItems(*installer_state,
786 TEST_F(QuickEnableAbsentTest, UninstallMultiChromeLeaveMultiChromeFrame) {
787 // Uninstall multi Chrome on a machine with multi Chrome Frame.
788 AddChromeToInstallationState(system_level_, true, false,
789 machine_state_.get());
790 AddChromeFrameToInstallationState(system_level_, true, false,
791 machine_state_.get());
792 scoped_ptr<MockInstallerState> installer_state(
793 BuildBasicInstallerState(system_level_, true, *machine_state_,
794 InstallerState::UNINSTALL));
795 AddChromeToInstallerState(*machine_state_, installer_state.get());
796 AddQuickEnableChromeFrameWorkItems(*installer_state,
803 TEST_F(QuickEnableAbsentTest, UninstallMultiChromeLeaveSingleChromeFrame) {
804 // Uninstall multi Chrome on a machine with single Chrome Frame.
805 AddChromeToInstallationState(system_level_, true, false,
806 machine_state_.get());
807 AddChromeFrameToInstallationState(system_level_, false, false,
808 machine_state_.get());
809 scoped_ptr<MockInstallerState> installer_state(
810 BuildBasicInstallerState(system_level_, true, *machine_state_,
811 InstallerState::UNINSTALL));
812 AddChromeToInstallerState(*machine_state_, installer_state.get());
813 AddChromeBinariesToInstallerState(*machine_state_, installer_state.get());
814 AddQuickEnableChromeFrameWorkItems(*installer_state,
821 TEST_F(QuickEnableAbsentTest, AcceptReadyMode) {
822 // Accept ready-mode.
823 AddChromeToInstallationState(system_level_, true, true,
824 machine_state_.get());
825 AddChromeFrameToInstallationState(system_level_, true, true,
826 machine_state_.get());
827 scoped_ptr<MockInstallerState> installer_state(
828 BuildBasicInstallerState(system_level_, true, *machine_state_,
829 InstallerState::UNINSTALL));
830 AddChromeToInstallerState(*machine_state_, installer_state.get());
831 AddChromeFrameToInstallerState(*machine_state_, false, installer_state.get());
832 AddChromeBinariesToInstallerState(*machine_state_, installer_state.get());
833 AddQuickEnableChromeFrameWorkItems(*installer_state,
840 // Test scenarios under which the quick-enable-cf command should exist after the
842 class QuickEnablePresentTest : public InstallWorkerTest {
844 virtual void SetUp() {
845 InstallWorkerTest::SetUp();
846 root_key_ = system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
847 create_reg_key_work_item_.reset(
848 WorkItem::CreateCreateRegKeyWorkItem(root_key_, kRegKeyPath));
849 set_reg_value_work_item_.reset(
850 WorkItem::CreateSetRegValueWorkItem(root_key_, kRegKeyPath, L"", L"",
852 machine_state_.reset(new MockInstallationState());
853 EXPECT_CALL(work_item_list_,
854 AddCreateRegKeyWorkItem(Eq(root_key_), StrCaseEq(kRegKeyPath)))
856 .WillOnce(Return(create_reg_key_work_item_.get()));
857 EXPECT_CALL(work_item_list_,
858 AddSetRegStringValueWorkItem(Eq(root_key_),
859 StrCaseEq(kRegKeyPath),
860 StrEq(L"CommandLine"), _,
863 .WillOnce(Return(set_reg_value_work_item_.get()));
864 EXPECT_CALL(work_item_list_,
865 AddSetRegDwordValueWorkItem(Eq(root_key_),
866 StrCaseEq(kRegKeyPath), _,
867 Eq(static_cast<DWORD>(1)),
870 .WillRepeatedly(Return(set_reg_value_work_item_.get()));
872 virtual void TearDown() {
873 machine_state_.reset();
874 set_reg_value_work_item_.reset();
875 create_reg_key_work_item_.reset();
877 InstallWorkerTest::TearDown();
880 static const bool system_level_ = false;
881 static const wchar_t kRegKeyPath[];
883 scoped_ptr<CreateRegKeyWorkItem> create_reg_key_work_item_;
884 scoped_ptr<SetRegValueWorkItem> set_reg_value_work_item_;
885 scoped_ptr<MockInstallationState> machine_state_;
886 StrictMock<MockWorkItemList> work_item_list_;
889 const wchar_t QuickEnablePresentTest::kRegKeyPath[] =
890 L"Software\\Google\\Update\\Clients\\"
891 L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}\\Commands\\quick-enable-cf";
893 TEST_F(QuickEnablePresentTest, CleanInstallMultiChrome) {
894 // Install multi Chrome on a clean system.
895 scoped_ptr<MockInstallerState> installer_state(
896 BuildChromeInstallerState(system_level_, true, *machine_state_,
897 InstallerState::MULTI_INSTALL));
898 AddQuickEnableChromeFrameWorkItems(*installer_state,
905 TEST_F(QuickEnablePresentTest, CleanInstallMultiChromeReadyMode) {
906 // Install multi Chrome with Chrome Frame ready-mode on a clean system.
907 scoped_ptr<MockInstallerState> installer_state(
908 BuildBasicInstallerState(system_level_, true, *machine_state_,
909 InstallerState::MULTI_INSTALL));
910 AddChromeBinariesToInstallerState(*machine_state_, installer_state.get());
911 AddChromeToInstallerState(*machine_state_, installer_state.get());
912 AddChromeFrameToInstallerState(*machine_state_, true,
913 installer_state.get());
914 AddQuickEnableChromeFrameWorkItems(*installer_state,
921 TEST_F(QuickEnablePresentTest, UninstallSingleChromeFrame) {
922 // Uninstall single Chrome Frame on a machine with multi Chrome.
923 AddChromeToInstallationState(system_level_, true, false,
924 machine_state_.get());
925 AddChromeFrameToInstallationState(system_level_, false, false,
926 machine_state_.get());
927 scoped_ptr<MockInstallerState> installer_state(
928 BuildBasicInstallerState(system_level_, false, *machine_state_,
929 InstallerState::UNINSTALL));
930 AddChromeFrameToInstallerState(*machine_state_, false, installer_state.get());
931 AddQuickEnableChromeFrameWorkItems(*installer_state,
938 TEST_F(QuickEnablePresentTest, UninstallMultiChromeFrame) {
939 // Uninstall multi Chrome Frame on a machine with multi Chrome.
940 AddChromeToInstallationState(system_level_, true, false,
941 machine_state_.get());
942 AddChromeFrameToInstallationState(system_level_, true, false,
943 machine_state_.get());
944 scoped_ptr<MockInstallerState> installer_state(
945 BuildBasicInstallerState(system_level_, true, *machine_state_,
946 InstallerState::UNINSTALL));
947 AddChromeFrameToInstallerState(*machine_state_, false, installer_state.get());
948 AddQuickEnableChromeFrameWorkItems(*installer_state,
955 TEST_F(InstallWorkerTest, WillProductBePresentAfterSetup) {
956 BrowserDistribution::Type prod_type_list[] = {
957 BrowserDistribution::CHROME_BROWSER,
958 BrowserDistribution::CHROME_FRAME,
959 // Excluding BrowserDistribution::CHROME_BINARIES, since it is installed
960 // along with other products.
962 enum { // Index into prod_type_list[].
965 NUM_TYPE // This must appear last.
967 DCHECK(arraysize(prod_type_list) == NUM_TYPE);
968 InstallerState::Operation op_list[] = {
969 InstallerState::UNINSTALL,
970 InstallerState::SINGLE_INSTALL_OR_UPDATE
973 const bool system_level = false;
974 const bool multi_install = true;
976 // Loop over machine states: {No product, Chrome, CF, Chrome + CF}.
977 for (int i_mach = 0; i_mach < (1 << NUM_TYPE); ++i_mach) {
978 // i_mach is the machine state before operation, as bit mask.
979 scoped_ptr<MockInstallationState> machine_state(
980 new MockInstallationState());
981 if ((i_mach & (1 << TYPE_BROWSER)) != 0) { // Add Chrome.
982 AddChromeToInstallationState(system_level, multi_install, false,
983 machine_state.get());
985 if ((i_mach & (1 << TYPE_CF)) != 0) { // Add Chrome Frame.
986 AddChromeFrameToInstallationState(system_level, multi_install, false,
987 machine_state.get());
990 // Loop over operations: {uninstall, install/update}.
991 for (int i_op = 0; i_op < arraysize(op_list); ++i_op) {
993 // Loop over product types to operate on: {TYPE_BROWSER, TYPE_CF}.
994 for (int i_type_op = 0; i_type_op < NUM_TYPE; ++i_type_op) {
995 scoped_ptr<InstallerState> installer_state;
996 if (i_type_op == TYPE_BROWSER) {
997 installer_state.reset(BuildChromeInstallerState(
998 system_level, multi_install, *machine_state, op_list[i_op]));
999 } else if (i_type_op == TYPE_CF) {
1000 // Skip the CF uninstall case due to limitations in
1001 // BuildChromeFrameInstallerState().
1002 if (op_list[i_op] == InstallerState::UNINSTALL)
1005 installer_state.reset(BuildChromeFrameInstallerState(
1006 system_level, multi_install, false, *machine_state,
1012 // Calculate the machine state after operation, as bit mask.
1013 // If uninstall, remove product with bitwise AND; else add with OR.
1014 int mach_after = (op_list[i_op] == InstallerState::UNINSTALL) ?
1015 i_mach & ~(1 << i_type_op) : i_mach | (1 << i_type_op);
1017 // Verify predicted presence of Chrome Binaries.
1018 bool bin_res = installer::WillProductBePresentAfterSetup(
1021 BrowserDistribution::CHROME_BINARIES);
1022 // Binaries are expected to be present iff any product is installed.
1023 bool bin_expect = mach_after != 0;
1024 EXPECT_EQ(bin_expect, bin_res);
1026 // Loop over product types to check: {TYPE_BROWSER, TYPE_CF}.
1027 for (int i_type_check = 0; i_type_check < NUM_TYPE; ++i_type_check) {
1028 // Verify predicted presence of product.
1029 bool prod_res = installer::WillProductBePresentAfterSetup(
1032 prod_type_list[i_type_check]);
1033 bool prod_expect = (mach_after & (1 << i_type_check)) != 0;
1034 EXPECT_EQ(prod_expect, prod_res);
1041 #endif // defined(GOOGLE_CHROME_BUILD)