summaryrefslogtreecommitdiffstats
path: root/ppapi/shared_impl
diff options
context:
space:
mode:
authoryzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-13 06:48:36 +0000
committeryzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-13 06:48:36 +0000
commitb1784f4dc9fbf104e4454796edf26d2f76e16a94 (patch)
tree476affcb92e4fa1e2f0772a935bc3f63f8164630 /ppapi/shared_impl
parentb1c988bcd7869765e1bd56e592787af123340516 (diff)
downloadchromium_src-b1784f4dc9fbf104e4454796edf26d2f76e16a94.zip
chromium_src-b1784f4dc9fbf104e4454796edf26d2f76e16a94.tar.gz
chromium_src-b1784f4dc9fbf104e4454796edf26d2f76e16a94.tar.bz2
Introduce PPB_TCPSocket_Dev.
This change exposes the PPB_TCPSocket_Dev interface and makes it to share the same backend as PPB_TCPSocket_Private. It doesn't include: - apps permission check; - TCP socket options that PPB_TCPSocket_Private doesn't support. These will be implemented in separate CLs. BUG=247225 TEST=newly added test_tcp_socket.{h,cc}. Review URL: https://chromiumcodereview.appspot.com/16667002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@206014 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/shared_impl')
-rw-r--r--ppapi/shared_impl/api_id.h1
-rw-r--r--ppapi/shared_impl/private/tcp_socket_private_impl.cc288
-rw-r--r--ppapi/shared_impl/private/tcp_socket_private_impl.h87
-rw-r--r--ppapi/shared_impl/resource.h1
-rw-r--r--ppapi/shared_impl/tcp_socket_shared.cc339
-rw-r--r--ppapi/shared_impl/tcp_socket_shared.h133
6 files changed, 496 insertions, 353 deletions
diff --git a/ppapi/shared_impl/api_id.h b/ppapi/shared_impl/api_id.h
index 16955aa..65a150e 100644
--- a/ppapi/shared_impl/api_id.h
+++ b/ppapi/shared_impl/api_id.h
@@ -40,6 +40,7 @@ enum ApiID {
API_ID_PPB_PDF,
API_ID_PPB_SURFACE_3D,
API_ID_PPB_TCPSERVERSOCKET_PRIVATE,
+ API_ID_PPB_TCPSOCKET,
API_ID_PPB_TCPSOCKET_PRIVATE,
API_ID_PPB_TALK,
API_ID_PPB_TESTING,
diff --git a/ppapi/shared_impl/private/tcp_socket_private_impl.cc b/ppapi/shared_impl/private/tcp_socket_private_impl.cc
index 87cc600..832603c 100644
--- a/ppapi/shared_impl/private/tcp_socket_private_impl.cc
+++ b/ppapi/shared_impl/private/tcp_socket_private_impl.cc
@@ -4,40 +4,18 @@
#include "ppapi/shared_impl/private/tcp_socket_private_impl.h"
-#include <string.h>
-
-#include <algorithm>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "ppapi/c/pp_completion_callback.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/shared_impl/ppapi_globals.h"
-#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
-#include "ppapi/shared_impl/var_tracker.h"
-#include "ppapi/shared_impl/var.h"
-#include "ppapi/thunk/enter.h"
-#include "ppapi/thunk/ppb_x509_certificate_private_api.h"
-
namespace ppapi {
-const int32_t TCPSocketPrivateImpl::kMaxReadSize = 1024 * 1024;
-const int32_t TCPSocketPrivateImpl::kMaxWriteSize = 1024 * 1024;
-
TCPSocketPrivateImpl::TCPSocketPrivateImpl(PP_Instance instance,
uint32 socket_id)
: Resource(OBJECT_IS_IMPL, instance),
- resource_type_(OBJECT_IS_IMPL) {
- Init(socket_id);
+ TCPSocketShared(OBJECT_IS_IMPL, socket_id) {
}
TCPSocketPrivateImpl::TCPSocketPrivateImpl(const HostResource& resource,
uint32 socket_id)
: Resource(OBJECT_IS_PROXY, resource),
- resource_type_(OBJECT_IS_PROXY) {
- Init(socket_id);
+ TCPSocketShared(OBJECT_IS_PROXY, socket_id) {
}
TCPSocketPrivateImpl::~TCPSocketPrivateImpl() {
@@ -51,303 +29,67 @@ TCPSocketPrivateImpl::AsPPB_TCPSocket_Private_API() {
int32_t TCPSocketPrivateImpl::Connect(const char* host,
uint16_t port,
scoped_refptr<TrackedCallback> callback) {
- if (!host)
- return PP_ERROR_BADARGUMENT;
- if (connection_state_ != BEFORE_CONNECT)
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(connect_callback_))
- return PP_ERROR_INPROGRESS; // Can only have one pending request.
-
- connect_callback_ = callback;
- // Send the request, the browser will call us back via ConnectACK.
- SendConnect(host, port);
- return PP_OK_COMPLETIONPENDING;
+ return ConnectImpl(host, port, callback);
}
int32_t TCPSocketPrivateImpl::ConnectWithNetAddress(
const PP_NetAddress_Private* addr,
scoped_refptr<TrackedCallback> callback) {
- if (!addr)
- return PP_ERROR_BADARGUMENT;
- if (connection_state_ != BEFORE_CONNECT)
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(connect_callback_))
- return PP_ERROR_INPROGRESS; // Can only have one pending request.
-
- connect_callback_ = callback;
- // Send the request, the browser will call us back via ConnectACK.
- SendConnectWithNetAddress(*addr);
- return PP_OK_COMPLETIONPENDING;
+ return ConnectWithNetAddressImpl(addr, callback);
}
PP_Bool TCPSocketPrivateImpl::GetLocalAddress(
PP_NetAddress_Private* local_addr) {
- if (!IsConnected() || !local_addr)
- return PP_FALSE;
-
- *local_addr = local_addr_;
- return PP_TRUE;
+ return GetLocalAddressImpl(local_addr);
}
PP_Bool TCPSocketPrivateImpl::GetRemoteAddress(
PP_NetAddress_Private* remote_addr) {
- if (!IsConnected() || !remote_addr)
- return PP_FALSE;
-
- *remote_addr = remote_addr_;
- return PP_TRUE;
+ return GetRemoteAddressImpl(remote_addr);
}
int32_t TCPSocketPrivateImpl::SSLHandshake(
const char* server_name,
uint16_t server_port,
scoped_refptr<TrackedCallback> callback) {
- if (!server_name)
- return PP_ERROR_BADARGUMENT;
-
- if (connection_state_ != CONNECTED)
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(ssl_handshake_callback_) ||
- TrackedCallback::IsPending(read_callback_) ||
- TrackedCallback::IsPending(write_callback_))
- return PP_ERROR_INPROGRESS;
-
- ssl_handshake_callback_ = callback;
-
- // Send the request, the browser will call us back via SSLHandshakeACK.
- SendSSLHandshake(server_name, server_port, trusted_certificates_,
- untrusted_certificates_);
- return PP_OK_COMPLETIONPENDING;
+ return SSLHandshakeImpl(server_name, server_port, callback);
}
PP_Resource TCPSocketPrivateImpl::GetServerCertificate() {
- if (!server_certificate_.get())
- return 0;
- return server_certificate_->GetReference();
+ return GetServerCertificateImpl();
}
PP_Bool TCPSocketPrivateImpl::AddChainBuildingCertificate(
PP_Resource certificate,
PP_Bool trusted) {
- // TODO(raymes): The plumbing for this functionality is implemented but the
- // certificates aren't yet used for the connection, so just return false for
- // now.
- return PP_FALSE;
-
- thunk::EnterResourceNoLock<thunk::PPB_X509Certificate_Private_API>
- enter_cert(certificate, true);
- if (enter_cert.failed())
- return PP_FALSE;
-
- PP_Var der_var = enter_cert.object()->GetField(
- PP_X509CERTIFICATE_PRIVATE_RAW);
- ArrayBufferVar* der_array_buffer = ArrayBufferVar::FromPPVar(der_var);
- PP_Bool success = PP_FALSE;
- if (der_array_buffer) {
- const char* der_bytes = static_cast<const char*>(der_array_buffer->Map());
- uint32_t der_length = der_array_buffer->ByteLength();
- std::vector<char> der(der_bytes, der_bytes + der_length);
- if (PP_ToBool(trusted))
- trusted_certificates_.push_back(der);
- else
- untrusted_certificates_.push_back(der);
- success = PP_TRUE;
- }
- PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(der_var);
- return success;
+ return AddChainBuildingCertificateImpl(certificate, trusted);
}
int32_t TCPSocketPrivateImpl::Read(char* buffer,
int32_t bytes_to_read,
scoped_refptr<TrackedCallback> callback) {
- if (!buffer || bytes_to_read <= 0)
- return PP_ERROR_BADARGUMENT;
-
- if (!IsConnected())
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(read_callback_) ||
- TrackedCallback::IsPending(ssl_handshake_callback_))
- return PP_ERROR_INPROGRESS;
- read_buffer_ = buffer;
- bytes_to_read_ = std::min(bytes_to_read, kMaxReadSize);
- read_callback_ = callback;
-
- // Send the request, the browser will call us back via ReadACK.
- SendRead(bytes_to_read_);
- return PP_OK_COMPLETIONPENDING;
+ return ReadImpl(buffer, bytes_to_read, callback);
}
int32_t TCPSocketPrivateImpl::Write(const char* buffer,
int32_t bytes_to_write,
scoped_refptr<TrackedCallback> callback) {
- if (!buffer || bytes_to_write <= 0)
- return PP_ERROR_BADARGUMENT;
-
- if (!IsConnected())
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(write_callback_) ||
- TrackedCallback::IsPending(ssl_handshake_callback_))
- return PP_ERROR_INPROGRESS;
-
- if (bytes_to_write > kMaxWriteSize)
- bytes_to_write = kMaxWriteSize;
-
- write_callback_ = callback;
-
- // Send the request, the browser will call us back via WriteACK.
- SendWrite(std::string(buffer, bytes_to_write));
- return PP_OK_COMPLETIONPENDING;
+ return WriteImpl(buffer, bytes_to_write, callback);
}
void TCPSocketPrivateImpl::Disconnect() {
- if (connection_state_ == DISCONNECTED)
- return;
-
- connection_state_ = DISCONNECTED;
-
- SendDisconnect();
- socket_id_ = 0;
-
- PostAbortIfNecessary(&connect_callback_);
- PostAbortIfNecessary(&ssl_handshake_callback_);
- PostAbortIfNecessary(&read_callback_);
- PostAbortIfNecessary(&write_callback_);
- PostAbortIfNecessary(&set_option_callback_);
- read_buffer_ = NULL;
- bytes_to_read_ = -1;
- server_certificate_ = NULL;
+ DisconnectImpl();
}
int32_t TCPSocketPrivateImpl::SetOption(
PP_TCPSocketOption_Private name,
const PP_Var& value,
scoped_refptr<TrackedCallback> callback) {
- if (!IsConnected())
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(set_option_callback_))
- return PP_ERROR_INPROGRESS;
-
- set_option_callback_ = callback;
-
- switch (name) {
- case PP_TCPSOCKETOPTION_NO_DELAY:
- if (value.type != PP_VARTYPE_BOOL)
- return PP_ERROR_BADARGUMENT;
- SendSetBoolOption(name, PP_ToBool(value.value.as_bool));
- return PP_OK_COMPLETIONPENDING;
- default:
- return PP_ERROR_BADARGUMENT;
- }
-}
-
-void TCPSocketPrivateImpl::OnConnectCompleted(
- bool succeeded,
- const PP_NetAddress_Private& local_addr,
- const PP_NetAddress_Private& remote_addr) {
- if (connection_state_ != BEFORE_CONNECT ||
- !TrackedCallback::IsPending(connect_callback_)) {
- NOTREACHED();
- return;
- }
-
- if (succeeded) {
- local_addr_ = local_addr;
- remote_addr_ = remote_addr;
- connection_state_ = CONNECTED;
- }
- connect_callback_->Run(succeeded ? PP_OK : PP_ERROR_FAILED);
-}
-
-void TCPSocketPrivateImpl::OnSSLHandshakeCompleted(
- bool succeeded,
- const PPB_X509Certificate_Fields& certificate_fields) {
- if (connection_state_ != CONNECTED ||
- !TrackedCallback::IsPending(ssl_handshake_callback_)) {
- NOTREACHED();
- return;
- }
-
- if (succeeded) {
- connection_state_ = SSL_CONNECTED;
- server_certificate_ = new PPB_X509Certificate_Private_Shared(
- resource_type_,
- pp_instance(),
- certificate_fields);
- ssl_handshake_callback_->Run(PP_OK);
- } else {
- // The resource might be released in the callback so we need to hold
- // a reference so we can Disconnect() first.
- AddRef();
- ssl_handshake_callback_->Run(PP_ERROR_FAILED);
- Disconnect();
- Release();
- }
-}
-
-void TCPSocketPrivateImpl::OnReadCompleted(bool succeeded,
- const std::string& data) {
- if (!TrackedCallback::IsPending(read_callback_) || !read_buffer_) {
- NOTREACHED();
- return;
- }
-
- if (succeeded) {
- CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_);
- if (!data.empty())
- memcpy(read_buffer_, data.c_str(), data.size());
- }
- read_buffer_ = NULL;
- bytes_to_read_ = -1;
-
- read_callback_->Run(
- succeeded ? static_cast<int32_t>(data.size()) :
- static_cast<int32_t>(PP_ERROR_FAILED));
+ return SetOptionImpl(name, value, callback);
}
-void TCPSocketPrivateImpl::OnWriteCompleted(bool succeeded,
- int32_t bytes_written) {
- if (!TrackedCallback::IsPending(write_callback_) ||
- (succeeded && bytes_written < 0)) {
- NOTREACHED();
- return;
- }
-
- write_callback_->Run(
- succeeded ? bytes_written : static_cast<int32_t>(PP_ERROR_FAILED));
-}
-
-void TCPSocketPrivateImpl::OnSetOptionCompleted(bool succeeded) {
- if (!TrackedCallback::IsPending(set_option_callback_)) {
- NOTREACHED();
- return;
- }
-
- set_option_callback_->Run(succeeded ? PP_OK : PP_ERROR_FAILED);
-}
-
-void TCPSocketPrivateImpl::Init(uint32 socket_id) {
- DCHECK(socket_id != 0);
- socket_id_ = socket_id;
- connection_state_ = BEFORE_CONNECT;
- read_buffer_ = NULL;
- bytes_to_read_ = -1;
-
- local_addr_.size = 0;
- memset(local_addr_.data, 0,
- arraysize(local_addr_.data) * sizeof(*local_addr_.data));
- remote_addr_.size = 0;
- memset(remote_addr_.data, 0,
- arraysize(remote_addr_.data) * sizeof(*remote_addr_.data));
-}
-
-bool TCPSocketPrivateImpl::IsConnected() const {
- return connection_state_ == CONNECTED || connection_state_ == SSL_CONNECTED;
-}
-
-void TCPSocketPrivateImpl::PostAbortIfNecessary(
- scoped_refptr<TrackedCallback>* callback) {
- if (TrackedCallback::IsPending(*callback))
- (*callback)->PostAbort();
+Resource* TCPSocketPrivateImpl::GetOwnerResource() {
+ return this;
}
} // namespace ppapi
diff --git a/ppapi/shared_impl/private/tcp_socket_private_impl.h b/ppapi/shared_impl/private/tcp_socket_private_impl.h
index 95057e7..62fba8e 100644
--- a/ppapi/shared_impl/private/tcp_socket_private_impl.h
+++ b/ppapi/shared_impl/private/tcp_socket_private_impl.h
@@ -5,26 +5,22 @@
#ifndef PPAPI_SHARED_IMPL_PRIVATE_TCP_SOCKET_PRIVATE_IMPL_H_
#define PPAPI_SHARED_IMPL_PRIVATE_TCP_SOCKET_PRIVATE_IMPL_H_
-#include <string>
-#include <vector>
-
+#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "ppapi/shared_impl/resource.h"
-#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/shared_impl/tcp_socket_shared.h"
#include "ppapi/thunk/ppb_tcp_socket_private_api.h"
namespace ppapi {
-class PPB_X509Certificate_Fields;
-class PPB_X509Certificate_Private_Shared;
-
// This class provides the shared implementation of a
// PPB_TCPSocket_Private. The functions that actually send messages
// to browser are implemented differently for the proxied and
// non-proxied derived classes.
class PPAPI_SHARED_EXPORT TCPSocketPrivateImpl
: public thunk::PPB_TCPSocket_Private_API,
- public Resource {
+ public Resource,
+ public TCPSocketShared {
public:
// C-tor used in Impl case.
TCPSocketPrivateImpl(PP_Instance instance, uint32 socket_id);
@@ -33,13 +29,6 @@ class PPAPI_SHARED_EXPORT TCPSocketPrivateImpl
virtual ~TCPSocketPrivateImpl();
- // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Read
- // message is allowed to request.
- static const int32_t kMaxReadSize;
- // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Write
- // message is allowed to carry.
- static const int32_t kMaxWriteSize;
-
// Resource overrides.
virtual PPB_TCPSocket_Private_API* AsPPB_TCPSocket_Private_API() OVERRIDE;
@@ -70,72 +59,10 @@ class PPAPI_SHARED_EXPORT TCPSocketPrivateImpl
const PP_Var& value,
scoped_refptr<TrackedCallback> callback) OVERRIDE;
- // Notifications on operations completion.
- void OnConnectCompleted(bool succeeded,
- const PP_NetAddress_Private& local_addr,
- const PP_NetAddress_Private& remote_addr);
- void OnSSLHandshakeCompleted(
- bool succeeded,
- const PPB_X509Certificate_Fields& certificate_fields);
- void OnReadCompleted(bool succeeded, const std::string& data);
- void OnWriteCompleted(bool succeeded, int32_t bytes_written);
- void OnSetOptionCompleted(bool succeeded);
-
- // Send functions that need to be implemented differently for the
- // proxied and non-proxied derived classes.
- virtual void SendConnect(const std::string& host, uint16_t port) = 0;
- virtual void SendConnectWithNetAddress(const PP_NetAddress_Private& addr) = 0;
- virtual void SendSSLHandshake(
- 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) = 0;
- virtual void SendRead(int32_t bytes_to_read) = 0;
- virtual void SendWrite(const std::string& buffer) = 0;
- virtual void SendDisconnect() = 0;
- virtual void SendSetBoolOption(PP_TCPSocketOption_Private name,
- bool value) = 0;
-
- protected:
- enum ConnectionState {
- // Before a connection is successfully established (including a connect
- // request is pending or a previous connect request failed).
- BEFORE_CONNECT,
- // A connection has been successfully established (including a request of
- // initiating SSL is pending).
- CONNECTED,
- // An SSL connection has been successfully established.
- SSL_CONNECTED,
- // The connection has been ended.
- DISCONNECTED
- };
-
- void Init(uint32 socket_id);
- bool IsConnected() const;
- void PostAbortIfNecessary(scoped_refptr<TrackedCallback>* callback);
-
- ResourceObjectType resource_type_;
-
- uint32 socket_id_;
- ConnectionState connection_state_;
-
- scoped_refptr<TrackedCallback> connect_callback_;
- scoped_refptr<TrackedCallback> ssl_handshake_callback_;
- scoped_refptr<TrackedCallback> read_callback_;
- scoped_refptr<TrackedCallback> write_callback_;
- scoped_refptr<TrackedCallback> set_option_callback_;
-
- char* read_buffer_;
- int32_t bytes_to_read_;
-
- PP_NetAddress_Private local_addr_;
- PP_NetAddress_Private remote_addr_;
-
- scoped_refptr<PPB_X509Certificate_Private_Shared> server_certificate_;
-
- std::vector<std::vector<char> > trusted_certificates_;
- std::vector<std::vector<char> > untrusted_certificates_;
+ // TCPSocketShared implementation.
+ virtual Resource* GetOwnerResource() OVERRIDE;
+ private:
DISALLOW_COPY_AND_ASSIGN(TCPSocketPrivateImpl);
};
diff --git a/ppapi/shared_impl/resource.h b/ppapi/shared_impl/resource.h
index f327388..05b3d51 100644
--- a/ppapi/shared_impl/resource.h
+++ b/ppapi/shared_impl/resource.h
@@ -63,6 +63,7 @@
F(PPB_TrueTypeFont_API) \
F(PPB_TrueTypeFont_Singleton_API) \
F(PPB_TCPServerSocket_Private_API) \
+ F(PPB_TCPSocket_API) \
F(PPB_TCPSocket_Private_API) \
F(PPB_UDPSocket_Private_API) \
F(PPB_URLLoader_API) \
diff --git a/ppapi/shared_impl/tcp_socket_shared.cc b/ppapi/shared_impl/tcp_socket_shared.cc
new file mode 100644
index 0000000..8799c49
--- /dev/null
+++ b/ppapi/shared_impl/tcp_socket_shared.cc
@@ -0,0 +1,339 @@
+// 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 "ppapi/shared_impl/tcp_socket_shared.h"
+
+#include <string.h>
+
+#include <algorithm>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/logging.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
+#include "ppapi/shared_impl/var_tracker.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_x509_certificate_private_api.h"
+
+namespace ppapi {
+
+const int32_t TCPSocketShared::kMaxReadSize = 1024 * 1024;
+const int32_t TCPSocketShared::kMaxWriteSize = 1024 * 1024;
+
+TCPSocketShared::TCPSocketShared(ResourceObjectType resource_type,
+ uint32 socket_id)
+ : resource_type_(resource_type) {
+ Init(socket_id);
+}
+
+TCPSocketShared::~TCPSocketShared() {
+}
+
+void TCPSocketShared::OnConnectCompleted(
+ bool succeeded,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ if (connection_state_ != BEFORE_CONNECT ||
+ !TrackedCallback::IsPending(connect_callback_)) {
+ NOTREACHED();
+ return;
+ }
+
+ if (succeeded) {
+ local_addr_ = local_addr;
+ remote_addr_ = remote_addr;
+ connection_state_ = CONNECTED;
+ }
+ connect_callback_->Run(succeeded ? PP_OK : PP_ERROR_FAILED);
+}
+
+void TCPSocketShared::OnSSLHandshakeCompleted(
+ bool succeeded,
+ const PPB_X509Certificate_Fields& certificate_fields) {
+ if (connection_state_ != CONNECTED ||
+ !TrackedCallback::IsPending(ssl_handshake_callback_)) {
+ NOTREACHED();
+ return;
+ }
+
+ if (succeeded) {
+ connection_state_ = SSL_CONNECTED;
+ server_certificate_ = new PPB_X509Certificate_Private_Shared(
+ resource_type_,
+ GetOwnerResource()->pp_instance(),
+ certificate_fields);
+ ssl_handshake_callback_->Run(PP_OK);
+ } else {
+ // The resource might be released in the callback so we need to hold
+ // a reference so we can Disconnect() first.
+ GetOwnerResource()->AddRef();
+ ssl_handshake_callback_->Run(PP_ERROR_FAILED);
+ DisconnectImpl();
+ GetOwnerResource()->Release();
+ }
+}
+
+void TCPSocketShared::OnReadCompleted(bool succeeded,
+ const std::string& data) {
+ if (!TrackedCallback::IsPending(read_callback_) || !read_buffer_) {
+ NOTREACHED();
+ return;
+ }
+
+ if (succeeded) {
+ CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_);
+ if (!data.empty())
+ memcpy(read_buffer_, data.c_str(), data.size());
+ }
+ read_buffer_ = NULL;
+ bytes_to_read_ = -1;
+
+ read_callback_->Run(
+ succeeded ? static_cast<int32_t>(data.size()) :
+ static_cast<int32_t>(PP_ERROR_FAILED));
+}
+
+void TCPSocketShared::OnWriteCompleted(bool succeeded,
+ int32_t bytes_written) {
+ if (!TrackedCallback::IsPending(write_callback_) ||
+ (succeeded && bytes_written < 0)) {
+ NOTREACHED();
+ return;
+ }
+
+ write_callback_->Run(
+ succeeded ? bytes_written : static_cast<int32_t>(PP_ERROR_FAILED));
+}
+
+void TCPSocketShared::OnSetOptionCompleted(bool succeeded) {
+ if (!TrackedCallback::IsPending(set_option_callback_)) {
+ NOTREACHED();
+ return;
+ }
+
+ set_option_callback_->Run(succeeded ? PP_OK : PP_ERROR_FAILED);
+}
+
+int32_t TCPSocketShared::ConnectImpl(const char* host,
+ uint16_t port,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!host)
+ return PP_ERROR_BADARGUMENT;
+ if (connection_state_ != BEFORE_CONNECT)
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(connect_callback_))
+ return PP_ERROR_INPROGRESS; // Can only have one pending request.
+
+ connect_callback_ = callback;
+ // Send the request, the browser will call us back via ConnectACK.
+ SendConnect(host, port);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TCPSocketShared::ConnectWithNetAddressImpl(
+ const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!addr)
+ return PP_ERROR_BADARGUMENT;
+ if (connection_state_ != BEFORE_CONNECT)
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(connect_callback_))
+ return PP_ERROR_INPROGRESS; // Can only have one pending request.
+
+ connect_callback_ = callback;
+ // Send the request, the browser will call us back via ConnectACK.
+ SendConnectWithNetAddress(*addr);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_Bool TCPSocketShared::GetLocalAddressImpl(
+ PP_NetAddress_Private* local_addr) {
+ if (!IsConnected() || !local_addr)
+ return PP_FALSE;
+
+ *local_addr = local_addr_;
+ return PP_TRUE;
+}
+
+PP_Bool TCPSocketShared::GetRemoteAddressImpl(
+ PP_NetAddress_Private* remote_addr) {
+ if (!IsConnected() || !remote_addr)
+ return PP_FALSE;
+
+ *remote_addr = remote_addr_;
+ return PP_TRUE;
+}
+
+int32_t TCPSocketShared::SSLHandshakeImpl(
+ const char* server_name,
+ uint16_t server_port,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!server_name)
+ return PP_ERROR_BADARGUMENT;
+
+ if (connection_state_ != CONNECTED)
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(ssl_handshake_callback_) ||
+ TrackedCallback::IsPending(read_callback_) ||
+ TrackedCallback::IsPending(write_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ ssl_handshake_callback_ = callback;
+
+ // Send the request, the browser will call us back via SSLHandshakeACK.
+ SendSSLHandshake(server_name, server_port, trusted_certificates_,
+ untrusted_certificates_);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_Resource TCPSocketShared::GetServerCertificateImpl() {
+ if (!server_certificate_.get())
+ return 0;
+ return server_certificate_->GetReference();
+}
+
+PP_Bool TCPSocketShared::AddChainBuildingCertificateImpl(
+ PP_Resource certificate,
+ PP_Bool trusted) {
+ // TODO(raymes): The plumbing for this functionality is implemented but the
+ // certificates aren't yet used for the connection, so just return false for
+ // now.
+ return PP_FALSE;
+
+ thunk::EnterResourceNoLock<thunk::PPB_X509Certificate_Private_API>
+ enter_cert(certificate, true);
+ if (enter_cert.failed())
+ return PP_FALSE;
+
+ PP_Var der_var = enter_cert.object()->GetField(
+ PP_X509CERTIFICATE_PRIVATE_RAW);
+ ArrayBufferVar* der_array_buffer = ArrayBufferVar::FromPPVar(der_var);
+ PP_Bool success = PP_FALSE;
+ if (der_array_buffer) {
+ const char* der_bytes = static_cast<const char*>(der_array_buffer->Map());
+ uint32_t der_length = der_array_buffer->ByteLength();
+ std::vector<char> der(der_bytes, der_bytes + der_length);
+ if (PP_ToBool(trusted))
+ trusted_certificates_.push_back(der);
+ else
+ untrusted_certificates_.push_back(der);
+ success = PP_TRUE;
+ }
+ PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(der_var);
+ return success;
+}
+
+int32_t TCPSocketShared::ReadImpl(char* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!buffer || bytes_to_read <= 0)
+ return PP_ERROR_BADARGUMENT;
+
+ if (!IsConnected())
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(read_callback_) ||
+ TrackedCallback::IsPending(ssl_handshake_callback_))
+ return PP_ERROR_INPROGRESS;
+ read_buffer_ = buffer;
+ bytes_to_read_ = std::min(bytes_to_read, kMaxReadSize);
+ read_callback_ = callback;
+
+ // Send the request, the browser will call us back via ReadACK.
+ SendRead(bytes_to_read_);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TCPSocketShared::WriteImpl(const char* buffer,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!buffer || bytes_to_write <= 0)
+ return PP_ERROR_BADARGUMENT;
+
+ if (!IsConnected())
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(write_callback_) ||
+ TrackedCallback::IsPending(ssl_handshake_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ if (bytes_to_write > kMaxWriteSize)
+ bytes_to_write = kMaxWriteSize;
+
+ write_callback_ = callback;
+
+ // Send the request, the browser will call us back via WriteACK.
+ SendWrite(std::string(buffer, bytes_to_write));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void TCPSocketShared::DisconnectImpl() {
+ if (connection_state_ == DISCONNECTED)
+ return;
+
+ connection_state_ = DISCONNECTED;
+
+ SendDisconnect();
+ socket_id_ = 0;
+
+ PostAbortIfNecessary(&connect_callback_);
+ PostAbortIfNecessary(&ssl_handshake_callback_);
+ PostAbortIfNecessary(&read_callback_);
+ PostAbortIfNecessary(&write_callback_);
+ PostAbortIfNecessary(&set_option_callback_);
+ read_buffer_ = NULL;
+ bytes_to_read_ = -1;
+ server_certificate_ = NULL;
+}
+
+int32_t TCPSocketShared::SetOptionImpl(
+ PP_TCPSocketOption_Private name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!IsConnected())
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(set_option_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ set_option_callback_ = callback;
+
+ switch (name) {
+ case PP_TCPSOCKETOPTION_NO_DELAY:
+ if (value.type != PP_VARTYPE_BOOL)
+ return PP_ERROR_BADARGUMENT;
+ SendSetBoolOption(name, PP_ToBool(value.value.as_bool));
+ return PP_OK_COMPLETIONPENDING;
+ default:
+ return PP_ERROR_BADARGUMENT;
+ }
+}
+
+void TCPSocketShared::Init(uint32 socket_id) {
+ DCHECK(socket_id != 0);
+ socket_id_ = socket_id;
+ connection_state_ = BEFORE_CONNECT;
+ read_buffer_ = NULL;
+ bytes_to_read_ = -1;
+
+ local_addr_.size = 0;
+ memset(local_addr_.data, 0,
+ arraysize(local_addr_.data) * sizeof(*local_addr_.data));
+ remote_addr_.size = 0;
+ memset(remote_addr_.data, 0,
+ arraysize(remote_addr_.data) * sizeof(*remote_addr_.data));
+}
+
+bool TCPSocketShared::IsConnected() const {
+ return connection_state_ == CONNECTED || connection_state_ == SSL_CONNECTED;
+}
+
+void TCPSocketShared::PostAbortIfNecessary(
+ scoped_refptr<TrackedCallback>* callback) {
+ if (TrackedCallback::IsPending(*callback))
+ (*callback)->PostAbort();
+}
+
+} // namespace ppapi
diff --git a/ppapi/shared_impl/tcp_socket_shared.h b/ppapi/shared_impl/tcp_socket_shared.h
new file mode 100644
index 0000000..bd5e56b
--- /dev/null
+++ b/ppapi/shared_impl/tcp_socket_shared.h
@@ -0,0 +1,133 @@
+// 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.
+
+#ifndef PPAPI_SHARED_IMPL_TCP_SOCKET_SHARED_H_
+#define PPAPI_SHARED_IMPL_TCP_SOCKET_SHARED_H_
+
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "ppapi/c/private/ppb_tcp_socket_private.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+
+namespace ppapi {
+
+class PPB_X509Certificate_Fields;
+class PPB_X509Certificate_Private_Shared;
+
+// This class provides the shared implementation for both PPB_TCPSocket and
+// PPB_TCPSocket_Private.
+class PPAPI_SHARED_EXPORT TCPSocketShared {
+ public:
+ // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Read
+ // message is allowed to request.
+ static const int32_t kMaxReadSize;
+ // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Write
+ // message is allowed to carry.
+ static const int32_t kMaxWriteSize;
+
+ // Notifications on operations completion.
+ void OnConnectCompleted(bool succeeded,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+ void OnSSLHandshakeCompleted(
+ bool succeeded,
+ const PPB_X509Certificate_Fields& certificate_fields);
+ void OnReadCompleted(bool succeeded, const std::string& data);
+ void OnWriteCompleted(bool succeeded, int32_t bytes_written);
+ void OnSetOptionCompleted(bool succeeded);
+
+ // Send functions that need to be implemented differently for the
+ // proxied and non-proxied derived classes.
+ virtual void SendConnect(const std::string& host, uint16_t port) = 0;
+ virtual void SendConnectWithNetAddress(const PP_NetAddress_Private& addr) = 0;
+ virtual void SendSSLHandshake(
+ 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) = 0;
+ virtual void SendRead(int32_t bytes_to_read) = 0;
+ virtual void SendWrite(const std::string& buffer) = 0;
+ virtual void SendDisconnect() = 0;
+ virtual void SendSetBoolOption(PP_TCPSocketOption_Private name,
+ bool value) = 0;
+
+ virtual Resource* GetOwnerResource() = 0;
+
+ protected:
+ enum ConnectionState {
+ // Before a connection is successfully established (including a connect
+ // request is pending or a previous connect request failed).
+ BEFORE_CONNECT,
+ // A connection has been successfully established (including a request of
+ // initiating SSL is pending).
+ CONNECTED,
+ // An SSL connection has been successfully established.
+ SSL_CONNECTED,
+ // The connection has been ended.
+ DISCONNECTED
+ };
+
+ TCPSocketShared(ResourceObjectType resource_type, uint32 socket_id);
+ virtual ~TCPSocketShared();
+
+ int32_t ConnectImpl(const char* host,
+ uint16_t port,
+ scoped_refptr<TrackedCallback> callback);
+ int32_t ConnectWithNetAddressImpl(const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback);
+ PP_Bool GetLocalAddressImpl(PP_NetAddress_Private* local_addr);
+ PP_Bool GetRemoteAddressImpl(PP_NetAddress_Private* remote_addr);
+ int32_t SSLHandshakeImpl(const char* server_name,
+ uint16_t server_port,
+ scoped_refptr<TrackedCallback> callback);
+ PP_Resource GetServerCertificateImpl();
+ PP_Bool AddChainBuildingCertificateImpl(PP_Resource certificate,
+ PP_Bool trusted);
+ int32_t ReadImpl(char* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback);
+ int32_t WriteImpl(const char* buffer,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback);
+ void DisconnectImpl();
+ int32_t SetOptionImpl(PP_TCPSocketOption_Private name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback);
+
+ void Init(uint32 socket_id);
+ bool IsConnected() const;
+ void PostAbortIfNecessary(scoped_refptr<TrackedCallback>* callback);
+
+ ResourceObjectType resource_type_;
+
+ uint32 socket_id_;
+ ConnectionState connection_state_;
+
+ scoped_refptr<TrackedCallback> connect_callback_;
+ scoped_refptr<TrackedCallback> ssl_handshake_callback_;
+ scoped_refptr<TrackedCallback> read_callback_;
+ scoped_refptr<TrackedCallback> write_callback_;
+ scoped_refptr<TrackedCallback> set_option_callback_;
+
+ char* read_buffer_;
+ int32_t bytes_to_read_;
+
+ PP_NetAddress_Private local_addr_;
+ PP_NetAddress_Private remote_addr_;
+
+ scoped_refptr<PPB_X509Certificate_Private_Shared> server_certificate_;
+
+ std::vector<std::vector<char> > trusted_certificates_;
+ std::vector<std::vector<char> > untrusted_certificates_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TCPSocketShared);
+};
+
+} // namespace ppapi
+
+#endif // PPAPI_SHARED_IMPL_TCP_SOCKET_SHARED_H_