apps_access_manager_impl_unittest.cc 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951
  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/webui/eche_app_ui/apps_access_manager_impl.h"
  5. #include "ash/components/phonehub/multidevice_feature_access_manager.h"
  6. #include "ash/constants/ash_features.h"
  7. #include "ash/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h"
  8. #include "ash/services/multidevice_setup/public/cpp/prefs.h"
  9. #include "ash/services/secure_channel/public/cpp/client/fake_connection_manager.h"
  10. #include "ash/webui/eche_app_ui/apps_access_setup_operation.h"
  11. #include "ash/webui/eche_app_ui/fake_eche_connector.h"
  12. #include "ash/webui/eche_app_ui/fake_eche_message_receiver.h"
  13. #include "ash/webui/eche_app_ui/fake_feature_status_provider.h"
  14. #include "ash/webui/eche_app_ui/pref_names.h"
  15. #include "ash/webui/eche_app_ui/proto/exo_messages.pb.h"
  16. #include "base/test/metrics/histogram_tester.h"
  17. #include "base/test/scoped_feature_list.h"
  18. #include "components/prefs/pref_service.h"
  19. #include "components/prefs/testing_pref_service.h"
  20. #include "testing/gtest/include/gtest/gtest.h"
  21. namespace ash {
  22. namespace eche_app {
  23. using AccessStatus =
  24. ash::phonehub::MultideviceFeatureAccessManager::AccessStatus;
  25. using OnboardingUserActionMetric =
  26. AppsAccessManagerImpl::OnboardingUserActionMetric;
  27. namespace {
  28. class FakeObserver : public AppsAccessManager::Observer {
  29. public:
  30. FakeObserver() = default;
  31. ~FakeObserver() override = default;
  32. size_t num_calls() const { return num_calls_; }
  33. // AppsAccessManager::Observer:
  34. void OnAppsAccessChanged() override { ++num_calls_; }
  35. private:
  36. size_t num_calls_ = 0;
  37. };
  38. class FakeOperationDelegate : public AppsAccessSetupOperation::Delegate {
  39. public:
  40. FakeOperationDelegate() = default;
  41. ~FakeOperationDelegate() override = default;
  42. AppsAccessSetupOperation::Status status() const { return status_; }
  43. // AppsAccessSetupOperation::Delegate:
  44. void OnAppsStatusChange(
  45. AppsAccessSetupOperation::Status new_status) override {
  46. status_ = new_status;
  47. }
  48. private:
  49. AppsAccessSetupOperation::Status status_ =
  50. AppsAccessSetupOperation::Status::kConnecting;
  51. };
  52. } // namespace
  53. using multidevice_setup::mojom::Feature;
  54. using multidevice_setup::mojom::FeatureState;
  55. class AppsAccessManagerImplTest : public testing::Test {
  56. protected:
  57. AppsAccessManagerImplTest() = default;
  58. AppsAccessManagerImplTest(const AppsAccessManagerImplTest&) = delete;
  59. AppsAccessManagerImplTest& operator=(const AppsAccessManagerImplTest&) =
  60. delete;
  61. ~AppsAccessManagerImplTest() override = default;
  62. void SetUp() override {
  63. AppsAccessManagerImpl::RegisterPrefs(pref_service_.registry());
  64. multidevice_setup::RegisterFeaturePrefs(pref_service_.registry());
  65. scoped_feature_list_.InitWithFeatures(
  66. /*enabled_features=*/{chromeos::features::kEcheSWA},
  67. /*disabled_features=*/{});
  68. fake_eche_connector_ = std::make_unique<FakeEcheConnector>();
  69. fake_eche_message_receiver_ = std::make_unique<FakeEcheMessageReceiver>();
  70. fake_feature_status_provider_ = std::make_unique<FakeFeatureStatusProvider>(
  71. FeatureStatus::kDependentFeature);
  72. }
  73. void TearDown() override {
  74. apps_access_manager_->RemoveObserver(&fake_observer_);
  75. apps_access_manager_.reset();
  76. fake_eche_connector_.reset();
  77. fake_eche_message_receiver_.reset();
  78. fake_feature_status_provider_.reset();
  79. }
  80. void Initialize(AccessStatus expected_status) {
  81. pref_service_.SetInteger(prefs::kAppsAccessStatus,
  82. static_cast<int>(expected_status));
  83. apps_access_manager_ = std::make_unique<AppsAccessManagerImpl>(
  84. fake_eche_connector_.get(), fake_eche_message_receiver_.get(),
  85. fake_feature_status_provider_.get(), &pref_service_,
  86. &fake_multidevice_setup_client_, &fake_connection_manager_);
  87. apps_access_manager_->AddObserver(&fake_observer_);
  88. }
  89. void FakeGetAppsAccessStateResponse(eche_app::proto::Result result,
  90. eche_app::proto::AppsAccessState status) {
  91. fake_eche_message_receiver_->FakeGetAppsAccessStateResponse(result, status);
  92. }
  93. void FakeSendAppsSetupResponse(eche_app::proto::Result result,
  94. eche_app::proto::AppsAccessState status) {
  95. fake_eche_message_receiver_->FakeSendAppsSetupResponse(result, status);
  96. }
  97. void FakeSendAppsPolicyStateChange(
  98. eche_app::proto::AppStreamingPolicy app_policy_state) {
  99. fake_eche_message_receiver_->FakeAppPolicyStateChange(app_policy_state);
  100. }
  101. void SetFeatureStatus(FeatureStatus status) {
  102. fake_feature_status_provider_->SetStatus(status);
  103. }
  104. FeatureStatus GetFeatureStatus() {
  105. return fake_feature_status_provider_->GetStatus();
  106. }
  107. void SetConnectionStatus(secure_channel::ConnectionManager::Status status) {
  108. fake_connection_manager_.SetStatus(status);
  109. }
  110. void VerifyAppsAccessGrantedState(AccessStatus expected_status) {
  111. EXPECT_EQ(static_cast<int>(expected_status),
  112. pref_service_.GetInteger(prefs::kAppsAccessStatus));
  113. EXPECT_EQ(expected_status, apps_access_manager_->GetAccessStatus());
  114. }
  115. AppsAccessSetupOperation::Status GetAppsAccessSetupOperationStatus() {
  116. return fake_delegate_.status();
  117. }
  118. std::unique_ptr<AppsAccessSetupOperation> StartSetupOperation() {
  119. return apps_access_manager_->AttemptAppsAccessSetup(&fake_delegate_);
  120. }
  121. bool IsSetupOperationInProgress() {
  122. return apps_access_manager_->IsSetupOperationInProgress();
  123. }
  124. size_t GetNumObserverCalls() const { return fake_observer_.num_calls(); }
  125. size_t GetAppsSetupRequestCount() const {
  126. return fake_eche_connector_->send_apps_setup_request_count();
  127. }
  128. size_t GetAppsAccessStateRequestCount() const {
  129. return fake_eche_connector_->get_apps_access_state_request_count();
  130. }
  131. size_t GetAttemptNearbyConnectionCount() const {
  132. return fake_eche_connector_->attempt_nearby_connection_count();
  133. }
  134. void SetFeatureState(Feature feature, FeatureState feature_state) {
  135. fake_multidevice_setup_client_.SetFeatureState(feature, feature_state);
  136. }
  137. void NotifyAppsAccessCanceled() {
  138. return apps_access_manager_->NotifyAppsAccessCanceled();
  139. }
  140. void SetFeatureEnabledState(const std::string& pref_name, bool enabled) {
  141. pref_service_.SetBoolean(pref_name, enabled);
  142. }
  143. multidevice_setup::FakeMultiDeviceSetupClient*
  144. fake_multidevice_setup_client() {
  145. return &fake_multidevice_setup_client_;
  146. }
  147. private:
  148. base::test::ScopedFeatureList scoped_feature_list_;
  149. FakeObserver fake_observer_;
  150. FakeOperationDelegate fake_delegate_;
  151. TestingPrefServiceSimple pref_service_;
  152. std::unique_ptr<AppsAccessManager> apps_access_manager_;
  153. std::unique_ptr<FakeEcheConnector> fake_eche_connector_;
  154. std::unique_ptr<FakeEcheMessageReceiver> fake_eche_message_receiver_;
  155. std::unique_ptr<FakeFeatureStatusProvider> fake_feature_status_provider_;
  156. secure_channel::FakeConnectionManager fake_connection_manager_;
  157. multidevice_setup::FakeMultiDeviceSetupClient fake_multidevice_setup_client_;
  158. };
  159. TEST_F(AppsAccessManagerImplTest, InitiallyGranted) {
  160. Initialize(AccessStatus::kAccessGranted);
  161. VerifyAppsAccessGrantedState(AccessStatus::kAccessGranted);
  162. // Cannot start the apps access setup flow if access has already been
  163. // granted.
  164. auto operation = StartSetupOperation();
  165. EXPECT_FALSE(operation);
  166. }
  167. TEST_F(AppsAccessManagerImplTest, OnFeatureStatusChanged) {
  168. Initialize(AccessStatus::kAvailableButNotGranted);
  169. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  170. // Set initial state to kIneligible.
  171. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  172. SetFeatureStatus(FeatureStatus::kIneligible);
  173. EXPECT_EQ(0u, GetAttemptNearbyConnectionCount());
  174. EXPECT_EQ(0u, GetAppsAccessStateRequestCount());
  175. EXPECT_EQ(AppsAccessSetupOperation::Status::kConnecting,
  176. GetAppsAccessSetupOperationStatus());
  177. // Simulate feature status to be enabled and disconnected.
  178. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  179. SetFeatureStatus(FeatureStatus::kDisconnected);
  180. EXPECT_EQ(1u, GetAttemptNearbyConnectionCount());
  181. EXPECT_EQ(0u, GetAppsAccessStateRequestCount());
  182. EXPECT_EQ(AppsAccessSetupOperation::Status::kConnecting,
  183. GetAppsAccessSetupOperationStatus());
  184. // Simulate feature status to be enabled and connected. SetupOperation is also
  185. // not in progress, so expect no new requests to be sent.
  186. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  187. SetFeatureStatus(FeatureStatus::kConnected);
  188. EXPECT_EQ(1u, GetAppsAccessStateRequestCount());
  189. EXPECT_EQ(0u, GetAppsSetupRequestCount());
  190. EXPECT_EQ(AppsAccessSetupOperation::Status::kConnecting,
  191. GetAppsAccessSetupOperationStatus());
  192. // Simulate setup operation is in progress. This will trigger a sent request.
  193. auto operation = StartSetupOperation();
  194. EXPECT_TRUE(operation);
  195. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  196. EXPECT_EQ(AppsAccessSetupOperation::Status::
  197. kSentMessageToPhoneAndWaitingForResponse,
  198. GetAppsAccessSetupOperationStatus());
  199. EXPECT_TRUE(IsSetupOperationInProgress());
  200. // Set another feature status, expect status to be updated.
  201. SetFeatureStatus(FeatureStatus::kIneligible);
  202. SetFeatureStatus(FeatureStatus::kConnected);
  203. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnecting);
  204. SetFeatureStatus(FeatureStatus::kConnecting);
  205. EXPECT_EQ(2u, GetAppsSetupRequestCount());
  206. EXPECT_EQ(AppsAccessSetupOperation::Status::kConnectionDisconnected,
  207. GetAppsAccessSetupOperationStatus());
  208. EXPECT_FALSE(IsSetupOperationInProgress());
  209. auto operation1 = StartSetupOperation();
  210. EXPECT_TRUE(operation1);
  211. EXPECT_EQ(2u, GetAppsSetupRequestCount());
  212. EXPECT_EQ(AppsAccessSetupOperation::Status::kConnecting,
  213. GetAppsAccessSetupOperationStatus());
  214. EXPECT_TRUE(IsSetupOperationInProgress());
  215. SetFeatureStatus(FeatureStatus::kDisconnected);
  216. EXPECT_EQ(2u, GetAppsSetupRequestCount());
  217. EXPECT_EQ(AppsAccessSetupOperation::Status::kTimedOutConnecting,
  218. GetAppsAccessSetupOperationStatus());
  219. EXPECT_FALSE(IsSetupOperationInProgress());
  220. }
  221. TEST_F(AppsAccessManagerImplTest, StartDisconnectedAndNoAccess) {
  222. // Set initial state to disconnected.
  223. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  224. SetFeatureStatus(FeatureStatus::kDisconnected);
  225. Initialize(AccessStatus::kAvailableButNotGranted);
  226. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  227. // Start a setup operation with enabled but disconnected status and access
  228. // not granted.
  229. auto operation = StartSetupOperation();
  230. EXPECT_TRUE(operation);
  231. EXPECT_EQ(1u, GetAttemptNearbyConnectionCount());
  232. // Simulate changing states from connecting to connected.
  233. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnecting);
  234. SetFeatureStatus(FeatureStatus::kConnecting);
  235. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  236. SetFeatureStatus(FeatureStatus::kConnected);
  237. // Verify that the request message has been sent and our operation status
  238. // is updated.
  239. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  240. EXPECT_EQ(AppsAccessSetupOperation::Status::
  241. kSentMessageToPhoneAndWaitingForResponse,
  242. GetAppsAccessSetupOperationStatus());
  243. EXPECT_TRUE(IsSetupOperationInProgress());
  244. // Simulate getting a response back from the phone.
  245. FakeSendAppsSetupResponse(eche_app::proto::Result::RESULT_NO_ERROR,
  246. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  247. VerifyAppsAccessGrantedState(AccessStatus::kAccessGranted);
  248. EXPECT_EQ(AppsAccessSetupOperation::Status::kCompletedSuccessfully,
  249. GetAppsAccessSetupOperationStatus());
  250. EXPECT_FALSE(IsSetupOperationInProgress());
  251. }
  252. TEST_F(AppsAccessManagerImplTest, StartConnectingAndNoAccess) {
  253. base::HistogramTester histograms;
  254. // Set initial state to connecting.
  255. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnecting);
  256. SetFeatureStatus(FeatureStatus::kConnecting);
  257. Initialize(AccessStatus::kAvailableButNotGranted);
  258. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  259. // Start a setup operation with enabled and connecting status and access
  260. // not granted.
  261. auto operation = StartSetupOperation();
  262. EXPECT_TRUE(operation);
  263. // Simulate changing states from connecting to connected.
  264. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  265. SetFeatureStatus(FeatureStatus::kConnected);
  266. // Verify that the request message has been sent and our operation status
  267. // is updated.
  268. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  269. EXPECT_EQ(AppsAccessSetupOperation::Status::
  270. kSentMessageToPhoneAndWaitingForResponse,
  271. GetAppsAccessSetupOperationStatus());
  272. EXPECT_TRUE(IsSetupOperationInProgress());
  273. // Simulate getting a response back from the phone.
  274. FakeSendAppsSetupResponse(eche_app::proto::Result::RESULT_NO_ERROR,
  275. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  276. VerifyAppsAccessGrantedState(AccessStatus::kAccessGranted);
  277. EXPECT_EQ(AppsAccessSetupOperation::Status::kCompletedSuccessfully,
  278. GetAppsAccessSetupOperationStatus());
  279. EXPECT_FALSE(IsSetupOperationInProgress());
  280. histograms.ExpectBucketCount(
  281. kEcheOnboardingHistogramName,
  282. OnboardingUserActionMetric::kUserActionPermissionGranted, 1);
  283. }
  284. TEST_F(AppsAccessManagerImplTest, StartConnectedAndNoAccess) {
  285. // Set initial state to connected.
  286. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  287. SetFeatureStatus(FeatureStatus::kConnected);
  288. Initialize(AccessStatus::kAvailableButNotGranted);
  289. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  290. // Start a setup operation with enabled and connected status and access
  291. // not granted.
  292. auto operation = StartSetupOperation();
  293. EXPECT_TRUE(operation);
  294. // Verify that the request message has been sent and our operation status
  295. // is updated.
  296. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  297. EXPECT_EQ(AppsAccessSetupOperation::Status::
  298. kSentMessageToPhoneAndWaitingForResponse,
  299. GetAppsAccessSetupOperationStatus());
  300. // Simulate getting a response back from the phone.
  301. FakeSendAppsSetupResponse(eche_app::proto::Result::RESULT_NO_ERROR,
  302. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  303. VerifyAppsAccessGrantedState(AccessStatus::kAccessGranted);
  304. EXPECT_EQ(AppsAccessSetupOperation::Status::kCompletedSuccessfully,
  305. GetAppsAccessSetupOperationStatus());
  306. EXPECT_FALSE(IsSetupOperationInProgress());
  307. }
  308. TEST_F(AppsAccessManagerImplTest, SimulateUserRejectedError) {
  309. base::HistogramTester histograms;
  310. // Set initial state to connected.
  311. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  312. SetFeatureStatus(FeatureStatus::kConnected);
  313. Initialize(AccessStatus::kAvailableButNotGranted);
  314. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  315. // Start a setup operation with enabled and connected status and access
  316. // not granted.
  317. auto operation = StartSetupOperation();
  318. EXPECT_TRUE(operation);
  319. // Verify that the request message has been sent and our operation status
  320. // is updated.
  321. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  322. EXPECT_EQ(AppsAccessSetupOperation::Status::
  323. kSentMessageToPhoneAndWaitingForResponse,
  324. GetAppsAccessSetupOperationStatus());
  325. // Simulate getting a response back from the phone.
  326. FakeSendAppsSetupResponse(
  327. eche_app::proto::Result::RESULT_ERROR_USER_REJECTED,
  328. eche_app::proto::AppsAccessState::ACCESS_NOT_GRANTED);
  329. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  330. EXPECT_EQ(AppsAccessSetupOperation::Status::kCompletedUserRejected,
  331. GetAppsAccessSetupOperationStatus());
  332. EXPECT_FALSE(IsSetupOperationInProgress());
  333. histograms.ExpectBucketCount(
  334. kEcheOnboardingHistogramName,
  335. OnboardingUserActionMetric::kUserActionPermissionRejected, 1);
  336. }
  337. TEST_F(AppsAccessManagerImplTest, SimulateReceivesAppsSetupAck) {
  338. base::HistogramTester histograms;
  339. // Set initial state to connected.
  340. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  341. SetFeatureStatus(FeatureStatus::kConnected);
  342. Initialize(AccessStatus::kAvailableButNotGranted);
  343. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  344. // Start a setup operation with enabled and connected status and access
  345. // not granted.
  346. auto operation = StartSetupOperation();
  347. EXPECT_TRUE(operation);
  348. // Verify that the request message has been sent and our operation status
  349. // is updated.
  350. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  351. EXPECT_EQ(AppsAccessSetupOperation::Status::
  352. kSentMessageToPhoneAndWaitingForResponse,
  353. GetAppsAccessSetupOperationStatus());
  354. // Simulate getting a response back from the phone.
  355. FakeSendAppsSetupResponse(
  356. eche_app::proto::Result::RESULT_ACK_BY_EXO,
  357. eche_app::proto::AppsAccessState::ACCESS_NOT_GRANTED);
  358. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  359. EXPECT_TRUE(IsSetupOperationInProgress());
  360. histograms.ExpectBucketCount(kEcheOnboardingHistogramName,
  361. OnboardingUserActionMetric::kAckByExo, 1);
  362. }
  363. TEST_F(AppsAccessManagerImplTest, SimulateOperationFailedOrCanceled) {
  364. base::HistogramTester histograms;
  365. // Set initial state to connected.
  366. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  367. SetFeatureStatus(FeatureStatus::kConnected);
  368. Initialize(AccessStatus::kAvailableButNotGranted);
  369. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  370. // Start a setup operation with enabled and connected status and access
  371. // not granted.
  372. auto operation = StartSetupOperation();
  373. EXPECT_TRUE(operation);
  374. // Verify that the request message has been sent and our operation status
  375. // is updated.
  376. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  377. EXPECT_EQ(AppsAccessSetupOperation::Status::
  378. kSentMessageToPhoneAndWaitingForResponse,
  379. GetAppsAccessSetupOperationStatus());
  380. // Simulate getting a response back from the phone.
  381. FakeSendAppsSetupResponse(
  382. eche_app::proto::Result::RESULT_ERROR_ACTION_TIMEOUT,
  383. eche_app::proto::AppsAccessState::ACCESS_NOT_GRANTED);
  384. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  385. EXPECT_EQ(AppsAccessSetupOperation::Status::kOperationFailedOrCancelled,
  386. GetAppsAccessSetupOperationStatus());
  387. EXPECT_FALSE(IsSetupOperationInProgress());
  388. histograms.ExpectBucketCount(kEcheOnboardingHistogramName,
  389. OnboardingUserActionMetric::kUserActionTimeout,
  390. 1);
  391. // Simulate flipping the access state to not granted.
  392. FakeGetAppsAccessStateResponse(
  393. eche_app::proto::Result::RESULT_NO_ERROR,
  394. eche_app::proto::AppsAccessState::ACCESS_NOT_GRANTED);
  395. // Start a setup operation with enabled and connected status and access
  396. // not granted.
  397. auto operation1 = StartSetupOperation();
  398. EXPECT_TRUE(operation1);
  399. // Verify that the request message has been sent and our operation status
  400. // is updated.
  401. EXPECT_EQ(2u, GetAppsSetupRequestCount());
  402. EXPECT_EQ(AppsAccessSetupOperation::Status::
  403. kSentMessageToPhoneAndWaitingForResponse,
  404. GetAppsAccessSetupOperationStatus());
  405. // Simulate getting a response back from the phone.
  406. FakeSendAppsSetupResponse(
  407. eche_app::proto::Result::RESULT_ERROR_ACTION_CANCELED,
  408. eche_app::proto::AppsAccessState::ACCESS_NOT_GRANTED);
  409. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  410. EXPECT_EQ(AppsAccessSetupOperation::Status::kOperationFailedOrCancelled,
  411. GetAppsAccessSetupOperationStatus());
  412. EXPECT_FALSE(IsSetupOperationInProgress());
  413. histograms.ExpectBucketCount(
  414. kEcheOnboardingHistogramName,
  415. OnboardingUserActionMetric::kUserActionRemoteInterrupt, 1);
  416. // Simulate flipping the access state to not granted.
  417. FakeGetAppsAccessStateResponse(
  418. eche_app::proto::Result::RESULT_NO_ERROR,
  419. eche_app::proto::AppsAccessState::ACCESS_NOT_GRANTED);
  420. // Start a setup operation with enabled and connected status and access
  421. // not granted.
  422. auto operation2 = StartSetupOperation();
  423. EXPECT_TRUE(operation2);
  424. // Verify that the request message has been sent and our operation status
  425. // is updated.
  426. EXPECT_EQ(3u, GetAppsSetupRequestCount());
  427. EXPECT_EQ(AppsAccessSetupOperation::Status::
  428. kSentMessageToPhoneAndWaitingForResponse,
  429. GetAppsAccessSetupOperationStatus());
  430. // Simulate getting a response back from the phone.
  431. FakeSendAppsSetupResponse(
  432. eche_app::proto::Result::RESULT_ERROR_SYSTEM,
  433. eche_app::proto::AppsAccessState::ACCESS_NOT_GRANTED);
  434. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  435. EXPECT_EQ(AppsAccessSetupOperation::Status::kOperationFailedOrCancelled,
  436. GetAppsAccessSetupOperationStatus());
  437. EXPECT_FALSE(IsSetupOperationInProgress());
  438. histograms.ExpectBucketCount(kEcheOnboardingHistogramName,
  439. OnboardingUserActionMetric::kSystemError, 1);
  440. }
  441. TEST_F(AppsAccessManagerImplTest, SimulateConnectingToDisconnected) {
  442. // Set initial state to disconnected.
  443. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  444. SetFeatureStatus(FeatureStatus::kDisconnected);
  445. Initialize(AccessStatus::kAvailableButNotGranted);
  446. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  447. auto operation = StartSetupOperation();
  448. EXPECT_TRUE(operation);
  449. // Simulate a disconnection and expect that status has been updated.
  450. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnecting);
  451. SetFeatureStatus(FeatureStatus::kConnecting);
  452. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  453. SetFeatureStatus(FeatureStatus::kDisconnected);
  454. EXPECT_EQ(AppsAccessSetupOperation::Status::kTimedOutConnecting,
  455. GetAppsAccessSetupOperationStatus());
  456. EXPECT_FALSE(IsSetupOperationInProgress());
  457. }
  458. TEST_F(AppsAccessManagerImplTest, SimulateConnectedToDisconnected) {
  459. // Set initial state to disconnected.
  460. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  461. SetFeatureStatus(FeatureStatus::kDisconnected);
  462. Initialize(AccessStatus::kAvailableButNotGranted);
  463. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  464. auto operation = StartSetupOperation();
  465. EXPECT_TRUE(operation);
  466. // Simulate connected state.
  467. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  468. SetFeatureStatus(FeatureStatus::kConnected);
  469. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  470. // Simulate a disconnection, expect status update.
  471. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  472. SetFeatureStatus(FeatureStatus::kDisconnected);
  473. EXPECT_EQ(AppsAccessSetupOperation::Status::kConnectionDisconnected,
  474. GetAppsAccessSetupOperationStatus());
  475. EXPECT_FALSE(IsSetupOperationInProgress());
  476. }
  477. TEST_F(AppsAccessManagerImplTest, OnConnectionStatusChanged) {
  478. Initialize(AccessStatus::kAvailableButNotGranted);
  479. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  480. // Simulate disabling the feature and connection is disconnected.
  481. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  482. SetFeatureStatus(FeatureStatus::kDisabled);
  483. EXPECT_EQ(1u, GetAttemptNearbyConnectionCount());
  484. EXPECT_EQ(0u, GetAppsAccessStateRequestCount());
  485. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  486. EXPECT_EQ(1u, GetAppsAccessStateRequestCount());
  487. // Simulate flipping the access state to granted.
  488. FakeGetAppsAccessStateResponse(
  489. eche_app::proto::Result::RESULT_NO_ERROR,
  490. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  491. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  492. EXPECT_EQ(1u, GetAttemptNearbyConnectionCount());
  493. }
  494. TEST_F(AppsAccessManagerImplTest,
  495. SimulateDisabledWithDifferentConnectionStatus) {
  496. Initialize(AccessStatus::kAvailableButNotGranted);
  497. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  498. // Simulate disabling the feature and connection is disconnected.
  499. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  500. SetFeatureStatus(FeatureStatus::kDisabled);
  501. auto operation = StartSetupOperation();
  502. EXPECT_TRUE(operation);
  503. EXPECT_EQ(AppsAccessSetupOperation::Status::kConnecting,
  504. GetAppsAccessSetupOperationStatus());
  505. EXPECT_EQ(2u, GetAttemptNearbyConnectionCount());
  506. EXPECT_EQ(0u, GetAppsSetupRequestCount());
  507. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnecting);
  508. EXPECT_EQ(AppsAccessSetupOperation::Status::kConnecting,
  509. GetAppsAccessSetupOperationStatus());
  510. EXPECT_EQ(0u, GetAppsSetupRequestCount());
  511. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  512. EXPECT_EQ(AppsAccessSetupOperation::Status::
  513. kSentMessageToPhoneAndWaitingForResponse,
  514. GetAppsAccessSetupOperationStatus());
  515. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  516. // Simulate getting a response back from the phone.
  517. FakeSendAppsSetupResponse(eche_app::proto::Result::RESULT_NO_ERROR,
  518. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  519. VerifyAppsAccessGrantedState(AccessStatus::kAccessGranted);
  520. EXPECT_EQ(AppsAccessSetupOperation::Status::kCompletedSuccessfully,
  521. GetAppsAccessSetupOperationStatus());
  522. }
  523. TEST_F(AppsAccessManagerImplTest, SimulateConnectedToDependentFeature) {
  524. // Set initial state to disconnected.
  525. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  526. SetFeatureStatus(FeatureStatus::kDisconnected);
  527. Initialize(AccessStatus::kAvailableButNotGranted);
  528. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  529. auto operation = StartSetupOperation();
  530. EXPECT_TRUE(operation);
  531. // Simulate connected state.
  532. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  533. SetFeatureStatus(FeatureStatus::kConnected);
  534. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  535. // Simulate disabling the feature, expect status update.
  536. SetFeatureStatus(FeatureStatus::kDependentFeature);
  537. EXPECT_EQ(AppsAccessSetupOperation::Status::kConnectionDisconnected,
  538. GetAppsAccessSetupOperationStatus());
  539. }
  540. TEST_F(AppsAccessManagerImplTest, SimulateConnectedToDependentFeaturePending) {
  541. // Set initial state to disconnected.
  542. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  543. SetFeatureStatus(FeatureStatus::kDisconnected);
  544. Initialize(AccessStatus::kAvailableButNotGranted);
  545. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  546. auto operation = StartSetupOperation();
  547. EXPECT_TRUE(operation);
  548. // Simulate connected state.
  549. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  550. SetFeatureStatus(FeatureStatus::kConnected);
  551. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  552. // Simulate disabling the feature, expect status update.
  553. SetFeatureStatus(FeatureStatus::kDependentFeaturePending);
  554. EXPECT_EQ(AppsAccessSetupOperation::Status::kConnectionDisconnected,
  555. GetAppsAccessSetupOperationStatus());
  556. }
  557. TEST_F(AppsAccessManagerImplTest, FlipAccessNotGrantedToGranted) {
  558. SetFeatureState(Feature::kPhoneHub, FeatureState::kEnabledByUser);
  559. Initialize(AccessStatus::kAvailableButNotGranted);
  560. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  561. // Simulate flipping the access state to granted.
  562. FakeGetAppsAccessStateResponse(
  563. eche_app::proto::Result::RESULT_NO_ERROR,
  564. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  565. VerifyAppsAccessGrantedState(AccessStatus::kAccessGranted);
  566. EXPECT_EQ(1u, GetNumObserverCalls());
  567. fake_multidevice_setup_client()->InvokePendingSetFeatureEnabledStateCallback(
  568. /*expected_feature=*/Feature::kEche,
  569. /*expected_enabled=*/true, /*expected_auth_token=*/absl::nullopt,
  570. /*success=*/true);
  571. }
  572. TEST_F(AppsAccessManagerImplTest, FlipAccessGrantedToNotGranted) {
  573. SetFeatureState(Feature::kPhoneHub, FeatureState::kEnabledByUser);
  574. SetFeatureState(Feature::kEche, FeatureState::kDisabledByUser);
  575. Initialize(AccessStatus::kAccessGranted);
  576. VerifyAppsAccessGrantedState(AccessStatus::kAccessGranted);
  577. // Simulate flipping the access state to not granted.
  578. FakeGetAppsAccessStateResponse(
  579. eche_app::proto::Result::RESULT_NO_ERROR,
  580. eche_app::proto::AppsAccessState::ACCESS_NOT_GRANTED);
  581. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  582. EXPECT_EQ(1u, GetNumObserverCalls());
  583. }
  584. TEST_F(AppsAccessManagerImplTest, AccessNotChanged) {
  585. SetFeatureState(Feature::kPhoneHub, FeatureState::kEnabledByUser);
  586. SetFeatureState(Feature::kEche, FeatureState::kEnabledByUser);
  587. Initialize(AccessStatus::kAccessGranted);
  588. VerifyAppsAccessGrantedState(AccessStatus::kAccessGranted);
  589. // Simulate flipping the access state granted.
  590. FakeGetAppsAccessStateResponse(
  591. eche_app::proto::Result::RESULT_NO_ERROR,
  592. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  593. VerifyAppsAccessGrantedState(AccessStatus::kAccessGranted);
  594. EXPECT_EQ(0u, GetNumObserverCalls());
  595. fake_multidevice_setup_client()->InvokePendingSetFeatureEnabledStateCallback(
  596. /*expected_feature=*/Feature::kEche,
  597. /*expected_enabled=*/true, /*expected_auth_token=*/absl::nullopt,
  598. /*success=*/true);
  599. }
  600. TEST_F(AppsAccessManagerImplTest,
  601. ShouleNotEnableEcheFeatureWhenPhoneHubIsDisabled) {
  602. // Explicitly disable Phone Hub, all sub feature should be disabled
  603. SetFeatureState(Feature::kPhoneHub, FeatureState::kDisabledByUser);
  604. SetFeatureState(Feature::kEche, FeatureState::kDisabledByUser);
  605. Initialize(AccessStatus::kAvailableButNotGranted);
  606. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  607. // No action after access is granted
  608. // Simulate flipping the access state granted.
  609. FakeGetAppsAccessStateResponse(
  610. eche_app::proto::Result::RESULT_NO_ERROR,
  611. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  612. EXPECT_EQ(
  613. 0u,
  614. fake_multidevice_setup_client()->NumPendingSetFeatureEnabledStateCalls());
  615. }
  616. TEST_F(AppsAccessManagerImplTest, InitiallyEnableApps) {
  617. SetFeatureState(Feature::kPhoneHub, FeatureState::kEnabledByUser);
  618. Initialize(AccessStatus::kAvailableButNotGranted);
  619. // Simulate flipping the access state granted.
  620. FakeGetAppsAccessStateResponse(
  621. eche_app::proto::Result::RESULT_NO_ERROR,
  622. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  623. // If the kEche feature has not been explicitly set yet, enable it
  624. // when Phone Hub is enabled and access has been granted.
  625. fake_multidevice_setup_client()->InvokePendingSetFeatureEnabledStateCallback(
  626. /*expected_feature=*/Feature::kEche,
  627. /*expected_enabled=*/true, /*expected_auth_token=*/absl::nullopt,
  628. /*success=*/true);
  629. }
  630. TEST_F(AppsAccessManagerImplTest,
  631. SimulateAccessNotGrantedShouleDisableEcheFeature) {
  632. SetFeatureState(Feature::kPhoneHub, FeatureState::kEnabledByUser);
  633. SetFeatureState(Feature::kEche, FeatureState::kEnabledByUser);
  634. Initialize(AccessStatus::kAccessGranted);
  635. VerifyAppsAccessGrantedState(AccessStatus::kAccessGranted);
  636. // Test that there is a call to disable kEche when apps access has been
  637. // revoked. Simulate flipping the access state to not granted.
  638. FakeGetAppsAccessStateResponse(
  639. eche_app::proto::Result::RESULT_NO_ERROR,
  640. eche_app::proto::AppsAccessState::ACCESS_NOT_GRANTED);
  641. fake_multidevice_setup_client()->InvokePendingSetFeatureEnabledStateCallback(
  642. /*expected_feature=*/Feature::kEche,
  643. /*expected_enabled=*/false, /*expected_auth_token=*/absl::nullopt,
  644. /*success=*/true);
  645. }
  646. TEST_F(AppsAccessManagerImplTest,
  647. InitiallyEnableEcheFeature_OnlyEnableFromDefaultState) {
  648. SetFeatureState(Feature::kPhoneHub, FeatureState::kEnabledByUser);
  649. Initialize(AccessStatus::kAccessGranted);
  650. // If the Eche feature has not been explicitly set yet, enable it
  651. // when Phone Hub is enabled and access has been granted.
  652. FakeGetAppsAccessStateResponse(
  653. eche_app::proto::Result::RESULT_NO_ERROR,
  654. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  655. fake_multidevice_setup_client()->InvokePendingSetFeatureEnabledStateCallback(
  656. /*expected_feature=*/Feature::kEche,
  657. /*expected_enabled=*/true, /*expected_auth_token=*/absl::nullopt,
  658. /*success=*/true);
  659. }
  660. TEST_F(AppsAccessManagerImplTest,
  661. ShouldNotEnableEcheFeatureIfFeatureIsNotDefaultState) {
  662. SetFeatureState(Feature::kPhoneHub, FeatureState::kEnabledByUser);
  663. // Simulate the Eche feature has been changed by user.
  664. SetFeatureEnabledState(ash::multidevice_setup::kEcheEnabledPrefName, false);
  665. Initialize(AccessStatus::kAccessGranted);
  666. // We take no action after access is granted because the Eche feature
  667. // state was already explicitly set; we respect the user's choice.
  668. FakeGetAppsAccessStateResponse(
  669. eche_app::proto::Result::RESULT_NO_ERROR,
  670. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  671. EXPECT_EQ(
  672. 0u,
  673. fake_multidevice_setup_client()->NumPendingSetFeatureEnabledStateCalls());
  674. }
  675. TEST_F(AppsAccessManagerImplTest,
  676. ShouleNotEnableEcheFeatureWhenAppsPolicyDisabled) {
  677. // Explicitly disable Phone Hub, all sub feature should be disabled
  678. SetFeatureState(Feature::kPhoneHub, FeatureState::kDisabledByUser);
  679. SetFeatureState(Feature::kEche, FeatureState::kDisabledByUser);
  680. Initialize(AccessStatus::kAvailableButNotGranted);
  681. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  682. // Simulate flipping the policy state is disabled.
  683. FakeSendAppsPolicyStateChange(
  684. eche_app::proto::AppStreamingPolicy::APP_POLICY_DISABLED);
  685. // No action after access is granted.
  686. // Simulate flipping the access state granted.
  687. FakeGetAppsAccessStateResponse(
  688. eche_app::proto::Result::RESULT_NO_ERROR,
  689. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  690. EXPECT_EQ(
  691. 0u,
  692. fake_multidevice_setup_client()->NumPendingSetFeatureEnabledStateCalls());
  693. }
  694. TEST_F(AppsAccessManagerImplTest,
  695. SimulateAppsPolicyDisabledShouldDisableEcheFeature) {
  696. SetFeatureState(Feature::kPhoneHub, FeatureState::kEnabledByUser);
  697. SetFeatureState(Feature::kEche, FeatureState::kEnabledByUser);
  698. Initialize(AccessStatus::kAccessGranted);
  699. VerifyAppsAccessGrantedState(AccessStatus::kAccessGranted);
  700. // Test that there is a call to disable kEche when apps polcy state has been
  701. // changed. Simulate flipping the policy state is disabled.
  702. FakeSendAppsPolicyStateChange(
  703. eche_app::proto::AppStreamingPolicy::APP_POLICY_DISABLED);
  704. // No action is taken until get apps access state response is received.
  705. EXPECT_EQ(0u, GetNumObserverCalls());
  706. FakeGetAppsAccessStateResponse(
  707. eche_app::proto::Result::RESULT_NO_ERROR,
  708. eche_app::proto::AppsAccessState::ACCESS_GRANTED);
  709. fake_multidevice_setup_client()->InvokePendingSetFeatureEnabledStateCallback(
  710. /*expected_feature=*/Feature::kEche,
  711. /*expected_enabled=*/false, /*expected_auth_token=*/absl::nullopt,
  712. /*success=*/true);
  713. EXPECT_EQ(1u, GetNumObserverCalls());
  714. }
  715. TEST_F(AppsAccessManagerImplTest, LogSetupCancelWhenAppsAccessCanceled) {
  716. base::HistogramTester histograms;
  717. // Set initial state to connecting.
  718. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnecting);
  719. SetFeatureStatus(FeatureStatus::kConnecting);
  720. Initialize(AccessStatus::kAvailableButNotGranted);
  721. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  722. // Start a setup operation with enabled and connecting status and access
  723. // not granted.
  724. auto operation = StartSetupOperation();
  725. EXPECT_TRUE(operation);
  726. // Simulate changing states from connecting to connected.
  727. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  728. SetFeatureStatus(FeatureStatus::kConnected);
  729. // Verify that the request message has been sent and our operation status
  730. // is updated.
  731. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  732. EXPECT_EQ(AppsAccessSetupOperation::Status::
  733. kSentMessageToPhoneAndWaitingForResponse,
  734. GetAppsAccessSetupOperationStatus());
  735. EXPECT_TRUE(IsSetupOperationInProgress());
  736. // Notify the apps access setup operation is canceled.
  737. NotifyAppsAccessCanceled();
  738. // Verify the metric logs the expected event.
  739. histograms.ExpectBucketCount(kEcheOnboardingHistogramName,
  740. OnboardingUserActionMetric::kUserActionCanceled,
  741. 1);
  742. }
  743. TEST_F(AppsAccessManagerImplTest,
  744. LogFailConnectionWhenCanceledAndDisconnected) {
  745. base::HistogramTester histograms;
  746. // Set initial state to connecting.
  747. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnecting);
  748. SetFeatureStatus(FeatureStatus::kConnecting);
  749. Initialize(AccessStatus::kAvailableButNotGranted);
  750. VerifyAppsAccessGrantedState(AccessStatus::kAvailableButNotGranted);
  751. // Start a setup operation with enabled and connecting status and access
  752. // not granted.
  753. auto operation = StartSetupOperation();
  754. EXPECT_TRUE(operation);
  755. // Simulate changing states from connecting to connected.
  756. SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected);
  757. SetFeatureStatus(FeatureStatus::kConnected);
  758. // Verify that the request message has been sent and our operation status
  759. // is updated.
  760. EXPECT_EQ(1u, GetAppsSetupRequestCount());
  761. EXPECT_EQ(AppsAccessSetupOperation::Status::
  762. kSentMessageToPhoneAndWaitingForResponse,
  763. GetAppsAccessSetupOperationStatus());
  764. EXPECT_TRUE(IsSetupOperationInProgress());
  765. // Simulate changing states from connected to disconnected.
  766. SetConnectionStatus(secure_channel::ConnectionManager::Status::kDisconnected);
  767. SetFeatureStatus(FeatureStatus::kDisconnected);
  768. // Notify the apps access setup operation is canceled.
  769. NotifyAppsAccessCanceled();
  770. // Verify the metric logs the expected event.
  771. histograms.ExpectBucketCount(kEcheOnboardingHistogramName,
  772. OnboardingUserActionMetric::kFailedConnection,
  773. 1);
  774. }
  775. } // namespace eche_app
  776. } // namespace ash