1 // Copyright 2015 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/util/beacons.h"
7 #include "base/base_paths.h"
8 #include "base/memory/scoped_vector.h"
9 #include "base/path_service.h"
10 #include "base/test/scoped_path_override.h"
11 #include "base/test/test_reg_util_win.h"
12 #include "base/test/test_timeouts.h"
13 #include "base/threading/platform_thread.h"
14 #include "base/win/registry.h"
15 #include "base/win/win_util.h"
16 #include "chrome/installer/util/browser_distribution.h"
17 #include "chrome/installer/util/test_app_registration_data.h"
18 #include "chrome/installer/util/util_constants.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using ::testing::Bool
;
22 using ::testing::Combine
;
23 using ::testing::Values
;
24 using BeaconType
= installer_util::Beacon::BeaconType
;
25 using BeaconScope
= installer_util::Beacon::BeaconScope
;
27 namespace installer_util
{
29 // A test fixture that exercises a beacon.
30 class BeaconTest
: public ::testing::TestWithParam
<
31 ::testing::tuple
<BeaconType
, BeaconScope
, bool>> {
33 static const base::char16 kBeaconName
[];
36 : beacon_type_(::testing::get
<0>(GetParam())),
37 beacon_scope_(::testing::get
<1>(GetParam())),
38 system_install_(::testing::get
<2>(GetParam())),
43 app_registration_data_
) {
44 // Override the registry so that tests can freely push state to it.
45 registry_override_manager_
.OverrideRegistry(HKEY_CURRENT_USER
);
46 registry_override_manager_
.OverrideRegistry(HKEY_LOCAL_MACHINE
);
49 TestAppRegistrationData app_registration_data_
;
50 BeaconType beacon_type_
;
51 BeaconScope beacon_scope_
;
56 registry_util::RegistryOverrideManager registry_override_manager_
;
60 const base::char16
BeaconTest::kBeaconName
[] = L
"TestBeacon";
62 // Nothing in the regsitry, so the beacon should not exist.
63 TEST_P(BeaconTest
, GetNonExistant
) {
64 ASSERT_TRUE(beacon_
.Get().is_null());
67 // Updating and then getting the beacon should return a value, and that it is
69 TEST_P(BeaconTest
, UpdateAndGet
) {
70 base::Time
before(base::Time::Now());
72 base::Time
after(base::Time::Now());
73 base::Time
beacon_time(beacon_
.Get());
74 ASSERT_FALSE(beacon_time
.is_null());
75 ASSERT_LE(before
, beacon_time
);
76 ASSERT_GE(after
, beacon_time
);
79 // Tests that updating a first beacon only updates it the first time, but doing
80 // so for a last beacon always updates.
81 TEST_P(BeaconTest
, UpdateTwice
) {
83 base::Time
beacon_time(beacon_
.Get());
85 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
88 if (beacon_type_
== BeaconType::FIRST
) {
89 ASSERT_EQ(beacon_time
, beacon_
.Get());
91 ASSERT_NE(beacon_time
, beacon_
.Get());
95 // Tests that the beacon is written into the proper location in the registry.
96 TEST_P(BeaconTest
, Location
) {
98 HKEY right_root
= system_install_
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
99 HKEY wrong_root
= system_install_
? HKEY_CURRENT_USER
: HKEY_LOCAL_MACHINE
;
100 base::string16 right_key
;
101 base::string16 wrong_key
;
102 base::string16 value_name
;
104 if (beacon_scope_
== BeaconScope::PER_INSTALL
|| !system_install_
) {
105 value_name
= kBeaconName
;
106 right_key
= app_registration_data_
.GetStateKey();
107 wrong_key
= app_registration_data_
.GetStateMediumKey();
109 ASSERT_TRUE(base::win::GetUserSidString(&value_name
));
111 app_registration_data_
.GetStateMediumKey() + L
"\\" + kBeaconName
;
112 wrong_key
= app_registration_data_
.GetStateKey();
115 // Keys should not exist in the wrong root or in the right root but wrong key.
116 ASSERT_FALSE(base::win::RegKey(wrong_root
, right_key
.c_str(),
117 KEY_READ
).Valid()) << right_key
;
118 ASSERT_FALSE(base::win::RegKey(wrong_root
, wrong_key
.c_str(),
119 KEY_READ
).Valid()) << wrong_key
;
120 ASSERT_FALSE(base::win::RegKey(right_root
, wrong_key
.c_str(),
121 KEY_READ
).Valid()) << wrong_key
;
122 // The right key should exist.
123 base::win::RegKey
key(right_root
, right_key
.c_str(), KEY_READ
);
124 ASSERT_TRUE(key
.Valid()) << right_key
;
125 // And should have the value.
126 ASSERT_TRUE(key
.HasValue(value_name
.c_str())) << value_name
;
129 // Run the tests for all combinations of beacon type, scope, and install level.
130 INSTANTIATE_TEST_CASE_P(BeaconTest
,
132 Combine(Values(BeaconType::FIRST
, BeaconType::LAST
),
133 Values(BeaconScope::PER_USER
,
134 BeaconScope::PER_INSTALL
),
137 enum class DistributionVariant
{
143 class DefaultBrowserBeaconTest
144 : public ::testing::TestWithParam
<DistributionVariant
> {
146 using Super
= ::testing::TestWithParam
<DistributionVariant
>;
148 DefaultBrowserBeaconTest()
149 : system_install_(GetParam() == DistributionVariant::SYSTEM_LEVEL
),
150 chrome_sxs_(GetParam() == DistributionVariant::SXS
),
151 chrome_exe_(GetChromePathForParams()),
152 distribution_(nullptr) {}
154 void SetUp() override
{
157 // Override FILE_EXE so that various InstallUtil functions will consider
158 // this to be a user/system Chrome or Chrome SxS.
159 path_overrides_
.push_back(new base::ScopedPathOverride(
160 base::FILE_EXE
, chrome_exe_
, true /* is_absolute */,
161 false /* !create */));
163 // Override these paths with their own values so that they can be found
164 // after the registry override manager is in place. Getting them would
165 // otherwise fail since the underlying calls to the OS need to see the real
166 // contents of the registry.
167 static const int kPathKeys
[] = {
168 base::DIR_PROGRAM_FILES
,
169 base::DIR_PROGRAM_FILESX86
,
170 base::DIR_LOCAL_APP_DATA
,
172 for (int key
: kPathKeys
) {
174 PathService::Get(key
, &temp
);
175 path_overrides_
.push_back(new base::ScopedPathOverride(key
, temp
));
178 // Override the registry so that tests can freely push state to it.
179 registry_override_manager_
.OverrideRegistry(HKEY_CURRENT_USER
);
180 registry_override_manager_
.OverrideRegistry(HKEY_LOCAL_MACHINE
);
182 distribution_
= BrowserDistribution::GetDistribution();
185 bool system_install_
;
187 base::FilePath chrome_exe_
;
188 BrowserDistribution
* distribution_
;
191 base::FilePath
GetChromePathForParams() const {
192 base::FilePath chrome_exe
;
193 int dir_key
= base::DIR_LOCAL_APP_DATA
;
195 if (system_install_
) {
197 static const int kSystemKey
= base::DIR_PROGRAM_FILESX86
;
199 static const int kSystemKey
= base::DIR_PROGRAM_FILES
;
201 dir_key
= kSystemKey
;
203 PathService::Get(dir_key
, &chrome_exe
);
204 #if defined(GOOGLE_CHROME_BUILD)
205 chrome_exe
= chrome_exe
.Append(installer::kGoogleChromeInstallSubDir1
);
207 chrome_exe
= chrome_exe
.Append(
208 base::string16(installer::kGoogleChromeInstallSubDir2
) +
209 installer::kSxSSuffix
);
211 chrome_exe
= chrome_exe
.Append(installer::kGoogleChromeInstallSubDir2
);
214 chrome_exe
= chrome_exe
.AppendASCII("Chromium");
216 chrome_exe
= chrome_exe
.Append(installer::kInstallBinaryDir
);
217 return chrome_exe
.Append(installer::kChromeExe
);
220 ScopedVector
<base::ScopedPathOverride
> path_overrides_
;
221 registry_util::RegistryOverrideManager registry_override_manager_
;
224 // Tests that the default browser beacons work as expected.
225 TEST_P(DefaultBrowserBeaconTest
, All
) {
226 scoped_ptr
<Beacon
> last_was_default(MakeLastWasDefaultBeacon(
227 system_install_
, distribution_
->GetAppRegistrationData()));
228 scoped_ptr
<Beacon
> first_not_default(MakeFirstNotDefaultBeacon(
229 system_install_
, distribution_
->GetAppRegistrationData()));
231 ASSERT_TRUE(last_was_default
->Get().is_null());
232 ASSERT_TRUE(first_not_default
->Get().is_null());
234 // Chrome is not default.
235 UpdateDefaultBrowserBeaconWithState(chrome_exe_
, distribution_
,
236 ShellUtil::NOT_DEFAULT
);
237 ASSERT_TRUE(last_was_default
->Get().is_null());
238 ASSERT_FALSE(first_not_default
->Get().is_null());
241 UpdateDefaultBrowserBeaconWithState(chrome_exe_
, distribution_
,
242 ShellUtil::IS_DEFAULT
);
243 ASSERT_FALSE(last_was_default
->Get().is_null());
244 ASSERT_TRUE(first_not_default
->Get().is_null());
247 UpdateDefaultBrowserBeaconWithState(chrome_exe_
, distribution_
,
248 ShellUtil::IS_DEFAULT
);
249 ASSERT_FALSE(last_was_default
->Get().is_null());
250 ASSERT_TRUE(first_not_default
->Get().is_null());
252 // Now it's not again.
253 UpdateDefaultBrowserBeaconWithState(chrome_exe_
, distribution_
,
254 ShellUtil::NOT_DEFAULT
);
255 ASSERT_FALSE(last_was_default
->Get().is_null());
256 ASSERT_FALSE(first_not_default
->Get().is_null());
258 // And it still isn't.
259 UpdateDefaultBrowserBeaconWithState(chrome_exe_
, distribution_
,
260 ShellUtil::NOT_DEFAULT
);
261 ASSERT_FALSE(last_was_default
->Get().is_null());
262 ASSERT_FALSE(first_not_default
->Get().is_null());
265 INSTANTIATE_TEST_CASE_P(SystemLevelChrome
,
266 DefaultBrowserBeaconTest
,
267 Values(DistributionVariant::SYSTEM_LEVEL
));
268 INSTANTIATE_TEST_CASE_P(UserLevelChrome
,
269 DefaultBrowserBeaconTest
,
270 Values(DistributionVariant::USER_LEVEL
));
271 #if 0 && defined(GOOGLE_CHROME_BUILD)
272 // Disabled for now since InstallUtil::IsChromeSxSProcess makes this impossible.
273 INSTANTIATE_TEST_CASE_P(ChromeSxS
, DefaultBrowserBeaconTest
,
274 Values(DistributionVariant::SXS
));
277 } // namespace installer_util