snooping_protection_controller_unittest.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. // Copyright 2021 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. #include "ash/system/human_presence/snooping_protection_controller.h"
  5. #include <memory>
  6. #include "ash/constants/ash_features.h"
  7. #include "ash/constants/ash_pref_names.h"
  8. #include "ash/constants/ash_switches.h"
  9. #include "ash/session/session_controller_impl.h"
  10. #include "ash/session/test_session_controller_client.h"
  11. #include "ash/shell.h"
  12. #include "ash/system/human_presence/human_presence_metrics.h"
  13. #include "ash/test/ash_test_base.h"
  14. #include "base/test/metrics/histogram_tester.h"
  15. #include "base/test/scoped_command_line.h"
  16. #include "base/test/scoped_feature_list.h"
  17. #include "base/test/task_environment.h"
  18. #include "base/time/time.h"
  19. #include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
  20. #include "chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.h"
  21. #include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
  22. #include "components/account_id/account_id.h"
  23. #include "components/user_manager/user_type.h"
  24. namespace ash {
  25. namespace {
  26. namespace metrics = ash::snooping_protection_metrics;
  27. // The minimum positive window length will be in the range of a few seconds.
  28. // Here we define two windows that will surely be shorter and longer resp. than
  29. // the positive window length.
  30. constexpr base::TimeDelta kShortTime = base::Milliseconds(30);
  31. constexpr base::TimeDelta kLongTime = base::Seconds(30);
  32. // A fixture that provides access to a fake daemon and an instance of the
  33. // controller hooked up to the test environment.
  34. class SnoopingProtectionControllerTestBase : public NoSessionAshTestBase {
  35. public:
  36. // Arguments control the state of the feature and service on controller
  37. // construction. We can't set this value in individual tests since it must be
  38. // done before AshTestBase::SetUp() executes.
  39. SnoopingProtectionControllerTestBase(
  40. bool service_available,
  41. bool service_state,
  42. const std::map<std::string, std::string>& params)
  43. : NoSessionAshTestBase(
  44. base::test::TaskEnvironment::TimeSource::MOCK_TIME),
  45. service_available_(service_available),
  46. service_state_(service_state),
  47. params_(params) {
  48. scoped_feature_list_.InitAndEnableFeatureWithParameters(
  49. ash::features::kSnoopingProtection, params_);
  50. scoped_command_line_.GetProcessCommandLine()->AppendSwitch(
  51. switches::kHasHps);
  52. }
  53. SnoopingProtectionControllerTestBase(
  54. const SnoopingProtectionControllerTestBase&) = delete;
  55. SnoopingProtectionControllerTestBase& operator=(
  56. const SnoopingProtectionControllerTestBase&) = delete;
  57. ~SnoopingProtectionControllerTestBase() override = default;
  58. void SetUp() override {
  59. HumanPresenceDBusClient::InitializeFake();
  60. dbus_client_ = FakeHumanPresenceDBusClient::Get();
  61. dbus_client_->set_hps_service_is_available(service_available_);
  62. hps::HpsResultProto state;
  63. state.set_value(service_state_ ? hps::HpsResult::POSITIVE
  64. : hps::HpsResult::NEGATIVE);
  65. dbus_client_->set_hps_notify_result(state);
  66. AshTestBase::SetUp();
  67. controller_ = Shell::Get()->snooping_protection_controller();
  68. // The controller has now been initialized, part of which entails sending a
  69. // method to the DBus service. Here we wait for the service to
  70. // asynchronously respond.
  71. task_environment()->FastForwardBy(kShortTime);
  72. }
  73. void TearDown() override {
  74. AshTestBase::TearDown();
  75. HumanPresenceDBusClient::Shutdown();
  76. }
  77. protected:
  78. base::test::ScopedFeatureList scoped_feature_list_;
  79. base::test::ScopedCommandLine scoped_command_line_;
  80. const bool service_available_;
  81. const bool service_state_;
  82. const std::map<std::string, std::string> params_;
  83. FakeHumanPresenceDBusClient* dbus_client_ = nullptr;
  84. SnoopingProtectionController* controller_ = nullptr;
  85. // Simulates a login. This will trigger a DBus call if and only if logging in
  86. // was the final precondition required for the feature. Hence we wait for any
  87. // asynchronous logic to complete, revealing whether a DBus call was correctly
  88. // or incorrectly made.
  89. void SimulateLogin() {
  90. SimulateUserLogin("testuser@gmail.com");
  91. task_environment()->FastForwardBy(kShortTime);
  92. }
  93. // Enables or disables the user pref for the feature. This will trigger a DBus
  94. // call if and only if logging in was the final precondition required for the
  95. // feature. Hence we wait for any asynchronous logic to complete, revealing
  96. // whether a DBus call was correctly or incorrectly made.
  97. void SetEnabledPref(bool enabled) {
  98. Shell::Get()->session_controller()->GetActivePrefService()->SetBoolean(
  99. prefs::kSnoopingProtectionEnabled, enabled);
  100. task_environment()->FastForwardBy(kShortTime);
  101. }
  102. };
  103. // A test fixture where no snooper is initially detected (using a minimal set of
  104. // valid params).
  105. class SnoopingProtectionControllerTestAbsent
  106. : public SnoopingProtectionControllerTestBase {
  107. public:
  108. SnoopingProtectionControllerTestAbsent()
  109. : SnoopingProtectionControllerTestBase(
  110. /*service_available=*/true,
  111. /*service_state=*/false,
  112. /*params=*/{{"SnoopingProtection_filter_config_case", "1"}}) {}
  113. };
  114. // Test that icon is hidden by default.
  115. TEST_F(SnoopingProtectionControllerTestAbsent, Hidden) {
  116. SimulateLogin();
  117. SetEnabledPref(false);
  118. EXPECT_EQ(dbus_client_->hps_notify_count(), 0);
  119. EXPECT_FALSE(controller_->SnooperPresent());
  120. }
  121. // Test that messages from the daemon toggle the icon.
  122. TEST_F(SnoopingProtectionControllerTestAbsent, PresenceChange) {
  123. SimulateLogin();
  124. SetEnabledPref(true);
  125. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  126. EXPECT_FALSE(controller_->SnooperPresent());
  127. hps::HpsResultProto state;
  128. state.set_value(hps::HpsResult::POSITIVE);
  129. controller_->OnHpsNotifyChanged(state);
  130. task_environment()->FastForwardBy(kLongTime);
  131. EXPECT_TRUE(controller_->SnooperPresent());
  132. state.set_value(hps::HpsResult::NEGATIVE);
  133. controller_->OnHpsNotifyChanged(state);
  134. task_environment()->FastForwardBy(kLongTime);
  135. EXPECT_FALSE(controller_->SnooperPresent());
  136. }
  137. // Test that daemon signals are only enabled when session and pref state means
  138. // they will be used.
  139. TEST_F(SnoopingProtectionControllerTestAbsent, ReconfigureOnPrefs) {
  140. // When the service becomes available for the first time, one disable is
  141. // performed in case the last session ended in a crash without de-configuring
  142. // the daemon.
  143. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 0);
  144. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 1);
  145. EXPECT_EQ(dbus_client_->hps_notify_count(), 0);
  146. SimulateLogin();
  147. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 0);
  148. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 1);
  149. EXPECT_EQ(dbus_client_->hps_notify_count(), 0);
  150. // Shouldn't configure or message the daemon until the user is ready to start
  151. // using the feature.
  152. SetEnabledPref(true);
  153. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 1);
  154. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 1);
  155. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  156. // Should de-configure the signal when it isn't being used.
  157. SetEnabledPref(false);
  158. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 1);
  159. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 2);
  160. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  161. // Should re-configure and re-poll when the signal becomes relevant again.
  162. SetEnabledPref(true);
  163. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 2);
  164. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 2);
  165. EXPECT_EQ(dbus_client_->hps_notify_count(), 2);
  166. }
  167. // Test that daemon signals are correctly enabled/disabled when the daemon
  168. // starts and stops.
  169. TEST_F(SnoopingProtectionControllerTestAbsent, ReconfigureOnRestarts) {
  170. SimulateLogin();
  171. SetEnabledPref(true);
  172. // Should configure when we're both logged in and have our pref enabled. The
  173. // clean-up deconfigure always occurs.
  174. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 1);
  175. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 1);
  176. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  177. // No deconfigure sent when the service shuts down, because it's unreachable.
  178. controller_->OnShutdown();
  179. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 1);
  180. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 1);
  181. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  182. // Should reconfigure as soon as the service becomes available again.
  183. controller_->OnRestart();
  184. task_environment()->FastForwardBy(kLongTime);
  185. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 2);
  186. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 1);
  187. EXPECT_EQ(dbus_client_->hps_notify_count(), 2);
  188. }
  189. // Test that the service is only re-configured when the user is _both_ logged-in
  190. // and has enabled the preference.
  191. TEST_F(SnoopingProtectionControllerTestAbsent, ReconfigureOnlyIfNecessary) {
  192. // Only the clean-up de-configure should have been sent.
  193. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 0);
  194. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 1);
  195. EXPECT_EQ(dbus_client_->hps_notify_count(), 0);
  196. // Not logged in, so should not configure the service.
  197. SetEnabledPref(true);
  198. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 0);
  199. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 1);
  200. EXPECT_EQ(dbus_client_->hps_notify_count(), 0);
  201. // Only configure when both logged in and pref enabled.
  202. SimulateLogin();
  203. SetEnabledPref(true);
  204. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 1);
  205. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 1);
  206. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  207. }
  208. // A test fixture where a snooper is initially detected (using a minimal set of
  209. // valid params).
  210. class SnoopingProtectionControllerTestPresent
  211. : public SnoopingProtectionControllerTestBase {
  212. public:
  213. SnoopingProtectionControllerTestPresent()
  214. : SnoopingProtectionControllerTestBase(
  215. /*service_available=*/true,
  216. /*service_state=*/true,
  217. /*params=*/{{"SnoopingProtection_filter_config_case", "1"}}) {}
  218. };
  219. // Test that initial daemon state is considered.
  220. TEST_F(SnoopingProtectionControllerTestPresent, PresenceState) {
  221. SimulateLogin();
  222. SetEnabledPref(true);
  223. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  224. EXPECT_TRUE(controller_->SnooperPresent());
  225. }
  226. // Test that a user changing their preference toggles the icon.
  227. TEST_F(SnoopingProtectionControllerTestPresent, PrefChanged) {
  228. SimulateLogin();
  229. SetEnabledPref(false);
  230. EXPECT_EQ(dbus_client_->hps_notify_count(), 0);
  231. EXPECT_FALSE(controller_->SnooperPresent());
  232. SetEnabledPref(true);
  233. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  234. EXPECT_TRUE(controller_->SnooperPresent());
  235. }
  236. // Test that eye icon isn't shown during the OOBE.
  237. TEST_F(SnoopingProtectionControllerTestPresent, Oobe) {
  238. TestSessionControllerClient* session = GetSessionControllerClient();
  239. // Simulate end of OOBE when user is logged in.
  240. session->AddUserSession("testuser@gmail.com", user_manager::USER_TYPE_REGULAR,
  241. /*provide_pref_service=*/true,
  242. /*is_new_profile=*/true);
  243. session->SwitchActiveUser(AccountId::FromUserEmail("testuser@gmail.com"));
  244. session->SetSessionState(session_manager::SessionState::OOBE);
  245. // Shouldn't configure, as the session isn't active.
  246. SetEnabledPref(true);
  247. EXPECT_EQ(dbus_client_->hps_notify_count(), 0);
  248. EXPECT_FALSE(controller_->SnooperPresent());
  249. // Triggers an asynchronous DBus method call.
  250. session->SetSessionState(session_manager::SessionState::ACTIVE);
  251. task_environment()->FastForwardBy(kLongTime);
  252. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  253. EXPECT_TRUE(controller_->SnooperPresent());
  254. }
  255. // Test that the eye icon isn't shown at the login page.
  256. TEST_F(SnoopingProtectionControllerTestPresent, Login) {
  257. // Note: login deferred.
  258. // Shouldn't configure, as the session isn't active.
  259. SetEnabledPref(true);
  260. EXPECT_EQ(dbus_client_->hps_notify_count(), 0);
  261. EXPECT_FALSE(controller_->SnooperPresent());
  262. SimulateLogin();
  263. // Don't show until new user has enabled their preference.
  264. EXPECT_FALSE(controller_->SnooperPresent());
  265. SetEnabledPref(true);
  266. EXPECT_TRUE(controller_->SnooperPresent());
  267. }
  268. // Test that the controller handles service restarts.
  269. TEST_F(SnoopingProtectionControllerTestPresent, Restarts) {
  270. SimulateLogin();
  271. SetEnabledPref(true);
  272. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  273. EXPECT_TRUE(controller_->SnooperPresent());
  274. // Icon is hidden when service goes down. Could erroneously trigger an
  275. // asynchronous DBus method call.
  276. dbus_client_->set_hps_service_is_available(false);
  277. controller_->OnShutdown();
  278. task_environment()->FastForwardBy(kLongTime);
  279. EXPECT_FALSE(controller_->SnooperPresent());
  280. // Icon returns when service restarts. Controller now polls the DBus service
  281. // which responds asynchronously.
  282. dbus_client_->set_hps_service_is_available(true);
  283. controller_->OnRestart();
  284. task_environment()->FastForwardBy(kLongTime);
  285. EXPECT_EQ(dbus_client_->hps_notify_count(), 2);
  286. EXPECT_TRUE(controller_->SnooperPresent());
  287. }
  288. // Check that the controller state stays consistent even when the daemon starts
  289. // and stops.
  290. TEST_F(SnoopingProtectionControllerTestPresent, ClearPresenceState) {
  291. SimulateLogin();
  292. SetEnabledPref(true);
  293. EXPECT_EQ(controller_->SnooperPresent(), true);
  294. // This should internally clear the cached daemon state.
  295. SetEnabledPref(false);
  296. EXPECT_EQ(controller_->SnooperPresent(), false);
  297. // Note: we don't exhaust the run loop here since we want to check the
  298. // controller state _before_ it is updated by asynchronous DBus calls.
  299. Shell::Get()->session_controller()->GetActivePrefService()->SetBoolean(
  300. prefs::kSnoopingProtectionEnabled, true);
  301. EXPECT_EQ(controller_->SnooperPresent(), false);
  302. }
  303. // Test that detection is started and stopped based on whether the device's
  304. // physical orientation is suitable for sensing.
  305. TEST_F(SnoopingProtectionControllerTestPresent, Orientation) {
  306. SimulateLogin();
  307. SetEnabledPref(true);
  308. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 1);
  309. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 1);
  310. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  311. EXPECT_TRUE(controller_->SnooperPresent());
  312. // When the orientation becomes unsuitable, we should disable the daemon.
  313. controller_->OnOrientationChanged(/*suitable_for_human_presence=*/false);
  314. task_environment()->FastForwardBy(kLongTime);
  315. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 1);
  316. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 2);
  317. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  318. EXPECT_FALSE(controller_->SnooperPresent());
  319. // When the orientation becomes suitable again, we should re-enable the
  320. // daemon.
  321. controller_->OnOrientationChanged(/*suitable_for_human_presence=*/true);
  322. task_environment()->FastForwardBy(kLongTime);
  323. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 2);
  324. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 2);
  325. EXPECT_EQ(dbus_client_->hps_notify_count(), 2);
  326. EXPECT_TRUE(controller_->SnooperPresent());
  327. }
  328. // Test that the minimum positive window is respected.
  329. TEST_F(SnoopingProtectionControllerTestPresent, PositiveWindow) {
  330. SimulateLogin();
  331. SetEnabledPref(true);
  332. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  333. EXPECT_TRUE(controller_->SnooperPresent());
  334. hps::HpsResultProto state;
  335. state.set_value(hps::HpsResult::NEGATIVE);
  336. controller_->OnHpsNotifyChanged(state);
  337. // The snooping status shouldn't immediately change, since we have a minimum
  338. // length that it should remain positive.
  339. task_environment()->FastForwardBy(kShortTime);
  340. EXPECT_TRUE(controller_->SnooperPresent());
  341. // After the window, it should become false.
  342. task_environment()->FastForwardBy(kLongTime);
  343. EXPECT_FALSE(controller_->SnooperPresent());
  344. // Snooping status should always immediately become true and stay true.
  345. state.set_value(hps::HpsResult::POSITIVE);
  346. controller_->OnHpsNotifyChanged(state);
  347. EXPECT_TRUE(controller_->SnooperPresent());
  348. task_environment()->FastForwardBy(kLongTime);
  349. EXPECT_TRUE(controller_->SnooperPresent());
  350. // Snooping status should immediately become false if there is a service
  351. // reconfiguration (v.s. state change).
  352. controller_->OnShutdown();
  353. task_environment()->FastForwardBy(kShortTime);
  354. EXPECT_FALSE(controller_->SnooperPresent());
  355. }
  356. // Fixture with the DBus service initially unavailable (using a minimal set of
  357. // valid params).
  358. class SnoopingProtectionControllerTestUnavailable
  359. : public SnoopingProtectionControllerTestBase {
  360. public:
  361. SnoopingProtectionControllerTestUnavailable()
  362. : SnoopingProtectionControllerTestBase(
  363. /*service_available=*/false,
  364. /*service_state=*/true,
  365. /*params=*/{{"SnoopingProtection_filter_config_case", "1"}}) {}
  366. };
  367. // Test that the controller waits for the DBus service to be available and
  368. // doesn't communicate until it is.
  369. TEST_F(SnoopingProtectionControllerTestUnavailable, WaitForService) {
  370. SimulateLogin();
  371. SetEnabledPref(true);
  372. // Shouldn't send any signals (even the clean-up deconfigure) to a service
  373. // that isn't available.
  374. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 0);
  375. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 0);
  376. EXPECT_EQ(dbus_client_->hps_notify_count(), 0);
  377. EXPECT_FALSE(controller_->SnooperPresent());
  378. // Triggers an asynchronous DBus method call.
  379. dbus_client_->set_hps_service_is_available(true);
  380. controller_->OnRestart();
  381. task_environment()->FastForwardBy(kLongTime);
  382. // Should now configure and send the initial poll.
  383. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 1);
  384. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 0);
  385. EXPECT_EQ(dbus_client_->hps_notify_count(), 1);
  386. // Controller now polls the DBus service which responds asynchronously.
  387. EXPECT_TRUE(controller_->SnooperPresent());
  388. }
  389. // Fixture with an invalid feature config.
  390. class SnoopingProtectionControllerTestBadParams
  391. : public SnoopingProtectionControllerTestBase {
  392. public:
  393. SnoopingProtectionControllerTestBadParams()
  394. : SnoopingProtectionControllerTestBase(
  395. /*service_available=*/true,
  396. /*service_state=*/true,
  397. /*params=*/{{"SnoopingProtection_filter_config_case", "0"}}) {}
  398. };
  399. // Test that the controller gracefully handles invalid feature parameters.
  400. TEST_F(SnoopingProtectionControllerTestBadParams, BadParams) {
  401. SimulateLogin();
  402. SetEnabledPref(true);
  403. // Should send the clean-up disable even if we currently have a bad config.
  404. EXPECT_EQ(dbus_client_->enable_hps_notify_count(), 0);
  405. EXPECT_EQ(dbus_client_->disable_hps_notify_count(), 1);
  406. EXPECT_EQ(dbus_client_->hps_notify_count(), 0);
  407. }
  408. // Use the same texture as TestAbsent for UMA metrics.
  409. class SnoopingProtectionControllerTestMetrics
  410. : public SnoopingProtectionControllerTestAbsent {};
  411. TEST_F(SnoopingProtectionControllerTestMetrics, EnableDisablePref) {
  412. base::HistogramTester tester;
  413. SimulateLogin();
  414. tester.ExpectTotalCount(metrics::kEnabledHistogramName, 0);
  415. SetEnabledPref(true);
  416. tester.ExpectBucketCount(metrics::kEnabledHistogramName, 1, 1);
  417. tester.ExpectTotalCount(metrics::kEnabledHistogramName, 1);
  418. SetEnabledPref(false);
  419. tester.ExpectBucketCount(metrics::kEnabledHistogramName, 0, 1);
  420. tester.ExpectTotalCount(metrics::kEnabledHistogramName, 2);
  421. }
  422. TEST_F(SnoopingProtectionControllerTestMetrics, Duration) {
  423. base::HistogramTester tester;
  424. SimulateLogin();
  425. SetEnabledPref(true);
  426. hps::HpsResultProto state;
  427. // The first HpsNotifyChanged will not log anything.
  428. state.set_value(hps::HpsResult::POSITIVE);
  429. controller_->OnHpsNotifyChanged(state);
  430. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 0);
  431. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 0);
  432. task_environment()->FastForwardBy(kLongTime);
  433. // Send UNKNOWN will log a positive duration event.
  434. state.set_value(hps::HpsResult::UNKNOWN);
  435. controller_->OnHpsNotifyChanged(state);
  436. tester.ExpectTimeBucketCount(metrics::kPositiveDurationHistogramName,
  437. kLongTime, 1);
  438. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 1);
  439. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 0);
  440. task_environment()->FastForwardBy(kLongTime);
  441. // Send NEGATIVE a second time will not log anything.
  442. state.set_value(hps::HpsResult::NEGATIVE);
  443. controller_->OnHpsNotifyChanged(state);
  444. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 1);
  445. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 0);
  446. // Send POSITIVE will log a negative duration event.
  447. state.set_value(hps::HpsResult::POSITIVE);
  448. controller_->OnHpsNotifyChanged(state);
  449. tester.ExpectTimeBucketCount(metrics::kNegativeDurationHistogramName,
  450. kLongTime, 1);
  451. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 1);
  452. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 1);
  453. }
  454. TEST_F(SnoopingProtectionControllerTestMetrics, ShutDownTest) {
  455. base::HistogramTester tester;
  456. SimulateLogin();
  457. SetEnabledPref(true);
  458. hps::HpsResultProto state;
  459. // The first HpsNotifyChanged will not log anything.
  460. state.set_value(hps::HpsResult::POSITIVE);
  461. controller_->OnHpsNotifyChanged(state);
  462. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 0);
  463. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 0);
  464. task_environment()->FastForwardBy(kLongTime);
  465. dbus_client_->Shutdown();
  466. tester.ExpectTimeBucketCount(metrics::kPositiveDurationHistogramName,
  467. kLongTime, 1);
  468. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 1);
  469. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 0);
  470. dbus_client_->Restart();
  471. // Send NEGATIVE will not log anything because of the shutdown.
  472. state.set_value(hps::HpsResult::NEGATIVE);
  473. controller_->OnHpsNotifyChanged(state);
  474. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 1);
  475. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 0);
  476. task_environment()->FastForwardBy(kLongTime);
  477. // Send POSITIVE will log a negative duration event.
  478. state.set_value(hps::HpsResult::POSITIVE);
  479. controller_->OnHpsNotifyChanged(state);
  480. tester.ExpectTimeBucketCount(metrics::kNegativeDurationHistogramName,
  481. kLongTime, 1);
  482. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 1);
  483. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 1);
  484. }
  485. TEST_F(SnoopingProtectionControllerTestMetrics, FlakeyDetection) {
  486. base::HistogramTester tester;
  487. SimulateLogin();
  488. SetEnabledPref(true);
  489. hps::HpsResultProto state;
  490. // The first HpsNotifyChanged will not log anything.
  491. state.set_value(hps::HpsResult::POSITIVE);
  492. controller_->OnHpsNotifyChanged(state);
  493. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 0);
  494. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 0);
  495. tester.ExpectTotalCount(metrics::kFlakeyHistogramName, 0);
  496. EXPECT_TRUE(controller_->SnooperPresent());
  497. task_environment()->FastForwardBy(kShortTime);
  498. // Send NEGATIVE after a short period of time will log a flakey detection.
  499. state.set_value(hps::HpsResult::NEGATIVE);
  500. controller_->OnHpsNotifyChanged(state);
  501. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 0);
  502. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 0);
  503. tester.ExpectTotalCount(metrics::kFlakeyHistogramName, 1);
  504. EXPECT_TRUE(controller_->SnooperPresent());
  505. task_environment()->FastForwardBy(kShortTime);
  506. // Send NEGATIVE again after a short period of time will log another flakey
  507. // detection.
  508. state.set_value(hps::HpsResult::NEGATIVE);
  509. controller_->OnHpsNotifyChanged(state);
  510. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 0);
  511. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 0);
  512. tester.ExpectTotalCount(metrics::kFlakeyHistogramName, 2);
  513. EXPECT_TRUE(controller_->SnooperPresent());
  514. task_environment()->FastForwardBy(kLongTime);
  515. state.set_value(hps::HpsResult::NEGATIVE);
  516. controller_->OnHpsNotifyChanged(state);
  517. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 1);
  518. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 0);
  519. tester.ExpectTotalCount(metrics::kFlakeyHistogramName, 2);
  520. EXPECT_FALSE(controller_->SnooperPresent());
  521. // Send POSITIVE after a short period of time will NOT log a flakey detection
  522. // for now.
  523. task_environment()->FastForwardBy(kShortTime);
  524. state.set_value(hps::HpsResult::POSITIVE);
  525. controller_->OnHpsNotifyChanged(state);
  526. tester.ExpectTotalCount(metrics::kPositiveDurationHistogramName, 1);
  527. tester.ExpectTotalCount(metrics::kNegativeDurationHistogramName, 1);
  528. tester.ExpectTotalCount(metrics::kFlakeyHistogramName, 2);
  529. EXPECT_TRUE(controller_->SnooperPresent());
  530. }
  531. TEST_F(SnoopingProtectionControllerTestMetrics,
  532. FlakeyDetectionWithOtherSignals) {
  533. base::HistogramTester tester;
  534. SimulateLogin();
  535. SetEnabledPref(true);
  536. hps::HpsResultProto state;
  537. // The first HpsNotifyChanged will not log anything.
  538. state.set_value(hps::HpsResult::POSITIVE);
  539. controller_->OnHpsNotifyChanged(state);
  540. tester.ExpectTotalCount(metrics::kFlakeyHistogramName, 0);
  541. // Changing Orientation will disable HpsNotify and make the Present state to
  542. // be false.
  543. task_environment()->FastForwardBy(kShortTime);
  544. controller_->OnOrientationChanged(/*suitable_for_human_presence=*/false);
  545. controller_->OnOrientationChanged(/*suitable_for_human_presence=*/true);
  546. tester.ExpectTotalCount(metrics::kFlakeyHistogramName, 0);
  547. EXPECT_FALSE(controller_->SnooperPresent());
  548. // Send NEGATIVE after a short period of time will log a flakey detection
  549. // under this specific situation because the OrientationChange already put the
  550. // controller_->SnooperPresent state into false.
  551. state.set_value(hps::HpsResult::NEGATIVE);
  552. controller_->OnHpsNotifyChanged(state);
  553. tester.ExpectTotalCount(metrics::kFlakeyHistogramName, 0);
  554. }
  555. } // namespace
  556. } // namespace ash