1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/pepper/pepper_network_monitor_host.h"
6
7 #include <stddef.h>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/callback_helpers.h"
12 #include "base/task_runner_util.h"
13 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
14 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
15 #include "content/public/browser/browser_task_traits.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/network_service_instance.h"
18 #include "content/public/common/socket_permission_request.h"
19 #include "ppapi/proxy/ppapi_messages.h"
20 #include "ppapi/shared_impl/private/net_address_private_impl.h"
21 #include "services/network/public/mojom/network_service.mojom.h"
22
23 namespace content {
24
25 namespace {
26
CanUseNetworkMonitor(bool external_plugin,int render_process_id,int render_frame_id)27 bool CanUseNetworkMonitor(bool external_plugin,
28 int render_process_id,
29 int render_frame_id) {
30 DCHECK_CURRENTLY_ON(BrowserThread::UI);
31
32 SocketPermissionRequest request = SocketPermissionRequest(
33 SocketPermissionRequest::NETWORK_STATE, std::string(), 0);
34 return pepper_socket_utils::CanUseSocketAPIs(external_plugin,
35 false /* private_api */,
36 &request,
37 render_process_id,
38 render_frame_id);
39 }
40
OnGetNetworkList(base::OnceCallback<void (const net::NetworkInterfaceList &)> callback,const base::Optional<net::NetworkInterfaceList> & networks)41 void OnGetNetworkList(
42 base::OnceCallback<void(const net::NetworkInterfaceList&)> callback,
43 const base::Optional<net::NetworkInterfaceList>& networks) {
44 DCHECK_CURRENTLY_ON(BrowserThread::UI);
45 GetIOThreadTaskRunner({})->PostTask(
46 FROM_HERE,
47 base::BindOnce(std::move(callback), networks.has_value()
48 ? *networks
49 : net::NetworkInterfaceList()));
50 }
51
GetNetworkList(base::OnceCallback<void (const net::NetworkInterfaceList &)> callback)52 void GetNetworkList(
53 base::OnceCallback<void(const net::NetworkInterfaceList&)> callback) {
54 DCHECK_CURRENTLY_ON(BrowserThread::UI);
55 content::GetNetworkService()->GetNetworkList(
56 net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES,
57 base::BindOnce(&OnGetNetworkList, std::move(callback)));
58 }
59
60 } // namespace
61
PepperNetworkMonitorHost(BrowserPpapiHostImpl * host,PP_Instance instance,PP_Resource resource)62 PepperNetworkMonitorHost::PepperNetworkMonitorHost(BrowserPpapiHostImpl* host,
63 PP_Instance instance,
64 PP_Resource resource)
65 : ResourceHost(host->GetPpapiHost(), instance, resource),
66 network_connection_tracker_(nullptr) {
67 int render_process_id;
68 int render_frame_id;
69 host->GetRenderFrameIDsForInstance(
70 instance, &render_process_id, &render_frame_id);
71
72 GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult(
73 FROM_HERE,
74 base::BindOnce(&CanUseNetworkMonitor, host->external_plugin(),
75 render_process_id, render_frame_id),
76 base::BindOnce(&PepperNetworkMonitorHost::OnPermissionCheckResult,
77 weak_factory_.GetWeakPtr()));
78 }
79
~PepperNetworkMonitorHost()80 PepperNetworkMonitorHost::~PepperNetworkMonitorHost() {
81 if (network_connection_tracker_)
82 network_connection_tracker_->RemoveNetworkConnectionObserver(this);
83 }
84
OnConnectionChanged(network::mojom::ConnectionType type)85 void PepperNetworkMonitorHost::OnConnectionChanged(
86 network::mojom::ConnectionType type) {
87 auto current_type = network::mojom::ConnectionType::CONNECTION_UNKNOWN;
88 network_connection_tracker_->GetConnectionType(¤t_type,
89 base::DoNothing());
90 if (type == current_type)
91 GetAndSendNetworkList();
92 }
93
OnPermissionCheckResult(bool can_use_network_monitor)94 void PepperNetworkMonitorHost::OnPermissionCheckResult(
95 bool can_use_network_monitor) {
96 if (!can_use_network_monitor) {
97 host()->SendUnsolicitedReply(pp_resource(),
98 PpapiPluginMsg_NetworkMonitor_Forbidden());
99 return;
100 }
101
102 GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult(
103 FROM_HERE, base::BindOnce(&content::GetNetworkConnectionTracker),
104 base::BindOnce(&PepperNetworkMonitorHost::SetNetworkConnectionTracker,
105 weak_factory_.GetWeakPtr()));
106 GetAndSendNetworkList();
107 }
108
SetNetworkConnectionTracker(network::NetworkConnectionTracker * network_connection_tracker)109 void PepperNetworkMonitorHost::SetNetworkConnectionTracker(
110 network::NetworkConnectionTracker* network_connection_tracker) {
111 DCHECK_EQ(network_connection_tracker_, nullptr);
112 network_connection_tracker_ = network_connection_tracker;
113 network_connection_tracker_->AddNetworkConnectionObserver(this);
114 }
115
GetAndSendNetworkList()116 void PepperNetworkMonitorHost::GetAndSendNetworkList() {
117 DCHECK_CURRENTLY_ON(BrowserThread::IO);
118 GetUIThreadTaskRunner({})->PostTask(
119 FROM_HERE,
120 base::BindOnce(&GetNetworkList,
121 base::BindOnce(&PepperNetworkMonitorHost::SendNetworkList,
122 weak_factory_.GetWeakPtr())));
123 }
124
SendNetworkList(const net::NetworkInterfaceList & list)125 void PepperNetworkMonitorHost::SendNetworkList(
126 const net::NetworkInterfaceList& list) {
127 DCHECK_CURRENTLY_ON(BrowserThread::IO);
128
129 std::unique_ptr<ppapi::proxy::SerializedNetworkList> list_copy(
130 new ppapi::proxy::SerializedNetworkList(list.size()));
131 for (size_t i = 0; i < list.size(); ++i) {
132 const net::NetworkInterface& network = list.at(i);
133 ppapi::proxy::SerializedNetworkInfo& network_copy = list_copy->at(i);
134 network_copy.name = network.name;
135
136 network_copy.addresses.resize(
137 1, ppapi::NetAddressPrivateImpl::kInvalidNetAddress);
138 bool result = ppapi::NetAddressPrivateImpl::IPEndPointToNetAddress(
139 network.address.bytes(), 0, &(network_copy.addresses[0]));
140 DCHECK(result);
141
142 // TODO(sergeyu): Currently net::NetworkInterfaceList provides
143 // only name and one IP address. Add all other fields and copy
144 // them here.
145 network_copy.type = PP_NETWORKLIST_TYPE_UNKNOWN;
146 network_copy.state = PP_NETWORKLIST_STATE_UP;
147 network_copy.display_name = network.name;
148 network_copy.mtu = 0;
149 }
150 host()->SendUnsolicitedReply(
151 pp_resource(), PpapiPluginMsg_NetworkMonitor_NetworkList(*list_copy));
152 }
153
154 } // namespace content
155