Commit 9e8a82fb authored by Alex Chau's avatar Alex Chau Committed by Commit Bot

Implement start/stop discovery in NearbyConnections and NearbyConnectionsManager

- Start Sharing process at start discovery/adveritisng
- Changed NearbyProcessManager::GetInstance to return pointer for easy
  injection in testing

Bug: 1076008
Change-Id: I33f8d5147b30c4f9e22e778991c17b2c2c3be49d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2308149Reviewed-by: default avatarAlex Gough <ajgo@chromium.org>
Reviewed-by: default avatarRichard Knoll <knollr@chromium.org>
Commit-Queue: Alex Chau <alexchau@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792049}
parent cba87606
...@@ -67,7 +67,6 @@ void FakeNearbyConnectionsManager::StopAdvertising() { ...@@ -67,7 +67,6 @@ void FakeNearbyConnectionsManager::StopAdvertising() {
} }
void FakeNearbyConnectionsManager::StartDiscovery( void FakeNearbyConnectionsManager::StartDiscovery(
std::vector<uint8_t> endpoint_info,
DiscoveryListener* listener, DiscoveryListener* listener,
ConnectionsCallback callback) { ConnectionsCallback callback) {
is_shutdown_ = false; is_shutdown_ = false;
......
...@@ -43,8 +43,7 @@ class FakeNearbyConnectionsManager : public NearbyConnectionsManager { ...@@ -43,8 +43,7 @@ class FakeNearbyConnectionsManager : public NearbyConnectionsManager {
DataUsage data_usage, DataUsage data_usage,
ConnectionsCallback callback) override; ConnectionsCallback callback) override;
void StopAdvertising() override; void StopAdvertising() override;
void StartDiscovery(std::vector<uint8_t> endpoint_info, void StartDiscovery(DiscoveryListener* listener,
DiscoveryListener* listener,
ConnectionsCallback callback) override; ConnectionsCallback callback) override;
void StopDiscovery() override; void StopDiscovery() override;
std::unique_ptr<NearbyConnection> Connect( std::unique_ptr<NearbyConnection> Connect(
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/nearby_sharing/mock_nearby_connections.h"
MockNearbyConnections::MockNearbyConnections() = default;
MockNearbyConnections::~MockNearbyConnections() = default;
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_NEARBY_SHARING_MOCK_NEARBY_CONNECTIONS_H_
#define CHROME_BROWSER_NEARBY_SHARING_MOCK_NEARBY_CONNECTIONS_H_
#include "chrome/services/sharing/public/mojom/nearby_connections.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
using NearbyConnectionsMojom =
location::nearby::connections::mojom::NearbyConnections;
using DiscoveryOptionsPtr =
location::nearby::connections::mojom::DiscoveryOptionsPtr;
using EndpointDiscoveryListener =
location::nearby::connections::mojom::EndpointDiscoveryListener;
class MockNearbyConnections : public NearbyConnectionsMojom {
public:
MockNearbyConnections();
MockNearbyConnections(const MockNearbyConnections&) = delete;
MockNearbyConnections& operator=(const MockNearbyConnections&) = delete;
~MockNearbyConnections() override;
MOCK_METHOD(void,
StartDiscovery,
(const std::string& service_id,
DiscoveryOptionsPtr,
mojo::PendingRemote<EndpointDiscoveryListener>,
StartDiscoveryCallback callback),
(override));
MOCK_METHOD(void,
StopDiscovery,
(StopDiscoveryCallback callback),
(override));
};
#endif // CHROME_BROWSER_NEARBY_SHARING_MOCK_NEARBY_CONNECTIONS_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/nearby_sharing/mock_nearby_process_manager.h"
MockNearbyProcessManager::MockNearbyProcessManager() = default;
MockNearbyProcessManager::~MockNearbyProcessManager() = default;
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_NEARBY_SHARING_MOCK_NEARBY_PROCESS_MANAGER_H_
#define CHROME_BROWSER_NEARBY_SHARING_MOCK_NEARBY_PROCESS_MANAGER_H_
#include "chrome/browser/nearby_sharing/nearby_process_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
using NearbyConnectionsMojom =
location::nearby::connections::mojom::NearbyConnections;
using NearbySharingDecoderMojom = sharing::mojom::NearbySharingDecoder;
class MockNearbyProcessManager : public NearbyProcessManager {
public:
MockNearbyProcessManager();
MockNearbyProcessManager(const MockNearbyProcessManager&) = delete;
MockNearbyProcessManager& operator=(const MockNearbyProcessManager&) = delete;
~MockNearbyProcessManager() override;
MOCK_METHOD(NearbyConnectionsMojom*,
GetOrStartNearbyConnections,
(Profile * profile),
(override));
MOCK_METHOD(NearbySharingDecoderMojom*,
GetOrStartNearbySharingDecoder,
(Profile * profile),
(override));
};
#endif // CHROME_BROWSER_NEARBY_SHARING_MOCK_NEARBY_PROCESS_MANAGER_H_
...@@ -29,6 +29,8 @@ class NearbyConnectionsManager { ...@@ -29,6 +29,8 @@ class NearbyConnectionsManager {
public: public:
virtual ~IncomingConnectionListener() = default; virtual ~IncomingConnectionListener() = default;
// |endpoint_info| is returned from remote devices and should be parsed in
// utilitiy process.
virtual void OnIncomingConnection( virtual void OnIncomingConnection(
const std::string& endpoint_id, const std::string& endpoint_id,
const std::vector<uint8_t>& endpoint_info, const std::vector<uint8_t>& endpoint_info,
...@@ -37,8 +39,11 @@ class NearbyConnectionsManager { ...@@ -37,8 +39,11 @@ class NearbyConnectionsManager {
// A callback for handling discovered devices while discovering. // A callback for handling discovered devices while discovering.
class DiscoveryListener { class DiscoveryListener {
public:
virtual ~DiscoveryListener() = default; virtual ~DiscoveryListener() = default;
// |endpoint_info| is returned from remote devices and should be parsed in
// utilitiy process.
virtual void OnEndpointDiscovered( virtual void OnEndpointDiscovered(
const std::string& endpoint_id, const std::string& endpoint_id,
const std::vector<uint8_t>& endpoint_info) = 0; const std::vector<uint8_t>& endpoint_info) = 0;
...@@ -75,8 +80,7 @@ class NearbyConnectionsManager { ...@@ -75,8 +80,7 @@ class NearbyConnectionsManager {
// Starts discovery through Nearby Connections. Caller is expected to ensure // Starts discovery through Nearby Connections. Caller is expected to ensure
// |listener| remains valid until StopDiscovery is called. // |listener| remains valid until StopDiscovery is called.
virtual void StartDiscovery(std::vector<uint8_t> endpoint_info, virtual void StartDiscovery(DiscoveryListener* listener,
DiscoveryListener* listener,
ConnectionsCallback callback) = 0; ConnectionsCallback callback) = 0;
// Stops discovery through Nearby Connections. // Stops discovery through Nearby Connections.
......
...@@ -4,7 +4,26 @@ ...@@ -4,7 +4,26 @@
#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" #include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h"
NearbyConnectionsManagerImpl::NearbyConnectionsManagerImpl() = default; #include "base/strings/string_number_conversions.h"
#include "chrome/browser/nearby_sharing/logging/logging.h"
#include "chrome/services/sharing/public/mojom/nearby_connections_types.mojom.h"
namespace {
const char kServiceId[] = "NearbySharing";
const location::nearby::connections::mojom::Strategy kStrategy =
location::nearby::connections::mojom::Strategy::kP2pPointToPoint;
} // namespace
NearbyConnectionsManagerImpl::NearbyConnectionsManagerImpl(
NearbyProcessManager* process_manager,
Profile* profile)
: process_manager_(process_manager), profile_(profile) {
DCHECK(process_manager_);
DCHECK(profile_);
nearby_process_observer_.Add(process_manager_);
}
NearbyConnectionsManagerImpl::~NearbyConnectionsManagerImpl() = default; NearbyConnectionsManagerImpl::~NearbyConnectionsManagerImpl() = default;
...@@ -18,22 +37,44 @@ void NearbyConnectionsManagerImpl::StartAdvertising( ...@@ -18,22 +37,44 @@ void NearbyConnectionsManagerImpl::StartAdvertising(
PowerLevel power_level, PowerLevel power_level,
DataUsage data_usage, DataUsage data_usage,
ConnectionsCallback callback) { ConnectionsCallback callback) {
// TOOD(crbug/1076008): Implement. if (!BindNearbyConnections()) {
std::move(callback).Run(ConnectionsStatus::kError);
return;
}
// TOOD(crbug/1076008): nearby_connections_->StartAdvertising
} }
void NearbyConnectionsManagerImpl::StopAdvertising() { void NearbyConnectionsManagerImpl::StopAdvertising() {
// TOOD(crbug/1076008): Implement. if (!nearby_connections_)
return;
} }
void NearbyConnectionsManagerImpl::StartDiscovery( void NearbyConnectionsManagerImpl::StartDiscovery(
std::vector<uint8_t> endpoint_info,
DiscoveryListener* listener, DiscoveryListener* listener,
ConnectionsCallback callback) { ConnectionsCallback callback) {
// TOOD(crbug/1076008): Implement. DCHECK(listener);
DCHECK(!discovery_listener_);
if (!BindNearbyConnections()) {
std::move(callback).Run(ConnectionsStatus::kError);
return;
}
discovery_listener_ = listener;
nearby_connections_->StartDiscovery(
kServiceId, DiscoveryOptions::New(kStrategy),
endpoint_discovery_listener_.BindNewPipeAndPassRemote(),
std::move(callback));
} }
void NearbyConnectionsManagerImpl::StopDiscovery() { void NearbyConnectionsManagerImpl::StopDiscovery() {
// TOOD(crbug/1076008): Implement. if (nearby_connections_)
nearby_connections_->StopDiscovery(base::DoNothing());
discovered_endpoints_.clear();
discovery_listener_ = nullptr;
endpoint_discovery_listener_.reset();
} }
std::unique_ptr<NearbyConnection> NearbyConnectionsManagerImpl::Connect( std::unique_ptr<NearbyConnection> NearbyConnectionsManagerImpl::Connect(
...@@ -42,11 +83,19 @@ std::unique_ptr<NearbyConnection> NearbyConnectionsManagerImpl::Connect( ...@@ -42,11 +83,19 @@ std::unique_ptr<NearbyConnection> NearbyConnectionsManagerImpl::Connect(
base::Optional<std::vector<uint8_t>> bluetooth_mac_address, base::Optional<std::vector<uint8_t>> bluetooth_mac_address,
DataUsage data_usage, DataUsage data_usage,
ConnectionsCallback callback) { ConnectionsCallback callback) {
if (!nearby_connections_) {
std::move(callback).Run(ConnectionsStatus::kError);
return nullptr;
}
// TOOD(crbug/1076008): Implement. // TOOD(crbug/1076008): Implement.
return nullptr; return nullptr;
} }
void NearbyConnectionsManagerImpl::Disconnect(const std::string& endpoint_id) { void NearbyConnectionsManagerImpl::Disconnect(const std::string& endpoint_id) {
if (!nearby_connections_)
return;
// TOOD(crbug/1076008): Implement. // TOOD(crbug/1076008): Implement.
} }
...@@ -54,33 +103,130 @@ void NearbyConnectionsManagerImpl::Send(const std::string& endpoint_id, ...@@ -54,33 +103,130 @@ void NearbyConnectionsManagerImpl::Send(const std::string& endpoint_id,
PayloadPtr payload, PayloadPtr payload,
PayloadStatusListener* listener, PayloadStatusListener* listener,
ConnectionsCallback callback) { ConnectionsCallback callback) {
if (!nearby_connections_) {
std::move(callback).Run(ConnectionsStatus::kError);
return;
}
// TOOD(crbug/1076008): Implement. // TOOD(crbug/1076008): Implement.
} }
void NearbyConnectionsManagerImpl::RegisterPayloadStatusListener( void NearbyConnectionsManagerImpl::RegisterPayloadStatusListener(
int64_t payload_id, int64_t payload_id,
PayloadStatusListener* listener) { PayloadStatusListener* listener) {
if (!nearby_connections_)
return;
// TOOD(crbug/1076008): Implement. // TOOD(crbug/1076008): Implement.
} }
NearbyConnectionsManagerImpl::PayloadPtr NearbyConnectionsManagerImpl::PayloadPtr
NearbyConnectionsManagerImpl::GetIncomingPayload(int64_t payload_id) { NearbyConnectionsManagerImpl::GetIncomingPayload(int64_t payload_id) {
if (!nearby_connections_)
return nullptr;
// TOOD(crbug/1076008): Implement. // TOOD(crbug/1076008): Implement.
return nullptr; return nullptr;
} }
void NearbyConnectionsManagerImpl::Cancel(int64_t payload_id, void NearbyConnectionsManagerImpl::Cancel(int64_t payload_id,
ConnectionsCallback callback) { ConnectionsCallback callback) {
if (!nearby_connections_) {
std::move(callback).Run(ConnectionsStatus::kError);
return;
}
// TOOD(crbug/1076008): Implement. // TOOD(crbug/1076008): Implement.
} }
void NearbyConnectionsManagerImpl::ClearIncomingPayloads() { void NearbyConnectionsManagerImpl::ClearIncomingPayloads() {
if (!nearby_connections_)
return;
// TOOD(crbug/1076008): Implement. // TOOD(crbug/1076008): Implement.
} }
base::Optional<std::vector<uint8_t>> base::Optional<std::vector<uint8_t>>
NearbyConnectionsManagerImpl::GetRawAuthenticationToken( NearbyConnectionsManagerImpl::GetRawAuthenticationToken(
const std::string& endpoint_id) { const std::string& endpoint_id) {
if (!nearby_connections_)
return base::nullopt;
// TOOD(crbug/1076008): Implement. // TOOD(crbug/1076008): Implement.
return base::nullopt; return base::nullopt;
} }
void NearbyConnectionsManagerImpl::OnNearbyProfileChanged(Profile* profile) {
NS_LOG(VERBOSE) << __func__;
}
void NearbyConnectionsManagerImpl::OnNearbyProcessStarted() {
NS_LOG(VERBOSE) << __func__;
}
void NearbyConnectionsManagerImpl::OnNearbyProcessStopped() {
NS_LOG(VERBOSE) << __func__;
Reset();
}
void NearbyConnectionsManagerImpl::OnEndpointFound(
const std::string& endpoint_id,
DiscoveredEndpointInfoPtr info) {
if (!discovery_listener_) {
NS_LOG(INFO) << "Ignoring discovered endpoint "
<< base::HexEncode(info->endpoint_info.data(),
info->endpoint_info.size())
<< " because we're no longer "
"in discovery mode";
return;
}
auto result = discovered_endpoints_.insert(endpoint_id);
if (!result.second) {
NS_LOG(INFO) << "Ignoring discovered endpoint "
<< base::HexEncode(info->endpoint_info.data(),
info->endpoint_info.size())
<< " because we've already "
"reported this endpoint";
return;
}
discovery_listener_->OnEndpointDiscovered(endpoint_id, info->endpoint_info);
NS_LOG(INFO) << "Discovered "
<< base::HexEncode(info->endpoint_info.data(),
info->endpoint_info.size())
<< " over Nearby Connections";
}
void NearbyConnectionsManagerImpl::OnEndpointLost(
const std::string& endpoint_id) {
if (!discovered_endpoints_.erase(endpoint_id)) {
NS_LOG(INFO) << "Ignoring lost endpoint " << endpoint_id
<< " because we haven't reported this endpoint";
return;
}
if (!discovery_listener_) {
NS_LOG(INFO) << "Ignoring lost endpoint " << endpoint_id
<< " because we're no longer in discovery mode";
return;
}
discovery_listener_->OnEndpointLost(endpoint_id);
NS_LOG(INFO) << "Endpoint " << endpoint_id << " lost over Nearby Connections";
}
bool NearbyConnectionsManagerImpl::BindNearbyConnections() {
if (!nearby_connections_) {
nearby_connections_ =
process_manager_->GetOrStartNearbyConnections(profile_);
}
return nearby_connections_ != nullptr;
}
void NearbyConnectionsManagerImpl::Reset() {
nearby_connections_ = nullptr;
discovered_endpoints_.clear();
discovery_listener_ = nullptr;
endpoint_discovery_listener_.reset();
}
...@@ -7,10 +7,23 @@ ...@@ -7,10 +7,23 @@
#include "chrome/browser/nearby_sharing/nearby_connections_manager.h" #include "chrome/browser/nearby_sharing/nearby_connections_manager.h"
#include <set>
#include "base/gtest_prod_util.h"
#include "chrome/browser/nearby_sharing/nearby_process_manager.h"
#include "chrome/services/sharing/public/mojom/nearby_connections.mojom.h"
#include "mojo/public/cpp/bindings/receiver.h"
class Profile;
// Concrete NearbyConnectionsManager implementation. // Concrete NearbyConnectionsManager implementation.
class NearbyConnectionsManagerImpl : public NearbyConnectionsManager { class NearbyConnectionsManagerImpl
: public NearbyConnectionsManager,
public NearbyProcessManager::Observer,
public location::nearby::connections::mojom::EndpointDiscoveryListener {
public: public:
NearbyConnectionsManagerImpl(); NearbyConnectionsManagerImpl(NearbyProcessManager* process_manager,
Profile* profile);
~NearbyConnectionsManagerImpl() override; ~NearbyConnectionsManagerImpl() override;
NearbyConnectionsManagerImpl(const NearbyConnectionsManagerImpl&) = delete; NearbyConnectionsManagerImpl(const NearbyConnectionsManagerImpl&) = delete;
NearbyConnectionsManagerImpl& operator=(const NearbyConnectionsManagerImpl&) = NearbyConnectionsManagerImpl& operator=(const NearbyConnectionsManagerImpl&) =
...@@ -24,8 +37,7 @@ class NearbyConnectionsManagerImpl : public NearbyConnectionsManager { ...@@ -24,8 +37,7 @@ class NearbyConnectionsManagerImpl : public NearbyConnectionsManager {
DataUsage data_usage, DataUsage data_usage,
ConnectionsCallback callback) override; ConnectionsCallback callback) override;
void StopAdvertising() override; void StopAdvertising() override;
void StartDiscovery(std::vector<uint8_t> endpoint_info, void StartDiscovery(DiscoveryListener* listener,
DiscoveryListener* listener,
ConnectionsCallback callback) override; ConnectionsCallback callback) override;
void StopDiscovery() override; void StopDiscovery() override;
std::unique_ptr<NearbyConnection> Connect( std::unique_ptr<NearbyConnection> Connect(
...@@ -46,6 +58,41 @@ class NearbyConnectionsManagerImpl : public NearbyConnectionsManager { ...@@ -46,6 +58,41 @@ class NearbyConnectionsManagerImpl : public NearbyConnectionsManager {
void ClearIncomingPayloads() override; void ClearIncomingPayloads() override;
base::Optional<std::vector<uint8_t>> GetRawAuthenticationToken( base::Optional<std::vector<uint8_t>> GetRawAuthenticationToken(
const std::string& endpoint_id) override; const std::string& endpoint_id) override;
private:
using DiscoveryOptions =
location::nearby::connections::mojom::DiscoveryOptions;
using EndpointDiscoveryListener =
location::nearby::connections::mojom::EndpointDiscoveryListener;
using DiscoveredEndpointInfoPtr =
location::nearby::connections::mojom::DiscoveredEndpointInfoPtr;
FRIEND_TEST_ALL_PREFIXES(NearbyConnectionsManagerImplTest,
DiscoveryProcessStopped);
// NearbyProcessManager::Observer:
void OnNearbyProfileChanged(Profile* profile) override;
void OnNearbyProcessStarted() override;
void OnNearbyProcessStopped() override;
// mojom::EndpointDiscoveryListener:
void OnEndpointFound(const std::string& endpoint_id,
DiscoveredEndpointInfoPtr info) override;
void OnEndpointLost(const std::string& endpoint_id) override;
bool BindNearbyConnections();
void Reset();
NearbyProcessManager* process_manager_;
Profile* profile_;
DiscoveryListener* discovery_listener_ = nullptr;
std::set<std::string> discovered_endpoints_;
ScopedObserver<NearbyProcessManager, NearbyProcessManager::Observer>
nearby_process_observer_{this};
mojo::Receiver<EndpointDiscoveryListener> endpoint_discovery_listener_{this};
location::nearby::connections::mojom::NearbyConnections* nearby_connections_ =
nullptr;
}; };
#endif // CHROME_BROWSER_NEARBY_SHARING_NEARBY_CONNECTIONS_MANAGER_IMPL_H_ #endif // CHROME_BROWSER_NEARBY_SHARING_NEARBY_CONNECTIONS_MANAGER_IMPL_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h"
#include <memory>
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
#include "chrome/browser/nearby_sharing/mock_nearby_connections.h"
#include "chrome/browser/nearby_sharing/mock_nearby_process_manager.h"
#include "chrome/services/sharing/public/mojom/nearby_connections_types.mojom.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/browser_task_environment.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
const char kServiceId[] = "NearbySharing";
const location::nearby::connections::mojom::Strategy kStrategy =
location::nearby::connections::mojom::Strategy::kP2pPointToPoint;
const char kEndpointId[] = "endpoint_id";
const char kEndpointInfo[] = {0x0d, 0x07, 0x07, 0x07, 0x07};
} // namespace
using Status = location::nearby::connections::mojom::Status;
using DiscoveredEndpointInfo =
location::nearby::connections::mojom::DiscoveredEndpointInfo;
class MockDiscoveryListener
: public NearbyConnectionsManager::DiscoveryListener {
public:
MOCK_METHOD(void,
OnEndpointDiscovered,
(const std::string& endpoint_id,
const std::vector<uint8_t>& endpoint_info),
(override));
MOCK_METHOD(void,
OnEndpointLost,
(const std::string& endpoint_id),
(override));
};
class NearbyConnectionsManagerImplTest : public testing::Test {
protected:
content::BrowserTaskEnvironment task_environment_;
TestingProfile profile_;
testing::NiceMock<MockNearbyConnections> nearby_connections_;
testing::NiceMock<MockNearbyProcessManager> nearby_process_manager_;
NearbyConnectionsManagerImpl nearby_connections_manager_{
&nearby_process_manager_, &profile_};
};
TEST_F(NearbyConnectionsManagerImplTest, DiscoveryFlow) {
const std::vector<uint8_t> endpoint_info(std::begin(kEndpointInfo),
std::end(kEndpointInfo));
EXPECT_CALL(nearby_process_manager_,
GetOrStartNearbyConnections(testing::Eq(&profile_)))
.WillRepeatedly(testing::Return(&nearby_connections_));
// StartDiscovery will succeed.
mojo::Remote<EndpointDiscoveryListener> listener_remote;
EXPECT_CALL(nearby_connections_, StartDiscovery)
.WillOnce([&listener_remote](
const std::string& service_id, DiscoveryOptionsPtr options,
mojo::PendingRemote<EndpointDiscoveryListener> listener,
NearbyConnectionsMojom::StartDiscoveryCallback callback) {
EXPECT_EQ(kServiceId, service_id);
EXPECT_EQ(kStrategy, options->strategy);
listener_remote.Bind(std::move(listener));
std::move(callback).Run(Status::kSuccess);
});
testing::NiceMock<MockDiscoveryListener> discovery_listener;
base::MockCallback<NearbyConnectionsManager::ConnectionsCallback> callback;
EXPECT_CALL(callback, Run(testing::Eq(Status::kSuccess)));
nearby_connections_manager_.StartDiscovery(&discovery_listener,
callback.Get());
// Invoking OnEndpointFound over remote will invoke OnEndpointDiscovered.
base::RunLoop discovered_run_loop;
EXPECT_CALL(discovery_listener,
OnEndpointDiscovered(testing::Eq(kEndpointId),
testing::Eq(endpoint_info)))
.WillOnce([&discovered_run_loop]() { discovered_run_loop.Quit(); });
listener_remote->OnEndpointFound(
kEndpointId, DiscoveredEndpointInfo::New(endpoint_info, kServiceId));
discovered_run_loop.Run();
// Invoking OnEndpointFound over remote on same endpointId will do nothing.
EXPECT_CALL(discovery_listener, OnEndpointDiscovered(testing::_, testing::_))
.Times(0);
listener_remote->OnEndpointFound(
kEndpointId, DiscoveredEndpointInfo::New(endpoint_info, kServiceId));
// Invoking OnEndpointLost over remote will invoke OnEndpointLost.
base::RunLoop lost_run_loop;
EXPECT_CALL(discovery_listener, OnEndpointLost(testing::Eq(kEndpointId)))
.WillOnce([&lost_run_loop]() { lost_run_loop.Quit(); });
listener_remote->OnEndpointLost(kEndpointId);
lost_run_loop.Run();
// Invoking OnEndpointLost over remote on same endpointId will do nothing.
EXPECT_CALL(discovery_listener, OnEndpointLost(testing::_)).Times(0);
listener_remote->OnEndpointLost(kEndpointId);
// After OnEndpointLost the same endpotinId can be discovered again.
base::RunLoop discovered_run_loop_2;
EXPECT_CALL(discovery_listener,
OnEndpointDiscovered(testing::Eq(kEndpointId),
testing::Eq(endpoint_info)))
.WillOnce([&discovered_run_loop_2]() { discovered_run_loop_2.Quit(); });
listener_remote->OnEndpointFound(
kEndpointId, DiscoveredEndpointInfo::New(endpoint_info, kServiceId));
discovered_run_loop_2.Run();
// Stop discvoery will call through mojo.
EXPECT_CALL(nearby_connections_, StopDiscovery).Times(1);
nearby_connections_manager_.StopDiscovery();
// StartDiscovery again will succeed.
listener_remote.reset();
EXPECT_CALL(nearby_connections_, StartDiscovery)
.WillOnce([&listener_remote](
const std::string& service_id, DiscoveryOptionsPtr options,
mojo::PendingRemote<EndpointDiscoveryListener> listener,
NearbyConnectionsMojom::StartDiscoveryCallback callback) {
listener_remote.Bind(std::move(listener));
std::move(callback).Run(Status::kSuccess);
});
EXPECT_CALL(callback, Run(testing::Eq(Status::kSuccess)));
nearby_connections_manager_.StartDiscovery(&discovery_listener,
callback.Get());
// Same endpotinId can be discovered again.
base::RunLoop discovered_run_loop_3;
EXPECT_CALL(discovery_listener,
OnEndpointDiscovered(testing::Eq(kEndpointId),
testing::Eq(endpoint_info)))
.WillOnce([&discovered_run_loop_3]() { discovered_run_loop_3.Quit(); });
listener_remote->OnEndpointFound(
kEndpointId, DiscoveredEndpointInfo::New(endpoint_info, kServiceId));
discovered_run_loop_3.Run();
}
TEST_F(NearbyConnectionsManagerImplTest, DiscoveryProcessStopped) {
const std::vector<uint8_t> endpoint_info(std::begin(kEndpointInfo),
std::end(kEndpointInfo));
EXPECT_CALL(nearby_process_manager_,
GetOrStartNearbyConnections(testing::Eq(&profile_)))
.WillRepeatedly(testing::Return(&nearby_connections_));
// StartDiscovery will succeed.
mojo::Remote<EndpointDiscoveryListener> listener_remote;
EXPECT_CALL(nearby_connections_, StartDiscovery)
.WillOnce([&listener_remote](
const std::string& service_id, DiscoveryOptionsPtr options,
mojo::PendingRemote<EndpointDiscoveryListener> listener,
NearbyConnectionsMojom::StartDiscoveryCallback callback) {
EXPECT_EQ(kServiceId, service_id);
EXPECT_EQ(kStrategy, options->strategy);
listener_remote.Bind(std::move(listener));
std::move(callback).Run(Status::kSuccess);
});
testing::NiceMock<MockDiscoveryListener> discovery_listener;
base::MockCallback<NearbyConnectionsManager::ConnectionsCallback> callback;
EXPECT_CALL(callback, Run(testing::Eq(Status::kSuccess)));
nearby_connections_manager_.StartDiscovery(&discovery_listener,
callback.Get());
nearby_connections_manager_.OnNearbyProcessStopped();
// Invoking OnEndpointFound will do nothing.
EXPECT_CALL(discovery_listener, OnEndpointDiscovered(testing::_, testing::_))
.Times(0);
listener_remote->OnEndpointFound(
kEndpointId, DiscoveredEndpointInfo::New(endpoint_info, kServiceId));
}
TEST_F(NearbyConnectionsManagerImplTest, StopDiscoveryBeforeStart) {
EXPECT_CALL(nearby_connections_, StopDiscovery).Times(0);
nearby_connections_manager_.StopDiscovery();
}
...@@ -87,13 +87,14 @@ class NearbyProcessManager : public ProfileManagerObserver { ...@@ -87,13 +87,14 @@ class NearbyProcessManager : public ProfileManagerObserver {
// stopped (via the OS or StopProcess()). That event can be observed via // stopped (via the OS or StopProcess()). That event can be observed via
// Observer::OnNearbyProcessStopped() and a client can decide to restart the // Observer::OnNearbyProcessStopped() and a client can decide to restart the
// process (e.g. via backoff timer) if it is still the active profile. // process (e.g. via backoff timer) if it is still the active profile.
NearbyConnectionsMojom* GetOrStartNearbyConnections(Profile* profile); virtual NearbyConnectionsMojom* GetOrStartNearbyConnections(Profile* profile);
// Gets a pointer to the Nearby Decoder interface. Starts a new process if // Gets a pointer to the Nearby Decoder interface. Starts a new process if
// there is none running already or reuses an existing one. The same // there is none running already or reuses an existing one. The same
// limitations around profiles and lifetime in GetOrStartNearbyConnections() // limitations around profiles and lifetime in GetOrStartNearbyConnections()
// apply here as well. // apply here as well.
NearbySharingDecoderMojom* GetOrStartNearbySharingDecoder(Profile* profile); virtual NearbySharingDecoderMojom* GetOrStartNearbySharingDecoder(
Profile* profile);
// Stops the Nearby process if the |profile| is the active profile. This may // Stops the Nearby process if the |profile| is the active profile. This may
// be used to save resources or to force stop any communication of the // be used to save resources or to force stop any communication of the
...@@ -117,6 +118,7 @@ class NearbyProcessManager : public ProfileManagerObserver { ...@@ -117,6 +118,7 @@ class NearbyProcessManager : public ProfileManagerObserver {
FRIEND_TEST_ALL_PREFIXES(NearbySharingServiceImplTest, FRIEND_TEST_ALL_PREFIXES(NearbySharingServiceImplTest,
RemovesNearbyProcessObserver); RemovesNearbyProcessObserver);
friend class base::NoDestructor<NearbyProcessManager>; friend class base::NoDestructor<NearbyProcessManager>;
friend class MockNearbyProcessManager;
// This class is a singleton. // This class is a singleton.
NearbyProcessManager(); NearbyProcessManager();
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/bind_test_util.h" #include "base/test/bind_test_util.h"
#include "chrome/browser/nearby_sharing/mock_nearby_connections.h"
#include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_attributes_entry.h"
#include "chrome/services/sharing/public/mojom/nearby_connections.mojom.h" #include "chrome/services/sharing/public/mojom/nearby_connections.mojom.h"
#include "chrome/services/sharing/public/mojom/nearby_connections_types.mojom.h" #include "chrome/services/sharing/public/mojom/nearby_connections_types.mojom.h"
...@@ -30,8 +31,6 @@ ...@@ -30,8 +31,6 @@
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using NearbyConnectionsMojom =
location::nearby::connections::mojom::NearbyConnections;
using NearbyConnectionsDependencies = using NearbyConnectionsDependencies =
location::nearby::connections::mojom::NearbyConnectionsDependencies; location::nearby::connections::mojom::NearbyConnectionsDependencies;
using NearbyConnectionsDependenciesPtr = using NearbyConnectionsDependenciesPtr =
...@@ -40,10 +39,6 @@ using NearbySharingDecoderMojom = sharing::mojom::NearbySharingDecoder; ...@@ -40,10 +39,6 @@ using NearbySharingDecoderMojom = sharing::mojom::NearbySharingDecoder;
namespace { namespace {
class MockNearbyConnections : public NearbyConnectionsMojom {
public:
};
class MockNearbySharingDecoder : public NearbySharingDecoderMojom { class MockNearbySharingDecoder : public NearbySharingDecoderMojom {
public: public:
MockNearbySharingDecoder() = default; MockNearbySharingDecoder() = default;
......
...@@ -14,8 +14,10 @@ ...@@ -14,8 +14,10 @@
#include "chrome/browser/nearby_sharing/logging/logging.h" #include "chrome/browser/nearby_sharing/logging/logging.h"
#include "chrome/browser/nearby_sharing/nearby_connections_manager.h" #include "chrome/browser/nearby_sharing/nearby_connections_manager.h"
#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" #include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h"
#include "chrome/browser/nearby_sharing/nearby_process_manager.h"
#include "chrome/browser/nearby_sharing/nearby_sharing_service_impl.h" #include "chrome/browser/nearby_sharing/nearby_sharing_service_impl.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
...@@ -41,7 +43,9 @@ NearbySharingService* NearbySharingServiceFactory::GetForBrowserContext( ...@@ -41,7 +43,9 @@ NearbySharingService* NearbySharingServiceFactory::GetForBrowserContext(
NearbySharingServiceFactory::NearbySharingServiceFactory() NearbySharingServiceFactory::NearbySharingServiceFactory()
: BrowserContextKeyedServiceFactory( : BrowserContextKeyedServiceFactory(
kServiceName, kServiceName,
BrowserContextDependencyManager::GetInstance()) {} BrowserContextDependencyManager::GetInstance()) {
DependsOn(IdentityManagerFactory::GetInstance());
}
NearbySharingServiceFactory::~NearbySharingServiceFactory() = default; NearbySharingServiceFactory::~NearbySharingServiceFactory() = default;
...@@ -56,7 +60,8 @@ KeyedService* NearbySharingServiceFactory::BuildServiceInstanceFor( ...@@ -56,7 +60,8 @@ KeyedService* NearbySharingServiceFactory::BuildServiceInstanceFor(
Profile* profile = Profile::FromBrowserContext(context); Profile* profile = Profile::FromBrowserContext(context);
PrefService* pref_service = profile->GetPrefs(); PrefService* pref_service = profile->GetPrefs();
auto nearby_connections_manager = auto nearby_connections_manager =
std::make_unique<NearbyConnectionsManagerImpl>(); std::make_unique<NearbyConnectionsManagerImpl>(
&NearbyProcessManager::GetInstance(), profile);
NS_LOG(VERBOSE) << __func__ << ": creating NearbySharingService."; NS_LOG(VERBOSE) << __func__ << ": creating NearbySharingService.";
return new NearbySharingServiceImpl(pref_service, profile, return new NearbySharingServiceImpl(pref_service, profile,
......
...@@ -99,8 +99,10 @@ std::string ConnectionsStatusToString( ...@@ -99,8 +99,10 @@ std::string ConnectionsStatusToString(
return "ALREADY_CONNECTED_TO_ENDPOINT"; return "ALREADY_CONNECTED_TO_ENDPOINT";
case NearbyConnectionsManager::ConnectionsStatus::kNotConnectedToEndpoint: case NearbyConnectionsManager::ConnectionsStatus::kNotConnectedToEndpoint:
return "NOT_CONNECTED_TO_ENDPOINT"; return "NOT_CONNECTED_TO_ENDPOINT";
case NearbyConnectionsManager::ConnectionsStatus::kRadioError: case NearbyConnectionsManager::ConnectionsStatus::kBluetoothError:
return "RADIO_ERROR"; return "BLUETOOTH_ERROR";
case NearbyConnectionsManager::ConnectionsStatus::kWifiLanError:
return "WIFI_LAN_ERROR";
case NearbyConnectionsManager::ConnectionsStatus::kPayloadUnknown: case NearbyConnectionsManager::ConnectionsStatus::kPayloadUnknown:
return "PAYLOAD_UNKNOWN"; return "PAYLOAD_UNKNOWN";
} }
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_change_registrar.h"
class FastInitiationManager; class FastInitiationManager;
class NearbyConnectionsManager;
class PrefService; class PrefService;
class Profile; class Profile;
......
...@@ -6,15 +6,33 @@ source_set("nearby") { ...@@ -6,15 +6,33 @@ source_set("nearby") {
sources = [ sources = [
"nearby_connections.cc", "nearby_connections.cc",
"nearby_connections.h", "nearby_connections.h",
"nearby_connections_conversions.cc",
"nearby_connections_conversions.h",
] ]
deps = [ "//third_party/nearby:core" ]
public_deps = [ public_deps = [
"decoder", "decoder",
"//base", "//base",
"//chrome/services/sharing/public/cpp", "//chrome/services/sharing/public/cpp",
"//chrome/services/sharing/public/mojom", "//chrome/services/sharing/public/mojom",
"//mojo/public/cpp/bindings", "//mojo/public/cpp/bindings",
"//third_party/nearby:core",
]
deps = [ "//chrome/browser/nearby_sharing/logging" ]
}
source_set("unit_tests") {
testonly = true
sources = [ "nearby_connections_unittest.cc" ]
deps = [
":nearby",
"test_support",
"//base/test:test_support",
"//testing/gmock",
"//testing/gtest",
"//third_party/nearby:core_v2_internal_test",
] ]
} }
...@@ -3,5 +3,6 @@ ...@@ -3,5 +3,6 @@
# found in the LICENSE file. # found in the LICENSE file.
include_rules = [ include_rules = [
"+chrome/browser/nearby_sharing/logging",
"+third_party/nearby", "+third_party/nearby",
] ]
...@@ -4,8 +4,10 @@ ...@@ -4,8 +4,10 @@
#include "chrome/services/sharing/nearby/nearby_connections.h" #include "chrome/services/sharing/nearby/nearby_connections.h"
#include "base/run_loop.h" #include "base/task/post_task.h"
#include "third_party/nearby/src/cpp/core_v2/core.h" #include "chrome/browser/nearby_sharing/logging/logging.h"
#include "chrome/services/sharing/nearby/nearby_connections_conversions.h"
#include "chrome/services/sharing/public/mojom/nearby_connections_types.mojom.h"
namespace location { namespace location {
namespace nearby { namespace nearby {
...@@ -23,42 +25,58 @@ NearbyConnections& NearbyConnections::GetInstance() { ...@@ -23,42 +25,58 @@ NearbyConnections& NearbyConnections::GetInstance() {
NearbyConnections::NearbyConnections( NearbyConnections::NearbyConnections(
mojo::PendingReceiver<mojom::NearbyConnections> nearby_connections, mojo::PendingReceiver<mojom::NearbyConnections> nearby_connections,
mojom::NearbyConnectionsDependenciesPtr dependencies, mojom::NearbyConnectionsDependenciesPtr dependencies,
base::OnceClosure on_disconnect) base::OnceClosure on_disconnect,
std::unique_ptr<Core> core)
: nearby_connections_(this, std::move(nearby_connections)), : nearby_connections_(this, std::move(nearby_connections)),
on_disconnect_(std::move(on_disconnect)) { on_disconnect_(std::move(on_disconnect)),
core_(std::move(core)) {
nearby_connections_.set_disconnect_handler(base::BindOnce( nearby_connections_.set_disconnect_handler(base::BindOnce(
&NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr())); &NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr()));
if (dependencies->bluetooth_adapter) { if (dependencies->bluetooth_adapter) {
bluetooth_adapter_.Bind(std::move(dependencies->bluetooth_adapter)); bluetooth_adapter_.Bind(std::move(dependencies->bluetooth_adapter),
bluetooth_adapter_.set_disconnect_handler(base::BindOnce( /*bind_task_runner=*/nullptr);
&NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr())); bluetooth_adapter_.set_disconnect_handler(
base::BindOnce(&NearbyConnections::OnDisconnect,
weak_ptr_factory_.GetWeakPtr()),
base::SequencedTaskRunnerHandle::Get());
} }
socket_manager_.Bind( socket_manager_.Bind(
std::move(dependencies->webrtc_dependencies->socket_manager)); std::move(dependencies->webrtc_dependencies->socket_manager),
socket_manager_.set_disconnect_handler(base::BindOnce( /*bind_task_runner=*/nullptr);
&NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr())); socket_manager_.set_disconnect_handler(
base::BindOnce(&NearbyConnections::OnDisconnect,
weak_ptr_factory_.GetWeakPtr()),
base::SequencedTaskRunnerHandle::Get());
mdns_responder_.Bind( mdns_responder_.Bind(
std::move(dependencies->webrtc_dependencies->mdns_responder)); std::move(dependencies->webrtc_dependencies->mdns_responder),
mdns_responder_.set_disconnect_handler(base::BindOnce( /*bind_task_runner=*/nullptr);
&NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr())); mdns_responder_.set_disconnect_handler(
base::BindOnce(&NearbyConnections::OnDisconnect,
weak_ptr_factory_.GetWeakPtr()),
base::SequencedTaskRunnerHandle::Get());
ice_config_fetcher_.Bind( ice_config_fetcher_.Bind(
std::move(dependencies->webrtc_dependencies->ice_config_fetcher)); std::move(dependencies->webrtc_dependencies->ice_config_fetcher),
ice_config_fetcher_.set_disconnect_handler(base::BindOnce( /*bind_task_runner=*/nullptr);
&NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr())); ice_config_fetcher_.set_disconnect_handler(
base::BindOnce(&NearbyConnections::OnDisconnect,
weak_ptr_factory_.GetWeakPtr()),
base::SequencedTaskRunnerHandle::Get());
webrtc_signaling_messenger_.Bind( webrtc_signaling_messenger_.Bind(
std::move(dependencies->webrtc_dependencies->messenger)); std::move(dependencies->webrtc_dependencies->messenger),
webrtc_signaling_messenger_.set_disconnect_handler(base::BindOnce( /*bind_task_runner=*/nullptr);
&NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr())); webrtc_signaling_messenger_.set_disconnect_handler(
base::BindOnce(&NearbyConnections::OnDisconnect,
weak_ptr_factory_.GetWeakPtr()),
base::SequencedTaskRunnerHandle::Get());
// There should only be one instance of NearbyConnections in a process. // There should only be one instance of NearbyConnections in a process.
DCHECK(!g_instance); DCHECK(!g_instance);
g_instance = this; g_instance = this;
core_ = std::make_unique<Core>();
} }
NearbyConnections::~NearbyConnections() { NearbyConnections::~NearbyConnections() {
...@@ -110,6 +128,49 @@ NearbyConnections::GetWebRtcSignalingMessenger() { ...@@ -110,6 +128,49 @@ NearbyConnections::GetWebRtcSignalingMessenger() {
return webrtc_signaling_messenger_.get(); return webrtc_signaling_messenger_.get();
} }
void NearbyConnections::StartDiscovery(
const std::string& service_id,
mojom::DiscoveryOptionsPtr options,
mojo::PendingRemote<mojom::EndpointDiscoveryListener> listener,
StartDiscoveryCallback callback) {
ConnectionOptions connection_options{
.strategy = StrategyFromMojom(options->strategy)};
mojo::SharedRemote<mojom::EndpointDiscoveryListener> remote(
std::move(listener));
DiscoveryListener discovery_listener{
.endpoint_found_cb =
[remote](const std::string& endpoint_id,
const std::string& endpoint_name,
const std::string& service_id) {
if (!remote) {
return;
}
remote->OnEndpointFound(
endpoint_id, mojom::DiscoveredEndpointInfo::New(
std::vector<uint8_t>(endpoint_name.begin(),
endpoint_name.end()),
service_id));
},
.endpoint_lost_cb =
[remote](const std::string& endpoint_id) {
if (!remote)
return;
remote->OnEndpointLost(endpoint_id);
},
};
ResultCallback result_callback = ResultCallbackFromMojom(std::move(callback));
core_->StartDiscovery(service_id, std::move(connection_options),
std::move(discovery_listener),
std::move(result_callback));
}
void NearbyConnections::StopDiscovery(StopDiscoveryCallback callback) {
core_->StopDiscovery(ResultCallbackFromMojom(std::move(callback)));
}
} // namespace connections } // namespace connections
} // namespace nearby } // namespace nearby
} // namespace location } // namespace location
...@@ -5,25 +5,23 @@ ...@@ -5,25 +5,23 @@
#ifndef CHROME_SERVICES_SHARING_NEARBY_NEARBY_CONNECTIONS_H_ #ifndef CHROME_SERVICES_SHARING_NEARBY_NEARBY_CONNECTIONS_H_
#define CHROME_SERVICES_SHARING_NEARBY_NEARBY_CONNECTIONS_H_ #define CHROME_SERVICES_SHARING_NEARBY_NEARBY_CONNECTIONS_H_
#include <memory>
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "chrome/services/sharing/public/mojom/nearby_connections.mojom.h" #include "chrome/services/sharing/public/mojom/nearby_connections.mojom.h"
#include "chrome/services/sharing/public/mojom/webrtc_signaling_messenger.mojom.h" #include "chrome/services/sharing/public/mojom/webrtc_signaling_messenger.mojom.h"
#include "device/bluetooth/public/mojom/adapter.mojom.h" #include "device/bluetooth/public/mojom/adapter.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/shared_remote.h"
#include "third_party/nearby/src/cpp/core_v2/core.h"
#include <memory>
namespace location { namespace location {
namespace nearby { namespace nearby {
namespace connections { namespace connections {
class Core;
// Implementation of the NearbyConnections mojo interface. // Implementation of the NearbyConnections mojo interface.
// This class acts as a bridge to the NearbyConnections library which is pulled // This class acts as a bridge to the NearbyConnections library which is pulled
// in as a third_party dependency. It handles the translation from mojo calls to // in as a third_party dependency. It handles the translation from mojo calls to
...@@ -40,7 +38,9 @@ class NearbyConnections : public mojom::NearbyConnections { ...@@ -40,7 +38,9 @@ class NearbyConnections : public mojom::NearbyConnections {
NearbyConnections( NearbyConnections(
mojo::PendingReceiver<mojom::NearbyConnections> nearby_connections, mojo::PendingReceiver<mojom::NearbyConnections> nearby_connections,
mojom::NearbyConnectionsDependenciesPtr dependencies, mojom::NearbyConnectionsDependenciesPtr dependencies,
base::OnceClosure on_disconnect); base::OnceClosure on_disconnect,
std::unique_ptr<Core> core = std::make_unique<Core>());
NearbyConnections(const NearbyConnections&) = delete; NearbyConnections(const NearbyConnections&) = delete;
NearbyConnections& operator=(const NearbyConnections&) = delete; NearbyConnections& operator=(const NearbyConnections&) = delete;
~NearbyConnections() override; ~NearbyConnections() override;
...@@ -54,18 +54,27 @@ class NearbyConnections : public mojom::NearbyConnections { ...@@ -54,18 +54,27 @@ class NearbyConnections : public mojom::NearbyConnections {
sharing::mojom::IceConfigFetcher* GetWebRtcIceConfigFetcher(); sharing::mojom::IceConfigFetcher* GetWebRtcIceConfigFetcher();
sharing::mojom::WebRtcSignalingMessenger* GetWebRtcSignalingMessenger(); sharing::mojom::WebRtcSignalingMessenger* GetWebRtcSignalingMessenger();
// mojom::NearbyConnections:
void StartDiscovery(
const std::string& service_id,
mojom::DiscoveryOptionsPtr options,
mojo::PendingRemote<mojom::EndpointDiscoveryListener> listener,
StartDiscoveryCallback callback) override;
void StopDiscovery(StopDiscoveryCallback callback) override;
private: private:
void OnDisconnect(); void OnDisconnect();
mojo::Receiver<mojom::NearbyConnections> nearby_connections_; mojo::Receiver<mojom::NearbyConnections> nearby_connections_;
base::OnceClosure on_disconnect_; base::OnceClosure on_disconnect_;
// Medium dependencies: // Medium dependencies. SharedRemote is used to ensure all calls are posted
mojo::Remote<bluetooth::mojom::Adapter> bluetooth_adapter_; // to sequence binding the Remote.
mojo::Remote<network::mojom::P2PSocketManager> socket_manager_; mojo::SharedRemote<bluetooth::mojom::Adapter> bluetooth_adapter_;
mojo::Remote<network::mojom::MdnsResponder> mdns_responder_; mojo::SharedRemote<network::mojom::P2PSocketManager> socket_manager_;
mojo::Remote<sharing::mojom::IceConfigFetcher> ice_config_fetcher_; mojo::SharedRemote<network::mojom::MdnsResponder> mdns_responder_;
mojo::Remote<sharing::mojom::WebRtcSignalingMessenger> mojo::SharedRemote<sharing::mojom::IceConfigFetcher> ice_config_fetcher_;
mojo::SharedRemote<sharing::mojom::WebRtcSignalingMessenger>
webrtc_signaling_messenger_; webrtc_signaling_messenger_;
std::unique_ptr<Core> core_; std::unique_ptr<Core> core_;
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/services/sharing/nearby/nearby_connections_conversions.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "chrome/services/sharing/public/mojom/nearby_connections.mojom.h"
#include "chrome/services/sharing/public/mojom/nearby_connections_types.mojom.h"
namespace location {
namespace nearby {
namespace connections {
Strategy StrategyFromMojom(mojom::Strategy strategy) {
switch (strategy) {
case mojom::Strategy::kP2pCluster:
return Strategy::kP2pCluster;
case mojom::Strategy::kP2pStar:
return Strategy::kP2pStar;
case mojom::Strategy::kP2pPointToPoint:
return Strategy::kP2pPointToPoint;
}
}
mojom::Status StatusToMojom(Status::Value status) {
switch (status) {
case Status::Value::kSuccess:
return mojom::Status::kSuccess;
case Status::Value::kError:
return mojom::Status::kError;
case Status::Value::kOutOfOrderApiCall:
return mojom::Status::kOutOfOrderApiCall;
case Status::Value::kAlreadyHaveActiveStrategy:
return mojom::Status::kAlreadyHaveActiveStrategy;
case Status::Value::kAlreadyAdvertising:
return mojom::Status::kAlreadyAdvertising;
case Status::Value::kAlreadyDiscovering:
return mojom::Status::kAlreadyDiscovering;
case Status::Value::kEndpointIoError:
return mojom::Status::kEndpointIOError;
case Status::Value::kEndpointUnknown:
return mojom::Status::kEndpointUnknown;
case Status::Value::kConnectionRejected:
return mojom::Status::kConnectionRejected;
case Status::Value::kAlreadyConnectedToEndpoint:
return mojom::Status::kAlreadyConnectedToEndpoint;
case Status::Value::kNotConnectedToEndpoint:
return mojom::Status::kNotConnectedToEndpoint;
case Status::Value::kBluetoothError:
return mojom::Status::kBluetoothError;
case Status::Value::kWifiLanError:
return mojom::Status::kWifiLanError;
case Status::Value::kPayloadUnknown:
return mojom::Status::kPayloadUnknown;
}
}
ResultCallback ResultCallbackFromMojom(StatusCallback callback) {
// Since std::function must be CopyAssignable, use std::shared_ptr to capture
// |callback| inside lambda, and only use callback first time ResultCallback
// is invoked.
// Also capture the current sequence runner to run |callback| in the correct
// sequence.
return {[callback = std::make_shared<StatusCallback>(std::move(callback)),
task_runner =
base::SequencedTaskRunnerHandle::Get()](Status status) {
if (*callback) {
task_runner->PostTask(
FROM_HERE,
base::BindOnce(std::move(*callback), StatusToMojom(status.value)));
}
}};
}
} // namespace connections
} // namespace nearby
} // namespace location
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_SERVICES_SHARING_NEARBY_NEARBY_CONNECTIONS_CONVERSIONS_H_
#define CHROME_SERVICES_SHARING_NEARBY_NEARBY_CONNECTIONS_CONVERSIONS_H_
#include <cstdint>
#include <vector>
#include "base/callback_forward.h"
#include "chrome/services/sharing/public/mojom/nearby_connections.mojom-forward.h"
#include "chrome/services/sharing/public/mojom/nearby_connections_types.mojom-forward.h"
#include "third_party/nearby/src/cpp/core_v2/options.h"
#include "third_party/nearby/src/cpp/core_v2/params.h"
namespace location {
namespace nearby {
namespace connections {
using StatusCallback = base::OnceCallback<void(mojom::Status)>;
Strategy StrategyFromMojom(mojom::Strategy strategy);
mojom::Status StatusToMojom(Status::Value status);
ResultCallback ResultCallbackFromMojom(StatusCallback callback);
} // namespace connections
} // namespace nearby
} // namespace location
#endif // CHROME_SERVICES_SHARING_NEARBY_NEARBY_CONNECTIONS_CONVERSIONS_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/services/sharing/nearby/nearby_connections.h"
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "chrome/services/sharing/nearby/test_support/mock_bluetooth_adapter.h"
#include "chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.h"
#include "chrome/services/sharing/public/mojom/nearby_decoder.mojom.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/nearby/src/cpp/core_v2/internal/mock_service_controller.h"
namespace location {
namespace nearby {
namespace connections {
namespace {
const char kServiceId[] = "service-id";
const char kRemoteEndpointId[] = "remote_endpoint_id";
const char kRemoteEndpointInfo[] = {0x0d, 0x07, 0x06, 0x08, 0x09};
} // namespace
class FakeEndpointDiscoveryListener : public mojom::EndpointDiscoveryListener {
public:
void OnEndpointFound(const std::string& endpoint_id,
mojom::DiscoveredEndpointInfoPtr info) override {
endpoint_found_cb.Run(endpoint_id, std::move(info));
}
void OnEndpointLost(const std::string& endpoint_id) override {
endpoint_lost_cb.Run(endpoint_id);
}
mojo::Receiver<mojom::EndpointDiscoveryListener> receiver{this};
base::RepeatingCallback<void(const std::string&,
mojom::DiscoveredEndpointInfoPtr)>
endpoint_found_cb = base::DoNothing();
base::RepeatingCallback<void(const std::string&)> endpoint_lost_cb =
base::DoNothing();
};
class NearbyConnectionsTest : public testing::Test {
public:
NearbyConnectionsTest() {
auto webrtc_dependencies = mojom::WebRtcDependencies::New(
webrtc_dependencies_.socket_manager_.BindNewPipeAndPassRemote(),
webrtc_dependencies_.mdns_responder_.BindNewPipeAndPassRemote(),
webrtc_dependencies_.ice_config_fetcher_.BindNewPipeAndPassRemote(),
webrtc_dependencies_.messenger_.BindNewPipeAndPassRemote());
auto dependencies = mojom::NearbyConnectionsDependencies::New(
bluetooth_adapter_.adapter.BindNewPipeAndPassRemote(),
std::move(webrtc_dependencies));
service_controller_ =
std::make_unique<testing::NiceMock<MockServiceController>>();
service_controller_ptr_ = service_controller_.get();
nearby_connections_ = std::make_unique<NearbyConnections>(
remote_.BindNewPipeAndPassReceiver(), std::move(dependencies),
base::BindOnce(&NearbyConnectionsTest::OnDisconnect,
base::Unretained(this)),
std::make_unique<Core>(
[&]() { return service_controller_.release(); }));
}
void OnDisconnect() { disconnect_run_loop_.Quit(); }
protected:
base::test::TaskEnvironment task_environment_;
mojo::Remote<mojom::NearbyConnections> remote_;
bluetooth::MockBluetoothAdapter bluetooth_adapter_;
sharing::MockWebRtcDependencies webrtc_dependencies_;
std::unique_ptr<NearbyConnections> nearby_connections_;
testing::NiceMock<MockServiceController>* service_controller_ptr_;
base::RunLoop disconnect_run_loop_;
private:
std::unique_ptr<testing::NiceMock<MockServiceController>> service_controller_;
};
TEST_F(NearbyConnectionsTest, RemoteDisconnect) {
remote_.reset();
disconnect_run_loop_.Run();
}
TEST_F(NearbyConnectionsTest, BluetoothDisconnect) {
bluetooth_adapter_.adapter.reset();
disconnect_run_loop_.Run();
}
TEST_F(NearbyConnectionsTest, P2PSocketManagerDisconnect) {
webrtc_dependencies_.socket_manager_.reset();
disconnect_run_loop_.Run();
}
TEST_F(NearbyConnectionsTest, MdnsResponderDisconnect) {
webrtc_dependencies_.mdns_responder_.reset();
disconnect_run_loop_.Run();
}
TEST_F(NearbyConnectionsTest, IceConfigFetcherDisconnect) {
webrtc_dependencies_.ice_config_fetcher_.reset();
disconnect_run_loop_.Run();
}
TEST_F(NearbyConnectionsTest, WebRtcSignalingMessengerDisconnect) {
webrtc_dependencies_.messenger_.reset();
disconnect_run_loop_.Run();
}
TEST_F(NearbyConnectionsTest, StartStopDiscovery) {
ClientProxy* client_proxy;
EXPECT_CALL(*service_controller_ptr_, StartDiscovery)
.WillOnce([&client_proxy](ClientProxy* client,
const std::string& service_id,
const ConnectionOptions& options,
const DiscoveryListener& listener) {
client_proxy = client;
EXPECT_EQ(kServiceId, service_id);
EXPECT_EQ(Strategy::kP2pPointToPoint, options.strategy);
client->StartedDiscovery(service_id, options.strategy, listener,
/*mediums=*/{});
return Status{Status::kAlreadyDiscovering};
});
base::RunLoop start_discovery_run_loop;
FakeEndpointDiscoveryListener fake_discovery_listener;
nearby_connections_->StartDiscovery(
kServiceId,
mojom::DiscoveryOptions::New(mojom::Strategy::kP2pPointToPoint),
fake_discovery_listener.receiver.BindNewPipeAndPassRemote(),
base::BindLambdaForTesting([&](mojom::Status status) {
EXPECT_EQ(mojom::Status::kAlreadyDiscovering, status);
start_discovery_run_loop.Quit();
}));
start_discovery_run_loop.Run();
base::RunLoop endpoint_found_run_loop;
fake_discovery_listener.endpoint_found_cb =
base::BindLambdaForTesting([&](const std::string& endpoint_id,
mojom::DiscoveredEndpointInfoPtr info) {
EXPECT_EQ(kRemoteEndpointId, endpoint_id);
EXPECT_EQ(std::vector<uint8_t>(std::begin(kRemoteEndpointInfo),
std::end(kRemoteEndpointInfo)),
info->endpoint_info);
EXPECT_EQ(kServiceId, info->service_id);
endpoint_found_run_loop.Quit();
});
client_proxy->OnEndpointFound(kServiceId, kRemoteEndpointId,
std::string(std::begin(kRemoteEndpointInfo),
std::end(kRemoteEndpointInfo)),
/*mediums=*/{});
endpoint_found_run_loop.Run();
base::RunLoop endpoint_lost_run_loop;
fake_discovery_listener.endpoint_lost_cb =
base::BindLambdaForTesting([&](const std::string& endpoint_id) {
EXPECT_EQ(kRemoteEndpointId, endpoint_id);
endpoint_lost_run_loop.Quit();
});
client_proxy->OnEndpointLost(kServiceId, kRemoteEndpointId);
endpoint_lost_run_loop.Run();
EXPECT_CALL(*service_controller_ptr_, StopDiscovery(testing::_)).Times(1);
base::RunLoop stop_discovery_run_loop;
nearby_connections_->StopDiscovery(
base::BindLambdaForTesting([&](mojom::Status status) {
EXPECT_EQ(mojom::Status::kSuccess, status);
stop_discovery_run_loop.Quit();
}));
stop_discovery_run_loop.Run();
// StopDiscovery is also called when Core is destroyed.
EXPECT_CALL(*service_controller_ptr_, StopDiscovery(testing::_)).Times(1);
}
} // namespace connections
} // namespace nearby
} // namespace location
...@@ -54,7 +54,7 @@ int GetCurrentTid() { ...@@ -54,7 +54,7 @@ int GetCurrentTid() {
std::unique_ptr<SubmittableExecutor> std::unique_ptr<SubmittableExecutor>
ImplementationPlatform::CreateSingleThreadExecutor() { ImplementationPlatform::CreateSingleThreadExecutor() {
return std::make_unique<chrome::SubmittableExecutor>( return std::make_unique<chrome::SubmittableExecutor>(
base::ThreadPool::CreateSingleThreadTaskRunner({base::MayBlock()})); base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}));
} }
std::unique_ptr<SubmittableExecutor> std::unique_ptr<SubmittableExecutor>
......
...@@ -24,12 +24,55 @@ struct WebRtcDependencies { ...@@ -24,12 +24,55 @@ struct WebRtcDependencies {
pending_remote<sharing.mojom.WebRtcSignalingMessenger> messenger; pending_remote<sharing.mojom.WebRtcSignalingMessenger> messenger;
}; };
// Listener invoked during endpoint discovery. This interface is used by the
// browser process to listen for remote endpoints status during endpoint
// discovery.
interface EndpointDiscoveryListener {
// Called when a remote endpoint is discovered.
//
// endpoint_id - The ID of the remote endpoint that was discovered.
// info - Further information about the remote endpoint which may
// include the human readable name if it is advertising in high
// visibility mode.
OnEndpointFound(string endpoint_id, DiscoveredEndpointInfo info);
// Called when a remote endpoint is no longer discoverable; only called for
// endpoints that previously had been passed to OnEndpointFound().
//
// endpoint_id - The ID of the remote endpoint that was lost.
OnEndpointLost(string endpoint_id);
};
// Main interface to control the NearbyConnections library. Implemented in a // Main interface to control the NearbyConnections library. Implemented in a
// sandboxed process. This interface is used by the browser process to connect // sandboxed process. This interface is used by the browser process to connect
// to remote devices and send / receive raw data packets. Parsing of those // to remote devices and send / receive raw data packets. Parsing of those
// packets is not part of the NearbyConnections library and is done in a // packets is not part of the NearbyConnections library and is done in a
// separate interface. // separate interface.
interface NearbyConnections { interface NearbyConnections {
// Starts discovery for remote endpoints with the specified service ID.
//
// service_id - The ID for the service to be discovered, as specified in
// the corresponding call to StartAdvertising.
// options - The options for discovery.
// listener - A callback notified when a remote endpoint is discovered.
// Possible status codes include:
// Status::kSuccess if discovery started successfully.
// Status::kAlreadyDiscovering if the app is already
// discovering the specified service.
// Status::kOutOfOrderApiCall if the app is currently
// connected to remote endpoints; call StopAllEndpoints first.
StartDiscovery(string service_id, DiscoveryOptions options,
pending_remote<EndpointDiscoveryListener> listener)
=> (Status status);
// Stops discovery for remote endpoints, after a previous call to
// StartDiscovery, when the client no longer needs to discover endpoints or
// goes inactive. Payloads can still be sent to connected endpoints after
// discovery ends.
//
// Possible return values include:
// Status::kSuccess returned after discovery got stopped.
StopDiscovery() => (Status status);
}; };
// Provide all the dependencies that NearbyConnections library requires. // Provide all the dependencies that NearbyConnections library requires.
......
...@@ -41,9 +41,10 @@ enum Status { ...@@ -41,9 +41,10 @@ enum Status {
kAlreadyConnectedToEndpoint, kAlreadyConnectedToEndpoint,
// The remote endpoint is not connected; messages cannot be sent to it. // The remote endpoint is not connected; messages cannot be sent to it.
kNotConnectedToEndpoint, kNotConnectedToEndpoint,
// There was an error trying to use the device's Bluetooth/WiFi/NFC // There was an error trying to use the device's Bluetooth capabilities.
// capabilities. kBluetoothError,
kRadioError, // There was an error trying to use the device's WiFi capabilities.
kWifiLanError,
// An attempt to interact with an in-flight Payload failed because it's // An attempt to interact with an in-flight Payload failed because it's
// unknown to us. // unknown to us.
kPayloadUnknown, kPayloadUnknown,
...@@ -70,12 +71,10 @@ struct ConnectionInfo { ...@@ -70,12 +71,10 @@ struct ConnectionInfo {
// Information about an endpoint when it's discovered. // Information about an endpoint when it's discovered.
struct DiscoveredEndpointInfo { struct DiscoveredEndpointInfo {
// The ID of the service advertised by the remote endpoint.
string service_id;
// The human readable name of the remote endpoint.
string endpoint_name;
// Information advertised by the remote endpoint. // Information advertised by the remote endpoint.
array<uint8> endpoint_info; array<uint8> endpoint_info;
// The ID of the service advertised by the remote endpoint.
string service_id;
}; };
// The Strategy to be used when discovering or advertising to Nearby devices. // The Strategy to be used when discovering or advertising to Nearby devices.
......
...@@ -3669,9 +3669,14 @@ test("unit_tests") { ...@@ -3669,9 +3669,14 @@ test("unit_tests") {
"../browser/nearby_sharing/instantmessaging/receive_messages_express_unittest.cc", "../browser/nearby_sharing/instantmessaging/receive_messages_express_unittest.cc",
"../browser/nearby_sharing/instantmessaging/send_message_express_unittest.cc", "../browser/nearby_sharing/instantmessaging/send_message_express_unittest.cc",
"../browser/nearby_sharing/instantmessaging/stream_parser_unittest.cc", "../browser/nearby_sharing/instantmessaging/stream_parser_unittest.cc",
"../browser/nearby_sharing/mock_nearby_connections.cc",
"../browser/nearby_sharing/mock_nearby_connections.h",
"../browser/nearby_sharing/mock_nearby_process_manager.cc",
"../browser/nearby_sharing/mock_nearby_process_manager.h",
"../browser/nearby_sharing/mock_nearby_sharing_service.cc", "../browser/nearby_sharing/mock_nearby_sharing_service.cc",
"../browser/nearby_sharing/mock_nearby_sharing_service.h", "../browser/nearby_sharing/mock_nearby_sharing_service.h",
"../browser/nearby_sharing/nearby_confirmation_manager_unittest.cc", "../browser/nearby_sharing/nearby_confirmation_manager_unittest.cc",
"../browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc",
"../browser/nearby_sharing/nearby_notification_manager_unittest.cc", "../browser/nearby_sharing/nearby_notification_manager_unittest.cc",
"../browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc", "../browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc",
"../browser/nearby_sharing/nearby_process_manager_unittest.cc", "../browser/nearby_sharing/nearby_process_manager_unittest.cc",
...@@ -4387,6 +4392,7 @@ test("unit_tests") { ...@@ -4387,6 +4392,7 @@ test("unit_tests") {
"//chrome/browser/resource_coordinator:tab_metrics_event_proto", "//chrome/browser/resource_coordinator:tab_metrics_event_proto",
"//chrome/browser/resource_coordinator/tab_ranker:tab_features_test_helper", "//chrome/browser/resource_coordinator/tab_ranker:tab_features_test_helper",
"//chrome/services/sharing:unit_tests", "//chrome/services/sharing:unit_tests",
"//chrome/services/sharing/nearby:unit_tests",
"//chrome/services/sharing/nearby/decoder:unit_tests", "//chrome/services/sharing/nearby/decoder:unit_tests",
"//chrome/services/sharing/nearby/platform_v2:unit_tests", "//chrome/services/sharing/nearby/platform_v2:unit_tests",
"//chrome/services/sharing/public/cpp:unit_tests", "//chrome/services/sharing/public/cpp:unit_tests",
......
...@@ -359,6 +359,16 @@ source_set("core_v2_internal") { ...@@ -359,6 +359,16 @@ source_set("core_v2_internal") {
configs += [ "//build/config/compiler:no_chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ]
} }
source_set("core_v2_internal_test") {
testonly = true
public_configs = [ ":nearby_include_config" ]
public = [ "src/cpp/core_v2/internal/mock_service_controller.h" ]
deps = [
":core_v2_internal",
"//third_party/googletest:gmock",
]
}
# src/cpp/core_v2/internal/mediums # src/cpp/core_v2/internal/mediums
source_set("core_v2_internal_mediums") { source_set("core_v2_internal_mediums") {
public_configs = [ ":nearby_include_config" ] public_configs = [ ":nearby_include_config" ]
......
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