Commit ece426d2 authored by Himanshu Jaju's avatar Himanshu Jaju Committed by Commit Bot

Accept share request in NearbySharingServiceImpl

- Implements the accept flow for a share request.
Todo - PayloadStatusTracker

Bug: 1085068
Change-Id: Ife793c110e39995d5484ae5edbd34103b64e69ad
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2332273
Commit-Queue: Himanshu Jaju <himanshujaju@chromium.org>
Reviewed-by: default avatarAlex Chau <alexchau@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795857}
parent db3d344f
......@@ -105,6 +105,12 @@ FakeNearbyConnectionsManager::GetRawAuthenticationToken(
return base::nullopt;
}
void FakeNearbyConnectionsManager::UpgradeBandwidth(
const std::string& endpoint_id) {
// TODO(alexchau): Implement.
upgrade_bandwidth_endpoint_ids_.insert(endpoint_id);
}
bool FakeNearbyConnectionsManager::IsAdvertising() {
return advertising_listener_ != nullptr;
}
......@@ -124,3 +130,8 @@ DataUsage FakeNearbyConnectionsManager::GetAdvertisingDataUsage() {
PowerLevel FakeNearbyConnectionsManager::GetAdvertisingPowerLevel() {
return advertising_power_level_;
}
bool FakeNearbyConnectionsManager::DidUpgradeBandwidth(
const std::string& endpoint_id) {
return (upgrade_bandwidth_endpoint_ids_.count(endpoint_id) > 0);
}
......@@ -6,6 +6,7 @@
#define CHROME_BROWSER_NEARBY_SHARING_FAKE_NEARBY_CONNECTIONS_MANAGER_H_
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
......@@ -47,6 +48,7 @@ class FakeNearbyConnectionsManager : public NearbyConnectionsManager {
void ClearIncomingPayloads() override;
base::Optional<std::vector<uint8_t>> GetRawAuthenticationToken(
const std::string& endpoint_id) override;
void UpgradeBandwidth(const std::string& endpoint_id) override;
// Testing methods
bool IsAdvertising();
......@@ -54,6 +56,7 @@ class FakeNearbyConnectionsManager : public NearbyConnectionsManager {
bool IsShutdown();
DataUsage GetAdvertisingDataUsage();
PowerLevel GetAdvertisingPowerLevel();
bool DidUpgradeBandwidth(const std::string& endpoint_id);
private:
IncomingConnectionListener* advertising_listener_ = nullptr;
......@@ -61,6 +64,7 @@ class FakeNearbyConnectionsManager : public NearbyConnectionsManager {
bool is_shutdown_ = false;
DataUsage advertising_data_usage_ = DataUsage::kUnknown;
PowerLevel advertising_power_level_ = PowerLevel::kUnknown;
std::set<std::string> upgrade_bandwidth_endpoint_ids_;
};
#endif // CHROME_BROWSER_NEARBY_SHARING_FAKE_NEARBY_CONNECTIONS_MANAGER_H_
......@@ -53,7 +53,7 @@ class IncomingShareTargetInfo {
private:
base::Optional<std::string> endpoint_id_;
base::Optional<NearbyShareDecryptedPublicCertificate> certificate_;
NearbyConnection* connection_;
NearbyConnection* connection_ = nullptr;
base::Optional<std::string> token_;
};
......
......@@ -124,6 +124,9 @@ class NearbyConnectionsManager {
// Gets the raw authentication token for the |endpoint_id|.
virtual base::Optional<std::vector<uint8_t>> GetRawAuthenticationToken(
const std::string& endpoint_id) = 0;
// Initiates bandwidth upgrade for |endpoint_id|.
virtual void UpgradeBandwidth(const std::string& endpoint_id) = 0;
};
#endif // CHROME_BROWSER_NEARBY_SHARING_NEARBY_CONNECTIONS_MANAGER_H_
......@@ -178,6 +178,11 @@ NearbyConnectionsManagerImpl::GetRawAuthenticationToken(
return it->second->raw_authentication_token;
}
void NearbyConnectionsManagerImpl::UpgradeBandwidth(
const std::string& endpoint_id) {
// TODO(crbug/1076008): Implement.
}
void NearbyConnectionsManagerImpl::OnNearbyProfileChanged(Profile* profile) {
NS_LOG(VERBOSE) << __func__;
}
......
......@@ -60,6 +60,7 @@ class NearbyConnectionsManagerImpl
void ClearIncomingPayloads() override;
base::Optional<std::vector<uint8_t>> GetRawAuthenticationToken(
const std::string& endpoint_id) override;
void UpgradeBandwidth(const std::string& endpoint_id) override;
private:
using DiscoveryOptions =
......
......@@ -109,6 +109,10 @@ TEST_F(NearbyPerSessionDiscoveryManagerTest, StartDiscovery_Error) {
TEST_F(NearbyPerSessionDiscoveryManagerTest, OnShareTargetDiscovered) {
MockShareTargetListener listener;
EXPECT_CALL(sharing_service(),
RegisterSendSurface(testing::_, testing::_, testing::_))
.WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target;
......@@ -124,6 +128,10 @@ TEST_F(NearbyPerSessionDiscoveryManagerTest, OnShareTargetDiscovered) {
TEST_F(NearbyPerSessionDiscoveryManagerTest, OnShareTargetLost) {
MockShareTargetListener listener;
EXPECT_CALL(sharing_service(),
RegisterSendSurface(testing::_, testing::_, testing::_))
.WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target;
......@@ -150,6 +158,10 @@ TEST_F(NearbyPerSessionDiscoveryManagerTest, SelectShareTarget_Invalid) {
TEST_F(NearbyPerSessionDiscoveryManagerTest, SelectShareTarget_SendSuccess) {
// Setup share target
MockShareTargetListener listener;
EXPECT_CALL(sharing_service(),
RegisterSendSurface(testing::_, testing::_, testing::_))
.WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target;
manager().OnShareTargetDiscovered(share_target);
......@@ -173,6 +185,10 @@ TEST_F(NearbyPerSessionDiscoveryManagerTest, SelectShareTarget_SendSuccess) {
TEST_F(NearbyPerSessionDiscoveryManagerTest, SelectShareTarget_SendError) {
// Setup share target
MockShareTargetListener listener;
EXPECT_CALL(sharing_service(),
RegisterSendSurface(testing::_, testing::_, testing::_))
.WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target;
manager().OnShareTargetDiscovered(share_target);
......@@ -198,6 +214,10 @@ TEST_F(NearbyPerSessionDiscoveryManagerTest, SelectShareTarget_SendError) {
TEST_F(NearbyPerSessionDiscoveryManagerTest, OnTransferUpdate_WaitRemote) {
// Setup share target
MockShareTargetListener listener;
EXPECT_CALL(sharing_service(),
RegisterSendSurface(testing::_, testing::_, testing::_))
.WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target;
manager().OnShareTargetDiscovered(share_target);
......@@ -219,6 +239,10 @@ TEST_F(NearbyPerSessionDiscoveryManagerTest, OnTransferUpdate_WaitRemote) {
TEST_F(NearbyPerSessionDiscoveryManagerTest, OnTransferUpdate_WaitLocal) {
// Setup share target
MockShareTargetListener listener;
EXPECT_CALL(sharing_service(),
RegisterSendSurface(testing::_, testing::_, testing::_))
.WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target;
manager().OnShareTargetDiscovered(share_target);
......
......@@ -27,10 +27,12 @@ class NearbyShareLocalDeviceDataManager;
class NearbySharingService : public KeyedService {
public:
enum class StatusCodes {
// The operation was successful.
kOk,
// The operation failed, without any more information.
kError,
// The operation was successful.
kOk,
// The operation failed since it was called in an invalid order.
kOutOfOrderApiCall,
};
enum class ReceiveSurfaceState {
......
......@@ -292,7 +292,19 @@ void NearbySharingServiceImpl::SendFiles(
void NearbySharingServiceImpl::Accept(
const ShareTarget& share_target,
StatusCodesCallback status_codes_callback) {
std::move(status_codes_callback).Run(StatusCodes::kOk);
base::Optional<std::pair<ShareTarget, TransferMetadata>> metadata =
share_target.is_incoming ? last_incoming_metadata_
: last_outgoing_metadata_;
if (!metadata || metadata->second.status() !=
TransferMetadata::Status::kAwaitingLocalConfirmation) {
std::move(status_codes_callback).Run(StatusCodes::kOutOfOrderApiCall);
return;
}
StatusCodes status_code = share_target.is_incoming
? ReceivePayloads(share_target)
: SendPayloads(share_target);
std::move(status_codes_callback).Run(status_code);
}
void NearbySharingServiceImpl::Reject(
......@@ -350,6 +362,7 @@ void NearbySharingServiceImpl::OnIncomingConnection(
share_target.is_incoming = true;
incoming_share_target_info_map_[share_target.id].set_connection(connection);
incoming_share_target_info_map_[share_target.id].set_endpoint_id(endpoint_id);
connection->RegisterForDisconnection(
base::BindOnce(&NearbySharingServiceImpl::UnregisterShareTarget,
weak_ptr_factory_.GetWeakPtr(), share_target));
......@@ -708,6 +721,68 @@ void NearbySharingServiceImpl::OnIncomingTransferUpdate(
}
}
NearbySharingService::StatusCodes NearbySharingServiceImpl::ReceivePayloads(
const ShareTarget& share_target) {
mutual_acceptance_timeout_alarm_.Cancel();
NearbyConnection* connection = GetIncomingConnection(share_target);
if (!connection) {
NS_LOG(WARNING) << __func__ << ": Accept invoked for unknown share target";
return StatusCodes::kOutOfOrderApiCall;
}
// TODO(himanshujaju) - Implement payload tracker.
for (const auto& attachment_id : share_target.GetAttachmentIds()) {
base::Optional<int64_t> payload_id = GetAttachmentPayloadId(attachment_id);
if (!payload_id) {
NS_LOG(WARNING) << __func__
<< ": Failed to retrieve payload for attachment id - "
<< attachment_id;
continue;
}
NS_LOG(VERBOSE) << __func__
<< ": Started listening for progress on payload - "
<< *payload_id;
// TODO(himanshujaju) - Register payload listener.
NS_LOG(VERBOSE) << __func__
<< ": Accepted incoming files from share target - "
<< share_target.device_name;
}
WriteResponse(*connection, sharing::nearby::ConnectionResponseFrame::ACCEPT);
NS_LOG(VERBOSE) << __func__ << ": Successfully wrote response frame";
OnIncomingTransferUpdate(
share_target,
TransferMetadataBuilder()
.set_status(TransferMetadata::Status::kAwaitingRemoteAcceptance)
.set_token(GetIncomingShareTargetInfo(share_target).token())
.build());
base::Optional<std::string> endpoint_id =
GetIncomingShareTargetInfo(share_target).endpoint_id();
if (endpoint_id) {
nearby_connections_manager_->UpgradeBandwidth(*endpoint_id);
} else {
NS_LOG(WARNING) << __func__
<< ": Failed to initiate bandwidth upgrade. No endpoint_id "
"found for target - "
<< share_target.device_name;
return StatusCodes::kOutOfOrderApiCall;
}
return StatusCodes::kOk;
}
NearbySharingService::StatusCodes NearbySharingServiceImpl::SendPayloads(
const ShareTarget& share_target) {
// TODO(crbug.com/1085067) - Implement.
return StatusCodes::kOk;
}
void NearbySharingServiceImpl::WriteResponse(
NearbyConnection& connection,
sharing::nearby::ConnectionResponseFrame::Status status) {
......@@ -1000,3 +1075,12 @@ void NearbySharingServiceImpl::SetAttachmentPayloadId(
int64_t payload_id) {
attachment_info_map_[attachment.id()].payload_id = payload_id;
}
base::Optional<int64_t> NearbySharingServiceImpl::GetAttachmentPayloadId(
const base::UnguessableToken& attachment_id) {
auto it = attachment_info_map_.find(attachment_id);
if (it == attachment_info_map_.end())
return base::nullopt;
return it->second.payload_id;
}
......@@ -135,6 +135,10 @@ class NearbySharingServiceImpl
void InvalidateReceiveSurfaceState();
void InvalidateAdvertisingState();
void StopAdvertising();
StatusCodes ReceivePayloads(const ShareTarget& share_target);
StatusCodes SendPayloads(const ShareTarget& share_target);
void WriteResponse(
NearbyConnection& connection,
sharing::nearby::ConnectionResponseFrame::Status reponse_status);
......@@ -167,6 +171,8 @@ class NearbySharingServiceImpl
const ShareTarget& share_target);
void ClearOutgoingShareTargetInfoMap();
void SetAttachmentPayloadId(const Attachment& attachment, int64_t payload_id);
base::Optional<int64_t> GetAttachmentPayloadId(
const base::UnguessableToken& attachment_id);
PrefService* prefs_;
Profile* profile_;
......
......@@ -141,6 +141,27 @@ class MockTransferUpdateCallback : public TransferUpdateCallback {
namespace {
const char kEndpointId[] = "endpoint_id";
sharing::mojom::FramePtr GetValidIntroductionFrame() {
std::vector<sharing::mojom::TextMetadataPtr> mojo_text_metadatas;
for (int i = 1; i <= 3; i++) {
mojo_text_metadatas.push_back(sharing::mojom::TextMetadata::New(
"title " + base::NumberToString(i),
static_cast<sharing::mojom::TextMetadata::Type>(i), i, i, i));
}
sharing::mojom::V1FramePtr mojo_v1frame = sharing::mojom::V1Frame::New();
mojo_v1frame->set_introduction(sharing::mojom::IntroductionFrame::New(
std::vector<sharing::mojom::FileMetadataPtr>(),
std::move(mojo_text_metadatas), base::nullopt,
std::vector<sharing::mojom::WifiCredentialsMetadataPtr>()));
sharing::mojom::FramePtr mojo_frame = sharing::mojom::Frame::New();
mojo_frame->set_v1(std::move(mojo_v1frame));
return mojo_frame;
}
class NearbySharingServiceImplTest : public testing::Test {
public:
NearbySharingServiceImplTest() {
......@@ -768,7 +789,7 @@ TEST_F(NearbySharingServiceImplTest,
EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk);
EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising());
service_->OnIncomingConnection("endpoint_id", {}, &connection);
service_->OnIncomingConnection(kEndpointId, {}, &connection);
run_loop.Run();
// To avoid UAF in OnIncomingTransferUpdate().
......@@ -784,31 +805,71 @@ TEST_F(NearbySharingServiceImplTest,
.WillOnce(testing::Invoke(
[&](const std::vector<uint8_t>& data,
MockNearbySharingDecoder::DecodeFrameCallback callback) {
// TODO(himanshujaju) - Write helper functions for these.
std::vector<sharing::mojom::TextMetadataPtr> mojo_text_metadatas;
for (int i = 1; i <= 3; i++) {
mojo_text_metadatas.push_back(sharing::mojom::TextMetadata::New(
"title " + base::NumberToString(i),
static_cast<sharing::mojom::TextMetadata::Type>(i), i, i, i));
}
std::move(callback).Run(GetValidIntroductionFrame());
}));
sharing::mojom::V1FramePtr mojo_v1frame =
sharing::mojom::V1Frame::New();
mojo_v1frame->set_introduction(
sharing::mojom::IntroductionFrame::New(
std::vector<sharing::mojom::FileMetadataPtr>(),
std::move(mojo_text_metadatas), base::nullopt,
std::vector<sharing::mojom::WifiCredentialsMetadataPtr>()));
EXPECT_CALL(mock_nearby_process_manager(),
GetOrStartNearbySharingDecoder(testing::_))
.WillRepeatedly(testing::Return(&mock_decoder));
sharing::mojom::FramePtr mojo_frame = sharing::mojom::Frame::New();
mojo_frame->set_v1(std::move(mojo_v1frame));
std::move(callback).Run(std::move(mojo_frame));
FakeNearbyConnection connection;
connection.AppendReadableData(bytes);
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
NiceMock<MockTransferUpdateCallback> callback;
base::RunLoop run_loop;
EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_))
.WillOnce(testing::Invoke([&run_loop](const ShareTarget& share_target,
TransferMetadata metadata) {
EXPECT_EQ(TransferMetadata::Status::kAwaitingLocalConfirmation,
metadata.status());
run_loop.Quit();
}));
NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface(
&callback, NearbySharingService::ReceiveSurfaceState::kForeground);
EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk);
EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising());
service_->OnIncomingConnection(kEndpointId, {}, &connection);
run_loop.Run();
// To avoid UAF in OnIncomingTransferUpdate().
service_->UnregisterReceiveSurface(&callback);
}
TEST_F(NearbySharingServiceImplTest, AcceptInvalidShareTarget) {
ShareTarget share_target;
base::RunLoop run_loop;
service_->Accept(
share_target,
base::BindLambdaForTesting(
[&](NearbySharingServiceImpl::StatusCodes status_code) {
EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOutOfOrderApiCall,
status_code);
run_loop.Quit();
}));
run_loop.Run();
}
TEST_F(NearbySharingServiceImplTest, AcceptValidShareTarget) {
// TODO(himanshujaju) - Refactor common set up.
std::string intro = "introduction_frame";
std::vector<uint8_t> bytes(intro.begin(), intro.end());
NiceMock<MockNearbySharingDecoder> mock_decoder;
EXPECT_CALL(mock_decoder, DecodeFrame(testing::Eq(bytes), testing::_))
.WillOnce(testing::Invoke(
[&](const std::vector<uint8_t>& data,
MockNearbySharingDecoder::DecodeFrameCallback callback) {
std::move(callback).Run(GetValidIntroductionFrame());
}));
EXPECT_CALL(mock_nearby_process_manager(),
GetOrStartNearbySharingDecoder(testing::_))
.WillRepeatedly(testing::Return(&mock_decoder));
ShareTarget share_target;
FakeNearbyConnection connection;
connection.AppendReadableData(bytes);
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
......@@ -816,10 +877,11 @@ TEST_F(NearbySharingServiceImplTest,
NiceMock<MockTransferUpdateCallback> callback;
base::RunLoop run_loop;
EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_))
.WillOnce(testing::Invoke([&run_loop](const ShareTarget& share_target,
.WillOnce(testing::Invoke([&](const ShareTarget& incoming_share_target,
TransferMetadata metadata) {
EXPECT_EQ(TransferMetadata::Status::kAwaitingLocalConfirmation,
metadata.status());
share_target = incoming_share_target;
run_loop.Quit();
}));
......@@ -828,9 +890,30 @@ TEST_F(NearbySharingServiceImplTest,
EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk);
EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising());
service_->OnIncomingConnection("endpoint_id", {}, &connection);
service_->OnIncomingConnection(kEndpointId, {}, &connection);
run_loop.Run();
base::RunLoop run_loop_accept;
EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_))
.WillOnce(testing::Invoke(
[](const ShareTarget& share_target, TransferMetadata metadata) {
EXPECT_EQ(TransferMetadata::Status::kAwaitingRemoteAcceptance,
metadata.status());
}));
service_->Accept(share_target,
base::BindLambdaForTesting(
[&](NearbySharingServiceImpl::StatusCodes status_code) {
EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
status_code);
run_loop_accept.Quit();
}));
run_loop_accept.Run();
EXPECT_TRUE(
fake_nearby_connections_manager_->DidUpgradeBandwidth(kEndpointId));
// To avoid UAF in OnIncomingTransferUpdate().
service_->UnregisterReceiveSurface(&callback);
}
......@@ -66,10 +66,10 @@ class OutgoingShareTargetInfo {
private:
base::Optional<std::string> endpoint_id_;
base::Optional<NearbyShareDecryptedPublicCertificate> certificate_;
NearbyConnection* connection_;
NearbyConnection* connection_ = nullptr;
base::Optional<std::string> obfuscated_gaia_id_;
base::Optional<std::string> token_;
bool is_connected_;
bool is_connected_ = false;
};
#endif // CHROME_BROWSER_NEARBY_SHARING_OUTGOING_SHARE_TARGET_INFO_H_
......@@ -34,3 +34,15 @@ ShareTarget& ShareTarget::operator=(const ShareTarget&) = default;
ShareTarget& ShareTarget::operator=(ShareTarget&&) = default;
ShareTarget::~ShareTarget() = default;
std::vector<base::UnguessableToken> ShareTarget::GetAttachmentIds() const {
std::vector<base::UnguessableToken> attachments;
for (const auto& file : file_attachments)
attachments.push_back(file.id());
for (const auto& text : text_attachments)
attachments.push_back(text.id());
return attachments;
}
......@@ -37,6 +37,8 @@ struct ShareTarget {
return !text_attachments.empty() || !file_attachments.empty();
}
std::vector<base::UnguessableToken> GetAttachmentIds() const;
base::UnguessableToken id = base::UnguessableToken::Create();
std::string device_name;
// Uri that points to an image of the ShareTarget, if one exists.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment