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

Unified Diff: content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc

Issue 22923014: TCPSockets are switched to the new Pepper proxy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync. Created 7 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2ec8c545177ebbc11d97e1fe76ed058a7fc572d5
--- /dev/null
+++ b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -0,0 +1,648 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#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_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/common/socket_permission_request.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/dns/single_request_host_resolver.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/client_socket_handle.h"
+#include "net/socket/ssl_client_socket.h"
+#include "net/socket/tcp_client_socket.h"
+#include "ppapi/c/private/ppb_net_address_private.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/error_conversion.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/tcp_socket_resource_base.h"
+#include "ppapi/shared_impl/private/net_address_private_impl.h"
+
+using ppapi::NetAddressPrivateImpl;
+using ppapi::host::NetErrorToPepperError;
+using ppapi::proxy::TCPSocketResourceBase;
+
+namespace {
+
+size_t g_num_instances = 0;
+
+} // namespace
+
+namespace content {
+
+PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ bool private_api)
+ : external_plugin_(host->external_plugin()),
+ private_api_(private_api),
+ render_process_id_(0),
+ render_view_id_(0),
+ state_(STATE_BEFORE_CONNECT),
+ end_of_file_reached_(false),
+ ssl_context_helper_(host->ssl_context_helper()) {
+ DCHECK(host);
+ ++g_num_instances;
+ if (!host->GetRenderViewIDsForInstance(instance,
+ &render_process_id_,
+ &render_view_id_)) {
+ NOTREACHED();
+ }
+}
+
+PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ bool private_api,
+ net::StreamSocket* socket)
+ : external_plugin_(host->external_plugin()),
+ private_api_(private_api),
+ render_process_id_(0),
+ render_view_id_(0),
+ state_(STATE_CONNECTED),
+ end_of_file_reached_(false),
+ socket_(socket),
+ ssl_context_helper_(host->ssl_context_helper()) {
+ DCHECK(host);
+ ++g_num_instances;
+ if (!host->GetRenderViewIDsForInstance(instance,
+ &render_process_id_,
+ &render_view_id_)) {
+ NOTREACHED();
+ }
+}
+
+PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
+ if (socket_)
+ socket_->Disconnect();
+ --g_num_instances;
+}
+
+// static
+size_t PepperTCPSocketMessageFilter::GetNumInstances() {
+ return g_num_instances;
+}
+
+scoped_refptr<base::TaskRunner>
+PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& message) {
+ switch (message.type()) {
+ case PpapiHostMsg_TCPSocket_Connect::ID:
+ case PpapiHostMsg_TCPSocket_ConnectWithNetAddress::ID:
+ return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
+ case PpapiHostMsg_TCPSocket_SSLHandshake::ID:
+ case PpapiHostMsg_TCPSocket_Read::ID:
+ case PpapiHostMsg_TCPSocket_Write::ID:
+ case PpapiHostMsg_TCPSocket_Disconnect::ID:
+ case PpapiHostMsg_TCPSocket_SetOption::ID:
+ return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
+ }
+ return NULL;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) {
+ IPC_BEGIN_MESSAGE_MAP(PepperTCPSocketMessageFilter, msg)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Connect, OnMsgConnect)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_ConnectWithNetAddress,
+ OnMsgConnectWithNetAddress)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_SSLHandshake, OnMsgSSLHandshake)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Read, OnMsgRead)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Write, OnMsgWrite)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+ PpapiHostMsg_TCPSocket_Disconnect, OnMsgDisconnect)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_SetOption, OnMsgSetOption)
+ IPC_END_MESSAGE_MAP()
+ return PP_ERROR_FAILED;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
+ const ppapi::host::HostMessageContext* context,
+ const std::string& host,
+ uint16_t port) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // This is only supported by PPB_TCPSocket_Private.
+ if (!private_api_) {
+ NOTREACHED();
+ return PP_ERROR_NOACCESS;
+ }
+
+ SocketPermissionRequest request(SocketPermissionRequest::TCP_CONNECT,
+ host,
+ port);
+ if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, private_api_,
+ request, render_process_id_,
+ render_view_id_)) {
+ return PP_ERROR_NOACCESS;
+ }
+
+ RenderProcessHost* render_process_host =
+ RenderProcessHost::FromID(render_process_id_);
+ if (!render_process_host)
+ return PP_ERROR_FAILED;
+ BrowserContext* browser_context = render_process_host->GetBrowserContext();
+ if (!browser_context || !browser_context->GetResourceContext())
+ return PP_ERROR_FAILED;
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PepperTCPSocketMessageFilter::DoConnect, this,
+ context->MakeReplyMessageContext(),
+ host, port, browser_context->GetResourceContext()));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
+ const ppapi::host::HostMessageContext* context,
+ const PP_NetAddress_Private& net_addr) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ content::SocketPermissionRequest request =
+ pepper_socket_utils::CreateSocketPermissionRequest(
+ content::SocketPermissionRequest::TCP_CONNECT, net_addr);
+ if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, private_api_,
+ request, render_process_id_,
+ render_view_id_)) {
+ return PP_ERROR_NOACCESS;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress, this,
+ context->MakeReplyMessageContext(), net_addr));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
+ const ppapi::host::HostMessageContext* context,
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // Allow to do SSL handshake only if currently the socket has been connected
+ // and there isn't pending read or write.
+ // IsConnected() includes the state that SSL handshake has been finished and
+ // therefore isn't suitable here.
+ if (state_ != STATE_CONNECTED || read_buffer_.get() ||
+ write_buffer_base_.get() || write_buffer_.get()) {
+ return PP_ERROR_FAILED;
+ }
+
+ SetState(STATE_SSL_HANDSHAKE_IN_PROGRESS);
+ // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
+
+ scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
+ handle->SetSocket(socket_.Pass());
+ net::ClientSocketFactory* factory =
+ net::ClientSocketFactory::GetDefaultFactory();
+ net::HostPortPair host_port_pair(server_name, server_port);
+ net::SSLClientSocketContext ssl_context;
+ ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier();
+ ssl_context.transport_security_state =
+ ssl_context_helper_->GetTransportSecurityState();
+ socket_ = factory->CreateSSLClientSocket(
+ handle.Pass(), host_port_pair, ssl_context_helper_->ssl_config(),
+ ssl_context);
+ if (!socket_) {
+ LOG(WARNING) << "Failed to create an SSL client socket.";
+ return PP_ERROR_FAILED;
+ }
+
+ const ppapi::host::ReplyMessageContext reply_context(
+ context->MakeReplyMessageContext());
+ int net_result = socket_->Connect(
+ base::Bind(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
+ base::Unretained(this), reply_context));
+ if (net_result != net::ERR_IO_PENDING)
+ OnSSLHandshakeCompleted(reply_context, net_result);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgRead(
+ const ppapi::host::HostMessageContext* context,
+ int32_t bytes_to_read) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!IsConnected() || end_of_file_reached_)
+ return PP_ERROR_FAILED;
+ if (read_buffer_.get())
+ return PP_ERROR_INPROGRESS;
+ if (bytes_to_read <= 0 ||
+ bytes_to_read > TCPSocketResourceBase::kMaxReadSize) {
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ ppapi::host::ReplyMessageContext reply_context(
+ context->MakeReplyMessageContext());
+ read_buffer_ = new net::IOBuffer(bytes_to_read);
+ int net_result = socket_->Read(
+ read_buffer_.get(),
+ bytes_to_read,
+ base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
+ base::Unretained(this), reply_context));
+ if (net_result != net::ERR_IO_PENDING)
+ OnReadCompleted(reply_context, net_result);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
+ const ppapi::host::HostMessageContext* context,
+ const std::string& data) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!IsConnected())
+ return PP_ERROR_FAILED;
+ if (write_buffer_base_.get() || write_buffer_.get())
+ return PP_ERROR_INPROGRESS;
+
+ size_t data_size = data.size();
+ if (data_size == 0 ||
+ data_size > static_cast<size_t>(TCPSocketResourceBase::kMaxWriteSize)) {
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ write_buffer_base_ = new net::IOBuffer(data_size);
+ memcpy(write_buffer_base_->data(), data.data(), data_size);
+ write_buffer_ =
+ new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
+ DoWrite(context->MakeReplyMessageContext());
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgDisconnect(
+ const ppapi::host::HostMessageContext* context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ SetState(STATE_CLOSED);
+ return PP_OK;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
+ const ppapi::host::HostMessageContext* context,
+ PP_TCPSocket_Option name,
+ const ppapi::SocketOptionData& value) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!IsConnected() || IsSsl())
+ return PP_ERROR_FAILED;
+
+ net::TCPClientSocket* tcp_socket =
+ static_cast<net::TCPClientSocket*>(socket_.get());
+ DCHECK(tcp_socket);
+
+ switch (name) {
+ case PP_TCPSOCKET_OPTION_NO_DELAY: {
+ bool boolean_value = false;
+ if (!value.GetBool(&boolean_value))
+ return PP_ERROR_BADARGUMENT;
+ return tcp_socket->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED;
+ }
+ case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
+ case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
+ int32_t integer_value = 0;
+ if (!value.GetInt32(&integer_value) || integer_value <= 0)
+ return PP_ERROR_BADARGUMENT;
+
+ bool result = false;
+ if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
+ if (integer_value > TCPSocketResourceBase::kMaxSendBufferSize)
+ return PP_ERROR_BADARGUMENT;
+ result = tcp_socket->SetSendBufferSize(integer_value);
+ } else {
+ if (integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize)
+ return PP_ERROR_BADARGUMENT;
+ result = tcp_socket->SetReceiveBufferSize(integer_value);
+ }
+ return result ? PP_OK : PP_ERROR_FAILED;
+ }
+ default: {
+ NOTREACHED();
+ return PP_ERROR_BADARGUMENT;
+ }
+ }
+ return PP_ERROR_FAILED;
+}
+
+void PepperTCPSocketMessageFilter::DoConnect(
+ const ppapi::host::ReplyMessageContext& context,
+ const std::string& host,
+ uint16_t port,
+ ResourceContext* resource_context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (state_ != STATE_BEFORE_CONNECT) {
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ SetState(STATE_CONNECT_IN_PROGRESS);
+ net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
+ resolver_.reset(new net::SingleRequestHostResolver(
+ resource_context->GetHostResolver()));
+ int net_result = resolver_->Resolve(
+ request_info,
+ net::DEFAULT_PRIORITY,
+ &address_list_,
+ base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
+ base::Unretained(this), context),
+ net::BoundNetLog());
+ if (net_result != net::ERR_IO_PENDING)
+ OnResolveCompleted(context, net_result);
+}
+
+void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
+ const ppapi::host::ReplyMessageContext& context,
+ const PP_NetAddress_Private& net_addr) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (state_ != STATE_BEFORE_CONNECT) {
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ net::IPAddressNumber address;
+ int port;
+ if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
+ &port)) {
+ SendConnectError(context, PP_ERROR_ADDRESS_INVALID);
+ return;
+ }
+
+ // Copy the single IPEndPoint to address_list_.
+ address_list_.clear();
+ address_list_.push_back(net::IPEndPoint(address, port));
+ SetState(STATE_CONNECT_IN_PROGRESS);
+ StartConnect(context);
+}
+
+void PepperTCPSocketMessageFilter::DoWrite(
+ const ppapi::host::ReplyMessageContext& context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(write_buffer_base_.get());
+ DCHECK(write_buffer_.get());
+ DCHECK_GT(write_buffer_->BytesRemaining(), 0);
+
+ int net_result = socket_->Write(
+ write_buffer_.get(),
+ write_buffer_->BytesRemaining(),
+ base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
+ base::Unretained(this), context));
+ if (net_result != net::ERR_IO_PENDING)
+ OnWriteCompleted(context, net_result);
+}
+
+void PepperTCPSocketMessageFilter::OnResolveCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (state_ != STATE_CONNECT_IN_PROGRESS) {
+ SendConnectError(context, PP_ERROR_FAILED);
+ SetState(STATE_CLOSED);
+ return;
+ }
+
+ if (net_result != net::OK) {
+ SendConnectError(context, NetErrorToPepperError(net_result));
+ SetState(STATE_BEFORE_CONNECT);
+ return;
+ }
+
+ StartConnect(context);
+}
+
+void PepperTCPSocketMessageFilter::StartConnect(
+ const ppapi::host::ReplyMessageContext& context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (state_ != STATE_CONNECT_IN_PROGRESS) {
+ SendConnectError(context, PP_ERROR_FAILED);
+ SetState(STATE_CLOSED);
+ return;
+ }
+
+ socket_.reset(new net::TCPClientSocket(address_list_, NULL,
+ net::NetLog::Source()));
+ int net_result = socket_->Connect(
+ base::Bind(&PepperTCPSocketMessageFilter::OnConnectCompleted,
+ base::Unretained(this), context));
+ if (net_result != net::ERR_IO_PENDING)
+ OnConnectCompleted(context, net_result);
+}
+
+void PepperTCPSocketMessageFilter::OnConnectCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(socket_.get());
+
+ if (state_ != STATE_CONNECT_IN_PROGRESS) {
+ SendConnectError(context, PP_ERROR_FAILED);
+ SetState(STATE_CLOSED);
+ return;
+ }
+
+ int32_t pp_result = NetErrorToPepperError(net_result);
+ do {
+ if (pp_result != PP_OK)
+ break;
+
+ net::IPEndPoint ip_end_point_local;
+ net::IPEndPoint ip_end_point_remote;
+ pp_result = NetErrorToPepperError(
+ socket_->GetLocalAddress(&ip_end_point_local));
+ if (pp_result != PP_OK)
+ break;
+ pp_result = NetErrorToPepperError(
+ socket_->GetPeerAddress(&ip_end_point_remote));
+ if (pp_result != PP_OK)
+ break;
+
+ PP_NetAddress_Private local_addr =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+ PP_NetAddress_Private remote_addr =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+ if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
+ ip_end_point_local.address(),
+ ip_end_point_local.port(),
+ &local_addr) ||
+ !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ ip_end_point_remote.address(),
+ ip_end_point_remote.port(),
+ &remote_addr)) {
+ pp_result = PP_ERROR_ADDRESS_INVALID;
+ break;
+ }
+
+ SendConnectReply(context, PP_OK, local_addr, remote_addr);
+ SetState(STATE_CONNECTED);
+ return;
+ } while (false);
+
+ SendConnectError(context, pp_result);
+ SetState(STATE_BEFORE_CONNECT);
+}
+
+void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (state_ != STATE_SSL_HANDSHAKE_IN_PROGRESS) {
+ SendSSLHandshakeReply(context, PP_ERROR_FAILED);
+ SetState(STATE_CLOSED);
+ return;
+ }
+ SendSSLHandshakeReply(context, NetErrorToPepperError(net_result));
+ SetState(net_result == net::OK ?
+ STATE_SSL_CONNECTED :
+ STATE_SSL_HANDSHAKE_FAILED);
+}
+
+void PepperTCPSocketMessageFilter::OnReadCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(read_buffer_.get());
+
+ if (net_result > 0) {
+ SendReadReply(context,
+ PP_OK,
+ std::string(read_buffer_->data(), net_result));
+ } else if (net_result == 0) {
+ end_of_file_reached_ = true;
+ SendReadReply(context, PP_OK, std::string());
+ } else {
+ SendReadError(context, NetErrorToPepperError(net_result));
+ }
+ read_buffer_ = NULL;
+}
+
+void PepperTCPSocketMessageFilter::OnWriteCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(write_buffer_base_.get());
+ DCHECK(write_buffer_.get());
+
+ // Note: For partial writes of 0 bytes, don't continue writing to avoid a
+ // likely infinite loop.
+ if (net_result > 0) {
+ write_buffer_->DidConsume(net_result);
+ if (write_buffer_->BytesRemaining() > 0) {
+ DoWrite(context);
+ return;
+ }
+ }
+
+ if (net_result >= 0)
+ SendWriteReply(context, write_buffer_->BytesConsumed());
+ else
+ SendWriteReply(context, NetErrorToPepperError(net_result));
+
+ write_buffer_ = NULL;
+ write_buffer_base_ = NULL;
+}
+
+void PepperTCPSocketMessageFilter::SendConnectReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context,
+ PpapiPluginMsg_TCPSocket_ConnectReply(local_addr, remote_addr));
+}
+
+void PepperTCPSocketMessageFilter::SendConnectError(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error) {
+ SendConnectReply(context,
+ pp_error,
+ NetAddressPrivateImpl::kInvalidNetAddress,
+ NetAddressPrivateImpl::kInvalidNetAddress);
+}
+
+void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ ppapi::PPB_X509Certificate_Fields certificate_fields;
+ if (pp_result == PP_OK) {
+ // Our socket is guaranteed to be an SSL socket if we get here.
+ net::SSLClientSocket* ssl_socket =
+ static_cast<net::SSLClientSocket*>(socket_.get());
+ net::SSLInfo ssl_info;
+ ssl_socket->GetSSLInfo(&ssl_info);
+ if (ssl_info.cert.get()) {
+ pepper_socket_utils::GetCertificateFields(*ssl_info.cert.get(),
+ &certificate_fields);
+ }
+ }
+ SendReply(reply_context,
+ PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
+}
+
+void PepperTCPSocketMessageFilter::SendReadReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const std::string& data) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context, PpapiPluginMsg_TCPSocket_ReadReply(data));
+}
+
+void PepperTCPSocketMessageFilter::SendReadError(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error) {
+ SendReadReply(context, pp_error, std::string());
+}
+
+void PepperTCPSocketMessageFilter::SendWriteReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context, PpapiPluginMsg_TCPSocket_WriteReply());
+}
+
+bool PepperTCPSocketMessageFilter::IsConnected() const {
+ return state_ == STATE_CONNECTED || state_ == STATE_SSL_CONNECTED;
+}
+
+bool PepperTCPSocketMessageFilter::IsSsl() const {
+ return state_ == STATE_SSL_HANDSHAKE_IN_PROGRESS ||
+ state_ == STATE_SSL_CONNECTED ||
+ state_ == STATE_SSL_HANDSHAKE_FAILED;
+}
+
+void PepperTCPSocketMessageFilter::SetState(State state) {
+ state_ = state;
+ if (state_ == STATE_CLOSED && socket_) {
+ // Make sure no further callbacks from socket_.
+ socket_->Disconnect();
+ socket_.reset();
+ }
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698