| // Copyright 2020 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "chrome/browser/nearby_sharing/nearby_receive_manager.h" | 
 |  | 
 | #include "base/test/bind.h" | 
 | #include "base/test/mock_callback.h" | 
 | #include "chrome/browser/nearby_sharing/mock_nearby_sharing_service.h" | 
 | #include "chrome/browser/nearby_sharing/share_target.h" | 
 | #include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom-test-utils.h" | 
 | #include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h" | 
 | #include "content/public/test/browser_task_environment.h" | 
 | #include "testing/gmock/include/gmock/gmock.h" | 
 | #include "testing/gtest/include/gtest/gtest.h" | 
 | #include "third_party/abseil-cpp/absl/types/optional.h" | 
 |  | 
 | namespace { | 
 |  | 
 | class FakeReceiveObserver : public nearby_share::mojom::ReceiveObserver { | 
 |  public: | 
 |   void OnHighVisibilityChanged(bool in_high_visibility) override { | 
 |     in_high_visibility_ = in_high_visibility; | 
 |   } | 
 |  | 
 |   void OnTransferUpdate( | 
 |       const ShareTarget& share_target, | 
 |       nearby_share::mojom::TransferMetadataPtr metadata) override { | 
 |     last_share_target_ = share_target; | 
 |     last_metadata_ = *metadata; | 
 |   } | 
 |  | 
 |   void OnNearbyProcessStopped() override { | 
 |     on_nearby_process_stopped_called_ = true; | 
 |   } | 
 |  | 
 |   void OnStartAdvertisingFailure() override { | 
 |     on_start_advertising_failure_called_ = true; | 
 |   } | 
 |  | 
 |   absl::optional<nearby_share::mojom::TransferMetadata> last_metadata_; | 
 |   absl::optional<bool> in_high_visibility_; | 
 |   ShareTarget last_share_target_; | 
 |   bool on_nearby_process_stopped_called_ = false; | 
 |   bool on_start_advertising_failure_called_ = false; | 
 |   mojo::Receiver<nearby_share::mojom::ReceiveObserver> receiver_{this}; | 
 | }; | 
 |  | 
 | class NearbyReceiveManagerTest : public testing::Test { | 
 |  public: | 
 |   using ReceiveSurfaceState = NearbySharingService::ReceiveSurfaceState; | 
 |   using StatusCodes = NearbySharingService::StatusCodes; | 
 |   using RegisterReceiveSurfaceResult = | 
 |       nearby_share::mojom::RegisterReceiveSurfaceResult; | 
 |  | 
 |   NearbyReceiveManagerTest() | 
 |       : transfer_metadata_(TransferMetadata::Status::kAwaitingLocalConfirmation, | 
 |                            /*progress=*/0.f, | 
 |                            /*token=*/"1234", | 
 |                            /*is_original=*/true, | 
 |                            /*is_final_status=*/false) { | 
 |     share_target_.id = base::UnguessableToken::Create(); | 
 |     receive_manager_.AddReceiveObserver( | 
 |         observer_.receiver_.BindNewPipeAndPassRemote()); | 
 |   } | 
 |  | 
 |   ~NearbyReceiveManagerTest() override = default; | 
 |  | 
 |  protected: | 
 |   void FlushMojoMessages() { observer_.receiver_.FlushForTesting(); } | 
 |  | 
 |   void ExpectRegister(StatusCodes code = StatusCodes::kOk) { | 
 |     EXPECT_CALL(sharing_service_, | 
 |                 RegisterReceiveSurface(testing::_, testing::_)) | 
 |         .WillOnce([=](TransferUpdateCallback* transfer_callback, | 
 |                       ReceiveSurfaceState state) { | 
 |           EXPECT_EQ(ReceiveSurfaceState::kForeground, state); | 
 |           return code; | 
 |         }); | 
 |   } | 
 |  | 
 |   void ExpectUnregister(StatusCodes code = StatusCodes::kOk) { | 
 |     EXPECT_CALL(sharing_service_, UnregisterReceiveSurface(testing::_)) | 
 |         .WillOnce( | 
 |             [=](TransferUpdateCallback* transfer_callback) { return code; }); | 
 |   } | 
 |  | 
 |   void ExpectIsInHighVisibility(bool in_high_visibility) { | 
 |     EXPECT_CALL(sharing_service_, IsInHighVisibility()) | 
 |         .WillOnce(testing::Return(in_high_visibility)); | 
 |   } | 
 |  | 
 |   void ExpectAccept(StatusCodes code = StatusCodes::kOk) { | 
 |     EXPECT_CALL(sharing_service_, Accept(testing::_, testing::_)) | 
 |         .WillOnce([=](const ShareTarget& share_target, | 
 |                       NearbySharingService::StatusCodesCallback | 
 |                           status_codes_callback) { | 
 |           std::move(status_codes_callback).Run(code); | 
 |         }); | 
 |   } | 
 |  | 
 |   void ExpectReject(StatusCodes code = StatusCodes::kOk) { | 
 |     EXPECT_CALL(sharing_service_, Reject(testing::_, testing::_)) | 
 |         .WillOnce([=](const ShareTarget& share_target, | 
 |                       NearbySharingService::StatusCodesCallback | 
 |                           status_codes_callback) { | 
 |           std::move(status_codes_callback).Run(code); | 
 |         }); | 
 |   } | 
 |  | 
 |   content::BrowserTaskEnvironment task_environment_; | 
 |   ShareTarget share_target_; | 
 |   TransferMetadata transfer_metadata_; | 
 |   MockNearbySharingService sharing_service_; | 
 |   FakeReceiveObserver observer_; | 
 |   NearbyReceiveManager receive_manager_{&sharing_service_}; | 
 |   nearby_share::mojom::ReceiveManagerAsyncWaiter receive_manager_waiter_{ | 
 |       &receive_manager_}; | 
 | }; | 
 |  | 
 | }  // namespace | 
 |  | 
 | TEST_F(NearbyReceiveManagerTest, Enter_Exit_Success) { | 
 |   ExpectRegister(); | 
 |   RegisterReceiveSurfaceResult result = RegisterReceiveSurfaceResult::kFailure; | 
 |   receive_manager_waiter_.RegisterForegroundReceiveSurface(&result); | 
 |   EXPECT_EQ(RegisterReceiveSurfaceResult::kSuccess, result); | 
 |  | 
 |   ExpectUnregister(); | 
 |   bool exited = false; | 
 |   receive_manager_waiter_.UnregisterForegroundReceiveSurface(&exited); | 
 |   EXPECT_TRUE(exited); | 
 |  | 
 |   ExpectUnregister(); | 
 | } | 
 |  | 
 | TEST_F(NearbyReceiveManagerTest, Enter_Failed) { | 
 |   RegisterReceiveSurfaceResult result = RegisterReceiveSurfaceResult::kSuccess; | 
 |   ExpectRegister(StatusCodes::kError); | 
 |   receive_manager_waiter_.RegisterForegroundReceiveSurface(&result); | 
 |   EXPECT_EQ(RegisterReceiveSurfaceResult::kFailure, result); | 
 |   ExpectUnregister(); | 
 | } | 
 |  | 
 | TEST_F(NearbyReceiveManagerTest, Multiple_Enter_Successful) { | 
 |   RegisterReceiveSurfaceResult result = RegisterReceiveSurfaceResult::kFailure; | 
 |   ExpectRegister(StatusCodes::kOk); | 
 |   receive_manager_waiter_.RegisterForegroundReceiveSurface(&result); | 
 |   FlushMojoMessages(); | 
 |   EXPECT_EQ(RegisterReceiveSurfaceResult::kSuccess, result); | 
 |  | 
 |   result = RegisterReceiveSurfaceResult::kFailure; | 
 |   ExpectRegister(StatusCodes::kOk); | 
 |   receive_manager_waiter_.RegisterForegroundReceiveSurface(&result); | 
 |   FlushMojoMessages(); | 
 |   EXPECT_EQ(RegisterReceiveSurfaceResult::kSuccess, result); | 
 |  | 
 |   ExpectUnregister(); | 
 | } | 
 |  | 
 | TEST_F(NearbyReceiveManagerTest, Exit_Failed) { | 
 |   RegisterReceiveSurfaceResult result = RegisterReceiveSurfaceResult::kFailure; | 
 |   ExpectRegister(); | 
 |   receive_manager_waiter_.RegisterForegroundReceiveSurface(&result); | 
 |   EXPECT_EQ(RegisterReceiveSurfaceResult::kSuccess, result); | 
 |  | 
 |   ExpectUnregister(StatusCodes::kError); | 
 |   bool exited = false; | 
 |   receive_manager_waiter_.UnregisterForegroundReceiveSurface(&exited); | 
 |   EXPECT_FALSE(exited); | 
 |  | 
 |   ExpectUnregister(); | 
 | } | 
 |  | 
 | TEST_F(NearbyReceiveManagerTest, ShareTargetNotifies_Accept) { | 
 |   receive_manager_.OnTransferUpdate(share_target_, transfer_metadata_); | 
 |   FlushMojoMessages(); | 
 |   EXPECT_EQ(share_target_.id, observer_.last_share_target_.id); | 
 |   ASSERT_TRUE(observer_.last_metadata_.has_value()); | 
 |   EXPECT_EQ("1234", observer_.last_metadata_->token); | 
 |  | 
 |   ExpectAccept(); | 
 |   bool success = false; | 
 |   receive_manager_waiter_.Accept(share_target_.id, &success); | 
 |   EXPECT_TRUE(success); | 
 |  | 
 |   ExpectUnregister(); | 
 | } | 
 |  | 
 | TEST_F(NearbyReceiveManagerTest, ShareTargetNotifies_Reject) { | 
 |   receive_manager_.OnTransferUpdate(share_target_, transfer_metadata_); | 
 |   FlushMojoMessages(); | 
 |   EXPECT_EQ(share_target_.id, observer_.last_share_target_.id); | 
 |   ASSERT_TRUE(observer_.last_metadata_.has_value()); | 
 |   EXPECT_EQ("1234", observer_.last_metadata_->token); | 
 |  | 
 |   ExpectReject(); | 
 |   bool success = false; | 
 |   receive_manager_waiter_.Reject(share_target_.id, &success); | 
 |   EXPECT_TRUE(success); | 
 |  | 
 |   ExpectUnregister(); | 
 | } | 
 |  | 
 | TEST_F(NearbyReceiveManagerTest, | 
 |        ShareTargetNotifies_SenderCancelsBeforeAccept) { | 
 |   receive_manager_.OnTransferUpdate(share_target_, transfer_metadata_); | 
 |   FlushMojoMessages(); | 
 |   EXPECT_EQ(share_target_.id, observer_.last_share_target_.id); | 
 |   ASSERT_TRUE(observer_.last_metadata_.has_value()); | 
 |   EXPECT_EQ("1234", observer_.last_metadata_->token); | 
 |  | 
 |   // Simulate the sender canceling before we accept the share target and causing | 
 |   // the accept to fail before hitting the service. | 
 |   TransferMetadata transfer_metadata_final(TransferMetadata::Status::kCancelled, | 
 |                                            1.f, absl::nullopt, true, true); | 
 |   receive_manager_.OnTransferUpdate(share_target_, transfer_metadata_final); | 
 |   FlushMojoMessages(); | 
 |  | 
 |   bool success = true; | 
 |   receive_manager_waiter_.Accept(share_target_.id, &success); | 
 |   EXPECT_FALSE(success); | 
 |  | 
 |   ExpectUnregister(); | 
 | } | 
 |  | 
 | TEST_F(NearbyReceiveManagerTest, | 
 |        ShareTargetNotifies_SenderCancelsBeforeReject) { | 
 |   receive_manager_.OnTransferUpdate(share_target_, transfer_metadata_); | 
 |   FlushMojoMessages(); | 
 |   EXPECT_EQ(share_target_.id, observer_.last_share_target_.id); | 
 |   ASSERT_TRUE(observer_.last_metadata_.has_value()); | 
 |   EXPECT_EQ("1234", observer_.last_metadata_->token); | 
 |  | 
 |   // Simulate the sender canceling before we reject the share target and causing | 
 |   // the reject to fail before hitting the service. | 
 |   TransferMetadata transfer_metadata_final(TransferMetadata::Status::kCancelled, | 
 |                                            1.f, absl::nullopt, true, true); | 
 |   receive_manager_.OnTransferUpdate(share_target_, transfer_metadata_final); | 
 |   FlushMojoMessages(); | 
 |  | 
 |   bool success = true; | 
 |   receive_manager_waiter_.Reject(share_target_.id, &success); | 
 |   EXPECT_FALSE(success); | 
 |  | 
 |   ExpectUnregister(); | 
 | } | 
 |  | 
 | TEST_F(NearbyReceiveManagerTest, IsInHighVisibility) { | 
 |   ExpectIsInHighVisibility(true); | 
 |   bool on = false; | 
 |   receive_manager_waiter_.IsInHighVisibility(&on); | 
 |   FlushMojoMessages(); | 
 |   EXPECT_TRUE(on); | 
 |  | 
 |   ExpectIsInHighVisibility(false); | 
 |   on = true; | 
 |   receive_manager_waiter_.IsInHighVisibility(&on); | 
 |   FlushMojoMessages(); | 
 |   EXPECT_FALSE(on); | 
 |  | 
 |   ExpectUnregister(); | 
 | } | 
 |  | 
 | TEST_F(NearbyReceiveManagerTest, OnHighVisibilityChangedObserver) { | 
 |   receive_manager_.OnHighVisibilityChanged(false); | 
 |   FlushMojoMessages(); | 
 |   ASSERT_TRUE(observer_.in_high_visibility_.has_value()); | 
 |   EXPECT_FALSE(*observer_.in_high_visibility_); | 
 |  | 
 |   observer_.in_high_visibility_ = absl::nullopt; | 
 |  | 
 |   receive_manager_.OnHighVisibilityChanged(true); | 
 |   FlushMojoMessages(); | 
 |   ASSERT_TRUE(observer_.in_high_visibility_.has_value()); | 
 |   EXPECT_TRUE(*observer_.in_high_visibility_); | 
 |  | 
 |   ExpectUnregister(); | 
 | } | 
 |  | 
 | TEST_F(NearbyReceiveManagerTest, OnStartAdvertisingFailureObserver) { | 
 |   EXPECT_FALSE(observer_.on_start_advertising_failure_called_); | 
 |   receive_manager_.OnStartAdvertisingFailure(); | 
 |   FlushMojoMessages(); | 
 |   EXPECT_TRUE(observer_.on_start_advertising_failure_called_); | 
 |  | 
 |   ExpectUnregister(); | 
 | } |