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_
= base::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 MockInstallationState
* installation_state
) {
225 MaybeAddBinariesToInstallationState(system_level
, installation_state
);
226 MockProductState product_state
;
227 product_state
.set_version(new Version(*current_version_
));
228 product_state
.set_multi_install(multi_install
);
229 product_state
.set_brand(L
"TEST");
230 product_state
.set_eula_accepted(1);
231 BrowserDistribution
* dist
=
232 BrowserDistribution::GetSpecificDistribution(
233 BrowserDistribution::CHROME_BROWSER
);
234 base::FilePath install_path
=
235 installer::GetChromeInstallPath(system_level
, dist
);
236 product_state
.SetUninstallProgram(
237 install_path
.AppendASCII(current_version_
->GetString())
238 .Append(installer::kInstallerDir
)
239 .Append(installer::kSetupExe
));
240 product_state
.AddUninstallSwitch(installer::switches::kUninstall
);
242 product_state
.AddUninstallSwitch(installer::switches::kSystemLevel
);
244 product_state
.AddUninstallSwitch(installer::switches::kMultiInstall
);
245 product_state
.AddUninstallSwitch(installer::switches::kChrome
);
248 installation_state
->SetProductState(system_level
,
249 BrowserDistribution::CHROME_BROWSER
,
253 void AddChromeFrameToInstallationState(
256 MockInstallationState
* installation_state
) {
258 MaybeAddBinariesToInstallationState(system_level
, installation_state
);
259 MockProductState product_state
;
260 product_state
.set_version(new Version(*current_version_
));
261 product_state
.set_multi_install(multi_install
);
262 BrowserDistribution
* dist
=
263 BrowserDistribution::GetSpecificDistribution(
264 multi_install
? BrowserDistribution::CHROME_BINARIES
:
265 BrowserDistribution::CHROME_FRAME
);
266 base::FilePath install_path
=
267 installer::GetChromeInstallPath(system_level
, dist
);
268 product_state
.SetUninstallProgram(
269 install_path
.AppendASCII(current_version_
->GetString())
270 .Append(installer::kInstallerDir
)
271 .Append(installer::kSetupExe
));
272 product_state
.AddUninstallSwitch(installer::switches::kUninstall
);
273 product_state
.AddUninstallSwitch(installer::switches::kChromeFrame
);
275 product_state
.AddUninstallSwitch(installer::switches::kSystemLevel
);
277 product_state
.AddUninstallSwitch(installer::switches::kMultiInstall
);
279 installation_state
->SetProductState(system_level
,
280 BrowserDistribution::CHROME_FRAME
,
284 MockInstallationState
* BuildChromeInstallationState(bool system_level
,
285 bool multi_install
) {
286 scoped_ptr
<MockInstallationState
> installation_state(
287 new MockInstallationState());
288 AddChromeToInstallationState(system_level
, multi_install
,
289 installation_state
.get());
290 return installation_state
.release();
293 static MockInstallerState
* BuildBasicInstallerState(
296 const InstallationState
& machine_state
,
297 InstallerState::Operation operation
) {
298 scoped_ptr
<MockInstallerState
> installer_state(new MockInstallerState());
300 InstallerState::Level level
= system_install
?
301 InstallerState::SYSTEM_LEVEL
: InstallerState::USER_LEVEL
;
302 installer_state
->set_level(level
);
303 installer_state
->set_operation(operation
);
304 // Hope this next one isn't checked for now.
305 installer_state
->set_state_key(L
"PROBABLY_INVALID_REG_PATH");
306 installer_state
->set_state_type(BrowserDistribution::CHROME_BROWSER
);
307 installer_state
->set_package_type(multi_install
?
308 InstallerState::MULTI_PACKAGE
:
309 InstallerState::SINGLE_PACKAGE
);
310 return installer_state
.release();
313 static void AddChromeBinariesToInstallerState(
314 const InstallationState
& machine_state
,
315 MockInstallerState
* installer_state
) {
316 if (!installer_state
->is_multi_install()) {
320 if (installer_state
->FindProduct(BrowserDistribution::CHROME_BINARIES
))
323 // Fresh install or upgrade?
324 const ProductState
* chrome_binaries
=
325 machine_state
.GetProductState(installer_state
->system_install(),
326 BrowserDistribution::CHROME_BINARIES
);
327 if (chrome_binaries
!= NULL
) {
328 installer_state
->AddProductFromState(BrowserDistribution::CHROME_BINARIES
,
331 BrowserDistribution
* dist
=
332 BrowserDistribution::GetSpecificDistribution(
333 BrowserDistribution::CHROME_BINARIES
);
334 scoped_ptr
<Product
> product(new Product(dist
));
335 product
->SetOption(installer::kOptionMultiInstall
, true);
336 installer_state
->AddProduct(&product
);
340 static void AddChromeToInstallerState(
341 const InstallationState
& machine_state
,
342 MockInstallerState
* installer_state
) {
343 // Fresh install or upgrade?
344 const ProductState
* chrome
=
345 machine_state
.GetProductState(installer_state
->system_install(),
346 BrowserDistribution::CHROME_BROWSER
);
347 if (chrome
!= NULL
&&
348 chrome
->is_multi_install() == installer_state
->is_multi_install()) {
349 installer_state
->AddProductFromState(BrowserDistribution::CHROME_BROWSER
,
352 BrowserDistribution
* dist
=
353 BrowserDistribution::GetSpecificDistribution(
354 BrowserDistribution::CHROME_BROWSER
);
355 scoped_ptr
<Product
> product(new Product(dist
));
356 if (installer_state
->is_multi_install())
357 product
->SetOption(installer::kOptionMultiInstall
, true);
358 installer_state
->AddProduct(&product
);
362 static void AddChromeFrameToInstallerState(
363 const InstallationState
& machine_state
,
364 MockInstallerState
* installer_state
) {
365 // Fresh install or upgrade?
366 const ProductState
* cf
=
367 machine_state
.GetProductState(installer_state
->system_install(),
368 BrowserDistribution::CHROME_FRAME
);
370 installer_state
->AddProductFromState(BrowserDistribution::CHROME_FRAME
,
373 BrowserDistribution
* dist
=
374 BrowserDistribution::GetSpecificDistribution(
375 BrowserDistribution::CHROME_FRAME
);
376 scoped_ptr
<Product
> product(new Product(dist
));
377 if (installer_state
->is_multi_install())
378 product
->SetOption(installer::kOptionMultiInstall
, true);
379 installer_state
->AddProduct(&product
);
383 static MockInstallerState
* BuildChromeInstallerState(
386 const InstallationState
& machine_state
,
387 InstallerState::Operation operation
) {
388 scoped_ptr
<MockInstallerState
> installer_state(
389 BuildBasicInstallerState(system_install
, multi_install
, machine_state
,
392 // We don't want to include Chrome Binaries for uninstall if the machine
393 // has other products. For simplicity, we check Chrome Frame only.
394 bool machine_has_other_products
=
395 machine_state
.GetProductState(system_install
,
396 BrowserDistribution::CHROME_FRAME
) != NULL
;
397 if (operation
!= InstallerState::UNINSTALL
|| !machine_has_other_products
)
398 AddChromeBinariesToInstallerState(machine_state
, installer_state
.get());
400 AddChromeToInstallerState(machine_state
, installer_state
.get());
401 return installer_state
.release();
404 static MockInstallerState
* BuildChromeFrameInstallerState(
407 const InstallationState
& machine_state
,
408 InstallerState::Operation operation
) {
409 // This method only works for installation/upgrade.
410 DCHECK(operation
!= InstallerState::UNINSTALL
);
411 scoped_ptr
<MockInstallerState
> installer_state(
412 BuildBasicInstallerState(system_install
, multi_install
, machine_state
,
415 AddChromeBinariesToInstallerState(machine_state
, installer_state
.get());
416 AddChromeFrameToInstallerState(machine_state
, installer_state
.get());
417 return installer_state
.release();
421 scoped_ptr
<Version
> current_version_
;
422 scoped_ptr
<Version
> new_version_
;
423 base::FilePath archive_path_
;
424 base::FilePath installation_path_
;
425 base::FilePath setup_path_
;
426 base::FilePath src_path_
;
427 base::FilePath temp_dir_
;
431 //------------------------------------------------------------------------------
433 TEST_F(InstallWorkerTest
, TestInstallChromeSingleSystem
) {
434 const bool system_level
= true;
435 const bool multi_install
= false;
436 MockWorkItemList work_item_list
;
438 const HKEY kRegRoot
= system_level
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
439 static const wchar_t kRegKeyPath
[] = L
"Software\\Chromium\\test";
440 scoped_ptr
<CreateRegKeyWorkItem
> create_reg_key_work_item(
441 WorkItem::CreateCreateRegKeyWorkItem(
442 kRegRoot
, kRegKeyPath
, WorkItem::kWow64Default
));
443 scoped_ptr
<SetRegValueWorkItem
> set_reg_value_work_item(
444 WorkItem::CreateSetRegValueWorkItem(
445 kRegRoot
, kRegKeyPath
, WorkItem::kWow64Default
, L
"", L
"", false));
447 scoped_ptr
<InstallationState
> installation_state(
448 BuildChromeInstallationState(system_level
, multi_install
));
450 scoped_ptr
<InstallerState
> installer_state(
451 BuildChromeInstallerState(system_level
, multi_install
,
453 InstallerState::SINGLE_INSTALL_OR_UPDATE
));
455 // Set up some expectations.
456 // TODO(robertshield): Set up some real expectations.
457 EXPECT_CALL(work_item_list
, AddCopyTreeWorkItem(_
, _
, _
, _
, _
))
459 EXPECT_CALL(work_item_list
, AddCreateRegKeyWorkItem(_
, _
))
460 .WillRepeatedly(Return(create_reg_key_work_item
.get()));
461 EXPECT_CALL(work_item_list
, AddSetRegStringValueWorkItem(_
, _
, _
, _
, _
))
462 .WillRepeatedly(Return(set_reg_value_work_item
.get()));
464 AddInstallWorkItems(*installation_state
.get(),
465 *installer_state
.get(),
470 current_version_
.get(),
477 const wchar_t elevation_key
[] =
478 L
"SOFTWARE\\Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\\"
479 L
"{E0A900DF-9611-4446-86BD-4B1D47E7DB2A}";
480 const wchar_t old_elevation_key
[] =
481 L
"SOFTWARE\\Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\\"
482 L
"{6C288DD7-76FB-4721-B628-56FAC252E199}";
486 // A test class for worker functions that manipulate the old IE low rights
489 // bool : system_level_
490 // bool : multi_install_
491 class OldIELowRightsTests
: public InstallWorkerTest
,
492 public ::testing::WithParamInterface
<std::tr1::tuple
<bool, bool> > {
494 virtual void SetUp() override
{
495 InstallWorkerTest::SetUp();
497 const ParamType
& param
= GetParam();
498 system_level_
= std::tr1::get
<0>(param
);
499 multi_install_
= std::tr1::get
<1>(param
);
500 root_key_
= system_level_
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
502 installation_state_
.reset(new MockInstallationState());
503 AddChromeFrameToInstallationState(system_level_
, multi_install_
,
504 installation_state_
.get());
505 installer_state_
.reset(BuildBasicInstallerState(
506 system_level_
, multi_install_
, *installation_state_
,
507 multi_install_
? InstallerState::MULTI_UPDATE
:
508 InstallerState::SINGLE_INSTALL_OR_UPDATE
));
510 AddChromeBinariesToInstallerState(*installation_state_
,
511 installer_state_
.get());
512 AddChromeFrameToInstallerState(*installation_state_
,
513 installer_state_
.get());
516 scoped_ptr
<MockInstallationState
> installation_state_
;
517 scoped_ptr
<MockInstallerState
> installer_state_
;
523 TEST_P(OldIELowRightsTests
, AddDeleteOldIELowRightsPolicyWorkItems
) {
524 StrictMock
<MockWorkItemList
> work_item_list
;
526 EXPECT_CALL(work_item_list
,
527 AddDeleteRegKeyWorkItem(root_key_
, StrEq(old_elevation_key
)))
530 AddDeleteOldIELowRightsPolicyWorkItems(*installer_state_
.get(),
534 INSTANTIATE_TEST_CASE_P(Variations
, OldIELowRightsTests
,
535 Combine(Bool(), Bool()));
537 TEST_F(InstallWorkerTest
, GoogleUpdateWorkItemsTest
) {
538 const bool system_level
= true;
539 const bool multi_install
= true;
540 MockWorkItemList work_item_list
;
542 scoped_ptr
<MockInstallationState
> installation_state(
543 BuildChromeInstallationState(system_level
, false));
545 MockProductState cf_state
;
546 cf_state
.set_version(new Version(*current_version_
));
547 cf_state
.set_multi_install(false);
549 installation_state
->SetProductState(system_level
,
550 BrowserDistribution::CHROME_FRAME
, cf_state
);
552 scoped_ptr
<MockInstallerState
> installer_state(
553 BuildChromeInstallerState(system_level
, multi_install
,
555 InstallerState::MULTI_INSTALL
));
557 // Expect the multi Client State key to be created.
558 BrowserDistribution
* multi_dist
=
559 BrowserDistribution::GetSpecificDistribution(
560 BrowserDistribution::CHROME_BINARIES
);
561 std::wstring
multi_app_guid(multi_dist
->GetAppGuid());
562 std::wstring
multi_client_state_suffix(L
"ClientState\\" + multi_app_guid
);
563 EXPECT_CALL(work_item_list
,
564 AddCreateRegKeyWorkItem(_
, HasSubstr(multi_client_state_suffix
)))
565 .Times(testing::AnyNumber());
567 // Expect ClientStateMedium to be created for system-level installs.
568 EXPECT_CALL(work_item_list
,
569 AddCreateRegKeyWorkItem(_
, HasSubstr(L
"ClientStateMedium\\" +
571 .Times(system_level
? 1 : 0);
573 // Expect to see a set value for the "TEST" brand code in the multi Client
575 EXPECT_CALL(work_item_list
,
576 AddSetRegStringValueWorkItem(_
,
577 HasSubstr(multi_client_state_suffix
),
578 StrEq(google_update::kRegBrandField
),
582 // There may also be some calls to set 'ap' values.
583 EXPECT_CALL(work_item_list
,
584 AddSetRegStringValueWorkItem(_
, _
,
585 StrEq(google_update::kRegApField
),
586 _
, _
)).Times(testing::AnyNumber());
588 // Expect "oeminstall" to be cleared.
589 EXPECT_CALL(work_item_list
,
590 AddDeleteRegValueWorkItem(
592 HasSubstr(multi_client_state_suffix
),
593 StrEq(google_update::kRegOemInstallField
))).Times(1);
595 // Expect "eulaaccepted" to set.
596 EXPECT_CALL(work_item_list
,
597 AddSetRegDwordValueWorkItem(
599 HasSubstr(multi_client_state_suffix
),
600 StrEq(google_update::kRegEULAAceptedField
),
601 Eq(static_cast<DWORD
>(1)),
604 AddGoogleUpdateWorkItems(*installation_state
.get(),
605 *installer_state
.get(),
609 // Test that usagestats values are migrated properly.
610 TEST_F(InstallWorkerTest
, AddUsageStatsWorkItems
) {
611 const bool system_level
= true;
612 const bool multi_install
= true;
613 MockWorkItemList work_item_list
;
615 scoped_ptr
<MockInstallationState
> installation_state(
616 BuildChromeInstallationState(system_level
, multi_install
));
618 MockProductState chrome_state
;
619 chrome_state
.set_version(new Version(*current_version_
));
620 chrome_state
.set_multi_install(false);
621 chrome_state
.set_usagestats(1);
623 installation_state
->SetProductState(system_level
,
624 BrowserDistribution::CHROME_BROWSER
, chrome_state
);
626 scoped_ptr
<MockInstallerState
> installer_state(
627 BuildChromeInstallerState(system_level
, multi_install
,
629 InstallerState::MULTI_INSTALL
));
631 // Expect the multi Client State key to be created.
632 BrowserDistribution
* multi_dist
=
633 BrowserDistribution::GetSpecificDistribution(
634 BrowserDistribution::CHROME_BINARIES
);
635 std::wstring
multi_app_guid(multi_dist
->GetAppGuid());
636 EXPECT_CALL(work_item_list
,
637 AddCreateRegKeyWorkItem(_
, HasSubstr(multi_app_guid
))).Times(1);
639 // Expect to see a set value for the usagestats in the multi Client State key.
640 EXPECT_CALL(work_item_list
,
641 AddSetRegDwordValueWorkItem(
643 HasSubstr(multi_app_guid
),
644 StrEq(google_update::kRegUsageStatsField
),
645 Eq(static_cast<DWORD
>(1)),
648 // Expect to see some values cleaned up from Chrome's keys.
649 BrowserDistribution
* chrome_dist
=
650 BrowserDistribution::GetSpecificDistribution(
651 BrowserDistribution::CHROME_BROWSER
);
653 EXPECT_CALL(work_item_list
,
654 AddDeleteRegValueWorkItem(
656 StrEq(chrome_dist
->GetStateMediumKey()),
657 StrEq(google_update::kRegUsageStatsField
))).Times(1);
658 EXPECT_CALL(work_item_list
,
659 AddDeleteRegValueWorkItem(
660 Eq(HKEY_CURRENT_USER
),
661 StrEq(chrome_dist
->GetStateKey()),
662 StrEq(google_update::kRegUsageStatsField
))).Times(1);
664 EXPECT_CALL(work_item_list
,
665 AddDeleteRegValueWorkItem(
666 Eq(installer_state
->root_key()),
667 StrEq(chrome_dist
->GetStateKey()),
668 StrEq(google_update::kRegUsageStatsField
))).Times(1);
670 AddUsageStatsWorkItems(*installation_state
.get(),
671 *installer_state
.get(),
675 // The Quick Enable tests only make sense for the Google Chrome build as it
676 // interacts with registry values that are specific to Google Update.
677 #if defined(GOOGLE_CHROME_BUILD)
679 // Test scenarios under which the quick-enable-cf command should not exist after
680 // the run. We're permissive in that we allow the DeleteRegKeyWorkItem even if
681 // it isn't strictly needed.
682 class QuickEnableAbsentTest
: public InstallWorkerTest
{
684 virtual void SetUp() {
685 InstallWorkerTest::SetUp();
686 root_key_
= system_level_
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
687 delete_reg_key_item_
.reset(WorkItem::CreateDeleteRegKeyWorkItem(
688 root_key_
, kRegKeyPath
, WorkItem::kWow64Default
));
689 machine_state_
.reset(new MockInstallationState());
690 EXPECT_CALL(work_item_list_
,
691 AddDeleteRegKeyWorkItem(Eq(root_key_
), StrCaseEq(kRegKeyPath
)))
693 .WillRepeatedly(Return(delete_reg_key_item_
.get()));
695 virtual void TearDown() {
696 machine_state_
.reset();
697 delete_reg_key_item_
.reset();
699 InstallWorkerTest::TearDown();
702 static const bool system_level_
= false;
703 static const wchar_t kRegKeyPath
[];
705 scoped_ptr
<DeleteRegKeyWorkItem
> delete_reg_key_item_
;
706 scoped_ptr
<MockInstallationState
> machine_state_
;
707 StrictMock
<MockWorkItemList
> work_item_list_
;
710 const wchar_t QuickEnableAbsentTest::kRegKeyPath
[] =
711 L
"Software\\Google\\Update\\Clients\\"
712 L
"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}\\Commands\\quick-enable-cf";
714 TEST_F(QuickEnableAbsentTest
, CleanInstallSingleChrome
) {
715 // Install single Chrome on a clean system.
716 scoped_ptr
<MockInstallerState
> installer_state(
717 BuildBasicInstallerState(system_level_
, true, *machine_state_
,
718 InstallerState::MULTI_UPDATE
));
719 AddQuickEnableChromeFrameWorkItems(*installer_state
, &work_item_list_
);
722 TEST_F(InstallWorkerTest
, WillProductBePresentAfterSetup
) {
723 BrowserDistribution::Type prod_type_list
[] = {
724 BrowserDistribution::CHROME_BROWSER
,
725 BrowserDistribution::CHROME_FRAME
,
726 // Excluding BrowserDistribution::CHROME_BINARIES, since it is installed
727 // along with other products.
729 enum { // Index into prod_type_list[].
732 NUM_TYPE
// This must appear last.
734 DCHECK(arraysize(prod_type_list
) == NUM_TYPE
);
735 InstallerState::Operation op_list
[] = {
736 InstallerState::UNINSTALL
,
737 InstallerState::SINGLE_INSTALL_OR_UPDATE
740 const bool system_level
= false;
741 const bool multi_install
= true;
743 // Loop over machine states: {No product, Chrome, CF, Chrome + CF}.
744 for (int i_mach
= 0; i_mach
< (1 << NUM_TYPE
); ++i_mach
) {
745 // i_mach is the machine state before operation, as bit mask.
746 scoped_ptr
<MockInstallationState
> machine_state(
747 new MockInstallationState());
748 if ((i_mach
& (1 << TYPE_BROWSER
)) != 0) { // Add Chrome.
749 AddChromeToInstallationState(system_level
, multi_install
,
750 machine_state
.get());
752 if ((i_mach
& (1 << TYPE_CF
)) != 0) { // Add Chrome Frame.
753 AddChromeFrameToInstallationState(system_level
, multi_install
,
754 machine_state
.get());
757 // Loop over operations: {uninstall, install/update}.
758 for (int i_op
= 0; i_op
< arraysize(op_list
); ++i_op
) {
760 // Loop over product types to operate on: {TYPE_BROWSER, TYPE_CF}.
761 for (int i_type_op
= 0; i_type_op
< NUM_TYPE
; ++i_type_op
) {
762 scoped_ptr
<InstallerState
> installer_state
;
763 if (i_type_op
== TYPE_BROWSER
) {
764 installer_state
.reset(BuildChromeInstallerState(
765 system_level
, multi_install
, *machine_state
, op_list
[i_op
]));
766 } else if (i_type_op
== TYPE_CF
) {
767 // Skip the CF uninstall case due to limitations in
768 // BuildChromeFrameInstallerState().
769 if (op_list
[i_op
] == InstallerState::UNINSTALL
)
772 installer_state
.reset(BuildChromeFrameInstallerState(
773 system_level
, multi_install
, *machine_state
, op_list
[i_op
]));
778 // Calculate the machine state after operation, as bit mask.
779 // If uninstall, remove product with bitwise AND; else add with OR.
780 int mach_after
= (op_list
[i_op
] == InstallerState::UNINSTALL
) ?
781 i_mach
& ~(1 << i_type_op
) : i_mach
| (1 << i_type_op
);
783 // Verify predicted presence of Chrome Binaries.
784 bool bin_res
= installer::WillProductBePresentAfterSetup(
787 BrowserDistribution::CHROME_BINARIES
);
788 // Binaries are expected to be present iff any product is installed.
789 bool bin_expect
= mach_after
!= 0;
790 EXPECT_EQ(bin_expect
, bin_res
);
792 // Loop over product types to check: {TYPE_BROWSER, TYPE_CF}.
793 for (int i_type_check
= 0; i_type_check
< NUM_TYPE
; ++i_type_check
) {
794 // Verify predicted presence of product.
795 bool prod_res
= installer::WillProductBePresentAfterSetup(
798 prod_type_list
[i_type_check
]);
799 bool prod_expect
= (mach_after
& (1 << i_type_check
)) != 0;
800 EXPECT_EQ(prod_expect
, prod_res
);
807 #endif // defined(GOOGLE_CHROME_BUILD)