 Chromium Code Reviews
 Chromium Code Reviews Issue 704133005:
  Pepper: Add support for multicast in PPB_UDPSocket API  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 704133005:
  Pepper: Add support for multicast in PPB_UDPSocket API  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| Index: content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc | 
| diff --git a/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc | 
| index 50221d9222c4f7dfe3e7f2c87e3218020c864d48..ff47e1c14f9251ec52f5a0eb295c6d119667f446 100644 | 
| --- a/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc | 
| +++ b/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc | 
| @@ -11,6 +11,7 @@ | 
| #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" | 
| #include "content/browser/renderer_host/pepper/pepper_socket_utils.h" | 
| #include "content/public/browser/browser_thread.h" | 
| +#include "content/public/browser/content_browser_client.h" | 
| #include "content/public/common/process_type.h" | 
| #include "content/public/common/socket_permission_request.h" | 
| #include "ipc/ipc_message_macros.h" | 
| @@ -60,6 +61,7 @@ PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter( | 
| : socket_options_(0), | 
| rcvbuf_size_(0), | 
| sndbuf_size_(0), | 
| + multicast_ttl_(0), | 
| closed_(false), | 
| remaining_recv_slots_(UDPSocketResourceBase::kPluginReceiveBufferSlots), | 
| external_plugin_(host->external_plugin()), | 
| @@ -95,6 +97,8 @@ PepperUDPSocketMessageFilter::OverrideTaskRunnerForMessage( | 
| return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); | 
| case PpapiHostMsg_UDPSocket_Bind::ID: | 
| case PpapiHostMsg_UDPSocket_SendTo::ID: | 
| + case PpapiHostMsg_UDPSocket_JoinGroup::ID: | 
| + case PpapiHostMsg_UDPSocket_LeaveGroup::ID: | 
| return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); | 
| } | 
| return NULL; | 
| @@ -113,6 +117,10 @@ int32_t PepperUDPSocketMessageFilter::OnResourceMessageReceived( | 
| OnMsgClose) | 
| PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( | 
| PpapiHostMsg_UDPSocket_RecvSlotAvailable, OnMsgRecvSlotAvailable) | 
| + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_JoinGroup, | 
| + OnMsgJoinGroup) | 
| + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_LeaveGroup, | 
| + OnMsgLeaveGroup) | 
| PPAPI_END_MESSAGE_MAP() | 
| return PP_ERROR_FAILED; | 
| } | 
| @@ -151,7 +159,7 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption( | 
| if (!value.GetBool(&boolean_value)) | 
| return PP_ERROR_BADARGUMENT; | 
| - // If the socket is already connected, proxy the value to TCPSocket. | 
| + // If the socket is already bound, proxy the value to UDPSocket. | 
| if (socket_.get()) | 
| return NetErrorToPepperError(socket_->SetBroadcast(boolean_value)); | 
| @@ -171,7 +179,7 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption( | 
| ppapi::proxy::UDPSocketResourceBase::kMaxSendBufferSize) | 
| return PP_ERROR_BADARGUMENT; | 
| - // If the socket is already connected, proxy the value to UDPSocket. | 
| + // If the socket is already bound, proxy the value to UDPSocket. | 
| if (socket_.get()) { | 
| return NetErrorToPepperError( | 
| socket_->SetSendBufferSize(integer_value)); | 
| @@ -190,7 +198,7 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption( | 
| ppapi::proxy::UDPSocketResourceBase::kMaxReceiveBufferSize) | 
| return PP_ERROR_BADARGUMENT; | 
| - // If the socket is already connected, proxy the value to UDPSocket. | 
| + // If the socket is already bound, proxy the value to UDPSocket. | 
| if (socket_.get()) { | 
| return NetErrorToPepperError( | 
| socket_->SetReceiveBufferSize(integer_value)); | 
| @@ -201,6 +209,40 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption( | 
| rcvbuf_size_ = integer_value; | 
| return PP_OK; | 
| } | 
| + case PP_UDPSOCKET_OPTION_MULTICAST_LOOP: { | 
| + bool boolean_value = false; | 
| + if (!value.GetBool(&boolean_value)) | 
| + return PP_ERROR_BADARGUMENT; | 
| + | 
| + // If the socket is already bound, proxy the value to UDPSocket. | 
| + if (socket_) | 
| 
bbudge
2015/03/10 01:30:50
See comment below: this should be:
if (socket_ &&
 | 
| + return NetErrorToPepperError( | 
| + socket_->SetMulticastLoopbackMode(boolean_value)); | 
| + | 
| + // UDPSocket instance is not yet created, so remember the value here. | 
| + if (boolean_value) { | 
| + socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP; | 
| + } else { | 
| + socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP; | 
| + } | 
| + return PP_OK; | 
| + } | 
| + case PP_UDPSOCKET_OPTION_MULTICAST_TTL: { | 
| + int32_t integer_value = 0; | 
| + if (!value.GetInt32(&integer_value) || | 
| + integer_value < 0 || integer_value > 255) | 
| + return PP_ERROR_BADARGUMENT; | 
| + | 
| + // If the socket is already bound, proxy the value to UDPSocket. | 
| + if (socket_) | 
| + return NetErrorToPepperError( | 
| + socket_->SetMulticastTimeToLive(integer_value)); | 
| + | 
| + // UDPSocket instance is not yet created, so remember the value here. | 
| + socket_options_ |= SOCKET_OPTION_MULTICAST_TTL; | 
| + multicast_ttl_ = integer_value; | 
| + return PP_OK; | 
| + } | 
| default: { | 
| NOTREACHED(); | 
| return PP_ERROR_BADARGUMENT; | 
| @@ -214,6 +256,15 @@ int32_t PepperUDPSocketMessageFilter::OnMsgBind( | 
| DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| DCHECK(context); | 
| + if (socket_options_ & SOCKET_OPTION_MULTICAST_TTL|| | 
| + socket_options_ & SOCKET_OPTION_MULTICAST_LOOP) { | 
| + PP_NetAddress_Private any_addr; | 
| + NetAddressPrivateImpl::GetAnyAddress(PP_FALSE, &any_addr); | 
| + int32_t ret = CanUseMulticastAPI(any_addr); | 
| + if (ret != PP_OK) | 
| + return ret; | 
| + } | 
| 
bbudge
2015/03/10 01:30:50
Sorry if I wasn't clear in my earlier comment. Thi
 | 
| + | 
| SocketPermissionRequest request = | 
| pepper_socket_utils::CreateSocketPermissionRequest( | 
| SocketPermissionRequest::UDP_BIND, addr); | 
| @@ -286,6 +337,48 @@ int32_t PepperUDPSocketMessageFilter::OnMsgRecvSlotAvailable( | 
| return PP_OK; | 
| } | 
| +int32_t PepperUDPSocketMessageFilter::OnMsgJoinGroup( | 
| + const ppapi::host::HostMessageContext* context, | 
| + const PP_NetAddress_Private& addr) { | 
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| + | 
| + int32_t ret = CanUseMulticastAPI(addr); | 
| + if (ret != PP_OK) | 
| + return ret; | 
| + | 
| + if (!socket_) | 
| + return PP_ERROR_FAILED; | 
| + | 
| + net::IPAddressNumber group; | 
| + uint16 port; | 
| + | 
| + if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &group, &port)) | 
| + return PP_ERROR_ADDRESS_INVALID; | 
| + | 
| + return NetErrorToPepperError(socket_->JoinGroup(group)); | 
| +} | 
| + | 
| +int32_t PepperUDPSocketMessageFilter::OnMsgLeaveGroup( | 
| + const ppapi::host::HostMessageContext* context, | 
| + const PP_NetAddress_Private& addr) { | 
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| + | 
| + int32_t ret = CanUseMulticastAPI(addr); | 
| + if (ret != PP_OK) | 
| + return ret; | 
| + | 
| + if (!socket_) | 
| + return PP_ERROR_FAILED; | 
| + | 
| + net::IPAddressNumber group; | 
| + uint16 port; | 
| + | 
| + if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &group, &port)) | 
| + return PP_ERROR_ADDRESS_INVALID; | 
| + | 
| + return NetErrorToPepperError(socket_->LeaveGroup(group)); | 
| +} | 
| + | 
| void PepperUDPSocketMessageFilter::DoBind( | 
| const ppapi::host::ReplyMessageContext& context, | 
| const PP_NetAddress_Private& addr) { | 
| @@ -343,6 +436,20 @@ void PepperUDPSocketMessageFilter::DoBind( | 
| return; | 
| } | 
| } | 
| + if (socket_options_ & SOCKET_OPTION_MULTICAST_LOOP) { | 
| + int net_result = socket->SetMulticastLoopbackMode(true); | 
| + if (net_result != net::OK) { | 
| + SendBindError(context, NetErrorToPepperError(net_result)); | 
| + return; | 
| + } | 
| + } | 
| + if (socket_options_ & SOCKET_OPTION_MULTICAST_TTL) { | 
| + int net_result = socket->SetMulticastInterface(multicast_ttl_); | 
| + if (net_result != net::OK) { | 
| + SendBindError(context, NetErrorToPepperError(net_result)); | 
| + return; | 
| + } | 
| + } | 
| { | 
| int net_result = socket->Bind(end_point); | 
| @@ -570,4 +677,30 @@ void PepperUDPSocketMessageFilter::SendSendToError( | 
| SendSendToReply(context, result, 0); | 
| } | 
| +int32_t PepperUDPSocketMessageFilter::CanUseMulticastAPI( | 
| + const PP_NetAddress_Private& addr) { | 
| + // Check for Dev API. | 
| + // TODO(etrunko): remove check when Multicast API reaches beta/stable. | 
| + // https://crbug.com/464452 | 
| + ContentBrowserClient* content_browser_client = GetContentClient()->browser(); | 
| + if (!content_browser_client->IsPluginAllowedToUseDevChannelAPIs(nullptr, | 
| + GURL())) { | 
| + return PP_ERROR_FAILED; | 
| + } | 
| + | 
| + // Check for plugin permissions. | 
| + SocketPermissionRequest request = | 
| + pepper_socket_utils::CreateSocketPermissionRequest( | 
| + SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, addr); | 
| + if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, | 
| + private_api_, | 
| + &request, | 
| + render_process_id_, | 
| + render_frame_id_)) { | 
| + return PP_ERROR_NOACCESS; | 
| + } | 
| + | 
| + return PP_OK; | 
| +} | 
| + | 
| } // namespace content |