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"
9 #include "base/win/registry.h"
10 #include "base/version.h"
11 #include "chrome/common/chrome_constants.h"
12 #include "chrome/installer/setup/setup_util.h"
13 #include "chrome/installer/util/create_reg_key_work_item.h"
14 #include "chrome/installer/util/delete_reg_key_work_item.h"
15 #include "chrome/installer/util/delete_tree_work_item.h"
16 #include "chrome/installer/util/helper.h"
17 #include "chrome/installer/util/google_update_constants.h"
18 #include "chrome/installer/util/installation_state.h"
19 #include "chrome/installer/util/installer_state.h"
20 #include "chrome/installer/util/set_reg_value_work_item.h"
21 #include "chrome/installer/util/util_constants.h"
22 #include "chrome/installer/util/work_item_list.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "testing/gmock/include/gmock/gmock.h"
27 using base::win::RegKey
;
28 using installer::InstallationState
;
29 using installer::InstallerState
;
30 using installer::Product
;
31 using installer::ProductState
;
34 using ::testing::AnyNumber
;
35 using ::testing::AtLeast
;
36 using ::testing::AtMost
;
37 using ::testing::Bool
;
38 using ::testing::Combine
;
40 using ::testing::HasSubstr
;
41 using ::testing::NiceMock
;
42 using ::testing::Return
;
43 using ::testing::StrCaseEq
;
44 using ::testing::StrEq
;
45 using ::testing::StrictMock
;
46 using ::testing::Values
;
48 // Mock classes to help with testing
49 //------------------------------------------------------------------------------
51 class MockWorkItemList
: public WorkItemList
{
55 MOCK_METHOD5(AddCopyTreeWorkItem
,
56 WorkItem
*(const std::wstring
&,
60 const std::wstring
&));
61 MOCK_METHOD1(AddCreateDirWorkItem
, WorkItem
* (const base::FilePath
&));
62 MOCK_METHOD3(AddCreateRegKeyWorkItem
,
63 WorkItem
*(HKEY
, const std::wstring
&, REGSAM
));
64 MOCK_METHOD3(AddDeleteRegKeyWorkItem
,
65 WorkItem
*(HKEY
, const std::wstring
&, REGSAM
));
67 AddDeleteRegValueWorkItem
,
68 WorkItem
*(HKEY
, const std::wstring
&, REGSAM
, const std::wstring
&));
69 MOCK_METHOD3(AddDeleteTreeWorkItem
,
70 WorkItem
*(const base::FilePath
&,
71 const base::FilePath
&,
72 const std::vector
<base::FilePath
>&));
73 MOCK_METHOD2(AddDeleteTreeWorkItem
,
74 WorkItem
*(const base::FilePath
&, const base::FilePath
&));
75 MOCK_METHOD4(AddMoveTreeWorkItem
,
76 WorkItem
*(const std::wstring
&,
80 // Workaround for gmock problems with disambiguating between string pointers
82 virtual WorkItem
* AddSetRegValueWorkItem(HKEY a1
,
83 const std::wstring
& a2
,
85 const std::wstring
& a4
,
86 const std::wstring
& a5
,
88 return AddSetRegStringValueWorkItem(a1
, a2
, a3
, a4
, a5
, a6
);
91 virtual WorkItem
* AddSetRegValueWorkItem(HKEY a1
,
92 const std::wstring
& a2
,
94 const std::wstring
& a4
,
97 return AddSetRegDwordValueWorkItem(a1
, a2
, a3
, a4
, a5
, a6
);
100 MOCK_METHOD6(AddSetRegStringValueWorkItem
,
107 MOCK_METHOD6(AddSetRegDwordValueWorkItem
,
114 MOCK_METHOD3(AddSelfRegWorkItem
, WorkItem
* (const std::wstring
&,
119 class MockProductState
: public ProductState
{
121 // Takes ownership of |version|.
122 void set_version(Version
* version
) { version_
.reset(version
); }
123 void set_multi_install(bool multi
) { multi_install_
= multi
; }
124 void set_brand(const std::wstring
& brand
) { brand_
= brand
; }
125 void set_eula_accepted(DWORD eula_accepted
) {
126 has_eula_accepted_
= true;
127 eula_accepted_
= eula_accepted
;
129 void clear_eula_accepted() { has_eula_accepted_
= false; }
130 void set_usagestats(DWORD usagestats
) {
131 has_usagestats_
= true;
132 usagestats_
= usagestats
;
134 void clear_usagestats() { has_usagestats_
= false; }
135 void set_oem_install(const std::wstring
& oem_install
) {
136 has_oem_install_
= true;
137 oem_install_
= oem_install
;
139 void clear_oem_install() { has_oem_install_
= false; }
140 void SetUninstallProgram(const base::FilePath
& setup_exe
) {
141 uninstall_command_
= base::CommandLine(setup_exe
);
143 void AddUninstallSwitch(const std::string
& option
) {
144 uninstall_command_
.AppendSwitch(option
);
148 // Okay, so this isn't really a mock as such, but it does add setter methods
149 // to make it easier to build custom InstallationStates.
150 class MockInstallationState
: public InstallationState
{
152 // Included for testing.
153 void SetProductState(bool system_install
,
154 BrowserDistribution::Type type
,
155 const ProductState
& product_state
) {
156 ProductState
& target
= (system_install
? system_products_
:
157 user_products_
)[IndexFromDistType(type
)];
158 target
.CopyFrom(product_state
);
162 class MockInstallerState
: public InstallerState
{
164 void set_level(Level level
) {
165 InstallerState::set_level(level
);
168 void set_operation(Operation operation
) { operation_
= operation
; }
170 void set_state_key(const std::wstring
& state_key
) {
171 state_key_
= state_key
;
174 void set_state_type(BrowserDistribution::Type state_type
) {
175 state_type_
= state_type
;
178 void set_package_type(PackageType type
) {
179 InstallerState::set_package_type(type
);
184 //------------------------------------------------------------------------------
186 class InstallWorkerTest
: public testing::Test
{
188 void SetUp() override
{
189 current_version_
.reset(new Version("1.0.0.0"));
190 new_version_
.reset(new Version("42.0.0.0"));
192 // Don't bother ensuring that these paths exist. Since we're just
193 // building the work item lists and not running them, they shouldn't
194 // actually be touched.
196 base::FilePath(L
"C:\\UnlikelyPath\\Temp\\chrome_123\\chrome.7z");
197 // TODO(robertshield): Take this from the BrowserDistribution once that
198 // no longer depends on MasterPreferences.
200 base::FilePath(L
"C:\\Program Files\\Google\\Chrome\\");
201 src_path_
= base::FilePath(
202 L
"C:\\UnlikelyPath\\Temp\\chrome_123\\source\\Chrome-bin");
203 setup_path_
= base::FilePath(
204 L
"C:\\UnlikelyPath\\Temp\\CR_123.tmp\\setup.exe");
205 temp_dir_
= base::FilePath(L
"C:\\UnlikelyPath\\Temp\\chrome_123");
208 void TearDown() override
{}
210 void MaybeAddBinariesToInstallationState(
212 MockInstallationState
* installation_state
) {
213 if (installation_state
->GetProductState(
214 system_level
, BrowserDistribution::CHROME_BINARIES
) == NULL
) {
215 MockProductState product_state
;
216 product_state
.set_version(new Version(*current_version_
));
217 product_state
.set_brand(L
"TEST");
218 product_state
.set_multi_install(true);
219 BrowserDistribution
* dist
=
220 BrowserDistribution::GetSpecificDistribution(
221 BrowserDistribution::CHROME_BINARIES
);
222 base::FilePath install_path
=
223 installer::GetChromeInstallPath(system_level
, dist
);
224 product_state
.SetUninstallProgram(
225 install_path
.AppendASCII(current_version_
->GetString())
226 .Append(installer::kInstallerDir
)
227 .Append(installer::kSetupExe
));
228 product_state
.AddUninstallSwitch(installer::switches::kUninstall
);
229 product_state
.AddUninstallSwitch(installer::switches::kMultiInstall
);
231 product_state
.AddUninstallSwitch(installer::switches::kSystemLevel
);
232 installation_state
->SetProductState(system_level
,
233 BrowserDistribution::CHROME_BINARIES
,
238 void AddChromeToInstallationState(
241 MockInstallationState
* installation_state
) {
243 MaybeAddBinariesToInstallationState(system_level
, installation_state
);
244 MockProductState product_state
;
245 product_state
.set_version(new Version(*current_version_
));
246 product_state
.set_multi_install(multi_install
);
247 product_state
.set_brand(L
"TEST");
248 product_state
.set_eula_accepted(1);
249 BrowserDistribution
* dist
=
250 BrowserDistribution::GetSpecificDistribution(
251 BrowserDistribution::CHROME_BROWSER
);
252 base::FilePath install_path
=
253 installer::GetChromeInstallPath(system_level
, dist
);
254 product_state
.SetUninstallProgram(
255 install_path
.AppendASCII(current_version_
->GetString())
256 .Append(installer::kInstallerDir
)
257 .Append(installer::kSetupExe
));
258 product_state
.AddUninstallSwitch(installer::switches::kUninstall
);
260 product_state
.AddUninstallSwitch(installer::switches::kSystemLevel
);
262 product_state
.AddUninstallSwitch(installer::switches::kMultiInstall
);
263 product_state
.AddUninstallSwitch(installer::switches::kChrome
);
266 installation_state
->SetProductState(system_level
,
267 BrowserDistribution::CHROME_BROWSER
,
271 void AddChromeFrameToInstallationState(
274 MockInstallationState
* installation_state
) {
276 MaybeAddBinariesToInstallationState(system_level
, installation_state
);
277 MockProductState product_state
;
278 product_state
.set_version(new Version(*current_version_
));
279 product_state
.set_multi_install(multi_install
);
280 BrowserDistribution
* dist
=
281 BrowserDistribution::GetSpecificDistribution(
282 multi_install
? BrowserDistribution::CHROME_BINARIES
:
283 BrowserDistribution::CHROME_FRAME
);
284 base::FilePath install_path
=
285 installer::GetChromeInstallPath(system_level
, dist
);
286 product_state
.SetUninstallProgram(
287 install_path
.AppendASCII(current_version_
->GetString())
288 .Append(installer::kInstallerDir
)
289 .Append(installer::kSetupExe
));
290 product_state
.AddUninstallSwitch(installer::switches::kUninstall
);
291 product_state
.AddUninstallSwitch(installer::switches::kChromeFrame
);
293 product_state
.AddUninstallSwitch(installer::switches::kSystemLevel
);
295 product_state
.AddUninstallSwitch(installer::switches::kMultiInstall
);
297 installation_state
->SetProductState(system_level
,
298 BrowserDistribution::CHROME_FRAME
,
302 MockInstallationState
* BuildChromeInstallationState(bool system_level
,
303 bool multi_install
) {
304 scoped_ptr
<MockInstallationState
> installation_state(
305 new MockInstallationState());
306 AddChromeToInstallationState(system_level
, multi_install
,
307 installation_state
.get());
308 return installation_state
.release();
311 static MockInstallerState
* BuildBasicInstallerState(
314 const InstallationState
& machine_state
,
315 InstallerState::Operation operation
) {
316 scoped_ptr
<MockInstallerState
> installer_state(new MockInstallerState());
318 InstallerState::Level level
= system_install
?
319 InstallerState::SYSTEM_LEVEL
: InstallerState::USER_LEVEL
;
320 installer_state
->set_level(level
);
321 installer_state
->set_operation(operation
);
322 // Hope this next one isn't checked for now.
323 installer_state
->set_state_key(L
"PROBABLY_INVALID_REG_PATH");
324 installer_state
->set_state_type(BrowserDistribution::CHROME_BROWSER
);
325 installer_state
->set_package_type(multi_install
?
326 InstallerState::MULTI_PACKAGE
:
327 InstallerState::SINGLE_PACKAGE
);
328 return installer_state
.release();
331 static void AddChromeBinariesToInstallerState(
332 const InstallationState
& machine_state
,
333 MockInstallerState
* installer_state
) {
334 if (!installer_state
->is_multi_install()) {
338 if (installer_state
->FindProduct(BrowserDistribution::CHROME_BINARIES
))
341 // Fresh install or upgrade?
342 const ProductState
* chrome_binaries
=
343 machine_state
.GetProductState(installer_state
->system_install(),
344 BrowserDistribution::CHROME_BINARIES
);
345 if (chrome_binaries
!= NULL
) {
346 installer_state
->AddProductFromState(BrowserDistribution::CHROME_BINARIES
,
349 BrowserDistribution
* dist
=
350 BrowserDistribution::GetSpecificDistribution(
351 BrowserDistribution::CHROME_BINARIES
);
352 scoped_ptr
<Product
> product(new Product(dist
));
353 product
->SetOption(installer::kOptionMultiInstall
, true);
354 installer_state
->AddProduct(&product
);
358 static void AddChromeToInstallerState(
359 const InstallationState
& machine_state
,
360 MockInstallerState
* installer_state
) {
361 // Fresh install or upgrade?
362 const ProductState
* chrome
=
363 machine_state
.GetProductState(installer_state
->system_install(),
364 BrowserDistribution::CHROME_BROWSER
);
365 if (chrome
!= NULL
&&
366 chrome
->is_multi_install() == installer_state
->is_multi_install()) {
367 installer_state
->AddProductFromState(BrowserDistribution::CHROME_BROWSER
,
370 BrowserDistribution
* dist
=
371 BrowserDistribution::GetSpecificDistribution(
372 BrowserDistribution::CHROME_BROWSER
);
373 scoped_ptr
<Product
> product(new Product(dist
));
374 if (installer_state
->is_multi_install())
375 product
->SetOption(installer::kOptionMultiInstall
, true);
376 installer_state
->AddProduct(&product
);
380 static void AddChromeFrameToInstallerState(
381 const InstallationState
& machine_state
,
382 MockInstallerState
* installer_state
) {
383 // Fresh install or upgrade?
384 const ProductState
* cf
=
385 machine_state
.GetProductState(installer_state
->system_install(),
386 BrowserDistribution::CHROME_FRAME
);
388 installer_state
->AddProductFromState(BrowserDistribution::CHROME_FRAME
,
391 BrowserDistribution
* dist
=
392 BrowserDistribution::GetSpecificDistribution(
393 BrowserDistribution::CHROME_FRAME
);
394 scoped_ptr
<Product
> product(new Product(dist
));
395 if (installer_state
->is_multi_install())
396 product
->SetOption(installer::kOptionMultiInstall
, true);
397 installer_state
->AddProduct(&product
);
401 static MockInstallerState
* BuildChromeInstallerState(
404 const InstallationState
& machine_state
,
405 InstallerState::Operation operation
) {
406 scoped_ptr
<MockInstallerState
> installer_state(
407 BuildBasicInstallerState(system_install
, multi_install
, machine_state
,
410 // We don't want to include Chrome Binaries for uninstall if the machine
411 // has other products. For simplicity, we check Chrome Frame only.
412 bool machine_has_other_products
=
413 machine_state
.GetProductState(system_install
,
414 BrowserDistribution::CHROME_FRAME
) != NULL
;
415 if (operation
!= InstallerState::UNINSTALL
|| !machine_has_other_products
)
416 AddChromeBinariesToInstallerState(machine_state
, installer_state
.get());
418 AddChromeToInstallerState(machine_state
, installer_state
.get());
419 return installer_state
.release();
422 static MockInstallerState
* BuildChromeFrameInstallerState(
425 const InstallationState
& machine_state
,
426 InstallerState::Operation operation
) {
427 // This method only works for installation/upgrade.
428 DCHECK(operation
!= InstallerState::UNINSTALL
);
429 scoped_ptr
<MockInstallerState
> installer_state(
430 BuildBasicInstallerState(system_install
, multi_install
, machine_state
,
433 AddChromeBinariesToInstallerState(machine_state
, installer_state
.get());
434 AddChromeFrameToInstallerState(machine_state
, 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 NiceMock
<MockWorkItemList
> work_item_list
;
456 const HKEY kRegRoot
= system_level
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
457 static const wchar_t kRegKeyPath
[] = L
"Software\\Chromium\\test";
458 scoped_ptr
<CreateRegKeyWorkItem
> create_reg_key_work_item(
459 WorkItem::CreateCreateRegKeyWorkItem(
460 kRegRoot
, kRegKeyPath
, WorkItem::kWow64Default
));
461 scoped_ptr
<SetRegValueWorkItem
> set_reg_value_work_item(
462 WorkItem::CreateSetRegValueWorkItem(
463 kRegRoot
, kRegKeyPath
, WorkItem::kWow64Default
, L
"", L
"", false));
464 scoped_ptr
<DeleteTreeWorkItem
> delete_tree_work_item(
465 WorkItem::CreateDeleteTreeWorkItem(base::FilePath(), base::FilePath(),
466 std::vector
<base::FilePath
>()));
467 scoped_ptr
<DeleteRegKeyWorkItem
> delete_reg_key_work_item(
468 WorkItem::CreateDeleteRegKeyWorkItem(kRegRoot
, kRegKeyPath
,
469 WorkItem::kWow64Default
));
471 scoped_ptr
<InstallationState
> installation_state(
472 BuildChromeInstallationState(system_level
, multi_install
));
474 scoped_ptr
<InstallerState
> installer_state(
475 BuildChromeInstallerState(system_level
, multi_install
,
477 InstallerState::SINGLE_INSTALL_OR_UPDATE
));
479 // Set up some expectations.
480 // TODO(robertshield): Set up some real expectations.
481 EXPECT_CALL(work_item_list
, AddCopyTreeWorkItem(_
, _
, _
, _
, _
))
483 EXPECT_CALL(work_item_list
, AddCreateRegKeyWorkItem(_
, _
, _
))
484 .WillRepeatedly(Return(create_reg_key_work_item
.get()));
485 EXPECT_CALL(work_item_list
, AddSetRegStringValueWorkItem(_
, _
, _
, _
, _
, _
))
486 .WillRepeatedly(Return(set_reg_value_work_item
.get()));
487 EXPECT_CALL(work_item_list
, AddDeleteTreeWorkItem(_
, _
))
488 .WillRepeatedly(Return(delete_tree_work_item
.get()));
489 EXPECT_CALL(work_item_list
, AddDeleteRegKeyWorkItem(_
, _
, _
))
490 .WillRepeatedly(Return(delete_reg_key_work_item
.get()));
492 AddInstallWorkItems(*installation_state
.get(),
493 *installer_state
.get(),
498 current_version_
.get(),
505 const wchar_t old_elevation_key
[] =
506 L
"SOFTWARE\\Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\\"
507 L
"{6C288DD7-76FB-4721-B628-56FAC252E199}";
511 // A test class for worker functions that manipulate the old IE low rights
514 // bool : system_level_
515 // bool : multi_install_
516 class OldIELowRightsTests
: public InstallWorkerTest
,
517 public ::testing::WithParamInterface
<std::tr1::tuple
<bool, bool> > {
519 void SetUp() override
{
520 InstallWorkerTest::SetUp();
522 const ParamType
& param
= GetParam();
523 system_level_
= std::tr1::get
<0>(param
);
524 multi_install_
= std::tr1::get
<1>(param
);
525 root_key_
= system_level_
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
527 installation_state_
.reset(new MockInstallationState());
528 AddChromeFrameToInstallationState(system_level_
, multi_install_
,
529 installation_state_
.get());
530 installer_state_
.reset(BuildBasicInstallerState(
531 system_level_
, multi_install_
, *installation_state_
,
532 multi_install_
? InstallerState::MULTI_UPDATE
:
533 InstallerState::SINGLE_INSTALL_OR_UPDATE
));
535 AddChromeBinariesToInstallerState(*installation_state_
,
536 installer_state_
.get());
537 AddChromeFrameToInstallerState(*installation_state_
,
538 installer_state_
.get());
541 scoped_ptr
<MockInstallationState
> installation_state_
;
542 scoped_ptr
<MockInstallerState
> installer_state_
;
548 TEST_P(OldIELowRightsTests
, AddDeleteOldIELowRightsPolicyWorkItems
) {
549 StrictMock
<MockWorkItemList
> work_item_list
;
551 EXPECT_CALL(work_item_list
,
552 AddDeleteRegKeyWorkItem(root_key_
, StrEq(old_elevation_key
), _
))
555 AddDeleteOldIELowRightsPolicyWorkItems(*installer_state_
.get(),
559 INSTANTIATE_TEST_CASE_P(Variations
, OldIELowRightsTests
,
560 Combine(Bool(), Bool()));
562 TEST_F(InstallWorkerTest
, GoogleUpdateWorkItemsTest
) {
563 const bool system_level
= true;
564 const bool multi_install
= true;
565 MockWorkItemList work_item_list
;
567 // Per-machine single-install Chrome is installed.
568 scoped_ptr
<MockInstallationState
> installation_state(
569 BuildChromeInstallationState(system_level
, false));
571 MockProductState cf_state
;
572 cf_state
.set_version(new Version(*current_version_
));
573 cf_state
.set_multi_install(false);
575 // Per-machine single-install Chrome Frame is installed.
576 installation_state
->SetProductState(system_level
,
577 BrowserDistribution::CHROME_FRAME
, cf_state
);
579 // Prepare per-machine multi-install Chrome for installation.
580 scoped_ptr
<MockInstallerState
> installer_state(
581 BuildChromeInstallerState(system_level
, multi_install
,
583 InstallerState::MULTI_INSTALL
));
585 // Expect the multi Client State key to be created for the binaries.
586 #if defined(GOOGLE_CHROME_BUILD)
587 BrowserDistribution
* multi_dist
=
588 BrowserDistribution::GetSpecificDistribution(
589 BrowserDistribution::CHROME_BINARIES
);
590 std::wstring
multi_app_guid(multi_dist
->GetAppGuid());
591 std::wstring
multi_client_state_suffix(L
"ClientState\\" + multi_app_guid
);
592 std::wstring
multi_medium_suffix(L
"ClientStateMedium\\" + multi_app_guid
);
594 // Expect ClientStateMedium to be created for system-level installs.
595 EXPECT_CALL(work_item_list
,
596 AddCreateRegKeyWorkItem(_
, HasSubstr(multi_medium_suffix
), _
))
597 .Times(system_level
? 1 : 0);
599 std::wstring
multi_client_state_suffix(L
"Chromium Binaries");
601 EXPECT_CALL(work_item_list
, AddCreateRegKeyWorkItem(
602 _
, HasSubstr(multi_client_state_suffix
), _
))
605 // Expect to see a set value for the "TEST" brand code in the multi Client
607 EXPECT_CALL(work_item_list
, AddSetRegStringValueWorkItem(
608 _
, HasSubstr(multi_client_state_suffix
), _
,
609 StrEq(google_update::kRegBrandField
),
610 StrEq(L
"TEST"), _
)).Times(1);
612 // There may also be some calls to set 'ap' values.
613 EXPECT_CALL(work_item_list
, AddSetRegStringValueWorkItem(
614 _
, _
, _
, StrEq(google_update::kRegApField
), _
,
615 _
)).Times(AnyNumber());
617 // Expect "oeminstall" to be cleared.
618 EXPECT_CALL(work_item_list
, AddDeleteRegValueWorkItem(
619 _
, HasSubstr(multi_client_state_suffix
), _
,
620 StrEq(google_update::kRegOemInstallField
)))
623 // Expect "eulaaccepted" to set.
624 EXPECT_CALL(work_item_list
, AddSetRegDwordValueWorkItem(
625 _
, HasSubstr(multi_client_state_suffix
), _
,
626 StrEq(google_update::kRegEULAAceptedField
),
627 Eq(static_cast<DWORD
>(1)), _
)).Times(1);
629 AddGoogleUpdateWorkItems(*installation_state
.get(),
630 *installer_state
.get(),
634 // Test that usagestats values are migrated properly.
635 TEST_F(InstallWorkerTest
, AddUsageStatsWorkItems
) {
636 const bool system_level
= true;
637 const bool multi_install
= true;
638 MockWorkItemList work_item_list
;
640 scoped_ptr
<MockInstallationState
> installation_state(
641 BuildChromeInstallationState(system_level
, multi_install
));
643 MockProductState chrome_state
;
644 chrome_state
.set_version(new Version(*current_version_
));
645 chrome_state
.set_multi_install(false);
646 chrome_state
.set_usagestats(1);
648 installation_state
->SetProductState(system_level
,
649 BrowserDistribution::CHROME_BROWSER
, chrome_state
);
651 scoped_ptr
<MockInstallerState
> installer_state(
652 BuildChromeInstallerState(system_level
, multi_install
,
654 InstallerState::MULTI_INSTALL
));
656 // Expect the multi Client State key to be created.
657 BrowserDistribution
* multi_dist
=
658 BrowserDistribution::GetSpecificDistribution(
659 BrowserDistribution::CHROME_BINARIES
);
660 std::wstring
multi_app_guid(multi_dist
->GetAppGuid());
661 EXPECT_CALL(work_item_list
, AddCreateRegKeyWorkItem(
662 _
, HasSubstr(multi_app_guid
), _
)).Times(1);
664 // Expect to see a set value for the usagestats in the multi Client State key.
665 EXPECT_CALL(work_item_list
, AddSetRegDwordValueWorkItem(
666 _
, HasSubstr(multi_app_guid
), _
,
667 StrEq(google_update::kRegUsageStatsField
),
668 Eq(static_cast<DWORD
>(1)), Eq(true)))
671 // Expect to see some values cleaned up from Chrome's keys.
672 BrowserDistribution
* chrome_dist
=
673 BrowserDistribution::GetSpecificDistribution(
674 BrowserDistribution::CHROME_BROWSER
);
676 #if defined(GOOGLE_CHROME_BUILD)
677 EXPECT_CALL(work_item_list
,
678 AddDeleteRegValueWorkItem(
679 _
, StrEq(chrome_dist
->GetStateMediumKey()), _
,
680 StrEq(google_update::kRegUsageStatsField
))).Times(1);
682 EXPECT_CALL(work_item_list
,
683 AddDeleteRegValueWorkItem(
684 Eq(HKEY_CURRENT_USER
), StrEq(chrome_dist
->GetStateKey()), _
,
685 StrEq(google_update::kRegUsageStatsField
))).Times(1);
687 #if defined(GOOGLE_CHROME_BUILD)
688 const int kDeleteTimes
= 1;
690 // Expect two deletes to the same key name since ClientState and
691 // ClientStateMedium are identical for Chromium.
692 const int kDeleteTimes
= 2;
696 AddDeleteRegValueWorkItem(
697 Eq(installer_state
->root_key()), StrEq(chrome_dist
->GetStateKey()), _
,
698 StrEq(google_update::kRegUsageStatsField
))).Times(kDeleteTimes
);
700 AddUsageStatsWorkItems(*installation_state
.get(),
701 *installer_state
.get(),
705 // The Quick Enable tests only make sense for the Google Chrome build as it
706 // interacts with registry values that are specific to Google Update.
707 #if defined(GOOGLE_CHROME_BUILD)
709 // Test scenarios under which the quick-enable-cf command should not exist after
710 // the run. We're permissive in that we allow the DeleteRegKeyWorkItem even if
711 // it isn't strictly needed.
712 class QuickEnableAbsentTest
: public InstallWorkerTest
{
714 virtual void SetUp() {
715 InstallWorkerTest::SetUp();
716 root_key_
= system_level_
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
717 delete_reg_key_item_
.reset(WorkItem::CreateDeleteRegKeyWorkItem(
718 root_key_
, kRegKeyPath
, WorkItem::kWow64Default
));
719 machine_state_
.reset(new MockInstallationState());
720 EXPECT_CALL(work_item_list_
, AddDeleteRegKeyWorkItem(
721 Eq(root_key_
), StrCaseEq(kRegKeyPath
), _
))
723 .WillRepeatedly(Return(delete_reg_key_item_
.get()));
725 virtual void TearDown() {
726 machine_state_
.reset();
727 delete_reg_key_item_
.reset();
729 InstallWorkerTest::TearDown();
732 static const bool system_level_
= false;
733 static const wchar_t kRegKeyPath
[];
735 scoped_ptr
<DeleteRegKeyWorkItem
> delete_reg_key_item_
;
736 scoped_ptr
<MockInstallationState
> machine_state_
;
737 StrictMock
<MockWorkItemList
> work_item_list_
;
740 const wchar_t QuickEnableAbsentTest::kRegKeyPath
[] =
741 L
"Software\\Google\\Update\\Clients\\"
742 L
"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}\\Commands\\quick-enable-cf";
744 TEST_F(QuickEnableAbsentTest
, CleanInstallSingleChrome
) {
745 // Install single Chrome on a clean system.
746 scoped_ptr
<MockInstallerState
> installer_state(
747 BuildBasicInstallerState(system_level_
, true, *machine_state_
,
748 InstallerState::MULTI_UPDATE
));
749 AddQuickEnableChromeFrameWorkItems(*installer_state
, &work_item_list_
);
752 TEST_F(InstallWorkerTest
, WillProductBePresentAfterSetup
) {
753 BrowserDistribution::Type prod_type_list
[] = {
754 BrowserDistribution::CHROME_BROWSER
,
755 BrowserDistribution::CHROME_FRAME
,
756 // Excluding BrowserDistribution::CHROME_BINARIES, since it is installed
757 // along with other products.
759 enum { // Index into prod_type_list[].
762 NUM_TYPE
// This must appear last.
764 DCHECK(arraysize(prod_type_list
) == NUM_TYPE
);
765 InstallerState::Operation op_list
[] = {
766 InstallerState::UNINSTALL
,
767 InstallerState::SINGLE_INSTALL_OR_UPDATE
770 const bool system_level
= false;
771 const bool multi_install
= true;
773 // Loop over machine states: {No product, Chrome, CF, Chrome + CF}.
774 for (int i_mach
= 0; i_mach
< (1 << NUM_TYPE
); ++i_mach
) {
775 // i_mach is the machine state before operation, as bit mask.
776 scoped_ptr
<MockInstallationState
> machine_state(
777 new MockInstallationState());
778 if ((i_mach
& (1 << TYPE_BROWSER
)) != 0) { // Add Chrome.
779 AddChromeToInstallationState(system_level
, multi_install
,
780 machine_state
.get());
782 if ((i_mach
& (1 << TYPE_CF
)) != 0) { // Add Chrome Frame.
783 AddChromeFrameToInstallationState(system_level
, multi_install
,
784 machine_state
.get());
787 // Loop over operations: {uninstall, install/update}.
788 for (int i_op
= 0; i_op
< arraysize(op_list
); ++i_op
) {
790 // Loop over product types to operate on: {TYPE_BROWSER, TYPE_CF}.
791 for (int i_type_op
= 0; i_type_op
< NUM_TYPE
; ++i_type_op
) {
792 scoped_ptr
<InstallerState
> installer_state
;
793 if (i_type_op
== TYPE_BROWSER
) {
794 installer_state
.reset(BuildChromeInstallerState(
795 system_level
, multi_install
, *machine_state
, op_list
[i_op
]));
796 } else if (i_type_op
== TYPE_CF
) {
797 // Skip the CF uninstall case due to limitations in
798 // BuildChromeFrameInstallerState().
799 if (op_list
[i_op
] == InstallerState::UNINSTALL
)
802 installer_state
.reset(BuildChromeFrameInstallerState(
803 system_level
, multi_install
, *machine_state
, op_list
[i_op
]));
808 // Calculate the machine state after operation, as bit mask.
809 // If uninstall, remove product with bitwise AND; else add with OR.
810 int mach_after
= (op_list
[i_op
] == InstallerState::UNINSTALL
) ?
811 i_mach
& ~(1 << i_type_op
) : i_mach
| (1 << i_type_op
);
813 // Verify predicted presence of Chrome Binaries.
814 bool bin_res
= installer::WillProductBePresentAfterSetup(
817 BrowserDistribution::CHROME_BINARIES
);
818 // Binaries are expected to be present iff any product is installed.
819 bool bin_expect
= mach_after
!= 0;
820 EXPECT_EQ(bin_expect
, bin_res
);
822 // Loop over product types to check: {TYPE_BROWSER, TYPE_CF}.
823 for (int i_type_check
= 0; i_type_check
< NUM_TYPE
; ++i_type_check
) {
824 // Verify predicted presence of product.
825 bool prod_res
= installer::WillProductBePresentAfterSetup(
828 prod_type_list
[i_type_check
]);
829 bool prod_expect
= (mach_after
& (1 << i_type_check
)) != 0;
830 EXPECT_EQ(prod_expect
, prod_res
);
837 #endif // defined(GOOGLE_CHROME_BUILD)