OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "chrome/installer/util/beacons.h" |
| 6 |
| 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" |
| 20 |
| 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; |
| 26 |
| 27 namespace installer_util { |
| 28 |
| 29 // A test fixture that exercises a beacon. |
| 30 class BeaconTest : public ::testing::TestWithParam< |
| 31 ::testing::tuple<BeaconType, BeaconScope, bool>> { |
| 32 protected: |
| 33 static const base::char16 kBeaconName[]; |
| 34 |
| 35 BeaconTest() |
| 36 : beacon_type_(::testing::get<0>(GetParam())), |
| 37 beacon_scope_(::testing::get<1>(GetParam())), |
| 38 system_install_(::testing::get<2>(GetParam())), |
| 39 beacon_(kBeaconName, |
| 40 beacon_type_, |
| 41 beacon_scope_, |
| 42 system_install_, |
| 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); |
| 47 } |
| 48 |
| 49 TestAppRegistrationData app_registration_data_; |
| 50 BeaconType beacon_type_; |
| 51 BeaconScope beacon_scope_; |
| 52 bool system_install_; |
| 53 Beacon beacon_; |
| 54 |
| 55 private: |
| 56 registry_util::RegistryOverrideManager registry_override_manager_; |
| 57 }; |
| 58 |
| 59 // static |
| 60 const base::char16 BeaconTest::kBeaconName[] = L"TestBeacon"; |
| 61 |
| 62 // Nothing in the regsitry, so the beacon should not exist. |
| 63 TEST_P(BeaconTest, GetNonExistant) { |
| 64 ASSERT_TRUE(beacon_.Get().is_null()); |
| 65 } |
| 66 |
| 67 // Updating and then getting the beacon should return a value, and that it is |
| 68 // within range. |
| 69 TEST_P(BeaconTest, UpdateAndGet) { |
| 70 base::Time before(base::Time::Now()); |
| 71 beacon_.Update(); |
| 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); |
| 77 } |
| 78 |
| 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) { |
| 82 beacon_.Update(); |
| 83 base::Time beacon_time(beacon_.Get()); |
| 84 |
| 85 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 86 |
| 87 beacon_.Update(); |
| 88 if (beacon_type_ == BeaconType::FIRST) { |
| 89 ASSERT_EQ(beacon_time, beacon_.Get()); |
| 90 } else { |
| 91 ASSERT_NE(beacon_time, beacon_.Get()); |
| 92 } |
| 93 } |
| 94 |
| 95 // Tests that the beacon is written into the proper location in the registry. |
| 96 TEST_P(BeaconTest, Location) { |
| 97 beacon_.Update(); |
| 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; |
| 103 |
| 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(); |
| 108 } else { |
| 109 ASSERT_TRUE(base::win::GetUserSidString(&value_name)); |
| 110 right_key = |
| 111 app_registration_data_.GetStateMediumKey() + L"\\" + kBeaconName; |
| 112 wrong_key = app_registration_data_.GetStateKey(); |
| 113 } |
| 114 |
| 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; |
| 127 } |
| 128 |
| 129 // Run the tests for all combinations of beacon type, scope, and install level. |
| 130 INSTANTIATE_TEST_CASE_P(BeaconTest, |
| 131 BeaconTest, |
| 132 Combine(Values(BeaconType::FIRST, BeaconType::LAST), |
| 133 Values(BeaconScope::PER_USER, |
| 134 BeaconScope::PER_INSTALL), |
| 135 Bool())); |
| 136 |
| 137 enum class DistributionVariant { |
| 138 SYSTEM_LEVEL, |
| 139 USER_LEVEL, |
| 140 SXS, |
| 141 }; |
| 142 |
| 143 class DefaultBrowserBeaconTest |
| 144 : public ::testing::TestWithParam<DistributionVariant> { |
| 145 protected: |
| 146 using Super = ::testing::TestWithParam<DistributionVariant>; |
| 147 |
| 148 DefaultBrowserBeaconTest() |
| 149 : system_install_(GetParam() == DistributionVariant::SYSTEM_LEVEL), |
| 150 chrome_sxs_(GetParam() == DistributionVariant::SXS), |
| 151 chrome_exe_(GetChromePathForParams()), |
| 152 distribution_(nullptr) {} |
| 153 |
| 154 void SetUp() override { |
| 155 Super::SetUp(); |
| 156 |
| 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 */)); |
| 162 |
| 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, |
| 171 }; |
| 172 for (int key : kPathKeys) { |
| 173 base::FilePath temp; |
| 174 PathService::Get(key, &temp); |
| 175 path_overrides_.push_back(new base::ScopedPathOverride(key, temp)); |
| 176 } |
| 177 |
| 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); |
| 181 |
| 182 distribution_ = BrowserDistribution::GetDistribution(); |
| 183 } |
| 184 |
| 185 bool system_install_; |
| 186 bool chrome_sxs_; |
| 187 base::FilePath chrome_exe_; |
| 188 BrowserDistribution* distribution_; |
| 189 |
| 190 private: |
| 191 base::FilePath GetChromePathForParams() const { |
| 192 base::FilePath chrome_exe; |
| 193 int dir_key = base::DIR_LOCAL_APP_DATA; |
| 194 |
| 195 if (system_install_) { |
| 196 #if defined(_WIN64) |
| 197 static const int kSystemKey = base::DIR_PROGRAM_FILESX86; |
| 198 #else |
| 199 static const int kSystemKey = base::DIR_PROGRAM_FILES; |
| 200 #endif |
| 201 dir_key = kSystemKey; |
| 202 } |
| 203 PathService::Get(dir_key, &chrome_exe); |
| 204 #if defined(GOOGLE_CHROME_BUILD) |
| 205 chrome_exe = chrome_exe.Append(installer::kGoogleChromeInstallSubDir1); |
| 206 if (chrome_sxs_) { |
| 207 chrome_exe = chrome_exe.Append( |
| 208 base::string16(installer::kGoogleChromeInstallSubDir2) + |
| 209 installer::kSxSSuffix); |
| 210 } else { |
| 211 chrome_exe = chrome_exe.Append(installer::kGoogleChromeInstallSubDir2); |
| 212 } |
| 213 #else |
| 214 chrome_exe = chrome_exe.AppendASCII("Chromium"); |
| 215 #endif |
| 216 chrome_exe = chrome_exe.Append(installer::kInstallBinaryDir); |
| 217 return chrome_exe.Append(installer::kChromeExe); |
| 218 } |
| 219 |
| 220 ScopedVector<base::ScopedPathOverride> path_overrides_; |
| 221 registry_util::RegistryOverrideManager registry_override_manager_; |
| 222 }; |
| 223 |
| 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())); |
| 230 |
| 231 ASSERT_TRUE(last_was_default->Get().is_null()); |
| 232 ASSERT_TRUE(first_not_default->Get().is_null()); |
| 233 |
| 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()); |
| 239 |
| 240 // Then it is. |
| 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()); |
| 245 |
| 246 // It still is. |
| 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()); |
| 251 |
| 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()); |
| 257 |
| 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()); |
| 263 } |
| 264 |
| 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)); |
| 275 #endif |
| 276 |
| 277 } // namespace installer_util |
OLD | NEW |