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(&current_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