mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Merge remote-tracking branch 'nearby/main'
# Conflicts: # connections/implementation/bwu_manager_test.cc # sharing/BUILD # sharing/certificates/fake_nearby_share_certificate_manager.cc # sharing/certificates/fake_nearby_share_certificate_manager.h # sharing/internal/base/utf_string_conversions.h
This commit is contained in:
@@ -250,6 +250,7 @@ cc_library(
|
||||
"//internal/base:files",
|
||||
"//internal/platform:types",
|
||||
"//location/nearby/sharing/lib/sync:sync_manager",
|
||||
"//location/nearby/cpp/sharing/clients/cpp/common",
|
||||
"//proto:sharing_enums_cc_proto",
|
||||
"//sharing/analytics",
|
||||
"//sharing/certificates",
|
||||
@@ -393,6 +394,7 @@ cc_library(
|
||||
"//connections/implementation/analytics:analytics_recorder_impl",
|
||||
"//internal/base",
|
||||
"//internal/base:file_path",
|
||||
"//internal/base:files",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/network:url",
|
||||
"//internal/platform:base",
|
||||
@@ -402,6 +404,7 @@ cc_library(
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation:types",
|
||||
#"//location/nearby/analytics/cpp/logging:event_logger",
|
||||
"//location/nearby/cpp/sharing/clients/cpp/common",
|
||||
"//location/nearby/sharing/lib/account:account_manager",
|
||||
"//location/nearby/sharing/lib/rpc:grpc_async_client_factory",
|
||||
"//location/nearby/sharing/lib/rpc:sharing_rpc_client",
|
||||
@@ -425,6 +428,7 @@ cc_library(
|
||||
"//sharing/proto:share_cc_proto",
|
||||
"//sharing/proto:wire_format_cc_proto",
|
||||
"//sharing/scheduling",
|
||||
"//third_party/gloop/util/time:protoutil",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/base:nullability",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
@@ -655,6 +659,7 @@ cc_test(
|
||||
":transfer_metadata",
|
||||
":transfer_metadata_matchers",
|
||||
":types",
|
||||
"//google/protobuf:timestamp_cc_proto",
|
||||
"//internal/base:file_path",
|
||||
"//internal/base:files",
|
||||
"//internal/flags:nearby_flags",
|
||||
|
||||
@@ -111,7 +111,9 @@ class AnalyticsRecorder {
|
||||
virtual void NewReceiveIntroduction(
|
||||
int64_t session_id, const ShareTarget& share_target,
|
||||
std::optional<std::string> referrer_package,
|
||||
location::nearby::proto::sharing::OSType share_target_os_type) = 0;
|
||||
location::nearby::proto::sharing::OSType share_target_os_type,
|
||||
location::nearby::proto::sharing::SharingUseCase sharing_use_case,
|
||||
location::nearby::proto::sharing::PowerStatus power_status) = 0;
|
||||
|
||||
virtual void NewRespondToIntroduction(
|
||||
location::nearby::proto::sharing::ResponseToIntroduction action,
|
||||
@@ -142,8 +144,7 @@ class AnalyticsRecorder {
|
||||
const AttachmentContainer& attachments,
|
||||
int transfer_position,
|
||||
int concurrent_connections,
|
||||
bool advanced_protection_enabled,
|
||||
bool advanced_protection_mismatch) = 0;
|
||||
bool advanced_protection_enabled) = 0;
|
||||
|
||||
virtual void NewSendFastInitialization() = 0;
|
||||
|
||||
@@ -159,7 +160,8 @@ class AnalyticsRecorder {
|
||||
virtual void NewSendIntroduction(
|
||||
int64_t session_id, const ShareTarget& share_target,
|
||||
int transfer_position, int concurrent_connections,
|
||||
location::nearby::proto::sharing::OSType share_target_os_type) = 0;
|
||||
location::nearby::proto::sharing::OSType share_target_os_type,
|
||||
location::nearby::proto::sharing::PowerStatus power_status) = 0;
|
||||
|
||||
virtual void NewSetVisibility(
|
||||
nearby::sharing::proto::DeviceVisibility src_visibility,
|
||||
|
||||
@@ -63,8 +63,11 @@ cc_library(
|
||||
"//sharing/proto:enums_cc_proto",
|
||||
"//sharing/proto:share_cc_proto",
|
||||
"//sharing/scheduling",
|
||||
"//third_party/gloop/util/time:protoutil",
|
||||
"//util/hash:highway_fingerprint",
|
||||
"@com_google_absl//absl/algorithm",
|
||||
"@com_google_absl//absl/algorithm:container",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/base:nullability",
|
||||
"@com_google_absl//absl/container:btree",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
@@ -145,6 +148,7 @@ cc_test(
|
||||
"//sharing/proto:share_cc_proto",
|
||||
"//sharing/scheduling",
|
||||
"//sharing/scheduling:test_support",
|
||||
"//third_party/gloop/util/time:protoutil",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/status",
|
||||
|
||||
@@ -20,9 +20,11 @@
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/base/file_path.h"
|
||||
#include "sharing/certificates/nearby_share_certificate_manager.h"
|
||||
#include "sharing/certificates/nearby_share_encrypted_metadata_key.h"
|
||||
@@ -102,6 +104,12 @@ void FakeNearbyShareCertificateManager::ClearPublicCertificates(
|
||||
callback(true);
|
||||
}
|
||||
|
||||
void FakeNearbyShareCertificateManager::AddBindingToPublicCertificate(
|
||||
absl::string_view certificate_id, absl::string_view binding_id) {
|
||||
add_binding_to_public_certificate_calls_.push_back(
|
||||
{std::string(certificate_id), std::string(binding_id)});
|
||||
}
|
||||
|
||||
std::optional<NearbySharePrivateCertificate>
|
||||
FakeNearbyShareCertificateManager::GetValidPrivateCertificate(
|
||||
DeviceVisibility visibility) const {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/base/file_path.h"
|
||||
#include "sharing/certificates/nearby_share_certificate_manager.h"
|
||||
#include "sharing/certificates/nearby_share_certificate_manager_impl.h"
|
||||
@@ -89,6 +90,11 @@ class FakeNearbyShareCertificateManager : public NearbyShareCertificateManager {
|
||||
CertDecryptedCallback callback;
|
||||
};
|
||||
|
||||
struct AddBindingToPublicCertificateCall {
|
||||
std::string certificate_id;
|
||||
std::string binding_id;
|
||||
};
|
||||
|
||||
FakeNearbyShareCertificateManager();
|
||||
~FakeNearbyShareCertificateManager() override;
|
||||
|
||||
@@ -100,6 +106,13 @@ class FakeNearbyShareCertificateManager : public NearbyShareCertificateManager {
|
||||
void ForceUploadPrivateCertificates() override {};
|
||||
void ClearPublicCertificates(std::function<void(bool)> callback) override;
|
||||
void SetVendorId(int32_t vendor_id) override {}
|
||||
void AddBindingToPublicCertificate(
|
||||
absl::string_view certificate_id, absl::string_view binding_id) override;
|
||||
void SetJoinBindingTime(absl::Time join_binding_time,
|
||||
absl::Duration life_time) override {
|
||||
join_binding_time_ = join_binding_time;
|
||||
join_binding_life_time_ = life_time;
|
||||
}
|
||||
std::string Dump() const override { return ""; }
|
||||
|
||||
// Make protected methods from base class public in this fake class.
|
||||
@@ -125,6 +138,11 @@ class FakeNearbyShareCertificateManager : public NearbyShareCertificateManager {
|
||||
return get_decrypted_public_certificate_calls_;
|
||||
}
|
||||
|
||||
const std::vector<AddBindingToPublicCertificateCall>&
|
||||
add_binding_to_public_certificate_calls() const {
|
||||
return add_binding_to_public_certificate_calls_;
|
||||
}
|
||||
|
||||
private:
|
||||
// NearbyShareCertificateManager:
|
||||
void OnStartScheduledTasks() override {}
|
||||
@@ -139,7 +157,11 @@ class FakeNearbyShareCertificateManager : public NearbyShareCertificateManager {
|
||||
size_t num_clear_public_certificates_calls_ = 0;
|
||||
std::vector<GetDecryptedPublicCertificateCall>
|
||||
get_decrypted_public_certificate_calls_;
|
||||
std::vector<AddBindingToPublicCertificateCall>
|
||||
add_binding_to_public_certificate_calls_;
|
||||
std::vector<uint8_t> next_salt_;
|
||||
absl::Time join_binding_time_;
|
||||
absl::Duration join_binding_life_time_;
|
||||
};
|
||||
|
||||
} // namespace sharing
|
||||
|
||||
@@ -106,7 +106,16 @@ void FakeNearbyShareCertificateStorage::GetPublicCertificate(
|
||||
std::function<
|
||||
void(bool, std::unique_ptr<nearby::sharing::proto::PublicCertificate>)>
|
||||
callback) {
|
||||
get_public_certificate_callback_ = std::move(callback);
|
||||
get_public_certificate_callback_ = callback;
|
||||
if (is_sync_mode_) {
|
||||
for (const auto& cert : public_certificates_) {
|
||||
if (cert.secret_id() == id) {
|
||||
callback(true, std::make_unique<PublicCertificate>(cert));
|
||||
return;
|
||||
}
|
||||
}
|
||||
callback(false, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<NearbySharePrivateCertificate>
|
||||
@@ -135,6 +144,19 @@ void FakeNearbyShareCertificateStorage::AddPublicCertificates(
|
||||
public_certificates.end()),
|
||||
callback);
|
||||
if (is_sync_mode_) {
|
||||
for (const auto& cert : public_certificates) {
|
||||
bool found = false;
|
||||
for (auto& existing_cert : public_certificates_) {
|
||||
if (existing_cert.secret_id() == cert.secret_id()) {
|
||||
existing_cert = cert;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
public_certificates_.push_back(cert);
|
||||
}
|
||||
}
|
||||
callback(add_public_certificates_result_);
|
||||
}
|
||||
}
|
||||
@@ -152,6 +174,12 @@ void FakeNearbyShareCertificateStorage::ClearPublicCertificates(
|
||||
clear_public_certificates_callbacks_.push_back(std::move(callback));
|
||||
}
|
||||
|
||||
void FakeNearbyShareCertificateStorage::SetPublicCertificates(
|
||||
absl::Span<const PublicCertificate> public_certificates) {
|
||||
public_certificates_ = std::vector<PublicCertificate>(
|
||||
public_certificates.begin(), public_certificates.end());
|
||||
}
|
||||
|
||||
void FakeNearbyShareCertificateStorage::SetPublicCertificateIds(
|
||||
absl::Span<const absl::string_view> ids) {
|
||||
public_certificate_ids_ = std::vector<std::string>(ids.begin(), ids.end());
|
||||
|
||||
@@ -123,6 +123,9 @@ class FakeNearbyShareCertificateStorage : public NearbyShareCertificateStorage {
|
||||
void ClearPublicCertificates(ResultCallback callback) override;
|
||||
|
||||
void SetPublicCertificateIds(absl::Span<const absl::string_view> ids);
|
||||
void SetPublicCertificates(
|
||||
absl::Span<const nearby::sharing::proto::PublicCertificate>
|
||||
public_certificates);
|
||||
void SetNextPublicCertificateExpirationTime(absl::Time time);
|
||||
|
||||
std::vector<PublicCertificateCallback>& get_public_certificates_callbacks() {
|
||||
@@ -156,6 +159,7 @@ class FakeNearbyShareCertificateStorage : public NearbyShareCertificateStorage {
|
||||
absl::Mutex mutex_;
|
||||
absl::Time next_public_certificate_expiration_time_ = absl::InfiniteFuture();
|
||||
std::vector<std::string> public_certificate_ids_;
|
||||
std::vector<nearby::sharing::proto::PublicCertificate> public_certificates_;
|
||||
std::vector<NearbySharePrivateCertificate> private_certificates_
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
std::vector<PublicCertificateCallback> get_public_certificates_callbacks_;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/span.h"
|
||||
@@ -73,6 +74,15 @@ NearbyShareCertificateManager::EncryptPrivateCertificateMetadataKey(
|
||||
return encrypted_key;
|
||||
}
|
||||
|
||||
std::optional<std::string>
|
||||
NearbyShareCertificateManager::GetPrivateCertificateId(
|
||||
DeviceVisibility visibility) {
|
||||
std::optional<NearbySharePrivateCertificate> cert =
|
||||
GetValidPrivateCertificate(visibility);
|
||||
if (!cert) return std::nullopt;
|
||||
return std::string(cert->id().begin(), cert->id().end());
|
||||
}
|
||||
|
||||
std::optional<std::vector<uint8_t>>
|
||||
NearbyShareCertificateManager::SignWithPrivateCertificate(
|
||||
DeviceVisibility visibility, absl::Span<const uint8_t> payload) const {
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "internal/base/observer_list.h"
|
||||
#include "sharing/certificates/nearby_share_decrypted_public_certificate.h"
|
||||
@@ -80,6 +82,12 @@ class NearbyShareCertificateManager {
|
||||
std::optional<NearbyShareEncryptedMetadataKey>
|
||||
EncryptPrivateCertificateMetadataKey(proto::DeviceVisibility visibility);
|
||||
|
||||
// Returns the id of the currently valid private certificate with
|
||||
// |visibility|, or absl::nullopt if there is no valid private certificate
|
||||
// with |visibility|.
|
||||
std::optional<std::string> GetPrivateCertificateId(
|
||||
proto::DeviceVisibility visibility);
|
||||
|
||||
// Signs the input |payload| using the currently valid private certificate
|
||||
// with |visibility|. Returns absl::nullopt if there is no valid private
|
||||
// certificate with |visibility| or if the signing was unsuccessful.
|
||||
@@ -119,9 +127,18 @@ class NearbyShareCertificateManager {
|
||||
// Sets the vendor ID to generate certificates for.
|
||||
virtual void SetVendorId(int32_t vendor_id) = 0;
|
||||
|
||||
// Sets the timestamp of the join binding rpc. This is used to ensure that the
|
||||
// requested public certificates contain the ids of the binding.
|
||||
// `life_time` determines how long this join_binding_time will be used.
|
||||
virtual void SetJoinBindingTime(absl::Time join_binding_time,
|
||||
absl::Duration life_time) = 0;
|
||||
|
||||
// Dump certificates ID information for troubleshooting.
|
||||
virtual std::string Dump() const = 0;
|
||||
|
||||
virtual void AddBindingToPublicCertificate(
|
||||
absl::string_view certificate_id, absl::string_view binding_id) = 0;
|
||||
|
||||
protected:
|
||||
virtual void OnStartScheduledTasks() = 0;
|
||||
virtual void OnStopScheduledTasks() = 0;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "location/nearby/sharing/lib/account/account_manager.h"
|
||||
#include "location/nearby/sharing/lib/rpc/sharing_rpc_client.h"
|
||||
#include "absl/algorithm/algorithm.h"
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/memory/memory.h"
|
||||
@@ -41,9 +42,11 @@
|
||||
#include "absl/strings/escaping.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/time.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "third_party/gloop/util/time/protoutil.h"
|
||||
#include "internal/base/file_path.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/platform/mac_address.h"
|
||||
@@ -383,6 +386,13 @@ void NearbyShareCertificateManagerImpl::CertificateDownloadContext::
|
||||
page_number_++;
|
||||
QuerySharedCredentialsWithBindingIdsRequest request;
|
||||
request.set_name(absl::StrCat("devices/", device_id_));
|
||||
if (join_time_.has_value()) {
|
||||
absl::StatusOr<google::protobuf::Timestamp> join_time =
|
||||
util_time::EncodeGoogleApiProto(*join_time_);
|
||||
if (join_time.ok()) {
|
||||
*request.mutable_join_binding_time() = *join_time;
|
||||
}
|
||||
}
|
||||
if (next_page_token_.has_value()) {
|
||||
request.set_page_token(*next_page_token_);
|
||||
}
|
||||
@@ -408,7 +418,8 @@ void NearbyShareCertificateManagerImpl::CertificateDownloadContext::
|
||||
<< absl::BytesToHexString(credential.data());
|
||||
continue;
|
||||
}
|
||||
VLOG(1) << "Successfully parsed credential: " << credential.id();
|
||||
VLOG(1) << "Successfully parsed credential: " << credential.id()
|
||||
<< " with binding id: " << certificate.binding_id();
|
||||
certificates_.push_back(certificate);
|
||||
}
|
||||
|
||||
@@ -466,10 +477,20 @@ bool NearbyShareCertificateManagerImpl::DownloadPublicCertificatesInExecutor() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Clear join_time if it is expired.
|
||||
std::optional<absl::Time> join_time;
|
||||
{
|
||||
absl::MutexLock lock(join_time_mutex_);
|
||||
if (join_time_.has_value() &&
|
||||
context_->GetClock()->Now() > join_time_discard_time_) {
|
||||
join_time_.reset();
|
||||
}
|
||||
join_time = join_time_;
|
||||
}
|
||||
bool download_succeeded = false;
|
||||
absl::Notification notification;
|
||||
auto context = std::make_unique<CertificateDownloadContext>(
|
||||
nearby_identity_client_, std::move(device_id),
|
||||
nearby_identity_client_, std::move(device_id), join_time,
|
||||
[this, &download_succeeded, ¬ification](
|
||||
absl::StatusOr<std::vector<PublicCertificate>> certificates_status) {
|
||||
if (!certificates_status.ok()) {
|
||||
@@ -489,7 +510,7 @@ bool NearbyShareCertificateManagerImpl::DownloadPublicCertificatesInExecutor() {
|
||||
notification.Notify();
|
||||
});
|
||||
if (NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_sharing_feature::kEnableFileSync)) {
|
||||
config_package_nearby::nearby_sharing_feature::kEnableBackup)) {
|
||||
context->QuerySharedCredentialsWithBindingIdsFetchNextPage();
|
||||
} else {
|
||||
context->QuerySharedCredentialsFetchNextPage();
|
||||
@@ -744,6 +765,13 @@ void NearbyShareCertificateManagerImpl::SetVendorId(int32_t vendor_id) {
|
||||
RegeneratePrivateCertificates();
|
||||
}
|
||||
|
||||
void NearbyShareCertificateManagerImpl::SetJoinBindingTime(
|
||||
absl::Time join_binding_time, absl::Duration life_time) {
|
||||
absl::MutexLock lock(join_time_mutex_);
|
||||
join_time_ = join_binding_time;
|
||||
join_time_discard_time_ = context_->GetClock()->Now() + life_time;
|
||||
}
|
||||
|
||||
std::string NearbyShareCertificateManagerImpl::Dump() const {
|
||||
std::stringstream sstream;
|
||||
sstream << "Public Certificates" << std::endl;
|
||||
@@ -892,6 +920,32 @@ bool NearbyShareCertificateManagerImpl::RefreshPrivateCertificatesInExecutor(
|
||||
return true;
|
||||
}
|
||||
|
||||
void NearbyShareCertificateManagerImpl::AddBindingToPublicCertificate(
|
||||
absl::string_view certificate_id, absl::string_view binding_id) {
|
||||
LOG(INFO) << "Adding binding to public certificate: "
|
||||
<< absl::BytesToHexString(certificate_id);
|
||||
absl::Notification notification;
|
||||
certificate_storage_->GetPublicCertificate(
|
||||
certificate_id,
|
||||
[this, id = std::string(binding_id), ¬ification](
|
||||
bool success, std::unique_ptr<PublicCertificate> certificate) {
|
||||
if (success && certificate != nullptr) {
|
||||
certificate->set_binding_id(id);
|
||||
certificate_storage_->AddPublicCertificates(
|
||||
{*certificate}, [](bool success) {
|
||||
if (!success) {
|
||||
LOG(WARNING)
|
||||
<< "Failed to add binding to public certificate.";
|
||||
}
|
||||
});
|
||||
} else {
|
||||
LOG(WARNING) << "Failed to add binding to public certificate.";
|
||||
}
|
||||
notification.Notify();
|
||||
});
|
||||
notification.WaitForNotification();
|
||||
}
|
||||
|
||||
void NearbyShareCertificateManagerImpl::ForceUploadPrivateCertificates() {
|
||||
executor_->PostTask([this]() {
|
||||
private_certificate_expiration_scheduler_->HandleResult(
|
||||
@@ -942,9 +996,9 @@ bool NearbyShareCertificateManagerImpl::UpdateAccountInfoInExecutor() {
|
||||
get_account_info_succeeded = true;
|
||||
const auto& capabilities = response->account_info().capabilities();
|
||||
bool has_titanium_capability =
|
||||
(std::find(capabilities.begin(), capabilities.end(),
|
||||
google::nearby::identity::v1::AccountInfo::
|
||||
CAPABILITY_TITANIUM) != capabilities.end());
|
||||
(absl::c_find(capabilities,
|
||||
google::nearby::identity::v1::AccountInfo::
|
||||
CAPABILITY_TITANIUM) != capabilities.end());
|
||||
preference_manager_.SetBoolean(PrefNames::kAdvancedProtectionEnabled,
|
||||
has_titanium_capability);
|
||||
LOG(INFO) << "GetAccountInfo succeeded, advanced protection enabled: "
|
||||
|
||||
@@ -26,8 +26,11 @@
|
||||
#include "location/nearby/sharing/lib/account/account_manager.h"
|
||||
#include "location/nearby/sharing/lib/rpc/sharing_rpc_client.h"
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/base/file_path.h"
|
||||
#include "internal/platform/task_runner.h"
|
||||
@@ -92,7 +95,12 @@ class NearbyShareCertificateManagerImpl
|
||||
void ForceUploadPrivateCertificates() override;
|
||||
void ClearPublicCertificates(std::function<void(bool)> callback) override;
|
||||
void SetVendorId(int32_t vendor_id) override;
|
||||
void SetJoinBindingTime(absl::Time join_binding_time,
|
||||
absl::Duration life_time)
|
||||
ABSL_LOCKS_EXCLUDED(join_time_mutex_) override;
|
||||
std::string Dump() const override;
|
||||
void AddBindingToPublicCertificate(
|
||||
absl::string_view certificate_id, absl::string_view binding_id) override;
|
||||
|
||||
private:
|
||||
// Class for maintaining a single instance of public certificate download
|
||||
@@ -104,12 +112,14 @@ class NearbyShareCertificateManagerImpl
|
||||
nearby::sharing::api::IdentityRpcClient* absl_nonnull
|
||||
nearby_identity_client,
|
||||
std::string device_id,
|
||||
std::optional<absl::Time> join_time,
|
||||
absl::AnyInvocable<void(absl::StatusOr<std::vector<
|
||||
nearby::sharing::proto::PublicCertificate>>
|
||||
certificates_status) &&>
|
||||
download_callback)
|
||||
: nearby_identity_client_(nearby_identity_client),
|
||||
device_id_(std::move(device_id)),
|
||||
join_time_(join_time),
|
||||
download_callback_(std::move(download_callback)) {}
|
||||
|
||||
// Fetches the next page of certificates by calling Identity API
|
||||
@@ -123,7 +133,8 @@ class NearbyShareCertificateManagerImpl
|
||||
private:
|
||||
nearby::sharing::api::IdentityRpcClient* absl_nonnull const
|
||||
nearby_identity_client_;
|
||||
std::string device_id_;
|
||||
const std::string device_id_;
|
||||
const std::optional<absl::Time> join_time_;
|
||||
std::optional<std::string> next_page_token_;
|
||||
int page_number_ = 1;
|
||||
std::vector<nearby::sharing::proto::PublicCertificate> certificates_;
|
||||
@@ -219,6 +230,12 @@ class NearbyShareCertificateManagerImpl
|
||||
account_info_update_scheduler_;
|
||||
|
||||
std::unique_ptr<TaskRunner> executor_;
|
||||
absl::Mutex join_time_mutex_;
|
||||
// Set to the transaction timestamp of the last successful pairing if
|
||||
// available. This is returned from the phone in the BindingResponse message.
|
||||
std::optional<absl::Time> join_time_ ABSL_GUARDED_BY(join_time_mutex_);
|
||||
// The time when the join_time_ will be discarded.
|
||||
absl::Time join_time_discard_time_ ABSL_GUARDED_BY(join_time_mutex_);
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "third_party/gloop/util/time/protoutil.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/platform/mac_address.h"
|
||||
#include "sharing/certificates/constants.h"
|
||||
@@ -78,6 +79,7 @@ using ::google::nearby::identity::v1::
|
||||
QuerySharedCredentialsWithBindingIdsResponse;
|
||||
using ::nearby::sharing::proto::DeviceVisibility;
|
||||
using ::nearby::sharing::proto::PublicCertificate;
|
||||
using ::protobuf_matchers::EqualsProto;
|
||||
using ::testing::Not;
|
||||
using ::testing::ReturnRef;
|
||||
using ::testing::UnorderedElementsAreArray;
|
||||
@@ -634,6 +636,31 @@ TEST_F(NearbyShareCertificateManagerImplTest,
|
||||
DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS));
|
||||
}
|
||||
|
||||
TEST_F(NearbyShareCertificateManagerImplTest,
|
||||
GetPrivateCertificateIdWithNoCertificates) {
|
||||
Initialize();
|
||||
cert_store_->ReplacePrivateCertificates({});
|
||||
EXPECT_FALSE(cert_manager_->GetPrivateCertificateId(
|
||||
DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS).has_value());
|
||||
}
|
||||
|
||||
TEST_F(NearbyShareCertificateManagerImplTest,
|
||||
GetPrivateCertificateIdWithValidCertificate) {
|
||||
Initialize();
|
||||
NearbySharePrivateCertificate private_certificate =
|
||||
GetNearbyShareTestPrivateCertificate(
|
||||
DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS);
|
||||
cert_store_->ReplacePrivateCertificates({private_certificate});
|
||||
FastForward(GetNearbyShareTestNotBefore() +
|
||||
kNearbyShareCertificateValidityPeriod * 0.5 - Now());
|
||||
ASSERT_TRUE(cert_manager_->GetPrivateCertificateId(
|
||||
DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS).has_value());
|
||||
EXPECT_EQ(cert_manager_->GetPrivateCertificateId(
|
||||
DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS).value(),
|
||||
std::string(private_certificate.id().begin(),
|
||||
private_certificate.id().end()));
|
||||
}
|
||||
|
||||
TEST_F(NearbyShareCertificateManagerImplTest, SignWithPrivateCertificate) {
|
||||
Initialize();
|
||||
NearbySharePrivateCertificate private_certificate =
|
||||
@@ -782,7 +809,7 @@ TEST_F(NearbyShareCertificateManagerImplTest,
|
||||
TEST_F(NearbyShareCertificateManagerImplTest,
|
||||
QuerySharedCredentialsWithBindingIdsSuccess) {
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_sharing_feature::kEnableFileSync, true);
|
||||
config_package_nearby::nearby_sharing_feature::kEnableBackup, true);
|
||||
Initialize();
|
||||
ASSERT_NO_FATAL_FAILURE(QuerySharedCredentialsWithBindingIdsFlow(
|
||||
/*num_pages=*/2, DownloadPublicCertificatesResult::kSuccess));
|
||||
@@ -791,12 +818,48 @@ TEST_F(NearbyShareCertificateManagerImplTest,
|
||||
TEST_F(NearbyShareCertificateManagerImplTest,
|
||||
QuerySharedCredentialsWithBindingIdsRPCFailure) {
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_sharing_feature::kEnableFileSync, true);
|
||||
config_package_nearby::nearby_sharing_feature::kEnableBackup, true);
|
||||
Initialize();
|
||||
ASSERT_NO_FATAL_FAILURE(QuerySharedCredentialsWithBindingIdsFlow(
|
||||
/*num_pages=*/2, DownloadPublicCertificatesResult::kHttpError));
|
||||
}
|
||||
|
||||
TEST_F(NearbyShareCertificateManagerImplTest,
|
||||
QuerySharedCredentialsWithBindingIdsWithJoinTime) {
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_sharing_feature::kEnableBackup, true);
|
||||
Initialize();
|
||||
cert_manager_->SetJoinBindingTime(absl::FromUnixSeconds(123456789),
|
||||
absl::Seconds(30));
|
||||
ASSERT_NO_FATAL_FAILURE(QuerySharedCredentialsWithBindingIdsFlow(
|
||||
/*num_pages=*/2, DownloadPublicCertificatesResult::kSuccess));
|
||||
std::vector<QuerySharedCredentialsWithBindingIdsRequest> requests =
|
||||
identity_client_.query_shared_credentials_with_binding_ids_requests();
|
||||
for (const auto& request : requests) {
|
||||
ASSERT_OK_AND_ASSIGN(
|
||||
auto expected_time,
|
||||
util_time::EncodeGoogleApiProto(absl::FromUnixSeconds(123456789)));
|
||||
EXPECT_THAT(request.join_binding_time(), EqualsProto(expected_time));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NearbyShareCertificateManagerImplTest,
|
||||
QuerySharedCredentialsWithBindingIdsWithJoinTimeExpiration) {
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_sharing_feature::kEnableBackup, true);
|
||||
Initialize();
|
||||
cert_manager_->SetJoinBindingTime(absl::FromUnixSeconds(123456789),
|
||||
absl::Seconds(30));
|
||||
FastForward(absl::Seconds(31));
|
||||
ASSERT_NO_FATAL_FAILURE(QuerySharedCredentialsWithBindingIdsFlow(
|
||||
/*num_pages=*/2, DownloadPublicCertificatesResult::kSuccess));
|
||||
std::vector<QuerySharedCredentialsWithBindingIdsRequest> requests =
|
||||
identity_client_.query_shared_credentials_with_binding_ids_requests();
|
||||
for (const auto& request : requests) {
|
||||
EXPECT_FALSE(request.has_join_binding_time());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NearbyShareCertificateManagerImplTest, ClearPublicCertificates) {
|
||||
Initialize();
|
||||
cert_manager_->ClearPublicCertificates([&](bool result) {});
|
||||
@@ -1110,4 +1173,24 @@ TEST_F(NearbyShareCertificateManagerImplTest,
|
||||
PrefNames::kAdvancedProtectionEnabled, /*default_value=*/false));
|
||||
}
|
||||
|
||||
TEST_F(NearbyShareCertificateManagerImplTest, AddBindingToPublicCertificate) {
|
||||
Initialize();
|
||||
|
||||
PublicCertificate cert;
|
||||
cert.set_secret_id("test_cert_id");
|
||||
cert.set_binding_id("old_binding_id");
|
||||
|
||||
cert_store_->SetPublicCertificates({cert});
|
||||
cert_store_->SetAddPublicCertificatesResult(true);
|
||||
|
||||
cert_manager_->AddBindingToPublicCertificate("test_cert_id",
|
||||
"new_binding_id");
|
||||
|
||||
ASSERT_EQ(cert_store_->add_public_certificates_calls().size(), 1u);
|
||||
const auto& call = cert_store_->add_public_certificates_calls().back();
|
||||
ASSERT_EQ(call.public_certificates.size(), 1u);
|
||||
EXPECT_EQ(call.public_certificates[0].secret_id(), "test_cert_id");
|
||||
EXPECT_EQ(call.public_certificates[0].binding_id(), "new_binding_id");
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing
|
||||
|
||||
@@ -342,7 +342,8 @@ void NearbyShareCertificateStorageImpl::GetPublicCertificate(
|
||||
});
|
||||
return;
|
||||
}
|
||||
VLOG(1) << __func__ << ": Calling LoadCertificate on database, key: " << id;
|
||||
VLOG(1) << __func__ << ": Calling LoadCertificate on database, key: "
|
||||
<< absl::BytesToHexString(id);
|
||||
public_certificate_database_->LoadCertificate(id, std::move(callback));
|
||||
}
|
||||
|
||||
|
||||
@@ -211,20 +211,20 @@ TEST_F(NearbyShareCertificateStorageImplTest, InitializeRetrySucceed) {
|
||||
auto db = std::make_unique<StrictMock<MockPublicCertificateDb>>();
|
||||
MockPublicCertificateDb* mock_db = db.get();
|
||||
EXPECT_CALL(*mock_db, Initialize(_))
|
||||
.WillOnce(Invoke(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
|
||||
.WillOnce(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
|
||||
callback) {
|
||||
std::move(callback)(MockPublicCertificateDb::InitStatus::kError);
|
||||
}))
|
||||
.WillRepeatedly(Invoke(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
|
||||
})
|
||||
.WillRepeatedly(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
|
||||
callback) {
|
||||
std::move(callback)(MockPublicCertificateDb::InitStatus::kOk);
|
||||
}));
|
||||
});
|
||||
EXPECT_CALL(*mock_db, Destroy(_))
|
||||
.WillOnce(Invoke([](absl::AnyInvocable<void(bool)&&> callback) {
|
||||
.WillOnce([](absl::AnyInvocable<void(bool) &&> callback) {
|
||||
std::move(callback)(true);
|
||||
}));
|
||||
});
|
||||
|
||||
auto cert_store = NearbyShareCertificateStorageImpl::Factory::Create(
|
||||
preference_manager_, std::move(db));
|
||||
@@ -243,11 +243,11 @@ TEST_F(NearbyShareCertificateStorageImplTest, InitializeRetryFailed) {
|
||||
auto db = std::make_unique<StrictMock<MockPublicCertificateDb>>();
|
||||
MockPublicCertificateDb* mock_db = db.get();
|
||||
EXPECT_CALL(*mock_db, Initialize(_))
|
||||
.WillRepeatedly(Invoke(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
|
||||
.WillRepeatedly(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
|
||||
callback) {
|
||||
std::move(callback)(MockPublicCertificateDb::InitStatus::kError);
|
||||
}));
|
||||
});
|
||||
|
||||
auto cert_store = NearbyShareCertificateStorageImpl::Factory::Create(
|
||||
preference_manager_, std::move(db));
|
||||
@@ -267,23 +267,23 @@ TEST_F(NearbyShareCertificateStorageImplTest,
|
||||
auto db = std::make_unique<StrictMock<MockPublicCertificateDb>>();
|
||||
MockPublicCertificateDb* mock_db = db.get();
|
||||
EXPECT_CALL(*mock_db, Initialize(_))
|
||||
.WillOnce(Invoke(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
|
||||
.WillOnce(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
|
||||
callback) {
|
||||
std::move(callback)(MockPublicCertificateDb::InitStatus::kCorrupt);
|
||||
}))
|
||||
.WillRepeatedly(Invoke(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
|
||||
})
|
||||
.WillRepeatedly(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
|
||||
callback) {
|
||||
std::move(callback)(MockPublicCertificateDb::InitStatus::kOk);
|
||||
}));
|
||||
});
|
||||
// Destroy called once from corrupted initialization and once from cal to
|
||||
// ClearPublicCertificates.
|
||||
EXPECT_CALL(*mock_db, Destroy(_))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Invoke([](absl::AnyInvocable<void(bool)&&> callback) {
|
||||
.WillRepeatedly([](absl::AnyInvocable<void(bool) &&> callback) {
|
||||
std::move(callback)(true);
|
||||
}));
|
||||
});
|
||||
|
||||
auto cert_store = NearbyShareCertificateStorageImpl::Factory::Create(
|
||||
preference_manager_, std::move(db));
|
||||
@@ -301,15 +301,15 @@ TEST_F(NearbyShareCertificateStorageImplTest, InitializeCorruptDestroyFails) {
|
||||
auto db = std::make_unique<StrictMock<MockPublicCertificateDb>>();
|
||||
MockPublicCertificateDb* mock_db = db.get();
|
||||
EXPECT_CALL(*mock_db, Initialize(_))
|
||||
.WillOnce(Invoke(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
|
||||
.WillOnce(
|
||||
[](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
|
||||
callback) {
|
||||
std::move(callback)(MockPublicCertificateDb::InitStatus::kCorrupt);
|
||||
}));
|
||||
});
|
||||
EXPECT_CALL(*mock_db, Destroy(_))
|
||||
.WillOnce(Invoke([](absl::AnyInvocable<void(bool)&&> callback) {
|
||||
.WillOnce([](absl::AnyInvocable<void(bool) &&> callback) {
|
||||
std::move(callback)(false);
|
||||
}));
|
||||
});
|
||||
|
||||
auto cert_store = NearbyShareCertificateStorageImpl::Factory::Create(
|
||||
preference_manager_, std::move(db));
|
||||
@@ -333,18 +333,18 @@ TEST_F(NearbyShareCertificateStorageImplTest, DeferredCallbackQueue) {
|
||||
auto db = std::make_unique<StrictMock<MockPublicCertificateDb>>();
|
||||
MockPublicCertificateDb* mock_db = db.get();
|
||||
EXPECT_CALL(*mock_db, Initialize(_))
|
||||
.WillOnce(Invoke(
|
||||
[&](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus)&&>
|
||||
callback) { init_status_callback = std::move(callback); }));
|
||||
.WillOnce(
|
||||
[&](absl::AnyInvocable<void(MockPublicCertificateDb::InitStatus) &&>
|
||||
callback) { init_status_callback = std::move(callback); });
|
||||
EXPECT_CALL(*mock_db, Destroy(_))
|
||||
.WillOnce(Invoke([&](absl::AnyInvocable<void(bool)&&> callback) {
|
||||
.WillOnce([&](absl::AnyInvocable<void(bool) &&> callback) {
|
||||
destroy_callback = std::move(callback);
|
||||
}));
|
||||
});
|
||||
EXPECT_CALL(*mock_db, LoadEntries(_))
|
||||
.WillOnce(Invoke(
|
||||
.WillOnce(
|
||||
[&](absl::AnyInvocable<void(
|
||||
bool, std::unique_ptr<std::vector<PublicCertificate>>)&&>
|
||||
callback) { load_callback = std::move(callback); }));
|
||||
bool, std::unique_ptr<std::vector<PublicCertificate>>) &&>
|
||||
callback) { load_callback = std::move(callback); });
|
||||
|
||||
auto cert_store = NearbyShareCertificateStorageImpl::Factory::Create(
|
||||
preference_manager_, std::move(db));
|
||||
|
||||
@@ -67,6 +67,7 @@ void RegisterNearbySharingPrefs(PreferenceManager& preference_manager,
|
||||
preference_manager.Remove(PrefNames::kUsers);
|
||||
preference_manager.SetBoolean(PrefNames::kAdvancedProtectionEnabled, false);
|
||||
|
||||
preference_manager.RemoveAllSyncConfigs();
|
||||
preference_manager.RemoveAllBindingConfigs();
|
||||
}
|
||||
|
||||
|
||||
@@ -61,9 +61,9 @@ constexpr auto kShowAutoUpdateSetting =
|
||||
// The default time in milliseconds a cached entry can be in LOST state.
|
||||
constexpr auto kDiscoveryCacheLostExpiryMs =
|
||||
flags::Flag<int64_t>(kConfigPackage, "45658774", 15000);
|
||||
// When true, enable file sync feature.
|
||||
constexpr auto kEnableFileSync =
|
||||
flags::Flag<bool>(kConfigPackage, "45762616", false);
|
||||
// When true, enable suspend resume listener.
|
||||
constexpr auto kEnableSuspendResumeListener =
|
||||
flags::Flag<bool>(kConfigPackage, "45815625", false);
|
||||
// When true, enable wifi hotspot medium for HP Realtek devices.
|
||||
constexpr auto kEnableWifiHotspotForHpRealtekDevices =
|
||||
flags::Flag<bool>(kConfigPackage, "45673628", false);
|
||||
@@ -108,7 +108,7 @@ inline absl::btree_map<int, const flags::Flag<bool>&> GetBoolFlags() {
|
||||
{45411589, kEnableRetryResumeTransfer},
|
||||
{45459748, kEnableSendingDesktopEvents},
|
||||
{45409033, kShowAutoUpdateSetting},
|
||||
{45762616, kEnableFileSync},
|
||||
{45815625, kEnableSuspendResumeListener},
|
||||
{45673628, kEnableWifiHotspotForHpRealtekDevices},
|
||||
{45683539, kUseAlternateServiceUuidForDiscovery},
|
||||
{45776229, kEnableBackup},
|
||||
|
||||
@@ -63,6 +63,7 @@ cc_library(
|
||||
"//internal/platform/implementation:types",
|
||||
"//location/nearby/sharing/lib/account:account_manager",
|
||||
"//location/nearby/sharing/lib/sync:sync_binding_prefs_cc_proto",
|
||||
"//location/nearby/sharing/lib/sync:sync_config_prefs_cc_proto",
|
||||
"//sharing/proto:share_cc_proto",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "location/nearby/sharing/lib/sync/sync_binding_prefs.pb.h"
|
||||
#include "location/nearby/sharing/lib/sync/sync_config_prefs.pb.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/span.h"
|
||||
@@ -80,6 +81,10 @@ class PreferenceManager {
|
||||
virtual void RemoveDictionaryItem(absl::string_view key,
|
||||
absl::string_view dictionary_item) = 0;
|
||||
|
||||
virtual void SetSyncConfigValue(
|
||||
absl::string_view binding_id,
|
||||
const nearby::sharing::sync::SyncConfigPrefs& value) = 0;
|
||||
|
||||
virtual void SetSyncBindingValue(
|
||||
const nearby::sharing::sync::SyncBindingPrefs& value) = 0;
|
||||
|
||||
@@ -122,12 +127,19 @@ class PreferenceManager {
|
||||
virtual std::optional<std::string> GetDictionaryStringValue(
|
||||
absl::string_view key, absl::string_view dictionary_item) const = 0;
|
||||
|
||||
virtual std::optional<nearby::sharing::sync::SyncConfigPrefs>
|
||||
GetSyncConfigValue(absl::string_view binding_id) const = 0;
|
||||
|
||||
virtual void RemoveSyncConfigPref(absl::string_view binding_id) = 0;
|
||||
|
||||
virtual std::optional<nearby::sharing::sync::SyncBindingPrefs>
|
||||
GetSyncBindingValue() const = 0;
|
||||
|
||||
// Removes preferences
|
||||
virtual void Remove(absl::string_view key) = 0;
|
||||
// Removes all binding configs.
|
||||
// Removes all sync configs.
|
||||
// Observers are not notified for each removed config.
|
||||
virtual void RemoveAllSyncConfigs() = 0; // Removes all binding configs.
|
||||
// Observers are not notified for each removed config.
|
||||
virtual void RemoveAllBindingConfigs() = 0;
|
||||
|
||||
|
||||
@@ -58,10 +58,18 @@ class PrefNames {
|
||||
// Binding configs preferences are stored in pref keys:
|
||||
// kBindingConfigPrefix + <service_name>
|
||||
// Example: "nearby_sharing.binding_config.FileSync"
|
||||
// TODO: b/485304482 - define data format for binding configs.
|
||||
// For FileSync service, data stored in binding config prefs is a
|
||||
// nearby::sharing::sync::SyncBindingPrefs proto.
|
||||
static constexpr absl::string_view kBindingConfigPrefix =
|
||||
"nearby_sharing.binding_config.";
|
||||
};
|
||||
|
||||
// Sync configs preferences are stored in pref keys:
|
||||
// kSyncConfigPrefix + <binding ID>
|
||||
// Example: "nearby_sharing.sync_config.01243347-2343-4324-3423-432432432432"
|
||||
// Data stored in sync config prefs is a
|
||||
// nearby::sharing::sync::SyncConfigPrefs proto.
|
||||
static constexpr absl::string_view kSyncConfigPrefix =
|
||||
"nearby_sharing.sync_config.";};
|
||||
|
||||
} // namespace nearby::sharing
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ cc_library(
|
||||
"//internal/platform:types",
|
||||
"//internal/test",
|
||||
"//location/nearby/sharing/lib/sync:sync_binding_prefs_cc_proto",
|
||||
"//location/nearby/sharing/lib/sync:sync_config_prefs_cc_proto",
|
||||
"//sharing/internal/api:platform",
|
||||
"//sharing/internal/public:pref_names",
|
||||
"//sharing/internal/public:types",
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "location/nearby/sharing/lib/sync/sync_binding_prefs.pb.h"
|
||||
#include "location/nearby/sharing/lib/sync/sync_config_prefs.pb.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
@@ -36,6 +37,7 @@ namespace nearby {
|
||||
using ::nearby::sharing::PrefNames;
|
||||
using ::nearby::sharing::api::PrivateCertificateData;
|
||||
using ::nearby::sharing::sync::SyncBindingPrefs;
|
||||
using ::nearby::sharing::sync::SyncConfigPrefs;
|
||||
|
||||
// Preference suffix for the sync binding information.
|
||||
constexpr absl::string_view kFileSyncBindingName = "FileSync";
|
||||
@@ -243,6 +245,16 @@ void FakePreferenceManager::RemoveDictionaryItem(
|
||||
NotifyPreferenceChanged(key);
|
||||
}
|
||||
|
||||
void FakePreferenceManager::SetSyncConfigValue(absl::string_view binding_id,
|
||||
const SyncConfigPrefs& value) {
|
||||
SetValue(absl::StrCat(PrefNames::kSyncConfigPrefix, binding_id),
|
||||
value.SerializeAsString());
|
||||
}
|
||||
|
||||
void FakePreferenceManager::RemoveSyncConfigPref(absl::string_view binding_id) {
|
||||
Remove(absl::StrCat(PrefNames::kSyncConfigPrefix, binding_id));
|
||||
}
|
||||
|
||||
void FakePreferenceManager::SetSyncBindingValue(
|
||||
const SyncBindingPrefs& value) {
|
||||
SetValue(absl::StrCat(PrefNames::kBindingConfigPrefix, kFileSyncBindingName),
|
||||
@@ -333,6 +345,21 @@ std::optional<std::string> FakePreferenceManager::GetDictionaryStringValue(
|
||||
return GetDictionaryValue<std::string>(key, dictionary_item);
|
||||
}
|
||||
|
||||
std::optional<SyncConfigPrefs> FakePreferenceManager::GetSyncConfigValue(
|
||||
absl::string_view binding_id) const {
|
||||
std::string serialized_sync_config;
|
||||
serialized_sync_config =
|
||||
GetString(absl::StrCat(PrefNames::kSyncConfigPrefix, binding_id), "");
|
||||
if (serialized_sync_config.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
SyncConfigPrefs sync_config;
|
||||
if (!sync_config.ParseFromString(serialized_sync_config)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return sync_config;
|
||||
}
|
||||
|
||||
std::optional<SyncBindingPrefs> FakePreferenceManager::GetSyncBindingValue()
|
||||
const {
|
||||
std::string serialized_sync_binding;
|
||||
@@ -358,6 +385,13 @@ void FakePreferenceManager::Remove(absl::string_view key) {
|
||||
NotifyPreferenceChanged(key);
|
||||
}
|
||||
|
||||
void FakePreferenceManager::RemoveAllSyncConfigs() {
|
||||
absl::MutexLock lock(mutex_);
|
||||
absl::erase_if(values_, [](const auto& item) {
|
||||
return item.first.starts_with(PrefNames::kSyncConfigPrefix);
|
||||
});
|
||||
}
|
||||
|
||||
void FakePreferenceManager::RemoveAllBindingConfigs() {
|
||||
absl::MutexLock lock(mutex_);
|
||||
absl::erase_if(values_, [](const auto& item) {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "location/nearby/sharing/lib/sync/sync_binding_prefs.pb.h"
|
||||
#include "location/nearby/sharing/lib/sync/sync_config_prefs.pb.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
@@ -75,6 +76,9 @@ class FakePreferenceManager : public nearby::sharing::api::PreferenceManager {
|
||||
void RemoveDictionaryItem(absl::string_view key,
|
||||
absl::string_view dictionary_item) override;
|
||||
|
||||
void SetSyncConfigValue(
|
||||
absl::string_view binding_id,
|
||||
const nearby::sharing::sync::SyncConfigPrefs& value) override;
|
||||
void SetSyncBindingValue(
|
||||
const nearby::sharing::sync::SyncBindingPrefs& value) override;
|
||||
|
||||
@@ -111,10 +115,14 @@ class FakePreferenceManager : public nearby::sharing::api::PreferenceManager {
|
||||
absl::string_view key, absl::string_view dictionary_item) const override;
|
||||
std::optional<std::string> GetDictionaryStringValue(
|
||||
absl::string_view key, absl::string_view dictionary_item) const override;
|
||||
std::optional<nearby::sharing::sync::SyncConfigPrefs>
|
||||
GetSyncConfigValue(absl::string_view binding_id) const override;
|
||||
void RemoveSyncConfigPref(absl::string_view binding_id) override;
|
||||
std::optional<nearby::sharing::sync::SyncBindingPrefs>
|
||||
GetSyncBindingValue() const override;
|
||||
|
||||
void Remove(absl::string_view key) override;
|
||||
void RemoveAllSyncConfigs() override;
|
||||
void RemoveAllBindingConfigs() override;
|
||||
|
||||
void AddObserver(
|
||||
|
||||
@@ -821,7 +821,6 @@ void NearbyConnectionsManagerImpl::DeleteUnknownFilePayloadAndCancel(
|
||||
std::optional<
|
||||
std::weak_ptr<NearbyConnectionsManagerImpl::PayloadStatusListener>>
|
||||
NearbyConnectionsManagerImpl::GetStatusListenerForId(int64_t payload_id) const {
|
||||
MutexLock lock(&mutex_);
|
||||
auto listener_it = payload_status_listeners_.find(payload_id);
|
||||
if (listener_it == payload_status_listeners_.end()) {
|
||||
return std::nullopt;
|
||||
@@ -840,12 +839,12 @@ NearbyConnectionImpl* NearbyConnectionsManagerImpl::GetConnectionForId(
|
||||
|
||||
void NearbyConnectionsManagerImpl::RemoveStatusListenerForPayloadId(
|
||||
int64_t payload_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
payload_status_listeners_.erase(payload_id);
|
||||
}
|
||||
|
||||
void NearbyConnectionsManagerImpl::OnPayloadTransferUpdate(
|
||||
absl::string_view endpoint_id, const PayloadTransferUpdate& update) {
|
||||
MutexLock lock(&mutex_);
|
||||
VLOG(1) << "Received payload transfer update id=" << update.payload_id
|
||||
<< ",status=" << PayloadStatusToString(update.status)
|
||||
<< ",total=" << update.total_bytes
|
||||
@@ -879,16 +878,21 @@ void NearbyConnectionsManagerImpl::OnPayloadTransferUpdate(
|
||||
// If this is an incoming payload that we have not registered for, then
|
||||
// we'll treat it as a control frame (e.g. IntroductionFrame) and
|
||||
// forward it to the associated NearbyConnection.
|
||||
auto payload = GetIncomingPayload(update.payload_id);
|
||||
if (payload == nullptr) return;
|
||||
if (update.status == PayloadStatus::kInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto node = incoming_payloads_.extract(update.payload_id);
|
||||
if (node.empty()) return;
|
||||
|
||||
if (update.status != PayloadStatus::kSuccess) return;
|
||||
|
||||
NearbyConnectionImpl* connection = GetConnectionForId(endpoint_id);
|
||||
if (connection == nullptr) return;
|
||||
auto connection_it = connections_.find(endpoint_id);
|
||||
if (connection_it == connections_.end()) return;
|
||||
|
||||
VLOG(1) << "Writing incoming byte message to NearbyConnection.";
|
||||
connection->WriteMessage(payload->content.bytes_payload.bytes);
|
||||
connection_it->second->WriteMessage(
|
||||
std::move(node.mapped().content.bytes_payload.bytes));
|
||||
}
|
||||
|
||||
void NearbyConnectionsManagerImpl::Reset() {
|
||||
|
||||
@@ -128,13 +128,13 @@ class NearbyConnectionsManagerImpl : public NearbyConnectionsManager {
|
||||
absl::flat_hash_set<FilePath> GetUnknownFilePathsToDelete();
|
||||
|
||||
std::optional<std::weak_ptr<PayloadStatusListener>> GetStatusListenerForId(
|
||||
int64_t payload_id) const ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
int64_t payload_id) const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
NearbyConnectionImpl* GetConnectionForId(absl::string_view endpoint_id) const
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
void RemoveStatusListenerForPayloadId(int64_t payload_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
void Reset();
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "location/nearby/cpp/sharing/clients/cpp/common/nearby_sharing_common.h"
|
||||
#include "location/nearby/sharing/lib/account/account_manager.h"
|
||||
#include "location/nearby/sharing/lib/rpc/sharing_rpc_client.h"
|
||||
#include "location/nearby/sharing/lib/sync/sync_binding_prefs.pb.h"
|
||||
@@ -43,8 +44,10 @@
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "third_party/gloop/util/time/protoutil.h"
|
||||
#include "internal/base/file_path.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/network/url.h"
|
||||
@@ -133,6 +136,17 @@ constexpr absl::Duration kProcessShutdownPendingTimerDelay = // NOLINT
|
||||
absl::Seconds(15);
|
||||
constexpr absl::Duration kProcessNetworkChangeTimerDelay = absl::Seconds(1);
|
||||
|
||||
// Delay invalidating the surface state after a resume event.
|
||||
// Network activities can cause system to resume for short periods before
|
||||
// suspending again. This delay allows us to ignore those and only resume
|
||||
// fully when the system is stable.
|
||||
constexpr absl::Duration kResumeDelay = absl::Milliseconds(500);
|
||||
|
||||
// The duration to use join binding time when downloading public certificates.
|
||||
// The default BE database query staleness is 30s. We extend this t0 40s to
|
||||
// ensure that we have some overlap.
|
||||
constexpr absl::Duration kJoinBindingTimeLifeTime = absl::Seconds(40);
|
||||
|
||||
// The maximum number of certificate downloads that can be performed during a
|
||||
// discovery session.
|
||||
// Assuming a 2min discovery session and 10s download interval.
|
||||
@@ -251,6 +265,24 @@ sync::SyncBinding::SourceDeviceType ShareTargetTypeToSourceDeviceType(
|
||||
return sync::SyncBinding::SOURCE_DEVICE_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
location::nearby::proto::sharing::SharingUseCase
|
||||
IntroductionUseCaseToLoggingUseCase(
|
||||
IntroductionFrame::SharingUseCase use_case) {
|
||||
switch (use_case) {
|
||||
case IntroductionFrame::NEARBY_SHARE:
|
||||
return location::nearby::proto::sharing::SharingUseCase::
|
||||
USE_CASE_NEARBY_SHARE;
|
||||
case IntroductionFrame::TAP_TO_SHARE:
|
||||
return location::nearby::proto::sharing::SharingUseCase::
|
||||
USE_CASE_TAP_TO_SHARE;
|
||||
case IntroductionFrame::FILE_SYNC:
|
||||
return location::nearby::proto::sharing::SharingUseCase::
|
||||
USE_CASE_FILE_SYNC;
|
||||
default:
|
||||
return location::nearby::proto::sharing::SharingUseCase::USE_CASE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
NearbySharingServiceImpl::NearbySharingServiceImpl(
|
||||
@@ -318,6 +350,13 @@ NearbySharingServiceImpl::NearbySharingServiceImpl(
|
||||
OnLockStateChanged(screen_status ==
|
||||
nearby::api::DeviceInfo::ScreenStatus::kLocked);
|
||||
});
|
||||
if (NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_sharing_feature::
|
||||
kEnableSuspendResumeListener)) {
|
||||
suspend_resume_listener_id_ =
|
||||
device_info_.RegisterSuspendResumeListener(absl::bind_front(
|
||||
&NearbySharingServiceImpl::OnSuspendResumeEvent, this));
|
||||
}
|
||||
|
||||
account_manager_.AddObserver(this);
|
||||
settings_->AddSettingsObserver(this);
|
||||
@@ -365,6 +404,8 @@ void NearbySharingServiceImpl::Shutdown(
|
||||
background_receive_callbacks_map_.clear();
|
||||
|
||||
device_info_.UnregisterScreenLockedListener(kScreenStateListenerName);
|
||||
device_info_.UnregisterSuspendResumeListener(
|
||||
suspend_resume_listener_id_);
|
||||
|
||||
settings_->RemoveSettingsObserver(this);
|
||||
|
||||
@@ -668,7 +709,7 @@ void NearbySharingServiceImpl::RegisterReceiveSurface(
|
||||
VLOG(1) << "[Call Identity API] ForceUploadPrivateCertificates.";
|
||||
certificate_manager_->ForceUploadPrivateCertificates();
|
||||
}
|
||||
InvalidateReceiveSurfaceState();
|
||||
InvalidateAdvertisingState();
|
||||
status_codes_callback(StatusCodes::kOk);
|
||||
});
|
||||
}
|
||||
@@ -1396,6 +1437,42 @@ void NearbySharingServiceImpl::OnLockStateChanged(bool locked) {
|
||||
});
|
||||
}
|
||||
|
||||
void NearbySharingServiceImpl::OnSuspendResumeEvent(
|
||||
nearby::api::DeviceInfo::SuspendResumeEvent event) {
|
||||
bool suspended =
|
||||
event == nearby::api::DeviceInfo::SuspendResumeEvent::kSuspend;
|
||||
{
|
||||
absl::MutexLock lock(suspend_mutex_);
|
||||
suspended_ = suspended;
|
||||
if (!suspended) {
|
||||
resume_delay_timer_ = std::make_unique<ThreadTimer>(
|
||||
*service_thread_, "suspend_resume_timer", kResumeDelay, [this]() {
|
||||
{
|
||||
absl::MutexLock lock(suspend_mutex_);
|
||||
if (suspended_) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG(INFO) << "InvalidateSurfaceState due to system resume";
|
||||
InvalidateSurfaceState();
|
||||
});
|
||||
}
|
||||
}
|
||||
if (suspended) {
|
||||
RunOnNearbySharingServiceThread("on_suspend", [this]() {
|
||||
LOG(INFO) << "InvalidateSurfaceState due to system suspend";
|
||||
{
|
||||
absl::MutexLock lock(suspend_mutex_);
|
||||
if (!suspended_) {
|
||||
return;
|
||||
}
|
||||
resume_delay_timer_.reset();
|
||||
}
|
||||
InvalidateSurfaceState();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void NearbySharingServiceImpl::AdapterPresentChanged(
|
||||
sharing::api::BluetoothAdapter* adapter, bool present) {
|
||||
RunOnNearbySharingServiceThread("bt_adapter_present_changed", [this, adapter,
|
||||
@@ -1845,7 +1922,7 @@ bool NearbySharingServiceImpl::HasAvailableConnectionMediums() {
|
||||
|
||||
void NearbySharingServiceImpl::InvalidateSurfaceState() {
|
||||
InvalidateSendSurfaceState();
|
||||
InvalidateReceiveSurfaceState();
|
||||
InvalidateAdvertisingState();
|
||||
}
|
||||
|
||||
void NearbySharingServiceImpl::InvalidateSendSurfaceState() {
|
||||
@@ -1854,6 +1931,16 @@ void NearbySharingServiceImpl::InvalidateSendSurfaceState() {
|
||||
}
|
||||
|
||||
void NearbySharingServiceImpl::InvalidateScanningState() {
|
||||
{
|
||||
absl::MutexLock lock(suspend_mutex_);
|
||||
if (suspended_) {
|
||||
StopScanning();
|
||||
VLOG(1) << __func__
|
||||
<< ": Stopping discovery because the system is suspended.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop scanning when screen is off.
|
||||
if (is_screen_locked_) {
|
||||
StopScanning();
|
||||
@@ -1891,6 +1978,17 @@ void NearbySharingServiceImpl::InvalidateScanningState() {
|
||||
}
|
||||
|
||||
void NearbySharingServiceImpl::InvalidateFastInitiationAdvertising() {
|
||||
{
|
||||
absl::MutexLock lock(suspend_mutex_);
|
||||
if (suspended_) {
|
||||
StopFastInitiationAdvertising();
|
||||
VLOG(1) << __func__
|
||||
<< ": Stopping fast initiation advertising because the "
|
||||
"system is suspended.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Screen is off. Do no work.
|
||||
if (is_screen_locked_) {
|
||||
StopFastInitiationAdvertising();
|
||||
@@ -1929,13 +2027,26 @@ void NearbySharingServiceImpl::InvalidateFastInitiationAdvertising() {
|
||||
StartFastInitiationAdvertising();
|
||||
}
|
||||
|
||||
void NearbySharingServiceImpl::InvalidateReceiveSurfaceState() {
|
||||
InvalidateAdvertisingState();
|
||||
}
|
||||
|
||||
void NearbySharingServiceImpl::InvalidateAdvertisingState() {
|
||||
// Do not advertise on lock screen unless Self Share is enabled.
|
||||
if (is_screen_locked_) {
|
||||
{
|
||||
absl::MutexLock lock(suspend_mutex_);
|
||||
if (suspended_) {
|
||||
StopAdvertising();
|
||||
VLOG(1) << __func__
|
||||
<< ": Stopping advertising because the system is suspended.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool supports_advertising_on_lock_screen =
|
||||
NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_sharing_feature::
|
||||
kEnableBackup) &&
|
||||
sync_manager_.HasSyncBindings();
|
||||
DeviceVisibility visibility = settings_->GetVisibility();
|
||||
// Do not advertise on lock screen unless Self Share is enabled, or Backup is
|
||||
// enabled and there are existing SyncBindings.
|
||||
if (is_screen_locked_ && !supports_advertising_on_lock_screen) {
|
||||
StopAdvertising();
|
||||
VLOG(1) << __func__
|
||||
<< ": Stopping advertising because the screen is locked.";
|
||||
@@ -1969,29 +2080,51 @@ void NearbySharingServiceImpl::InvalidateAdvertisingState() {
|
||||
|
||||
// We should only advertise if the user has set the visibility to something
|
||||
// other than HIDDEN or UNSPECIFIED.
|
||||
if (!IsVisibleInBackground(settings_->GetVisibility())) {
|
||||
if (!IsVisibleInBackground(visibility)) {
|
||||
StopAdvertising();
|
||||
VLOG(1) << __func__
|
||||
<< ": Stopping advertising because device is visible to NO_ONE.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_screen_locked_ && supports_advertising_on_lock_screen) {
|
||||
if (visibility != DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE) {
|
||||
VLOG(1) << __func__
|
||||
<< ": Restarting advertising to SELF_SHARE on lock screen.";
|
||||
visibility = DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE;
|
||||
}
|
||||
}
|
||||
|
||||
bool need_to_restart_advertising = false;
|
||||
|
||||
// This is used to set up the PairedKeyVerificationRunner correctly on
|
||||
// incoming connections.
|
||||
advertising_on_screen_locked_ = is_screen_locked_;
|
||||
|
||||
if (last_advertised_device_visibility_ !=
|
||||
DeviceVisibility::DEVICE_VISIBILITY_UNSPECIFIED &&
|
||||
visibility != last_advertised_device_visibility_) {
|
||||
StopAdvertising();
|
||||
need_to_restart_advertising = true;
|
||||
VLOG(1) << __func__
|
||||
<< ": Restarting advertising because visibility has changed.";
|
||||
}
|
||||
|
||||
PowerLevel power_level;
|
||||
if (!foreground_receive_callbacks_map_.empty()) {
|
||||
power_level = PowerLevel::kHighPower;
|
||||
} else {
|
||||
power_level = PowerLevel::kLowPower;
|
||||
}
|
||||
|
||||
DataUsage data_usage = settings_->GetDataUsage();
|
||||
if (advertising_power_level_ != PowerLevel::kUnknown) {
|
||||
if (!need_to_restart_advertising &&
|
||||
advertising_power_level_ != PowerLevel::kUnknown) {
|
||||
if (power_level == advertising_power_level_) {
|
||||
VLOG(1) << __func__ << ": Ignoring, already advertising with power level "
|
||||
<< PowerLevelToString(advertising_power_level_)
|
||||
<< " and data usage preference " << static_cast<int>(data_usage);
|
||||
return;
|
||||
}
|
||||
|
||||
StopAdvertising();
|
||||
VLOG(1) << __func__ << ": Restart advertising with power level "
|
||||
<< PowerLevelToString(power_level) << " and data usage preference "
|
||||
@@ -1999,7 +2132,6 @@ void NearbySharingServiceImpl::InvalidateAdvertisingState() {
|
||||
}
|
||||
|
||||
std::optional<std::string> device_name;
|
||||
DeviceVisibility visibility = settings_->GetVisibility();
|
||||
if (visibility == DeviceVisibility::DEVICE_VISIBILITY_EVERYONE) {
|
||||
device_name = local_device_data_manager_->GetDeviceName();
|
||||
}
|
||||
@@ -2043,11 +2175,13 @@ void NearbySharingServiceImpl::InvalidateAdvertisingState() {
|
||||
force_new_endpoint_id_ = false;
|
||||
|
||||
advertising_power_level_ = power_level;
|
||||
last_advertised_device_visibility_ = visibility;
|
||||
VLOG(1) << __func__
|
||||
<< ": StartAdvertising requested over Nearby Connections: "
|
||||
<< " power level: " << PowerLevelToString(power_level)
|
||||
<< " screen locked: " << is_screen_locked_
|
||||
<< " visibility: "
|
||||
<< DeviceVisibility_Name(settings_->GetVisibility())
|
||||
<< DeviceVisibility_Name(visibility)
|
||||
<< " data usage: " << DataUsage_Name(data_usage)
|
||||
<< " advertise device name?: "
|
||||
<< (device_name.has_value() ? "yes" : "no");
|
||||
@@ -2090,7 +2224,7 @@ void NearbySharingServiceImpl::StartScanning() {
|
||||
scanning_start_timestamp_ = context_->GetClock()->Now();
|
||||
share_foreground_send_surface_start_timestamp_ = absl::InfinitePast();
|
||||
is_scanning_ = true;
|
||||
InvalidateReceiveSurfaceState();
|
||||
InvalidateAdvertisingState();
|
||||
|
||||
outgoing_targets_manager_.AllTargetsLost(
|
||||
Milliseconds(NearbyFlags::GetInstance().GetInt64Flag(
|
||||
@@ -2333,6 +2467,15 @@ void NearbySharingServiceImpl::OnIncomingTransferUpdate(
|
||||
LOG(WARNING) << __func__ << ": Unknown file paths are not empty.";
|
||||
}
|
||||
}
|
||||
// If backup session, update last backup time in preference.
|
||||
if (session.session_usage() == ShareSessionUsage::kFileSync) {
|
||||
if (session.certificate()) {
|
||||
sync_manager_.SetSyncConfigBackupTime(
|
||||
session.certificate()->binding_id(),
|
||||
metadata.status() == TransferMetadata::Status::kComplete,
|
||||
context_->GetClock()->Now());
|
||||
}
|
||||
}
|
||||
} else if (metadata.status() ==
|
||||
TransferMetadata::Status::kAwaitingLocalConfirmation) {
|
||||
OnTransferStarted(/*is_incoming=*/true);
|
||||
@@ -2463,6 +2606,7 @@ void NearbySharingServiceImpl::OnIncomingDecryptedCertificate(
|
||||
.visibility = settings_->GetVisibility(),
|
||||
.last_visibility = settings_->GetLastVisibility(),
|
||||
.last_visibility_time = settings_->GetLastVisibilityTimestamp(),
|
||||
.screen_locked_advertising = advertising_on_screen_locked_,
|
||||
},
|
||||
GetCertificateManager(),
|
||||
absl::bind_front(
|
||||
@@ -2588,8 +2732,7 @@ void NearbySharingServiceImpl::BeginOutgoingTransfer(
|
||||
bool protection_enabled =
|
||||
preference_manager_.GetBoolean(PrefNames::kAdvancedProtectionEnabled,
|
||||
/*default_value=*/false);
|
||||
session.SetAdvancedProtectionStatus(protection_enabled,
|
||||
/*advanced_protection_mismatch=*/false);
|
||||
session.SetAdvancedProtectionStatus(protection_enabled);
|
||||
if (session.token().empty() || !protection_enabled) {
|
||||
// Auto accept if no token or if advanced protection is disabled.
|
||||
OutgoingSessionAccept(session);
|
||||
@@ -2624,6 +2767,20 @@ void NearbySharingServiceImpl::BeginOutgoingPairing(
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::string> NearbySharingServiceImpl::GetCertIdsForSyncBinding() {
|
||||
std::vector<std::string> cert_ids;
|
||||
cert_ids.reserve(2);
|
||||
if (auto id = certificate_manager_->GetPrivateCertificateId(
|
||||
proto::DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE)) {
|
||||
cert_ids.push_back(*id);
|
||||
}
|
||||
if (auto id = certificate_manager_->GetPrivateCertificateId(
|
||||
proto::DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS)) {
|
||||
cert_ids.push_back(*id);
|
||||
}
|
||||
return cert_ids;
|
||||
}
|
||||
|
||||
void NearbySharingServiceImpl::OnInitiateSyncBindingResponse(
|
||||
int64_t share_target_id, absl::StatusOr<std::string> binding_status) {
|
||||
RunOnNearbySharingServiceThread(
|
||||
@@ -2642,11 +2799,10 @@ void NearbySharingServiceImpl::OnInitiateSyncBindingResponse(
|
||||
LOG(INFO) << __func__
|
||||
<< ": Sync binding rpc succeeded: id=" << binding_id;
|
||||
session->StartPeerBinding(
|
||||
binding_id, BindingRequest::FILESYNC,
|
||||
[this, share_target_id,
|
||||
binding_id](BindingResponse::Status status) {
|
||||
OnPeerSyncBindingComplete(share_target_id, binding_id, status);
|
||||
});
|
||||
binding_id, BindingRequest::FILESYNC, GetCertIdsForSyncBinding(),
|
||||
absl::bind_front(
|
||||
&NearbySharingServiceImpl::OnPeerSyncBindingComplete, this,
|
||||
share_target_id, binding_id));
|
||||
} else {
|
||||
LOG(INFO) << __func__ << ": Sync binding rpc failed.";
|
||||
session->Abort(TransferMetadata::Status::kFailed);
|
||||
@@ -2656,7 +2812,7 @@ void NearbySharingServiceImpl::OnInitiateSyncBindingResponse(
|
||||
|
||||
void NearbySharingServiceImpl::OnPeerSyncBindingComplete(
|
||||
int64_t share_target_id, absl::string_view binding_id,
|
||||
BindingResponse::Status status) {
|
||||
const BindingResponse& binding_response) {
|
||||
OutgoingShareSession* session =
|
||||
outgoing_targets_manager_.GetOutgoingShareSession(share_target_id);
|
||||
if (!session || !session->IsConnected()) {
|
||||
@@ -2664,7 +2820,7 @@ void NearbySharingServiceImpl::OnPeerSyncBindingComplete(
|
||||
<< share_target_id;
|
||||
return;
|
||||
}
|
||||
if (status != BindingResponse::SUCCESS) {
|
||||
if (binding_response.status() != BindingResponse::SUCCESS) {
|
||||
LOG(INFO) << __func__ << ": Sync binding response failed.";
|
||||
session->Abort(TransferMetadata::Status::kFailed);
|
||||
return;
|
||||
@@ -2690,9 +2846,28 @@ void NearbySharingServiceImpl::OnPeerSyncBindingComplete(
|
||||
.set_binding_id(binding_id)
|
||||
.set_status(TransferMetadata::Status::kComplete)
|
||||
.build());
|
||||
// Update binding id in peer certificates so we can identify the sync peer
|
||||
// immediately without waiting for cert sync from Backend.
|
||||
for (const auto& cert_id : binding_response.cert_ids()) {
|
||||
certificate_manager_->AddBindingToPublicCertificate(cert_id, binding_id);
|
||||
}
|
||||
|
||||
// Download public certificates again to update the newly added sync binding.
|
||||
certificate_manager_->DownloadPublicCertificates();
|
||||
if (binding_response.has_join_binding_time()) {
|
||||
auto join_binding_time =
|
||||
util_time::DecodeGoogleApiProto(binding_response.join_binding_time());
|
||||
if (join_binding_time.ok()) {
|
||||
certificate_manager_->SetJoinBindingTime(join_binding_time.value(),
|
||||
kJoinBindingTimeLifeTime);
|
||||
}
|
||||
}
|
||||
// TODO: Remove this check after BE supports cert download without join time.
|
||||
// Without join time, the new download can overwrite the bindings we added
|
||||
// from the binding response.
|
||||
if (binding_response.has_join_binding_time()) {
|
||||
// Download public certificates again to update the newly added sync
|
||||
// binding.
|
||||
certificate_manager_->DownloadPublicCertificates();
|
||||
}
|
||||
}
|
||||
|
||||
void NearbySharingServiceImpl::OnReceivedIntroduction(
|
||||
@@ -2737,7 +2912,9 @@ void NearbySharingServiceImpl::OnReceivedIntroduction(
|
||||
// Log analytics event of receiving introduction.
|
||||
analytics_recorder_.NewReceiveIntroduction(
|
||||
session.session_id(), session.share_target(),
|
||||
/*referrer_package=*/std::nullopt, session.os_type());
|
||||
/*referrer_package=*/std::nullopt, session.os_type(),
|
||||
IntroductionUseCaseToLoggingUseCase(frame.use_case()),
|
||||
nearby::sharing::cpp::common::GetPowerStatus());
|
||||
|
||||
std::optional<size_t> available_storage =
|
||||
device_info_.GetAvailableDiskSpaceInBytes(save_path);
|
||||
|
||||
@@ -31,11 +31,13 @@
|
||||
#include "location/nearby/sharing/lib/rpc/sharing_rpc_client.h"
|
||||
#include "location/nearby/sharing/lib/sync/sync_manager.h"
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "internal/platform/clock.h"
|
||||
@@ -219,6 +221,9 @@ class NearbySharingServiceImpl
|
||||
// Handle the state changes of screen lock.
|
||||
void OnLockStateChanged(bool locked);
|
||||
|
||||
void OnSuspendResumeEvent(
|
||||
nearby::api::DeviceInfo::SuspendResumeEvent event);
|
||||
|
||||
// Handle the state changes of bluetooth adapter.
|
||||
void AdapterPresentChanged(sharing::api::BluetoothAdapter* adapter,
|
||||
bool present) override;
|
||||
@@ -281,7 +286,6 @@ class NearbySharingServiceImpl
|
||||
void InvalidateSendSurfaceState();
|
||||
void InvalidateScanningState();
|
||||
void InvalidateFastInitiationAdvertising();
|
||||
void InvalidateReceiveSurfaceState();
|
||||
void InvalidateAdvertisingState();
|
||||
void StopAdvertising();
|
||||
void StartScanning();
|
||||
@@ -406,13 +410,14 @@ class NearbySharingServiceImpl
|
||||
bool OutgoingSessionAccept(OutgoingShareSession& session);
|
||||
void OnIncomingFilesMetadataUpdated(int64_t share_target_id,
|
||||
TransferMetadata metadata, bool success);
|
||||
std::vector<std::string> GetCertIdsForSyncBinding();
|
||||
// Called when InitiateBinding rpc returns.
|
||||
void OnInitiateSyncBindingResponse(
|
||||
int64_t share_target_id, absl::StatusOr<std::string> binding_status);
|
||||
// Called when Bindings response frame is received from the peer.
|
||||
void OnPeerSyncBindingComplete(
|
||||
int64_t share_target_id, absl::string_view binding_id,
|
||||
service::proto::BindingResponse::Status status);
|
||||
const service::proto::BindingResponse& binding_response);
|
||||
|
||||
// Notify all registered send surfaces of share target state changes.
|
||||
void NotifyShareTargetDiscovered(const ShareTarget& share_target);
|
||||
@@ -546,6 +551,16 @@ class NearbySharingServiceImpl
|
||||
bool force_new_endpoint_id_ = false;
|
||||
OutgoingTargetsManager outgoing_targets_manager_;
|
||||
nearby::sharing::SyncManager sync_manager_;
|
||||
|
||||
// Visibility used for the last advertisement.
|
||||
proto::DeviceVisibility last_advertised_device_visibility_ =
|
||||
proto::DeviceVisibility::DEVICE_VISIBILITY_UNSPECIFIED;
|
||||
bool advertising_on_screen_locked_ = false;
|
||||
int64_t suspend_resume_listener_id_ = 0;
|
||||
absl::Mutex suspend_mutex_;
|
||||
bool suspended_ ABSL_GUARDED_BY(suspend_mutex_) = false;
|
||||
std::unique_ptr<ThreadTimer> resume_delay_timer_
|
||||
ABSL_GUARDED_BY(suspend_mutex_);
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "google/protobuf/timestamp.pb.h"
|
||||
#include "location/nearby/analytics/cpp/logging/mock_event_logger.h"
|
||||
#include "location/nearby/sharing/lib/account/fake_account_manager.h"
|
||||
#include "location/nearby/sharing/lib/account/mock_account_observer.h"
|
||||
@@ -4638,6 +4639,34 @@ TEST_F(NearbySharingServiceImplTest, ScreenLocksDuringAdvertising) {
|
||||
EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown());
|
||||
}
|
||||
|
||||
TEST_F(NearbySharingServiceImplTest,
|
||||
ScreenLocksDuringAdvertisingWithBackupAndSyncBindings) {
|
||||
// Enable Backup flag.
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_sharing_feature::kEnableBackup, true);
|
||||
|
||||
// Add SyncBindings.
|
||||
nearby::sharing::sync::SyncBindingPrefs sync_binding_prefs;
|
||||
auto* binding = sync_binding_prefs.add_sync_bindings();
|
||||
binding->set_binding_id("test_binding_id");
|
||||
service_->GetSettings()->SetSyncBindingPrefs(sync_binding_prefs);
|
||||
|
||||
SetLanConnected(true);
|
||||
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());
|
||||
|
||||
// Screen locks, but we should STILL be advertising.
|
||||
SetScreenLocked(true);
|
||||
EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising());
|
||||
EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown());
|
||||
}
|
||||
|
||||
TEST_F(NearbySharingServiceImplTest, ScreenLocksDuringDiscovery) {
|
||||
SetLanConnected(true);
|
||||
MockTransferUpdateCallback transfer_callback;
|
||||
@@ -5151,6 +5180,7 @@ TEST_F(NearbySharingServiceImplTest,
|
||||
EXPECT_EQ(frame->v1().bindings().binding_request().binding_id(), kBindingId);
|
||||
EXPECT_EQ(frame->v1().bindings().binding_request().type(),
|
||||
service::proto::BindingRequest::FILESYNC);
|
||||
EXPECT_EQ(frame->v1().bindings().binding_request().cert_ids_size(), 2);
|
||||
|
||||
// BindingResponse frame timeout.
|
||||
FastForward(absl::Seconds(60));
|
||||
@@ -5201,15 +5231,18 @@ TEST_F(NearbySharingServiceImplTest, InitiatePairingSuccess) {
|
||||
EXPECT_EQ(frame->v1().bindings().binding_request().type(),
|
||||
service::proto::BindingRequest::FILESYNC);
|
||||
|
||||
preference_manager_.SetString(PrefNames::kCustomSavePath, "Downloads");
|
||||
FilePath custom_save_path = Files::GetTemporaryDirectory();
|
||||
preference_manager_.SetString(PrefNames::kCustomSavePath,
|
||||
custom_save_path.ToString());
|
||||
Frame binding_response_frame;
|
||||
binding_response_frame.set_version(Frame::V1);
|
||||
binding_response_frame.mutable_v1()->set_type(
|
||||
service::proto::V1Frame::BINDINGS);
|
||||
binding_response_frame.mutable_v1()
|
||||
auto* binding_response = binding_response_frame.mutable_v1()
|
||||
->mutable_bindings()
|
||||
->mutable_binding_response()
|
||||
->set_status(service::proto::BindingResponse::SUCCESS);
|
||||
->mutable_binding_response();
|
||||
binding_response->set_status(service::proto::BindingResponse::SUCCESS);
|
||||
binding_response->mutable_join_binding_time()->set_seconds(1234567890);
|
||||
std::vector<uint8_t> result_bytes(binding_response_frame.ByteSizeLong());
|
||||
binding_response_frame.SerializeToArray(result_bytes.data(),
|
||||
result_bytes.size());
|
||||
@@ -5230,7 +5263,7 @@ TEST_F(NearbySharingServiceImplTest, InitiatePairingSuccess) {
|
||||
expected_binding.set_binding_id(kBindingId);
|
||||
expected_binding.set_source_name(kDeviceName);
|
||||
expected_binding.set_destination_directory(
|
||||
FilePath("Downloads").append(FilePath(kDeviceName)).ToString());
|
||||
FilePath(custom_save_path).append(FilePath(kDeviceName)).ToString());
|
||||
expected_binding.set_source_device_type(
|
||||
sync::SyncBinding::SOURCE_DEVICE_TYPE_PHONE);
|
||||
EXPECT_THAT(binding->sync_bindings(0), EqualsProto(expected_binding));
|
||||
@@ -5305,7 +5338,9 @@ TEST_F(NearbySharingServiceImplTest,
|
||||
EXPECT_EQ(frame->v1().bindings().binding_request().type(),
|
||||
service::proto::BindingRequest::FILESYNC);
|
||||
|
||||
preference_manager_.SetString(PrefNames::kCustomSavePath, "Downloads");
|
||||
FilePath custom_save_path = Files::GetTemporaryDirectory();
|
||||
preference_manager_.SetString(PrefNames::kCustomSavePath,
|
||||
custom_save_path.ToString());
|
||||
Frame binding_response_frame;
|
||||
binding_response_frame.set_version(Frame::V1);
|
||||
binding_response_frame.mutable_v1()->set_type(
|
||||
@@ -5332,7 +5367,7 @@ TEST_F(NearbySharingServiceImplTest,
|
||||
expected_binding.set_binding_id(kBindingId);
|
||||
expected_binding.set_source_name(kDeviceName);
|
||||
expected_binding.set_destination_directory(
|
||||
FilePath("Downloads").append(FilePath(kDeviceName)).ToString());
|
||||
FilePath(custom_save_path).append(FilePath(kDeviceName)).ToString());
|
||||
expected_binding.set_source_device_type(
|
||||
sync::SyncBinding::SOURCE_DEVICE_TYPE_PHONE);
|
||||
EXPECT_THAT(binding->sync_bindings(0), EqualsProto(expected_binding));
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/base/file_path.h"
|
||||
#include "internal/base/files.h"
|
||||
#include "internal/platform/clock.h"
|
||||
#include "internal/platform/implementation/device_info.h"
|
||||
#include "internal/platform/task_runner.h"
|
||||
@@ -184,8 +186,12 @@ void NearbyShareSettings::RestoreFallbackVisibility() {
|
||||
}
|
||||
|
||||
std::string NearbyShareSettings::GetCustomSavePath() const {
|
||||
return preference_manager_.GetString(
|
||||
std::string custom_save_path = preference_manager_.GetString(
|
||||
PrefNames::kCustomSavePath, device_info_.GetDownloadPath().ToString());
|
||||
if (Files::IsAbsolutePath(FilePath(custom_save_path))) {
|
||||
return custom_save_path;
|
||||
}
|
||||
return device_info_.GetDownloadPath().ToString();
|
||||
}
|
||||
|
||||
SyncBindingPrefs NearbyShareSettings::GetSyncBindingPrefs() const {
|
||||
@@ -347,6 +353,10 @@ void NearbyShareSettings::SetFallbackVisibility(DeviceVisibility visibility) {
|
||||
|
||||
void NearbyShareSettings::SetCustomSavePathAsync(
|
||||
absl::string_view save_path, const std::function<void()>& callback) {
|
||||
if (!Files::IsAbsolutePath(FilePath(save_path))) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
absl::MutexLock lock(mutex_);
|
||||
preference_manager_.SetString(PrefNames::kCustomSavePath, save_path);
|
||||
callback();
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "location/nearby/cpp/sharing/clients/cpp/common/nearby_sharing_common.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "internal/base/file_path.h"
|
||||
#include "internal/base/files.h"
|
||||
#include "internal/platform/clock.h"
|
||||
@@ -372,8 +374,7 @@ void OutgoingShareSession::SendPayloads(
|
||||
analytics_recorder().NewSendAttachmentsStart(
|
||||
session_id(), attachment_container(),
|
||||
/*transfer_position=*/1,
|
||||
/*concurrent_connections=*/1, advanced_protection_enabled_,
|
||||
advanced_protection_mismatch_);
|
||||
/*concurrent_connections=*/1, advanced_protection_enabled_);
|
||||
VLOG(1) << "The connection was accepted. Payloads are now being sent.";
|
||||
InitializePayloadTracker(std::move(payload_transder_update_callback));
|
||||
SendNextPayload();
|
||||
@@ -423,10 +424,11 @@ bool OutgoingShareSession::SendIntroduction(
|
||||
}
|
||||
WriteFrame(frame);
|
||||
// Log analytics event of sending introduction.
|
||||
analytics_recorder().NewSendIntroduction(session_id(), share_target(),
|
||||
/*transfer_position=*/1,
|
||||
/*concurrent_connections=*/1,
|
||||
os_type());
|
||||
analytics_recorder().NewSendIntroduction(
|
||||
session_id(), share_target(),
|
||||
/*transfer_position=*/1,
|
||||
/*concurrent_connections=*/1, os_type(),
|
||||
nearby::sharing::cpp::common::GetPowerStatus());
|
||||
VLOG(1) << "Successfully wrote the introduction frame";
|
||||
ready_for_accept_ = true;
|
||||
mutual_acceptance_timeout_ = std::make_unique<ThreadTimer>(
|
||||
@@ -646,7 +648,8 @@ OutgoingShareSession::ProcessPayloadTransferUpdates() {
|
||||
|
||||
void OutgoingShareSession::StartPeerBinding(
|
||||
std::string binding_id, BindingRequest::Type binding_type,
|
||||
absl::AnyInvocable<void(BindingResponse::Status)> callback) {
|
||||
absl::Span<const std::string> cert_ids,
|
||||
absl::AnyInvocable<void(const BindingResponse&)> callback) {
|
||||
Frame frame;
|
||||
frame.set_version(Frame::V1);
|
||||
V1Frame* v1_frame = frame.mutable_v1();
|
||||
@@ -655,6 +658,7 @@ void OutgoingShareSession::StartPeerBinding(
|
||||
v1_frame->mutable_bindings()->mutable_binding_request();
|
||||
binding_request->set_binding_id(binding_id);
|
||||
binding_request->set_type(binding_type);
|
||||
binding_request->mutable_cert_ids()->Add(cert_ids.begin(), cert_ids.end());
|
||||
WriteFrame(frame);
|
||||
LOG(INFO) << "Waiting for bindings response frame from " << share_target().id;
|
||||
UpdateTransferMetadata(
|
||||
@@ -667,19 +671,19 @@ void OutgoingShareSession::StartPeerBinding(
|
||||
nearby::sharing::service::proto::V1Frame::BINDINGS,
|
||||
[callback = std::move(callback)](
|
||||
bool is_timeout, std::optional<V1Frame> frame) mutable {
|
||||
BindingResponse failure_response;
|
||||
failure_response.set_status(BindingResponse::FAILURE);
|
||||
if (!frame.has_value()) {
|
||||
std::move(callback)(BindingResponse::FAILURE);
|
||||
std::move(callback)(failure_response);
|
||||
return;
|
||||
}
|
||||
if (!frame->has_bindings() ||
|
||||
!frame->bindings().has_binding_response() ||
|
||||
frame->bindings().binding_response().status() !=
|
||||
BindingResponse::SUCCESS) {
|
||||
std::move(callback)(BindingResponse::FAILURE);
|
||||
!frame->bindings().has_binding_response()) {
|
||||
std::move(callback)(failure_response);
|
||||
return;
|
||||
}
|
||||
// Peer binding flow completed successfully.
|
||||
std::move(callback)(BindingResponse::SUCCESS);
|
||||
std::move(callback)(frame->bindings().binding_response());
|
||||
},
|
||||
kReadResponseFrameTimeout);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "internal/platform/clock.h"
|
||||
#include "internal/platform/task_runner.h"
|
||||
#include "sharing/analytics/analytics_recorder.h"
|
||||
@@ -141,10 +142,8 @@ class OutgoingShareSession : public ShareSession {
|
||||
|
||||
std::optional<TransferMetadata> ProcessPayloadTransferUpdates();
|
||||
|
||||
void SetAdvancedProtectionStatus(bool advanced_protection_enabled,
|
||||
bool advanced_protection_mismatch) {
|
||||
void SetAdvancedProtectionStatus(bool advanced_protection_enabled) {
|
||||
advanced_protection_enabled_ = advanced_protection_enabled;
|
||||
advanced_protection_mismatch_ = advanced_protection_mismatch;
|
||||
}
|
||||
|
||||
// Returns true if the session is connected or in the process of connecting.
|
||||
@@ -166,13 +165,16 @@ class OutgoingShareSession : public ShareSession {
|
||||
|
||||
// Initiates the peer binding message exchange with the remote device.
|
||||
// `binding_id` is the result of a successful call to InitiateBinding rpc.
|
||||
// `cert_ids` are the public certificate ids that can be used to identify this
|
||||
// device.
|
||||
// `callback` is called when either a BindingResponse frame is received or a
|
||||
// timeout occurs.
|
||||
void StartPeerBinding(
|
||||
std::string binding_id,
|
||||
nearby::sharing::service::proto::BindingRequest::Type binding_type,
|
||||
absl::Span<const std::string> cert_ids,
|
||||
absl::AnyInvocable<
|
||||
void(nearby::sharing::service::proto::BindingResponse::Status)>
|
||||
void(const nearby::sharing::service::proto::BindingResponse&)>
|
||||
callback);
|
||||
|
||||
protected:
|
||||
@@ -210,7 +212,6 @@ class OutgoingShareSession : public ShareSession {
|
||||
// Timeout waiting for remote disconnect in order to complete transfer.
|
||||
std::unique_ptr<ThreadTimer> disconnection_timeout_;
|
||||
bool advanced_protection_enabled_ = false;
|
||||
bool advanced_protection_mismatch_ = false;
|
||||
bool is_connecting_ = false;
|
||||
// Session can be for transfer or pairing.
|
||||
bool is_transfer_session_ = false;
|
||||
|
||||
@@ -74,6 +74,7 @@ using ::nearby::sharing::service::proto::V1Frame;
|
||||
using ::nearby::sharing::service::proto::WifiCredentials;
|
||||
using ::testing::_;
|
||||
using ::testing::AllOf;
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::Eq;
|
||||
using ::protobuf_matchers::EqualsProto;
|
||||
using ::testing::InSequence;
|
||||
@@ -676,11 +677,7 @@ TEST_F(OutgoingShareSessionTest, SendPayloads) {
|
||||
Log(Matcher<const SharingLog&>(AllOf(
|
||||
(HasCategory(EventCategory::SENDING_EVENT),
|
||||
HasEventType(EventType::SEND_ATTACHMENTS_START),
|
||||
ProtoField<"send_attachments_start", "session_id">(1234),
|
||||
ProtoField<"send_attachments_start", "advanced_protection_enabled">(
|
||||
false),
|
||||
ProtoField<"send_attachments_start", "advanced_protection_mismatch">(
|
||||
false))))));
|
||||
ProtoField<"send_attachments_start", "session_id">(1234))))));
|
||||
|
||||
NearbyConnectionImpl connection(device_info_);
|
||||
ConnectionSuccess(&connection);
|
||||
@@ -717,15 +714,12 @@ TEST_F(OutgoingShareSessionTest, SendPayloadsSetsAdvancedProtectionFlags) {
|
||||
HasEventType(EventType::SEND_ATTACHMENTS_START),
|
||||
ProtoField<"send_attachments_start", "session_id">(1234),
|
||||
ProtoField<"send_attachments_start", "advanced_protection_enabled">(
|
||||
true),
|
||||
ProtoField<"send_attachments_start", "advanced_protection_mismatch">(
|
||||
true))))));
|
||||
|
||||
NearbyConnectionImpl connection(device_info_);
|
||||
ConnectionSuccess(&connection);
|
||||
|
||||
session_.SetAdvancedProtectionStatus(/*advanced_protection_enabled=*/true,
|
||||
/*advanced_protection_mismatch=*/true);
|
||||
session_.SetAdvancedProtectionStatus(/*advanced_protection_enabled=*/true);
|
||||
session_.SendPayloads([](bool is_timeout, std::optional<V1Frame> frame) {},
|
||||
payload_transder_update_callback.AsStdFunction());
|
||||
|
||||
@@ -759,8 +753,6 @@ TEST_F(OutgoingShareSessionTest, SendNextPayload) {
|
||||
HasEventType(EventType::SEND_ATTACHMENTS_START),
|
||||
ProtoField<"send_attachments_start", "session_id">(1234),
|
||||
ProtoField<"send_attachments_start", "advanced_protection_enabled">(
|
||||
false),
|
||||
ProtoField<"send_attachments_start", "advanced_protection_mismatch">(
|
||||
false))))));
|
||||
NearbyConnectionImpl connection(device_info_);
|
||||
ConnectionSuccess(&connection);
|
||||
@@ -937,6 +929,8 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingSuccess) {
|
||||
binding_request {
|
||||
binding_id: "test_binding_id"
|
||||
type: FILESYNC
|
||||
cert_ids: "cert_id_1"
|
||||
cert_ids: "cert_id_2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -954,12 +948,12 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingSuccess) {
|
||||
AllOf(HasStatus(TransferMetadata::Status::kAwaitingRemoteAcceptance),
|
||||
HasUsage(ShareSessionUsage::kPairing))));
|
||||
|
||||
BindingResponse::Status binding_response_status = BindingResponse::FAILURE;
|
||||
session_.StartPeerBinding("test_binding_id", BindingRequest::FILESYNC,
|
||||
[&binding_response_status](
|
||||
BindingResponse::Status status) {
|
||||
binding_response_status = status;
|
||||
});
|
||||
BindingResponse binding_response;
|
||||
session_.StartPeerBinding(
|
||||
"test_binding_id", BindingRequest::FILESYNC, {"cert_id_1", "cert_id_2"},
|
||||
[&binding_response](const BindingResponse& response) {
|
||||
binding_response = response;
|
||||
});
|
||||
|
||||
Frame frame;
|
||||
ASSERT_THAT(frame.ParseFromArray(frame_data.data(), frame_data.size()),
|
||||
@@ -976,6 +970,8 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingSuccess) {
|
||||
bindings {
|
||||
binding_response {
|
||||
status: SUCCESS
|
||||
cert_ids: "cert_id_3"
|
||||
cert_ids: "cert_id_4"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -987,7 +983,9 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingSuccess) {
|
||||
IsTrue());
|
||||
connection.WriteMessage(std::move(data));
|
||||
|
||||
EXPECT_THAT(binding_response_status, Eq(BindingResponse::SUCCESS));
|
||||
EXPECT_THAT(binding_response.status(), Eq(BindingResponse::SUCCESS));
|
||||
EXPECT_THAT(binding_response.cert_ids(),
|
||||
ElementsAre("cert_id_3", "cert_id_4"));
|
||||
}
|
||||
|
||||
TEST_F(OutgoingShareSessionTest, StartPeerBindingTimeout) {
|
||||
@@ -1022,12 +1020,12 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingTimeout) {
|
||||
AllOf(HasStatus(TransferMetadata::Status::kAwaitingRemoteAcceptance),
|
||||
HasUsage(ShareSessionUsage::kPairing))));
|
||||
|
||||
BindingResponse::Status binding_response_status = BindingResponse::FAILURE;
|
||||
session_.StartPeerBinding("test_binding_id", BindingRequest::FILESYNC,
|
||||
[&binding_response_status](
|
||||
BindingResponse::Status status) {
|
||||
binding_response_status = status;
|
||||
});
|
||||
BindingResponse binding_response;
|
||||
session_.StartPeerBinding(
|
||||
"test_binding_id", BindingRequest::FILESYNC, {},
|
||||
[&binding_response](const BindingResponse& response) {
|
||||
binding_response = response;
|
||||
});
|
||||
|
||||
Frame frame;
|
||||
ASSERT_THAT(frame.ParseFromArray(frame_data.data(), frame_data.size()),
|
||||
@@ -1038,7 +1036,7 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingTimeout) {
|
||||
fake_clock_.FastForward(absl::Seconds(60));
|
||||
fake_task_runner_.SyncWithTimeout(absl::Milliseconds(100));
|
||||
|
||||
EXPECT_THAT(binding_response_status, Eq(BindingResponse::FAILURE));
|
||||
EXPECT_THAT(binding_response.status(), Eq(BindingResponse::FAILURE));
|
||||
}
|
||||
|
||||
TEST_F(OutgoingShareSessionTest, StartPeerBindingFailure) {
|
||||
@@ -1073,12 +1071,12 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingFailure) {
|
||||
AllOf(HasStatus(TransferMetadata::Status::kAwaitingRemoteAcceptance),
|
||||
HasUsage(ShareSessionUsage::kPairing))));
|
||||
|
||||
BindingResponse::Status binding_response_status = BindingResponse::FAILURE;
|
||||
session_.StartPeerBinding("test_binding_id", BindingRequest::FILESYNC,
|
||||
[&binding_response_status](
|
||||
BindingResponse::Status status) {
|
||||
binding_response_status = status;
|
||||
});
|
||||
BindingResponse binding_response;
|
||||
session_.StartPeerBinding(
|
||||
"test_binding_id", BindingRequest::FILESYNC, {},
|
||||
[&binding_response](const BindingResponse& response) {
|
||||
binding_response = response;
|
||||
});
|
||||
|
||||
Frame frame;
|
||||
ASSERT_THAT(frame.ParseFromArray(frame_data.data(), frame_data.size()),
|
||||
@@ -1106,7 +1104,8 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingFailure) {
|
||||
IsTrue());
|
||||
connection.WriteMessage(std::move(data));
|
||||
|
||||
EXPECT_THAT(binding_response_status, Eq(BindingResponse::FAILURE));
|
||||
EXPECT_THAT(binding_response.status(), Eq(BindingResponse::FAILURE));
|
||||
EXPECT_THAT(binding_response.cert_ids(), IsEmpty());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -140,18 +140,8 @@ void PairedKeyVerificationRunner::OnReadPairedKeyEncryptionFrame(
|
||||
OSType::UNKNOWN_OS_TYPE);
|
||||
return;
|
||||
}
|
||||
|
||||
PairedKeyVerificationResult auth_token_hash_result =
|
||||
VerifyAuthTokenHashWithPrivateCertificate(visibility_history_.visibility,
|
||||
*frame);
|
||||
|
||||
if (auth_token_hash_result != PairedKeyVerificationResult::kSuccess) {
|
||||
if (IsVisibilityRecentlyUpdated()) {
|
||||
auth_token_hash_result = VerifyAuthTokenHashWithPrivateCertificate(
|
||||
visibility_history_.last_visibility, *frame);
|
||||
}
|
||||
}
|
||||
|
||||
VerifyAuthTokenHashWithPrivateCertificates(*frame);
|
||||
if (auth_token_hash_result == PairedKeyVerificationResult::kUnable) {
|
||||
if (share_target_is_incoming_ &&
|
||||
visibility_history_.visibility !=
|
||||
@@ -255,9 +245,18 @@ void PairedKeyVerificationRunner::SendPairedKeyEncryptionFrame() {
|
||||
share_target_is_incoming_ ? kNearbyShareReceiverVerificationPrefix
|
||||
: kNearbyShareSenderVerificationPrefix,
|
||||
raw_token_);
|
||||
DeviceVisibility primary_visibility;
|
||||
DeviceVisibility secondary_visibility;
|
||||
if (visibility_history_.screen_locked_advertising) {
|
||||
primary_visibility = DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE;
|
||||
secondary_visibility = visibility_history_.visibility;
|
||||
} else {
|
||||
primary_visibility = visibility_history_.visibility;
|
||||
secondary_visibility = visibility_history_.last_visibility;
|
||||
}
|
||||
std::optional<std::vector<uint8_t>> signature =
|
||||
certificate_manager_.SignWithPrivateCertificate(
|
||||
visibility_history_.visibility, padded_token);
|
||||
certificate_manager_.SignWithPrivateCertificate(primary_visibility,
|
||||
padded_token);
|
||||
if (!signature.has_value() || signature->empty()) {
|
||||
signature = GenerateRandomBytes(kNearbyShareNumBytesRandomSignature);
|
||||
}
|
||||
@@ -282,8 +281,8 @@ void PairedKeyVerificationRunner::SendPairedKeyEncryptionFrame() {
|
||||
LOG(INFO)
|
||||
<< "Attempts to sign authentication token with a previous private key.";
|
||||
std::optional<std::vector<uint8_t>> optional_signature =
|
||||
certificate_manager_.SignWithPrivateCertificate(
|
||||
visibility_history_.last_visibility, padded_token);
|
||||
certificate_manager_.SignWithPrivateCertificate(secondary_visibility,
|
||||
padded_token);
|
||||
|
||||
if (optional_signature.has_value()) {
|
||||
encryption_frame->set_optional_signed_data(optional_signature->data(),
|
||||
@@ -297,22 +296,36 @@ void PairedKeyVerificationRunner::SendPairedKeyEncryptionFrame() {
|
||||
}
|
||||
|
||||
PairedKeyVerificationRunner::PairedKeyVerificationResult
|
||||
PairedKeyVerificationRunner::VerifyAuthTokenHashWithPrivateCertificate(
|
||||
DeviceVisibility visibility,
|
||||
PairedKeyVerificationRunner::VerifyAuthTokenHashWithPrivateCertificates(
|
||||
const nearby::sharing::service::proto::V1Frame& frame) {
|
||||
std::optional<std::vector<uint8_t>> hash =
|
||||
certificate_manager_.HashAuthenticationTokenWithPrivateCertificate(
|
||||
visibility, raw_token_);
|
||||
|
||||
const std::string& frame_hash =
|
||||
frame.paired_key_encryption().secret_id_hash();
|
||||
std::vector<uint8_t> frame_hash_data{frame_hash.begin(), frame_hash.end()};
|
||||
|
||||
if (hash.has_value() && *hash == frame_hash_data) {
|
||||
VLOG(1) << __func__ << ": Successfully verified remote public certificate.";
|
||||
return PairedKeyVerificationResult::kSuccess;
|
||||
std::vector<DeviceVisibility> visibilities_to_check;
|
||||
// At most 3 visibilities to check.
|
||||
visibilities_to_check.reserve(3);
|
||||
// If we are advertising under lock screen then verify against self share
|
||||
// private certificate first.
|
||||
if (visibility_history_.screen_locked_advertising) {
|
||||
visibilities_to_check.push_back(
|
||||
DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE);
|
||||
}
|
||||
visibilities_to_check.push_back(visibility_history_.visibility);
|
||||
if (IsVisibilityRecentlyUpdated()) {
|
||||
visibilities_to_check.push_back(visibility_history_.last_visibility);
|
||||
}
|
||||
for (const auto& visibility : visibilities_to_check) {
|
||||
std::optional<std::vector<uint8_t>> hash =
|
||||
certificate_manager_.HashAuthenticationTokenWithPrivateCertificate(
|
||||
visibility, raw_token_);
|
||||
|
||||
if (hash.has_value() && *hash == frame_hash_data) {
|
||||
VLOG(1) << __func__
|
||||
<< ": Successfully verified remote public certificate.";
|
||||
return PairedKeyVerificationResult::kSuccess;
|
||||
}
|
||||
}
|
||||
VLOG(1) << __func__ << ": Unable to verify remote public certificate.";
|
||||
return PairedKeyVerificationResult::kUnable;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ class PairedKeyVerificationRunner
|
||||
proto::DeviceVisibility visibility;
|
||||
proto::DeviceVisibility last_visibility;
|
||||
absl::Time last_visibility_time;
|
||||
// Set to true if device is advertising under lock screen.
|
||||
bool screen_locked_advertising = false;
|
||||
};
|
||||
|
||||
PairedKeyVerificationRunner(
|
||||
@@ -85,10 +87,10 @@ class PairedKeyVerificationRunner
|
||||
void OnReadPairedKeyResultFrame(
|
||||
std::optional<nearby::sharing::service::proto::V1Frame> frame);
|
||||
void SendPairedKeyResultFrame(PairedKeyVerificationResult result);
|
||||
// Verifies auth token hash in frame using private certificate for visibility.
|
||||
// Returns either kSuccess or kUnable. This function never returns kFail.
|
||||
PairedKeyVerificationResult VerifyAuthTokenHashWithPrivateCertificate(
|
||||
proto::DeviceVisibility visibility,
|
||||
// Verifies auth token hash in frame using private certificates in
|
||||
// `visibility_history_`. Returns either kSuccess or kUnable. This function
|
||||
// never returns kFail.
|
||||
PairedKeyVerificationResult VerifyAuthTokenHashWithPrivateCertificates(
|
||||
const nearby::sharing::service::proto::V1Frame& frame);
|
||||
PairedKeyVerificationResult VerifyPairedKeyEncryptionFrame(
|
||||
const nearby::sharing::service::proto::V1Frame& frame);
|
||||
|
||||
@@ -126,9 +126,13 @@ GenerateVisibilityHistory() {
|
||||
DeviceVisibility::DEVICE_VISIBILITY_EVERYONE,
|
||||
};
|
||||
std::list<PairedKeyVerificationRunner::VisibilityHistory> result;
|
||||
for (DeviceVisibility visibility : kValidVisibilities) {
|
||||
for (DeviceVisibility last_visibility : kValidVisibilities) {
|
||||
result.push_back({visibility, last_visibility, absl::UnixEpoch()});
|
||||
for (bool screen_locked_advertising : {true, false}) {
|
||||
for (DeviceVisibility visibility : kValidVisibilities) {
|
||||
for (DeviceVisibility last_visibility : kValidVisibilities) {
|
||||
result.push_back(
|
||||
{visibility, last_visibility, absl::UnixEpoch(),
|
||||
screen_locked_advertising});
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -476,10 +480,12 @@ TEST_P(ParameterisedPairedKeyVerificationRunnerTest,
|
||||
std::get<2>(GetParam());
|
||||
PairedKeyVerificationRunner::PairedKeyVerificationResult result =
|
||||
params.result;
|
||||
// If our visibility has no certificates, then downgrade expected result to
|
||||
// kUnable if it is not expected to fail.
|
||||
// If our visibility has no certificates (i.e. EVERYONE and not under lock
|
||||
// screen), then downgrade expected result to kUnable if it is not expected to
|
||||
// fail.
|
||||
if ((visibility_history.visibility ==
|
||||
DeviceVisibility::DEVICE_VISIBILITY_EVERYONE) &&
|
||||
DeviceVisibility::DEVICE_VISIBILITY_EVERYONE &&
|
||||
!visibility_history.screen_locked_advertising) &&
|
||||
!(visibility_history.last_visibility !=
|
||||
DeviceVisibility::DEVICE_VISIBILITY_EVERYONE &&
|
||||
(params.encryption_frame_type ==
|
||||
@@ -511,7 +517,9 @@ TEST_P(ParameterisedPairedKeyVerificationRunnerTest,
|
||||
<< ", expected_result=" << (int)expected_result
|
||||
<< ", result_frame=" << (int)result_frame.status()
|
||||
<< ", visibility=" << (int)visibility_history.visibility
|
||||
<< ", last_visibility=" << (int)visibility_history.last_visibility;
|
||||
<< ", last_visibility=" << (int)visibility_history.last_visibility
|
||||
<< ", screen_locked_advertising="
|
||||
<< visibility_history.screen_locked_advertising;
|
||||
|
||||
SetUpPairedKeyEncryptionFrame(params.encryption_frame_type);
|
||||
bool encryption_frame_timeout =
|
||||
|
||||
+4
-1
@@ -42,7 +42,10 @@ proto_library(
|
||||
name = "wire_format_proto",
|
||||
srcs = ["wire_format.proto"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//proto:sharing_enums_proto"],
|
||||
deps = [
|
||||
"//google/protobuf:timestamp",
|
||||
"//proto:sharing_enums_proto",
|
||||
],
|
||||
)
|
||||
|
||||
cc_proto_library(
|
||||
|
||||
@@ -16,6 +16,8 @@ syntax = "proto2";
|
||||
|
||||
package nearby.sharing.service.proto;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
// import "storage/datapol/annotations/proto/semantic_annotations.proto";
|
||||
import "proto/sharing_enums.proto";
|
||||
|
||||
@@ -233,6 +235,7 @@ message IntroductionFrame {
|
||||
repeated StreamMetadata stream_metadata = 7;
|
||||
optional SharingUseCase use_case = 8;
|
||||
repeated int64 preview_payload_ids = 9;
|
||||
optional string transfer_id = 10;
|
||||
}
|
||||
|
||||
// A progress update packet sent by the sending side. Contains transfer progress
|
||||
@@ -265,6 +268,13 @@ message BindingRequest {
|
||||
}
|
||||
optional string binding_id = 1;
|
||||
optional Type type = 2;
|
||||
// A list of public cert ids that can be used to identify the sender.
|
||||
// If binding is successful, the receiver can add the binding ids to these
|
||||
// public certs to ensure that it can immediately identify the sender without
|
||||
// having to download public certs from the BE.
|
||||
// The sender does not need to provide all its future public certs, just the
|
||||
// current ones will be sufficient.
|
||||
repeated bytes cert_ids = 3;
|
||||
}
|
||||
|
||||
message BindingResponse {
|
||||
@@ -274,6 +284,10 @@ message BindingResponse {
|
||||
FAILURE = 2; // TODO: b/485307320 - Add more specific error codes.
|
||||
}
|
||||
optional Status status = 1;
|
||||
optional google.protobuf.Timestamp join_binding_time = 2;
|
||||
// A list of public cert ids that can be used to identify the receiver.
|
||||
// See the comment of cert_ids in BindingRequest for more details.
|
||||
repeated bytes cert_ids = 3;
|
||||
}
|
||||
|
||||
// A response packet sent by the receiving side. Accepts or rejects the list of
|
||||
|
||||
Reference in New Issue
Block a user