blob: 72ec477f57871b460adf83ea9e1a4bd217d5eebe [file] [log] [blame]
// Copyright (c) 2012 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 "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
#include "base/memory/scoped_refptr.h"
#include "services/network/public/cpp/p2p_param_traits.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/p2p/network_list_observer.h"
#include "third_party/blink/renderer/platform/p2p/socket_client_impl.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
P2PSocketDispatcher::P2PSocketDispatcher()
: main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
network_list_observers_(
new base::ObserverListThreadSafe<blink::NetworkListObserver>()) {}
P2PSocketDispatcher::~P2PSocketDispatcher() {}
void P2PSocketDispatcher::AddNetworkListObserver(
blink::NetworkListObserver* network_list_observer) {
network_list_observers_->AddObserver(network_list_observer);
PostCrossThreadTask(
*main_task_runner_.get(), FROM_HERE,
CrossThreadBindOnce(&P2PSocketDispatcher::RequestNetworkEventsIfNecessary,
scoped_refptr<P2PSocketDispatcher>(this)));
}
void P2PSocketDispatcher::RemoveNetworkListObserver(
blink::NetworkListObserver* network_list_observer) {
network_list_observers_->RemoveObserver(network_list_observer);
}
mojo::SharedRemote<network::mojom::blink::P2PSocketManager>
P2PSocketDispatcher::GetP2PSocketManager() {
base::AutoLock lock(p2p_socket_manager_lock_);
if (!p2p_socket_manager_) {
mojo::PendingRemote<network::mojom::blink::P2PSocketManager>
p2p_socket_manager;
p2p_socket_manager_receiver_ =
p2p_socket_manager.InitWithNewPipeAndPassReceiver();
p2p_socket_manager_ =
mojo::SharedRemote<network::mojom::blink::P2PSocketManager>(
std::move(p2p_socket_manager));
p2p_socket_manager_.set_disconnect_handler(
WTF::Bind(&P2PSocketDispatcher::OnConnectionError,
WTF::Unretained(this)),
main_task_runner_);
}
PostCrossThreadTask(
*main_task_runner_.get(), FROM_HERE,
CrossThreadBindOnce(&P2PSocketDispatcher::RequestInterfaceIfNecessary,
scoped_refptr<P2PSocketDispatcher>(this)));
return p2p_socket_manager_;
}
void P2PSocketDispatcher::NetworkListChanged(
const Vector<net::NetworkInterface>& networks,
const net::IPAddress& default_ipv4_local_address,
const net::IPAddress& default_ipv6_local_address) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
networks_ = networks;
default_ipv4_local_address_ = default_ipv4_local_address;
default_ipv6_local_address_ = default_ipv6_local_address;
// TODO(crbug.com/787254): Remove this helper when network_list_observer.h
// gets moved from blink/public to blink/renderer, and operate over
// WTF::Vector.
std::vector<net::NetworkInterface> copy(networks.size());
for (size_t i = 0; i < networks.size(); i++)
copy[i] = networks[i];
network_list_observers_->Notify(
FROM_HERE, &blink::NetworkListObserver::OnNetworkListChanged,
std::move(copy), default_ipv4_local_address, default_ipv6_local_address);
}
void P2PSocketDispatcher::RequestInterfaceIfNecessary() {
if (!p2p_socket_manager_receiver_.is_valid())
return;
blink::Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
std::move(p2p_socket_manager_receiver_));
}
void P2PSocketDispatcher::RequestNetworkEventsIfNecessary() {
if (network_notification_client_receiver_.is_bound()) {
// TODO(crbug.com/787254): Remove this helper when network_list_observer.h
// gets moved from blink/public to blink/renderer, and operate over
// WTF::Vector.
std::vector<net::NetworkInterface> copy(networks_.size());
for (size_t i = 0; i < networks_.size(); i++)
copy[i] = networks_[i];
network_list_observers_->Notify(
FROM_HERE, &blink::NetworkListObserver::OnNetworkListChanged,
std::move(copy), default_ipv4_local_address_,
default_ipv6_local_address_);
} else {
GetP2PSocketManager()->StartNetworkNotifications(
network_notification_client_receiver_.BindNewPipeAndPassRemote());
}
}
void P2PSocketDispatcher::OnConnectionError() {
base::AutoLock lock(p2p_socket_manager_lock_);
p2p_socket_manager_.reset();
// Attempt to reconnect in case the network service crashed in his being
// restarted.
PostCrossThreadTask(
*main_task_runner_.get(), FROM_HERE,
CrossThreadBindOnce(&P2PSocketDispatcher::ReconnectP2PSocketManager,
scoped_refptr<P2PSocketDispatcher>(this)));
}
void P2PSocketDispatcher::ReconnectP2PSocketManager() {
network_notification_client_receiver_.reset();
GetP2PSocketManager()->StartNetworkNotifications(
network_notification_client_receiver_.BindNewPipeAndPassRemote());
}
} // namespace blink