diff --git a/sharing/certificates/BUILD b/sharing/certificates/BUILD index 26b5291d..40f09113 100644 --- a/sharing/certificates/BUILD +++ b/sharing/certificates/BUILD @@ -41,12 +41,13 @@ cc_library( deps = [ "//internal/base", "//internal/crypto_cros", + "//internal/flags:nearby_flags", "//internal/platform:types", "//internal/platform/implementation:account_manager", - "//internal/platform/implementation:types", "//sharing/common", "//sharing/common:enum", "//sharing/contacts", + "//sharing/flags/generated:generated_flags", "//sharing/internal/api:platform", "//sharing/internal/base", "//sharing/internal/public:logging", @@ -114,13 +115,14 @@ cc_test( deps = [ ":certificates", ":test_support", + "//internal/flags:nearby_flags", "//internal/platform/implementation:account_manager", - "//internal/platform/implementation:types", "//internal/platform/implementation/g3", # fixdeps: keep "//internal/test", "//sharing/common", "//sharing/common:enum", "//sharing/contacts:test_support", + "//sharing/flags/generated:generated_flags", "//sharing/internal/api:mock_sharing_platform", "//sharing/internal/public:logging", "//sharing/internal/test:nearby_test", diff --git a/sharing/certificates/nearby_share_certificate_manager_impl.cc b/sharing/certificates/nearby_share_certificate_manager_impl.cc index fdb94d23..4736cfe4 100644 --- a/sharing/certificates/nearby_share_certificate_manager_impl.cc +++ b/sharing/certificates/nearby_share_certificate_manager_impl.cc @@ -37,6 +37,7 @@ #include "absl/synchronization/notification.h" #include "absl/time/time.h" #include "absl/types/span.h" +#include "internal/flags/nearby_flags.h" #include "internal/platform/implementation/account_manager.h" #include "sharing/certificates/common.h" #include "sharing/certificates/constants.h" @@ -48,6 +49,7 @@ #include "sharing/certificates/nearby_share_private_certificate.h" #include "sharing/common/nearby_share_prefs.h" #include "sharing/contacts/nearby_share_contact_manager.h" +#include "sharing/flags/generated/nearby_sharing_feature_flags.h" #include "sharing/internal/api/bluetooth_adapter.h" #include "sharing/internal/api/preference_manager.h" #include "sharing/internal/api/public_certificate_database.h" @@ -384,11 +386,11 @@ void NearbyShareCertificateManagerImpl::DownloadPublicCertificates() { } void NearbyShareCertificateManagerImpl::UploadLocalDeviceCertificates() { - executor_->PostTask([&]() { - NL_LOG(INFO) << __func__ << ": Start to upload local device certificates."; + executor_->PostTask([this]() { + LOG(INFO) << __func__ << ": Start to upload local device certificates."; if (!is_running()) { - NL_LOG(WARNING) + LOG(WARNING) << __func__ << ": Ignore to upload local device certificates due to manager is " "not running."; @@ -396,10 +398,9 @@ void NearbyShareCertificateManagerImpl::UploadLocalDeviceCertificates() { } if (!account_manager_.GetCurrentAccount().has_value()) { - NL_LOG(WARNING) - << __func__ - << ": Ignore to upload local device certificates due to no " - "login account."; + LOG(WARNING) << __func__ + << ": Ignore to upload local device certificates due to no " + "login account."; upload_local_device_certificates_scheduler_->HandleResult( /*success=*/true); return; @@ -413,20 +414,50 @@ void NearbyShareCertificateManagerImpl::UploadLocalDeviceCertificates() { public_certs.push_back(*private_cert.ToPublicCertificate()); } - NL_LOG(INFO) << __func__ << ": Uploading " << public_certs.size() - << " local device certificates."; bool upload_certificates_result = false; absl::Notification notification; - local_device_data_manager_->UploadCertificates( - std::move(public_certs), [&](bool success) { - upload_certificates_result = success; - notification.Notify(); - }); + if (NearbyFlags::GetInstance().GetBoolFlag( + config_package_nearby::nearby_sharing_feature:: + kCallNearbyIdentityApi)) { + LOG(INFO) << __func__ << ": [Call Identity API] PublishDevice: upload " + << public_certs.size() << " local device certificates."; + local_device_data_manager_->PublishDevice( + std::move(public_certs), call_publish_device_after_certs_regen_, + [this, &upload_certificates_result, ¬ification]( + bool success, bool contact_removed) { + upload_certificates_result = success; + call_publish_device_after_certs_regen_ = contact_removed; + notification.Notify(); + }); + } else { + LOG(INFO) << __func__ + << ": [Call NearbyShare API] UploadCertificates: upload" + << public_certs.size() << " local device certificates."; + local_device_data_manager_->UploadCertificates( + std::move(public_certs), [&](bool success) { + upload_certificates_result = success; + notification.Notify(); + }); + } notification.WaitForNotification(); - NL_LOG(INFO) << __func__ << ": Upload of local device certificates " - << (upload_certificates_result ? "succeeded" : "failed."); + LOG(INFO) << __func__ << ": Upload of local device certificates " + << (upload_certificates_result ? "succeeded" : "failed."); upload_local_device_certificates_scheduler_->HandleResult( upload_certificates_result); + + // TODO(b/373780923): add Unit test for the two RPC calls and add a cap to + // the number of time you can keep calling PublishDevice due to contacts + // changes (it could indicate a server bug). + if (call_publish_device_after_certs_regen_ && + NearbyFlags::GetInstance().GetBoolFlag( + config_package_nearby::nearby_sharing_feature:: + kCallNearbyIdentityApi)) { + LOG(INFO) << __func__ + << ": [Call Identity API] Another call to PublishDevice after " + "regenerating all Private certificates: "; + certificate_storage_->ClearPrivateCertificates(); + private_certificate_expiration_scheduler_->MakeImmediateRequest(); + } }); } diff --git a/sharing/certificates/nearby_share_certificate_manager_impl.h b/sharing/certificates/nearby_share_certificate_manager_impl.h index 67baf99a..f8580359 100644 --- a/sharing/certificates/nearby_share_certificate_manager_impl.h +++ b/sharing/certificates/nearby_share_certificate_manager_impl.h @@ -213,6 +213,11 @@ class NearbyShareCertificateManagerImpl std::unique_ptr download_public_certificates_scheduler_; std::unique_ptr executor_; + // Whether we need to regenerate the certificates and make another + // PublishDevice call. At every PublishDevice call, we check + // PublishDeviceResponse to see if contacts are removed. In which case, we + // need to regenerate the certificates and make another PublishDevice call. + bool call_publish_device_after_certs_regen_ = false; }; } // namespace sharing diff --git a/sharing/certificates/nearby_share_certificate_manager_impl_test.cc b/sharing/certificates/nearby_share_certificate_manager_impl_test.cc index ca12e6ff..3cc0876e 100644 --- a/sharing/certificates/nearby_share_certificate_manager_impl_test.cc +++ b/sharing/certificates/nearby_share_certificate_manager_impl_test.cc @@ -35,6 +35,7 @@ #include "absl/strings/string_view.h" #include "absl/time/time.h" #include "absl/types/span.h" +#include "internal/flags/nearby_flags.h" #include "internal/platform/implementation/account_manager.h" #include "internal/test/fake_account_manager.h" #include "sharing/certificates/constants.h" @@ -47,6 +48,7 @@ #include "sharing/certificates/test_util.h" #include "sharing/common/nearby_share_prefs.h" #include "sharing/contacts/fake_nearby_share_contact_manager.h" +#include "sharing/flags/generated/nearby_sharing_feature_flags.h" #include "sharing/internal/api/fake_nearby_share_client.h" #include "sharing/internal/api/mock_sharing_platform.h" #include "sharing/internal/public/logging.h" @@ -167,6 +169,7 @@ class NearbyShareCertificateManagerImplTest cert_manager_->RemoveObserver(this); NearbyShareSchedulerFactory::SetFactoryForTesting(nullptr); NearbyShareCertificateStorageImpl::Factory::SetFactoryForTesting(nullptr); + NearbyFlags::GetInstance().ResetOverridedValues(); } void SetBluetoothMacAddress(absl::string_view bluetooth_mac_address) { @@ -323,6 +326,28 @@ class NearbyShareCertificateManagerImplTest EXPECT_EQ(upload_scheduler_->handled_results().back(), success); } + void RunPublishDevice(bool success) { + size_t initial_num_upload_calls = + local_device_data_manager_->publish_device_calls().size(); + local_device_data_manager_->SetPublishDeviceResult(success); + size_t initial_num_handled_results = + upload_scheduler_->handled_results().size(); + + upload_scheduler_->InvokeRequestCallback(); + Sync(); + EXPECT_EQ(local_device_data_manager_->publish_device_calls().size(), + initial_num_upload_calls + 1); + + EXPECT_EQ(local_device_data_manager_->publish_device_calls() + .back() + .certificates.size(), + 3 * kNearbyShareNumPrivateCertificates); + + EXPECT_EQ(upload_scheduler_->handled_results().size(), + initial_num_handled_results + 1); + EXPECT_EQ(upload_scheduler_->handled_results().back(), success); + } + // Test downloading public certificates with or without errors. The RPC is // paginated, and |num_pages| will be simulated. Any failures, as indicated by // |result|, will be simulated on the last page. @@ -703,6 +728,19 @@ TEST_F(NearbyShareCertificateManagerImplTest, VerifyPrivateCertificates(/*expected_metadata=*/GetNearbyShareTestMetadata()); } +TEST_F(NearbyShareCertificateManagerImplTest, + RefreshPrivateCertificates_PublishDevice_NoCertificates_UploadSuccess) { + NearbyFlags::GetInstance().OverrideBoolFlagValue( + config_package_nearby::nearby_sharing_feature::kCallNearbyIdentityApi, + true); + cert_store_->ReplacePrivateCertificates({}); + + HandlePrivateCertificateRefresh(/*expect_private_cert_refresh=*/true, + /*expected_success=*/true); + RunPublishDevice(/*success=*/true); + VerifyPrivateCertificates(/*expected_metadata=*/GetNearbyShareTestMetadata()); +} + TEST_F(NearbyShareCertificateManagerImplTest, RefreshPrivateCertificates_NoCertificates_UploadFailure) { cert_store_->ReplacePrivateCertificates({}); diff --git a/sharing/contacts/BUILD b/sharing/contacts/BUILD index b22d00f2..bf3a3e9b 100644 --- a/sharing/contacts/BUILD +++ b/sharing/contacts/BUILD @@ -30,9 +30,11 @@ cc_library( deps = [ "//internal/base", "//internal/crypto_cros", + "//internal/flags:nearby_flags", "//internal/platform:types", "//internal/platform/implementation:account_manager", "//sharing/common", + "//sharing/flags/generated:generated_flags", "//sharing/internal/api:platform", "//sharing/internal/base", "//sharing/internal/public:logging", @@ -43,7 +45,6 @@ cc_library( "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/functional:bind_front", "@com_google_absl//absl/memory", - "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", "@com_google_absl//absl/synchronization", diff --git a/sharing/contacts/nearby_share_contact_manager_impl.cc b/sharing/contacts/nearby_share_contact_manager_impl.cc index 07afb338..fe07c2c4 100644 --- a/sharing/contacts/nearby_share_contact_manager_impl.cc +++ b/sharing/contacts/nearby_share_contact_manager_impl.cc @@ -31,11 +31,13 @@ #include "absl/synchronization/notification.h" #include "absl/time/time.h" #include "internal/crypto_cros/secure_hash.h" +#include "internal/flags/nearby_flags.h" #include "internal/platform/clock.h" #include "internal/platform/implementation/account_manager.h" #include "sharing/common/nearby_share_prefs.h" #include "sharing/contacts/nearby_share_contact_manager.h" #include "sharing/contacts/nearby_share_contacts_sorter.h" +#include "sharing/flags/generated/nearby_sharing_feature_flags.h" #include "sharing/internal/api/preference_manager.h" #include "sharing/internal/api/sharing_rpc_client.h" #include "sharing/internal/base/encode.h" @@ -172,7 +174,10 @@ NearbyShareContactManagerImpl::NearbyShareContactManagerImpl( /*require_connectivity=*/true, prefs::kNearbySharingSchedulerContactDownloadAndUploadName, [&] { DownloadContacts(); })), - executor_(context->CreateSequencedTaskRunner()) {} + executor_(context->CreateSequencedTaskRunner()), + use_identity_api_(NearbyFlags::GetInstance().GetBoolFlag( + config_package_nearby::nearby_sharing_feature:: + kCallNearbyIdentityApi)) {} NearbyShareContactManagerImpl::~NearbyShareContactManagerImpl() = default; @@ -230,6 +235,10 @@ void NearbyShareContactManagerImpl::ContactDownloadContext::FetchNextPage() { } void NearbyShareContactManagerImpl::DownloadContacts() { + if (use_identity_api_) { + LOG(INFO) << __func__ << ": [Call Identity API] Skipping DownloadContacts"; + return; + } executor_->PostTask([this]() { NL_LOG(INFO) << __func__ << ": Start to download contacts"; if (!is_running()) { @@ -287,10 +296,22 @@ void NearbyShareContactManagerImpl::GetContacts(ContactsCallback callback) { } void NearbyShareContactManagerImpl::OnStart() { + if (use_identity_api_) { + LOG(INFO) << __func__ + << ": [Call Identity API] Skipping " + "contact_download_and_upload_scheduler start."; + return; + } contact_download_and_upload_scheduler_->Start(); } void NearbyShareContactManagerImpl::OnStop() { + if (use_identity_api_) { + LOG(INFO) << __func__ + << ": [Call Identity API] Skipping " + "contact_download_and_upload_scheduler stop."; + return; + } contact_download_and_upload_scheduler_->Stop(); } diff --git a/sharing/contacts/nearby_share_contact_manager_impl.h b/sharing/contacts/nearby_share_contact_manager_impl.h index 7bf9d329..9697da8c 100644 --- a/sharing/contacts/nearby_share_contact_manager_impl.h +++ b/sharing/contacts/nearby_share_contact_manager_impl.h @@ -149,6 +149,9 @@ class NearbyShareContactManagerImpl : public NearbyShareContactManager { std::unique_ptr contact_download_and_upload_scheduler_; std::unique_ptr executor_ = nullptr; + // Identity API does not support contacts upload/download. So essentially + // contact manager is inactive. + bool use_identity_api_ = false; }; } // namespace sharing diff --git a/sharing/local_device_data/BUILD b/sharing/local_device_data/BUILD index 46f9a213..c599a203 100644 --- a/sharing/local_device_data/BUILD +++ b/sharing/local_device_data/BUILD @@ -30,19 +30,23 @@ cc_library( "//internal/platform:types", "//internal/platform/implementation:account_manager", "//internal/platform/implementation:types", + "//proto/identity/v1:resources_cc_proto", + "//proto/identity/v1:rpcs_cc_proto", "//sharing/common", "//sharing/common:enum", "//sharing/internal/api:platform", "//sharing/internal/base:utf_utils", + "//sharing/internal/impl/common:nearby_identity_grpc_client", "//sharing/internal/public:logging", "//sharing/internal/public:types", "//sharing/proto:share_cc_proto", - "//sharing/scheduling", + "//util/hash:highway_fingerprint", + "@com_google_absl//absl/algorithm", + "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/memory", "@com_google_absl//absl/random", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", - "@com_google_absl//absl/time", ], ) @@ -63,7 +67,6 @@ cc_library( "//sharing/internal/public:types", "//sharing/proto:share_cc_proto", "@com_google_absl//absl/strings", - "@com_google_absl//absl/types:optional", ], ) @@ -77,9 +80,12 @@ cc_test( "//internal/platform/implementation:account_manager", "//internal/platform/implementation/g3", # fixdeps: keep "//internal/test", + "//proto/identity/v1:resources_cc_proto", + "//proto/identity/v1:rpcs_cc_proto", "//sharing/common", "//sharing/common:enum", "//sharing/internal/api:mock_sharing_platform", + "//sharing/internal/public:logging", "//sharing/internal/test:nearby_test", "//sharing/proto:share_cc_proto", "//sharing/scheduling", diff --git a/sharing/local_device_data/fake_nearby_share_local_device_data_manager.cc b/sharing/local_device_data/fake_nearby_share_local_device_data_manager.cc index 4f7467c7..a9f60840 100644 --- a/sharing/local_device_data/fake_nearby_share_local_device_data_manager.cc +++ b/sharing/local_device_data/fake_nearby_share_local_device_data_manager.cc @@ -20,7 +20,6 @@ #include #include "absl/strings/string_view.h" -#include "absl/types/optional.h" #include "sharing/common/nearby_share_enums.h" #include "sharing/internal/api/sharing_rpc_client.h" #include "sharing/internal/public/context.h" @@ -132,5 +131,15 @@ void FakeNearbyShareLocalDeviceDataManager::UploadCertificates( } } +void FakeNearbyShareLocalDeviceDataManager::PublishDevice( + std::vector certificates, + bool is_second_call, PublishDeviceCallback callback) { + publish_device_calls_.emplace_back(std::move(certificates), is_second_call, + callback); + if (is_sync_mode_) { + callback(publish_device_result_, false); + } +}; + } // namespace sharing } // namespace nearby diff --git a/sharing/local_device_data/fake_nearby_share_local_device_data_manager.h b/sharing/local_device_data/fake_nearby_share_local_device_data_manager.h index a0fb4317..960cfbe4 100644 --- a/sharing/local_device_data/fake_nearby_share_local_device_data_manager.h +++ b/sharing/local_device_data/fake_nearby_share_local_device_data_manager.h @@ -90,6 +90,19 @@ class FakeNearbyShareLocalDeviceDataManager UploadCompleteCallback callback; }; + struct PublishDeviceCall { + PublishDeviceCall( + std::vector certificates, + bool is_second_call, PublishDeviceCallback callback) + : certificates(std::move(certificates)), + callback(std::move(callback)) {} + PublishDeviceCall(PublishDeviceCall&&) = default; + ~PublishDeviceCall() = default; + + std::vector certificates; + PublishDeviceCallback callback; + }; + explicit FakeNearbyShareLocalDeviceDataManager( absl::string_view default_device_name); ~FakeNearbyShareLocalDeviceDataManager() override; @@ -106,6 +119,10 @@ class FakeNearbyShareLocalDeviceDataManager std::vector certificates, UploadCompleteCallback callback) override; + void PublishDevice( + std::vector certificates, + bool is_second_call, PublishDeviceCallback callback) override; + // Make protected observer-notification methods from the base class public in // this fake class. using NearbyShareLocalDeviceDataManager::NotifyLocalDeviceDataChanged; @@ -120,6 +137,10 @@ class FakeNearbyShareLocalDeviceDataManager return upload_certificates_calls_; } + std::vector& publish_device_calls() { + return publish_device_calls_; + } + void set_next_validation_result(DeviceNameValidationResult result) { next_validation_result_ = result; } @@ -135,6 +156,10 @@ class FakeNearbyShareLocalDeviceDataManager upload_certificate_result_ = upload_certificate_result; } + void SetPublishDeviceResult(bool publish_device_result) { + publish_device_result_ = publish_device_result; + } + private: // NearbyShareLocalDeviceDataManager: @@ -142,6 +167,7 @@ class FakeNearbyShareLocalDeviceDataManager std::string device_name_; std::vector upload_contacts_calls_; std::vector upload_certificates_calls_; + std::vector publish_device_calls_; DeviceNameValidationResult next_validation_result_ = DeviceNameValidationResult::kValid; @@ -149,6 +175,7 @@ class FakeNearbyShareLocalDeviceDataManager bool is_sync_mode_ = false; bool upload_contact_result_ = false; bool upload_certificate_result_ = false; + bool publish_device_result_ = false; }; } // namespace sharing diff --git a/sharing/local_device_data/nearby_share_local_device_data_manager.h b/sharing/local_device_data/nearby_share_local_device_data_manager.h index 1d6a3de7..0f7b7bc3 100644 --- a/sharing/local_device_data/nearby_share_local_device_data_manager.h +++ b/sharing/local_device_data/nearby_share_local_device_data_manager.h @@ -47,6 +47,8 @@ class NearbyShareLocalDeviceDataManager { }; using UploadCompleteCallback = std::function; + using PublishDeviceCallback = + std::function; NearbyShareLocalDeviceDataManager(); virtual ~NearbyShareLocalDeviceDataManager(); @@ -96,6 +98,12 @@ class NearbyShareLocalDeviceDataManager { std::vector certificates, UploadCompleteCallback callback) = 0; + // Calls Identity PublishDevice RPC to upload local device's public + // certificates. + virtual void PublishDevice( + std::vector certificates, + bool force_update_contacts, PublishDeviceCallback callback) = 0; + protected: void NotifyLocalDeviceDataChanged(bool did_device_name_change, bool did_full_name_change, diff --git a/sharing/local_device_data/nearby_share_local_device_data_manager_impl.cc b/sharing/local_device_data/nearby_share_local_device_data_manager_impl.cc index 25af9f38..894a75a5 100644 --- a/sharing/local_device_data/nearby_share_local_device_data_manager_impl.cc +++ b/sharing/local_device_data/nearby_share_local_device_data_manager_impl.cc @@ -25,16 +25,18 @@ #include #include +#include "absl/algorithm/algorithm.h" #include "absl/memory/memory.h" #include "absl/random/random.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" -#include "absl/time/time.h" #include "internal/platform/device_info.h" #include "internal/platform/implementation/account_manager.h" #include "internal/platform/implementation/device_info.h" +#include "proto/identity/v1/resources.pb.h" +#include "proto/identity/v1/rpcs.pb.h" #include "sharing/common/nearby_share_enums.h" #include "sharing/common/nearby_share_prefs.h" #include "sharing/internal/api/preference_manager.h" @@ -46,12 +48,14 @@ #include "sharing/proto/device_rpc.pb.h" #include "sharing/proto/field_mask.pb.h" #include "sharing/proto/rpc_resources.pb.h" -#include "sharing/scheduling/nearby_share_scheduler.h" -#include "sharing/scheduling/nearby_share_scheduler_factory.h" +#include "sharing/proto/timestamp.pb.h" +#include "util/hash/highway_fingerprint.h" namespace nearby { namespace sharing { namespace { +using ::google::nearby::identity::v1::PublishDeviceRequest; +using ::google::nearby::identity::v1::PublishDeviceResponse; using ::nearby::api::DeviceInfo; using ::nearby::sharing::api::PreferenceManager; using ::nearby::sharing::api::SharingRpcClientFactory; @@ -131,6 +135,7 @@ NearbyShareLocalDeviceDataManagerImpl::NearbyShareLocalDeviceDataManagerImpl( account_manager_(account_manager), device_info_(device_info), nearby_share_client_(rpc_client_factory->CreateInstance()), + nearby_identity_client_(rpc_client_factory->CreateIdentityInstance()), device_id_(GetId()), executor_(context->CreateSequencedTaskRunner()) {} @@ -228,6 +233,107 @@ void NearbyShareLocalDeviceDataManagerImpl::UploadContacts( }); }); } +void NearbyShareLocalDeviceDataManagerImpl::PublishDevice( + std::vector certificates, + bool force_update_contacts, PublishDeviceCallback callback) { + executor_->PostTask([this, force_update_contacts, + certificates = std::move(certificates), + callback = std::move(callback)]() mutable { + if (!is_running()) { + LOG(WARNING) << __func__ + << ": [Call Identity API] no-op as manager is stopped."; + callback(/*success=*/false, /*contact_removed=*/false); + return; + } + LOG(INFO) << __func__ << ": [Call Identity API] Upload " + << certificates.size() << " certificates."; + + PublishDeviceRequest request; + request.mutable_device()->set_name(absl::StrCat("devices/", device_id_)); + LOG(INFO) << __func__ + << ": [Call Identity API] PublishDeviceRequest with Device.name: " + << request.device().name(); + request.mutable_device()->set_display_name(GetDeviceName()); + // Force update contacts call is right after CONTACT_GOOGLE_CONTACT_LATEST + // call and can use CONTACT_GOOGLE_CONTACT to save server side computation. + + request.mutable_device()->set_contact( + force_update_contacts + ? google::nearby::identity::v1::Device::CONTACT_GOOGLE_CONTACT + : google::nearby::identity::v1::Device:: + CONTACT_GOOGLE_CONTACT_LATEST); + + auto* new_self_credential = + request.mutable_device()->add_per_visibility_shared_credentials(); + new_self_credential->set_visibility( + google::nearby::identity::v1::PerVisibilitySharedCredentials:: + VISIBILITY_SELF); + auto* new_contacts_credential = + request.mutable_device()->add_per_visibility_shared_credentials(); + new_contacts_credential->set_visibility( + google::nearby::identity::v1::PerVisibilitySharedCredentials:: + VISIBILITY_CONTACTS); + + for (const auto& certificate : certificates) { + google::nearby::identity::v1::SharedCredential* shared_credential; + if (certificate.for_self_share()) { + shared_credential = new_self_credential->add_shared_credentials(); + LOG(INFO) << __func__ << ": [Call Identity API] self_share"; + } else { + shared_credential = new_contacts_credential->add_shared_credentials(); + LOG(INFO) << __func__ << ": [Call Identity API] contacts_share"; + } + + shared_credential->set_id( + util_hash::HighwayFingerprint64(certificate.secret_id())); + shared_credential->set_data(certificate.SerializeAsString()); + shared_credential->set_data_type( + ::google::nearby::identity::v1::SharedCredential:: + DATA_TYPE_PUBLIC_CERTIFICATE); + *shared_credential->mutable_expiration_time() = certificate.end_time(); + LOG(INFO) << __func__ + << ": shared_credential.id(): " << shared_credential->id(); + } + nearby_identity_client_->PublishDevice( + request, [this, callback = std::move(callback)]( + const absl::StatusOr& response) { + // check whether the manager is running again + if (!is_running()) { + LOG(WARNING) + << __func__ + << ": [Call Identity API] manager is stopped after call."; + callback(/*success=*/false, /*contact_removed=*/false); + return; + } + if (!response.ok()) { + LOG(WARNING) + << __func__ + << ": [Call Identity API] Failed to get response from backend: " + << response.status(); + callback(/*success=*/false, /*contact_removed=*/false); + return; + } + + LOG(INFO) << __func__ + << ": [Call Identity API] Successfully published device."; + + // If contacts are removed, regenerate all Private certificates and + // make a 2nd PublishDevice RPC call. + bool need_another_call = false; + if (absl::linear_search( + response.value().contact_updates().begin(), + response.value().contact_updates().end(), + google::nearby::identity::v1::PublishDeviceResponse:: + CONTACT_UPDATE_REMOVED)) { + need_another_call = true; + LOG(INFO) + << __func__ + << ": [Call Identity API] need another PublishDevice call"; + } + callback(/*success=*/true, /*contact_removed=*/need_another_call); + }); + }); +} void NearbyShareLocalDeviceDataManagerImpl::UploadCertificates( std::vector certificates, @@ -250,7 +356,6 @@ void NearbyShareLocalDeviceDataManagerImpl::UploadCertificates( callback(/*success=*/true); return; } - UpdateDeviceRequest request; request.mutable_device()->set_name( absl::StrCat(kDeviceIdPrefix, device_id_)); diff --git a/sharing/local_device_data/nearby_share_local_device_data_manager_impl.h b/sharing/local_device_data/nearby_share_local_device_data_manager_impl.h index 183ce270..7145f6ac 100644 --- a/sharing/local_device_data/nearby_share_local_device_data_manager_impl.h +++ b/sharing/local_device_data/nearby_share_local_device_data_manager_impl.h @@ -27,6 +27,7 @@ #include "sharing/common/nearby_share_enums.h" #include "sharing/internal/api/preference_manager.h" #include "sharing/internal/api/sharing_rpc_client.h" +#include "sharing/internal/impl/common/nearby_identity_grpc_client.h" #include "sharing/internal/public/context.h" #include "sharing/local_device_data/nearby_share_local_device_data_manager.h" #include "sharing/proto/rpc_resources.pb.h" @@ -85,6 +86,10 @@ class NearbyShareLocalDeviceDataManagerImpl std::vector certificates, UploadCompleteCallback callback) override; + void PublishDevice( + std::vector certificates, + bool force_update_contacts, PublishDeviceCallback callback) override; + // Creates a default device name of the form "'s ." // For example, "Josh's Chromebook." If a given name cannot be found, returns // just the device type. If the resulting name is too long the user's name @@ -95,6 +100,8 @@ class NearbyShareLocalDeviceDataManagerImpl AccountManager& account_manager_; nearby::DeviceInfo& device_info_; std::unique_ptr nearby_share_client_; + std::unique_ptr + nearby_identity_client_; const std::string device_id_; std::unique_ptr executor_; }; diff --git a/sharing/local_device_data/nearby_share_local_device_data_manager_impl_test.cc b/sharing/local_device_data/nearby_share_local_device_data_manager_impl_test.cc index 83005eab..c20d1b16 100644 --- a/sharing/local_device_data/nearby_share_local_device_data_manager_impl_test.cc +++ b/sharing/local_device_data/nearby_share_local_device_data_manager_impl_test.cc @@ -26,6 +26,7 @@ #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" #include "absl/strings/substitute.h" #include "absl/time/time.h" #include "absl/types/optional.h" @@ -33,14 +34,18 @@ #include "internal/test/fake_account_manager.h" #include "internal/test/fake_device_info.h" #include "internal/test/fake_task_runner.h" +#include "proto/identity/v1/resources.pb.h" +#include "proto/identity/v1/rpcs.pb.h" #include "sharing/common/nearby_share_enums.h" #include "sharing/common/nearby_share_prefs.h" #include "sharing/internal/api/fake_nearby_share_client.h" +#include "sharing/internal/public/logging.h" #include "sharing/internal/test/fake_context.h" #include "sharing/internal/test/fake_preference_manager.h" #include "sharing/local_device_data/nearby_share_local_device_data_manager.h" #include "sharing/proto/device_rpc.pb.h" #include "sharing/proto/rpc_resources.pb.h" +#include "sharing/proto/timestamp.pb.h" #include "sharing/scheduling/fake_nearby_share_scheduler_factory.h" #include "sharing/scheduling/nearby_share_scheduler_factory.h" @@ -49,6 +54,7 @@ namespace sharing { namespace { using UpdateDeviceResponse = nearby::sharing::proto::UpdateDeviceResponse; +using google::nearby::identity::v1::PublishDeviceResponse; using Contact = nearby::sharing::proto::Contact; const char kDefaultDeviceName[] = "$0\'s $1"; @@ -232,6 +238,10 @@ class NearbyShareLocalDeviceDataManagerImplTest return nearby_client_factory_.instances().back(); } + FakeNearbyIdentityClient* identity_client() { + return nearby_client_factory_.identity_instances().back(); + } + void Sync() { EXPECT_TRUE(context_.last_sequenced_task_runner()->SyncWithTimeout( absl::Milliseconds(1000))); @@ -360,6 +370,183 @@ TEST_F(NearbyShareLocalDeviceDataManagerImplTest, UploadCertificates_Failure) { UploadCertificates(/*response=*/absl::InternalError("")); } +std::vector GetTestCertificates() { + nearby::sharing::proto::PublicCertificate cert1; + cert1.set_secret_id("id1"); + cert1.set_for_self_share(true); + cert1.mutable_end_time()->set_seconds(1000); + cert1.mutable_end_time()->set_nanos(2000); + + nearby::sharing::proto::PublicCertificate cert2; + cert2.set_secret_id("id2"); + cert2.set_for_self_share(false); + cert2.mutable_end_time()->set_seconds(2000); + cert2.mutable_end_time()->set_nanos(200); + + nearby::sharing::proto::PublicCertificate cert3; + cert3.set_secret_id("id3"); + cert3.set_for_self_share(true); + cert3.mutable_end_time()->set_seconds(3000); + cert3.mutable_end_time()->set_nanos(300); + + nearby::sharing::proto::PublicCertificate cert4; + cert4.set_secret_id("id4"); + cert4.set_for_self_share(false); + cert4.mutable_end_time()->set_seconds(4000); + cert4.mutable_end_time()->set_nanos(400); + return {cert1, cert2, cert3, cert4}; +} + +TEST_F(NearbyShareLocalDeviceDataManagerImplTest, + PublishDeviceInitialCall_ContactUpdateAdded) { + CreateManager(); + bool returned_success; + bool returned_make_another_call; + PublishDeviceResponse response; + response.add_contact_updates(google::nearby::identity::v1:: + PublishDeviceResponse::CONTACT_UPDATE_ADDED); + + identity_client()->SetPublishDeviceResponse( + absl::StatusOr(response)); + manager()->PublishDevice(GetTestCertificates(), /*is_second_call=*/false, + [&returned_success, &returned_make_another_call]( + bool success, bool make_another_call) { + returned_success = success; + returned_make_another_call = make_another_call; + }); + + Sync(); + auto request = identity_client()->publish_device_requests().back(); + EXPECT_EQ(request.device().name(), + absl::StrCat("devices/", manager()->GetId())); + EXPECT_EQ(request.device().display_name(), "Barack奥巴马's PC"); + EXPECT_EQ( + request.device().contact(), + google::nearby::identity::v1::Device::CONTACT_GOOGLE_CONTACT_LATEST); + ASSERT_EQ(request.device().per_visibility_shared_credentials_size(), 2); + + auto self_credential = request.device().per_visibility_shared_credentials(0); + EXPECT_EQ(self_credential.visibility(), + google::nearby::identity::v1::PerVisibilitySharedCredentials:: + VISIBILITY_SELF); + EXPECT_EQ(self_credential.shared_credentials_size(), 2); + EXPECT_EQ(self_credential.shared_credentials(0).id(), 4993322223562966528); + + ASSERT_EQ(GetTestCertificates().size(), 4); + EXPECT_EQ(self_credential.shared_credentials(0).data(), + GetTestCertificates().at(0).SerializeAsString()); + EXPECT_EQ(self_credential.shared_credentials(0).data_type(), + google::nearby::identity::v1::SharedCredential:: + DATA_TYPE_PUBLIC_CERTIFICATE); + EXPECT_EQ(self_credential.shared_credentials(0).expiration_time().seconds(), + 1000); + EXPECT_EQ(self_credential.shared_credentials(0).expiration_time().nanos(), + 2000); + + EXPECT_EQ(self_credential.shared_credentials(1).id(), 2903692628687846585); + EXPECT_EQ(self_credential.shared_credentials(1).data(), + GetTestCertificates().at(2).SerializeAsString()); + EXPECT_EQ(self_credential.shared_credentials(1).data_type(), + google::nearby::identity::v1::SharedCredential:: + DATA_TYPE_PUBLIC_CERTIFICATE); + EXPECT_EQ(self_credential.shared_credentials(1).expiration_time().seconds(), + 3000); + EXPECT_EQ(self_credential.shared_credentials(1).expiration_time().nanos(), + 300); + + auto contact_credential = + request.device().per_visibility_shared_credentials(1); + EXPECT_EQ(contact_credential.visibility(), + google::nearby::identity::v1::PerVisibilitySharedCredentials:: + VISIBILITY_CONTACTS); + ASSERT_EQ(contact_credential.shared_credentials_size(), 2); + EXPECT_EQ(contact_credential.shared_credentials(0).id(), + -5684021477085783942); + EXPECT_EQ(contact_credential.shared_credentials(0).data(), + GetTestCertificates().at(1).SerializeAsString()); + EXPECT_EQ(contact_credential.shared_credentials(0).data_type(), + google::nearby::identity::v1::SharedCredential:: + DATA_TYPE_PUBLIC_CERTIFICATE); + EXPECT_EQ( + contact_credential.shared_credentials(0).expiration_time().seconds(), + 2000); + EXPECT_EQ(contact_credential.shared_credentials(0).expiration_time().nanos(), + 200); + + EXPECT_TRUE(returned_success); + EXPECT_FALSE(returned_make_another_call); +} + +TEST_F(NearbyShareLocalDeviceDataManagerImplTest, + PublishDeviceInitialCall_ContactUpdateRemoved) { + CreateManager(); + bool returned_success; + bool returned_make_another_call; + PublishDeviceResponse response; + response.add_contact_updates( + google::nearby::identity::v1::PublishDeviceResponse:: + CONTACT_UPDATE_REMOVED); + + identity_client()->SetPublishDeviceResponse( + absl::StatusOr(response)); + manager()->PublishDevice(GetTestCertificates(), /*is_second_call=*/false, + [&returned_success, &returned_make_another_call]( + bool success, bool make_another_call) { + returned_success = success; + returned_make_another_call = make_another_call; + }); + + Sync(); + + EXPECT_TRUE(returned_success); + // 2nd call is needed to regenerate all Private certificates. + EXPECT_TRUE(returned_make_another_call); +} + +TEST_F(NearbyShareLocalDeviceDataManagerImplTest, + PublishDeviceSecondCall_ContactUnchanged) { + CreateManager(); + bool returned_success; + bool returned_make_another_call; + PublishDeviceResponse response; + + identity_client()->SetPublishDeviceResponse( + absl::StatusOr(response)); + manager()->PublishDevice(GetTestCertificates(), /*is_second_call=*/true, + [&returned_success, &returned_make_another_call]( + bool success, bool make_another_call) { + returned_success = success; + returned_make_another_call = make_another_call; + }); + + Sync(); + auto request = identity_client()->publish_device_requests().back(); + + EXPECT_EQ(request.device().contact(), + google::nearby::identity::v1::Device::CONTACT_GOOGLE_CONTACT); + + EXPECT_TRUE(returned_success); + // Contacts are not changed, no need to make another call. + EXPECT_FALSE(returned_make_another_call); +} + +TEST_F(NearbyShareLocalDeviceDataManagerImplTest, PublishDevice_Failure) { + CreateManager(); + bool returned_success; + bool returned_make_another_call; + identity_client()->SetPublishDeviceResponse(absl::InternalError("")); + manager()->PublishDevice(GetTestCertificates(), /*is_second_call=*/false, + [&returned_success, &returned_make_another_call]( + bool success, bool make_another_call) { + returned_success = success; + returned_make_another_call = make_another_call; + }); + + Sync(); + EXPECT_FALSE(returned_success); + EXPECT_FALSE(returned_make_another_call); +} + } // namespace } // namespace sharing } // namespace nearby diff --git a/sharing/nearby_sharing_service_impl.cc b/sharing/nearby_sharing_service_impl.cc index 94270d5c..73d55a55 100644 --- a/sharing/nearby_sharing_service_impl.cc +++ b/sharing/nearby_sharing_service_impl.cc @@ -500,9 +500,10 @@ void NearbySharingServiceImpl::RegisterSendSurface( // user to be blocked for hours waiting for a periodic sync. if (state == SendSurfaceState::kForeground && !last_outgoing_metadata_) { - VLOG(1) << __func__ << ": Downloading contacts & certificates from " - << "Nearby server at start of sending flow."; contact_manager_->DownloadContacts(); + VLOG(1) << __func__ + << ": Downloading public certificates from Nearby server at " + "start of sending flow."; certificate_manager_->DownloadPublicCertificates(); } @@ -1030,9 +1031,10 @@ void NearbySharingServiceImpl::OnIncomingConnection( // need to wait for these calls to finish. The periodic server requests will // typically be sufficient, but we don't want the user to be blocked for // hours waiting for a periodic sync. - VLOG(1) << __func__ << ": Downloading contacts, and certificates from " - << "Nearby server at start of receiving flow."; + contact_manager_->DownloadContacts(); + VLOG(1) << __func__ << ": Downloading certificates from " + << "Nearby server at start of receiving flow."; certificate_manager_->DownloadPublicCertificates(); ShareTarget placeholder_share_target;