Skip to content

Commit

Permalink
[Nearby Presence] Add public credentials to SaveCredentials.
Browse files Browse the repository at this point in the history
Added SharedCredential to the SaveCredentials interface, allowing
public credentials to be saved to the appropriate database. Also
added logic to save to the correct database depending on the
PublicCredentialType parameter.

SaveCredentials does not attempt to save private credentials
when PublicCredentialType is set to kRemotePublicCredential.
The library provides an empty array of LocalCredentials when
updating remote shared credentials; to prevent overriding the
existing local credentials, a remote public save skips private
credential save.

CredentialStorage is hosted inside of a sandboxed utility process,
and calls upon NearbyPresenceCredentialStorage in the browser
process to persist credentials generated by the Nearby Presence
library to storage.  A full design is given at
go/cros-nearby-presence-credential-storage.

Test: Unit tests
Bug: b:287334195
Change-Id: I87858d6f05f5e19af0e0f0fe4a92406b17271d22
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4797847
Reviewed-by: Juliet Lévesque <julietlevesque@google.com>
Commit-Queue: Mark Polner <polner@google.com>
Reviewed-by: Nasko Oskov <nasko@chromium.org>
Reviewed-by: Ryan Hansberry <hansberry@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1209142}
  • Loading branch information
markwhosthat authored and Chromium LUCI CQ committed Oct 12, 2023
1 parent ee8fb35 commit 41036db
Show file tree
Hide file tree
Showing 7 changed files with 593 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "chrome/browser/ash/nearby/presence/credential_storage/nearby_presence_credential_storage.h"

#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
Expand All @@ -21,6 +22,15 @@ const base::FilePath::CharType kRemotePublicCredentialDatabaseName[] =
const base::FilePath::CharType kPrivateCredentialDatabaseName[] =
FILE_PATH_LITERAL("NearbyPresencePrivateCredentialDatabase");

// When saving credentials, |delete_key_filter| is always set to true, since
// |entries_to_save| are not deleted if they match |delete_key_filter|. This
// avoids duplicating new keys in memory to be saved.
const leveldb_proto::KeyFilter& DeleteKeyFilter() {
static const base::NoDestructor<leveldb_proto::KeyFilter> filter(
base::BindRepeating([](const std::string& key) { return true; }));
return *filter;
}

} // namespace

namespace ash::nearby::presence {
Expand Down Expand Up @@ -90,7 +100,66 @@ void NearbyPresenceCredentialStorage::Initialize(

void NearbyPresenceCredentialStorage::SaveCredentials(
std::vector<mojom::LocalCredentialPtr> local_credentials,
SaveCredentialsCallback on_save_credential_callback) {
std::vector<mojom::SharedCredentialPtr> shared_credentials,
mojom::PublicCredentialType public_credential_type,
SaveCredentialsCallback on_credentials_fully_saved_callback) {
CHECK(on_credentials_fully_saved_callback);

auto credential_pairs_to_save = std::make_unique<std::vector<
std::pair<std::string, ::nearby::internal::SharedCredential>>>();
for (const auto& shared_credential : shared_credentials) {
auto shared_credential_proto =
proto::SharedCredentialFromMojom(shared_credential.get());

credential_pairs_to_save->emplace_back(std::make_pair(
shared_credential_proto.secret_id(), shared_credential_proto));
}

switch (public_credential_type) {
case (mojom::PublicCredentialType::kLocalPublicCredential):
// In the chain of callbacks, attempt to first save public credentials.
// If successful, then attempt to save private credentials in a
// follow-up callback. Iff both operations are successful,
// 'on_credentials_fully_saved_callback' will return kOk.
local_public_db_->UpdateEntriesWithRemoveFilter(
/*entries_to_save=*/std::move(credential_pairs_to_save),
/*delete_key_filter=*/DeleteKeyFilter(),
base::BindOnce(
&NearbyPresenceCredentialStorage::OnLocalPublicCredentialsSaved,
weak_ptr_factory_.GetWeakPtr(), std::move(local_credentials),
std::move(on_credentials_fully_saved_callback)));
break;
case (mojom::PublicCredentialType::kRemotePublicCredential):
// When remote public credentials are updated, the private credentials
// provided are empty. To preserve the existing private credentials, do
// not update the private credential database.
remote_public_db_->UpdateEntriesWithRemoveFilter(
/*entries_to_save=*/std::move(credential_pairs_to_save),
/*delete_key_filter=*/DeleteKeyFilter(),
base::BindOnce(
&NearbyPresenceCredentialStorage::OnRemotePublicCredentialsSaved,
weak_ptr_factory_.GetWeakPtr(),
std::move(on_credentials_fully_saved_callback)));
break;
}
}

void NearbyPresenceCredentialStorage::OnLocalPublicCredentialsSaved(
std::vector<mojom::LocalCredentialPtr> local_credentials,
SaveCredentialsCallback on_credentials_fully_saved_callback,
bool success) {
CHECK(on_credentials_fully_saved_callback);

// If local public credentials failed to save, skip saving the
// private credentials.
if (!success) {
// TODO(b/287334363): Emit a failure metric.
LOG(ERROR) << __func__ << ": failed to save local public credentials";
std::move(on_credentials_fully_saved_callback)
.Run(mojo_base::mojom::AbslStatusCode::kAborted);
return;
}

std::vector<::nearby::internal::LocalCredential> proto_local_credentials;
for (const auto& local_credential : local_credentials) {
proto_local_credentials.push_back(
Expand All @@ -104,35 +173,45 @@ void NearbyPresenceCredentialStorage::SaveCredentials(
std::make_pair(local_credential.secret_id(), local_credential));
}

// |delete_key_filter| is always set to true, since |entries_to_save| are not
// deleted if they match |delete_key_filter|. This avoids duplicating new keys
// in memory to be saved.
const leveldb_proto::KeyFilter clearAllFilter =
base::BindRepeating([](const std::string& key) { return true; });

private_db_->UpdateEntriesWithRemoveFilter(
std::move(credential_pairs_to_save), clearAllFilter,
/*entries_to_save=*/std::move(credential_pairs_to_save),
/*delete_key_filter=*/DeleteKeyFilter(),
base::BindOnce(
&NearbyPresenceCredentialStorage::OnPrivateCredentialsSaved,
weak_ptr_factory_.GetWeakPtr(),
std::move(on_save_credential_callback)));
std::move(on_credentials_fully_saved_callback)));
}

void NearbyPresenceCredentialStorage::OnRemotePublicCredentialsSaved(
SaveCredentialsCallback on_credentials_fully_saved_callback,
bool success) {
mojo_base::mojom::AbslStatusCode save_status;
if (success) {
save_status = mojo_base::mojom::AbslStatusCode::kOk;
} else {
// TODO(b/287334363): Emit failure metric for remote public credential save.
LOG(ERROR) << __func__ << ": failed to save remote public credentials";
save_status = mojo_base::mojom::AbslStatusCode::kAborted;
}

CHECK(on_credentials_fully_saved_callback);
std::move(on_credentials_fully_saved_callback).Run(save_status);
}

void NearbyPresenceCredentialStorage::OnPrivateCredentialsSaved(
SaveCredentialsCallback on_save_credential_callback,
SaveCredentialsCallback on_credentials_fully_saved_callback,
bool success) {
mojo_base::mojom::AbslStatusCode save_status;
if (success) {
save_status = mojo_base::mojom::AbslStatusCode::kOk;
} else {
// TODO(b/287334363): Emit a failure metric.
LOG(ERROR) << __func__ << ": failed to save private credentials";
save_status = mojo_base::mojom::AbslStatusCode::kUnknown;
save_status = mojo_base::mojom::AbslStatusCode::kAborted;
}

// TODO(b/287334195): Attempt to save public credentials if private
// credentials were successfully saved.
std::move(on_save_credential_callback).Run(save_status);
CHECK(on_credentials_fully_saved_callback);
std::move(on_credentials_fully_saved_callback).Run(save_status);
}

void NearbyPresenceCredentialStorage::OnPrivateDatabaseInitialized(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ class NearbyPresenceCredentialStorage
void Initialize(base::OnceCallback<void(bool)> on_initialized);

// NearbyPresenceCredentialStorage:
void SaveCredentials(std::vector<mojom::LocalCredentialPtr> local_credentials,
SaveCredentialsCallback callback) override;
void SaveCredentials(
std::vector<mojom::LocalCredentialPtr> local_credentials,
std::vector<mojom::SharedCredentialPtr> shared_credentials,
mojom::PublicCredentialType public_credential_type,
SaveCredentialsCallback on_credentials_fully_saved_callback) override;

protected:
NearbyPresenceCredentialStorage(
Expand All @@ -58,8 +61,15 @@ class NearbyPresenceCredentialStorage
remote_public_db);

private:
void OnLocalPublicCredentialsSaved(
std::vector<mojom::LocalCredentialPtr> local_credentials,
SaveCredentialsCallback on_credentials_fully_saved_callback,
bool success);
void OnRemotePublicCredentialsSaved(
SaveCredentialsCallback on_credentials_fully_saved_callback,
bool success);
void OnPrivateCredentialsSaved(
SaveCredentialsCallback on_save_credential_callback,
SaveCredentialsCallback on_credentials_fully_saved_callback,
bool success);

void OnPrivateDatabaseInitialized(
Expand Down

0 comments on commit 41036db

Please sign in to comment.