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

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

Issue 632113003: Pepper: Allow plugins to call PPB_UDP_Socket::SendTo multiple times. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Review comments, document INPROGRESS error in IDL. Created 6 years, 2 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"
(...skipping 13 matching lines...) Expand all
24 #include "ppapi/host/host_message_context.h" 24 #include "ppapi/host/host_message_context.h"
25 #include "ppapi/host/ppapi_host.h" 25 #include "ppapi/host/ppapi_host.h"
26 #include "ppapi/host/resource_host.h" 26 #include "ppapi/host/resource_host.h"
27 #include "ppapi/proxy/ppapi_messages.h" 27 #include "ppapi/proxy/ppapi_messages.h"
28 #include "ppapi/proxy/udp_socket_resource_base.h" 28 #include "ppapi/proxy/udp_socket_resource_base.h"
29 #include "ppapi/shared_impl/private/net_address_private_impl.h" 29 #include "ppapi/shared_impl/private/net_address_private_impl.h"
30 #include "ppapi/shared_impl/socket_option_data.h" 30 #include "ppapi/shared_impl/socket_option_data.h"
31 31
32 using ppapi::NetAddressPrivateImpl; 32 using ppapi::NetAddressPrivateImpl;
33 using ppapi::host::NetErrorToPepperError; 33 using ppapi::host::NetErrorToPepperError;
34 using ppapi::proxy::UDPSocketResourceBase;
34 35
35 namespace { 36 namespace {
36 37
37 size_t g_num_instances = 0; 38 size_t g_num_instances = 0;
38 39
39 } // namespace 40 } // namespace
40 41
41 namespace content { 42 namespace content {
42 43
44 PepperUDPSocketMessageFilter::PendingSend::PendingSend(
45 const net::IPAddressNumber& address,
46 int port,
47 const scoped_refptr<net::IOBufferWithSize>& buffer,
48 const ppapi::host::ReplyMessageContext& context)
49 : address(address), port(port), buffer(buffer), context(context) {
50 }
51
52 PepperUDPSocketMessageFilter::PendingSend::~PendingSend() {
53 }
54
43 PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter( 55 PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter(
44 BrowserPpapiHostImpl* host, 56 BrowserPpapiHostImpl* host,
45 PP_Instance instance, 57 PP_Instance instance,
46 bool private_api) 58 bool private_api)
47 : allow_address_reuse_(false), 59 : allow_address_reuse_(false),
48 allow_broadcast_(false), 60 allow_broadcast_(false),
49 closed_(false), 61 closed_(false),
50 remaining_recv_slots_( 62 remaining_recv_slots_(UDPSocketResourceBase::kPluginReceiveBufferSlots),
51 ppapi::proxy::UDPSocketResourceBase::kPluginReceiveBufferSlots), 63 send_in_progress_(false),
52 external_plugin_(host->external_plugin()), 64 external_plugin_(host->external_plugin()),
53 private_api_(private_api), 65 private_api_(private_api),
54 render_process_id_(0), 66 render_process_id_(0),
55 render_frame_id_(0) { 67 render_frame_id_(0) {
56 ++g_num_instances; 68 ++g_num_instances;
57 DCHECK(host); 69 DCHECK(host);
58 70
59 if (!host->GetRenderFrameIDsForInstance( 71 if (!host->GetRenderFrameIDsForInstance(
60 instance, &render_process_id_, &render_frame_id_)) { 72 instance, &render_process_id_, &render_frame_id_)) {
61 NOTREACHED(); 73 NOTREACHED();
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 if (!socket_.get()) { 148 if (!socket_.get()) {
137 // They only take effect after the socket is bound. 149 // They only take effect after the socket is bound.
138 return PP_ERROR_FAILED; 150 return PP_ERROR_FAILED;
139 } 151 }
140 int32_t integer_value = 0; 152 int32_t integer_value = 0;
141 if (!value.GetInt32(&integer_value) || integer_value <= 0) 153 if (!value.GetInt32(&integer_value) || integer_value <= 0)
142 return PP_ERROR_BADARGUMENT; 154 return PP_ERROR_BADARGUMENT;
143 155
144 int net_result = net::ERR_UNEXPECTED; 156 int net_result = net::ERR_UNEXPECTED;
145 if (name == PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE) { 157 if (name == PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE) {
146 if (integer_value > 158 if (integer_value > UDPSocketResourceBase::kMaxSendBufferSize) {
147 ppapi::proxy::UDPSocketResourceBase::kMaxSendBufferSize) {
148 return PP_ERROR_BADARGUMENT; 159 return PP_ERROR_BADARGUMENT;
149 } 160 }
150 net_result = socket_->SetSendBufferSize(integer_value); 161 net_result = socket_->SetSendBufferSize(integer_value);
151 } else { 162 } else {
152 if (integer_value > 163 if (integer_value > UDPSocketResourceBase::kMaxReceiveBufferSize) {
153 ppapi::proxy::UDPSocketResourceBase::kMaxReceiveBufferSize) {
154 return PP_ERROR_BADARGUMENT; 164 return PP_ERROR_BADARGUMENT;
155 } 165 }
156 net_result = socket_->SetReceiveBufferSize(integer_value); 166 net_result = socket_->SetReceiveBufferSize(integer_value);
157 } 167 }
158 // TODO(wtc): Add error mapping code. 168 // TODO(wtc): Add error mapping code.
159 return (net_result == net::OK) ? PP_OK : PP_ERROR_FAILED; 169 return (net_result == net::OK) ? PP_OK : PP_ERROR_FAILED;
160 } 170 }
161 default: { 171 default: {
162 NOTREACHED(); 172 NOTREACHED();
163 return PP_ERROR_BADARGUMENT; 173 return PP_ERROR_BADARGUMENT;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 DCHECK_CURRENTLY_ON(BrowserThread::IO); 234 DCHECK_CURRENTLY_ON(BrowserThread::IO);
225 Close(); 235 Close();
226 return PP_OK; 236 return PP_OK;
227 } 237 }
228 238
229 int32_t PepperUDPSocketMessageFilter::OnMsgRecvSlotAvailable( 239 int32_t PepperUDPSocketMessageFilter::OnMsgRecvSlotAvailable(
230 const ppapi::host::HostMessageContext* context) { 240 const ppapi::host::HostMessageContext* context) {
231 DCHECK_CURRENTLY_ON(BrowserThread::IO); 241 DCHECK_CURRENTLY_ON(BrowserThread::IO);
232 242
233 if (remaining_recv_slots_ < 243 if (remaining_recv_slots_ <
234 ppapi::proxy::UDPSocketResourceBase::kPluginReceiveBufferSlots) { 244 UDPSocketResourceBase::kPluginReceiveBufferSlots) {
235 remaining_recv_slots_++; 245 remaining_recv_slots_++;
236 } 246 }
237 247
238 if (!recvfrom_buffer_.get() && !closed_ && socket_.get()) { 248 if (!recvfrom_buffer_.get() && !closed_ && socket_.get()) {
239 DCHECK_EQ(1u, remaining_recv_slots_); 249 DCHECK_EQ(1u, remaining_recv_slots_);
240 DoRecvFrom(); 250 DoRecvFrom();
241 } 251 }
242 252
243 return PP_OK; 253 return PP_OK;
244 } 254 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 DoRecvFrom(); 307 DoRecvFrom();
298 } 308 }
299 309
300 void PepperUDPSocketMessageFilter::DoRecvFrom() { 310 void PepperUDPSocketMessageFilter::DoRecvFrom() {
301 DCHECK_CURRENTLY_ON(BrowserThread::IO); 311 DCHECK_CURRENTLY_ON(BrowserThread::IO);
302 DCHECK(!closed_); 312 DCHECK(!closed_);
303 DCHECK(socket_.get()); 313 DCHECK(socket_.get());
304 DCHECK(!recvfrom_buffer_.get()); 314 DCHECK(!recvfrom_buffer_.get());
305 DCHECK_GT(remaining_recv_slots_, 0u); 315 DCHECK_GT(remaining_recv_slots_, 0u);
306 316
307 recvfrom_buffer_ = new net::IOBuffer( 317 recvfrom_buffer_ = new net::IOBuffer(UDPSocketResourceBase::kMaxReadSize);
308 ppapi::proxy::UDPSocketResourceBase::kMaxReadSize);
309 318
310 // Use base::Unretained(this), so that the lifespan of this object doesn't 319 // Use base::Unretained(this), so that the lifespan of this object doesn't
311 // have to last until the callback is called. 320 // have to last until the callback is called.
312 // It is safe to do so because |socket_| is owned by this object. If this 321 // It is safe to do so because |socket_| is owned by this object. If this
313 // object gets destroyed (and so does |socket_|), the callback won't be 322 // object gets destroyed (and so does |socket_|), the callback won't be
314 // called. 323 // called.
315 int net_result = socket_->RecvFrom( 324 int net_result = socket_->RecvFrom(
316 recvfrom_buffer_.get(), 325 recvfrom_buffer_.get(),
317 ppapi::proxy::UDPSocketResourceBase::kMaxReadSize, 326 UDPSocketResourceBase::kMaxReadSize,
318 &recvfrom_address_, 327 &recvfrom_address_,
319 base::Bind(&PepperUDPSocketMessageFilter::OnRecvFromCompleted, 328 base::Bind(&PepperUDPSocketMessageFilter::OnRecvFromCompleted,
320 base::Unretained(this))); 329 base::Unretained(this)));
321 if (net_result != net::ERR_IO_PENDING) 330 if (net_result != net::ERR_IO_PENDING)
322 OnRecvFromCompleted(net_result); 331 OnRecvFromCompleted(net_result);
323 } 332 }
324 333
325 void PepperUDPSocketMessageFilter::DoSendTo( 334 void PepperUDPSocketMessageFilter::DoSendTo(
326 const ppapi::host::ReplyMessageContext& context, 335 const ppapi::host::ReplyMessageContext& context,
327 const std::string& data, 336 const std::string& data,
328 const PP_NetAddress_Private& addr) { 337 const PP_NetAddress_Private& addr) {
329 DCHECK_CURRENTLY_ON(BrowserThread::IO); 338 DCHECK_CURRENTLY_ON(BrowserThread::IO);
330 DCHECK(socket_.get()); 339 DCHECK(socket_.get());
331 340
332 if (closed_ || !socket_.get()) { 341 if (closed_ || !socket_.get()) {
333 SendSendToError(context, PP_ERROR_FAILED); 342 SendSendToError(context, PP_ERROR_FAILED);
334 return; 343 return;
335 } 344 }
336 345
337 if (sendto_buffer_.get()) {
338 SendSendToError(context, PP_ERROR_INPROGRESS);
339 return;
340 }
341
342 size_t num_bytes = data.size(); 346 size_t num_bytes = data.size();
343 if (num_bytes == 0 || 347 if (num_bytes == 0 ||
344 num_bytes > static_cast<size_t>( 348 num_bytes > static_cast<size_t>(UDPSocketResourceBase::kMaxWriteSize)) {
345 ppapi::proxy::UDPSocketResourceBase::kMaxWriteSize)) {
346 // Size of |data| is checked on the plugin side. 349 // Size of |data| is checked on the plugin side.
347 NOTREACHED(); 350 NOTREACHED();
348 SendSendToError(context, PP_ERROR_BADARGUMENT); 351 SendSendToError(context, PP_ERROR_BADARGUMENT);
349 return; 352 return;
350 } 353 }
351 354
352 sendto_buffer_ = new net::IOBufferWithSize(num_bytes);
353 memcpy(sendto_buffer_->data(), data.data(), num_bytes);
354
355 net::IPAddressNumber address; 355 net::IPAddressNumber address;
356 int port; 356 int port;
357 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) { 357 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
358 SendSendToError(context, PP_ERROR_ADDRESS_INVALID); 358 SendSendToError(context, PP_ERROR_ADDRESS_INVALID);
359 return; 359 return;
360 } 360 }
361 361
362 // Please see OnMsgRecvFrom() for the reason why we use base::Unretained(this) 362 scoped_refptr<net::IOBufferWithSize> buffer(
363 new net::IOBufferWithSize(num_bytes));
364 memcpy(buffer->data(), data.data(), num_bytes);
365
366 // Make sure a malicious plugin can't queue up an unlimited number of buffers.
367 if (pending_sends_.size() ==
368 UDPSocketResourceBase::kPluginSendBufferSlots) {
369 SendSendToError(context, PP_ERROR_FAILED);
370 return;
371 }
372
373 pending_sends_.push(PendingSend(address, port, buffer, context));
374 if (!send_in_progress_)
375 DoPendingSend();
dmichael (off chromium) 2014/10/08 22:42:40 I think you can get rid of the if and just always
bbudge 2014/10/09 00:18:26 Done.
376 }
377
378 void PepperUDPSocketMessageFilter::DoPendingSend() {
379 PendingSend pending_send = pending_sends_.front();
380 pending_sends_.pop();
dmichael (off chromium) 2014/10/08 22:42:40 ...but to do my suggestion, you'd want to not pop
bbudge 2014/10/09 00:18:26 Done.
381 // See OnMsgRecvFrom() for the reason why we use base::Unretained(this)
363 // when calling |socket_| methods. 382 // when calling |socket_| methods.
364 int net_result = socket_->SendTo( 383 int net_result = socket_->SendTo(
365 sendto_buffer_.get(), 384 pending_send.buffer.get(),
366 sendto_buffer_->size(), 385 pending_send.buffer->size(),
367 net::IPEndPoint(address, port), 386 net::IPEndPoint(pending_send.address, pending_send.port),
368 base::Bind(&PepperUDPSocketMessageFilter::OnSendToCompleted, 387 base::Bind(&PepperUDPSocketMessageFilter::OnSendToCompleted,
369 base::Unretained(this), 388 base::Unretained(this),
370 context)); 389 pending_send.buffer,
390 pending_send.context));
371 if (net_result != net::ERR_IO_PENDING) 391 if (net_result != net::ERR_IO_PENDING)
372 OnSendToCompleted(context, net_result); 392 OnSendToCompleted(pending_send.buffer, pending_send.context, net_result);
393 else
394 send_in_progress_ = true;
373 } 395 }
374 396
375 void PepperUDPSocketMessageFilter::Close() { 397 void PepperUDPSocketMessageFilter::Close() {
376 DCHECK_CURRENTLY_ON(BrowserThread::IO); 398 DCHECK_CURRENTLY_ON(BrowserThread::IO);
377 if (socket_.get() && !closed_) 399 if (socket_.get() && !closed_)
378 socket_->Close(); 400 socket_->Close();
379 closed_ = true; 401 closed_ = true;
380 } 402 }
381 403
382 void PepperUDPSocketMessageFilter::OnRecvFromCompleted(int net_result) { 404 void PepperUDPSocketMessageFilter::OnRecvFromCompleted(int net_result) {
(...skipping 21 matching lines...) Expand all
404 recvfrom_buffer_ = NULL; 426 recvfrom_buffer_ = NULL;
405 427
406 DCHECK_GT(remaining_recv_slots_, 0u); 428 DCHECK_GT(remaining_recv_slots_, 0u);
407 remaining_recv_slots_--; 429 remaining_recv_slots_--;
408 430
409 if (remaining_recv_slots_ > 0 && !closed_ && socket_.get()) 431 if (remaining_recv_slots_ > 0 && !closed_ && socket_.get())
410 DoRecvFrom(); 432 DoRecvFrom();
411 } 433 }
412 434
413 void PepperUDPSocketMessageFilter::OnSendToCompleted( 435 void PepperUDPSocketMessageFilter::OnSendToCompleted(
436 scoped_refptr<net::IOBufferWithSize> buffer,
dmichael (off chromium) 2014/10/08 22:42:40 I think you won't need this anymore because the he
bbudge 2014/10/09 00:18:26 Done.
414 const ppapi::host::ReplyMessageContext& context, 437 const ppapi::host::ReplyMessageContext& context,
415 int net_result) { 438 int net_result) {
416 DCHECK_CURRENTLY_ON(BrowserThread::IO); 439 DCHECK_CURRENTLY_ON(BrowserThread::IO);
417 DCHECK(sendto_buffer_.get());
418 440
419 int32_t pp_result = NetErrorToPepperError(net_result); 441 int32_t pp_result = NetErrorToPepperError(net_result);
420 if (pp_result < 0) 442 if (pp_result < 0)
421 SendSendToError(context, pp_result); 443 SendSendToError(context, pp_result);
422 else 444 else
423 SendSendToReply(context, PP_OK, pp_result); 445 SendSendToReply(context, PP_OK, pp_result);
424 sendto_buffer_ = NULL; 446
447 send_in_progress_ = false;
448
449 if (!pending_sends_.empty())
450 DoPendingSend();
dmichael (off chromium) 2014/10/08 22:42:40 And you'll want to pop() right before calling this
bbudge 2014/10/09 00:18:26 Done. Very nice simplification. Thanks!
425 } 451 }
426 452
427 void PepperUDPSocketMessageFilter::SendBindReply( 453 void PepperUDPSocketMessageFilter::SendBindReply(
428 const ppapi::host::ReplyMessageContext& context, 454 const ppapi::host::ReplyMessageContext& context,
429 int32_t result, 455 int32_t result,
430 const PP_NetAddress_Private& addr) { 456 const PP_NetAddress_Private& addr) {
431 ppapi::host::ReplyMessageContext reply_context(context); 457 ppapi::host::ReplyMessageContext reply_context(context);
432 reply_context.params.set_result(result); 458 reply_context.params.set_result(result);
433 SendReply(reply_context, PpapiPluginMsg_UDPSocket_BindReply(addr)); 459 SendReply(reply_context, PpapiPluginMsg_UDPSocket_BindReply(addr));
434 } 460 }
(...skipping 28 matching lines...) Expand all
463 NetAddressPrivateImpl::kInvalidNetAddress); 489 NetAddressPrivateImpl::kInvalidNetAddress);
464 } 490 }
465 491
466 void PepperUDPSocketMessageFilter::SendSendToError( 492 void PepperUDPSocketMessageFilter::SendSendToError(
467 const ppapi::host::ReplyMessageContext& context, 493 const ppapi::host::ReplyMessageContext& context,
468 int32_t result) { 494 int32_t result) {
469 SendSendToReply(context, result, 0); 495 SendSendToReply(context, result, 0);
470 } 496 }
471 497
472 } // namespace content 498 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h ('k') | ppapi/api/ppb_udp_socket.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698