// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/services/sharing/sharing_impl.h"
#include <utility>
#include "base/functional/callback.h"
#include "base/metrics/histogram_functions.h"
#include "base/task/sequenced_task_runner.h"
#include "chrome/services/sharing/nearby/decoder/nearby_decoder.h"
#include "chrome/services/sharing/nearby/nearby_connections.h"
#include "chrome/services/sharing/nearby/nearby_presence.h"
#include "chrome/services/sharing/nearby/quick_start_decoder/quick_start_decoder.h"
#include "chromeos/ash/services/nearby/public/mojom/nearby_decoder.mojom.h"
#include "chromeos/ash/services/nearby/public/mojom/quick_start_decoder.mojom.h"
namespace sharing {
SharingImpl::SharingImpl(
mojo::PendingReceiver<mojom::Sharing> receiver,
scoped_refptr<base::SequencedTaskRunner> io_task_runner)
: receiver_(this, std::move(receiver)),
io_task_runner_(std::move(io_task_runner)) {}
SharingImpl::~SharingImpl() {
// No need to call DoShutDown() from the destructor because SharingImpl should
// only be destroyed after SharingImpl::ShutDown() has been called.
CHECK(!nearby_connections_ && !nearby_presence_ && !nearby_decoder_);
}
void SharingImpl::Connect(
NearbyDependenciesPtr deps,
mojo::PendingReceiver<NearbyConnectionsMojom> connections_receiver,
mojo::PendingReceiver<NearbyPresenceMojom> presence_receiver,
mojo::PendingReceiver<::sharing::mojom::NearbySharingDecoder>
decoder_receiver,
mojo::PendingReceiver<ash::quick_start::mojom::QuickStartDecoder>
quick_start_decoder_receiver) {
CHECK(!nearby_connections_);
CHECK(!nearby_presence_);
CHECK(!nearby_decoder_);
nearby::api::LogMessage::Severity min_log_severity = deps->min_log_severity;
InitializeNearbySharedRemotes(std::move(deps));
nearby_presence_ = std::make_unique<NearbyPresence>(
std::move(presence_receiver),
base::BindOnce(&SharingImpl::OnDisconnect, weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kNearbyPresence));
nearby_connections_ = std::make_unique<NearbyConnections>(
std::move(connections_receiver),
nearby_presence_->GetLocalDeviceProvider(), min_log_severity,
base::BindOnce(&SharingImpl::OnDisconnect, weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kNearbyConnections));
nearby_decoder_ = std::make_unique<NearbySharingDecoder>(
std::move(decoder_receiver),
base::BindOnce(&SharingImpl::OnDisconnect, weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kNearbyShareDecoder));
quick_start_decoder_ = std::make_unique<ash::quick_start::QuickStartDecoder>(
std::move(quick_start_decoder_receiver),
base::BindOnce(&SharingImpl::OnDisconnect, weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kQuickStartDecoder));
}
void SharingImpl::ShutDown(ShutDownCallback callback) {
DoShutDown(/*is_expected=*/true);
std::move(callback).Run();
}
void SharingImpl::DoShutDown(bool is_expected) {
nearby::NearbySharedRemotes::SetInstance(nullptr);
if (!nearby_connections_ && !nearby_presence_ && !nearby_decoder_) {
return;
}
nearby_connections_.reset();
nearby_presence_.reset();
nearby_decoder_.reset();
// Leave |receiver_| valid. Its disconnection is reserved as a signal that the
// Sharing utility process has crashed.
}
void SharingImpl::OnDisconnect(MojoDependencyName mojo_dependency_name) {
LOG(WARNING) << "The utility process has detected that the browser process "
"has disconnected from a mojo pipe: ["
<< GetMojoDependencyName(mojo_dependency_name) << "]";
base::UmaHistogramEnumeration(
"Nearby.Connections.UtilityProcessShutdownReason."
"DisconnectedMojoDependency",
mojo_dependency_name);
LOG(ERROR) << "A Sharing process dependency has unexpectedly disconnected.";
DoShutDown(/*is_expected=*/false);
}
void SharingImpl::InitializeNearbySharedRemotes(NearbyDependenciesPtr deps) {
nearby_shared_remotes_ = std::make_unique<nearby::NearbySharedRemotes>();
nearby::NearbySharedRemotes::SetInstance(nearby_shared_remotes_.get());
if (deps->bluetooth_adapter) {
nearby_shared_remotes_->bluetooth_adapter.Bind(
std::move(deps->bluetooth_adapter), io_task_runner_);
nearby_shared_remotes_->bluetooth_adapter.set_disconnect_handler(
base::BindOnce(&SharingImpl::OnDisconnect,
weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kBluetoothAdapter),
base::SequencedTaskRunner::GetCurrentDefault());
}
if (deps->nearby_presence_credential_storage) {
nearby_shared_remotes_->nearby_presence_credential_storage.Bind(
std::move(deps->nearby_presence_credential_storage), io_task_runner_);
nearby_shared_remotes_->nearby_presence_credential_storage
.set_disconnect_handler(
base::BindOnce(
&SharingImpl::OnDisconnect, weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kNearbyPresenceCredentialStorage),
base::SequencedTaskRunner::GetCurrentDefault());
}
nearby_shared_remotes_->socket_manager.Bind(
std::move(deps->webrtc_dependencies->socket_manager), io_task_runner_);
nearby_shared_remotes_->socket_manager.set_disconnect_handler(
base::BindOnce(&SharingImpl::OnDisconnect, weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kSocketManager),
base::SequencedTaskRunner::GetCurrentDefault());
nearby_shared_remotes_->mdns_responder_factory.Bind(
std::move(deps->webrtc_dependencies->mdns_responder_factory),
io_task_runner_);
nearby_shared_remotes_->mdns_responder_factory.set_disconnect_handler(
base::BindOnce(&SharingImpl::OnDisconnect, weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kMdnsResponder),
base::SequencedTaskRunner::GetCurrentDefault());
nearby_shared_remotes_->ice_config_fetcher.Bind(
std::move(deps->webrtc_dependencies->ice_config_fetcher),
io_task_runner_);
nearby_shared_remotes_->ice_config_fetcher.set_disconnect_handler(
base::BindOnce(&SharingImpl::OnDisconnect, weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kIceConfigFetcher),
base::SequencedTaskRunner::GetCurrentDefault());
nearby_shared_remotes_->webrtc_signaling_messenger.Bind(
std::move(deps->webrtc_dependencies->messenger), io_task_runner_);
nearby_shared_remotes_->webrtc_signaling_messenger.set_disconnect_handler(
base::BindOnce(&SharingImpl::OnDisconnect, weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kWebRtcSignalingMessenger),
base::SequencedTaskRunner::GetCurrentDefault());
// TODO(https://crbug.com/1261238): This should always be true when the
// WifiLan feature flag is enabled. Remove when flag is enabled by default.
if (deps->wifilan_dependencies) {
nearby_shared_remotes_->cros_network_config.Bind(
std::move(deps->wifilan_dependencies->cros_network_config),
io_task_runner_);
nearby_shared_remotes_->cros_network_config.set_disconnect_handler(
base::BindOnce(&SharingImpl::OnDisconnect,
weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kCrosNetworkConfig),
base::SequencedTaskRunner::GetCurrentDefault());
nearby_shared_remotes_->firewall_hole_factory.Bind(
std::move(deps->wifilan_dependencies->firewall_hole_factory),
io_task_runner_);
nearby_shared_remotes_->firewall_hole_factory.set_disconnect_handler(
base::BindOnce(&SharingImpl::OnDisconnect,
weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kFirewallHoleFactory),
base::SequencedTaskRunner::GetCurrentDefault());
nearby_shared_remotes_->tcp_socket_factory.Bind(
std::move(deps->wifilan_dependencies->tcp_socket_factory),
io_task_runner_);
nearby_shared_remotes_->tcp_socket_factory.set_disconnect_handler(
base::BindOnce(&SharingImpl::OnDisconnect,
weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kTcpSocketFactory),
base::SequencedTaskRunner::GetCurrentDefault());
if (deps->wifilan_dependencies->mdns_manager) {
nearby_shared_remotes_->mdns_manager.Bind(
std::move(deps->wifilan_dependencies->mdns_manager), io_task_runner_);
nearby_shared_remotes_->mdns_manager.set_disconnect_handler(
base::BindOnce(&SharingImpl::OnDisconnect,
weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kMdnsManager),
base::SequencedTaskRunner::GetCurrentDefault());
}
}
if (deps->wifidirect_dependencies) {
nearby_shared_remotes_->wifi_direct_firewall_hole_factory.Bind(
std::move(deps->wifidirect_dependencies->firewall_hole_factory),
io_task_runner_);
nearby_shared_remotes_->wifi_direct_firewall_hole_factory
.set_disconnect_handler(
base::BindOnce(&SharingImpl::OnDisconnect,
weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kFirewallHoleFactory),
base::SequencedTaskRunner::GetCurrentDefault());
nearby_shared_remotes_->wifi_direct_manager.Bind(
std::move(deps->wifidirect_dependencies->wifi_direct_manager),
io_task_runner_);
nearby_shared_remotes_->wifi_direct_manager.set_disconnect_handler(
base::BindOnce(&SharingImpl::OnDisconnect,
weak_ptr_factory_.GetWeakPtr(),
MojoDependencyName::kWifiDirectManager),
base::SequencedTaskRunner::GetCurrentDefault());
}
}
std::string SharingImpl::GetMojoDependencyName(
MojoDependencyName dependency_name) {
switch (dependency_name) {
case MojoDependencyName::kNearbyConnections:
return "Nearby Connections";
case MojoDependencyName::kBluetoothAdapter:
return "Bluetooth Adapter";
case MojoDependencyName::kSocketManager:
return "Socket Manager";
case MojoDependencyName::kMdnsResponder:
return "MDNS Responder";
case MojoDependencyName::kIceConfigFetcher:
return "ICE Config Fetcher";
case MojoDependencyName::kWebRtcSignalingMessenger:
return "WebRTC Signaling Messenger";
case MojoDependencyName::kCrosNetworkConfig:
return "CrOS Network Config";
case MojoDependencyName::kFirewallHoleFactory:
return "Firewall Hole Factory";
case MojoDependencyName::kTcpSocketFactory:
return "TCP socket Factory";
case MojoDependencyName::kNearbyPresence:
return "Nearby Presence";
case MojoDependencyName::kNearbyShareDecoder:
return "Decoder";
case MojoDependencyName::kQuickStartDecoder:
return "Quick Start Decoder";
case MojoDependencyName::kNearbyPresenceCredentialStorage:
return "Nearby Presence Credential Storage";
case MojoDependencyName::kWifiDirectManager:
return "WiFi Direct Manager";
case MojoDependencyName::kMdnsManager:
return "mDNS Manager";
}
}
} // namespace sharing