Chromium Code Reviews| Index: chrome/browser/extensions/api/sockets_tcp/sockets_tcp_api.cc | 
| diff --git a/chrome/browser/extensions/api/sockets_tcp/sockets_tcp_api.cc b/chrome/browser/extensions/api/sockets_tcp/sockets_tcp_api.cc | 
| index fbf02dc0a1e0561a3a3e7ed3c3f0399a2e7e4974..ec3a4bd839e73f3ea9bee3f1d98fa84304e09a9d 100644 | 
| --- a/chrome/browser/extensions/api/sockets_tcp/sockets_tcp_api.cc | 
| +++ b/chrome/browser/extensions/api/sockets_tcp/sockets_tcp_api.cc | 
| @@ -5,10 +5,12 @@ | 
| #include "chrome/browser/extensions/api/sockets_tcp/sockets_tcp_api.h" | 
| #include "chrome/browser/extensions/api/socket/tcp_socket.h" | 
| +#include "chrome/browser/extensions/api/socket/tls_socket.h" | 
| #include "chrome/browser/extensions/api/sockets_tcp/tcp_socket_event_dispatcher.h" | 
| #include "chrome/common/extensions/api/sockets/sockets_manifest_data.h" | 
| #include "content/public/common/socket_permission_request.h" | 
| #include "net/base/net_errors.h" | 
| +#include "net/url_request/url_request_context_getter.h" | 
| using extensions::ResumableTCPSocket; | 
| using extensions::api::sockets_tcp::SocketInfo; | 
| @@ -18,6 +20,9 @@ namespace { | 
| const char kSocketNotFoundError[] = "Socket not found"; | 
| const char kPermissionError[] = "Does not have permission"; | 
| +const char kInvalidSocketStateError[] = | 
| + "Socket must be a connected client TCP socket."; | 
| +const char kSocketNotConnectedError[] = "Socket not connected"; | 
| linked_ptr<SocketInfo> CreateSocketInfo(int socket_id, | 
| ResumableTCPSocket* socket) { | 
| @@ -259,6 +264,8 @@ void SocketsTcpConnectFunction::AsyncWorkStart() { | 
| return; | 
| } | 
| + socket->set_hostname(params_->peer_address); | 
| + | 
| content::SocketPermissionRequest param( | 
| SocketPermissionRequest::TCP_CONNECT, | 
| params_->peer_address, | 
| @@ -440,5 +447,78 @@ void SocketsTcpGetSocketsFunction::Work() { | 
| results_ = sockets_tcp::GetSockets::Results::Create(socket_infos); | 
| } | 
| +SocketsTcpSecureFunction::SocketsTcpSecureFunction() {} | 
| +SocketsTcpSecureFunction::~SocketsTcpSecureFunction() {} | 
| + | 
| +bool SocketsTcpSecureFunction::Prepare() { | 
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 
| + params_ = api::socket::Secure::Params::Create(*args_); | 
| + EXTENSION_FUNCTION_VALIDATE(params_.get()); | 
| + url_request_getter_ = GetProfile()->GetRequestContext(); | 
| + return true; | 
| +} | 
| + | 
| +// Override the regular implementation, which would call AsyncWorkCompleted | 
| +// immediately after Work(). | 
| +void SocketsTcpSecureFunction::AsyncWorkStart() { | 
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 
| + | 
| + ResumableTCPSocket* socket(GetTcpSocket(params_->socket_id)); | 
| + if (!socket) { | 
| + SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT)); | 
| + error_ = kSocketNotFoundError; | 
| + AsyncWorkCompleted(); | 
| + return; | 
| + } | 
| + | 
| + paused_ = socket->paused(); | 
| + persistent_ = socket->persistent(); | 
| + | 
| + // Make sure it's a connected TCP client socket. Error out if it's already | 
| + // secure()'d. | 
| + if (socket->GetSocketType() == Socket::TYPE_TLS || | 
| + socket->ClientStream() == NULL) { | 
| + SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT)); | 
| + error_ = kInvalidSocketStateError; | 
| + AsyncWorkCompleted(); | 
| + return; | 
| + } | 
| + | 
| + if (!socket->IsConnected()) { | 
| + SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT)); | 
| + error_ = kSocketNotConnectedError; | 
| + AsyncWorkCompleted(); | 
| + return; | 
| + } | 
| + | 
| + Profile* profile = GetProfile(); | 
| 
 
Ryan Sleevi
2014/02/04 22:28:14
SECURITY: I don't think it's safe to do this from
 
lally
2014/02/11 22:05:35
This isn't the normal GetProfile() api.  It actual
 
 | 
| + DCHECK(profile); | 
| + | 
| + TLSSocket::UpgradeSocketToTLS( | 
| + socket, profile, url_request_getter_, extension_id(), | 
| 
 
Ryan Sleevi
2014/02/04 22:28:14
SECURITY: url_request_getter_ may be invalid by th
 
lally
2014/02/11 22:05:35
now in a scoped_refptr<>.
 
 | 
| + params_->options.get(), | 
| + base::Bind(&SocketsTcpSecureFunction::TlsConnectDone, | 
| + this)); | 
| +} | 
| + | 
| +void SocketsTcpSecureFunction::TlsConnectDone( | 
| + scoped_ptr<TLSSocket> socket, int result) { | 
| 
 
Ryan Sleevi
2014/02/04 22:28:14
STYLE: one parameter per line 
see http://www.chr
 
lally
2014/02/11 22:05:35
Thanks for the pointer.  I fixed this one.  A gene
 
 | 
| + // |socket| can only be non-null if |result| == net::OK. | 
| + DCHECK(result == net::OK || socket == NULL); | 
| + | 
| + if (socket && result == net::OK) { | 
| + socket->set_persistent(persistent_); | 
| + socket->set_paused(paused_); | 
| + SetSocket(params_->socket_id, socket.release()); | 
| + } else { | 
| + RemoveSocket(params_->socket_id); | 
| + error_ = net::ErrorToString(result); | 
| + } | 
| + | 
| + results_ = api::sockets_tcp::Secure::Results::Create(result); | 
| + url_request_getter_->Release(); | 
| 
 
Ryan Sleevi
2014/02/04 22:28:14
SECURITY: manual memory management?
 
lally
2014/02/11 22:05:35
Fixed.
 
 | 
| + AsyncWorkCompleted(); | 
| +} | 
| + | 
| } // namespace api | 
| } // namespace extensions |