global_state_feature_manager_impl_unittest.cc 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  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/services/multidevice_setup/global_state_feature_manager_impl.h"
  5. #include <memory>
  6. #include <utility>
  7. #include <vector>
  8. #include "ash/components/multidevice/remote_device_ref.h"
  9. #include "ash/components/multidevice/remote_device_test_util.h"
  10. #include "ash/components/multidevice/software_feature.h"
  11. #include "ash/components/multidevice/software_feature_state.h"
  12. #include "ash/constants/ash_features.h"
  13. #include "ash/services/device_sync/public/cpp/fake_device_sync_client.h"
  14. #include "ash/services/multidevice_setup/fake_host_status_provider.h"
  15. #include "ash/services/multidevice_setup/global_state_feature_manager.h"
  16. #include "ash/services/multidevice_setup/public/cpp/prefs.h"
  17. #include "ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
  18. #include "ash/services/multidevice_setup/wifi_sync_notification_controller.h"
  19. #include "base/test/scoped_feature_list.h"
  20. #include "base/test/task_environment.h"
  21. #include "base/timer/mock_timer.h"
  22. #include "components/sync_preferences/testing_pref_service_syncable.h"
  23. #include "testing/gtest/include/gtest/gtest.h"
  24. #include "third_party/abseil-cpp/absl/types/optional.h"
  25. namespace ash {
  26. namespace multidevice_setup {
  27. namespace {
  28. const GlobalStateFeatureManagerImpl::Factory::Option kTestOption =
  29. GlobalStateFeatureManagerImpl::Factory::Option::kWifiSync;
  30. const multidevice::SoftwareFeature kTestHostFeature =
  31. multidevice::SoftwareFeature::kWifiSyncHost;
  32. const multidevice::SoftwareFeature kTestClientFeature =
  33. multidevice::SoftwareFeature::kWifiSyncClient;
  34. const std::string& kFeatureAllowedPrefName = kWifiSyncAllowedPrefName;
  35. const char kPendingStatePrefName[] =
  36. "multidevice_setup.pending_set_wifi_sync_enabled_request";
  37. const base::Feature& kTestFeatureFlag = chromeos::features::kWifiSyncAndroid;
  38. enum PendingState {
  39. kPendingNone = 0,
  40. kPendingEnable = 1,
  41. kPendingDisable = 2,
  42. kSetPendingEnableOnVerify = 3
  43. };
  44. const size_t kNumTestDevices = 4;
  45. } // namespace
  46. class MultiDeviceSetupGlobalStateFeatureManagerImplTest
  47. : public ::testing::TestWithParam<bool> {
  48. public:
  49. MultiDeviceSetupGlobalStateFeatureManagerImplTest(
  50. const MultiDeviceSetupGlobalStateFeatureManagerImplTest&) = delete;
  51. MultiDeviceSetupGlobalStateFeatureManagerImplTest& operator=(
  52. const MultiDeviceSetupGlobalStateFeatureManagerImplTest&) = delete;
  53. protected:
  54. MultiDeviceSetupGlobalStateFeatureManagerImplTest()
  55. : test_devices_(
  56. multidevice::CreateRemoteDeviceRefListForTest(kNumTestDevices)) {}
  57. ~MultiDeviceSetupGlobalStateFeatureManagerImplTest() override = default;
  58. // testing::Test:
  59. void SetUp() override {
  60. // Tests are run once to simulate when v1 DeviceSync is enabled and once to
  61. // simulate when it is disabled, leaving only v2 DeviceSync operational. In
  62. // the former case, only public keys are needed, and in the latter case,
  63. // only Instance IDs are needed.
  64. for (multidevice::RemoteDeviceRef device : test_devices_) {
  65. if (features::ShouldUseV1DeviceSync())
  66. GetMutableRemoteDevice(device)->instance_id.clear();
  67. else
  68. GetMutableRemoteDevice(device)->public_key.clear();
  69. }
  70. SetFeatureSupportedInDeviceSyncClient();
  71. fake_host_status_provider_ = std::make_unique<FakeHostStatusProvider>();
  72. test_pref_service_ =
  73. std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
  74. GlobalStateFeatureManagerImpl::RegisterPrefs(
  75. test_pref_service_->registry());
  76. WifiSyncNotificationController::RegisterPrefs(
  77. test_pref_service_->registry());
  78. test_pref_service_->registry()->RegisterBooleanPref(kFeatureAllowedPrefName,
  79. true);
  80. fake_device_sync_client_ =
  81. std::make_unique<device_sync::FakeDeviceSyncClient>();
  82. fake_device_sync_client_->set_synced_devices(test_devices_);
  83. multidevice::RemoteDeviceRef local_device =
  84. multidevice::CreateRemoteDeviceRefForTest();
  85. GetMutableRemoteDevice(local_device)
  86. ->software_features[kTestClientFeature] =
  87. multidevice::SoftwareFeatureState::kSupported;
  88. fake_device_sync_client_->set_local_device_metadata(local_device);
  89. }
  90. void TearDown() override {}
  91. void SetHostInDeviceSyncClient(
  92. const absl::optional<multidevice::RemoteDeviceRef>& host_device) {
  93. for (const auto& remote_device : test_devices_) {
  94. bool should_be_host =
  95. host_device != absl::nullopt &&
  96. ((!remote_device.instance_id().empty() &&
  97. host_device->instance_id() == remote_device.instance_id()) ||
  98. (!remote_device.GetDeviceId().empty() &&
  99. host_device->GetDeviceId() == remote_device.GetDeviceId()));
  100. GetMutableRemoteDevice(remote_device)
  101. ->software_features
  102. [multidevice::SoftwareFeature::kBetterTogetherHost] =
  103. should_be_host ? multidevice::SoftwareFeatureState::kEnabled
  104. : multidevice::SoftwareFeatureState::kSupported;
  105. }
  106. fake_device_sync_client_->NotifyNewDevicesSynced();
  107. }
  108. void SetFeatureSupportedInDeviceSyncClient() {
  109. for (const auto& remote_device : test_devices_) {
  110. GetMutableRemoteDevice(remote_device)
  111. ->software_features[kTestHostFeature] =
  112. multidevice::SoftwareFeatureState::kSupported;
  113. }
  114. }
  115. void CreateDelegate(
  116. const absl::optional<multidevice::RemoteDeviceRef>& initial_host,
  117. int initial_pending_state = kPendingNone) {
  118. SetHostInDeviceSyncClient(initial_host);
  119. test_pref_service_->SetInteger(kPendingStatePrefName,
  120. initial_pending_state);
  121. auto mock_timer = std::make_unique<base::MockOneShotTimer>();
  122. mock_timer_ = mock_timer.get();
  123. SetHostWithStatus(initial_host);
  124. delegate_ = GlobalStateFeatureManagerImpl::Factory::Create(
  125. kTestOption, fake_host_status_provider_.get(), test_pref_service_.get(),
  126. fake_device_sync_client_.get(), std::move(mock_timer));
  127. }
  128. void SetHostWithStatus(
  129. const absl::optional<multidevice::RemoteDeviceRef>& host_device) {
  130. mojom::HostStatus host_status =
  131. (host_device == absl::nullopt ? mojom::HostStatus::kNoEligibleHosts
  132. : mojom::HostStatus::kHostVerified);
  133. fake_host_status_provider_->SetHostWithStatus(host_status, host_device);
  134. }
  135. void SetIsFeatureEnabled(bool enabled) {
  136. delegate_->SetIsFeatureEnabled(enabled);
  137. HostStatusProvider::HostStatusWithDevice host_with_status =
  138. fake_host_status_provider_->GetHostWithStatus();
  139. if (host_with_status.host_status() != mojom::HostStatus::kHostVerified) {
  140. return;
  141. }
  142. multidevice::RemoteDeviceRef host_device = *host_with_status.host_device();
  143. bool enabled_on_backend =
  144. (host_device.GetSoftwareFeatureState(kTestHostFeature) ==
  145. multidevice::SoftwareFeatureState::kEnabled);
  146. bool pending_request_state_same_as_backend =
  147. (enabled == enabled_on_backend);
  148. if (pending_request_state_same_as_backend) {
  149. return;
  150. }
  151. VerifyLatestSetHostNetworkRequest(host_device, enabled);
  152. }
  153. void VerifyLatestSetHostNetworkRequest(
  154. const multidevice::RemoteDeviceRef expected_host,
  155. bool expected_should_enable) {
  156. if (features::ShouldUseV1DeviceSync()) {
  157. ASSERT_FALSE(
  158. fake_device_sync_client_->set_software_feature_state_inputs_queue()
  159. .empty());
  160. const device_sync::FakeDeviceSyncClient::SetSoftwareFeatureStateInputs&
  161. inputs = fake_device_sync_client_
  162. ->set_software_feature_state_inputs_queue()
  163. .back();
  164. EXPECT_EQ(expected_host.public_key(), inputs.public_key);
  165. EXPECT_EQ(kTestHostFeature, inputs.software_feature);
  166. EXPECT_EQ(expected_should_enable, inputs.enabled);
  167. EXPECT_EQ(expected_should_enable, inputs.is_exclusive);
  168. return;
  169. }
  170. // Verify inputs to SetFeatureStatus().
  171. ASSERT_FALSE(
  172. fake_device_sync_client_->set_feature_status_inputs_queue().empty());
  173. const device_sync::FakeDeviceSyncClient::SetFeatureStatusInputs& inputs =
  174. fake_device_sync_client_->set_feature_status_inputs_queue().back();
  175. EXPECT_EQ(expected_host.instance_id(), inputs.device_instance_id);
  176. EXPECT_EQ(kTestHostFeature, inputs.feature);
  177. EXPECT_EQ(expected_should_enable
  178. ? device_sync::FeatureStatusChange::kEnableExclusively
  179. : device_sync::FeatureStatusChange::kDisable,
  180. inputs.status_change);
  181. }
  182. int GetSetHostNetworkRequestCallbackQueueSize() {
  183. return features::ShouldUseV1DeviceSync()
  184. ? fake_device_sync_client_
  185. ->GetSetSoftwareFeatureStateInputsQueueSize()
  186. : fake_device_sync_client_->GetSetFeatureStatusInputsQueueSize();
  187. }
  188. void InvokePendingSetHostNetworkRequestCallback(
  189. device_sync::mojom::NetworkRequestResult result_code,
  190. bool expected_to_notify_observer_and_start_retry_timer) {
  191. if (features::ShouldUseV1DeviceSync()) {
  192. fake_device_sync_client_->InvokePendingSetSoftwareFeatureStateCallback(
  193. result_code);
  194. } else {
  195. fake_device_sync_client_->InvokePendingSetFeatureStatusCallback(
  196. result_code);
  197. }
  198. EXPECT_EQ(expected_to_notify_observer_and_start_retry_timer,
  199. mock_timer_->IsRunning());
  200. }
  201. void SetHostInDeviceSyncClient(
  202. const absl::optional<multidevice::RemoteDeviceRef>& host_device,
  203. bool enabled) {
  204. GetMutableRemoteDevice(*host_device)->software_features[kTestHostFeature] =
  205. (enabled ? multidevice::SoftwareFeatureState::kEnabled
  206. : multidevice::SoftwareFeatureState::kSupported);
  207. fake_device_sync_client_->NotifyNewDevicesSynced();
  208. }
  209. void SetFeatureFlags(bool use_v1_devicesync, bool enable_feature_flag) {
  210. std::vector<base::Feature> enabled_features;
  211. std::vector<base::Feature> disabled_features;
  212. // These flags have no direct effect of on the GlobalStateFeatureManager;
  213. // however, v2 Enrollment and DeviceSync must be enabled before v1
  214. // DeviceSync can be disabled.
  215. enabled_features.push_back(chromeos::features::kCryptAuthV2Enrollment);
  216. enabled_features.push_back(chromeos::features::kCryptAuthV2DeviceSync);
  217. if (use_v1_devicesync) {
  218. disabled_features.push_back(
  219. chromeos::features::kDisableCryptAuthV1DeviceSync);
  220. } else {
  221. enabled_features.push_back(
  222. chromeos::features::kDisableCryptAuthV1DeviceSync);
  223. }
  224. if (enable_feature_flag) {
  225. enabled_features.push_back(kTestFeatureFlag);
  226. } else {
  227. disabled_features.push_back(kTestFeatureFlag);
  228. }
  229. scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
  230. }
  231. FakeHostStatusProvider* fake_host_status_provider() {
  232. return fake_host_status_provider_.get();
  233. }
  234. device_sync::FakeDeviceSyncClient* fake_device_sync_client() {
  235. return fake_device_sync_client_.get();
  236. }
  237. base::MockOneShotTimer* mock_timer() { return mock_timer_; }
  238. GlobalStateFeatureManager* delegate() { return delegate_.get(); }
  239. sync_preferences::TestingPrefServiceSyncable* test_pref_service() {
  240. return test_pref_service_.get();
  241. }
  242. const multidevice::RemoteDeviceRefList& test_devices() const {
  243. return test_devices_;
  244. }
  245. private:
  246. base::test::TaskEnvironment task_environment_;
  247. multidevice::RemoteDeviceRefList test_devices_;
  248. std::unique_ptr<FakeHostStatusProvider> fake_host_status_provider_;
  249. std::unique_ptr<sync_preferences::TestingPrefServiceSyncable>
  250. test_pref_service_;
  251. std::unique_ptr<device_sync::FakeDeviceSyncClient> fake_device_sync_client_;
  252. base::MockOneShotTimer* mock_timer_;
  253. std::unique_ptr<GlobalStateFeatureManager> delegate_;
  254. base::test::ScopedFeatureList scoped_feature_list_;
  255. };
  256. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest, Success) {
  257. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  258. true /* enable_feature_flag */);
  259. CreateDelegate(test_devices()[0] /* initial_host */);
  260. // Attempt to enable the feature on host device and succeed
  261. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  262. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  263. multidevice::SoftwareFeatureState::kSupported);
  264. SetIsFeatureEnabled(true);
  265. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  266. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  267. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  268. multidevice::SoftwareFeatureState::kSupported);
  269. InvokePendingSetHostNetworkRequestCallback(
  270. device_sync::mojom::NetworkRequestResult::kSuccess,
  271. false /* expected_to_notify_observer_and_start_retry_timer */);
  272. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  273. SetHostInDeviceSyncClient(test_devices()[0], true /* enabled */);
  274. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  275. multidevice::SoftwareFeatureState::kEnabled);
  276. // Attempt to disable the feature on host device and succeed
  277. SetIsFeatureEnabled(false);
  278. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  279. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  280. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  281. multidevice::SoftwareFeatureState::kEnabled);
  282. InvokePendingSetHostNetworkRequestCallback(
  283. device_sync::mojom::NetworkRequestResult::kSuccess,
  284. false /* expected_to_notify_observer_and_start_retry_timer */);
  285. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  286. SetHostInDeviceSyncClient(test_devices()[0], false /* enabled */);
  287. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  288. multidevice::SoftwareFeatureState::kSupported);
  289. }
  290. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  291. NewDevicesSyncedBeforeCallback) {
  292. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  293. true /* enable_feature_flag */);
  294. CreateDelegate(test_devices()[0] /* initial_host */);
  295. // Attempt to enable the feature on host device and succeed
  296. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  297. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  298. multidevice::SoftwareFeatureState::kSupported);
  299. SetIsFeatureEnabled(true);
  300. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  301. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  302. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  303. multidevice::SoftwareFeatureState::kSupported);
  304. // Triggers OnNewDevicesSynced
  305. SetHostInDeviceSyncClient(test_devices()[0], true /* enabled */);
  306. // Triggers Success Callback
  307. InvokePendingSetHostNetworkRequestCallback(
  308. device_sync::mojom::NetworkRequestResult::kSuccess,
  309. false /* expected_to_notify_observer_and_start_retry_timer */);
  310. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  311. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  312. multidevice::SoftwareFeatureState::kEnabled);
  313. }
  314. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest, Failure) {
  315. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  316. true /* enable_feature_flag */);
  317. CreateDelegate(test_devices()[0] /* initial_host */);
  318. // Attempt to enable the feature on host device and fail
  319. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  320. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  321. multidevice::SoftwareFeatureState::kSupported);
  322. SetIsFeatureEnabled(true);
  323. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  324. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  325. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  326. multidevice::SoftwareFeatureState::kSupported);
  327. InvokePendingSetHostNetworkRequestCallback(
  328. device_sync::mojom::NetworkRequestResult::kOffline,
  329. true /* expected_to_notify_observer_and_start_retry_timer */);
  330. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  331. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  332. multidevice::SoftwareFeatureState::kSupported);
  333. // A retry should have been scheduled, so fire the timer to start the retry.
  334. mock_timer()->Fire();
  335. // Simulate another failure.
  336. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  337. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  338. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  339. multidevice::SoftwareFeatureState::kSupported);
  340. InvokePendingSetHostNetworkRequestCallback(
  341. device_sync::mojom::NetworkRequestResult::kOffline,
  342. true /* expected_to_notify_observer_and_start_retry_timer */);
  343. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  344. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  345. multidevice::SoftwareFeatureState::kSupported);
  346. }
  347. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  348. MultipleRequests_FirstFail_ThenSucceed) {
  349. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  350. true /* enable_feature_flag */);
  351. CreateDelegate(test_devices()[0] /* initial_host */);
  352. // Attempt to enable the feature on host device and fail
  353. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  354. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  355. multidevice::SoftwareFeatureState::kSupported);
  356. SetIsFeatureEnabled(true);
  357. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  358. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  359. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  360. multidevice::SoftwareFeatureState::kSupported);
  361. InvokePendingSetHostNetworkRequestCallback(
  362. device_sync::mojom::NetworkRequestResult::kOffline,
  363. true /* expected_to_notify_observer_and_start_retry_timer */);
  364. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  365. multidevice::SoftwareFeatureState::kSupported);
  366. // The retry timer is running; however, instead of relying on that, call
  367. // SetIsFeatureEnabled() again to trigger an immediate
  368. // retry without the timer.
  369. SetIsFeatureEnabled(true);
  370. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  371. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  372. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  373. multidevice::SoftwareFeatureState::kSupported);
  374. InvokePendingSetHostNetworkRequestCallback(
  375. device_sync::mojom::NetworkRequestResult::kSuccess,
  376. false /* expected_to_notify_observer_and_start_retry_timer */);
  377. SetHostInDeviceSyncClient(test_devices()[0], true /* enabled */);
  378. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  379. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  380. multidevice::SoftwareFeatureState::kEnabled);
  381. }
  382. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  383. PendingRequest_NoSyncedHostDevice) {
  384. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  385. true /* enable_feature_flag */);
  386. CreateDelegate(test_devices()[0] /* initial_host */);
  387. // Attempt to enable the feature on test_device 0
  388. SetIsFeatureEnabled(true);
  389. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  390. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  391. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  392. multidevice::SoftwareFeatureState::kSupported);
  393. // Fail to set host enabled on test_device 0
  394. InvokePendingSetHostNetworkRequestCallback(
  395. device_sync::mojom::NetworkRequestResult::kOffline,
  396. true /* expected_to_notify_observer_and_start_retry_timer */);
  397. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  398. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  399. multidevice::SoftwareFeatureState::kSupported);
  400. EXPECT_TRUE(mock_timer()->IsRunning());
  401. // Remove synced device. This should remove the pending request and stop the
  402. // retry timer.
  403. SetHostInDeviceSyncClient(absl::nullopt);
  404. SetHostWithStatus(absl::nullopt);
  405. EXPECT_FALSE(mock_timer()->IsRunning());
  406. }
  407. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  408. InitialPendingEnableRequest_NoInitialDevice) {
  409. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  410. true /* enable_feature_flag */);
  411. CreateDelegate(absl::nullopt /* initial_host */,
  412. kPendingEnable /* initial_pending_state*/);
  413. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  414. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  415. multidevice::SoftwareFeatureState::kSupported);
  416. }
  417. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  418. InitialPendingEnableRequest_Success) {
  419. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  420. true /* enable_feature_flag */);
  421. CreateDelegate(test_devices()[0] /* initial_host */,
  422. kPendingEnable /* initial_pending_state*/);
  423. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  424. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  425. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  426. multidevice::SoftwareFeatureState::kSupported);
  427. InvokePendingSetHostNetworkRequestCallback(
  428. device_sync::mojom::NetworkRequestResult::kSuccess,
  429. false /* expected_to_notify_observer_and_start_retry_timer */);
  430. SetHostInDeviceSyncClient(test_devices()[0], true /* enabled */);
  431. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  432. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  433. multidevice::SoftwareFeatureState::kEnabled);
  434. }
  435. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  436. MultiplePendingRequests_EnableDisable) {
  437. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  438. true /* enable_feature_flag */);
  439. CreateDelegate(test_devices()[0] /* initial_host */);
  440. // Attempt to enable->disable the feature without invoking any
  441. // callbacks.
  442. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  443. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  444. multidevice::SoftwareFeatureState::kSupported);
  445. SetIsFeatureEnabled(true);
  446. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  447. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  448. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  449. multidevice::SoftwareFeatureState::kSupported);
  450. // The feature is already disabled on back-end so there should be no new
  451. // pending request
  452. SetIsFeatureEnabled(false);
  453. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  454. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  455. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  456. multidevice::SoftwareFeatureState::kSupported);
  457. }
  458. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  459. PendingRequest_SyncedHostBecomesUnverified) {
  460. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  461. true /* enable_feature_flag */);
  462. CreateDelegate(test_devices()[0] /* initial_host */,
  463. kPendingEnable /* initial_pending_state */);
  464. fake_host_status_provider()->SetHostWithStatus(
  465. mojom::HostStatus::kHostSetButNotYetVerified, test_devices()[0]);
  466. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  467. kPendingNone);
  468. }
  469. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  470. Retrying_SyncedHostBecomesUnverified) {
  471. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  472. true /* enable_feature_flag */);
  473. CreateDelegate(test_devices()[0] /* initial_host */);
  474. SetIsFeatureEnabled(true);
  475. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  476. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  477. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  478. multidevice::SoftwareFeatureState::kSupported);
  479. InvokePendingSetHostNetworkRequestCallback(
  480. device_sync::mojom::NetworkRequestResult::kOffline,
  481. true /* expected_to_notify_observer_and_start_retry_timer */);
  482. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  483. EXPECT_TRUE(mock_timer()->IsRunning());
  484. // Host becomes unverified, this should stop timer and clear pending request
  485. fake_host_status_provider()->SetHostWithStatus(
  486. mojom::HostStatus::kHostSetButNotYetVerified, test_devices()[0]);
  487. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  488. kPendingNone);
  489. EXPECT_FALSE(mock_timer()->IsRunning());
  490. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  491. }
  492. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  493. FailureCallback_SyncedHostBecomesUnverified) {
  494. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  495. true /* enable_feature_flag */);
  496. CreateDelegate(test_devices()[0] /* initial_host */);
  497. SetIsFeatureEnabled(true);
  498. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  499. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  500. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  501. multidevice::SoftwareFeatureState::kSupported);
  502. // Set host unverified. This should reset pending request.
  503. fake_host_status_provider()->SetHostWithStatus(
  504. mojom::HostStatus::kHostSetButNotYetVerified, test_devices()[0]);
  505. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  506. kPendingNone);
  507. // Invoke failure callback. No retry should be scheduled.
  508. InvokePendingSetHostNetworkRequestCallback(
  509. device_sync::mojom::NetworkRequestResult::kOffline,
  510. false /* expected_to_notify_observer_and_start_retry_timer */);
  511. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  512. EXPECT_FALSE(mock_timer()->IsRunning());
  513. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  514. }
  515. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  516. NoVerifiedHost_AttemptToEnable) {
  517. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  518. true /* enable_feature_flag */);
  519. CreateDelegate(test_devices()[0] /* initial_host */);
  520. fake_host_status_provider()->SetHostWithStatus(
  521. mojom::HostStatus::kHostSetButNotYetVerified, test_devices()[0]);
  522. // Attempt to enable the feature on host device
  523. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  524. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  525. multidevice::SoftwareFeatureState::kSupported);
  526. SetIsFeatureEnabled(true);
  527. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  528. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  529. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  530. multidevice::SoftwareFeatureState::kSupported);
  531. }
  532. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  533. StatusChangedOnRemoteDevice) {
  534. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  535. true /* enable_feature_flag */);
  536. CreateDelegate(test_devices()[0] /* initial_host */);
  537. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  538. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  539. multidevice::SoftwareFeatureState::kSupported);
  540. // Simulate enabled on a remote device.
  541. SetHostInDeviceSyncClient(test_devices()[0], true /* enabled */);
  542. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  543. }
  544. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  545. SimultaneousRequests_StartOff_ToggleOnOff) {
  546. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  547. true /* enable_feature_flag */);
  548. CreateDelegate(test_devices()[0] /* initial_host */);
  549. // Attempt to enable
  550. SetIsFeatureEnabled(true);
  551. // Attempt to disable
  552. SetIsFeatureEnabled(false);
  553. // Only one network request should be in flight at a time
  554. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  555. // Successfully enable on host
  556. InvokePendingSetHostNetworkRequestCallback(
  557. device_sync::mojom::NetworkRequestResult::kSuccess,
  558. false /* expected_to_notify_observer_and_start_retry_timer */);
  559. SetHostInDeviceSyncClient(test_devices()[0], true /* enabled */);
  560. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  561. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  562. multidevice::SoftwareFeatureState::kEnabled);
  563. // A new network request should be scheduled to disable
  564. EXPECT_EQ(1, GetSetHostNetworkRequestCallbackQueueSize());
  565. InvokePendingSetHostNetworkRequestCallback(
  566. device_sync::mojom::NetworkRequestResult::kSuccess,
  567. false /* expected_to_notify_observer_and_start_retry_timer */);
  568. SetHostInDeviceSyncClient(test_devices()[0], false /* enabled */);
  569. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  570. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  571. multidevice::SoftwareFeatureState::kSupported);
  572. }
  573. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  574. SetPendingEnableOnVerify_HostSetLocallyThenHostVerified) {
  575. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  576. true /* enable_feature_flag */);
  577. CreateDelegate(absl::nullopt /* initial_host */);
  578. // kHostSetLocallyButWaitingForBackendConfirmation is only possible if the
  579. // setup flow has been completed on the local device.
  580. SetHostInDeviceSyncClient(test_devices()[0]);
  581. fake_host_status_provider()->SetHostWithStatus(
  582. mojom::HostStatus::kHostSetLocallyButWaitingForBackendConfirmation,
  583. test_devices()[0]);
  584. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  585. kSetPendingEnableOnVerify);
  586. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  587. fake_host_status_provider()->SetHostWithStatus(
  588. mojom::HostStatus::kHostVerified, test_devices()[0]);
  589. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  590. kPendingEnable);
  591. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  592. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  593. multidevice::SoftwareFeatureState::kSupported);
  594. InvokePendingSetHostNetworkRequestCallback(
  595. device_sync::mojom::NetworkRequestResult::kSuccess,
  596. false /* expected_to_notify_observer_and_start_retry_timer */);
  597. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  598. SetHostInDeviceSyncClient(test_devices()[0], true /* enabled */);
  599. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  600. multidevice::SoftwareFeatureState::kEnabled);
  601. }
  602. TEST_P(
  603. MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  604. SetPendingEnableOnVerify_HostSetLocallyThenHostSetNotVerifiedThenHostVerified) {
  605. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  606. true /* enable_feature_flag */);
  607. CreateDelegate(absl::nullopt /* initial_host */);
  608. // kHostSetLocallyButWaitingForBackendConfirmation is only possible if the
  609. // setup flow has been completed on the local device.
  610. SetHostInDeviceSyncClient(test_devices()[0]);
  611. fake_host_status_provider()->SetHostWithStatus(
  612. mojom::HostStatus::kHostSetLocallyButWaitingForBackendConfirmation,
  613. test_devices()[0]);
  614. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  615. kSetPendingEnableOnVerify);
  616. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  617. fake_host_status_provider()->SetHostWithStatus(
  618. mojom::HostStatus::kHostSetButNotYetVerified, test_devices()[0]);
  619. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  620. kSetPendingEnableOnVerify);
  621. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  622. fake_host_status_provider()->SetHostWithStatus(
  623. mojom::HostStatus::kHostVerified, test_devices()[0]);
  624. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  625. kPendingEnable);
  626. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  627. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  628. multidevice::SoftwareFeatureState::kSupported);
  629. InvokePendingSetHostNetworkRequestCallback(
  630. device_sync::mojom::NetworkRequestResult::kSuccess,
  631. false /* expected_to_notify_observer_and_start_retry_timer */);
  632. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  633. SetHostInDeviceSyncClient(test_devices()[0], true /* enabled */);
  634. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  635. multidevice::SoftwareFeatureState::kEnabled);
  636. }
  637. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  638. SetPendingEnableOnVerify_FeatureFlagOff) {
  639. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  640. false /* enable_feature_flag */);
  641. CreateDelegate(absl::nullopt /* initial_host */);
  642. // kHostSetLocallyButWaitingForBackendConfirmation is only possible if the
  643. // setup flow has been completed on the local device.
  644. SetHostInDeviceSyncClient(test_devices()[0]);
  645. fake_host_status_provider()->SetHostWithStatus(
  646. mojom::HostStatus::kHostSetLocallyButWaitingForBackendConfirmation,
  647. test_devices()[0]);
  648. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  649. kPendingNone);
  650. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  651. }
  652. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  653. SetPendingEnableOnVerify_FeatureNotAllowedByPolicy) {
  654. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  655. true /* enable_feature_flag */);
  656. // Disable by policy
  657. test_pref_service()->SetBoolean(kFeatureAllowedPrefName, false);
  658. CreateDelegate(absl::nullopt /* initial_host */);
  659. // kHostSetLocallyButWaitingForBackendConfirmation is only possible if the
  660. // setup flow has been completed on the local device.
  661. SetHostInDeviceSyncClient(test_devices()[0]);
  662. fake_host_status_provider()->SetHostWithStatus(
  663. mojom::HostStatus::kHostSetLocallyButWaitingForBackendConfirmation,
  664. test_devices()[0]);
  665. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  666. kPendingNone);
  667. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  668. }
  669. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  670. SetPendingEnableOnVerify_FeatureNotSupportedOnHostDevice) {
  671. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  672. true /* enable_feature_flag */);
  673. CreateDelegate(absl::nullopt /* initial_host */);
  674. GetMutableRemoteDevice(test_devices()[0])
  675. ->software_features[kTestHostFeature] =
  676. multidevice::SoftwareFeatureState::kNotSupported;
  677. // kHostSetLocallyButWaitingForBackendConfirmation is only possible if the
  678. // setup flow has been completed on the local device.
  679. SetHostInDeviceSyncClient(test_devices()[0]);
  680. fake_host_status_provider()->SetHostWithStatus(
  681. mojom::HostStatus::kHostSetLocallyButWaitingForBackendConfirmation,
  682. test_devices()[0]);
  683. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  684. kPendingNone);
  685. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  686. }
  687. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  688. SetPendingEnableOnVerify_HostRemoved) {
  689. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  690. true /* enable_feature_flag */);
  691. CreateDelegate(absl::nullopt /* initial_host */);
  692. // kHostSetLocallyButWaitingForBackendConfirmation is only possible if the
  693. // setup flow has been completed on the local device.
  694. SetHostInDeviceSyncClient(test_devices()[0]);
  695. fake_host_status_provider()->SetHostWithStatus(
  696. mojom::HostStatus::kHostSetLocallyButWaitingForBackendConfirmation,
  697. test_devices()[0]);
  698. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  699. kSetPendingEnableOnVerify);
  700. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  701. // Host is added but not verified.
  702. fake_host_status_provider()->SetHostWithStatus(
  703. mojom::HostStatus::kHostSetButNotYetVerified, test_devices()[0]);
  704. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  705. kSetPendingEnableOnVerify);
  706. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  707. // Host is removed before it was verified. This simulates the user going
  708. // through the forget phone flow before the phone was able to be verified.
  709. // The feature manager should stop the enable attempt because it requires a
  710. // paired host device that transitions from unverified to verified.
  711. fake_host_status_provider()->SetHostWithStatus(
  712. mojom::HostStatus::kEligibleHostExistsButNoHostSet, absl::nullopt);
  713. EXPECT_EQ(test_pref_service()->GetInteger(kPendingStatePrefName),
  714. kPendingNone);
  715. EXPECT_FALSE(delegate()->IsFeatureEnabled());
  716. }
  717. TEST_P(MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  718. SetPendingEnableOnVerify_InitialPendingRequest) {
  719. SetFeatureFlags(GetParam() /* use_v1_devicesync */,
  720. true /* enable_feature_flag */);
  721. fake_host_status_provider()->SetHostWithStatus(
  722. mojom::HostStatus::kHostVerified, test_devices()[0]);
  723. CreateDelegate(test_devices()[0] /* initial_host */,
  724. kSetPendingEnableOnVerify /* initial_pending_state */);
  725. EXPECT_TRUE(delegate()->IsFeatureEnabled());
  726. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  727. multidevice::SoftwareFeatureState::kSupported);
  728. InvokePendingSetHostNetworkRequestCallback(
  729. device_sync::mojom::NetworkRequestResult::kSuccess,
  730. false /* expected_to_notify_observer_and_start_retry_timer */);
  731. EXPECT_EQ(0, GetSetHostNetworkRequestCallbackQueueSize());
  732. SetHostInDeviceSyncClient(test_devices()[0], true /* enabled */);
  733. EXPECT_EQ(test_devices()[0].GetSoftwareFeatureState(kTestHostFeature),
  734. multidevice::SoftwareFeatureState::kEnabled);
  735. }
  736. // Runs tests twice; once with v1 DeviceSync enabled and once with it disabled.
  737. // TODO(https://crbug.com/1019206): Remove when v1 DeviceSync is disabled,
  738. // when all devices should have an Instance ID.
  739. INSTANTIATE_TEST_SUITE_P(All,
  740. MultiDeviceSetupGlobalStateFeatureManagerImplTest,
  741. ::testing::Bool());
  742. } // namespace multidevice_setup
  743. } // namespace ash