Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc

Issue 704133005: Pepper: Add support for multicast in PPB_UDPSocket API (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Properly check for permissions, restore check for API version 1.2 so all trybots are happy Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter. h" 5 #include "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter. h"
6 6
7 #include <cstring> 7 #include <cstring>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" 11 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
12 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h" 12 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
13 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/content_browser_client.h"
14 #include "content/public/common/process_type.h" 15 #include "content/public/common/process_type.h"
15 #include "content/public/common/socket_permission_request.h" 16 #include "content/public/common/socket_permission_request.h"
16 #include "ipc/ipc_message_macros.h" 17 #include "ipc/ipc_message_macros.h"
17 #include "net/base/io_buffer.h" 18 #include "net/base/io_buffer.h"
18 #include "net/base/net_errors.h" 19 #include "net/base/net_errors.h"
19 #include "net/base/rand_callback.h" 20 #include "net/base/rand_callback.h"
20 #include "net/udp/udp_socket.h" 21 #include "net/udp/udp_socket.h"
21 #include "ppapi/c/pp_errors.h" 22 #include "ppapi/c/pp_errors.h"
22 #include "ppapi/c/private/ppb_net_address_private.h" 23 #include "ppapi/c/private/ppb_net_address_private.h"
23 #include "ppapi/host/dispatch_host_message.h" 24 #include "ppapi/host/dispatch_host_message.h"
(...skipping 29 matching lines...) Expand all
53 PepperUDPSocketMessageFilter::PendingSend::~PendingSend() { 54 PepperUDPSocketMessageFilter::PendingSend::~PendingSend() {
54 } 55 }
55 56
56 PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter( 57 PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter(
57 BrowserPpapiHostImpl* host, 58 BrowserPpapiHostImpl* host,
58 PP_Instance instance, 59 PP_Instance instance,
59 bool private_api) 60 bool private_api)
60 : socket_options_(0), 61 : socket_options_(0),
61 rcvbuf_size_(0), 62 rcvbuf_size_(0),
62 sndbuf_size_(0), 63 sndbuf_size_(0),
64 multicast_ttl_(0),
63 closed_(false), 65 closed_(false),
64 remaining_recv_slots_(UDPSocketResourceBase::kPluginReceiveBufferSlots), 66 remaining_recv_slots_(UDPSocketResourceBase::kPluginReceiveBufferSlots),
65 external_plugin_(host->external_plugin()), 67 external_plugin_(host->external_plugin()),
66 private_api_(private_api), 68 private_api_(private_api),
67 render_process_id_(0), 69 render_process_id_(0),
68 render_frame_id_(0) { 70 render_frame_id_(0) {
69 ++g_num_instances; 71 ++g_num_instances;
70 DCHECK(host); 72 DCHECK(host);
71 73
72 if (!host->GetRenderFrameIDsForInstance( 74 if (!host->GetRenderFrameIDsForInstance(
(...skipping 15 matching lines...) Expand all
88 scoped_refptr<base::TaskRunner> 90 scoped_refptr<base::TaskRunner>
89 PepperUDPSocketMessageFilter::OverrideTaskRunnerForMessage( 91 PepperUDPSocketMessageFilter::OverrideTaskRunnerForMessage(
90 const IPC::Message& message) { 92 const IPC::Message& message) {
91 switch (message.type()) { 93 switch (message.type()) {
92 case PpapiHostMsg_UDPSocket_SetOption::ID: 94 case PpapiHostMsg_UDPSocket_SetOption::ID:
93 case PpapiHostMsg_UDPSocket_Close::ID: 95 case PpapiHostMsg_UDPSocket_Close::ID:
94 case PpapiHostMsg_UDPSocket_RecvSlotAvailable::ID: 96 case PpapiHostMsg_UDPSocket_RecvSlotAvailable::ID:
95 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); 97 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
96 case PpapiHostMsg_UDPSocket_Bind::ID: 98 case PpapiHostMsg_UDPSocket_Bind::ID:
97 case PpapiHostMsg_UDPSocket_SendTo::ID: 99 case PpapiHostMsg_UDPSocket_SendTo::ID:
100 case PpapiHostMsg_UDPSocket_JoinGroup::ID:
101 case PpapiHostMsg_UDPSocket_LeaveGroup::ID:
98 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); 102 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
99 } 103 }
100 return NULL; 104 return NULL;
101 } 105 }
102 106
103 int32_t PepperUDPSocketMessageFilter::OnResourceMessageReceived( 107 int32_t PepperUDPSocketMessageFilter::OnResourceMessageReceived(
104 const IPC::Message& msg, 108 const IPC::Message& msg,
105 ppapi::host::HostMessageContext* context) { 109 ppapi::host::HostMessageContext* context) {
106 PPAPI_BEGIN_MESSAGE_MAP(PepperUDPSocketMessageFilter, msg) 110 PPAPI_BEGIN_MESSAGE_MAP(PepperUDPSocketMessageFilter, msg)
107 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_SetOption, 111 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_SetOption,
108 OnMsgSetOption) 112 OnMsgSetOption)
109 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_Bind, OnMsgBind) 113 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_Bind, OnMsgBind)
110 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_SendTo, 114 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_SendTo,
111 OnMsgSendTo) 115 OnMsgSendTo)
112 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_UDPSocket_Close, 116 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_UDPSocket_Close,
113 OnMsgClose) 117 OnMsgClose)
114 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( 118 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
115 PpapiHostMsg_UDPSocket_RecvSlotAvailable, OnMsgRecvSlotAvailable) 119 PpapiHostMsg_UDPSocket_RecvSlotAvailable, OnMsgRecvSlotAvailable)
120 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_JoinGroup,
121 OnMsgJoinGroup)
122 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_LeaveGroup,
123 OnMsgLeaveGroup)
116 PPAPI_END_MESSAGE_MAP() 124 PPAPI_END_MESSAGE_MAP()
117 return PP_ERROR_FAILED; 125 return PP_ERROR_FAILED;
118 } 126 }
119 127
120 int32_t PepperUDPSocketMessageFilter::OnMsgSetOption( 128 int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
121 const ppapi::host::HostMessageContext* context, 129 const ppapi::host::HostMessageContext* context,
122 PP_UDPSocket_Option name, 130 PP_UDPSocket_Option name,
123 const ppapi::SocketOptionData& value) { 131 const ppapi::SocketOptionData& value) {
124 DCHECK_CURRENTLY_ON(BrowserThread::IO); 132 DCHECK_CURRENTLY_ON(BrowserThread::IO);
125 133
(...skipping 18 matching lines...) Expand all
144 } else { 152 } else {
145 socket_options_ &= ~SOCKET_OPTION_ADDRESS_REUSE; 153 socket_options_ &= ~SOCKET_OPTION_ADDRESS_REUSE;
146 } 154 }
147 return PP_OK; 155 return PP_OK;
148 } 156 }
149 case PP_UDPSOCKET_OPTION_BROADCAST: { 157 case PP_UDPSOCKET_OPTION_BROADCAST: {
150 bool boolean_value = false; 158 bool boolean_value = false;
151 if (!value.GetBool(&boolean_value)) 159 if (!value.GetBool(&boolean_value))
152 return PP_ERROR_BADARGUMENT; 160 return PP_ERROR_BADARGUMENT;
153 161
154 // If the socket is already connected, proxy the value to TCPSocket. 162 // If the socket is already bound, proxy the value to UDPSocket.
155 if (socket_.get()) 163 if (socket_.get())
156 return NetErrorToPepperError(socket_->SetBroadcast(boolean_value)); 164 return NetErrorToPepperError(socket_->SetBroadcast(boolean_value));
157 165
158 // UDPSocket instance is not yet created, so remember the value here. 166 // UDPSocket instance is not yet created, so remember the value here.
159 if (boolean_value) { 167 if (boolean_value) {
160 socket_options_ |= SOCKET_OPTION_BROADCAST; 168 socket_options_ |= SOCKET_OPTION_BROADCAST;
161 } else { 169 } else {
162 socket_options_ &= ~SOCKET_OPTION_BROADCAST; 170 socket_options_ &= ~SOCKET_OPTION_BROADCAST;
163 } 171 }
164 return PP_OK; 172 return PP_OK;
165 } 173 }
166 case PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE: { 174 case PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE: {
167 int32_t integer_value = 0; 175 int32_t integer_value = 0;
168 if (!value.GetInt32(&integer_value) || 176 if (!value.GetInt32(&integer_value) ||
169 integer_value <= 0 || 177 integer_value <= 0 ||
170 integer_value > 178 integer_value >
171 ppapi::proxy::UDPSocketResourceBase::kMaxSendBufferSize) 179 ppapi::proxy::UDPSocketResourceBase::kMaxSendBufferSize)
172 return PP_ERROR_BADARGUMENT; 180 return PP_ERROR_BADARGUMENT;
173 181
174 // If the socket is already connected, proxy the value to UDPSocket. 182 // If the socket is already bound, proxy the value to UDPSocket.
175 if (socket_.get()) { 183 if (socket_.get()) {
176 return NetErrorToPepperError( 184 return NetErrorToPepperError(
177 socket_->SetSendBufferSize(integer_value)); 185 socket_->SetSendBufferSize(integer_value));
178 } 186 }
179 187
180 // UDPSocket instance is not yet created, so remember the value here. 188 // UDPSocket instance is not yet created, so remember the value here.
181 socket_options_ |= SOCKET_OPTION_SNDBUF_SIZE; 189 socket_options_ |= SOCKET_OPTION_SNDBUF_SIZE;
182 sndbuf_size_ = integer_value; 190 sndbuf_size_ = integer_value;
183 return PP_OK; 191 return PP_OK;
184 } 192 }
185 case PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE: { 193 case PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE: {
186 int32_t integer_value = 0; 194 int32_t integer_value = 0;
187 if (!value.GetInt32(&integer_value) || 195 if (!value.GetInt32(&integer_value) ||
188 integer_value <= 0 || 196 integer_value <= 0 ||
189 integer_value > 197 integer_value >
190 ppapi::proxy::UDPSocketResourceBase::kMaxReceiveBufferSize) 198 ppapi::proxy::UDPSocketResourceBase::kMaxReceiveBufferSize)
191 return PP_ERROR_BADARGUMENT; 199 return PP_ERROR_BADARGUMENT;
192 200
193 // If the socket is already connected, proxy the value to UDPSocket. 201 // If the socket is already bound, proxy the value to UDPSocket.
194 if (socket_.get()) { 202 if (socket_.get()) {
195 return NetErrorToPepperError( 203 return NetErrorToPepperError(
196 socket_->SetReceiveBufferSize(integer_value)); 204 socket_->SetReceiveBufferSize(integer_value));
197 } 205 }
198 206
199 // UDPSocket instance is not yet created, so remember the value here. 207 // UDPSocket instance is not yet created, so remember the value here.
200 socket_options_ |= SOCKET_OPTION_RCVBUF_SIZE; 208 socket_options_ |= SOCKET_OPTION_RCVBUF_SIZE;
201 rcvbuf_size_ = integer_value; 209 rcvbuf_size_ = integer_value;
202 return PP_OK; 210 return PP_OK;
203 } 211 }
212 case PP_UDPSOCKET_OPTION_MULTICAST_LOOP: {
213 PP_NetAddress_Private any_addr;
214 NetAddressPrivateImpl::CreateNetAddressPrivateFromAnyAddress(
215 PP_FromBool(false), &any_addr);
bbudge 2015/03/07 00:52:21 s/PP_FromBool(false)/PP_FALSE
etrunko 2015/03/09 17:24:30 Done.
216 if (!CanUseUDPMulticastAPI(any_addr))
217 return PP_ERROR_NOACCESS;
218
219 bool boolean_value = false;
220 if (!value.GetBool(&boolean_value))
221 return PP_ERROR_BADARGUMENT;
222
223 // If the socket is already bound, proxy the value to UDPSocket.
224 if (socket_)
225 return NetErrorToPepperError(
226 socket_->SetMulticastLoopbackMode(boolean_value));
227
228 // UDPSocket instance is not yet created, so remember the value here.
229 if (boolean_value) {
230 socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
231 } else {
232 socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
233 }
234 return PP_OK;
235 }
236 case PP_UDPSOCKET_OPTION_MULTICAST_TTL: {
237 PP_NetAddress_Private any_addr;
238 NetAddressPrivateImpl::CreateNetAddressPrivateFromAnyAddress(
239 PP_FromBool(false), &any_addr);
bbudge 2015/03/07 00:52:21 PP_FALSE
etrunko 2015/03/09 17:24:30 Done.
240 if (!CanUseUDPMulticastAPI(any_addr))
241 return PP_ERROR_NOACCESS;
242
243 int32_t integer_value = 0;
244 if (!value.GetInt32(&integer_value) ||
245 integer_value < 0 || integer_value > 255)
246 return PP_ERROR_BADARGUMENT;
247
248 // If the socket is already bound, proxy the value to UDPSocket.
249 if (socket_)
250 return NetErrorToPepperError(
251 socket_->SetMulticastTimeToLive(integer_value));
252
253 // UDPSocket instance is not yet created, so remember the value here.
254 socket_options_ |= SOCKET_OPTION_MULTICAST_TTL;
255 multicast_ttl_ = integer_value;
256 return PP_OK;
257 }
204 default: { 258 default: {
205 NOTREACHED(); 259 NOTREACHED();
206 return PP_ERROR_BADARGUMENT; 260 return PP_ERROR_BADARGUMENT;
207 } 261 }
208 } 262 }
209 } 263 }
210 264
211 int32_t PepperUDPSocketMessageFilter::OnMsgBind( 265 int32_t PepperUDPSocketMessageFilter::OnMsgBind(
212 const ppapi::host::HostMessageContext* context, 266 const ppapi::host::HostMessageContext* context,
213 const PP_NetAddress_Private& addr) { 267 const PP_NetAddress_Private& addr) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 } 333 }
280 334
281 if (!recvfrom_buffer_.get() && !closed_ && socket_.get()) { 335 if (!recvfrom_buffer_.get() && !closed_ && socket_.get()) {
282 DCHECK_EQ(1u, remaining_recv_slots_); 336 DCHECK_EQ(1u, remaining_recv_slots_);
283 DoRecvFrom(); 337 DoRecvFrom();
284 } 338 }
285 339
286 return PP_OK; 340 return PP_OK;
287 } 341 }
288 342
343 int32_t PepperUDPSocketMessageFilter::OnMsgJoinGroup(
344 const ppapi::host::HostMessageContext* context,
345 const PP_NetAddress_Private& addr) {
346 DCHECK_CURRENTLY_ON(BrowserThread::UI);
347
348 if (!CanUseUDPMulticastAPI(addr))
349 return PP_ERROR_NOACCESS;
350
351 if (!socket_)
352 return PP_ERROR_FAILED;
353
354 net::IPAddressNumber group;
355 uint16 port;
356
357 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &group, &port))
358 return PP_ERROR_ADDRESS_INVALID;
359
360 return NetErrorToPepperError(socket_->JoinGroup(group));
361 }
362
363 int32_t PepperUDPSocketMessageFilter::OnMsgLeaveGroup(
364 const ppapi::host::HostMessageContext* context,
365 const PP_NetAddress_Private& addr) {
366 DCHECK_CURRENTLY_ON(BrowserThread::UI);
367
368 if (!CanUseUDPMulticastAPI(addr))
369 return PP_ERROR_NOACCESS;
370
371 if (!socket_)
372 return PP_ERROR_FAILED;
373
374 net::IPAddressNumber group;
375 uint16 port;
376
377 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &group, &port))
378 return PP_ERROR_ADDRESS_INVALID;
379
380 return NetErrorToPepperError(socket_->LeaveGroup(group));
381 }
382
289 void PepperUDPSocketMessageFilter::DoBind( 383 void PepperUDPSocketMessageFilter::DoBind(
290 const ppapi::host::ReplyMessageContext& context, 384 const ppapi::host::ReplyMessageContext& context,
291 const PP_NetAddress_Private& addr) { 385 const PP_NetAddress_Private& addr) {
292 DCHECK_CURRENTLY_ON(BrowserThread::IO); 386 DCHECK_CURRENTLY_ON(BrowserThread::IO);
293 387
294 if (closed_ || socket_.get()) { 388 if (closed_ || socket_.get()) {
295 SendBindError(context, PP_ERROR_FAILED); 389 SendBindError(context, PP_ERROR_FAILED);
296 return; 390 return;
297 } 391 }
298 392
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 return; 430 return;
337 } 431 }
338 } 432 }
339 if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE) { 433 if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE) {
340 int net_result = socket->SetReceiveBufferSize(rcvbuf_size_); 434 int net_result = socket->SetReceiveBufferSize(rcvbuf_size_);
341 if (net_result != net::OK) { 435 if (net_result != net::OK) {
342 SendBindError(context, NetErrorToPepperError(net_result)); 436 SendBindError(context, NetErrorToPepperError(net_result));
343 return; 437 return;
344 } 438 }
345 } 439 }
440 if (socket_options_ & SOCKET_OPTION_MULTICAST_LOOP) {
441 int net_result = socket->SetMulticastLoopbackMode(true);
442 if (net_result != net::OK) {
443 SendBindError(context, NetErrorToPepperError(net_result));
444 return;
445 }
446 }
447 if (socket_options_ & SOCKET_OPTION_MULTICAST_TTL) {
448 int net_result = socket->SetMulticastInterface(multicast_ttl_);
449 if (net_result != net::OK) {
450 SendBindError(context, NetErrorToPepperError(net_result));
451 return;
452 }
453 }
346 454
347 { 455 {
348 int net_result = socket->Bind(end_point); 456 int net_result = socket->Bind(end_point);
349 if (net_result != net::OK) { 457 if (net_result != net::OK) {
350 SendBindError(context, NetErrorToPepperError(net_result)); 458 SendBindError(context, NetErrorToPepperError(net_result));
351 return; 459 return;
352 } 460 }
353 } 461 }
354 462
355 net::IPEndPoint bound_address; 463 net::IPEndPoint bound_address;
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 SendRecvFromResult(result, std::string(), 671 SendRecvFromResult(result, std::string(),
564 NetAddressPrivateImpl::kInvalidNetAddress); 672 NetAddressPrivateImpl::kInvalidNetAddress);
565 } 673 }
566 674
567 void PepperUDPSocketMessageFilter::SendSendToError( 675 void PepperUDPSocketMessageFilter::SendSendToError(
568 const ppapi::host::ReplyMessageContext& context, 676 const ppapi::host::ReplyMessageContext& context,
569 int32_t result) { 677 int32_t result) {
570 SendSendToReply(context, result, 0); 678 SendSendToReply(context, result, 0);
571 } 679 }
572 680
681 bool PepperUDPSocketMessageFilter::CanUseUDPMulticastAPI(
682 const PP_NetAddress_Private& addr) {
683 // Check for Dev API.
684 // TODO(etrunko): remove check when Multicast API reaches beta/stable.
685 // https://crbug.com/464452
686 ContentBrowserClient* content_renderer_client = GetContentClient()->browser();
bbudge 2015/03/07 00:52:21 nit: content_browser_client or content_client.
etrunko 2015/03/09 17:24:30 Done.
687 if (!content_renderer_client->IsPluginAllowedToUseDevChannelAPIs(NULL,
688 GURL())) {
689 return false;
bbudge 2015/03/07 00:52:21 It would be better if we could return PP_ERROR_FAI
etrunko 2015/03/09 17:24:30 Done.
690 }
691
692 // Check for plugin permissions.
693 SocketPermissionRequest request =
694 pepper_socket_utils::CreateSocketPermissionRequest(
695 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, addr);
696 if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
697 private_api_,
698 &request,
699 render_process_id_,
700 render_frame_id_)) {
701 return false;
702 }
703
704 return true;
705 }
706
573 } // namespace content 707 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698