1 // Copyright (c) 2012 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_message_filter.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/callback.h" 10 #include "base/compiler_specific.h" 11 #include "base/files/file_path.h" 12 #include "base/logging.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/threading/sequenced_worker_pool.h" 16 #include "base/threading/worker_pool.h" 17 #include "build/build_config.h" 18 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h" 19 #include "content/browser/renderer_host/pepper/pepper_tcp_socket.h" 20 #include "content/browser/renderer_host/render_process_host_impl.h" 21 #include "content/browser/renderer_host/render_view_host_impl.h" 22 #include "content/common/pepper_messages.h" 23 #include "content/public/browser/browser_context.h" 24 #include "content/public/browser/browser_thread.h" 25 #include "content/public/browser/content_browser_client.h" 26 #include "content/public/browser/resource_context.h" 27 #include "content/public/common/content_client.h" 28 #include "net/base/address_family.h" 29 #include "net/base/address_list.h" 30 #include "net/base/host_port_pair.h" 31 #include "net/base/sys_addrinfo.h" 32 #include "net/cert/cert_verifier.h" 33 #include "ppapi/c/pp_errors.h" 34 #include "ppapi/c/private/ppb_net_address_private.h" 35 #include "ppapi/proxy/ppapi_messages.h" 36 #include "ppapi/shared_impl/api_id.h" 37 #include "ppapi/shared_impl/private/net_address_private_impl.h" 38 #include "ppapi/shared_impl/socket_option_data.h" 39 40 using ppapi::NetAddressPrivateImpl; 41 42 namespace content { 43 namespace { 44 45 const size_t kMaxSocketsAllowed = 1024; 46 const uint32 kInvalidSocketID = 0; 47 48 } // namespace 49 50 PepperMessageFilter::PepperMessageFilter(int process_id, 51 BrowserContext* browser_context) 52 : plugin_type_(PLUGIN_TYPE_IN_PROCESS), 53 permissions_(), 54 process_id_(process_id), 55 external_plugin_render_view_id_(0), 56 resource_context_(browser_context->GetResourceContext()), 57 host_resolver_(NULL), 58 next_socket_id_(1) { 59 DCHECK(browser_context); 60 // Keep BrowserContext data in FILE-thread friendly storage. 61 browser_path_ = browser_context->GetPath(); 62 incognito_ = browser_context->IsOffTheRecord(); 63 DCHECK(resource_context_); 64 } 65 66 PepperMessageFilter::PepperMessageFilter( 67 const ppapi::PpapiPermissions& permissions, 68 net::HostResolver* host_resolver) 69 : plugin_type_(PLUGIN_TYPE_OUT_OF_PROCESS), 70 permissions_(permissions), 71 process_id_(0), 72 external_plugin_render_view_id_(0), 73 resource_context_(NULL), 74 host_resolver_(host_resolver), 75 next_socket_id_(1), 76 incognito_(false) { 77 DCHECK(host_resolver); 78 } 79 80 PepperMessageFilter::PepperMessageFilter( 81 const ppapi::PpapiPermissions& permissions, 82 net::HostResolver* host_resolver, 83 int process_id, 84 int render_view_id) 85 : plugin_type_(PLUGIN_TYPE_EXTERNAL_PLUGIN), 86 permissions_(permissions), 87 process_id_(process_id), 88 external_plugin_render_view_id_(render_view_id), 89 resource_context_(NULL), 90 host_resolver_(host_resolver), 91 next_socket_id_(1) { 92 DCHECK(host_resolver); 93 } 94 95 bool PepperMessageFilter::OnMessageReceived(const IPC::Message& msg, 96 bool* message_was_ok) { 97 bool handled = true; 98 IPC_BEGIN_MESSAGE_MAP_EX(PepperMessageFilter, msg, *message_was_ok) 99 // TCP messages. 100 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Create, OnTCPCreate) 101 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_CreatePrivate, 102 OnTCPCreatePrivate) 103 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Connect, OnTCPConnect) 104 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress, 105 OnTCPConnectWithNetAddress) 106 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_SSLHandshake, 107 OnTCPSSLHandshake) 108 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Read, OnTCPRead) 109 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Write, OnTCPWrite) 110 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Disconnect, OnTCPDisconnect) 111 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_SetOption, OnTCPSetOption) 112 113 // NetworkMonitor messages. 114 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBNetworkMonitor_Start, 115 OnNetworkMonitorStart) 116 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBNetworkMonitor_Stop, 117 OnNetworkMonitorStop) 118 119 // X509 certificate messages. 120 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBX509Certificate_ParseDER, 121 OnX509CertificateParseDER); 122 123 IPC_MESSAGE_UNHANDLED(handled = false) 124 IPC_END_MESSAGE_MAP_EX() 125 return handled; 126 } 127 128 void PepperMessageFilter::OnIPAddressChanged() { 129 GetAndSendNetworkList(); 130 } 131 132 net::HostResolver* PepperMessageFilter::GetHostResolver() { 133 return resource_context_ ? 134 resource_context_->GetHostResolver() : host_resolver_; 135 } 136 137 net::CertVerifier* PepperMessageFilter::GetCertVerifier() { 138 if (!cert_verifier_) 139 cert_verifier_.reset(net::CertVerifier::CreateDefault()); 140 141 return cert_verifier_.get(); 142 } 143 144 net::TransportSecurityState* PepperMessageFilter::GetTransportSecurityState() { 145 if (!transport_security_state_) 146 transport_security_state_.reset(new net::TransportSecurityState); 147 148 return transport_security_state_.get(); 149 } 150 151 uint32 PepperMessageFilter::AddAcceptedTCPSocket( 152 int32 routing_id, 153 uint32 plugin_dispatcher_id, 154 net::StreamSocket* socket) { 155 scoped_ptr<net::StreamSocket> s(socket); 156 157 uint32 tcp_socket_id = GenerateSocketID(); 158 if (tcp_socket_id != kInvalidSocketID) { 159 // Currently all TCP sockets created this way correspond to 160 // PPB_TCPSocket_Private. 161 tcp_sockets_[tcp_socket_id] = linked_ptr<PepperTCPSocket>( 162 new PepperTCPSocket(this, 163 routing_id, 164 plugin_dispatcher_id, 165 tcp_socket_id, 166 s.release(), 167 true /* private_api */)); 168 } 169 return tcp_socket_id; 170 } 171 172 PepperMessageFilter::~PepperMessageFilter() { 173 if (!network_monitor_ids_.empty()) 174 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 175 } 176 177 void PepperMessageFilter::OnTCPCreate(int32 routing_id, 178 uint32 plugin_dispatcher_id, 179 uint32* socket_id) { 180 CreateTCPSocket(routing_id, plugin_dispatcher_id, false, socket_id); 181 } 182 183 void PepperMessageFilter::OnTCPCreatePrivate(int32 routing_id, 184 uint32 plugin_dispatcher_id, 185 uint32* socket_id) { 186 CreateTCPSocket(routing_id, plugin_dispatcher_id, true, socket_id); 187 } 188 189 void PepperMessageFilter::OnTCPConnect(int32 routing_id, 190 uint32 socket_id, 191 const std::string& host, 192 uint16_t port) { 193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 194 TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); 195 if (iter == tcp_sockets_.end()) { 196 NOTREACHED(); 197 return; 198 } 199 200 // This is only supported by PPB_TCPSocket_Private. 201 if (!iter->second->private_api()) { 202 NOTREACHED(); 203 return; 204 } 205 206 content::SocketPermissionRequest params( 207 content::SocketPermissionRequest::TCP_CONNECT, host, port); 208 BrowserThread::PostTaskAndReplyWithResult( 209 BrowserThread::UI, FROM_HERE, 210 base::Bind(&PepperMessageFilter::CanUseSocketAPIs, this, 211 routing_id, params, true /* private_api */), 212 base::Bind(&PepperMessageFilter::DoTCPConnect, this, 213 routing_id, socket_id, host, port)); 214 } 215 216 void PepperMessageFilter::DoTCPConnect(int32 routing_id, 217 uint32 socket_id, 218 const std::string& host, 219 uint16_t port, 220 bool allowed) { 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 222 TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); 223 if (iter == tcp_sockets_.end()) { 224 // Due to current permission check process (IO -> UI -> IO) some 225 // calls to the TCP socket interface can be intermixed (like 226 // Connect and Close). So, NOTREACHED() is not appropriate here. 227 return; 228 } 229 230 if (routing_id == iter->second->routing_id() && allowed) 231 iter->second->Connect(host, port); 232 else 233 iter->second->SendConnectACKError(PP_ERROR_NOACCESS); 234 } 235 236 void PepperMessageFilter::OnTCPConnectWithNetAddress( 237 int32 routing_id, 238 uint32 socket_id, 239 const PP_NetAddress_Private& net_addr) { 240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 241 TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); 242 if (iter == tcp_sockets_.end()) { 243 NOTREACHED(); 244 return; 245 } 246 247 content::SocketPermissionRequest params = 248 pepper_socket_utils::CreateSocketPermissionRequest( 249 content::SocketPermissionRequest::TCP_CONNECT, net_addr); 250 BrowserThread::PostTaskAndReplyWithResult( 251 BrowserThread::UI, FROM_HERE, 252 base::Bind(&PepperMessageFilter::CanUseSocketAPIs, this, 253 routing_id, params, iter->second->private_api()), 254 base::Bind(&PepperMessageFilter::DoTCPConnectWithNetAddress, this, 255 routing_id, socket_id, net_addr)); 256 } 257 258 void PepperMessageFilter::DoTCPConnectWithNetAddress( 259 int32 routing_id, 260 uint32 socket_id, 261 const PP_NetAddress_Private& net_addr, 262 bool allowed) { 263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 264 TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); 265 if (iter == tcp_sockets_.end()) { 266 // Due to current permission check process (IO -> UI -> IO) some 267 // calls to the TCP socket interface can be intermixed (like 268 // ConnectWithNetAddress and Close). So, NOTREACHED() is not 269 // appropriate here. 270 return; 271 } 272 273 if (routing_id == iter->second->routing_id() && allowed) 274 iter->second->ConnectWithNetAddress(net_addr); 275 else 276 iter->second->SendConnectACKError(PP_ERROR_NOACCESS); 277 } 278 279 void PepperMessageFilter::OnTCPSSLHandshake( 280 uint32 socket_id, 281 const std::string& server_name, 282 uint16_t server_port, 283 const std::vector<std::vector<char> >& trusted_certs, 284 const std::vector<std::vector<char> >& untrusted_certs) { 285 TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); 286 if (iter == tcp_sockets_.end()) { 287 NOTREACHED(); 288 return; 289 } 290 291 // This is only supported by PPB_TCPSocket_Private. 292 if (!iter->second->private_api()) { 293 NOTREACHED(); 294 return; 295 } 296 297 iter->second->SSLHandshake(server_name, server_port, trusted_certs, 298 untrusted_certs); 299 } 300 301 void PepperMessageFilter::OnTCPRead(uint32 socket_id, int32_t bytes_to_read) { 302 TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); 303 if (iter == tcp_sockets_.end()) { 304 NOTREACHED(); 305 return; 306 } 307 308 iter->second->Read(bytes_to_read); 309 } 310 311 void PepperMessageFilter::OnTCPWrite(uint32 socket_id, 312 const std::string& data) { 313 TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); 314 if (iter == tcp_sockets_.end()) { 315 NOTREACHED(); 316 return; 317 } 318 319 iter->second->Write(data); 320 } 321 322 void PepperMessageFilter::OnTCPDisconnect(uint32 socket_id) { 323 TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); 324 if (iter == tcp_sockets_.end()) { 325 NOTREACHED(); 326 return; 327 } 328 329 // Destroying the TCPSocket instance will cancel any pending completion 330 // callback. From this point on, there won't be any messages associated with 331 // this socket sent to the plugin side. 332 tcp_sockets_.erase(iter); 333 } 334 335 void PepperMessageFilter::OnTCPSetOption(uint32 socket_id, 336 PP_TCPSocket_Option name, 337 const ppapi::SocketOptionData& value) { 338 TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); 339 if (iter == tcp_sockets_.end()) { 340 NOTREACHED(); 341 return; 342 } 343 344 iter->second->SetOption(name, value); 345 } 346 347 void PepperMessageFilter::OnNetworkMonitorStart(uint32 plugin_dispatcher_id) { 348 // Support all in-process plugins, and ones with "private" permissions. 349 if (plugin_type_ != PLUGIN_TYPE_IN_PROCESS && 350 !permissions_.HasPermission(ppapi::PERMISSION_PRIVATE)) { 351 return; 352 } 353 354 if (network_monitor_ids_.empty()) 355 net::NetworkChangeNotifier::AddIPAddressObserver(this); 356 357 network_monitor_ids_.insert(plugin_dispatcher_id); 358 GetAndSendNetworkList(); 359 } 360 361 void PepperMessageFilter::OnNetworkMonitorStop(uint32 plugin_dispatcher_id) { 362 // Support all in-process plugins, and ones with "private" permissions. 363 if (plugin_type_ != PLUGIN_TYPE_IN_PROCESS && 364 !permissions_.HasPermission(ppapi::PERMISSION_PRIVATE)) { 365 return; 366 } 367 368 network_monitor_ids_.erase(plugin_dispatcher_id); 369 if (network_monitor_ids_.empty()) 370 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 371 } 372 373 void PepperMessageFilter::OnX509CertificateParseDER( 374 const std::vector<char>& der, 375 bool* succeeded, 376 ppapi::PPB_X509Certificate_Fields* result) { 377 if (der.size() == 0) 378 *succeeded = false; 379 *succeeded = PepperTCPSocket::GetCertificateFields(&der[0], der.size(), 380 result); 381 } 382 383 uint32 PepperMessageFilter::GenerateSocketID() { 384 // TODO(yzshen): Change to use Pepper resource ID as socket ID. 385 // 386 // Generate a socket ID. For each process which sends us socket requests, IDs 387 // of living sockets must be unique, to each socket type. 388 // 389 // However, it is safe to generate IDs based on the internal state of a single 390 // PepperSocketMessageHandler object, because for each plugin or renderer 391 // process, there is at most one PepperMessageFilter (in other words, at most 392 // one PepperSocketMessageHandler) talking to it. 393 if (tcp_sockets_.size() >= kMaxSocketsAllowed) 394 return kInvalidSocketID; 395 396 uint32 socket_id = kInvalidSocketID; 397 do { 398 // Although it is unlikely, make sure that we won't cause any trouble when 399 // the counter overflows. 400 socket_id = next_socket_id_++; 401 } while (socket_id == kInvalidSocketID || 402 tcp_sockets_.find(socket_id) != tcp_sockets_.end()); 403 404 return socket_id; 405 } 406 407 bool PepperMessageFilter::CanUseSocketAPIs( 408 int32 render_id, 409 const content::SocketPermissionRequest& params, 410 bool private_api) { 411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 412 413 // External plugins always get their own PepperMessageFilter, initialized with 414 // a render view id. Use this instead of the one that came with the message, 415 // which is actually an API ID. 416 bool external_plugin = false; 417 if (plugin_type_ == PLUGIN_TYPE_EXTERNAL_PLUGIN) { 418 external_plugin = true; 419 render_id = external_plugin_render_view_id_; 420 } 421 422 RenderViewHostImpl* render_view_host = 423 RenderViewHostImpl::FromID(process_id_, render_id); 424 425 return pepper_socket_utils::CanUseSocketAPIs(external_plugin, 426 private_api, 427 params, 428 render_view_host); 429 } 430 431 void PepperMessageFilter::GetAndSendNetworkList() { 432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 433 434 BrowserThread::PostBlockingPoolTask( 435 FROM_HERE, base::Bind(&PepperMessageFilter::DoGetNetworkList, this)); 436 } 437 438 void PepperMessageFilter::DoGetNetworkList() { 439 scoped_ptr<net::NetworkInterfaceList> list(new net::NetworkInterfaceList()); 440 net::GetNetworkList(list.get()); 441 BrowserThread::PostTask( 442 BrowserThread::IO, FROM_HERE, 443 base::Bind(&PepperMessageFilter::SendNetworkList, 444 this, base::Passed(&list))); 445 } 446 447 void PepperMessageFilter::SendNetworkList( 448 scoped_ptr<net::NetworkInterfaceList> list) { 449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 450 451 scoped_ptr< ::ppapi::NetworkList> list_copy( 452 new ::ppapi::NetworkList(list->size())); 453 for (size_t i = 0; i < list->size(); ++i) { 454 const net::NetworkInterface& network = list->at(i); 455 ::ppapi::NetworkInfo& network_copy = list_copy->at(i); 456 network_copy.name = network.name; 457 458 network_copy.addresses.resize(1, NetAddressPrivateImpl::kInvalidNetAddress); 459 bool result = NetAddressPrivateImpl::IPEndPointToNetAddress( 460 network.address, 0, &(network_copy.addresses[0])); 461 DCHECK(result); 462 463 // TODO(sergeyu): Currently net::NetworkInterfaceList provides 464 // only name and one IP address. Add all other fields and copy 465 // them here. 466 network_copy.type = PP_NETWORKLIST_UNKNOWN; 467 network_copy.state = PP_NETWORKLIST_UP; 468 network_copy.display_name = network.name; 469 network_copy.mtu = 0; 470 } 471 for (NetworkMonitorIdSet::iterator it = network_monitor_ids_.begin(); 472 it != network_monitor_ids_.end(); ++it) { 473 Send(new PpapiMsg_PPBNetworkMonitor_NetworkList( 474 ppapi::API_ID_PPB_NETWORKMANAGER_PRIVATE, *it, *list_copy)); 475 } 476 } 477 478 void PepperMessageFilter::CreateTCPSocket(int32 routing_id, 479 uint32 plugin_dispatcher_id, 480 bool private_api, 481 uint32* socket_id) { 482 *socket_id = GenerateSocketID(); 483 if (*socket_id == kInvalidSocketID) 484 return; 485 486 tcp_sockets_[*socket_id] = linked_ptr<PepperTCPSocket>( 487 new PepperTCPSocket(this, routing_id, plugin_dispatcher_id, *socket_id, 488 private_api)); 489 } 490 491 } // namespace content 492