// Copyright 2022-2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "sharing/nearby_sharing_service_impl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "base/casts.h" #include "gmock/gmock.h" #include "protobuf-matchers/protocol-buffer-matchers.h" #include "gtest/gtest.h" #include "absl/base/thread_annotations.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "absl/synchronization/notification.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "absl/types/span.h" #include "internal/analytics/mock_event_logger.h" #include "internal/base/file_path.h" #include "internal/base/files.h" #include "internal/flags/nearby_flags.h" #include "internal/platform/implementation/signin_attempt.h" #include "internal/test/fake_account_manager.h" #include "internal/test/fake_device_info.h" #include "internal/test/fake_task_runner.h" #include "internal/test/mock_account_observer.h" #include "sharing/advertisement.h" #include "sharing/analytics/analytics_recorder.h" #include "sharing/attachment_container.h" #include "sharing/certificates/fake_nearby_share_certificate_manager.h" #include "sharing/certificates/nearby_share_certificate_manager_impl.h" #include "sharing/certificates/nearby_share_decrypted_public_certificate.h" #include "sharing/certificates/test_util.h" #include "sharing/common/nearby_share_enums.h" #include "sharing/common/nearby_share_prefs.h" #include "sharing/constants.h" #include "sharing/contacts/fake_nearby_share_contact_manager.h" #include "sharing/contacts/nearby_share_contact_manager_impl.h" #include "sharing/fake_nearby_connections_manager.h" #include "sharing/fast_initiation/fake_nearby_fast_initiation.h" #include "sharing/fast_initiation/nearby_fast_initiation_impl.h" #include "sharing/file_attachment.h" #include "sharing/flags/generated/nearby_sharing_feature_flags.h" #include "sharing/incoming_share_session.h" #include "sharing/internal/api/mock_app_info.h" #include "sharing/internal/api/mock_sharing_platform.h" #include "sharing/internal/api/preference_manager.h" #include "sharing/internal/public/connectivity_manager.h" #include "sharing/internal/test/fake_bluetooth_adapter.h" #include "sharing/internal/test/fake_connectivity_manager.h" #include "sharing/internal/test/fake_context.h" #include "sharing/internal/test/fake_preference_manager.h" #include "sharing/local_device_data/fake_nearby_share_local_device_data_manager.h" #include "sharing/local_device_data/nearby_share_local_device_data_manager_impl.h" #include "sharing/nearby_connection_impl.h" #include "sharing/nearby_connections_manager.h" #include "sharing/nearby_connections_types.h" #include "sharing/nearby_sharing_service.h" #include "sharing/nearby_sharing_settings.h" #include "sharing/proto/enums.pb.h" #include "sharing/proto/rpc_resources.pb.h" #include "sharing/proto/wire_format.pb.h" #include "sharing/share_target.h" #include "sharing/share_target_discovered_callback.h" #include "sharing/text_attachment.h" #include "sharing/transfer_metadata.h" #include "sharing/transfer_metadata_matchers.h" #include "sharing/transfer_update_callback.h" #include "sharing/wifi_credentials_attachment.h" namespace nearby::sharing { namespace { using ConnectionType = ::nearby::ConnectivityManager::ConnectionType; using SendSurfaceState = ::nearby::sharing::NearbySharingService::SendSurfaceState; using ::nearby::sharing::api::MockAppInfo; using ::nearby::sharing::api::PreferenceManager; using ::nearby::sharing::proto::DataUsage; using ::nearby::sharing::proto::DeviceVisibility; using ::nearby::sharing::proto::FastInitiationNotificationState; using ::nearby::sharing::service::proto::ConnectionResponseFrame; using ::nearby::sharing::service::proto::FileMetadata; using ::nearby::sharing::service::proto::Frame; using ::nearby::sharing::service::proto::IntroductionFrame; using ::nearby::sharing::service::proto::PairedKeyResultFrame; using ::nearby::sharing::service::proto::TextMetadata; using ::nearby::sharing::service::proto::V1Frame; using ::testing::_; using ::testing::InSequence; using ::testing::NiceMock; using ::testing::Return; using ::testing::ReturnRef; using ::testing::SaveArg; using ::testing::StrictMock; using ::testing::UnorderedElementsAre; // Used to wait for absl::Notification to finish. constexpr absl::Duration kWaitTimeout = absl::Milliseconds(500); constexpr absl::Duration kTaskWaitTimeout = absl::Seconds(2); class MockTransferUpdateCallback : public TransferUpdateCallback { public: ~MockTransferUpdateCallback() override = default; MOCK_METHOD(void, OnTransferUpdate, (const ShareTarget& shareTarget, const AttachmentContainer& attachmentContainer, const TransferMetadata& transferMetadata), (override)); }; class MockShareTargetDiscoveredCallback : public ShareTargetDiscoveredCallback { public: ~MockShareTargetDiscoveredCallback() override = default; MOCK_METHOD(void, OnShareTargetDiscovered, (const ShareTarget& share_target), (override)); MOCK_METHOD(void, OnShareTargetLost, (const ShareTarget& share_target), (override)); MOCK_METHOD(void, OnShareTargetUpdated, (const ShareTarget& share_target), (override)); }; // Auto unregister the receive surface when it goes out of scope. class ScopedReceiveSurface { public: ScopedReceiveSurface(NearbySharingServiceImpl* service, TransferUpdateCallback* transfer_callback) : service_(service), transfer_callback_(transfer_callback) {} ~ScopedReceiveSurface() { absl::Notification notification; service_->UnregisterReceiveSurface( transfer_callback_, [¬ification](NearbySharingService::StatusCodes status_codes) { notification.Notify(); }); notification.WaitForNotificationWithTimeout(kWaitTimeout); } private: NearbySharingServiceImpl* const service_; TransferUpdateCallback* const transfer_callback_; }; // Auto unregister the send surface when it goes out of scope. class ScopedSendSurface { public: ScopedSendSurface(NearbySharingServiceImpl* service, TransferUpdateCallback* transfer_callback) : service_(service), transfer_callback_(transfer_callback) {} ~ScopedSendSurface() { absl::Notification notification; service_->UnregisterSendSurface( transfer_callback_, [¬ification](NearbySharingService::StatusCodes status_codes) { notification.Notify(); }); notification.WaitForNotificationWithTimeout(kWaitTimeout); } private: NearbySharingServiceImpl* const service_; TransferUpdateCallback* const transfer_callback_; }; } // namespace namespace NearbySharingServiceUnitTests { constexpr absl::Duration kDelta = absl::Milliseconds(100); constexpr char kServiceId[] = "NearbySharing"; constexpr char kDeviceName[] = "test_device_name"; constexpr ShareTargetType kDeviceType = ShareTargetType::kPhone; constexpr char kEndpointId[] = "test_endpoint_id"; constexpr char kTextPayload[] = "Test text payload"; constexpr char kFourDigitToken[] = "1953"; constexpr absl::string_view kTestAccountId = "test_account"; constexpr uint8_t kVendorId = 0; constexpr int64_t kFreeDiskSpace = 10000; const std::vector& GetToken() { static std::vector* token = new std::vector({0, 1, 2}); return *token; } const std::vector& GetPrivateCertificateHashAuthToken() { static std::vector* private_certificate_hash_auth_token = new std::vector({0x8b, 0xcb, 0xa2, 0xf8, 0xe4, 0x06}); return *private_certificate_hash_auth_token; } const std::vector& GetIncomingConnectionSignedData() { static std::vector* incoming_connection_signed_data = new std::vector( {0x30, 0x45, 0x02, 0x20, 0x4f, 0x83, 0x72, 0xbd, 0x02, 0x70, 0xd9, 0xda, 0x62, 0x83, 0x5d, 0xb2, 0xdc, 0x6e, 0x3f, 0xa6, 0xa8, 0xa1, 0x4f, 0x5f, 0xd3, 0xe3, 0xd9, 0x1a, 0x5d, 0x2d, 0x61, 0xd2, 0x6c, 0xdd, 0x8d, 0xa5, 0x02, 0x21, 0x00, 0xd4, 0xe1, 0x1d, 0x14, 0xcb, 0x58, 0xf7, 0x02, 0xd5, 0xab, 0x48, 0xe2, 0x2f, 0xcb, 0xc0, 0x53, 0x41, 0x06, 0x50, 0x65, 0x95, 0x19, 0xa9, 0x22, 0x92, 0x00, 0x42, 0x01, 0x26, 0x25, 0xcb, 0x8c}); return *incoming_connection_signed_data; } const std::vector& GetOutgoingConnectionSignedData() { static std::vector* outgoing_connection_signed_data = new std::vector( {0x30, 0x45, 0x02, 0x21, 0x00, 0xf9, 0xc9, 0xa8, 0x89, 0x96, 0x6e, 0x5c, 0xea, 0x0a, 0x60, 0x37, 0x3a, 0x84, 0x7d, 0xf5, 0x31, 0x82, 0x74, 0xb9, 0xde, 0x3f, 0x64, 0x1b, 0xff, 0x4f, 0x54, 0x31, 0x1f, 0x9e, 0x63, 0x68, 0xca, 0x02, 0x20, 0x52, 0x43, 0x46, 0xa7, 0x6f, 0xcb, 0x96, 0x50, 0x86, 0xfd, 0x6f, 0x9f, 0x7e, 0x50, 0xa7, 0xa0, 0x9b, 0xdf, 0xae, 0x79, 0x42, 0x47, 0xd9, 0x60, 0x71, 0x91, 0x7a, 0xbb, 0x81, 0x9b, 0x0d, 0x2e}); return *outgoing_connection_signed_data; } constexpr int kFilePayloadId = 111; constexpr int kPayloadSize = 1000000; const std::vector& GetValidIntroductionFramePayloadIds() { static std::vector* valid_introduction_frame_payload_ids = new std::vector({1, 2, 3, kFilePayloadId}); return *valid_introduction_frame_payload_ids; } constexpr size_t kMaxCertificateDownloadsDuringDiscovery = 3u; constexpr absl::Duration kCertificateDownloadDuringDiscoveryPeriod = absl::Seconds(10); std::unique_ptr GetFilePayload(int64_t payload_id) { FilePath path = Files::GetTemporaryDirectory().append(FilePath(absl::StrCat(payload_id))); InputFile input_file{path.ToString()}; return std::make_unique(input_file); } std::unique_ptr GetTextPayload(int64_t payload_id, absl::string_view text) { return std::make_unique( std::vector(text.begin(), text.end())); } std::unique_ptr GetValidIntroductionFrame() { IntroductionFrame* introduction_frame = IntroductionFrame::default_instance().New(); auto text_metadatas = introduction_frame->mutable_text_metadata(); introduction_frame->set_start_transfer(true); for (int i = 1; i <= 3; ++i) { nearby::sharing::service::proto::TextMetadata* text_metadata = nearby::sharing::service::proto::TextMetadata::default_instance().New(); text_metadata->set_text_title(absl::StrCat("title ", i)); text_metadata->set_type( static_cast(i)); text_metadata->set_payload_id(i); text_metadata->set_size(kPayloadSize); text_metadata->set_id(i); text_metadatas->AddAllocated(text_metadata); } auto file_metadatas = introduction_frame->mutable_file_metadata(); nearby::sharing::service::proto::FileMetadata* file_metadata = nearby::sharing::service::proto::FileMetadata::default_instance().New(); file_metadata->set_name("unit_test_nearby_share_name_\x80"); file_metadata->set_type(nearby::sharing::service::proto::FileMetadata::VIDEO); file_metadata->set_payload_id(kFilePayloadId); file_metadata->set_size(kPayloadSize); file_metadata->set_mime_type("mime type"); file_metadata->set_id(100); file_metadatas->AddAllocated(file_metadata); V1Frame* v1_frame = V1Frame::default_instance().New(); v1_frame->set_type(V1Frame::INTRODUCTION); v1_frame->set_allocated_introduction(introduction_frame); Frame* frame = Frame::default_instance().New(); frame->set_version(Frame::V1); frame->set_allocated_v1(std::move(v1_frame)); return std::unique_ptr(frame); } std::unique_ptr GetEmptyIntroductionFrame() { V1Frame* v1_frame = V1Frame::default_instance().New(); v1_frame->set_type(V1Frame::INTRODUCTION); v1_frame->set_allocated_introduction( IntroductionFrame::default_instance().New()); Frame* frame = Frame::default_instance().New(); frame->set_version(Frame::V1); frame->set_allocated_v1(v1_frame); return std::unique_ptr(frame); } std::unique_ptr GetConnectionResponseFrame( ConnectionResponseFrame::Status status) { V1Frame* v1_frame = V1Frame::default_instance().New(); v1_frame->set_type(V1Frame::RESPONSE); ConnectionResponseFrame* response_frame = ConnectionResponseFrame::default_instance().New(); response_frame->set_status(status); v1_frame->set_allocated_connection_response(response_frame); Frame* frame = Frame::default_instance().New(); frame->set_version(Frame::V1); frame->set_allocated_v1(v1_frame); return std::unique_ptr(frame); } std::unique_ptr GetCancelFrame() { V1Frame* v1_frame = V1Frame::default_instance().New(); v1_frame->set_type(V1Frame::CANCEL); Frame* frame = Frame::default_instance().New(); frame->set_version(Frame::V1); frame->set_allocated_v1(v1_frame); return std::unique_ptr(frame); } std::unique_ptr CreateTextAttachments( std::vector texts) { auto attachment_container = std::make_unique(); for (auto& text : texts) { attachment_container->AddTextAttachment( TextAttachment(service::proto::TextMetadata::TEXT, std::move(text), /*text_title=*/std::nullopt, /*mime_type=*/std::nullopt)); } return attachment_container; } std::unique_ptr CreateFileAttachments( std::vector file_paths) { auto attachment_container = std::make_unique(); for (auto& file_path : file_paths) { attachment_container->AddFileAttachment( FileAttachment(std::move(file_path))); } return attachment_container; } std::unique_ptr CreateWifiCredentialAttachments( std::string ssid, std::string password) { auto attachment_container = std::make_unique(); attachment_container->AddWifiCredentialsAttachment(WifiCredentialsAttachment( std::move(ssid), service::proto::WifiCredentialsMetadata::WPA_PSK, std::move(password))); return attachment_container; } class NearbySharingServiceImplTest : public testing::Test { public: struct PayloadInfo { std::unique_ptr payload; std::weak_ptr listener; }; NearbySharingServiceImplTest() = default; ~NearbySharingServiceImplTest() override = default; void SetUp() override { ON_CALL(mock_sharing_platform_, GetDeviceInfo) .WillByDefault(ReturnRef(fake_device_info_)); ON_CALL(mock_sharing_platform_, GetPreferenceManager) .WillByDefault(ReturnRef(preference_manager_)); ON_CALL(mock_sharing_platform_, GetAccountManager) .WillByDefault(ReturnRef(fake_account_manager_)); ON_CALL(mock_sharing_platform_, UpdateFileOriginMetadata) .WillByDefault(Return(true)); auto mock_app_info = std::make_unique>(); mock_app_info_ = mock_app_info.get(); EXPECT_CALL(mock_sharing_platform_, CreateAppInfo()) .WillOnce(Return(std::move(mock_app_info))); NearbyShareLocalDeviceDataManagerImpl::Factory::SetFactoryForTesting( &local_device_data_manager_factory_); NearbyShareContactManagerImpl::Factory::SetFactoryForTesting( &contact_manager_factory_); NearbyShareCertificateManagerImpl::Factory::SetFactoryForTesting( &certificate_manager_factory_); nearby_fast_initiation_factory_ = std::make_unique(); NearbyFastInitiationImpl::Factory::SetFactoryForTesting( nearby_fast_initiation_factory_.get()); NearbyFlags::GetInstance().OverrideBoolFlagValue( config_package_nearby::nearby_sharing_feature::kEnableMediumWifiLan, true); prefs::RegisterNearbySharingPrefs(preference_manager_); auto fake_task_runner = std::make_unique(fake_context_.fake_clock(), 1); sharing_service_task_runner_ = fake_task_runner.get(); fake_nearby_connections_manager_ = new FakeNearbyConnectionsManager(); connection_ = std::make_unique(fake_device_info_); fake_nearby_connections_manager_->set_send_payload_callback( [this](std::unique_ptr payload, std::weak_ptr listener) { // If there are no listeners, treat it as a control frame. if (listener.use_count() == 0) { auto frame = std::make_unique(); std::vector data = std::move(payload->content.bytes_payload.bytes); frame->ParseFromArray(data.data(), data.size()); absl::MutexLock lock(connection_output_mutex_); frames_data_.push(std::move(frame)); } else { absl::MutexLock lock(connection_output_mutex_); written_payloads_.push(PayloadInfo(std::move(payload), listener)); } }); SetBluetoothIsPresent(true); SetBluetoothIsPowered(true); SetScreenLocked(false); SetConnectionType(ConnectionType::kWifi); analytics_recorder_ = std::make_unique( /*vendor_id=*/0, /*event_logger=*/nullptr); service_ = CreateService(std::move(fake_task_runner)); } void TearDown() override { if (connection_) { connection_.reset(); } Shutdown(); NearbyFlags::GetInstance().OverrideBoolFlagValue( config_package_nearby::nearby_sharing_feature::kEnableMediumWifiLan, true); NearbyShareLocalDeviceDataManagerImpl::Factory::SetFactoryForTesting( nullptr); NearbyShareContactManagerImpl::Factory::SetFactoryForTesting(nullptr); NearbyShareCertificateManagerImpl::Factory::SetFactoryForTesting(nullptr); NearbyFlags::GetInstance().ResetOverridedValues(); nearby_fast_initiation_factory_.reset(); } void SetConnectionType(ConnectionType type) { FakeConnectivityManager* connectivity_manager = down_cast( fake_context_.GetConnectivityManager()); connectivity_manager->SetConnectionType(type); } std::unique_ptr CreateService( std::unique_ptr task_runner) { return std::make_unique( std::move(task_runner), &fake_context_, mock_sharing_platform_, absl::WrapUnique(fake_nearby_connections_manager_), analytics_recorder_.get()); } void SetVisibility(DeviceVisibility visibility) { service_->GetSettings()->SetVisibility(visibility); FlushTesting(); } void SetFastInitiationNotificationState( FastInitiationNotificationState state) { service_->GetSettings()->SetFastInitiationNotificationState(state); FlushTesting(); } void SetBluetoothIsPresent(bool present) { FakeBluetoothAdapter& bluetooth_adapter = down_cast(fake_context_.GetBluetoothAdapter()); bluetooth_adapter.ReceivedAdapterPresentChangedFromOs(present); FlushTesting(); } void SetBluetoothIsPowered(bool powered) { FakeBluetoothAdapter& bluetooth_adapter = down_cast(fake_context_.GetBluetoothAdapter()); bluetooth_adapter.ReceivedAdapterPoweredChangedFromOs(powered); FlushTesting(); } void SetLanIsConnected(bool connected) { FakeConnectivityManager* connectivity_manager = down_cast( fake_context_.GetConnectivityManager()); connectivity_manager->SetLanConnected(connected); FlushTesting(); } void ReceiveMessageFromConnection(std::vector bytes) { sharing_service_task_runner_->PostTask([this, bytes]() { connection_->WriteMessage(bytes); }); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kWaitTimeout)); } void FastForward(absl::Duration duration) { fake_context_.fake_clock()->FastForward(duration); FlushTesting(); } void SetScreenLocked(bool locked) { fake_device_info_.SetScreenLocked(locked); FlushTesting(); } void StartIncomingConnection() { std::vector endpoint_info = CreateTestEndpointInfo(); fake_nearby_connections_manager_->AcceptConnection( endpoint_info, kEndpointId, connection_.get()); service_->OnIncomingConnection(kEndpointId, endpoint_info, connection_.get()); } NearbySharingService::StatusCodes RegisterSendSurface( TransferUpdateCallback* transfer_callback, ShareTargetDiscoveredCallback* discovery_callback, SendSurfaceState state, Advertisement::BlockedVendorId vendor_id = static_cast(kVendorId)) { NearbySharingService::StatusCodes result = NearbySharingService::StatusCodes::kError; absl::Notification notification; service_->RegisterSendSurface( transfer_callback, discovery_callback, state, vendor_id, /*disable_wifi_hotspot=*/false, [&](NearbySharingService::StatusCodes status_codes) { result = status_codes; notification.Notify(); }); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kTaskWaitTimeout)); return result; } NearbySharingService::StatusCodes UnregisterSendSurface( TransferUpdateCallback* transfer_callback) { NearbySharingService::StatusCodes result = NearbySharingService::StatusCodes::kError; absl::Notification notification; service_->UnregisterSendSurface( transfer_callback, [&](NearbySharingService::StatusCodes status_codes) { result = status_codes; notification.Notify(); }); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kTaskWaitTimeout)); return result; } NearbySharingService::StatusCodes RegisterReceiveSurface( TransferUpdateCallback* transfer_callback, NearbySharingService::ReceiveSurfaceState state, uint8_t vendor_id = kVendorId) { NearbySharingService::StatusCodes result = NearbySharingService::StatusCodes::kError; absl::Notification notification; service_->RegisterReceiveSurface( transfer_callback, state, static_cast(vendor_id), [&](NearbySharingService::StatusCodes status_codes) { result = status_codes; notification.Notify(); }); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kTaskWaitTimeout)); return result; } NearbySharingService::StatusCodes UnregisterReceiveSurface( TransferUpdateCallback* transfer_callback) { NearbySharingService::StatusCodes result = NearbySharingService::StatusCodes::kError; absl::Notification notification; service_->UnregisterReceiveSurface( transfer_callback, [&](NearbySharingService::StatusCodes status_codes) { result = status_codes; notification.Notify(); }); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kTaskWaitTimeout)); return result; } NearbySharingService::StatusCodes SendAttachments( int64_t share_target_id, std::unique_ptr attachment_container) { NearbySharingService::StatusCodes result = NearbySharingService::StatusCodes::kError; absl::Notification notification; service_->SendAttachments( share_target_id, std::move(attachment_container), [&](NearbySharingService::StatusCodes status_codes) { result = status_codes; notification.Notify(); }); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kTaskWaitTimeout)); return result; } void Shutdown() { if (is_shutdown_) { return; } is_shutdown_ = true; NearbySharingService::StatusCodes result = NearbySharingService::StatusCodes::kError; absl::Notification notification; service_->Shutdown([&](NearbySharingService::StatusCodes status_codes) { result = status_codes; notification.Notify(); }); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kTaskWaitTimeout)); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); } void SetUpForegroundReceiveSurface( NiceMock& callback) { NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } void SetUpBackgroundReceiveSurface( NiceMock& callback) { NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } void ProcessLatestPublicCertificateDecryption(size_t expected_num_calls, bool success, bool for_self_share = false, uint8_t vendor_id = 0) { // Ensure that all pending mojo messages are processed and the certificate // manager state is as expected up to this point. std::vector< FakeNearbyShareCertificateManager::GetDecryptedPublicCertificateCall>& calls = certificate_manager()->get_decrypted_public_certificate_calls(); ASSERT_FALSE(calls.empty()); EXPECT_EQ(calls.size(), expected_num_calls); EXPECT_EQ(GetNearbyShareTestEncryptedMetadataKey().salt(), calls.back().encrypted_metadata_key.salt()); EXPECT_EQ(GetNearbyShareTestEncryptedMetadataKey().encrypted_key(), calls.back().encrypted_metadata_key.encrypted_key()); if (success) { nearby::sharing::proto::PublicCertificate cert = GetNearbyShareTestPublicCertificate( DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS, GetNearbyShareTestNotBefore(), vendor_id); cert.set_for_self_share(for_self_share); std::move(calls.back().callback)( NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate( cert, GetNearbyShareTestEncryptedMetadataKey())); } else { std::move(calls.back().callback)(std::nullopt); } FlushTesting(); } void SetUpKeyVerification(bool is_incoming, PairedKeyResultFrame::Status status) { SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); local_device_data_manager()->SetDeviceName(kDeviceName); Frame frame; frame.set_version(Frame::V1); V1Frame* v1_frame = frame.mutable_v1(); v1_frame->set_type(V1Frame::PAIRED_KEY_ENCRYPTION); nearby::sharing::service::proto::PairedKeyEncryptionFrame* paired_key_encryption_frame = nearby::sharing::service::proto::PairedKeyEncryptionFrame:: default_instance() .New(); paired_key_encryption_frame->set_signed_data( is_incoming ? std::string(GetIncomingConnectionSignedData().begin(), GetIncomingConnectionSignedData().end()) : std::string(GetOutgoingConnectionSignedData().begin(), GetOutgoingConnectionSignedData().end())); paired_key_encryption_frame->set_secret_id_hash( std::string(GetPrivateCertificateHashAuthToken().begin(), GetPrivateCertificateHashAuthToken().end())); v1_frame->set_allocated_paired_key_encryption(paired_key_encryption_frame); std::vector encryption_bytes(frame.ByteSizeLong()); frame.SerializeToArray(encryption_bytes.data(), encryption_bytes.size()); ReceiveMessageFromConnection(std::move(encryption_bytes)); Frame result_frame; result_frame.set_version(Frame::V1); V1Frame* result_v1_frame = result_frame.mutable_v1(); result_v1_frame->set_type(V1Frame::PAIRED_KEY_RESULT); PairedKeyResultFrame* paired_key_result_frame = result_v1_frame->mutable_paired_key_result(); paired_key_result_frame->set_status(status); std::vector result_bytes(result_frame.ByteSizeLong()); result_frame.SerializeToArray(result_bytes.data(), result_bytes.size()); ReceiveMessageFromConnection(std::move(result_bytes)); } std::vector CreateTestEndpointInfo(uint8_t vendor_id = kVendorId) { std::unique_ptr advertisement = Advertisement::NewInstance( GetNearbyShareTestEncryptedMetadataKey().salt(), GetNearbyShareTestEncryptedMetadataKey().encrypted_key(), kDeviceType, kDeviceName, vendor_id); return advertisement->ToEndpointInfo(); } void SetUpIntroductionFrameDecoder(bool return_empty_introduction_frame) { std::unique_ptr frame; if (return_empty_introduction_frame) { frame = GetEmptyIntroductionFrame(); } else { frame = GetValidIntroductionFrame(); } std::vector bytes(frame->ByteSizeLong()); frame->SerializeToArray(bytes.data(), bytes.size()); ReceiveMessageFromConnection(std::move(bytes)); } void SendConnectionResponse(ConnectionResponseFrame::Status status) { std::unique_ptr frame = GetConnectionResponseFrame(status); std::vector bytes(frame->ByteSizeLong()); frame->SerializeToArray(bytes.data(), bytes.size()); ReceiveMessageFromConnection(std::move(bytes)); } void SendCancel() { std::unique_ptr frame = GetCancelFrame(); std::vector bytes(frame->ByteSizeLong()); frame->SerializeToArray(bytes.data(), bytes.size()); ReceiveMessageFromConnection(std::move(bytes)); } int64_t SetUpIncomingConnection( NiceMock& callback, bool is_foreground = true, bool for_self_share = false) { fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/false); int64_t share_target_id; SetConnectionType(ConnectionType::kWifi); absl::Notification notification; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& incoming_share_target, const AttachmentContainer& container, const TransferMetadata& metadata) { EXPECT_FALSE(metadata.is_final_status()); TransferMetadata::Status expected_status; if (for_self_share) { expected_status = TransferMetadata::Status::kAwaitingRemoteAcceptance; } else { expected_status = TransferMetadata::Status::kAwaitingLocalConfirmation; } EXPECT_EQ(metadata.status(), expected_status); share_target_id = incoming_share_target.id; notification.Notify(); })); SetUpKeyVerification( /*is_incoming=*/true, PairedKeyResultFrame::SUCCESS); if (is_foreground) { SetUpForegroundReceiveSurface(callback); } else { SetUpBackgroundReceiveSurface(callback); } EXPECT_CALL(*mock_app_info_, SetActiveFlag()); StartIncomingConnection(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true, for_self_share); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); return share_target_id; } void AcceptConnection(NiceMock& callback, int64_t share_target_id, absl::string_view endpoint_id) { // After accepting the transfer, we get another update of // kAwaitingRemoteAcceptance. EXPECT_CALL(callback, OnTransferUpdate( testing::_, testing::_, nearby::sharing::HasStatus( TransferMetadata::Status::kAwaitingRemoteAcceptance))); absl::Notification accept_notification; service_->Accept( share_target_id, [&accept_notification]( nearby::sharing::NearbySharingService::StatusCodes status_code) { EXPECT_EQ(status_code, NearbySharingServiceImpl::StatusCodes::kOk); accept_notification.Notify(); }); EXPECT_TRUE( accept_notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_TRUE( fake_nearby_connections_manager_->DidUpgradeBandwidth(endpoint_id)); } int64_t SetUpOutgoingShareTarget( MockTransferUpdateCallback& transfer_callback, MockShareTargetDiscoveredCallback& discovery_callback) { SetUpKeyVerification( /*is_incoming=*/false, PairedKeyResultFrame::SUCCESS); fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); fake_nearby_connections_manager_->set_nearby_connection(connection_.get()); return DiscoverShareTarget(transfer_callback, discovery_callback); } int64_t DiscoverShareTarget( MockTransferUpdateCallback& transfer_callback, MockShareTargetDiscoveredCallback& discovery_callback) { SetConnectionType(ConnectionType::kWifi); // Start discovering, to ensure a discovery listener is registered. EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); int64_t discovered_target_id; // Discover a new endpoint, with fields set up a valid certificate. EXPECT_CALL(discovery_callback, OnShareTargetDiscovered) .WillOnce([&discovered_target_id](ShareTarget share_target) { discovered_target_id = share_target.id; }); auto endpoint_info = std::make_unique( CreateTestEndpointInfo(), kServiceId); fake_nearby_connections_manager_->OnEndpointFound(kEndpointId, std::move(endpoint_info)); FlushTesting(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); return discovered_target_id; } std::unique_ptr GetWrittenFrame() { EXPECT_TRUE( sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); absl::MutexLock lock(connection_output_mutex_); std::unique_ptr frame = std::move(frames_data_.front()); frames_data_.pop(); return frame; } PayloadInfo GetWrittenPayload() { EXPECT_TRUE( sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); absl::MutexLock lock(connection_output_mutex_); PayloadInfo info = std::move(written_payloads_.front()); written_payloads_.pop(); return info; } bool ExpectPairedKeyEncryptionFrame() { std::unique_ptr frame = GetWrittenFrame(); if (!frame->has_v1()) { return false; } if (!frame->v1().has_paired_key_encryption()) { return false; } return true; } bool ExpectPairedKeyResultFrame() { std::unique_ptr frame = GetWrittenFrame(); if (!frame->has_v1()) { return false; } if (!frame->v1().has_paired_key_result()) { return false; } return true; } bool ExpectConnectionResponseFrame(ConnectionResponseFrame::Status status) { std::unique_ptr frame = GetWrittenFrame(); if (!frame->has_v1()) { return false; } if (!frame->v1().has_connection_response()) { return false; } if (status != frame->v1().connection_response().status()) { return false; } return true; } std::optional ExpectIntroductionFrame() { std::unique_ptr frame = GetWrittenFrame(); if (!frame->has_v1()) { return std::nullopt; } if (!frame->v1().has_introduction()) { return std::nullopt; } return frame->v1().introduction(); } bool ExpectCancelFrame() { std::unique_ptr frame = GetWrittenFrame(); if (!frame->has_v1()) { return false; } if (frame->v1().type() != V1Frame::CANCEL) { return false; } return true; } // Optionally, |new_share_target| is updated with the ShareTargets sent to // OnTransferUpdate() calls. void ExpectTransferUpdates( MockTransferUpdateCallback& transfer_callback, int64_t share_target_id, const std::vector& updates, std::function callback) { expect_transfer_updates_count_ = 0; expect_transfer_updates_callback_ = std::move(callback); auto& expectation = EXPECT_CALL(transfer_callback, OnTransferUpdate).Times(updates.size()); for (TransferMetadata::Status status : updates) { expectation.WillOnce(testing::Invoke( [this, share_target_id, status, update_size = updates.size()]( const ShareTarget& share_target, const AttachmentContainer& container, const TransferMetadata& metadata) { EXPECT_EQ(share_target.id, share_target_id); EXPECT_EQ(metadata.status(), status); ++expect_transfer_updates_count_; if (expect_transfer_updates_count_ == update_size) { expect_transfer_updates_callback_(); } })); } } // Returns the modified ShareTarget received from a TransferUpdate. void SetUpOutgoingConnectionUntilAccept( MockTransferUpdateCallback& transfer_callback, int64_t share_target_id) { ExpectTransferUpdates(transfer_callback, share_target_id, {TransferMetadata::Status::kConnecting, TransferMetadata::Status::kAwaitingRemoteAcceptance}, [] {}); absl::Notification send_notification; NearbySharingServiceImpl::StatusCodes send_result; EXPECT_CALL(*mock_app_info_, SetActiveFlag()); service_->SendAttachments( share_target_id, CreateTextAttachments({kTextPayload}), [&](NearbySharingServiceImpl::StatusCodes status_codes) { send_result = status_codes; send_notification.Notify(); }); EXPECT_TRUE( send_notification.WaitForNotificationWithTimeout(kTaskWaitTimeout)); EXPECT_EQ(send_result, NearbySharingServiceImpl::StatusCodes::kOk); FlushTesting(); // Verify data sent to the remote device so far. if (!ExpectPairedKeyEncryptionFrame()) { return; } if (!ExpectPairedKeyResultFrame()) { return; } if (!ExpectIntroductionFrame().has_value()) { return; } } PayloadInfo AcceptAndSendPayload( MockTransferUpdateCallback& transfer_callback, int64_t share_target_id) { // We're now waiting for the remote device to respond with the accept // result. ExpectTransferUpdates(transfer_callback, share_target_id, {TransferMetadata::Status::kInProgress}, [] {}); // Kick off send process by accepting the transfer from the remote device. SendConnectionResponse(ConnectionResponseFrame::ACCEPT); PayloadInfo info = GetWrittenPayload(); EXPECT_EQ(kTextPayload, std::string(info.payload->content.bytes_payload.bytes.begin(), info.payload->content.bytes_payload.bytes.end())); return info; } void FinishOutgoingTransfer(MockTransferUpdateCallback& transfer_callback, int64_t share_target_id, bool complete, const PayloadInfo& info) { // Simulate a successful transfer via Nearby Connections. ExpectTransferUpdates(transfer_callback, share_target_id, {TransferMetadata::Status::kInProgress, complete ? TransferMetadata::Status::kComplete : TransferMetadata::Status::kFailed}, [] {}); auto payload_transfer_update = std::make_unique( info.payload->id, PayloadStatus::kSuccess, /*total_bytes=*/strlen(kTextPayload), /*bytes_transferred=*/strlen(kTextPayload)); if (auto listener = info.listener.lock()) { listener->OnStatusUpdate(std::move(payload_transfer_update)); } EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kWaitTimeout)); } std::unique_ptr GetCurrentAdvertisement() { auto endpoint_info = fake_nearby_connections_manager_->advertising_endpoint_info(); if (!endpoint_info) return nullptr; return Advertisement::FromEndpointInfo(absl::MakeSpan( *fake_nearby_connections_manager_->advertising_endpoint_info())); } std::vector CreateInvalidTestEndpointInfo() { std::unique_ptr advertisement = Advertisement::NewInstance( GetNearbyShareTestEncryptedMetadataKey().salt(), GetNearbyShareTestEncryptedMetadataKey().encrypted_key(), kDeviceType, std::nullopt, kVendorId); return advertisement->ToEndpointInfo(); } void FindInvalidEndpoint(absl::string_view endpoint_id) { fake_nearby_connections_manager_->OnEndpointFound( endpoint_id, std::make_unique( CreateInvalidTestEndpointInfo(), kServiceId)); FlushTesting(); } void FindEndpoint(absl::string_view endpoint_id) { FindEndpointWithVendorId(endpoint_id, kVendorId); } void FindEndpointWithVendorId(absl::string_view endpoint_id, uint8_t vendor_id) { fake_nearby_connections_manager_->OnEndpointFound( endpoint_id, std::make_unique( CreateTestEndpointInfo(vendor_id), kServiceId)); FlushTesting(); } void LoseEndpoint(absl::string_view endpoint_id) { fake_nearby_connections_manager_->OnEndpointLost(endpoint_id); FlushTesting(); } // This method sets up an incoming connection and performs the steps // required to simulate a successful incoming transfer. void SuccessfullyReceiveTransfer() { NiceMock callback; int64_t share_target_id = SetUpIncomingConnection(callback); ScopedReceiveSurface r(service_.get(), &callback); AcceptConnection(callback, share_target_id, kEndpointId); // Fail to accept again. service_->Accept( share_target_id, [&](NearbySharingServiceImpl::StatusCodes status_code) { EXPECT_EQ(status_code, NearbySharingServiceImpl::StatusCodes::kOutOfOrderApiCall); }); fake_nearby_connections_manager_->SetIncomingPayload( kFilePayloadId, GetFilePayload(kFilePayloadId)); EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillRepeatedly( testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_FALSE(metadata.is_final_status()); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kInProgress); })); absl::Notification block_notification; // Block the service thread so all PayloadTransferUpdate will be processed // together.. sharing_service_task_runner_->PostTask([&block_notification]() { block_notification.WaitForNotificationWithTimeout(absl::Seconds(5)); }); for (int64_t id : GetValidIntroductionFramePayloadIds()) { // Update file payload at the end. if (id == kFilePayloadId) continue; fake_nearby_connections_manager_->SetIncomingPayload( id, GetTextPayload(id, kTextPayload)); std::weak_ptr listener = fake_nearby_connections_manager_->GetRegisteredPayloadStatusListener( id); PayloadTransferUpdate payload_update = PayloadTransferUpdate(id, PayloadStatus::kSuccess, /*total_bytes=*/kPayloadSize, /*bytes_transferred=*/kPayloadSize); if (auto locked_listener = listener.lock()) { locked_listener->OnStatusUpdate( std::make_unique(payload_update)); } } block_notification.Notify(); FlushTesting(); std::weak_ptr listener = fake_nearby_connections_manager_->GetRegisteredPayloadStatusListener( kFilePayloadId); FilePath file_path; absl::Notification success_notification; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(metadata.is_final_status()); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kComplete); ASSERT_TRUE(container.HasAttachments()); EXPECT_EQ(1u, container.GetFileAttachments().size()); for (const FileAttachment& file : container.GetFileAttachments()) { EXPECT_TRUE(file.file_path()); file_path = *file.file_path(); } EXPECT_EQ(3u, container.GetTextAttachments().size()); for (const TextAttachment& text : container.GetTextAttachments()) { EXPECT_EQ(text.text_body(), kTextPayload); } success_notification.Notify(); })); PayloadTransferUpdate payload = PayloadTransferUpdate(kFilePayloadId, PayloadStatus::kSuccess, /*total_bytes=*/kPayloadSize, /*bytes_transferred=*/kPayloadSize); if (auto locked_listener = listener.lock()) { locked_listener->OnStatusUpdate( std::make_unique(payload)); } FlushTesting(); EXPECT_TRUE( success_notification.WaitForNotificationWithTimeout(kWaitTimeout)); FlushTesting(); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); // connection has been closed, destroy it like the real connections manager. connection_.reset(); EXPECT_FALSE(fake_nearby_connections_manager_->has_incoming_payloads()); // Remove test file. Files::RemoveFile(file_path); } void FlushTesting() { absl::SleepFor(absl::Milliseconds(200)); EXPECT_TRUE( sharing_service_task_runner_->SyncWithTimeout(absl::Milliseconds(200))); } void SetDiskSpace(size_t size) { fake_device_info_.SetAvailableDiskSpaceInBytes( Files::GetTemporaryDirectory(), size); } void ResetDiskSpace() { fake_device_info_.ResetDiskSpace(); } protected: FakeNearbyShareLocalDeviceDataManager* local_device_data_manager() { EXPECT_EQ(local_device_data_manager_factory_.instances().size(), 1u); return local_device_data_manager_factory_.instances().back(); } FakeNearbyShareCertificateManager* certificate_manager() { EXPECT_EQ(certificate_manager_factory_.instances().size(), 1u); return certificate_manager_factory_.instances().back(); } FakeAccountManager& account_manager() { return fake_account_manager_; } FilePath CreateTestFile(absl::string_view name, const std::vector& content) { FilePath path = Files::GetTemporaryDirectory().append(FilePath(name)); std::ofstream file(path.GetPath(), std::ios_base::out | std::ios_base::trunc); if (file.good()) { file.write(reinterpret_cast(content.data()), content.size()); } file.close(); return path; } PreferenceManager& preference_manager() { return preference_manager_; } api::MockSharingPlatform mock_sharing_platform_; nearby::FakePreferenceManager preference_manager_; FakeAccountManager fake_account_manager_; FakeContext fake_context_; FakeDeviceInfo fake_device_info_; FakeNearbyConnectionsManager* fake_nearby_connections_manager_ = nullptr; FakeNearbyShareLocalDeviceDataManager::Factory local_device_data_manager_factory_; FakeNearbyShareContactManager::Factory contact_manager_factory_; FakeNearbyShareCertificateManager::Factory certificate_manager_factory_; std::unique_ptr nearby_fast_initiation_factory_; std::unique_ptr connection_; StrictMock* mock_app_info_ = nullptr; std::unique_ptr analytics_recorder_; std::unique_ptr service_; int expect_transfer_updates_count_ = 0; std::function expect_transfer_updates_callback_; FakeTaskRunner* sharing_service_task_runner_ = nullptr; bool is_shutdown_ = false; absl::Mutex connection_output_mutex_; std::queue> frames_data_ ABSL_GUARDED_BY(connection_output_mutex_); std::queue written_payloads_ ABSL_GUARDED_BY(connection_output_mutex_); }; struct ValidSendSurfaceTestData { bool bluetooth_enabled; ConnectionType connection_type; } kValidSendSurfaceTestData[] = { // No network connection, only bluetooth available {true, ConnectionType::kNone}, // Wifi available {true, ConnectionType::kWifi}, // Ethernet available {true, ConnectionType::kEthernet}, // 3G available {true, ConnectionType::k3G}}; class NearbySharingServiceImplValidSendTest : public NearbySharingServiceImplTest, public testing::WithParamInterface {}; struct InvalidSendSurfaceTestData { } kInvalidSendSurfaceTestData[] = { // Screen locked {/*screen_locked=*/}, // No network connection and no bluetooth {/*screen_locked=*/}, // 3G available and no bluetooth {/*screen_locked=*/}, // Wi-Fi available and no bluetooth (invalid until Wi-Fi LAN is supported) {/*screen_locked=*/}, // Ethernet available and no bluetooth (invalid until Wi-Fi LAN is // supported) {/*screen_locked=*/}}; using ResponseFrameStatus = ConnectionResponseFrame::Status; struct SendFailureTestData { ResponseFrameStatus response_status; TransferMetadata::Status expected_status; } kSendFailureTestData[] = { {service::proto::ConnectionResponseFrame::REJECT, TransferMetadata::Status::kRejected}, {service::proto::ConnectionResponseFrame::NOT_ENOUGH_SPACE, TransferMetadata::Status::kNotEnoughSpace}, {service::proto::ConnectionResponseFrame::UNSUPPORTED_ATTACHMENT_TYPE, TransferMetadata::Status::kUnsupportedAttachmentType}, {service::proto::ConnectionResponseFrame::TIMED_OUT, TransferMetadata::Status::kTimedOut}, {service::proto::ConnectionResponseFrame::UNKNOWN, TransferMetadata::Status::kFailed}, }; class NearbySharingServiceImplSendFailureTest : public NearbySharingServiceImplTest, public testing::WithParamInterface {}; class TestObserver : public NearbySharingService::Observer { public: explicit TestObserver(NearbySharingService* service) : service_(service) { service_->AddObserver(this); } ~TestObserver() override { // Check if Shutdown has been called. if (service_ != nullptr) { service_->RemoveObserver(this); } } void OnHighVisibilityChanged(bool in_high_visibility) override { in_high_visibility_ = in_high_visibility; } void OnStartAdvertisingFailure() override { on_start_advertising_failure_called_ = true; } void OnBluetoothStatusChanged(AdapterState state) override { bluetooth_state_ = state; } void OnLanStatusChanged(AdapterState state) override { lan_state_ = state; } void OnCredentialError() override { credential_error_called_ = true; } bool in_high_visibility_ = false; bool on_start_advertising_failure_called_ = false; bool credential_error_called_ = false; NearbySharingService* service_; AdapterState bluetooth_state_ = AdapterState::INVALID; AdapterState lan_state_ = AdapterState::INVALID; }; TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertising) { FakeNearbyFastInitiation* fast_initiation = nearby_fast_initiation_factory_->GetNearbyFastInitiation(); SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(fast_initiation->StartAdvertisingCount(), 1); // Call RegisterSendSurface a second time and make sure StartAdvertising is // not called again. EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kInvalidArgument); EXPECT_EQ(fast_initiation->StartAdvertisingCount(), 1); } TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertisingError) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; nearby_fast_initiation_factory_->GetNearbyFastInitiation() ->SetStartAdvertisingError(true); EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); } TEST_F(NearbySharingServiceImplTest, BackgroundStartFastInitiationAdvertisingError) { FakeNearbyFastInitiation* fast_initiation = nearby_fast_initiation_factory_->GetNearbyFastInitiation(); SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kBackground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(fast_initiation->StartAdvertisingCount(), 0); } TEST_F(NearbySharingServiceImplTest, StopFastInitiationAdvertising) { FakeNearbyFastInitiation* fast_initiation = nearby_fast_initiation_factory_->GetNearbyFastInitiation(); SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(fast_initiation->StartAdvertisingCount(), 1); EXPECT_EQ(UnregisterSendSurface(&transfer_callback), NearbySharingService::StatusCodes::kOk); EXPECT_EQ(fast_initiation->StartAdvertisingCount(), fast_initiation->StopAdvertisingCount()); } TEST_F(NearbySharingServiceImplTest, StopFastInitiationAdvertising_BluetoothBecomesNotPresent) { FakeNearbyFastInitiation* fast_initiation = nearby_fast_initiation_factory_->GetNearbyFastInitiation(); SetConnectionType(ConnectionType::kNone); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); SetBluetoothIsPresent(false); EXPECT_EQ(fast_initiation->StartAdvertisingCount(), 1); EXPECT_EQ(fast_initiation->StopAdvertisingCount(), 1); } TEST_F(NearbySharingServiceImplTest, StopFastInitiationAdvertising_BluetoothBecomesNotPowered) { FakeNearbyFastInitiation* fast_initiation = nearby_fast_initiation_factory_->GetNearbyFastInitiation(); SetConnectionType(ConnectionType::kNone); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); SetBluetoothIsPowered(false); EXPECT_EQ(fast_initiation->StartAdvertisingCount(), 1); EXPECT_EQ(fast_initiation->StopAdvertisingCount(), 1); } TEST_F(NearbySharingServiceImplTest, FastInitiationScanning_StartAndStop) { FakeNearbyFastInitiation* fast_initiation = nearby_fast_initiation_factory_->GetNearbyFastInitiation(); SetConnectionType(ConnectionType::kWifi); EXPECT_EQ(fast_initiation->StartScanningCount(), 1); EXPECT_EQ(fast_initiation->StopScanningCount(), 0); // Trigger a call to StopFastInitiationScanning(). SetBluetoothIsPowered(false); EXPECT_EQ(fast_initiation->StartScanningCount(), 1); EXPECT_EQ(fast_initiation->StopScanningCount(), 1); // Trigger a call to StartFastInitiationScanning(). SetBluetoothIsPowered(true); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); EXPECT_EQ(fast_initiation->StartScanningCount(), 2); EXPECT_EQ(fast_initiation->StopScanningCount(), 1); } TEST_F(NearbySharingServiceImplTest, FastInitiationScanning_PostTransferCooldown) { FakeNearbyFastInitiation* fast_initiation = nearby_fast_initiation_factory_->GetNearbyFastInitiation(); SetConnectionType(ConnectionType::kBluetooth); // Make sure we started scanning once EXPECT_EQ(fast_initiation->StartScanningCount(), 1); EXPECT_EQ(fast_initiation->StopScanningCount(), 0); SuccessfullyReceiveTransfer(); // Make sure we stopped scanning and didn't restart... yet. EXPECT_EQ(fast_initiation->StartScanningCount(), 1); EXPECT_EQ(fast_initiation->StopScanningCount(), 1); // Fast-forward 10s to pass through the cooldown period. FastForward(absl::Seconds(10)); // Make sure we restarted Fast Initiation scanning. EXPECT_EQ(fast_initiation->StartScanningCount(), 2); EXPECT_EQ(fast_initiation->StopScanningCount(), 1); } TEST_F(NearbySharingServiceImplTest, ForegroundRegisterSendSurfaceStartsDiscovering) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); } TEST_F(NearbySharingServiceImplTest, ForegroundRegisterSendSurfaceTwiceKeepsDiscovering) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kInvalidArgument); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); } TEST_F(NearbySharingServiceImplTest, RegisterSendSurfaceAlreadyReceivingNotDiscovering) { NiceMock callback; int64_t share_target_id = SetUpIncomingConnection(callback); ScopedReceiveSurface r(service_.get(), &callback); AcceptConnection(callback, share_target_id, kEndpointId); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); MockTransferUpdateCallback send_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&send_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kTransferAlreadyInProgress); EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); } TEST_F(NearbySharingServiceImplTest, BackgroundRegisterSendSurfaceNotDiscovering) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kBackground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); } TEST_F(NearbySharingServiceImplTest, DifferentSurfaceRegisterSendSurfaceTwiceKeepsDiscovering) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kBackground), NearbySharingService::StatusCodes::kInvalidArgument); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); } TEST_F(NearbySharingServiceImplTest, RegisterSendSurfaceEndpointFoundDiscoveryCallbackNotified) { SetConnectionType(ConnectionType::kWifi); // Start discovering, to ensure a discovery listener is registered. MockTransferUpdateCallback transfer_callback; NiceMock discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); // Discover a new endpoint, with fields set up a valid certificate. EXPECT_CALL(discovery_callback, OnShareTargetDiscovered) .WillOnce([&](ShareTarget share_target) { EXPECT_FALSE(share_target.is_incoming); EXPECT_TRUE(share_target.is_known); EXPECT_EQ(share_target.device_name, kDeviceName); EXPECT_EQ(share_target.type, kDeviceType); EXPECT_TRUE(share_target.device_id); EXPECT_NE(share_target.device_id, kEndpointId); EXPECT_EQ(share_target.full_name, kTestMetadataFullName); }); fake_nearby_connections_manager_->OnEndpointFound( kEndpointId, std::make_unique( CreateTestEndpointInfo(), kServiceId)); FlushTesting(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); // Register another send surface, which will automatically catch up // discovered endpoints. MockTransferUpdateCallback transfer_callback2; NiceMock discovery_callback2; EXPECT_CALL(discovery_callback2, OnShareTargetDiscovered) .WillOnce([&](ShareTarget share_target) { EXPECT_EQ(share_target.device_name, kDeviceName); }); EXPECT_EQ(RegisterSendSurface(&transfer_callback2, &discovery_callback2, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s2(service_.get(), &transfer_callback2); // Shut down the service while the discovery callbacks are still in // scope. OnShareTargetLost() will be invoked during shutdown. Shutdown(); } TEST_F(NearbySharingServiceImplTest, RegisterSendSurfaceEmptyCertificate) { SetConnectionType(ConnectionType::kWifi); // Start discovering, to ensure a discovery listener is registered. MockTransferUpdateCallback transfer_callback; NiceMock discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); // Discover a new endpoint, with fields set up a valid certificate. EXPECT_CALL(discovery_callback, OnShareTargetDiscovered) .WillOnce([](ShareTarget share_target) { EXPECT_FALSE(share_target.is_incoming); EXPECT_FALSE(share_target.is_known); EXPECT_EQ(share_target.device_name, kDeviceName); EXPECT_FALSE(share_target.image_url); EXPECT_EQ(share_target.type, kDeviceType); EXPECT_TRUE(share_target.device_id); EXPECT_EQ(share_target.device_id, kEndpointId); EXPECT_FALSE(share_target.full_name); }); fake_nearby_connections_manager_->OnEndpointFound( kEndpointId, std::make_unique( CreateTestEndpointInfo(), kServiceId)); FlushTesting(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/false); // Register another send surface, which will automatically catch up // discovered endpoints. MockTransferUpdateCallback transfer_callback2; NiceMock discovery_callback2; EXPECT_CALL(discovery_callback2, OnShareTargetDiscovered) .WillOnce([](ShareTarget share_target) { EXPECT_EQ(share_target.device_name, kDeviceName); }); EXPECT_EQ(RegisterSendSurface(&transfer_callback2, &discovery_callback2, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s2(service_.get(), &transfer_callback2); // Shut down the service while the discovery callbacks are still in scope. // OnShareTargetLost() will be invoked during shutdown. Shutdown(); } TEST_P(NearbySharingServiceImplValidSendTest, RegisterSendSurfaceIsDiscovering) { SetBluetoothIsPresent(GetParam().bluetooth_enabled); SetConnectionType(GetParam().connection_type); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); FlushTesting(); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); } INSTANTIATE_TEST_SUITE_P(NearbySharingServiceImplTest, NearbySharingServiceImplValidSendTest, testing::ValuesIn(kValidSendSurfaceTestData)); TEST_F(NearbySharingServiceImplTest, UnregisterSendSurfaceStopsDiscovering) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); EXPECT_EQ(UnregisterSendSurface(&transfer_callback), NearbySharingService::StatusCodes::kOk); EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); } TEST_F(NearbySharingServiceImplTest, UnregisterSendSurfaceDifferentCallbackKeepDiscovering) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); MockTransferUpdateCallback transfer_callback2; MockShareTargetDiscoveredCallback discovery_callback2; EXPECT_EQ(UnregisterSendSurface(&transfer_callback2), NearbySharingService::StatusCodes::kError); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); } TEST_F(NearbySharingServiceImplTest, UnregisterSendSurfaceNeverRegistered) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(UnregisterSendSurface(&transfer_callback), NearbySharingService::StatusCodes::kError); EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); } TEST_F(NearbySharingServiceImplTest, ForegroundRegisterReceiveSurfaceIsAdvertisingAllContacts) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); ::nearby::AccountManager::Account account; account.id = kTestAccountId; account_manager().SetAccount(account); local_device_data_manager()->SetDeviceName(kDeviceName); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_EQ(fake_nearby_connections_manager_->advertising_power_level(), PowerLevel::kHighPower); ASSERT_TRUE(fake_nearby_connections_manager_->advertising_endpoint_info()); std::unique_ptr advertisement = GetCurrentAdvertisement(); ASSERT_NE(advertisement, nullptr); EXPECT_EQ(advertisement->device_name(), std::nullopt); EXPECT_EQ(advertisement->device_type(), ShareTargetType::kLaptop); auto& test_metadata_key = GetNearbyShareTestEncryptedMetadataKey(); EXPECT_EQ(test_metadata_key.salt(), advertisement->salt()); EXPECT_EQ(test_metadata_key.encrypted_key(), advertisement->encrypted_metadata_key()); account_manager().SetAccount(std::nullopt); } TEST_F(NearbySharingServiceImplTest, ForegroundRegisterReceiveSurfaceIsAdvertisingNoOne) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE); local_device_data_manager()->SetDeviceName(kDeviceName); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_EQ(PowerLevel::kHighPower, fake_nearby_connections_manager_->advertising_power_level()); ASSERT_TRUE(fake_nearby_connections_manager_->advertising_endpoint_info()); std::unique_ptr advertisement = GetCurrentAdvertisement(); ASSERT_NE(advertisement, nullptr); EXPECT_EQ(advertisement->device_name(), std::nullopt); EXPECT_EQ(ShareTargetType::kLaptop, advertisement->device_type()); // Expecting random metadata key. EXPECT_EQ(static_cast(sharing::Advertisement::kSaltSize), advertisement->salt().size()); EXPECT_EQ(static_cast( sharing::Advertisement::kMetadataEncryptionKeyHashByteSize), advertisement->encrypted_metadata_key().size()); } TEST_F(NearbySharingServiceImplTest, BackgroundRegisterReceiveSurfaceIsAdvertisingSelectedContacts) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_SELECTED_CONTACTS); ::nearby::AccountManager::Account account; account.id = kTestAccountId; account_manager().SetAccount(account); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_EQ(PowerLevel::kLowPower, fake_nearby_connections_manager_->advertising_power_level()); ASSERT_TRUE(fake_nearby_connections_manager_->advertising_endpoint_info()); std::unique_ptr advertisement = GetCurrentAdvertisement(); ASSERT_NE(advertisement, nullptr); EXPECT_FALSE(advertisement->device_name()); EXPECT_EQ(ShareTargetType::kLaptop, advertisement->device_type()); auto& test_metadata_key = GetNearbyShareTestEncryptedMetadataKey(); EXPECT_EQ(test_metadata_key.salt(), advertisement->salt()); EXPECT_EQ(test_metadata_key.encrypted_key(), advertisement->encrypted_metadata_key()); account_manager().SetAccount(std::nullopt); } TEST_F(NearbySharingServiceImplTest, RegisterReceiveSurfaceTwiceSameCallbackKeepAdvertising) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); NearbySharingService::StatusCodes result2 = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result2, NearbySharingService::StatusCodes::kOk); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, RegisterReceiveSurfaceTwiceKeepAdvertising) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); MockTransferUpdateCallback callback2; NearbySharingService::StatusCodes result2 = RegisterReceiveSurface( &callback2, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result2, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r2(service_.get(), &callback2); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, DataUsageChangedRegisterReceiveSurfaceRestartsAdvertising) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); preference_manager().SetInteger( prefs::kNearbySharingDataUsageName, static_cast(DataUsage::OFFLINE_DATA_USAGE)); FlushTesting(); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_EQ(DataUsage::OFFLINE_DATA_USAGE, fake_nearby_connections_manager_->advertising_data_usage()); preference_manager().SetInteger( prefs::kNearbySharingDataUsageName, static_cast(DataUsage::ONLINE_DATA_USAGE)); FlushTesting(); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_EQ(DataUsage::ONLINE_DATA_USAGE, fake_nearby_connections_manager_->advertising_data_usage()); } TEST_F( NearbySharingServiceImplTest, UnregisterForegroundReceiveSurfaceVisibilityAllContactsRestartAdvertising) { TestObserver observer(service_.get()); SetConnectionType(ConnectionType::kWifi); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS)); FlushTesting(); // Register both foreground and background receive surfaces MockTransferUpdateCallback background_transfer_callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &background_transfer_callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &background_transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); MockTransferUpdateCallback foreground_transfer_callback; result = RegisterReceiveSurface( &foreground_transfer_callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r2(service_.get(), &foreground_transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); // Unregister the foreground surface. Advertising is stopped and restarted // with low power. The service reports InHighVisibility until the // StopAdvertising callback is called. FakeNearbyConnectionsManager::ConnectionsCallback stop_advertising_callback = fake_nearby_connections_manager_->GetStopAdvertisingCallback(); FakeNearbyConnectionsManager::ConnectionsCallback start_advertising_callback = fake_nearby_connections_manager_->GetStartAdvertisingCallback(); result = UnregisterReceiveSurface(&foreground_transfer_callback); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_FALSE(observer.in_high_visibility_); std::move(stop_advertising_callback)(ConnectionsStatus::kSuccess); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_FALSE(observer.in_high_visibility_); std::move(start_advertising_callback)(ConnectionsStatus::kSuccess); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_FALSE(observer.in_high_visibility_); } TEST_F(NearbySharingServiceImplTest, RegisterReceiveSurfaceWithVendorId_StartAdvertisingVendorId) { SetConnectionType(ConnectionType::kWifi); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_EVERYONE)); FlushTesting(); // Register background receive surface with vendor ID 1. MockTransferUpdateCallback background_transfer_callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &background_transfer_callback, NearbySharingService::ReceiveSurfaceState::kBackground, static_cast(Advertisement::BlockedVendorId::kSamsung)); ASSERT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &background_transfer_callback); ASSERT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); auto endpoint_info = fake_nearby_connections_manager_->advertising_endpoint_info(); auto advertisement = Advertisement::FromEndpointInfo(*endpoint_info); EXPECT_EQ(advertisement->vendor_id(), static_cast(Advertisement::BlockedVendorId::kSamsung)); } TEST_F(NearbySharingServiceImplTest, RegisterReceiveSurfaceWithVendorId_DoesNotAdvertiseInContacts) { SetConnectionType(ConnectionType::kWifi); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS)); FlushTesting(); // Register background receive surface with vendor ID 1. MockTransferUpdateCallback background_transfer_callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &background_transfer_callback, NearbySharingService::ReceiveSurfaceState::kBackground, static_cast(Advertisement::BlockedVendorId::kSamsung)); ASSERT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &background_transfer_callback); ASSERT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); auto endpoint_info = fake_nearby_connections_manager_->advertising_endpoint_info(); auto advertisement = Advertisement::FromEndpointInfo(*endpoint_info); EXPECT_EQ(advertisement->vendor_id(), static_cast(Advertisement::BlockedVendorId::kNone)); } TEST_F(NearbySharingServiceImplTest, RegisterReceiveSurfaceWithDifferentVendorIdIsBlocked) { SetConnectionType(ConnectionType::kWifi); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS)); FlushTesting(); // Register background receive surface with vendor ID 1. MockTransferUpdateCallback background_transfer_callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &background_transfer_callback, NearbySharingService::ReceiveSurfaceState::kBackground, static_cast(Advertisement::BlockedVendorId::kSamsung)); ASSERT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &background_transfer_callback); ASSERT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); // Register foreground receive surface with different vendor ID. MockTransferUpdateCallback foreground_transfer_callback; result = RegisterReceiveSurface( &foreground_transfer_callback, NearbySharingService::ReceiveSurfaceState::kForeground, /*vendor_id=*/2); EXPECT_EQ(result, NearbySharingService::StatusCodes::kInvalidArgument); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, RegisterReceiveSurfaceWithVendorId_OkWithBgNoVendorId) { SetConnectionType(ConnectionType::kWifi); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_EVERYONE)); FlushTesting(); // Register background receive surface with vendor ID 0. MockTransferUpdateCallback background_transfer_callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &background_transfer_callback, NearbySharingService::ReceiveSurfaceState::kBackground, static_cast(Advertisement::BlockedVendorId::kNone)); ASSERT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &background_transfer_callback); ASSERT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); // Register foreground receive surface with vendor ID 1. MockTransferUpdateCallback foreground_transfer_callback; result = RegisterReceiveSurface( &foreground_transfer_callback, NearbySharingService::ReceiveSurfaceState::kForeground, static_cast(Advertisement::BlockedVendorId::kSamsung)); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r2(service_.get(), &foreground_transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); // Verify endpoint info is advertising the foreground surface. auto endpoint_info = fake_nearby_connections_manager_->advertising_endpoint_info(); auto advertisement = Advertisement::FromEndpointInfo(*endpoint_info); EXPECT_EQ(advertisement->vendor_id(), static_cast(Advertisement::BlockedVendorId::kSamsung)); } TEST_F(NearbySharingServiceImplTest, NoNetworkRegisterReceiveSurfaceIsAdvertising) { MockTransferUpdateCallback callback; SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); // Succeeds since bluetooth is present. EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, WifiRegisterReceiveSurfaceIsAdvertising) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, EthernetRegisterReceiveSurfaceIsAdvertising) { SetConnectionType(ConnectionType::kEthernet); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, ThreeGRegisterReceiveSurfaceIsAdvertising) { SetConnectionType(ConnectionType::k3G); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); // Since bluetooth is on, connection still succeeds. EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, NoBluetoothWifiReceiveSurfaceIsAdvertising) { SetBluetoothIsPresent(false); SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, NoBluetoothEthernetReceiveSurfaceIsAdvertising) { SetBluetoothIsPresent(false); SetConnectionType(ConnectionType::kEthernet); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, ForegroundReceiveSurfaceNoOneVisibilityIsAdvertising) { SetConnectionType(ConnectionType::kWifi); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE)); FlushTesting(); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, BackgroundReceiveSurfaceNoOneVisibilityNotAdvertising) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_UNSPECIFIED)); FlushTesting(); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); } TEST_F(NearbySharingServiceImplTest, BackgroundReceiveSurfaceVisibilityToNoOneStopsAdvertising) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_SELECTED_CONTACTS); FlushTesting(); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_HIDDEN)); FlushTesting(); EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); } TEST_F(NearbySharingServiceImplTest, ValidateLoginStateWhenSettingVisibility) { absl::Notification set_visibility_notification; NearbySharingService::StatusCodes set_visibility_status; SetConnectionType(ConnectionType::kWifi); FlushTesting(); service_->SetVisibility( DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS, absl::ZeroDuration(), [&set_visibility_notification, &set_visibility_status](NearbySharingService::StatusCodes status) { set_visibility_status = status; set_visibility_notification.Notify(); }); // We should not have been able to set all contacts visibility because we are // not logged in. ASSERT_TRUE( set_visibility_notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_EQ(set_visibility_status, NearbySharingService::StatusCodes::kInvalidArgument); // Create account. AccountManager::Account account; account.id = kTestAccountId; // Log in. account_manager().SetAccount(account); std::unique_ptr signin_attempt = service_->GetAccountManager()->Login("test_client_id", "test_client_secret"); account_manager().NotifyLogin(kTestAccountId); // We are now logged in, so we should be able to set all contacts visibility. absl::Notification set_visibility_notification2; NearbySharingService::StatusCodes set_visibility_status2; service_->SetVisibility( DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS, absl::ZeroDuration(), [&set_visibility_notification2, &set_visibility_status2](NearbySharingService::StatusCodes status) { set_visibility_status2 = status; set_visibility_notification2.Notify(); }); ASSERT_TRUE(set_visibility_notification2.WaitForNotificationWithTimeout( kWaitTimeout)); EXPECT_EQ(set_visibility_status2, NearbySharingService::StatusCodes::kOk); } TEST_F(NearbySharingServiceImplTest, BackgroundReceiveSurfaceVisibilityToAllContactsStartsAdvertising) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_UNSPECIFIED); FlushTesting(); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); FlushTesting(); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, ForegroundReceiveSurfaceSelectedContactsVisibilityIsAdvertising) { SetConnectionType(ConnectionType::kWifi); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_SELECTED_CONTACTS)); FlushTesting(); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, BackgroundReceiveSurfaceSelectedContactsVisibilityIsAdvertising) { SetConnectionType(ConnectionType::kWifi); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_SELECTED_CONTACTS)); FlushTesting(); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, ForegroundReceiveSurfaceAllContactsVisibilityIsAdvertising) { SetConnectionType(ConnectionType::kWifi); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS)); FlushTesting(); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, BackgroundReceiveSurfaceAllContactsVisibilityNotAdvertising) { SetConnectionType(ConnectionType::kWifi); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS)); FlushTesting(); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, UnregisterReceiveSurfaceStopsAdvertising) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); NearbySharingService::StatusCodes result2 = UnregisterReceiveSurface(&callback); EXPECT_EQ(result2, NearbySharingService::StatusCodes::kOk); EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); } TEST_F(NearbySharingServiceImplTest, UnregisterReceiveSurfaceDifferentCallbackKeepAdvertising) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); MockTransferUpdateCallback callback2; NearbySharingService::StatusCodes result2 = UnregisterReceiveSurface(&callback2); EXPECT_EQ(result2, NearbySharingService::StatusCodes::kOk); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, UnregisterReceiveSurfaceNeverRegistered) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = UnregisterReceiveSurface(&callback); // This is no longer considered an error condition. EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionClosedAfterShutdown) { fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); SetConnectionType(ConnectionType::kWifi); NiceMock callback; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .Times(0); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); Shutdown(); StartIncomingConnection(); sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionClosedBeforeCertDecryption) { fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); NiceMock callback; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(metadata.is_final_status()); EXPECT_EQ(TransferMetadata::Status::kFailed, metadata.status()); })); SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); StartIncomingConnection(); sharing_service_task_runner_->PostTask( [this]() { fake_nearby_connections_manager_->Disconnect(kEndpointId); // FakeNearbyConnectionsManager does not delete the connection on close. connection_.reset(); }); sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionClosedReadingIntroduction) { fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); SetConnectionType(ConnectionType::kWifi); NiceMock callback; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(metadata.is_final_status()); EXPECT_EQ(TransferMetadata::Status::kFailed, metadata.status()); })); SetUpKeyVerification(/*is_incoming=*/true, service::proto::PairedKeyResultFrame::SUCCESS); SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); StartIncomingConnection(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); sharing_service_task_runner_->PostTask([this]() { fake_nearby_connections_manager_->Disconnect(kEndpointId); // FakeNearbyConnectionsManager does not delete the connection on close. connection_.reset(); }); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionEmptyIntroductionFrame) { fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/true); SetConnectionType(ConnectionType::kWifi); NiceMock callback; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(metadata.is_final_status()); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kUnsupportedAttachmentType); EXPECT_TRUE(share_target.is_incoming); EXPECT_TRUE(share_target.is_known); EXPECT_FALSE(container.HasAttachments()); EXPECT_EQ(share_target.device_name, kDeviceName); EXPECT_EQ(share_target.type, kDeviceType); EXPECT_TRUE(share_target.device_id); EXPECT_NE(share_target.device_id, kEndpointId); EXPECT_EQ(share_target.full_name, kTestMetadataFullName); })); SetUpKeyVerification(/*is_incoming=*/true, service::proto::PairedKeyResultFrame::SUCCESS); SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); StartIncomingConnection(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); // Check data written to connection_. ASSERT_TRUE(ExpectPairedKeyEncryptionFrame()); ASSERT_TRUE(ExpectPairedKeyResultFrame()); ASSERT_TRUE(ExpectConnectionResponseFrame( service::proto::ConnectionResponseFrame::UNSUPPORTED_ATTACHMENT_TYPE)); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionValidIntroductionFrameInvalidCertificate) { fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/false); SetConnectionType(ConnectionType::kWifi); NiceMock callback; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_FALSE(metadata.is_final_status()); EXPECT_EQ(TransferMetadata::Status::kAwaitingLocalConfirmation, metadata.status()); EXPECT_TRUE(share_target.is_incoming); EXPECT_FALSE(share_target.is_known); EXPECT_TRUE(container.HasAttachments()); EXPECT_EQ(container.GetTextAttachments().size(), 3u); EXPECT_EQ(container.GetFileAttachments().size(), 1u); EXPECT_EQ(share_target.device_name, kDeviceName); EXPECT_FALSE(share_target.image_url); EXPECT_EQ(share_target.type, kDeviceType); EXPECT_EQ(share_target.device_id, kEndpointId); EXPECT_FALSE(share_target.full_name); })); SetUpKeyVerification(/*is_incoming=*/true, service::proto::PairedKeyResultFrame::SUCCESS); SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); StartIncomingConnection(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/false); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionTimedOut) { NiceMock callback; SetUpIncomingConnection(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(metadata.is_final_status()); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kTimedOut); })); FastForward(kReadResponseFrameTimeout); // Waits for delay to close connection. FastForward(kIncomingRejectionDelay); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionClosedWaitingLocalConfirmation) { NiceMock callback; SetUpIncomingConnection(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(metadata.is_final_status()); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kFailed); })); sharing_service_task_runner_->PostTask( [this]() { fake_nearby_connections_manager_->Disconnect(kEndpointId); // FakeNearbyConnectionsManager does not delete the connection on close. connection_.reset(); }); sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionOutOfStorage) { SetDiskSpace(kFreeDiskSpace); preference_manager().SetString( prefs::kNearbySharingCustomSavePath, fake_device_info_.GetDownloadPath().ToString()); fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); // Set a huge file size in introduction frame to go out of storage. Frame frame; frame.set_version(Frame::V1); V1Frame* v1_frame = frame.mutable_v1(); v1_frame->set_type(V1Frame::INTRODUCTION); IntroductionFrame* introduction_frame = v1_frame->mutable_introduction(); nearby::sharing::service::proto::FileMetadata* file_metadata = introduction_frame->add_file_metadata(); file_metadata->set_name("name"); file_metadata->set_type(nearby::sharing::service::proto::FileMetadata::AUDIO); file_metadata->set_payload_id(1); file_metadata->set_size(kFreeDiskSpace + 1); file_metadata->set_mime_type("mime type"); file_metadata->set_id(123); std::vector bytes(frame.ByteSizeLong()); frame.SerializeToArray(bytes.data(), bytes.size()); ReceiveMessageFromConnection(std::move(bytes)); SetConnectionType(ConnectionType::kWifi); NiceMock callback; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(share_target.is_incoming); EXPECT_TRUE(share_target.is_known); EXPECT_TRUE(container.HasAttachments()); EXPECT_EQ(container.GetTextAttachments().size(), 0u); EXPECT_EQ(container.GetFileAttachments().size(), 1u); EXPECT_EQ(share_target.device_name, kDeviceName); EXPECT_EQ(share_target.type, kDeviceType); EXPECT_TRUE(share_target.device_id); EXPECT_NE(share_target.device_id, kEndpointId); EXPECT_EQ(share_target.full_name, kTestMetadataFullName); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kNotEnoughSpace); })); SetUpKeyVerification( /*is_incoming=*/true, PairedKeyResultFrame::SUCCESS); SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); StartIncomingConnection(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); ResetDiskSpace(); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionFileSizeOverflow) { fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); // Set file size sum huge to check for overflow. Frame frame; frame.set_version(Frame::V1); V1Frame* v1_frame = frame.mutable_v1(); v1_frame->set_type(V1Frame::INTRODUCTION); IntroductionFrame* introduction_frame = v1_frame->mutable_introduction(); nearby::sharing::service::proto::FileMetadata* file_metadata = introduction_frame->add_file_metadata(); file_metadata->set_name("name_1"); file_metadata->set_type(nearby::sharing::service::proto::FileMetadata::AUDIO); file_metadata->set_payload_id(1); file_metadata->set_size(std::numeric_limits::max()); file_metadata->set_mime_type("mime type"); file_metadata->set_id(123); nearby::sharing::service::proto::FileMetadata* file2_metadata = introduction_frame->add_file_metadata(); file2_metadata->set_name("name_2"); file2_metadata->set_type( nearby::sharing::service::proto::FileMetadata::VIDEO); file2_metadata->set_payload_id(2); file2_metadata->set_size(100); file2_metadata->set_mime_type("mime type"); file2_metadata->set_id(124); std::vector bytes(frame.ByteSizeLong()); frame.SerializeToArray(bytes.data(), bytes.size()); ReceiveMessageFromConnection(std::move(bytes)); SetConnectionType(ConnectionType::kWifi); NiceMock callback; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(share_target.is_incoming); EXPECT_TRUE(share_target.is_known); EXPECT_EQ(share_target.device_name, kDeviceName); EXPECT_EQ(share_target.type, kDeviceType); EXPECT_TRUE(share_target.device_id); EXPECT_NE(share_target.device_id, kEndpointId); EXPECT_EQ(share_target.full_name, kTestMetadataFullName); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kNotEnoughSpace); })); SetUpKeyVerification( /*is_incoming=*/true, PairedKeyResultFrame::SUCCESS); SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); StartIncomingConnection(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionValidIntroductionFrameValidCertificate) { fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/false); SetConnectionType(ConnectionType::kWifi); NiceMock callback; absl::Notification notification; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce( testing::Invoke([¬ification](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_FALSE(metadata.is_final_status()); EXPECT_EQ(TransferMetadata::Status::kAwaitingLocalConfirmation, metadata.status()); EXPECT_TRUE(share_target.is_incoming); EXPECT_TRUE(share_target.is_known); EXPECT_TRUE(container.HasAttachments()); EXPECT_EQ(container.GetTextAttachments().size(), 3u); EXPECT_EQ(container.GetFileAttachments().size(), 1u); EXPECT_EQ(share_target.device_name, kDeviceName); EXPECT_EQ(share_target.type, kDeviceType); EXPECT_TRUE(share_target.device_id); EXPECT_NE(share_target.device_id, kEndpointId); EXPECT_EQ(share_target.full_name, kTestMetadataFullName); EXPECT_FALSE(share_target.for_self_share); EXPECT_FALSE(metadata.is_self_share()); EXPECT_TRUE(metadata.token().has_value()); notification.Notify(); })); SetUpKeyVerification(/*is_incoming=*/true, PairedKeyResultFrame::SUCCESS); SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); StartIncomingConnection(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, AcceptInvalidShareTarget) { absl::Notification notification; service_->Accept( 98765L, [&](NearbySharingServiceImpl::StatusCodes status_code) { EXPECT_EQ(status_code, NearbySharingServiceImpl::StatusCodes::kInvalidArgument); notification.Notify(); }); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } TEST_F(NearbySharingServiceImplTest, AcceptValidShareTarget) { NiceMock callback; int64_t share_target_id = SetUpIncomingConnection(callback); ScopedReceiveSurface r(service_.get(), &callback); AcceptConnection(callback, share_target_id, kEndpointId); // Check data written to connection_. EXPECT_TRUE(ExpectPairedKeyEncryptionFrame()); EXPECT_TRUE(ExpectPairedKeyResultFrame()); EXPECT_TRUE(ExpectConnectionResponseFrame( service::proto::ConnectionResponseFrame::ACCEPT)); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, AcceptValidShareTargetPayloadSuccessful) { SuccessfullyReceiveTransfer(); } TEST_F(NearbySharingServiceImplTest, AcceptValidShareTargetPayloadSuccessfulIncomingPayloadNotFound) { NiceMock callback; int64_t share_target_id = SetUpIncomingConnection(callback); ScopedReceiveSurface r(service_.get(), &callback); AcceptConnection(callback, share_target_id, kEndpointId); fake_nearby_connections_manager_->SetIncomingPayload( kFilePayloadId, GetFilePayload(kFilePayloadId)); for (int64_t id : GetValidIntroductionFramePayloadIds()) { // Update file payload at the end. if (id == kFilePayloadId) continue; // Deliberately not calling SetIncomingPayload() for text payloads to check // for failure condition. absl::Notification progress_notification; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_FALSE(metadata.is_final_status()); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kInProgress); progress_notification.Notify(); })); std::weak_ptr listener = fake_nearby_connections_manager_->GetRegisteredPayloadStatusListener( id); ASSERT_FALSE(listener.expired()); auto payload = std::make_unique( id, PayloadStatus::kSuccess, /*total_bytes=*/kPayloadSize, /*bytes_transferred=*/kPayloadSize); if (auto locked_listener = listener.lock()) { locked_listener->OnStatusUpdate(std::move(payload)); } FlushTesting(); EXPECT_TRUE( progress_notification.WaitForNotificationWithTimeout(kWaitTimeout)); } absl::Notification success_notification; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(metadata.is_final_status()); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kIncompletePayloads); ASSERT_TRUE(container.HasAttachments()); EXPECT_EQ(container.GetFileAttachments().size(), 1u); const FileAttachment& file = container.GetFileAttachments()[0]; EXPECT_FALSE(file.file_path()); success_notification.Notify(); })); std::weak_ptr listener = fake_nearby_connections_manager_->GetRegisteredPayloadStatusListener( kFilePayloadId); ASSERT_FALSE(listener.expired()); auto payload = std::make_unique( kFilePayloadId, PayloadStatus::kSuccess, /*total_bytes=*/kPayloadSize, /*bytes_transferred=*/kPayloadSize); if (auto locked_listener = listener.lock()) { locked_listener->OnStatusUpdate(std::move(payload)); } EXPECT_TRUE( success_notification.WaitForNotificationWithTimeout(kWaitTimeout)); FlushTesting(); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); EXPECT_FALSE(fake_nearby_connections_manager_->has_incoming_payloads()); // File deletion runs in a ThreadPool. EXPECT_TRUE( sharing_service_task_runner_->SyncWithTimeout(absl::Milliseconds(200))); } TEST_F(NearbySharingServiceImplTest, AcceptValidShareTargetPayloadFailed) { NiceMock callback; int64_t share_target_id = SetUpIncomingConnection(callback); ScopedReceiveSurface r(service_.get(), &callback); AcceptConnection(callback, share_target_id, kEndpointId); absl::Notification failure_notification; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(metadata.is_final_status()); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kFailed); ASSERT_TRUE(container.HasAttachments()); EXPECT_EQ(container.GetFileAttachments().size(), 1u); const FileAttachment& file = container.GetFileAttachments()[0]; EXPECT_FALSE(file.file_path()); failure_notification.Notify(); })); std::weak_ptr listener = fake_nearby_connections_manager_->GetRegisteredPayloadStatusListener( kFilePayloadId); ASSERT_FALSE(listener.expired()); auto payload = std::make_unique( kFilePayloadId, PayloadStatus::kFailure, /*total_bytes=*/kPayloadSize, /*bytes_transferred=*/kPayloadSize); if (auto locked_listener = listener.lock()) { locked_listener->OnStatusUpdate(std::move(payload)); } EXPECT_TRUE( failure_notification.WaitForNotificationWithTimeout(kWaitTimeout)); FlushTesting(); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); EXPECT_FALSE(fake_nearby_connections_manager_->has_incoming_payloads()); // File deletion runs in a ThreadPool. EXPECT_TRUE( sharing_service_task_runner_->SyncWithTimeout(absl::Milliseconds(200))); } TEST_F(NearbySharingServiceImplTest, AcceptValidShareTargetPayloadCancelled) { NiceMock callback; int64_t share_target_id = SetUpIncomingConnection(callback); ScopedReceiveSurface r(service_.get(), &callback); AcceptConnection(callback, share_target_id, kEndpointId); absl::Notification failure_notification; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(metadata.is_final_status()); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kCancelled); ASSERT_TRUE(container.HasAttachments()); EXPECT_EQ(container.GetFileAttachments().size(), 1u); const FileAttachment& file = container.GetFileAttachments()[0]; EXPECT_FALSE(file.file_path()); failure_notification.Notify(); })); std::weak_ptr listener = fake_nearby_connections_manager_->GetRegisteredPayloadStatusListener( kFilePayloadId); ASSERT_FALSE(listener.expired()); auto payload = std::make_unique( kFilePayloadId, PayloadStatus::kCanceled, /*total_bytes=*/kPayloadSize, /*bytes_transferred=*/kPayloadSize); if (auto locked_listener = listener.lock()) { locked_listener->OnStatusUpdate(std::move(payload)); } EXPECT_TRUE( failure_notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_FALSE(fake_nearby_connections_manager_->has_incoming_payloads()); // File deletion runs in a ThreadPool. EXPECT_TRUE( sharing_service_task_runner_->SyncWithTimeout(absl::Milliseconds(200))); } TEST_F(NearbySharingServiceImplTest, RejectInvalidShareTarget) { absl::Notification notification; service_->Reject( 98456L, [&](NearbySharingServiceImpl::StatusCodes status_code) { EXPECT_EQ(status_code, NearbySharingServiceImpl::StatusCodes::kInvalidArgument); notification.Notify(); }); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } TEST_F(NearbySharingServiceImplTest, RejectValidShareTarget) { NiceMock callback; int64_t share_target_id = SetUpIncomingConnection(callback); ScopedReceiveSurface r(service_.get(), &callback); absl::Notification notification; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_TRUE(metadata.is_final_status()); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kRejected); })); service_->Reject( share_target_id, [&](NearbySharingServiceImpl::StatusCodes status_code) { EXPECT_EQ(status_code, NearbySharingServiceImpl::StatusCodes::kOk); notification.Notify(); }); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); // Check data written to connection_. EXPECT_TRUE(ExpectPairedKeyEncryptionFrame()); EXPECT_TRUE(ExpectPairedKeyResultFrame()); EXPECT_TRUE(ExpectConnectionResponseFrame(ConnectionResponseFrame::REJECT)); FastForward(kIncomingRejectionDelay + kDelta); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionKeyVerificationRunnerStatusUnable) { fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/false); SetConnectionType(ConnectionType::kWifi); NiceMock callback; absl::Notification notification; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_FALSE(metadata.is_final_status()); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kAwaitingLocalConfirmation); EXPECT_TRUE(share_target.is_incoming); EXPECT_TRUE(share_target.is_known); EXPECT_TRUE(container.HasAttachments()); EXPECT_EQ(container.GetTextAttachments().size(), 3u); EXPECT_EQ(container.GetFileAttachments().size(), 1u); EXPECT_EQ(share_target.device_name, kDeviceName); EXPECT_EQ(share_target.type, kDeviceType); EXPECT_TRUE(share_target.device_id); EXPECT_NE(share_target.device_id, kEndpointId); EXPECT_EQ(share_target.full_name, kTestMetadataFullName); EXPECT_EQ(metadata.token(), kFourDigitToken); notification.Notify(); })); SetUpKeyVerification(/*is_incoming=*/true, PairedKeyResultFrame::UNABLE); SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); StartIncomingConnection(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionKeyVerificationRunnerStatusUnableLowPower) { fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/false); SetConnectionType(ConnectionType::kWifi); NiceMock callback; absl::Notification notification; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_FALSE(metadata.is_final_status()); EXPECT_EQ(TransferMetadata::Status::kAwaitingLocalConfirmation, metadata.status()); EXPECT_TRUE(share_target.is_incoming); EXPECT_TRUE(share_target.is_known); EXPECT_TRUE(container.HasAttachments()); EXPECT_EQ(container.GetTextAttachments().size(), 3u); EXPECT_EQ(container.GetFileAttachments().size(), 1u); EXPECT_EQ(share_target.device_name, kDeviceName); EXPECT_EQ(share_target.type, kDeviceType); EXPECT_TRUE(share_target.device_id); EXPECT_NE(share_target.device_id, kEndpointId); EXPECT_EQ(share_target.full_name, kTestMetadataFullName); EXPECT_EQ(kFourDigitToken, metadata.token()); notification.Notify(); })); SetUpKeyVerification(/*is_incoming=*/true, PairedKeyResultFrame::UNABLE); NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); StartIncomingConnection(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionKeyVerificationRunnerStatusFail) { fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); SetConnectionType(ConnectionType::kWifi); NiceMock callback; SetUpKeyVerification(/*is_incoming=*/true, PairedKeyResultFrame::FAIL); SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); // Ensures that introduction is never received for failed key verification. std::string intro = "introduction_frame"; std::vector bytes(intro.begin(), intro.end()); ReceiveMessageFromConnection(std::move(bytes)); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); EXPECT_CALL(callback, OnTransferUpdate( testing::_, testing::_, nearby::sharing::HasStatus( TransferMetadata::Status::kDeviceAuthenticationFailed))); StartIncomingConnection(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); // Ensure that the messages sent by ProcessLatestPublicCertificateDecryption // are processed prior to checking if connection is closed. EXPECT_TRUE( sharing_service_task_runner_->SyncWithTimeout(absl::Milliseconds(200))); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, IncomingConnectionEmptyAuthTokenKeyVerificationRunnerStatusFail) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_EVERYONE); NiceMock callback; SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); // Ensures that introduction is never received for empty auth token. std::string intro = "introduction_frame"; std::vector bytes(intro.begin(), intro.end()); ReceiveMessageFromConnection(std::move(bytes)); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); StartIncomingConnection(); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, RegisterReceiveSurfaceAlreadyReceiving) { NiceMock callback; SetUpIncomingConnection(callback); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); EXPECT_EQ( RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); } TEST_F(NearbySharingServiceImplTest, RegisterReceiveSurfaceWhileDiscovering) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); NearbySharingService::StatusCodes result = RegisterReceiveSurface( &transfer_callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &transfer_callback); } TEST_F(NearbySharingServiceImplTest, SendAttachmentsWithoutAttachments) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = DiscoverShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(SendAttachments(target_id, /*attachment_container=*/nullptr), NearbySharingServiceImpl::StatusCodes::kInvalidArgument); } TEST_F(NearbySharingServiceImplTest, RegisterReceiveSurfaceWhileSending) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = SetUpOutgoingShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); absl::Notification notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kConnecting, TransferMetadata::Status::kAwaitingRemoteAcceptance}, [&]() { notification.Notify(); }); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); EXPECT_EQ(SendAttachments(target_id, CreateTextAttachments({kTextPayload})), NearbySharingServiceImpl::StatusCodes::kOk); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); NearbySharingService::StatusCodes result = RegisterReceiveSurface( &transfer_callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &transfer_callback); } TEST_F(NearbySharingServiceImplTest, SendTextAlreadySending) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = SetUpOutgoingShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); absl::Notification notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kConnecting, TransferMetadata::Status::kAwaitingRemoteAcceptance}, [&]() { notification.Notify(); }); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); EXPECT_EQ(SendAttachments(target_id, CreateTextAttachments({kTextPayload})), NearbySharingServiceImpl::StatusCodes::kOk); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); // We're now in the sending state, try to send again should fail EXPECT_EQ(SendAttachments(target_id, CreateTextAttachments({kTextPayload})), NearbySharingServiceImpl::StatusCodes::kOutOfOrderApiCall); } TEST_F(NearbySharingServiceImplTest, SendTextWithoutScanning) { EXPECT_EQ(SendAttachments(325626L, CreateTextAttachments({kTextPayload})), NearbySharingServiceImpl::StatusCodes::kOutOfOrderApiCall); } TEST_F(NearbySharingServiceImplTest, SendTextUnknownTarget) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; DiscoverShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(SendAttachments(12345L, CreateTextAttachments({kTextPayload})), NearbySharingServiceImpl::StatusCodes::kInvalidArgument); } TEST_F(NearbySharingServiceImplTest, SendTextFailedCreateEndpointInfo) { // Set name with too many characters. local_device_data_manager()->SetDeviceName(std::string(300, 'a')); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = DiscoverShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(SendAttachments(target_id, CreateTextAttachments({kTextPayload})), NearbySharingServiceImpl::StatusCodes::kError); } TEST_F(NearbySharingServiceImplTest, SendTextFailedToConnect) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; // Call DiscoverShareTarget() instead of SetUpOutgoingShareTarget() as we want // to fail before key verification is done. int64_t target_id = DiscoverShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); absl::Notification notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kConnecting, TransferMetadata::Status::kFailed}, [&]() { notification.Notify(); }); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); EXPECT_EQ(SendAttachments(target_id, CreateTextAttachments({kTextPayload})), NearbySharingServiceImpl::StatusCodes::kOk); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } TEST_F(NearbySharingServiceImplTest, SendTextFailedKeyVerification) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = DiscoverShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); absl::Notification notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kConnecting, TransferMetadata::Status::kDeviceAuthenticationFailed}, [&]() { notification.Notify(); }); SetUpKeyVerification(/*is_incoming=*/false, PairedKeyResultFrame::FAIL); fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); fake_nearby_connections_manager_->set_nearby_connection(connection_.get()); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); EXPECT_EQ(SendAttachments(target_id, CreateTextAttachments({kTextPayload})), NearbySharingServiceImpl::StatusCodes::kOk); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } TEST_F(NearbySharingServiceImplTest, SendTextUnableToVerifyKey) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = DiscoverShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); absl::Notification notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kConnecting, TransferMetadata::Status::kAwaitingRemoteAcceptance}, [&]() { notification.Notify(); }); SetUpKeyVerification(/*is_incoming=*/false, PairedKeyResultFrame::UNABLE); fake_nearby_connections_manager_->SetRawAuthenticationToken(kEndpointId, GetToken()); fake_nearby_connections_manager_->set_nearby_connection(connection_.get()); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); EXPECT_EQ(SendAttachments(target_id, CreateTextAttachments({kTextPayload})), NearbySharingServiceImpl::StatusCodes::kOk); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } INSTANTIATE_TEST_SUITE_P(NearbySharingServiceImplSendFailureTest, NearbySharingServiceImplSendFailureTest, testing::ValuesIn(kSendFailureTestData)); TEST_P(NearbySharingServiceImplSendFailureTest, SendTextRemoteFailure) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = SetUpOutgoingShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); absl::Notification notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kConnecting, TransferMetadata::Status::kAwaitingRemoteAcceptance}, [&]() { notification.Notify(); }); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); EXPECT_EQ(SendAttachments(target_id, CreateTextAttachments({kTextPayload})), NearbySharingServiceImpl::StatusCodes::kOk); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); // Verify data sent to the remote device so far. EXPECT_TRUE(ExpectPairedKeyEncryptionFrame()); EXPECT_TRUE(ExpectPairedKeyResultFrame()); EXPECT_TRUE(ExpectIntroductionFrame().has_value()); // We're now waiting for the remote device to respond with the accept absl::Notification reject_notification; ExpectTransferUpdates(transfer_callback, target_id, {GetParam().expected_status}, [&]() { reject_notification.Notify(); }); // Cancel the transfer by rejecting it. SendConnectionResponse(GetParam().response_status); EXPECT_TRUE(reject_notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, SendFileWithEmptyPath) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = DiscoverShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(SendAttachments(target_id, CreateFileAttachments({FilePath{""}})), NearbySharingServiceImpl::StatusCodes::kInvalidArgument); } TEST_P(NearbySharingServiceImplSendFailureTest, SendFilesRemoteFailure) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = SetUpOutgoingShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); std::vector test_data = {'T', 'e', 's', 't'}; FilePath path = CreateTestFile("text.txt", test_data); absl::Notification notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kConnecting, TransferMetadata::Status::kAwaitingRemoteAcceptance}, [&]() { notification.Notify(); }); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); EXPECT_EQ(SendAttachments(target_id, CreateFileAttachments({path})), NearbySharingServiceImpl::StatusCodes::kOk); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); // Verify data sent to the remote device so far. EXPECT_TRUE(ExpectPairedKeyEncryptionFrame()); EXPECT_TRUE(ExpectPairedKeyResultFrame()); EXPECT_TRUE(ExpectIntroductionFrame().has_value()); // We're now waiting for the remote device to respond with the accept absl::Notification reject_notification; ExpectTransferUpdates(transfer_callback, target_id, {GetParam().expected_status}, [&]() { reject_notification.Notify(); }); // Cancel the transfer by rejecting it. SendConnectionResponse(GetParam().response_status); EXPECT_TRUE(reject_notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, SendTextDisconnectTimeout) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; AccountManager::Account account; account.id = kTestAccountId; account_manager().SetAccount(account); int64_t target_id = SetUpOutgoingShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); absl::Notification notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kConnecting, TransferMetadata::Status::kAwaitingRemoteAcceptance}, [&]() { notification.Notify(); }); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); EXPECT_EQ(SendAttachments(target_id, CreateTextAttachments({kTextPayload})), NearbySharingServiceImpl::StatusCodes::kOk); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); // Verify data sent to the remote device so far. EXPECT_TRUE(ExpectPairedKeyEncryptionFrame()); EXPECT_TRUE(ExpectPairedKeyResultFrame()); std::optional intro = ExpectIntroductionFrame(); ASSERT_TRUE(intro.has_value()); ASSERT_EQ(intro->text_metadata_size(), 1); auto meta = intro->text_metadata(0); EXPECT_EQ(meta.text_title(), kTextPayload); EXPECT_EQ(static_cast(meta.size()), strlen(kTextPayload)); EXPECT_EQ(meta.type(), TextMetadata::TEXT); ASSERT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); std::unique_ptr advertisement = Advertisement::FromEndpointInfo(absl::Span( *fake_nearby_connections_manager_->connection_endpoint_info( kEndpointId))); ASSERT_TRUE(advertisement); EXPECT_EQ(advertisement->device_name(), kDeviceName); EXPECT_EQ(advertisement->device_type(), ShareTargetType::kLaptop); auto& test_metadata_key = GetNearbyShareTestEncryptedMetadataKey(); EXPECT_EQ(advertisement->salt(), test_metadata_key.salt()); EXPECT_EQ(advertisement->encrypted_metadata_key(), test_metadata_key.encrypted_key()); PayloadInfo info = AcceptAndSendPayload(transfer_callback, target_id); FinishOutgoingTransfer(transfer_callback, target_id, /*complete=*/false, info); // We should not have called disconnect yet as we want to wait for 1 minute to // make sure all outgoing packets have been sent properly. EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); // Forward time until we send the disconnect request to Nearby FastForward(kOutgoingDisconnectionDelay); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); // FakeNearbyConnectionsManager does not destroy the connection. sharing_service_task_runner_->PostTask([this]() { connection_.reset(); }); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); account_manager().SetAccount(std::nullopt); } TEST_F(NearbySharingServiceImplTest, SendTextSuccessClosedConnection) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = SetUpOutgoingShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); SetUpOutgoingConnectionUntilAccept(transfer_callback, target_id); PayloadInfo info = AcceptAndSendPayload(transfer_callback, target_id); FinishOutgoingTransfer(transfer_callback, target_id, /*complete=*/true, info); // We should not have called disconnect yet as we want to wait for 1 minute // to make sure all outgoing packets have been sent properly. EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); // Call disconnect on the connection early before the timeout has passed. sharing_service_task_runner_->PostTask( [this]() { fake_nearby_connections_manager_->Disconnect(kEndpointId); // FakeNearbyConnectionsManager does not destroy the connection. connection_.reset(); }); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); // Make sure the scheduled disconnect callback does nothing. FastForward(kOutgoingDisconnectionDelay); } TEST_F(NearbySharingServiceImplTest, SendFilesSuccess) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = SetUpOutgoingShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); std::vector test_data = {'T', 'e', 's', 't'}; std::string file_name = "test.txt"; FilePath path = CreateTestFile(file_name, test_data); absl::Notification introduction_notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kConnecting, TransferMetadata::Status::kAwaitingRemoteAcceptance}, [&]() { introduction_notification.Notify(); }); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); EXPECT_EQ(SendAttachments(target_id, CreateFileAttachments({path})), NearbySharingServiceImpl::StatusCodes::kOk); EXPECT_TRUE( introduction_notification.WaitForNotificationWithTimeout(kWaitTimeout)); // Verify data sent to the remote device so far. EXPECT_TRUE(ExpectPairedKeyEncryptionFrame()); EXPECT_TRUE(ExpectPairedKeyResultFrame()); auto intro = ExpectIntroductionFrame(); ASSERT_TRUE(intro.has_value()); ASSERT_EQ(intro->file_metadata_size(), 1); auto meta = intro->file_metadata(0); EXPECT_EQ(meta.name(), file_name); EXPECT_EQ(meta.mime_type(), "text/plain"); EXPECT_EQ(test_data.size(), static_cast(meta.size())); EXPECT_EQ(meta.type(), FileMetadata::UNKNOWN); // We're now waiting for the remote device to respond with the accept // result. absl::Notification accept_notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kInProgress}, [&]() { accept_notification.Notify(); }); // Kick off send process by accepting the transfer from the remote device. SendConnectionResponse(ConnectionResponseFrame::ACCEPT); EXPECT_TRUE(accept_notification.WaitForNotificationWithTimeout(kWaitTimeout)); // Expect the file payload to be sent in the end. PayloadInfo info = GetWrittenPayload(); ASSERT_TRUE(info.payload->content.is_file()); FilePath file = info.payload->content.file_payload.file.path; ASSERT_TRUE(Files::FileExists(file)); } TEST_F(NearbySharingServiceImplTest, SendWifiCredentialsSuccess) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = SetUpOutgoingShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); absl::Notification introduction_notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kConnecting, TransferMetadata::Status::kAwaitingRemoteAcceptance}, [&]() { introduction_notification.Notify(); }); EXPECT_CALL(*mock_app_info_, SetActiveFlag()); EXPECT_EQ(SendAttachments(target_id, CreateWifiCredentialAttachments( "GoogleGuest", "password")), NearbySharingServiceImpl::StatusCodes::kOk); EXPECT_TRUE( introduction_notification.WaitForNotificationWithTimeout(kWaitTimeout)); // Verify data sent to the remote device so far. EXPECT_TRUE(ExpectPairedKeyEncryptionFrame()); EXPECT_TRUE(ExpectPairedKeyResultFrame()); std::optional intro = ExpectIntroductionFrame(); ASSERT_TRUE(intro.has_value()); ASSERT_EQ(intro->wifi_credentials_metadata_size(), 1); auto meta = intro->wifi_credentials_metadata(0); EXPECT_EQ(meta.ssid(), "GoogleGuest"); EXPECT_EQ(meta.security_type(), service::proto::WifiCredentialsMetadata::WPA_PSK); // We're now waiting for the remote device to respond with the accept // result. absl::Notification accept_notification; ExpectTransferUpdates(transfer_callback, target_id, {TransferMetadata::Status::kInProgress}, [&]() { accept_notification.Notify(); }); // Kick off send process by accepting the transfer from the remote device. SendConnectionResponse(ConnectionResponseFrame::ACCEPT); EXPECT_TRUE(accept_notification.WaitForNotificationWithTimeout(kWaitTimeout)); // Expect the wifi credential payload to be sent in the end. PayloadInfo info = GetWrittenPayload(); ASSERT_TRUE(info.payload->content.is_bytes()); std::vector bytes = info.payload->content.bytes_payload.bytes; nearby::sharing::service::proto::WifiCredentials wifi_credentials; ASSERT_TRUE(wifi_credentials.ParseFromArray(bytes.data(), bytes.size())); EXPECT_EQ(wifi_credentials.password(), "password"); EXPECT_FALSE(wifi_credentials.hidden_ssid()); } TEST_F(NearbySharingServiceImplTest, CancelSenderInitiator) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = SetUpOutgoingShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); SetUpOutgoingConnectionUntilAccept(transfer_callback, target_id); PayloadInfo info = AcceptAndSendPayload(transfer_callback, target_id); // After we stop scanning, we check back in after kInvalidateDelay // milliseconds to make sure that we stopped in order to send a file and // not because the user left the page. We have to fast-forward here. // otherwise, we will hit this callback when trying to fast-forward by // kInitiatorCancelDelay below. FastForward(kInvalidateDelay); absl::Notification notification; EXPECT_CALL(transfer_callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_EQ(share_target.id, target_id); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kCancelled); })); EXPECT_FALSE( fake_nearby_connections_manager_->WasPayloadCanceled(info.payload->id)); // The initiator of the cancellation explicitly calls Cancel(). service_->Cancel( target_id, [&](NearbySharingServiceImpl::StatusCodes status_code) { EXPECT_EQ(status_code, NearbySharingServiceImpl::StatusCodes::kOk); notification.Notify(); }); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_TRUE( fake_nearby_connections_manager_->WasPayloadCanceled(info.payload->id)); // After the TransferMetadata::Status::kCancelled update, we expect other // classes to unregister the send surface. UnregisterSendSurface(&transfer_callback); // The initiator of the cancel should send a cancel frame to the other device, // then wait a few seconds before disconnecting to allow for processing on the // other device. EXPECT_TRUE(ExpectCancelFrame()); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); FastForward(kInitiatorCancelDelay); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, CancelSenderNoninitiator) { MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; int64_t target_id = SetUpOutgoingShareTarget(transfer_callback, discovery_callback); ScopedSendSurface s(service_.get(), &transfer_callback); SetUpOutgoingConnectionUntilAccept(transfer_callback, target_id); PayloadInfo info = AcceptAndSendPayload(transfer_callback, target_id); absl::Notification notification; EXPECT_CALL(transfer_callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_EQ(share_target.id, target_id); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kCancelled); notification.Notify(); })); EXPECT_FALSE( fake_nearby_connections_manager_->WasPayloadCanceled(info.payload->id)); // The non-initiator of the cancellation processes a cancellation frame from // the initiator. SendCancel(); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); EXPECT_TRUE( fake_nearby_connections_manager_->WasPayloadCanceled(info.payload->id)); // The non-initiator should close the connection immediately EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, CancelReceiverInitiator) { NiceMock transfer_callback; int64_t target_id = SetUpIncomingConnection(transfer_callback); ScopedReceiveSurface r(service_.get(), &transfer_callback); AcceptConnection(transfer_callback, target_id, kEndpointId); ASSERT_TRUE(ExpectPairedKeyEncryptionFrame()); ASSERT_TRUE(ExpectPairedKeyResultFrame()); absl::Notification notification; EXPECT_CALL(transfer_callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_EQ(share_target.id, target_id); EXPECT_EQ(metadata.status(), TransferMetadata::Status::kCancelled); })); EXPECT_FALSE( fake_nearby_connections_manager_->WasPayloadCanceled(kFilePayloadId)); // The initiator of the cancellation explicitly calls Cancel(). service_->Cancel( target_id, [&](NearbySharingServiceImpl::StatusCodes status_code) { EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk, status_code); notification.Notify(); }); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_TRUE( fake_nearby_connections_manager_->WasPayloadCanceled(kFilePayloadId)); // After the TransferMetadata::Status::kCancelled update, we expect other // classes to unregister the receive surface. UnregisterReceiveSurface(&transfer_callback); // This is a response frame generated by accept(). GetWrittenFrame(); // The initiator of the cancel should send a cancel frame to the other device, // then wait a few seconds before disconnecting to allow for processing on the // other device. ASSERT_TRUE(ExpectCancelFrame()); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); FastForward(kInitiatorCancelDelay); EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, CancelReceiverNoninitiator) { NiceMock transfer_callback; int64_t target_id = SetUpIncomingConnection(transfer_callback); ScopedReceiveSurface r(service_.get(), &transfer_callback); AcceptConnection(transfer_callback, target_id, kEndpointId); ExpectPairedKeyEncryptionFrame(); ExpectPairedKeyResultFrame(); absl::Notification notification; EXPECT_CALL(transfer_callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .WillOnce(testing::Invoke([&](const ShareTarget& share_target, const AttachmentContainer& container, TransferMetadata metadata) { EXPECT_EQ(target_id, share_target.id); EXPECT_EQ(TransferMetadata::Status::kCancelled, metadata.status()); notification.Notify(); })); EXPECT_FALSE( fake_nearby_connections_manager_->WasPayloadCanceled(kFilePayloadId)); // The non-initiator of the cancellation processes a cancellation frame from // the initiator. SendCancel(); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); EXPECT_TRUE( fake_nearby_connections_manager_->WasPayloadCanceled(kFilePayloadId)); // The non-initiator should close the connection immediately EXPECT_FALSE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, RegisterForegroundReceiveSurfaceEntersHighVisibility) { TestObserver observer(service_.get()); NiceMock callback; SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_EVERYONE); local_device_data_manager()->SetDeviceName(kDeviceName); // To start, we should not be in high visibility state. EXPECT_FALSE(observer.in_high_visibility_); EXPECT_FALSE(observer.on_start_advertising_failure_called_); // If we register a foreground surface we should end up in high visibility // state. SetUpForegroundReceiveSurface(callback); ScopedReceiveSurface r(service_.get(), &callback); // At this point we should have a new high visibility state and the observer // should have been called as well. EXPECT_TRUE(observer.in_high_visibility_); EXPECT_FALSE(observer.on_start_advertising_failure_called_); // If we unregister the foreground receive surface we should no longer be in // high visibility and the observer should be notified. EXPECT_EQ(UnregisterReceiveSurface(&callback), NearbySharingService::StatusCodes::kOk); EXPECT_FALSE(observer.in_high_visibility_); // Remove the observer before it goes out of scope. service_->RemoveObserver(&observer); FlushTesting(); } TEST_F(NearbySharingServiceImplTest, AddObserverSendsInitialAdapterState) { SetBluetoothIsPresent(true); SetBluetoothIsPowered(false); SetLanIsConnected(true); TestObserver observer(service_.get()); FlushTesting(); EXPECT_EQ(observer.bluetooth_state_, NearbySharingService::Observer::AdapterState::DISABLED); EXPECT_EQ(observer.lan_state_, NearbySharingService::Observer::AdapterState::ENABLED); // Remove the observer before it goes out of scope. service_->RemoveObserver(&observer); } TEST_F(NearbySharingServiceImplTest, AddObserverBluetoothAdapterUpdate) { SetBluetoothIsPresent(false); SetBluetoothIsPowered(false); SetLanIsConnected(false); TestObserver observer(service_.get()); FlushTesting(); EXPECT_EQ(observer.bluetooth_state_, NearbySharingService::Observer::AdapterState::NOT_PRESENT); SetBluetoothIsPresent(true); SetBluetoothIsPowered(false); EXPECT_EQ(observer.bluetooth_state_, NearbySharingService::Observer::AdapterState::DISABLED); SetBluetoothIsPresent(true); SetBluetoothIsPowered(true); EXPECT_EQ(observer.bluetooth_state_, NearbySharingService::Observer::AdapterState::ENABLED); SetBluetoothIsPresent(false); SetBluetoothIsPowered(true); EXPECT_EQ(observer.bluetooth_state_, NearbySharingService::Observer::AdapterState::NOT_PRESENT); // Remove the observer before it goes out of scope. service_->RemoveObserver(&observer); } TEST_F(NearbySharingServiceImplTest, AddObserverLanAdapterUpdate) { SetBluetoothIsPresent(false); SetBluetoothIsPowered(false); SetLanIsConnected(false); TestObserver observer(service_.get()); FlushTesting(); EXPECT_EQ(observer.lan_state_, NearbySharingService::Observer::AdapterState::DISABLED); SetLanIsConnected(true); EXPECT_EQ(observer.lan_state_, NearbySharingService::Observer::AdapterState::ENABLED); // Remove the observer before it goes out of scope. service_->RemoveObserver(&observer); } TEST_F(NearbySharingServiceImplTest, RotateBackgroundAdvertisementPeriodic) { certificate_manager()->set_next_salt({0x00, 0x01}); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); NiceMock callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); auto endpoint_info_initial = fake_nearby_connections_manager_->advertising_endpoint_info(); certificate_manager()->set_next_salt({0x00, 0x02}); FastForward(absl::Seconds(870)); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); auto endpoint_info_rotated = fake_nearby_connections_manager_->advertising_endpoint_info(); EXPECT_NE(endpoint_info_initial, endpoint_info_rotated); } TEST_F(NearbySharingServiceImplTest, RotateBackgroundAdvertisementPrivateCertificatesChange) { certificate_manager()->set_next_salt({0x00, 0x01}); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); NiceMock callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); auto endpoint_info_initial = fake_nearby_connections_manager_->advertising_endpoint_info(); certificate_manager()->set_next_salt({0x00, 0x02}); certificate_manager()->NotifyPrivateCertificatesChanged(); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); auto endpoint_info_rotated = fake_nearby_connections_manager_->advertising_endpoint_info(); EXPECT_NE(endpoint_info_initial, endpoint_info_rotated); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); } TEST_F(NearbySharingServiceImplTest, OrderedEndpointDiscoveryEvents) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; // Start discovering, to ensure a discovery listener is registered. EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); // Ensure that the endpoint discovered and lost event are process // sequentially. This is particularly important due to the asynchronous // operations needed to handle endpoint discovery. // // Order of events: // - Nearby Connections discovers endpoint 1 // - Nearby Connections loses endpoint 1 // - Nearby Share processes discovered event. // - endpoint 1 moved to discovery cache. // - Nearby Connections discovers endpoint 2 // - Nearby Connections discovers endpoint 3 // - Nearby Connections loses endpoint 3 // - Nearby Connections loses endpoint 2 // - Nearby Share processes these 2 discovered events in order. // - endpoints 2 and 3 moved to discovery cache. { absl::Notification notification; FindEndpoint(/*endpoint_id=*/"1"); LoseEndpoint(/*endpoint_id=*/"1"); EXPECT_CALL(discovery_callback, OnShareTargetDiscovered) .WillOnce([&](ShareTarget share_target) { notification.Notify(); }); // Needed for discovery processing. ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } { absl::Notification notification; FindEndpoint(/*endpoint_id=*/"2"); FindEndpoint(/*endpoint_id=*/"3"); LoseEndpoint(/*endpoint_id=*/"3"); LoseEndpoint(/*endpoint_id=*/"2"); InSequence s; EXPECT_CALL(discovery_callback, OnShareTargetDiscovered) .WillOnce([](ShareTarget share_target) { EXPECT_EQ(share_target.device_id, "2"); }); EXPECT_CALL(discovery_callback, OnShareTargetDiscovered) .WillOnce([&](ShareTarget share_target) { EXPECT_EQ(share_target.device_id, "3"); notification.Notify(); }); // Needed for discovery processing. Fail, then the ShareTarget device ID is // set to the endpoint ID, which we use above to verify the correct endpoint // ID processing order. ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/2, /*success=*/false); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/3, /*success=*/false); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } } TEST_F(NearbySharingServiceImplTest, RetryDiscoveredEndpointsNoDownloadIfDecryption) { // Start discovery. SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); // Order of events: // - Discover endpoint 1 --> decrypts public certificate // - Fire certificate download timer --> no download because no cached // advertisements { absl::Notification notification; FindEndpoint(/*endpoint_id=*/"1"); EXPECT_CALL(discovery_callback, OnShareTargetDiscovered) .WillOnce([&](ShareTarget share_target) { notification.Notify(); }); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } FastForward(kCertificateDownloadDuringDiscoveryPeriod); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u); } TEST_F(NearbySharingServiceImplTest, DedupSameEndpointId) { // Start discovery. SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); { absl::Notification notification; // vendor_id is default to 0. FindEndpoint(/*endpoint_id=*/"1"); FindEndpointWithVendorId( /*endpoint_id=*/"1", static_cast(Advertisement::BlockedVendorId::kSamsung)); ::testing::InSequence s; ShareTarget share_target_1; ShareTarget share_target_2; EXPECT_CALL(discovery_callback, OnShareTargetDiscovered(_)) .WillOnce(SaveArg<0>(&share_target_1)); EXPECT_CALL(discovery_callback, OnShareTargetUpdated(_)) .WillOnce([&](ShareTarget share_target) { share_target_2 = share_target; notification.Notify(); }); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/false); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/2, /*success=*/false); EXPECT_EQ(share_target_1.id, share_target_2.id); // Vendor_id updated. EXPECT_EQ(share_target_1.vendor_id, 0); EXPECT_EQ(share_target_2.vendor_id, static_cast(Advertisement::BlockedVendorId::kSamsung)); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } Shutdown(); } TEST_F(NearbySharingServiceImplTest, OnLostDedupSameEndpointIdBeforeExpiryNoOnShareTargetLost) { // Start discovery. SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); { absl::Notification notification; ::testing::InSequence s; ShareTarget share_target_1; EXPECT_CALL(discovery_callback, OnShareTargetDiscovered(_)) .WillOnce(SaveArg<0>(&share_target_1)); // vendor_id is default to 0. FindEndpoint(/*endpoint_id=*/"1"); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); // Finish processing all the HandleEndpointDiscovered events. FlushTesting(); // No call to OnShareTargetLost. LoseEndpoint(/*endpoint_id=*/"1"); // Fastforward to just before the cache expiry time. FastForward( absl::Milliseconds(NearbyFlags::GetInstance().GetInt64Flag( config_package_nearby::nearby_sharing_feature:: kDiscoveryCacheLostExpiryMs) - 10)); FindEndpointWithVendorId( /*endpoint_id=*/"1", static_cast(Advertisement::BlockedVendorId::kSamsung)); ShareTarget share_target_2; EXPECT_CALL(discovery_callback, OnShareTargetUpdated(_)) .WillOnce([&](ShareTarget share_target) { share_target_2 = share_target; notification.Notify(); }); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/2, /*success=*/false); EXPECT_EQ(share_target_1.id, share_target_2.id); // Vendor_id updated. EXPECT_EQ(share_target_1.vendor_id, 0); EXPECT_EQ(share_target_2.vendor_id, static_cast(Advertisement::BlockedVendorId::kSamsung)); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } Shutdown(); } TEST_F(NearbySharingServiceImplTest, OnLostDedupSameEndpointIdAfterExpiry) { // Start discovery. SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); { absl::Notification notification; ::testing::InSequence s; ShareTarget share_target_1; EXPECT_CALL(discovery_callback, OnShareTargetDiscovered(_)) .WillOnce(SaveArg<0>(&share_target_1)); // vendor_id is default to 0. FindEndpoint(/*endpoint_id=*/"1"); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/false); // Finish processing all the HandleEndpointDiscovered related events before // fast forwarding to avoid race condition. FlushTesting(); ShareTarget share_target_1_lost; EXPECT_CALL(discovery_callback, OnShareTargetLost) .WillOnce(SaveArg<0>(&share_target_1_lost)); LoseEndpoint(/*endpoint_id=*/"1"); // Fast forward to after the cache expiry time. FastForward( absl::Milliseconds(NearbyFlags::GetInstance().GetInt64Flag( config_package_nearby::nearby_sharing_feature:: kDiscoveryCacheLostExpiryMs) + 10)); FindEndpointWithVendorId( /*endpoint_id=*/"1", static_cast(Advertisement::BlockedVendorId::kSamsung)); ShareTarget share_target_2; EXPECT_CALL(discovery_callback, OnShareTargetDiscovered(_)) .WillOnce([&](ShareTarget share_target) { share_target_2 = share_target; notification.Notify(); }); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/2, /*success=*/false); EXPECT_EQ(share_target_1_lost.id, share_target_1.id); // Cache entry expires and the share_target ID is not preserved. EXPECT_NE(share_target_1.id, share_target_2.id); EXPECT_EQ(share_target_1.vendor_id, 0); EXPECT_EQ(share_target_2.vendor_id, static_cast(Advertisement::BlockedVendorId::kSamsung)); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } } // This test verifies the de-dup logic. Since certificates are the same, all the // share targets are duplicates. TEST_F(NearbySharingServiceImplTest, EndpointDedupBasedOnDeviceId) { // Make kDiscoveryCacheLostExpiryMs larger than // kCertificateDownloadDuringDiscoveryPeriod (10s). NearbyFlags::GetInstance().OverrideInt64FlagValue( config_package_nearby::nearby_sharing_feature:: kDiscoveryCacheLostExpiryMs, 20000); // 20s // Start discovery. SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); // Order of events: // - Discover endpoint 1 --> decrypts public certificate // - Discover endpoint 2 --> cannot decrypt public certificate // - Discover endpoint 3 --> decrypts public certificate // --> De-dup endpoint 1 with endpoint 3 // - Discover endpoint 4 --> cannot decrypt public certificate // - Lose endpoint 3 --> endpoint 3 is added to discovery_cache // ---------------------------------------------------------------- // - Fire certificate download timer --> certificates downloaded // - {x|y} can be 2 or 4, as the (Re)discover order is non-deterministic // - (Re)discover endpoints x before endpoint 3 discovery cache expiry // --> De-dup endpoint 3 with endpoint x // - (Re)discover endpoints y --> De-dup endpoint x with endpoint y { absl::Notification notification; ::testing::InSequence s; // vendor_id is default to 0. FindEndpoint(/*endpoint_id=*/"1"); ShareTarget share_target_ep_1; EXPECT_CALL(discovery_callback, OnShareTargetDiscovered(_)) .WillOnce(SaveArg<0>(&share_target_ep_1)); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/true); FlushTesting(); FindInvalidEndpoint(/*endpoint_id=*/"2"); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/2, /*success=*/false); FlushTesting(); FindEndpointWithVendorId( /*endpoint_id=*/"3", static_cast(Advertisement::BlockedVendorId::kSamsung)); // Update endpoint 1 to endpoint 3 ShareTarget share_target_ep_3; EXPECT_CALL(discovery_callback, OnShareTargetUpdated(_)) .WillOnce([&](ShareTarget share_target) { share_target_ep_3 = share_target; }); // Update endpoint 3 to receive disabled after on lost. ShareTarget share_target_ep_3_disabled; EXPECT_CALL(discovery_callback, OnShareTargetUpdated(_)) .WillOnce([&](ShareTarget share_target) { share_target_ep_3_disabled = share_target; notification.Notify(); }); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/3, /*success=*/true, /*for_self_share=*/false, /*vendor_id*/ 1); FlushTesting(); FindInvalidEndpoint(/*endpoint_id=*/"4"); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/4, /*success=*/false); FlushTesting(); LoseEndpoint(/*endpoint_id=*/"3"); FlushTesting(); EXPECT_EQ(share_target_ep_1.id, share_target_ep_3.id); // Vendor_id updated. EXPECT_EQ(share_target_ep_3.vendor_id, static_cast(Advertisement::BlockedVendorId::kSamsung)); EXPECT_FALSE(share_target_ep_3.receive_disabled); EXPECT_EQ(share_target_ep_1.id, share_target_ep_3_disabled.id); EXPECT_TRUE(share_target_ep_3_disabled.receive_disabled); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } // kDiscoveryCacheLostExpiryMs is set to be larger than // kCertificateDownloadDuringDiscoveryPeriod so the cache_entry is unexpired. FastForward(kCertificateDownloadDuringDiscoveryPeriod); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 2u); certificate_manager()->NotifyPublicCertificatesDownloaded(); FlushTesting(); ShareTarget share_target_updated; { absl::Notification notification; ::testing::InSequence s; // Update endpoint 3 EXPECT_CALL(discovery_callback, OnShareTargetUpdated(_)).Times(1); // One of the re-discovered endpoint updates the other one. The ordering // is non-deterministic. EXPECT_CALL(discovery_callback, OnShareTargetUpdated) .WillOnce([&](ShareTarget share_target) { share_target_updated = share_target; notification.Notify(); }); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/5, /*success=*/true); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/6, /*success=*/true); EXPECT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout)); } FlushTesting(); // Send Text to the updated endpoint. SetUpKeyVerification( /*is_incoming=*/false, PairedKeyResultFrame::SUCCESS); // Since we don't know exactly which endpoint is updated, we need to set the // token for both of them. fake_nearby_connections_manager_->SetRawAuthenticationToken( /*endpoint_id=*/"4", GetToken()); fake_nearby_connections_manager_->SetRawAuthenticationToken( /*endpoint_id=*/"2", GetToken()); fake_nearby_connections_manager_->set_nearby_connection(connection_.get()); SetUpOutgoingConnectionUntilAccept(transfer_callback, share_target_updated.id); PayloadInfo info = AcceptAndSendPayload(transfer_callback, share_target_updated.id); FinishOutgoingTransfer(transfer_callback, share_target_updated.id, /*complete=*/true, info); EXPECT_TRUE(fake_nearby_connections_manager_ ->connection_endpoint_info(/*endpoint_id=*/"4") .has_value() || fake_nearby_connections_manager_ ->connection_endpoint_info(/*endpoint_id=*/"2") .has_value()); Shutdown(); } TEST_F(NearbySharingServiceImplTest, RetryDiscoveredEndpointsDiscoveryRestartClearsCache) { // Start discovery. SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); // Order of events: // - Discover endpoint 1 --> cannot decrypt public certificate // - Stop discovery // - Certificate download timer not running; not discovering // - Start discovery // - Fire certificate download timer --> certificates not downloaded; cached // advertisement map has been cleared FindInvalidEndpoint(/*endpoint_id=*/"1"); InSequence seq; EXPECT_CALL(discovery_callback, OnShareTargetDiscovered).Times(0); EXPECT_CALL(discovery_callback, OnShareTargetLost).Times(0); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/false); UnregisterSendSurface(&transfer_callback); FastForward(kCertificateDownloadDuringDiscoveryPeriod); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u); RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground); // Note: Certificate downloads are also requested in RegisterSendSurface; this // is not related to the retry timer. EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 2u); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); FastForward(kCertificateDownloadDuringDiscoveryPeriod); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 2u); } TEST_F(NearbySharingServiceImplTest, RetryDiscoveredEndpointsWhenCannotDecrypted) { // Start discovery. SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); FindInvalidEndpoint(/*endpoint_id=*/"1"); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/false); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u); // Because there is one pending advertisement to resolve, it will cause public // certificates download. FastForward(kCertificateDownloadDuringDiscoveryPeriod); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 2u); certificate_manager()->NotifyPublicCertificatesDownloaded(); FlushTesting(); // Don't download public certificates when it is tried. FastForward(kCertificateDownloadDuringDiscoveryPeriod); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 2u); FlushTesting(); // Don't download public certificates in case of the endpoint is discovered // again. FindInvalidEndpoint(/*endpoint_id=*/"1"); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/2, /*success=*/false); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 2u); } TEST_F(NearbySharingServiceImplTest, RetryDiscoveredEndpointsDownloadLimit) { // Start discovery. SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); // Order of events: // - x3: // - (Re)discover endpoint 1 --> cannot decrypt public certificate // - Fire certificate download timer --> certificates downloaded // - Rediscover endpoint 1 --> cannot decrypt public certificate // - Fire certificate download timer --> no download; limit reached // - Restart discovery which resets limit counter for (size_t i = 1; i <= kMaxCertificateDownloadsDuringDiscovery; ++i) { FindInvalidEndpoint(/*endpoint_id=*/absl::StrCat(i)); } for (size_t i = 1; i <= kMaxCertificateDownloadsDuringDiscovery; ++i) { SCOPED_TRACE(i); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/i, /*success=*/false); FastForward(kCertificateDownloadDuringDiscoveryPeriod); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u + i); certificate_manager()->NotifyPublicCertificatesDownloaded(); FlushTesting(); } FastForward(kCertificateDownloadDuringDiscoveryPeriod); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 1u + kMaxCertificateDownloadsDuringDiscovery); UnregisterSendSurface(&transfer_callback); RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground); // Note: Certificate downloads are also requested in RegisterSendSurface; this // is not related to the retry timer. EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 2u + kMaxCertificateDownloadsDuringDiscovery); FindInvalidEndpoint(/*endpoint_id=*/"1"); ProcessLatestPublicCertificateDecryption( /*expected_num_calls=*/1u + kMaxCertificateDownloadsDuringDiscovery, /*success=*/false); FastForward(kCertificateDownloadDuringDiscoveryPeriod); EXPECT_EQ(certificate_manager()->num_download_public_certificates_calls(), 3u + kMaxCertificateDownloadsDuringDiscovery); } TEST_F(NearbySharingServiceImplTest, ScreenLockedRegisterReceiveSurfaceNotAdvertising) { SetScreenLocked(true); SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); } TEST_F(NearbySharingServiceImplTest, BlockTargetWithSameVendorId) { InSequence seq; // Register send surface with vendor ID 1 that requests blocking. MockTransferUpdateCallback callback; MockShareTargetDiscoveredCallback discovery_callback; ASSERT_EQ(RegisterSendSurface(&callback, &discovery_callback, SendSurfaceState::kForeground, Advertisement::BlockedVendorId::kSamsung), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &callback); // Verify service will not report discovered. EXPECT_CALL(discovery_callback, OnShareTargetDiscovered(testing::_)).Times(0); // Find endpoint with vendor ID 1. FindEndpointWithVendorId( /*endpoint_id=*/"1", static_cast(Advertisement::BlockedVendorId::kSamsung)); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, /*success=*/false); } TEST_F(NearbySharingServiceImplTest, RegisterSendSurfaceWithDifferentVendorIdIsBlocked) { SetConnectionType(ConnectionType::kWifi); preference_manager().SetInteger( prefs::kNearbySharingBackgroundVisibilityName, static_cast(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS)); FlushTesting(); // Register background send surface with vendor ID 1. MockShareTargetDiscoveredCallback background_discovered_callback; MockTransferUpdateCallback background_transfer_callback; NearbySharingService::StatusCodes result = RegisterSendSurface( &background_transfer_callback, &background_discovered_callback, NearbySharingService::SendSurfaceState::kBackground, Advertisement::BlockedVendorId::kSamsung); ASSERT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &background_transfer_callback); // Register foreground send surface with different vendor ID. MockShareTargetDiscoveredCallback foreground_discovered_callback; MockTransferUpdateCallback foreground_transfer_callback; result = RegisterSendSurface( &foreground_transfer_callback, &foreground_discovered_callback, NearbySharingService::SendSurfaceState::kForeground, static_cast(2)); EXPECT_EQ(result, NearbySharingService::StatusCodes::kInvalidArgument); EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); } TEST_F(NearbySharingServiceImplTest, ScreenLocksDuringAdvertising) { SetConnectionType(ConnectionType::kWifi); SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); SetScreenLocked(true); EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); SetScreenLocked(false); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); } TEST_F(NearbySharingServiceImplTest, ScreenLocksDuringDiscovery) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); SetScreenLocked(true); EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); SetScreenLocked(false); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); } TEST_F(NearbySharingServiceImplTest, CreateShareTarget) { std::unique_ptr advertisement = Advertisement::NewInstance( GetNearbyShareTestEncryptedMetadataKey().salt(), GetNearbyShareTestEncryptedMetadataKey().encrypted_key(), kDeviceType, kDeviceName, kVendorId); // Flip |for_self_share| to true to ensure the resulting ShareTarget picks // this up. nearby::sharing::proto::PublicCertificate certificate_proto = GetNearbyShareTestPublicCertificate( DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); certificate_proto.set_for_self_share(true); std::optional certificate = NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate( certificate_proto, GetNearbyShareTestEncryptedMetadataKey()); ASSERT_TRUE(certificate.has_value()); ASSERT_EQ(certificate_proto.for_self_share(), certificate->for_self_share()); std::optional share_target = service_->CreateShareTarget( kEndpointId, *advertisement, certificate, /*is_incoming=*/true); ASSERT_TRUE(share_target.has_value()); EXPECT_EQ(kDeviceName, share_target->device_name); EXPECT_EQ(kDeviceType, share_target->type); EXPECT_EQ(certificate_proto.for_self_share(), share_target->for_self_share); // Test when |certificate| is null. share_target = service_->CreateShareTarget(kEndpointId, *advertisement, /*certificate=*/std::nullopt, /*is_incoming=*/true); ASSERT_TRUE(share_target.has_value()); EXPECT_EQ(kDeviceName, share_target->device_name); EXPECT_EQ(kDeviceType, share_target->type); EXPECT_EQ(kVendorId, share_target->vendor_id); EXPECT_FALSE(share_target->for_self_share); } TEST_F(NearbySharingServiceImplTest, SelfShareAutoAccept) { // We create an incoming connection corresponding to a certificate where the // |for_self_share| field is set to 'true'. This value will be propagated to // the ShareTarget, which will be used as a signal for the service to // automatically accept the transfer when Self Share is enabled. This is // similar to other tests (see "AcceptValidShareTarget") but without the // explicit call to service_->Accept(). NiceMock callback; int64_t share_target_id = SetUpIncomingConnection(callback, /*is_foreground=*/false, /*for_self_share=*/true); ScopedReceiveSurface r(service_.get(), &callback); // Should fail to call accept. service_->Accept( share_target_id, [&](NearbySharingServiceImpl::StatusCodes status_code) { EXPECT_EQ(status_code, NearbySharingServiceImpl::StatusCodes::kOutOfOrderApiCall); }); // Check data written to connection_. ExpectPairedKeyEncryptionFrame(); ExpectPairedKeyResultFrame(); ExpectConnectionResponseFrame(ConnectionResponseFrame::ACCEPT); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); FlushTesting(); } TEST_F(NearbySharingServiceImplTest, SelfShareNoAutoAcceptInForeground) { NiceMock callback; int64_t share_target_id = SetUpIncomingConnection(callback, /*is_foreground=*/true, /*for_self_share=*/true); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_, testing::_)) .Times(0); service_->Accept( share_target_id, [&](NearbySharingServiceImpl::StatusCodes status_code) { EXPECT_EQ(status_code, NearbySharingServiceImpl::StatusCodes::kOutOfOrderApiCall); }); // Check data written to connection_. ExpectPairedKeyEncryptionFrame(); ExpectPairedKeyResultFrame(); ExpectConnectionResponseFrame(ConnectionResponseFrame::ACCEPT); EXPECT_TRUE( fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId) .has_value()); } TEST_F(NearbySharingServiceImplTest, ObserveAccountLoginAndLogout) { MockAccountObserver account_observer; absl::Notification notification; service_->GetAccountManager()->AddObserver(&account_observer); EXPECT_CALL(account_observer, OnLoginSucceeded(kTestAccountId)).Times(1); AccountManager::Account account; account.id = kTestAccountId; account_manager().SetAccount(account); std::unique_ptr signin_attempt = service_->GetAccountManager()->Login("test_client_id", "test_client_secret"); account_manager().NotifyLogin(kTestAccountId); EXPECT_CALL(account_observer, OnLogoutSucceeded(kTestAccountId, false)) .Times(1); absl::Notification logout_notification; service_->GetAccountManager()->Logout([&](absl::Status status) { EXPECT_TRUE(status.ok()); logout_notification.Notify(); }); EXPECT_TRUE(logout_notification.WaitForNotificationWithTimeout(kWaitTimeout)); service_->GetAccountManager()->RemoveObserver(&account_observer); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); } TEST_F(NearbySharingServiceImplTest, LoginAndLogoutShouldResetSettings) { SetConnectionType(ConnectionType::kWifi); // Used to check whether the setting is cleared after login. service_->GetSettings()->SetIsAnalyticsEnabled(true); std::string device_id = preference_manager_.GetString(prefs::kNearbySharingDeviceIdName, ""); EXPECT_TRUE(device_id.empty()); // Create account. AccountManager::Account account; account.id = kTestAccountId; // Login user. account_manager().SetAccount(account); std::unique_ptr signin_attempt = service_->GetAccountManager()->Login("test_client_id", "test_client_secret"); account_manager().NotifyLogin(kTestAccountId); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); EXPECT_TRUE(service_->GetSettings()->GetIsAnalyticsEnabled()); ASSERT_TRUE(service_->GetAccountManager()->GetCurrentAccount().has_value()); EXPECT_EQ(service_->GetAccountManager()->GetCurrentAccount()->id, kTestAccountId); device_id = preference_manager_.GetString(prefs::kNearbySharingDeviceIdName, ""); EXPECT_FALSE(device_id.empty()); EXPECT_EQ(device_id.size(), 10u); for (const char c : device_id) EXPECT_TRUE(std::isalnum(c)); // Logout user. absl::Notification logout_notification; service_->GetAccountManager()->Logout([&](absl::Status status) { EXPECT_TRUE(status.ok()); logout_notification.Notify(); }); EXPECT_TRUE(logout_notification.WaitForNotificationWithTimeout(kWaitTimeout)); absl::SleepFor(absl::Milliseconds(100)); // data collection flag is not reset on logout. EXPECT_TRUE(service_->GetSettings()->GetIsAnalyticsEnabled()); EXPECT_FALSE(service_->GetAccountManager()->GetCurrentAccount().has_value()); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); device_id = preference_manager_.GetString(prefs::kNearbySharingDeviceIdName, ""); EXPECT_TRUE(device_id.empty()); } TEST_F(NearbySharingServiceImplTest, LoginShouldSetContactsVisibility) { SetConnectionType(ConnectionType::kWifi); // Create account. AccountManager::Account account; account.id = kTestAccountId; // Login user. account_manager().SetAccount(account); std::unique_ptr signin_attempt = service_->GetAccountManager()->Login("test_client_id", "test_client_secret"); account_manager().NotifyLogin(kTestAccountId); ASSERT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); EXPECT_EQ(service_->GetSettings()->GetVisibility(), DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); } TEST_F(NearbySharingServiceImplTest, LogoutShouldSetValidVisibility) { SetConnectionType(ConnectionType::kWifi); // Create account. AccountManager::Account account; account.id = kTestAccountId; // Login user. account_manager().SetAccount(account); std::unique_ptr signin_attempt = service_->GetAccountManager()->Login("test_client_id", "test_client_secret"); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); // Set visibility. service_->GetSettings()->SetVisibility( DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE); // Logout user. absl::Notification logout_notification; service_->GetAccountManager()->Logout([&](absl::Status status) { EXPECT_TRUE(status.ok()); logout_notification.Notify(); }); EXPECT_TRUE(logout_notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); EXPECT_EQ(service_->GetSettings()->GetVisibility(), DeviceVisibility::DEVICE_VISIBILITY_HIDDEN); // Login user. account_manager().SetAccount(account); std::unique_ptr signin_attempt2 = service_->GetAccountManager()->Login("test_client_id", "test_client_secret"); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); // Set visibility. service_->GetSettings()->SetVisibility( DeviceVisibility::DEVICE_VISIBILITY_EVERYONE); // Logout user. absl::Notification logout2_notification; service_->GetAccountManager()->Logout([&](absl::Status status) { EXPECT_TRUE(status.ok()); logout2_notification.Notify(); }); EXPECT_TRUE( logout2_notification.WaitForNotificationWithTimeout(kWaitTimeout)); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); EXPECT_EQ(service_->GetSettings()->GetVisibility(), DeviceVisibility::DEVICE_VISIBILITY_EVERYONE); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); } TEST_F(NearbySharingServiceImplTest, LoginAndLogoutNoStopRunningSurfaces) { SetConnectionType(ConnectionType::kWifi); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; EXPECT_EQ(RegisterSendSurface(&transfer_callback, &discovery_callback, SendSurfaceState::kForeground), NearbySharingService::StatusCodes::kOk); ScopedSendSurface s(service_.get(), &transfer_callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); // Set an account and use it to login. AccountManager::Account account; account.id = kTestAccountId; account_manager().SetAccount(account); std::unique_ptr signin_attempt = service_->GetAccountManager()->Login("test_client_id", "test_client_secret"); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); // Logout user. absl::Notification logout_notification; service_->GetAccountManager()->Logout([&](absl::Status status) { EXPECT_TRUE(status.ok()); logout_notification.Notify(); }); EXPECT_TRUE(logout_notification.WaitForNotificationWithTimeout(kWaitTimeout)); } TEST_F(NearbySharingServiceImplTest, IsReceivingEnabledWithRegisterReceiveSurfaceForeground) { SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, IsReceivingDisabledWithRegisterReceiveSurfaceForeground) { MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, IsReceivingEnabledWithRegisterReceiveSurfaceBackground) { MockTransferUpdateCallback callback; service_->GetSettings()->SetVisibility( DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE); NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_TRUE(sharing_service_task_runner_->SyncWithTimeout(kTaskWaitTimeout)); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, IsReceivingDisabledWithRegisterReceiveSurfaceBackground) { MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, NoAdvertisingWhenHidden) { MockTransferUpdateCallback callback; SetVisibility(DeviceVisibility::DEVICE_VISIBILITY_HIDDEN); NearbySharingService::StatusCodes result = RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); ScopedReceiveSurface r(service_.get(), &callback); EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); } TEST_F(NearbySharingServiceImplTest, RemoveIncomingPayloads) { fake_nearby_connections_manager_->AddUnknownFilePathsToDeleteForTesting( FilePath{"test1.txt"}); fake_nearby_connections_manager_->AddUnknownFilePathsToDeleteForTesting( FilePath{"test2.txt"}); auto unknown_file_paths_to_delete = fake_nearby_connections_manager_->GetUnknownFilePathsToDeleteForTesting(); EXPECT_EQ(unknown_file_paths_to_delete.size(), 2); EXPECT_THAT( unknown_file_paths_to_delete, UnorderedElementsAre(FilePath("test1.txt"), FilePath("test2.txt"))); nearby::analytics::MockEventLogger mock_event_logger; analytics::AnalyticsRecorder analytics_recorder{/*vendor_id=*/0, &mock_event_logger}; ShareTarget share_target; share_target.is_incoming = true; IncomingShareSession session( fake_context_.fake_clock(), *sharing_service_task_runner_, fake_nearby_connections_manager_, analytics_recorder, "endpoint_id", share_target, [](const IncomingShareSession&, const TransferMetadata&) {}); service_->RemoveIncomingPayloads(session); EXPECT_EQ( fake_nearby_connections_manager_->GetUnknownFilePathsToDeleteForTesting() .size(), 0); // Test GetAndClearUnknownFilePathsToDelete fake_nearby_connections_manager_->AddUnknownFilePathsToDeleteForTesting( FilePath{"test1.txt"}); fake_nearby_connections_manager_->AddUnknownFilePathsToDeleteForTesting( FilePath{"test2.txt"}); unknown_file_paths_to_delete = fake_nearby_connections_manager_->GetAndClearUnknownFilePathsToDelete(); EXPECT_EQ(unknown_file_paths_to_delete.size(), 2); EXPECT_EQ( fake_nearby_connections_manager_->GetUnknownFilePathsToDeleteForTesting() .size(), 0); } TEST_F(NearbySharingServiceImplTest, NotifyLogoutSucceededWithCredentialError) { TestObserver observer(service_.get()); ::nearby::AccountManager::Account account; account.id = kTestAccountId; account_manager().SetAccount(account); account_manager().NotifyCredentialError(); FlushTesting(); EXPECT_TRUE(observer.credential_error_called_); // Remove the observer before it goes out of scope. service_->RemoveObserver(&observer); FlushTesting(); } } // namespace NearbySharingServiceUnitTests } // namespace nearby::sharing