Commit fa869e00 authored by Naomi Musgrave's avatar Naomi Musgrave Committed by Commit Bot

Implement the send surface in NearbySharingService.

Track share targets as they are (un)registered, and start scanning.
Only handles surfaces registered to the foreground for now.

Bug: 1084644
Change-Id: I852388f8dd1d355263979d94f2959cc79f905929
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2292214
Commit-Queue: Naomi Musgrave <nmusgrave@chromium.org>
Reviewed-by: default avatarRichard Knoll <knollr@chromium.org>
Reviewed-by: default avatarAlex Chau <alexchau@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796384}
parent b4283204
......@@ -110,6 +110,23 @@ void FakeNearbyConnectionsManager::UpgradeBandwidth(
upgrade_bandwidth_endpoint_ids_.insert(endpoint_id);
}
void FakeNearbyConnectionsManager::OnEndpointFound(
const std::string& endpoint_id,
location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info) {
if (!discovery_listener_)
return;
discovery_listener_->OnEndpointDiscovered(endpoint_id, info->endpoint_info);
}
void FakeNearbyConnectionsManager::OnEndpointLost(
const std::string& endpoint_id) {
if (!discovery_listener_)
return;
discovery_listener_->OnEndpointLost(endpoint_id);
}
bool FakeNearbyConnectionsManager::IsAdvertising() {
return advertising_listener_ != nullptr;
}
......
......@@ -12,11 +12,13 @@
#include <vector>
#include "chrome/browser/nearby_sharing/nearby_connections_manager.h"
#include "chrome/services/sharing/public/mojom/nearby_connections.mojom.h"
// Fake NearbyConnectionsManager for testing.
class FakeNearbyConnectionsManager : public NearbyConnectionsManager {
class FakeNearbyConnectionsManager
: public NearbyConnectionsManager,
public location::nearby::connections::mojom::EndpointDiscoveryListener {
public:
FakeNearbyConnectionsManager();
~FakeNearbyConnectionsManager() override;
......@@ -50,6 +52,13 @@ class FakeNearbyConnectionsManager : public NearbyConnectionsManager {
const std::string& endpoint_id) override;
void UpgradeBandwidth(const std::string& endpoint_id) override;
// mojom::EndpointDiscoveryListener:
void OnEndpointFound(
const std::string& endpoint_id,
location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info)
override;
void OnEndpointLost(const std::string& endpoint_id) override;
// Testing methods
bool IsAdvertising();
bool IsDiscovering();
......
......@@ -33,6 +33,14 @@ class NearbySharingService : public KeyedService {
kOk,
// The operation failed since it was called in an invalid order.
kOutOfOrderApiCall,
// Tried to stop something that was already stopped.
kStatusAlreadyStopped,
// Tried to register an opposite foreground surface in the midst of a
// transfer or connection.
// (Tried to register Send Surface when receiving a file or tried to
// register Receive Surface when
// sending a file.)
kTransferAlreadyInProgress,
};
enum class ReceiveSurfaceState {
......
......@@ -7,8 +7,10 @@
#include <utility>
#include "base/bind.h"
#include "base/logging.h"
#include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager_impl.h"
#include "chrome/browser/nearby_sharing/client/nearby_share_client_impl.h"
#include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h"
......@@ -34,6 +36,9 @@ constexpr base::TimeDelta kReadResponseFrameTimeout =
base::TimeDelta::FromSeconds(60);
constexpr base::TimeDelta kIncomingRejectionDelay =
base::TimeDelta::FromSeconds(2);
// Time to delay running the task to invalidate send and receive surfaces.
constexpr base::TimeDelta kInvalidateDelay =
base::TimeDelta::FromMilliseconds(500);
std::string ReceiveSurfaceStateToString(
NearbySharingService::ReceiveSurfaceState state) {
......@@ -130,8 +135,7 @@ NearbySharingServiceImpl::NearbySharingServiceImpl(
Profile* profile,
std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager,
NearbyProcessManager* process_manager)
: prefs_(prefs),
profile_(profile),
: profile_(profile),
settings_(prefs),
nearby_connections_manager_(std::move(nearby_connections_manager)),
process_manager_(process_manager),
......@@ -146,7 +150,6 @@ NearbySharingServiceImpl::NearbySharingServiceImpl(
contact_manager_(NearbyShareContactManagerImpl::Factory::Create()),
certificate_manager_(
NearbyShareCertificateManagerImpl::Factory::Create()) {
DCHECK(prefs_);
DCHECK(profile_);
DCHECK(nearby_connections_manager_);
......@@ -178,7 +181,61 @@ NearbySharingService::StatusCodes NearbySharingServiceImpl::RegisterSendSurface(
ShareTargetDiscoveredCallback* discovery_callback,
SendSurfaceState state) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// TODO(crrbug.com/1084644): Implement send surface logic.
DCHECK(transfer_callback);
DCHECK(discovery_callback);
DCHECK_NE(state, SendSurfaceState::kUnknown);
if (!process_manager_->IsActiveProfile(profile_)) {
NS_LOG(VERBOSE) << __func__
<< ": RegisterSendSurface failed, since profile not active";
return StatusCodes::kError;
}
if (foreground_send_transfer_callbacks_.HasObserver(transfer_callback) ||
background_send_transfer_callbacks_.HasObserver(transfer_callback)) {
NS_LOG(VERBOSE) << __func__
<< ": RegisterSendSurface failed. Already registered.";
return StatusCodes::kError;
}
if (state == SendSurfaceState::kForeground) {
foreground_send_transfer_callbacks_.AddObserver(transfer_callback);
foreground_send_discovery_callbacks_.AddObserver(discovery_callback);
} else {
background_send_transfer_callbacks_.AddObserver(transfer_callback);
background_send_discovery_callbacks_.AddObserver(discovery_callback);
}
NS_LOG(VERBOSE) << __func__ << ": RegisterSendSurface";
if (is_receiving_files_) {
UnregisterSendSurface(transfer_callback, discovery_callback);
NS_LOG(VERBOSE)
<< __func__
<< ": Ignore registering (and unregistering if registered) send "
"surface because we're currently receiving files.";
return StatusCodes::kTransferAlreadyInProgress;
}
// If the share sheet to be registered is a foreground surface, let it catch
// up with most recent transfer metadata immediately.
if (state == SendSurfaceState::kForeground && last_outgoing_metadata_) {
// When a new share sheet is registered, we want to immediately show the
// in-progress bar.
discovery_callback->OnShareTargetDiscovered(last_outgoing_metadata_->first);
transfer_callback->OnTransferUpdate(last_outgoing_metadata_->first,
last_outgoing_metadata_->second);
}
// Let newly registered send surface catch up with discovered share targets
// from current scanning session.
for (const std::pair<std::string, ShareTarget>& item :
outgoing_share_target_map_) {
discovery_callback->OnShareTargetDiscovered(item.second);
}
NS_LOG(VERBOSE) << __func__ << ": A SendSurface has been registered.";
InvalidateSendSurfaceState();
if (state == SendSurfaceState::kForeground)
StartFastInitiationAdvertising();
return StatusCodes::kOk;
......@@ -189,6 +246,46 @@ NearbySharingServiceImpl::UnregisterSendSurface(
TransferUpdateCallback* transfer_callback,
ShareTargetDiscoveredCallback* discovery_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(transfer_callback);
DCHECK(discovery_callback);
if (!foreground_send_transfer_callbacks_.HasObserver(transfer_callback) &&
!background_send_transfer_callbacks_.HasObserver(transfer_callback)) {
NS_LOG(VERBOSE)
<< __func__
<< ": unregisterSendSurface failed. Unknown TransferUpdateCallback";
return StatusCodes::kError;
}
if (foreground_send_transfer_callbacks_.might_have_observers() &&
last_outgoing_metadata_ &&
last_outgoing_metadata_->second.is_final_status()) {
// We already saw the final status in the foreground
// Nullify it so the next time the user opens sharing, it starts the UI from
// the beginning
last_outgoing_metadata_.reset();
}
if (foreground_send_transfer_callbacks_.HasObserver(transfer_callback)) {
foreground_send_transfer_callbacks_.RemoveObserver(transfer_callback);
foreground_send_discovery_callbacks_.RemoveObserver(discovery_callback);
} else {
background_send_transfer_callbacks_.RemoveObserver(transfer_callback);
background_send_discovery_callbacks_.RemoveObserver(discovery_callback);
}
// Displays the most recent payload status processed by foreground surfaces on
// background surfaces.
if (!foreground_send_transfer_callbacks_.might_have_observers() &&
last_outgoing_metadata_) {
for (TransferUpdateCallback& background_transfer_callback :
background_send_transfer_callbacks_) {
background_transfer_callback.OnTransferUpdate(
last_outgoing_metadata_->first, last_outgoing_metadata_->second);
}
}
NS_LOG(VERBOSE) << __func__ << ": A SendSurface has been unregistered";
InvalidateSurfaceState();
StopFastInitiationAdvertising();
return StatusCodes::kOk;
}
......@@ -200,6 +297,14 @@ NearbySharingServiceImpl::RegisterReceiveSurface(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(transfer_callback);
DCHECK_NE(state, ReceiveSurfaceState::kUnknown);
if (!process_manager_->IsActiveProfile(profile_)) {
NS_LOG(VERBOSE)
<< __func__
<< ": registerReceiveSurface failed, since profile not active";
return StatusCodes::kError;
}
if (foreground_receive_callbacks_.HasObserver(transfer_callback) ||
background_receive_callbacks_.HasObserver(transfer_callback)) {
NS_LOG(VERBOSE) << __func__
......@@ -272,8 +377,7 @@ NearbySharingServiceImpl::UnregisterReceiveSurface(
NS_LOG(VERBOSE) << __func__ << ": A ReceiveSurface("
<< (is_foreground ? "foreground" : "background")
<< ") has been unregistered";
InvalidateReceiveSurfaceState();
InvalidateSurfaceState();
return StatusCodes::kOk;
}
......@@ -363,6 +467,8 @@ NearbyShareSettings* NearbySharingServiceImpl::GetSettings() {
void NearbySharingServiceImpl::OnNearbyProfileChanged(Profile* profile) {
// TODO(crbug.com/1084576): Notify UI about the new active profile.
NS_LOG(VERBOSE) << __func__ << ": Nearby profile changed to "
<< process_manager_->IsActiveProfile(profile_);
}
void NearbySharingServiceImpl::OnNearbyProcessStarted() {
......@@ -384,7 +490,6 @@ void NearbySharingServiceImpl::OnIncomingConnection(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(connection);
// TODO(crbug/1085068): Handle incoming connection; use CertificateManager
// TODO(himanshujaju) - Update placeholder implementation
ShareTarget share_target;
share_target.is_incoming = true;
......@@ -398,15 +503,128 @@ void NearbySharingServiceImpl::OnIncomingConnection(
ReceiveIntroduction(std::move(share_target), /*token=*/base::nullopt);
}
void NearbySharingServiceImpl::OnEndpointDiscovered(
const std::string& endpoint_id,
const std::vector<uint8_t>& endpoint_info) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!is_scanning_) {
NS_LOG(VERBOSE)
<< __func__
<< ": Ignoring discovered endpoint because we're no longer scanning";
return;
}
process_manager_->GetOrStartNearbySharingDecoder(profile_)
->DecodeAdvertisement(
endpoint_info,
base::BindOnce(
&NearbySharingServiceImpl::OnOutgoingAdvertisementDecoded,
weak_ptr_factory_.GetWeakPtr(), endpoint_id));
}
void NearbySharingServiceImpl::OnOutgoingAdvertisementDecoded(
const std::string& endpoint_id,
sharing::mojom::AdvertisementPtr advertisement) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!advertisement) {
NS_LOG(VERBOSE) << __func__
<< ": Failed to parse discovered advertisement.";
return;
}
// Now we will report endpoints met before in NearbyConnectionsManager.
// Check outgoingShareTargetInfoMap first and pass the same shareTarget if we
// found one.
// Looking for the ShareTarget based on endpoint id.
if (outgoing_share_target_map_.find(endpoint_id) !=
outgoing_share_target_map_.end()) {
return;
}
// Once get the advertisement, first thing to do is to decrypt its device name
// based on its visibility and create a ShareTarget to represent this remote
// device.
base::Optional<ShareTarget> share_target =
CreateShareTarget(endpoint_id, std::move(advertisement),
/*is_incoming=*/false);
if (!share_target) {
NS_LOG(VERBOSE) << __func__
<< ": Failed to convert advertisement to share target from "
"discovered advertisement. Ignoring endpoint.";
return;
}
// Update the endpoint id for the share target.
NS_LOG(VERBOSE) << __func__
<< ": An endpoint has been discovered, with an advertisement "
"containing a valid share target.";
GetOrCreateOutgoingShareTargetInfo(*share_target, endpoint_id)
.set_endpoint_id(endpoint_id);
// Notifies the user that we discovered a device.
for (ShareTargetDiscoveredCallback& discovery_callback :
foreground_send_discovery_callbacks_) {
discovery_callback.OnShareTargetDiscovered(*share_target);
}
for (ShareTargetDiscoveredCallback& discovery_callback :
background_send_discovery_callbacks_) {
discovery_callback.OnShareTargetDiscovered(*share_target);
}
NS_LOG(VERBOSE) << __func__ << ": Reported OnShareTargetDiscovered "
<< (base::Time::Now() - scanning_start_timestamp_);
// TODO(crbug/1108348) CachingManager should cache known and non-external
// share targets.
}
void NearbySharingServiceImpl::OnEndpointLost(const std::string& endpoint_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!is_scanning_) {
NS_LOG(VERBOSE)
<< __func__
<< ": Ignoring lost endpoint because we're no longer scanning";
return;
}
// Remove the share target with this endpoint id.
auto it = outgoing_share_target_map_.find(endpoint_id);
if (it == outgoing_share_target_map_.end()) {
NS_LOG(VERBOSE) << __func__
<< ": Ignoring lost endpoint because we don't have an "
"associated ShareTarget";
return;
}
ShareTarget share_target = std::move(it->second);
outgoing_share_target_info_map_.erase(share_target.id);
outgoing_share_target_map_.erase(it);
for (ShareTargetDiscoveredCallback& discovery_callback :
foreground_send_discovery_callbacks_) {
discovery_callback.OnShareTargetLost(share_target);
}
for (ShareTargetDiscoveredCallback& discovery_callback :
background_send_discovery_callbacks_) {
discovery_callback.OnShareTargetLost(share_target);
}
NS_LOG(VERBOSE) << __func__ << ": Reported onShareTargetLost";
}
void NearbySharingServiceImpl::OnEnabledChanged(bool enabled) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (enabled) {
NS_LOG(VERBOSE) << __func__ << ": Nearby sharing enabled!";
} else {
NS_LOG(VERBOSE) << __func__ << ": Nearby sharing disabled!";
StopAdvertising();
StopScanning();
// TODO(crbug/1085067): Stop discovery.
nearby_connections_manager_->Shutdown();
}
InvalidateSurfaceState();
}
void NearbySharingServiceImpl::FlushMojoForTesting() {
......@@ -437,25 +655,43 @@ bool NearbySharingServiceImpl::IsVisibleInBackground(Visibility visibility) {
}
void NearbySharingServiceImpl::OnVisibilityChanged(Visibility new_visibility) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NS_LOG(VERBOSE) << __func__ << ": Nearby sharing visibility changed to "
<< VisibilityToString(new_visibility);
if (advertising_power_level_ != PowerLevel::kUnknown) {
if (advertising_power_level_ != PowerLevel::kUnknown)
StopAdvertising();
}
InvalidateReceiveSurfaceState();
InvalidateSurfaceState();
}
void NearbySharingServiceImpl::OnDataUsageChanged(DataUsage data_usage) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NS_LOG(VERBOSE) << __func__ << ": Nearby sharing data usage changed to "
<< DataUsageToString(data_usage);
if (advertising_power_level_ != PowerLevel::kUnknown) {
if (advertising_power_level_ != PowerLevel::kUnknown)
StopAdvertising();
}
InvalidateReceiveSurfaceState();
InvalidateSurfaceState();
}
const base::Optional<std::vector<uint8_t>>
NearbySharingServiceImpl::CreateEndpointInfo(
const base::Optional<std::string>& device_name) {
// TODO(nmusgrave) fill values from CertificateManager
std::vector<uint8_t> salt(sharing::Advertisement::kSaltSize, 0);
std::vector<uint8_t> encrypted_metadata_key(
sharing::Advertisement::kMetadataEncryptionKeyHashByteSize, 0);
// TODO(nmusgrave) fill value from local device data manager
std::unique_ptr<sharing::Advertisement> advertisement =
sharing::Advertisement::NewInstance(
std::move(salt), std::move(encrypted_metadata_key), device_name);
if (advertisement) {
return advertisement->ToEndpointInfo();
} else {
return base::nullopt;
}
}
void NearbySharingServiceImpl::OnDeviceNameChanged(
......@@ -557,6 +793,19 @@ bool NearbySharingServiceImpl::IsBluetoothPowered() const {
return IsBluetoothPresent() && bluetooth_adapter_->IsPowered();
}
bool NearbySharingServiceImpl::HasAvailableConnectionMediums() {
// Check if Wifi or Ethernet LAN is off. Advertisements won't work, so
// disable them, unless bluetooth is known to be enabled. Not all platforms
// have bluetooth, so wifi LAN is a platform-agnostic check.
net::NetworkChangeNotifier::ConnectionType connection_type =
net::NetworkChangeNotifier::GetConnectionType();
return IsBluetoothPresent() ||
(connection_type ==
net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI ||
connection_type ==
net::NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET);
}
void NearbySharingServiceImpl::AdapterPresentChanged(
device::BluetoothAdapter* adapter,
bool present) {
......@@ -571,9 +820,14 @@ void NearbySharingServiceImpl::AdapterPoweredChanged(
StopFastInitiationAdvertising();
}
void NearbySharingServiceImpl::InvalidateSurfaceState() {
InvalidateSendSurfaceState();
InvalidateReceiveSurfaceState();
}
void NearbySharingServiceImpl::InvalidateReceiveSurfaceState() {
InvalidateAdvertisingState();
// TODO(crbug/154846208) InvalidateFastInitScan();
// TODO(b/161889067) InvalidateFastInitScan();
}
void NearbySharingServiceImpl::InvalidateAdvertisingState() {
......@@ -585,16 +839,7 @@ void NearbySharingServiceImpl::InvalidateAdvertisingState() {
return;
}
// Check if Wifi or Ethernet LAN is off. Advertisements won't work, so
// disable them, unless bluetooth is known to be enabled. Not all platforms
// have bluetooth, so wifi LAN is a platform-agnostic check.
net::NetworkChangeNotifier::ConnectionType connection_type =
net::NetworkChangeNotifier::GetConnectionType();
if (!IsBluetoothPresent() &&
!(connection_type ==
net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI ||
connection_type ==
net::NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET)) {
if (!HasAvailableConnectionMediums()) {
StopAdvertising();
NS_LOG(VERBOSE)
<< __func__
......@@ -621,7 +866,7 @@ void NearbySharingServiceImpl::InvalidateAdvertisingState() {
return;
}
if (is_transferring_files_) {
if (is_transferring_) {
StopAdvertising();
NS_LOG(VERBOSE)
<< __func__
......@@ -664,10 +909,10 @@ void NearbySharingServiceImpl::InvalidateAdvertisingState() {
if (power_level == advertising_power_level_) {
NS_LOG(VERBOSE)
<< __func__
<< "Failed to advertise because we're already advertising with power"
<< " level " << PowerLevelToString(advertising_power_level_)
<< " and data usage preference "
<< DataUsageToString(settings_.GetDataUsage());
<< ": Failed to advertise because we're already advertising with "
"power level "
<< PowerLevelToString(advertising_power_level_)
<< " and data usage preference " << DataUsageToString(data_usage);
return;
}
......@@ -678,23 +923,23 @@ void NearbySharingServiceImpl::InvalidateAdvertisingState() {
<< DataUsageToString(data_usage);
}
base::Optional<std::string> device_name;
if (foreground_receive_callbacks_.might_have_observers())
device_name = local_device_data_manager_->GetDeviceName();
// Starts advertising through Nearby Connections. Caller is expected to ensure
// |listener| remains valid until StopAdvertising is called.
base::Optional<std::vector<uint8_t>> endpoint_info =
CreateEndpointInfo(device_name);
if (!endpoint_info) {
NS_LOG(VERBOSE) << __func__
<< ": Unable to advertise since could not parse the "
"endpoint info from the advertisement.";
return;
}
// TODO(nmusgrave) fill values from CertificateManager
std::vector<uint8_t> salt(sharing::Advertisement::kSaltSize, 0);
std::vector<uint8_t> encrypted_metadata_key(
sharing::Advertisement::kMetadataEncryptionKeyHashByteSize, 0);
// TODO(nmusgrave) fill value from local device data manager
base::Optional<std::string> device_name = "todo_device_name";
std::vector<uint8_t> endpoint_info =
sharing::Advertisement::NewInstance(std::move(salt),
std::move(encrypted_metadata_key),
std::move(device_name))
->ToEndpointInfo();
nearby_connections_manager_->StartAdvertising(
std::move(endpoint_info),
*endpoint_info,
/* listener= */ this, power_level, data_usage,
base::BindOnce([](NearbyConnectionsManager::ConnectionsStatus status) {
NS_LOG(VERBOSE)
......@@ -722,11 +967,139 @@ void NearbySharingServiceImpl::StopAdvertising() {
}
nearby_connections_manager_->StopAdvertising();
advertising_power_level_ = PowerLevel::kUnknown;
NS_LOG(VERBOSE) << __func__ << ": Advertising has stopped";
}
void NearbySharingServiceImpl::InvalidateSendSurfaceState() {
InvalidateScanningState();
// TODO(b/161889067) InvalidateFastInitAdvertisement();
}
void NearbySharingServiceImpl::InvalidateScanningState() {
// Screen is off. Do no work.
if (ui::CheckIdleStateIsLocked()) {
StopScanning();
NS_LOG(VERBOSE) << __func__
<< ": Stopping discovery because the screen is locked.";
return;
}
if (!HasAvailableConnectionMediums()) {
StopScanning();
NS_LOG(VERBOSE)
<< __func__
<< ": Stopping scanning because both bluetooth and wifi LAN are "
"disabled.";
return;
}
// Nearby Sharing is disabled. Don't advertise.
if (!settings_.GetEnabled()) {
StopScanning();
NS_LOG(VERBOSE)
<< __func__
<< ": Stopping discovery because Nearby Sharing is disabled.";
return;
}
if (is_transferring_ || is_connecting_) {
StopScanning();
NS_LOG(VERBOSE)
<< __func__
<< ": Stopping discovery because we're currently in the midst of a "
"transfer.";
return;
}
if (!foreground_send_transfer_callbacks_.might_have_observers()) {
StopScanning();
NS_LOG(VERBOSE)
<< __func__
<< ": Stopping discovery because no scanning surface has been "
"registered.";
return;
}
// Screen is on, Bluetooth is enabled, and Nearby Sharing is enabled! Start
// discovery.
StartScanning();
}
void NearbySharingServiceImpl::StartScanning() {
if (!settings_.GetEnabled()) {
NS_LOG(VERBOSE) << __func__
<< ": Failed to scan because we're not enabled.";
return;
}
if (ui::CheckIdleStateIsLocked()) {
NS_LOG(VERBOSE) << __func__
<< ": Failed to scan because the user's screen is locked.";
return;
}
if (!HasAvailableConnectionMediums()) {
NS_LOG(VERBOSE) << __func__ << ": Failed to scan because Bluetooth is off.";
return;
}
if (is_scanning_) {
NS_LOG(VERBOSE) << __func__
<< ": Failed to scan because we're currently scanning.";
return;
}
if (!foreground_send_transfer_callbacks_.might_have_observers()) {
NS_LOG(VERBOSE)
<< __func__
<< ": Failed to scan because there's no scanning send surface "
"registered.";
return;
}
scanning_start_timestamp_ = base::Time::Now();
is_scanning_ = true;
InvalidateReceiveSurfaceState();
ClearOutgoingShareTargetInfoMap();
nearby_connections_manager_->StartDiscovery(
/* listener= */ this,
base::BindOnce([](NearbyConnectionsManager::ConnectionsStatus status) {
NS_LOG(VERBOSE) << __func__
<< ": Scanning start attempted over Nearby Connections "
"with result "
<< ConnectionsStatusToString(status);
}));
InvalidateSendSurfaceState();
NS_LOG(VERBOSE) << __func__ << ": Scanning has started";
}
NearbySharingService::StatusCodes NearbySharingServiceImpl::StopScanning() {
if (!is_scanning_) {
NS_LOG(VERBOSE) << __func__
<< ": Failed to stop scanning because weren't scanning.";
return StatusCodes::kStatusAlreadyStopped;
}
nearby_connections_manager_->StopDiscovery();
is_scanning_ = false;
// Note: We don't know if we stopped scanning in preparation to send a file,
// or we stopped because the user left the page. We'll invalidate after a
// short delay.
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&NearbySharingServiceImpl::InvalidateSurfaceState,
weak_ptr_factory_.GetWeakPtr()),
kInvalidateDelay);
NS_LOG(VERBOSE) << __func__ << ": Scanning has stopped.";
return StatusCodes::kOk;
}
void NearbySharingServiceImpl::OnIncomingTransferUpdate(
const ShareTarget& share_target,
TransferMetadata metadata) {
......@@ -1074,17 +1447,6 @@ void NearbySharingServiceImpl::OnIncomingConnectionDisconnected(
UnregisterShareTarget(share_target);
}
void NearbySharingServiceImpl::UnregisterShareTarget(
const ShareTarget& share_target) {
if (share_target.is_incoming) {
incoming_share_target_info_map_.erase(share_target.id);
nearby_connections_manager_->ClearIncomingPayloads();
} else {
// TODO(crbug.com/1084644) - Clear from outgoing map.
}
mutual_acceptance_timeout_alarm_.Cancel();
}
bool NearbySharingServiceImpl::IsOutOfStorage(const ShareTarget& share_target) {
// TODO(himanshujaju) - Check storage space based on file path.
return false;
......@@ -1116,13 +1478,68 @@ NearbyConnection* NearbySharingServiceImpl::GetIncomingConnection(
return GetIncomingShareTargetInfo(share_target).connection();
}
OutgoingShareTargetInfo& NearbySharingServiceImpl::GetOutgoingShareTargetInfo(
const ShareTarget& share_target) {
OutgoingShareTargetInfo&
NearbySharingServiceImpl::GetOrCreateOutgoingShareTargetInfo(
const ShareTarget& share_target,
const std::string& endpoint_id) {
// Default initialize outgoing_share_target_map_ as well, since Share Target
// needs to have fields explicitly set.
outgoing_share_target_map_.emplace(endpoint_id, share_target);
return outgoing_share_target_info_map_[share_target.id];
}
void NearbySharingServiceImpl::ClearOutgoingShareTargetInfoMap() {
// TODO(crbug.com/1085068) close file payloads
outgoing_share_target_info_map_.clear();
outgoing_share_target_map_.clear();
}
base::Optional<ShareTarget> NearbySharingServiceImpl::CreateShareTarget(
const std::string& endpoint_id,
sharing::mojom::AdvertisementPtr advertisement,
bool is_incoming) {
if (!advertisement->device_name) {
// TODO(crbug/1085068): Handle incoming connection; relies upon
// CertificateManager
return base::nullopt;
}
return ShareTarget(*advertisement->device_name, /* image_url= */ GURL(),
nearby_share::mojom::ShareTargetType::kUnknown,
std::vector<TextAttachment>(),
std::vector<FileAttachment>(), is_incoming,
/* full_name= */ base::nullopt, /* is_known= */ false);
}
void NearbySharingServiceImpl::UnregisterShareTarget(
const ShareTarget& share_target) {
if (share_target.is_incoming) {
incoming_share_target_info_map_.erase(share_target.id);
// Clear legacy incoming payloads to release resource
nearby_connections_manager_->ClearIncomingPayloads();
} else {
// Find the endpoint id that matches the given share target.
base::Optional<std::string> endpoint_id;
auto it = outgoing_share_target_info_map_.find(share_target.id);
if (it != outgoing_share_target_info_map_.end())
endpoint_id = it->second.endpoint_id();
// Remove info except for this endpoint id, if present.
ClearOutgoingShareTargetInfoMap();
if (endpoint_id) {
NS_LOG(VERBOSE) << __func__ << ": Unregister share target: "
<< share_target.device_name;
GetOrCreateOutgoingShareTargetInfo(share_target, *endpoint_id)
.set_endpoint_id(*endpoint_id);
} else {
NS_LOG(VERBOSE)
<< __func__
<< ": Cannot unregister share target since none registered: "
<< share_target.device_name;
}
}
mutual_acceptance_timeout_alarm_.Cancel();
}
void NearbySharingServiceImpl::SetAttachmentPayloadId(
......
......@@ -16,6 +16,7 @@
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "chrome/browser/nearby_sharing/attachment.h"
#include "chrome/browser/nearby_sharing/attachment_info.h"
......@@ -23,6 +24,7 @@
#include "chrome/browser/nearby_sharing/common/nearby_share_enums.h"
#include "chrome/browser/nearby_sharing/incoming_frames_reader.h"
#include "chrome/browser/nearby_sharing/incoming_share_target_info.h"
#include "chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager.h"
#include "chrome/browser/nearby_sharing/nearby_connections_manager.h"
#include "chrome/browser/nearby_sharing/nearby_notification_manager.h"
#include "chrome/browser/nearby_sharing/nearby_process_manager.h"
......@@ -52,7 +54,8 @@ class NearbySharingServiceImpl
public nearby_share::mojom::NearbyShareSettingsObserver,
public NearbyProcessManager::Observer,
public device::BluetoothAdapter::Observer,
public NearbyConnectionsManager::IncomingConnectionListener {
public NearbyConnectionsManager::IncomingConnectionListener,
public NearbyConnectionsManager::DiscoveryListener {
public:
explicit NearbySharingServiceImpl(
PrefService* prefs,
......@@ -117,8 +120,15 @@ class NearbySharingServiceImpl
NearbyShareContactManager* GetContactManager() override;
NearbyShareCertificateManager* GetCertificateManager() override;
// NearbyConnectionsManager::DiscoveryListener:
void OnEndpointDiscovered(const std::string& endpoint_id,
const std::vector<uint8_t>& endpoint_info) override;
void OnEndpointLost(const std::string& endpoint_id) override;
private:
bool IsVisibleInBackground(Visibility visibility);
const base::Optional<std::vector<uint8_t>> CreateEndpointInfo(
const base::Optional<std::string>& device_name);
void StartFastInitiationAdvertising();
void StopFastInitiationAdvertising();
void GetBluetoothAdapter();
......@@ -126,12 +136,19 @@ class NearbySharingServiceImpl
void OnStartFastInitiationAdvertising();
void OnStartFastInitiationAdvertisingError();
void OnStopFastInitiationAdvertising();
void OnOutgoingAdvertisementDecoded(
const std::string& endpoint_id,
sharing::mojom::AdvertisementPtr advertisement);
bool IsBluetoothPresent() const;
bool IsBluetoothPowered() const;
bool HasAvailableConnectionMediums();
void AdapterPresentChanged(device::BluetoothAdapter* adapter,
bool present) override;
void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
bool powered) override;
void InvalidateSurfaceState();
void InvalidateSendSurfaceState();
void InvalidateScanningState();
void InvalidateReceiveSurfaceState();
void InvalidateAdvertisingState();
void StopAdvertising();
......@@ -143,6 +160,10 @@ class NearbySharingServiceImpl
NearbyConnection& connection,
sharing::nearby::ConnectionResponseFrame::Status reponse_status);
void Fail(const ShareTarget& share_target, TransferMetadata::Status status);
void StartScanning(
base::Optional<ShareTargetDiscoveredCallback*> discovery_callback);
void StartScanning();
StatusCodes StopScanning();
void OnIncomingTransferUpdate(const ShareTarget& share_target,
TransferMetadata metadata);
void CloseConnection(const ShareTarget& share_target);
......@@ -158,7 +179,6 @@ class NearbySharingServiceImpl
const sharing::mojom::CertificateInfoFramePtr& certificate_frame);
void OnIncomingConnectionDisconnected(const ShareTarget& share_target);
void UnregisterShareTarget(const ShareTarget& share_target);
bool IsOutOfStorage(const ShareTarget& share_target);
void OnIncomingMutualAcceptanceTimeout(const ShareTarget& share_target);
......@@ -166,14 +186,19 @@ class NearbySharingServiceImpl
IncomingShareTargetInfo& GetIncomingShareTargetInfo(
const ShareTarget& share_target);
NearbyConnection* GetIncomingConnection(const ShareTarget& share_target);
OutgoingShareTargetInfo& GetOutgoingShareTargetInfo(
const ShareTarget& share_target);
OutgoingShareTargetInfo& GetOrCreateOutgoingShareTargetInfo(
const ShareTarget& share_target,
const std::string& endpoint_id);
void ClearOutgoingShareTargetInfoMap();
void SetAttachmentPayloadId(const Attachment& attachment, int64_t payload_id);
base::Optional<int64_t> GetAttachmentPayloadId(
const base::UnguessableToken& attachment_id);
base::Optional<ShareTarget> CreateShareTarget(
const std::string& endpoint_id,
sharing::mojom::AdvertisementPtr advertisement,
bool is_incoming);
void UnregisterShareTarget(const ShareTarget& share_target);
PrefService* prefs_;
Profile* profile_;
NearbyShareSettings settings_;
std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager_;
......@@ -193,6 +218,20 @@ class NearbySharingServiceImpl
base::ObserverList<TransferUpdateCallback> foreground_receive_callbacks_;
// A list of foreground receivers.
base::ObserverList<TransferUpdateCallback> background_receive_callbacks_;
// A list of foreground receivers for transfer updates on the send surface.
base::ObserverList<TransferUpdateCallback>
foreground_send_transfer_callbacks_;
// A list of foreground receivers for discovered device updates on the send
// surface.
base::ObserverList<ShareTargetDiscoveredCallback>
foreground_send_discovery_callbacks_;
// A list of background receivers for transfer updates on the send surface.
base::ObserverList<TransferUpdateCallback>
background_send_transfer_callbacks_;
// A list of background receivers for discovered device updates on the send
// surface.
base::ObserverList<ShareTargetDiscoveredCallback>
background_send_discovery_callbacks_;
// Registers the most recent TransferMetadata and ShareTarget used for
// transitioning notifications between foreground surfaces and background
......@@ -207,6 +246,10 @@ class NearbySharingServiceImpl
// incoming share target.
base::flat_map<base::UnguessableToken, IncomingShareTargetInfo>
incoming_share_target_info_map_;
// A map of endpoint id to ShareTarget, where each ShareTarget entry
// directly corresponds to a OutgoingShareTargetInfo entry in
// outgoing_share_target_info_map_;
base::flat_map<std::string, ShareTarget> outgoing_share_target_map_;
// A map of ShareTarget id to OutgoingShareTargetInfo. This lets us know which
// endpoint and public certificate are related to the outgoing share target.
// TODO(crbug/1085068) update this map when handling payloads
......@@ -227,7 +270,13 @@ class NearbySharingServiceImpl
// True if we are currently scanning for remote devices.
bool is_scanning_ = false;
// True if we're currently sending or receiving a file.
bool is_transferring_files_ = false;
bool is_transferring_ = false;
// True if we're currently receiving a file.
bool is_receiving_files_ = false;
// True if we're currently attempting to connect to a remote device.
bool is_connecting_ = false;
// The time scanning began.
base::Time scanning_start_timestamp_;
mojo::Receiver<nearby_share::mojom::NearbyShareSettingsObserver>
settings_receiver_{this};
......
......@@ -23,6 +23,7 @@
#include "chrome/browser/nearby_sharing/nearby_connections_manager.h"
#include "chrome/browser/notifications/notification_display_service_factory.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/services/sharing/public/cpp/advertisement.h"
#include "chrome/services/sharing/public/proto/wire_format.pb.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
......@@ -43,6 +44,8 @@ using testing::Return;
using NetConnectionType = net::NetworkChangeNotifier::ConnectionType;
using SendSurfaceState = NearbySharingService::SendSurfaceState;
class FakeFastInitiationManager : public FastInitiationManager {
public:
explicit FakeFastInitiationManager(
......@@ -112,7 +115,10 @@ class FakeFastInitiationManagerFactory : public FastInitiationManager::Factory {
}
size_t StartAdvertisingCount() {
return last_fake_fast_initiation_manager_->start_advertising_call_count();
return last_fake_fast_initiation_manager_
? last_fake_fast_initiation_manager_
->start_advertising_call_count()
: 0;
}
bool StopAdvertisingCalledAndManagerDestroyed() {
......@@ -139,9 +145,22 @@ class MockTransferUpdateCallback : public TransferUpdateCallback {
(override));
};
class MockShareTargetDiscoveredCallback : public ShareTargetDiscoveredCallback {
public:
~MockShareTargetDiscoveredCallback() override = default;
MOCK_METHOD(void,
OnShareTargetDiscovered,
(ShareTarget shareTarget),
(override));
MOCK_METHOD(void, OnShareTargetLost, (ShareTarget shareTarget), (override));
};
namespace {
const char kServiceId[] = "NearbySharing";
const char kEndpointId[] = "endpoint_id";
const char kDeviceName[] = "device_name";
sharing::mojom::FramePtr GetValidIntroductionFrame() {
std::vector<sharing::mojom::TextMetadataPtr> mojo_text_metadatas;
......@@ -162,6 +181,19 @@ sharing::mojom::FramePtr GetValidIntroductionFrame() {
return mojo_frame;
}
// Length sharing::Advertisement::kSaltSize
const uint8_t kSalt[] = {0x0c, 0x08};
// Length sharing::Advertisement::kMetadataEncryptionKeyHashByteSize
const uint8_t kMetadataEncryptionKeyHashByte[] = {0x07, 0x01, 0x08, 0x08, 0x04,
0x09, 0x06, 0x00, 0x0b, 0x0f,
0x0c, 0x09, 0x03, 0x0d};
const int kEndpointInfoSize =
1 + sharing::Advertisement::kSaltSize +
sharing::Advertisement::kMetadataEncryptionKeyHashByteSize;
const uint8_t kEndpointInfo[] = {0x00, 0x0c, 0x08, 0x07, 0x01, 0x08,
0x08, 0x04, 0x09, 0x06, 0x00, 0x0b,
0x0f, 0x0c, 0x09, 0x03, 0x0d};
class NearbySharingServiceImplTest : public testing::Test {
public:
NearbySharingServiceImplTest() {
......@@ -206,6 +238,8 @@ class NearbySharingServiceImplTest : public testing::Test {
&prefs_, notification_display_service, profile,
base::WrapUnique(fake_nearby_connections_manager_),
&mock_nearby_process_manager_);
NearbyProcessManager& process_manager = NearbyProcessManager::GetInstance();
process_manager.SetActiveProfile(profile);
// Allow the posted task to fetch the BluetoothAdapter to finish.
base::RunLoop().RunUntilIdle();
......@@ -259,6 +293,47 @@ class NearbySharingServiceImplTest : public testing::Test {
net::test::MockNetworkChangeNotifier::Create();
};
struct ValidSendSurfaceTestData {
ui::IdleState idle_state;
bool bluetooth_enabled;
net::NetworkChangeNotifier::ConnectionType connection_type;
} kValidSendSurfaceTestData[] = {
// No network connection, only bluetooth available
{ui::IDLE_STATE_IDLE, true, net::NetworkChangeNotifier::CONNECTION_NONE},
// Wifi available
{ui::IDLE_STATE_IDLE, true, net::NetworkChangeNotifier::CONNECTION_WIFI},
// Ethernet available
{ui::IDLE_STATE_IDLE, true,
net::NetworkChangeNotifier::CONNECTION_ETHERNET},
// 3G available
{ui::IDLE_STATE_IDLE, true, net::NetworkChangeNotifier::CONNECTION_3G},
// Wifi available and no bluetooth
{ui::IDLE_STATE_IDLE, false, net::NetworkChangeNotifier::CONNECTION_WIFI},
// Ethernet available and no bluetooth
{ui::IDLE_STATE_IDLE, false,
net::NetworkChangeNotifier::CONNECTION_ETHERNET}};
class NearbySharingServiceImplValidSendTest
: public NearbySharingServiceImplTest,
public testing::WithParamInterface<ValidSendSurfaceTestData> {};
struct InvalidSendSurfaceTestData {
ui::IdleState idle_state;
bool bluetooth_enabled;
net::NetworkChangeNotifier::ConnectionType connection_type;
} kInvalidSendSurfaceTestData[] = {
// Screen locked
{ui::IDLE_STATE_LOCKED, true, net::NetworkChangeNotifier::CONNECTION_WIFI},
// No network connection and no bluetooth
{ui::IDLE_STATE_IDLE, false, net::NetworkChangeNotifier::CONNECTION_NONE},
// 3G available and no bluetooth
{ui::IDLE_STATE_IDLE, false, net::NetworkChangeNotifier::CONNECTION_3G},
};
class NearbySharingServiceImplInvalidSendTest
: public NearbySharingServiceImplTest,
public testing::WithParamInterface<InvalidSendSurfaceTestData> {};
} // namespace
TEST_F(NearbySharingServiceImplTest, AddsNearbyProcessObserver) {
......@@ -272,79 +347,111 @@ TEST_F(NearbySharingServiceImplTest, RemovesNearbyProcessObserver) {
}
TEST_F(NearbySharingServiceImplTest, DisableNearbyShutdownConnections) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
prefs_.SetBoolean(prefs::kNearbySharingEnabledPrefName, false);
service_->FlushMojoForTesting();
EXPECT_TRUE(fake_nearby_connections_manager_->IsShutdown());
}
TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertising) {
EXPECT_EQ(NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(
/*transfer_callback=*/nullptr,
/*discovery_callback=*/nullptr,
NearbySharingService::SendSurfaceState::kForeground));
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_EQ(1u, fast_initiation_manager_factory_->StartAdvertisingCount());
// Call RegisterSendSurface() a second time and make sure StartAdvertising is
// Call RegisterSendSurface a second time and make sure StartAdvertising is
// not called again.
EXPECT_EQ(NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(
/*transfer_callback=*/nullptr,
/*discovery_callback=*/nullptr,
NearbySharingService::SendSurfaceState::kForeground));
EXPECT_EQ(
NearbySharingService::StatusCodes::kError,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_EQ(1u, fast_initiation_manager_factory_->StartAdvertisingCount());
}
TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertisingError) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
SetFakeFastInitiationManagerFactory(/*should_succeed_on_start=*/false);
EXPECT_EQ(NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(
/*transfer_callback=*/nullptr,
/*discovery_callback=*/nullptr,
NearbySharingService::SendSurfaceState::kForeground));
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
}
TEST_F(NearbySharingServiceImplTest,
BackgroundStartFastInitiationAdvertisingError) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kBackground));
EXPECT_EQ(0u, fast_initiation_manager_factory_->StartAdvertisingCount());
}
TEST_F(NearbySharingServiceImplTest,
StartFastInitiationAdvertising_BluetoothNotPresent) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
is_bluetooth_present_ = false;
EXPECT_EQ(NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(
/*transfer_callback=*/nullptr,
/*discovery_callback=*/nullptr,
NearbySharingService::SendSurfaceState::kForeground));
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
}
TEST_F(NearbySharingServiceImplTest,
StartFastInitiationAdvertising_BluetoothNotPowered) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
is_bluetooth_powered_ = false;
EXPECT_EQ(NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(
/*transfer_callback=*/nullptr,
/*discovery_callback=*/nullptr,
NearbySharingService::SendSurfaceState::kForeground));
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
}
TEST_F(NearbySharingServiceImplTest, StopFastInitiationAdvertising) {
EXPECT_EQ(NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(
/*transfer_callback=*/nullptr,
/*discovery_callback=*/nullptr,
NearbySharingService::SendSurfaceState::kForeground));
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_EQ(1u, fast_initiation_manager_factory_->StartAdvertisingCount());
EXPECT_EQ(NearbySharingService::StatusCodes::kOk,
service_->UnregisterSendSurface(/*transfer_callback=*/nullptr,
/*discovery_callback=*/nullptr));
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->UnregisterSendSurface(&transfer_callback, &discovery_callback));
EXPECT_TRUE(fast_initiation_manager_factory_
->StopAdvertisingCalledAndManagerDestroyed());
}
TEST_F(NearbySharingServiceImplTest,
StopFastInitiationAdvertising_BluetoothBecomesNotPresent) {
EXPECT_EQ(NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(
/*transfer_callback=*/nullptr,
/*discovery_callback=*/nullptr,
NearbySharingService::SendSurfaceState::kForeground));
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
adapter_observer_->AdapterPresentChanged(mock_bluetooth_adapter_.get(),
false);
EXPECT_TRUE(fast_initiation_manager_factory_
......@@ -353,17 +460,300 @@ TEST_F(NearbySharingServiceImplTest,
TEST_F(NearbySharingServiceImplTest,
StopFastInitiationAdvertising_BluetoothBecomesNotPowered) {
EXPECT_EQ(NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(
/*transfer_callback=*/nullptr,
/*discovery_callback=*/nullptr,
NearbySharingService::SendSurfaceState::kForeground));
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
adapter_observer_->AdapterPoweredChanged(mock_bluetooth_adapter_.get(),
false);
EXPECT_TRUE(fast_initiation_manager_factory_
->StopAdvertisingCalledAndManagerDestroyed());
}
TEST_F(NearbySharingServiceImplTest,
RegisterSendSurfaceNoActiveProfilesNotDiscovering) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
NearbyProcessManager& process_manager = NearbyProcessManager::GetInstance();
process_manager.ClearActiveProfile();
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kError,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
}
TEST_F(NearbySharingServiceImplTest,
ForegroundRegisterSendSurfaceStartsDiscovering) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
}
TEST_F(NearbySharingServiceImplTest,
ForegroundRegisterSendSurfaceTwiceKeepsDiscovering) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
EXPECT_EQ(
NearbySharingService::StatusCodes::kError,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
}
TEST_F(NearbySharingServiceImplTest,
RegisterSendSurfaceAlreadyReceivingNotDiscovering) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
// TODO(himanshujaju) is_receiving_files_ should be set to true when
// receiving. Test that WHEN receiving files, THEN below passes.
// EXPECT_EQ(NearbySharingService::StatusCodes::kTransferAlreadyInProgress,
// RegisterSendSurface(SendSurfaceState::kForeground));
// EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering());
// EXPECT_FALSE(fake_nearby_connections_manager_->IsShutdown());
}
TEST_F(NearbySharingServiceImplTest,
BackgroundRegisterSendSurfaceNotDiscovering) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kBackground));
EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering());
EXPECT_FALSE(fake_nearby_connections_manager_->IsShutdown());
}
TEST_F(NearbySharingServiceImplTest,
DifferentSurfaceRegisterSendSurfaceTwiceKeepsDiscovering) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
EXPECT_EQ(
NearbySharingService::StatusCodes::kError,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kBackground));
EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
}
TEST_F(NearbySharingServiceImplTest,
RegisterSendSurfaceEndpointFoundDiscoveryCallbackNotified) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
// Ensure decoder parses a valid endpoint advertisement.
NiceMock<MockNearbySharingDecoder> mock_decoder;
std::vector<uint8_t> endpoint_info(kEndpointInfo,
kEndpointInfo + kEndpointInfoSize);
std::vector<uint8_t> metadata_encryption_key(
kMetadataEncryptionKeyHashByte,
kMetadataEncryptionKeyHashByte +
sharing::Advertisement::kMetadataEncryptionKeyHashByteSize);
std::vector<uint8_t> salt(kSalt, kSalt + sharing::Advertisement::kSaltSize);
EXPECT_CALL(mock_decoder,
DecodeAdvertisement(testing::Eq(endpoint_info), testing::_))
.WillOnce(testing::Invoke(
[&salt, &metadata_encryption_key](
const std::vector<uint8_t>& data,
MockNearbySharingDecoder::DecodeAdvertisementCallback callback) {
sharing::mojom::AdvertisementPtr mojo_adv =
sharing::mojom::Advertisement::New(
salt, metadata_encryption_key, kDeviceName);
std::move(callback).Run(std::move(mojo_adv));
}));
EXPECT_CALL(mock_nearby_process_manager(),
GetOrStartNearbySharingDecoder(testing::_))
.WillRepeatedly(testing::Return(&mock_decoder));
// Start discovering, to ensure a discovery listener is registered.
base::RunLoop run_loop;
MockTransferUpdateCallback transfer_callback;
NiceMock<MockShareTargetDiscoveredCallback> discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
// Discover a new endpoint.
EXPECT_CALL(discovery_callback, OnShareTargetDiscovered)
.WillOnce([&run_loop](ShareTarget share_target) {
EXPECT_EQ(kDeviceName, share_target.device_name);
run_loop.Quit();
});
fake_nearby_connections_manager_->OnEndpointFound(
kEndpointId,
location::nearby::connections::mojom::DiscoveredEndpointInfo::New(
endpoint_info, kServiceId));
run_loop.Run();
// Register another send surface, which will automatically catch up discovered
// endpoints.
base::RunLoop run_loop2;
MockTransferUpdateCallback transfer_callback2;
NiceMock<MockShareTargetDiscoveredCallback> discovery_callback2;
EXPECT_CALL(discovery_callback2, OnShareTargetDiscovered)
.WillOnce([&run_loop2](ShareTarget share_target) {
EXPECT_EQ(kDeviceName, share_target.device_name);
run_loop2.Quit();
});
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback2, &discovery_callback2,
SendSurfaceState::kForeground));
run_loop2.Run();
}
TEST_P(NearbySharingServiceImplValidSendTest,
RegisterSendSurfaceIsDiscovering) {
ui::ScopedSetIdleState idle_state(GetParam().idle_state);
is_bluetooth_present_ = GetParam().bluetooth_enabled;
SetConnectionType(GetParam().connection_type);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
}
INSTANTIATE_TEST_SUITE_P(NearbySharingServiceImplTest,
NearbySharingServiceImplValidSendTest,
testing::ValuesIn(kValidSendSurfaceTestData));
TEST_P(NearbySharingServiceImplInvalidSendTest,
RegisterSendSurfaceNotDiscovering) {
ui::ScopedSetIdleState idle_state(GetParam().idle_state);
is_bluetooth_present_ = GetParam().bluetooth_enabled;
SetConnectionType(GetParam().connection_type);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering());
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering());
EXPECT_FALSE(fake_nearby_connections_manager_->IsShutdown());
}
INSTANTIATE_TEST_SUITE_P(NearbySharingServiceImplTest,
NearbySharingServiceImplInvalidSendTest,
testing::ValuesIn(kInvalidSendSurfaceTestData));
TEST_F(NearbySharingServiceImplTest, DisableFeatureSendSurfaceNotDiscovering) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
prefs_.SetBoolean(prefs::kNearbySharingEnabledPrefName, false);
service_->FlushMojoForTesting();
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering());
EXPECT_TRUE(fake_nearby_connections_manager_->IsShutdown());
}
TEST_F(NearbySharingServiceImplTest,
DisableFeatureSendSurfaceStopsDiscovering) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
prefs_.SetBoolean(prefs::kNearbySharingEnabledPrefName, false);
service_->FlushMojoForTesting();
EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering());
EXPECT_TRUE(fake_nearby_connections_manager_->IsShutdown());
}
TEST_F(NearbySharingServiceImplTest, UnregisterSendSurfaceStopsDiscovering) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->UnregisterSendSurface(&transfer_callback, &discovery_callback));
EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering());
EXPECT_FALSE(fake_nearby_connections_manager_->IsShutdown());
}
TEST_F(NearbySharingServiceImplTest,
UnregisterSendSurfaceDifferentCallbackKeepDiscovering) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kOk,
service_->RegisterSendSurface(&transfer_callback, &discovery_callback,
SendSurfaceState::kForeground));
EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
MockTransferUpdateCallback transfer_callback2;
MockShareTargetDiscoveredCallback discovery_callback2;
EXPECT_EQ(NearbySharingService::StatusCodes::kError,
service_->UnregisterSendSurface(&transfer_callback2,
&discovery_callback2));
EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
}
TEST_F(NearbySharingServiceImplTest, UnregisterSendSurfaceNeverRegistered) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
MockTransferUpdateCallback transfer_callback;
MockShareTargetDiscoveredCallback discovery_callback;
EXPECT_EQ(
NearbySharingService::StatusCodes::kError,
service_->UnregisterSendSurface(&transfer_callback, &discovery_callback));
EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering());
}
TEST_F(NearbySharingServiceImplTest,
ForegroundRegisterReceiveSurfaceIsAdvertising) {
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
......
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