Set file save path on a per session basis.

PiperOrigin-RevId: 866512037
This commit is contained in:
Francis Tsui
2026-02-06 10:16:09 -08:00
committed by Copybara-Service
parent 23fe8106b8
commit 183fdacb03
18 changed files with 113 additions and 18 deletions
+5
View File
@@ -207,6 +207,11 @@ void Core::SetCustomSavePath(absl::string_view path, ResultCallback callback) {
router_->SetCustomSavePath(&client_, path, std::move(callback));
}
void Core::OverrideSavePath(absl::string_view endpoint_id,
absl::string_view path) {
client_.OverrideSavePath(endpoint_id, path);
}
std::string Core::Dump() { return client_.Dump(); }
// V3
+2 -2
View File
@@ -19,7 +19,6 @@
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
@@ -29,7 +28,6 @@
#include "connections/implementation/client_proxy.h"
#include "connections/implementation/service_controller_router.h"
#include "connections/listeners.h"
#include "connections/medium_selector.h"
#include "connections/out_of_band_connection_metadata.h"
#include "connections/params.h"
#include "connections/payload.h"
@@ -254,6 +252,8 @@ class Core {
//
// path - The path where the received files will be saved to.
void SetCustomSavePath(absl::string_view path, ResultCallback callback);
// Override the save path for payloads from a specific endpoint.
void OverrideSavePath(absl::string_view endpoint_id, absl::string_view path);
// Gets the local endpoint generated by Nearby Connections.
std::string GetLocalEndpointId() { return client_.GetLocalEndpointId(); }
@@ -196,6 +196,27 @@ std::string ClientProxy::GetConnectionToken(const std::string& endpoint_id) {
return {};
}
bool ClientProxy::OverrideSavePath(absl::string_view endpoint_id,
absl::string_view path) {
MutexLock lock(&mutex_);
ConnectionPair* item = LookupConnection(endpoint_id);
if (item != nullptr) {
item->first.save_path = path;
return true;
}
return false;
}
std::string ClientProxy::GetSavePath(
absl::string_view endpoint_id) const {
MutexLock lock(&mutex_);
const ConnectionPair* item = LookupConnection(endpoint_id);
if (item != nullptr) {
return item->first.save_path;
}
return "";
}
std::optional<MacAddress> ClientProxy::GetBluetoothMacAddress(
const std::string& endpoint_id) {
auto item = bluetooth_mac_addresses_.find(endpoint_id);
@@ -77,6 +77,13 @@ class ClientProxy final {
std::string GetLocalEndpointId();
std::string GetLocalEndpointInfo() { return local_endpoint_info_; }
// Override the base for received file attachments from a specific endpoint.
// Returns true if the endpoint is found and the path is overridden.
bool OverrideSavePath(absl::string_view endpoint_id, absl::string_view path);
// Get the save path for a specific endpoint. Returns empty string if
// not set.
std::string GetSavePath(absl::string_view endpoint_id) const;
analytics::AnalyticsRecorder& GetAnalyticsRecorder() const {
return *analytics_recorder_;
}
@@ -394,6 +401,7 @@ class ClientProxy final {
std::optional<location::nearby::connections::OsInfo> os_info;
std::int32_t safe_to_disconnect_version;
std::int32_t remote_multiplex_socket_bitmask;
std::string save_path;
};
using ConnectionPair = std::pair<Connection, PayloadListener>;
@@ -21,7 +21,6 @@
#include <utility>
#include <vector>
#include "base/casts.h"
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
@@ -65,6 +64,7 @@ using ::location::nearby::connections::OsInfo;
using ::location::nearby::proto::connections::CLIENT_SESSION;
using ::location::nearby::proto::connections::START_CLIENT_SESSION;
using ::location::nearby::proto::connections::STOP_CLIENT_SESSION;
using ::testing::IsEmpty;
using ::testing::MockFunction;
using ::testing::StrictMock;
@@ -1400,9 +1400,7 @@ TEST_F(ClientProxyTest, GetLocalDeviceWorksWithDeviceProvider) {
MockDeviceProvider provider;
client1()->RegisterDeviceProvider(&provider);
ASSERT_NE(client1()->GetLocalDeviceProvider(), nullptr);
EXPECT_CALL(*(absl::down_cast<MockDeviceProvider*>(
client1()->GetLocalDeviceProvider())),
GetLocalDevice);
EXPECT_CALL(provider, GetLocalDevice);
client1()->GetLocalDevice();
}
@@ -1612,6 +1610,23 @@ TEST_F(ClientProxyTest, NotLoadClientInfoFromPreferencesOnExpired) {
false);
}
TEST_F(ClientProxyTest, OverrideSavePath) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint);
client1()->OverrideSavePath(advertising_endpoint.id, "/tmp/test_path");
EXPECT_EQ(client1()->GetSavePath(advertising_endpoint.id), "/tmp/test_path");
}
TEST_F(ClientProxyTest, GetSavePathDefaultsToEmpty) {
Endpoint advertising_endpoint =
StartAdvertising(client1(), advertising_connection_listener_);
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint);
EXPECT_THAT(client1()->GetSavePath(advertising_endpoint.id), IsEmpty());
}
} // namespace
} // namespace connections
} // namespace nearby
@@ -792,9 +792,12 @@ PayloadTransferFrame::PayloadChunk PayloadManager::CreatePayloadChunk(
ErrorOr<PayloadManager::PendingPayloadHandle>
PayloadManager::CreateIncomingPayload(const PayloadTransferFrame& frame,
const std::string& endpoint_id) {
const std::string& endpoint_id,
const std::string& save_path) {
ErrorOr<std::unique_ptr<InternalPayload>> result =
CreateIncomingInternalPayload(frame, custom_save_path_);
CreateIncomingInternalPayload(frame, save_path.empty()
? custom_save_path_
: save_path);
if (result.has_error()) {
return {result.error()};
}
@@ -1340,7 +1343,8 @@ void PayloadManager::ProcessDataPacket(
});
ErrorOr<PendingPayloadHandle> result =
CreateIncomingPayload(payload_transfer_frame, from_endpoint_id);
CreateIncomingPayload(payload_transfer_frame, from_endpoint_id,
to_client->GetSavePath(from_endpoint_id));
if (result.has_error()) {
LOG(WARNING) << "PayloadManager failed to create InternalPayload from "
"PayloadTransferFrame with payload_id="
+5 -1
View File
@@ -323,9 +323,13 @@ class PayloadManager : public EndpointManager::FrameProcessor {
LAST_CHUNK) != 0);
}
// Creates an incoming payload and returns a handle to it.
// If `save_path` is empty, the payload will be saved to the default save
// path set in `SetCustomSavePath()`.
ErrorOr<PendingPayloadHandle> CreateIncomingPayload(
const location::nearby::connections::PayloadTransferFrame& frame,
const std::string& endpoint_id) ABSL_LOCKS_EXCLUDED(mutex_);
const std::string& endpoint_id,
const std::string& save_path) ABSL_LOCKS_EXCLUDED(mutex_);
Payload::Id CreateOutgoingPayload(Payload payload,
const EndpointIds& endpoint_ids)
@@ -311,11 +311,6 @@ void FakeNearbyConnectionsManager::HandleStopAdvertisingCallback(
capture_next_stop_advertising_callback_ = false;
}
void FakeNearbyConnectionsManager::SetCustomSavePath(
absl::string_view custom_save_path) {
custom_save_path_ = custom_save_path;
}
absl::flat_hash_set<FilePath>
FakeNearbyConnectionsManager::GetAndClearUnknownFilePathsToDelete() {
absl::flat_hash_set<FilePath> file_paths_to_delete = file_paths_to_delete_;
+3 -2
View File
@@ -74,7 +74,9 @@ class FakeNearbyConnectionsManager : public NearbyConnectionsManager {
std::optional<std::vector<uint8_t>> GetRawAuthenticationToken(
absl::string_view endpoint_id) override;
void UpgradeBandwidth(absl::string_view endpoint_id) override;
void SetCustomSavePath(absl::string_view custom_save_path) override;
void SetCustomSavePath(absl::string_view custom_save_path) override {}
void OverrideSavePath(absl::string_view endpoint_id,
const FilePath& custom_save_path) override {}
absl::flat_hash_set<FilePath> GetAndClearUnknownFilePathsToDelete() override;
// Testing methods
@@ -170,7 +172,6 @@ class FakeNearbyConnectionsManager : public NearbyConnectionsManager {
ConnectionsCallback pending_stop_advertising_callback_;
bool capture_next_start_advertising_callback_ = false;
ConnectionsCallback pending_start_advertising_callback_;
std::string custom_save_path_;
absl::Mutex endpoints_mutex_;
// Maps endpoint_id to endpoint_info.
@@ -111,6 +111,10 @@ class FakeNearbyConnectionsService : public NearbyConnectionsService {
std::function<void(Status status)> callback),
(override));
MOCK_METHOD(void, OverrideSavePath,
(absl::string_view endpoint_id, absl::string_view path),
(override));
MOCK_METHOD(std::string, Dump, (), (const, override));
};
+3
View File
@@ -156,6 +156,9 @@ class NearbyConnectionsManager {
// Sets a custom save path.
virtual void SetCustomSavePath(absl::string_view custom_save_path) = 0;
// Overrides the save path for transfers from a specific endpoint.
virtual void OverrideSavePath(absl::string_view endpoint_id,
const FilePath& custom_save_path) = 0;
// Gets the file paths to delete and clear the hash set.
virtual absl::flat_hash_set<FilePath>
@@ -972,6 +972,13 @@ void NearbyConnectionsManagerImpl::SetCustomSavePath(
});
}
void NearbyConnectionsManagerImpl::OverrideSavePath(
absl::string_view endpoint_id, const FilePath& custom_save_path) {
MutexLock lock(&mutex_);
nearby_connections_service_->OverrideSavePath(endpoint_id,
custom_save_path.ToString());
}
absl::flat_hash_set<FilePath>
NearbyConnectionsManagerImpl::GetUnknownFilePathsToDelete() {
MutexLock lock(&mutex_);
@@ -87,6 +87,8 @@ class NearbyConnectionsManagerImpl : public NearbyConnectionsManager {
absl::string_view endpoint_id) override;
void UpgradeBandwidth(absl::string_view endpoint_id) override;
void SetCustomSavePath(absl::string_view custom_save_path) override;
void OverrideSavePath(absl::string_view endpoint_id,
const FilePath& custom_save_path) override;
absl::flat_hash_set<FilePath> GetAndClearUnknownFilePathsToDelete() override;
std::string Dump() const override;
@@ -2050,5 +2050,13 @@ TEST_F(NearbyConnectionsManagerImplTest, ProcessUnknownFilePathsToDelete) {
nearby_connections_manager_->GetAndClearUnknownFilePathsToDelete();
}
TEST_F(NearbyConnectionsManagerImplTest, OverrideSavePath) {
EXPECT_CALL(*nearby_connections_,
OverrideSavePath(kRemoteEndpointId, "/tmp/test"));
nearby_connections_manager_->OverrideSavePath(kRemoteEndpointId,
FilePath("/tmp/test"));
}
} // namespace NearbyConnectionsManagerUnitTests
} // namespace nearby::sharing
+4
View File
@@ -137,6 +137,10 @@ class NearbyConnectionsService {
virtual void SetCustomSavePath(
absl::string_view path, std::function<void(Status status)> callback) = 0;
// Overrides the save path for transfers from a specific endpoint.
virtual void OverrideSavePath(absl::string_view endpoint_id,
absl::string_view path) = 0;
virtual std::string Dump() const = 0;
};
@@ -381,6 +381,11 @@ void NearbyConnectionsServiceImpl::SetCustomSavePath(
->SetCustomSavePath(path, BuildResultCallback(callback));
}
void NearbyConnectionsServiceImpl::OverrideSavePath(
absl::string_view endpoint_id, absl::string_view path) {
GetService(service_handle_)->OverrideSavePath(endpoint_id, path);
}
std::string NearbyConnectionsServiceImpl::Dump() const {
return GetService(service_handle_)->Dump();
}
@@ -90,6 +90,9 @@ class NearbyConnectionsServiceImpl : public NearbyConnectionsService {
void SetCustomSavePath(absl::string_view path,
std::function<void(Status status)> callback) override;
void OverrideSavePath(absl::string_view endpoint_id,
absl::string_view path) override;
std::string Dump() const override;
private:
+7 -1
View File
@@ -2520,13 +2520,19 @@ void NearbySharingServiceImpl::OnReceivedIntroduction(
Fail(*session, *status);
return;
}
FilePath save_path{settings_->GetCustomSavePath()};
// Override save path for this connection.
// This must be called before the transfer is accepted and payloads are being
// received.
nearby_connections_manager_->OverrideSavePath(session->endpoint_id(),
save_path);
// Log analytics event of receiving introduction.
analytics_recorder_.NewReceiveIntroduction(
session->session_id(), session->share_target(),
/*referrer_package=*/std::nullopt, session->os_type());
if (IsOutOfStorage(device_info_, FilePath{settings_->GetCustomSavePath()},
if (IsOutOfStorage(device_info_, save_path,
session->attachment_container().GetStorageSize())) {
Fail(*session, TransferMetadata::Status::kNotEnoughSpace);
LOG(WARNING) << __func__