Home | History | Annotate | Download | only in socket
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "extensions/browser/api/socket/socket_api.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/containers/hash_tables.h"
     11 #include "content/public/browser/browser_context.h"
     12 #include "content/public/browser/resource_context.h"
     13 #include "extensions/browser/api/dns/host_resolver_wrapper.h"
     14 #include "extensions/browser/api/socket/socket.h"
     15 #include "extensions/browser/api/socket/tcp_socket.h"
     16 #include "extensions/browser/api/socket/tls_socket.h"
     17 #include "extensions/browser/api/socket/udp_socket.h"
     18 #include "extensions/browser/extension_system.h"
     19 #include "extensions/common/extension.h"
     20 #include "extensions/common/permissions/permissions_data.h"
     21 #include "extensions/common/permissions/socket_permission.h"
     22 #include "net/base/host_port_pair.h"
     23 #include "net/base/io_buffer.h"
     24 #include "net/base/ip_endpoint.h"
     25 #include "net/base/net_errors.h"
     26 #include "net/base/net_log.h"
     27 #include "net/base/net_util.h"
     28 #include "net/url_request/url_request_context.h"
     29 #include "net/url_request/url_request_context_getter.h"
     30 
     31 namespace extensions {
     32 
     33 using content::SocketPermissionRequest;
     34 
     35 const char kAddressKey[] = "address";
     36 const char kPortKey[] = "port";
     37 const char kBytesWrittenKey[] = "bytesWritten";
     38 const char kDataKey[] = "data";
     39 const char kResultCodeKey[] = "resultCode";
     40 const char kSocketIdKey[] = "socketId";
     41 
     42 const char kSocketNotFoundError[] = "Socket not found";
     43 const char kDnsLookupFailedError[] = "DNS resolution failed";
     44 const char kPermissionError[] = "App does not have permission";
     45 const char kNetworkListError[] = "Network lookup failed or unsupported";
     46 const char kTCPSocketBindError[] =
     47     "TCP socket does not support bind. For TCP server please use listen.";
     48 const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast.";
     49 const char kSecureSocketTypeError[] = "Only TCP sockets are supported for TLS.";
     50 const char kSocketNotConnectedError[] = "Socket not connected";
     51 const char kWildcardAddress[] = "*";
     52 const int kWildcardPort = 0;
     53 
     54 SocketAsyncApiFunction::SocketAsyncApiFunction() {}
     55 
     56 SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
     57 
     58 bool SocketAsyncApiFunction::PrePrepare() {
     59   manager_ = CreateSocketResourceManager();
     60   return manager_->SetBrowserContext(browser_context());
     61 }
     62 
     63 bool SocketAsyncApiFunction::Respond() { return error_.empty(); }
     64 
     65 scoped_ptr<SocketResourceManagerInterface>
     66 SocketAsyncApiFunction::CreateSocketResourceManager() {
     67   return scoped_ptr<SocketResourceManagerInterface>(
     68              new SocketResourceManager<Socket>()).Pass();
     69 }
     70 
     71 int SocketAsyncApiFunction::AddSocket(Socket* socket) {
     72   return manager_->Add(socket);
     73 }
     74 
     75 Socket* SocketAsyncApiFunction::GetSocket(int api_resource_id) {
     76   return manager_->Get(extension_->id(), api_resource_id);
     77 }
     78 
     79 void SocketAsyncApiFunction::ReplaceSocket(int api_resource_id,
     80                                            Socket* socket) {
     81   manager_->Replace(extension_->id(), api_resource_id, socket);
     82 }
     83 
     84 base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() {
     85   return manager_->GetResourceIds(extension_->id());
     86 }
     87 
     88 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
     89   manager_->Remove(extension_->id(), api_resource_id);
     90 }
     91 
     92 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction()
     93     : resource_context_(NULL),
     94       request_handle_(new net::HostResolver::RequestHandle),
     95       addresses_(new net::AddressList) {}
     96 
     97 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {}
     98 
     99 bool SocketExtensionWithDnsLookupFunction::PrePrepare() {
    100   if (!SocketAsyncApiFunction::PrePrepare())
    101     return false;
    102   resource_context_ = browser_context()->GetResourceContext();
    103   return resource_context_ != NULL;
    104 }
    105 
    106 void SocketExtensionWithDnsLookupFunction::StartDnsLookup(
    107     const std::string& hostname) {
    108   net::HostResolver* host_resolver =
    109       HostResolverWrapper::GetInstance()->GetHostResolver(resource_context_);
    110   DCHECK(host_resolver);
    111 
    112   // Yes, we are passing zero as the port. There are some interesting but not
    113   // presently relevant reasons why HostResolver asks for the port of the
    114   // hostname you'd like to resolve, even though it doesn't use that value in
    115   // determining its answer.
    116   net::HostPortPair host_port_pair(hostname, 0);
    117 
    118   net::HostResolver::RequestInfo request_info(host_port_pair);
    119   int resolve_result = host_resolver->Resolve(
    120       request_info,
    121       net::DEFAULT_PRIORITY,
    122       addresses_.get(),
    123       base::Bind(&SocketExtensionWithDnsLookupFunction::OnDnsLookup, this),
    124       request_handle_.get(),
    125       net::BoundNetLog());
    126 
    127   if (resolve_result != net::ERR_IO_PENDING)
    128     OnDnsLookup(resolve_result);
    129 }
    130 
    131 void SocketExtensionWithDnsLookupFunction::OnDnsLookup(int resolve_result) {
    132   if (resolve_result == net::OK) {
    133     DCHECK(!addresses_->empty());
    134     resolved_address_ = addresses_->front().ToStringWithoutPort();
    135   } else {
    136     error_ = kDnsLookupFailedError;
    137   }
    138   AfterDnsLookup(resolve_result);
    139 }
    140 
    141 SocketCreateFunction::SocketCreateFunction()
    142     : socket_type_(kSocketTypeInvalid) {}
    143 
    144 SocketCreateFunction::~SocketCreateFunction() {}
    145 
    146 bool SocketCreateFunction::Prepare() {
    147   params_ = core_api::socket::Create::Params::Create(*args_);
    148   EXTENSION_FUNCTION_VALIDATE(params_.get());
    149 
    150   switch (params_->type) {
    151     case extensions::core_api::socket::SOCKET_TYPE_TCP:
    152       socket_type_ = kSocketTypeTCP;
    153       break;
    154     case extensions::core_api::socket::SOCKET_TYPE_UDP:
    155       socket_type_ = kSocketTypeUDP;
    156       break;
    157     case extensions::core_api::socket::SOCKET_TYPE_NONE:
    158       NOTREACHED();
    159       break;
    160   }
    161 
    162   return true;
    163 }
    164 
    165 void SocketCreateFunction::Work() {
    166   Socket* socket = NULL;
    167   if (socket_type_ == kSocketTypeTCP) {
    168     socket = new TCPSocket(extension_->id());
    169   } else if (socket_type_ == kSocketTypeUDP) {
    170     socket = new UDPSocket(extension_->id());
    171   }
    172   DCHECK(socket);
    173 
    174   base::DictionaryValue* result = new base::DictionaryValue();
    175   result->SetInteger(kSocketIdKey, AddSocket(socket));
    176   SetResult(result);
    177 }
    178 
    179 bool SocketDestroyFunction::Prepare() {
    180   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
    181   return true;
    182 }
    183 
    184 void SocketDestroyFunction::Work() { RemoveSocket(socket_id_); }
    185 
    186 SocketConnectFunction::SocketConnectFunction()
    187     : socket_id_(0), hostname_(), port_(0), socket_(NULL) {}
    188 
    189 SocketConnectFunction::~SocketConnectFunction() {}
    190 
    191 bool SocketConnectFunction::Prepare() {
    192   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
    193   EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &hostname_));
    194   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_));
    195   return true;
    196 }
    197 
    198 void SocketConnectFunction::AsyncWorkStart() {
    199   socket_ = GetSocket(socket_id_);
    200   if (!socket_) {
    201     error_ = kSocketNotFoundError;
    202     SetResult(new base::FundamentalValue(-1));
    203     AsyncWorkCompleted();
    204     return;
    205   }
    206 
    207   socket_->set_hostname(hostname_);
    208 
    209   SocketPermissionRequest::OperationType operation_type;
    210   switch (socket_->GetSocketType()) {
    211     case Socket::TYPE_TCP:
    212       operation_type = SocketPermissionRequest::TCP_CONNECT;
    213       break;
    214     case Socket::TYPE_UDP:
    215       operation_type = SocketPermissionRequest::UDP_SEND_TO;
    216       break;
    217     default:
    218       NOTREACHED() << "Unknown socket type.";
    219       operation_type = SocketPermissionRequest::NONE;
    220       break;
    221   }
    222 
    223   SocketPermission::CheckParam param(operation_type, hostname_, port_);
    224   if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
    225           APIPermission::kSocket, &param)) {
    226     error_ = kPermissionError;
    227     SetResult(new base::FundamentalValue(-1));
    228     AsyncWorkCompleted();
    229     return;
    230   }
    231 
    232   StartDnsLookup(hostname_);
    233 }
    234 
    235 void SocketConnectFunction::AfterDnsLookup(int lookup_result) {
    236   if (lookup_result == net::OK) {
    237     StartConnect();
    238   } else {
    239     SetResult(new base::FundamentalValue(lookup_result));
    240     AsyncWorkCompleted();
    241   }
    242 }
    243 
    244 void SocketConnectFunction::StartConnect() {
    245   socket_->Connect(resolved_address_,
    246                    port_,
    247                    base::Bind(&SocketConnectFunction::OnConnect, this));
    248 }
    249 
    250 void SocketConnectFunction::OnConnect(int result) {
    251   SetResult(new base::FundamentalValue(result));
    252   AsyncWorkCompleted();
    253 }
    254 
    255 bool SocketDisconnectFunction::Prepare() {
    256   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
    257   return true;
    258 }
    259 
    260 void SocketDisconnectFunction::Work() {
    261   Socket* socket = GetSocket(socket_id_);
    262   if (socket)
    263     socket->Disconnect();
    264   else
    265     error_ = kSocketNotFoundError;
    266   SetResult(base::Value::CreateNullValue());
    267 }
    268 
    269 bool SocketBindFunction::Prepare() {
    270   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
    271   EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_));
    272   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_));
    273   return true;
    274 }
    275 
    276 void SocketBindFunction::Work() {
    277   int result = -1;
    278   Socket* socket = GetSocket(socket_id_);
    279 
    280   if (!socket) {
    281     error_ = kSocketNotFoundError;
    282     SetResult(new base::FundamentalValue(result));
    283     return;
    284   }
    285 
    286   if (socket->GetSocketType() == Socket::TYPE_UDP) {
    287     SocketPermission::CheckParam param(
    288         SocketPermissionRequest::UDP_BIND, address_, port_);
    289     if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
    290             APIPermission::kSocket, &param)) {
    291       error_ = kPermissionError;
    292       SetResult(new base::FundamentalValue(result));
    293       return;
    294     }
    295   } else if (socket->GetSocketType() == Socket::TYPE_TCP) {
    296     error_ = kTCPSocketBindError;
    297     SetResult(new base::FundamentalValue(result));
    298     return;
    299   }
    300 
    301   result = socket->Bind(address_, port_);
    302   SetResult(new base::FundamentalValue(result));
    303 }
    304 
    305 SocketListenFunction::SocketListenFunction() {}
    306 
    307 SocketListenFunction::~SocketListenFunction() {}
    308 
    309 bool SocketListenFunction::Prepare() {
    310   params_ = core_api::socket::Listen::Params::Create(*args_);
    311   EXTENSION_FUNCTION_VALIDATE(params_.get());
    312   return true;
    313 }
    314 
    315 void SocketListenFunction::Work() {
    316   int result = -1;
    317 
    318   Socket* socket = GetSocket(params_->socket_id);
    319   if (socket) {
    320     SocketPermission::CheckParam param(
    321         SocketPermissionRequest::TCP_LISTEN, params_->address, params_->port);
    322     if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
    323             APIPermission::kSocket, &param)) {
    324       error_ = kPermissionError;
    325       SetResult(new base::FundamentalValue(result));
    326       return;
    327     }
    328 
    329     result =
    330         socket->Listen(params_->address,
    331                        params_->port,
    332                        params_->backlog.get() ? *params_->backlog.get() : 5,
    333                        &error_);
    334   } else {
    335     error_ = kSocketNotFoundError;
    336   }
    337 
    338   SetResult(new base::FundamentalValue(result));
    339 }
    340 
    341 SocketAcceptFunction::SocketAcceptFunction() {}
    342 
    343 SocketAcceptFunction::~SocketAcceptFunction() {}
    344 
    345 bool SocketAcceptFunction::Prepare() {
    346   params_ = core_api::socket::Accept::Params::Create(*args_);
    347   EXTENSION_FUNCTION_VALIDATE(params_.get());
    348   return true;
    349 }
    350 
    351 void SocketAcceptFunction::AsyncWorkStart() {
    352   Socket* socket = GetSocket(params_->socket_id);
    353   if (socket) {
    354     socket->Accept(base::Bind(&SocketAcceptFunction::OnAccept, this));
    355   } else {
    356     error_ = kSocketNotFoundError;
    357     OnAccept(-1, NULL);
    358   }
    359 }
    360 
    361 void SocketAcceptFunction::OnAccept(int result_code,
    362                                     net::TCPClientSocket* socket) {
    363   base::DictionaryValue* result = new base::DictionaryValue();
    364   result->SetInteger(kResultCodeKey, result_code);
    365   if (socket) {
    366     Socket* client_socket = new TCPSocket(socket, extension_id(), true);
    367     result->SetInteger(kSocketIdKey, AddSocket(client_socket));
    368   }
    369   SetResult(result);
    370 
    371   AsyncWorkCompleted();
    372 }
    373 
    374 SocketReadFunction::SocketReadFunction() {}
    375 
    376 SocketReadFunction::~SocketReadFunction() {}
    377 
    378 bool SocketReadFunction::Prepare() {
    379   params_ = core_api::socket::Read::Params::Create(*args_);
    380   EXTENSION_FUNCTION_VALIDATE(params_.get());
    381   return true;
    382 }
    383 
    384 void SocketReadFunction::AsyncWorkStart() {
    385   Socket* socket = GetSocket(params_->socket_id);
    386   if (!socket) {
    387     error_ = kSocketNotFoundError;
    388     OnCompleted(-1, NULL);
    389     return;
    390   }
    391 
    392   socket->Read(params_->buffer_size.get() ? *params_->buffer_size.get() : 4096,
    393                base::Bind(&SocketReadFunction::OnCompleted, this));
    394 }
    395 
    396 void SocketReadFunction::OnCompleted(int bytes_read,
    397                                      scoped_refptr<net::IOBuffer> io_buffer) {
    398   base::DictionaryValue* result = new base::DictionaryValue();
    399   result->SetInteger(kResultCodeKey, bytes_read);
    400   if (bytes_read > 0) {
    401     result->Set(kDataKey,
    402                 base::BinaryValue::CreateWithCopiedBuffer(io_buffer->data(),
    403                                                           bytes_read));
    404   } else {
    405     result->Set(kDataKey, new base::BinaryValue());
    406   }
    407   SetResult(result);
    408 
    409   AsyncWorkCompleted();
    410 }
    411 
    412 SocketWriteFunction::SocketWriteFunction()
    413     : socket_id_(0), io_buffer_(NULL), io_buffer_size_(0) {}
    414 
    415 SocketWriteFunction::~SocketWriteFunction() {}
    416 
    417 bool SocketWriteFunction::Prepare() {
    418   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
    419   base::BinaryValue* data = NULL;
    420   EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data));
    421 
    422   io_buffer_size_ = data->GetSize();
    423   io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer());
    424   return true;
    425 }
    426 
    427 void SocketWriteFunction::AsyncWorkStart() {
    428   Socket* socket = GetSocket(socket_id_);
    429 
    430   if (!socket) {
    431     error_ = kSocketNotFoundError;
    432     OnCompleted(-1);
    433     return;
    434   }
    435 
    436   socket->Write(io_buffer_,
    437                 io_buffer_size_,
    438                 base::Bind(&SocketWriteFunction::OnCompleted, this));
    439 }
    440 
    441 void SocketWriteFunction::OnCompleted(int bytes_written) {
    442   base::DictionaryValue* result = new base::DictionaryValue();
    443   result->SetInteger(kBytesWrittenKey, bytes_written);
    444   SetResult(result);
    445 
    446   AsyncWorkCompleted();
    447 }
    448 
    449 SocketRecvFromFunction::SocketRecvFromFunction() {}
    450 
    451 SocketRecvFromFunction::~SocketRecvFromFunction() {}
    452 
    453 bool SocketRecvFromFunction::Prepare() {
    454   params_ = core_api::socket::RecvFrom::Params::Create(*args_);
    455   EXTENSION_FUNCTION_VALIDATE(params_.get());
    456   return true;
    457 }
    458 
    459 void SocketRecvFromFunction::AsyncWorkStart() {
    460   Socket* socket = GetSocket(params_->socket_id);
    461   if (!socket) {
    462     error_ = kSocketNotFoundError;
    463     OnCompleted(-1, NULL, std::string(), 0);
    464     return;
    465   }
    466 
    467   socket->RecvFrom(params_->buffer_size.get() ? *params_->buffer_size : 4096,
    468                    base::Bind(&SocketRecvFromFunction::OnCompleted, this));
    469 }
    470 
    471 void SocketRecvFromFunction::OnCompleted(int bytes_read,
    472                                          scoped_refptr<net::IOBuffer> io_buffer,
    473                                          const std::string& address,
    474                                          int port) {
    475   base::DictionaryValue* result = new base::DictionaryValue();
    476   result->SetInteger(kResultCodeKey, bytes_read);
    477   if (bytes_read > 0) {
    478     result->Set(kDataKey,
    479                 base::BinaryValue::CreateWithCopiedBuffer(io_buffer->data(),
    480                                                           bytes_read));
    481   } else {
    482     result->Set(kDataKey, new base::BinaryValue());
    483   }
    484   result->SetString(kAddressKey, address);
    485   result->SetInteger(kPortKey, port);
    486   SetResult(result);
    487 
    488   AsyncWorkCompleted();
    489 }
    490 
    491 SocketSendToFunction::SocketSendToFunction()
    492     : socket_id_(0),
    493       io_buffer_(NULL),
    494       io_buffer_size_(0),
    495       port_(0),
    496       socket_(NULL) {}
    497 
    498 SocketSendToFunction::~SocketSendToFunction() {}
    499 
    500 bool SocketSendToFunction::Prepare() {
    501   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
    502   base::BinaryValue* data = NULL;
    503   EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data));
    504   EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &hostname_));
    505   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(3, &port_));
    506 
    507   io_buffer_size_ = data->GetSize();
    508   io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer());
    509   return true;
    510 }
    511 
    512 void SocketSendToFunction::AsyncWorkStart() {
    513   socket_ = GetSocket(socket_id_);
    514   if (!socket_) {
    515     error_ = kSocketNotFoundError;
    516     SetResult(new base::FundamentalValue(-1));
    517     AsyncWorkCompleted();
    518     return;
    519   }
    520 
    521   if (socket_->GetSocketType() == Socket::TYPE_UDP) {
    522     SocketPermission::CheckParam param(
    523         SocketPermissionRequest::UDP_SEND_TO, hostname_, port_);
    524     if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
    525             APIPermission::kSocket, &param)) {
    526       error_ = kPermissionError;
    527       SetResult(new base::FundamentalValue(-1));
    528       AsyncWorkCompleted();
    529       return;
    530     }
    531   }
    532 
    533   StartDnsLookup(hostname_);
    534 }
    535 
    536 void SocketSendToFunction::AfterDnsLookup(int lookup_result) {
    537   if (lookup_result == net::OK) {
    538     StartSendTo();
    539   } else {
    540     SetResult(new base::FundamentalValue(lookup_result));
    541     AsyncWorkCompleted();
    542   }
    543 }
    544 
    545 void SocketSendToFunction::StartSendTo() {
    546   socket_->SendTo(io_buffer_,
    547                   io_buffer_size_,
    548                   resolved_address_,
    549                   port_,
    550                   base::Bind(&SocketSendToFunction::OnCompleted, this));
    551 }
    552 
    553 void SocketSendToFunction::OnCompleted(int bytes_written) {
    554   base::DictionaryValue* result = new base::DictionaryValue();
    555   result->SetInteger(kBytesWrittenKey, bytes_written);
    556   SetResult(result);
    557 
    558   AsyncWorkCompleted();
    559 }
    560 
    561 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
    562 
    563 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
    564 
    565 bool SocketSetKeepAliveFunction::Prepare() {
    566   params_ = core_api::socket::SetKeepAlive::Params::Create(*args_);
    567   EXTENSION_FUNCTION_VALIDATE(params_.get());
    568   return true;
    569 }
    570 
    571 void SocketSetKeepAliveFunction::Work() {
    572   bool result = false;
    573   Socket* socket = GetSocket(params_->socket_id);
    574   if (socket) {
    575     int delay = 0;
    576     if (params_->delay.get())
    577       delay = *params_->delay;
    578     result = socket->SetKeepAlive(params_->enable, delay);
    579   } else {
    580     error_ = kSocketNotFoundError;
    581   }
    582   SetResult(new base::FundamentalValue(result));
    583 }
    584 
    585 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
    586 
    587 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
    588 
    589 bool SocketSetNoDelayFunction::Prepare() {
    590   params_ = core_api::socket::SetNoDelay::Params::Create(*args_);
    591   EXTENSION_FUNCTION_VALIDATE(params_.get());
    592   return true;
    593 }
    594 
    595 void SocketSetNoDelayFunction::Work() {
    596   bool result = false;
    597   Socket* socket = GetSocket(params_->socket_id);
    598   if (socket)
    599     result = socket->SetNoDelay(params_->no_delay);
    600   else
    601     error_ = kSocketNotFoundError;
    602   SetResult(new base::FundamentalValue(result));
    603 }
    604 
    605 SocketGetInfoFunction::SocketGetInfoFunction() {}
    606 
    607 SocketGetInfoFunction::~SocketGetInfoFunction() {}
    608 
    609 bool SocketGetInfoFunction::Prepare() {
    610   params_ = core_api::socket::GetInfo::Params::Create(*args_);
    611   EXTENSION_FUNCTION_VALIDATE(params_.get());
    612   return true;
    613 }
    614 
    615 void SocketGetInfoFunction::Work() {
    616   Socket* socket = GetSocket(params_->socket_id);
    617   if (!socket) {
    618     error_ = kSocketNotFoundError;
    619     return;
    620   }
    621 
    622   core_api::socket::SocketInfo info;
    623   // This represents what we know about the socket, and does not call through
    624   // to the system.
    625   if (socket->GetSocketType() == Socket::TYPE_TCP)
    626     info.socket_type = extensions::core_api::socket::SOCKET_TYPE_TCP;
    627   else
    628     info.socket_type = extensions::core_api::socket::SOCKET_TYPE_UDP;
    629   info.connected = socket->IsConnected();
    630 
    631   // Grab the peer address as known by the OS. This and the call below will
    632   // always succeed while the socket is connected, even if the socket has
    633   // been remotely closed by the peer; only reading the socket will reveal
    634   // that it should be closed locally.
    635   net::IPEndPoint peerAddress;
    636   if (socket->GetPeerAddress(&peerAddress)) {
    637     info.peer_address.reset(new std::string(peerAddress.ToStringWithoutPort()));
    638     info.peer_port.reset(new int(peerAddress.port()));
    639   }
    640 
    641   // Grab the local address as known by the OS.
    642   net::IPEndPoint localAddress;
    643   if (socket->GetLocalAddress(&localAddress)) {
    644     info.local_address.reset(
    645         new std::string(localAddress.ToStringWithoutPort()));
    646     info.local_port.reset(new int(localAddress.port()));
    647   }
    648 
    649   SetResult(info.ToValue().release());
    650 }
    651 
    652 bool SocketGetNetworkListFunction::RunAsync() {
    653   content::BrowserThread::PostTask(
    654       content::BrowserThread::FILE,
    655       FROM_HERE,
    656       base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread,
    657                  this));
    658   return true;
    659 }
    660 
    661 void SocketGetNetworkListFunction::GetNetworkListOnFileThread() {
    662   net::NetworkInterfaceList interface_list;
    663   if (GetNetworkList(&interface_list,
    664                      net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
    665     content::BrowserThread::PostTask(
    666         content::BrowserThread::UI,
    667         FROM_HERE,
    668         base::Bind(&SocketGetNetworkListFunction::SendResponseOnUIThread,
    669                    this,
    670                    interface_list));
    671     return;
    672   }
    673 
    674   content::BrowserThread::PostTask(
    675       content::BrowserThread::UI,
    676       FROM_HERE,
    677       base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError,
    678                  this));
    679 }
    680 
    681 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
    682   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    683   error_ = kNetworkListError;
    684   SendResponse(false);
    685 }
    686 
    687 void SocketGetNetworkListFunction::SendResponseOnUIThread(
    688     const net::NetworkInterfaceList& interface_list) {
    689   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    690 
    691   std::vector<linked_ptr<core_api::socket::NetworkInterface> > create_arg;
    692   create_arg.reserve(interface_list.size());
    693   for (net::NetworkInterfaceList::const_iterator i = interface_list.begin();
    694        i != interface_list.end();
    695        ++i) {
    696     linked_ptr<core_api::socket::NetworkInterface> info =
    697         make_linked_ptr(new core_api::socket::NetworkInterface);
    698     info->name = i->name;
    699     info->address = net::IPAddressToString(i->address);
    700     info->prefix_length = i->network_prefix;
    701     create_arg.push_back(info);
    702   }
    703 
    704   results_ = core_api::socket::GetNetworkList::Results::Create(create_arg);
    705   SendResponse(true);
    706 }
    707 
    708 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
    709 
    710 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
    711 
    712 bool SocketJoinGroupFunction::Prepare() {
    713   params_ = core_api::socket::JoinGroup::Params::Create(*args_);
    714   EXTENSION_FUNCTION_VALIDATE(params_.get());
    715   return true;
    716 }
    717 
    718 void SocketJoinGroupFunction::Work() {
    719   int result = -1;
    720   Socket* socket = GetSocket(params_->socket_id);
    721   if (!socket) {
    722     error_ = kSocketNotFoundError;
    723     SetResult(new base::FundamentalValue(result));
    724     return;
    725   }
    726 
    727   if (socket->GetSocketType() != Socket::TYPE_UDP) {
    728     error_ = kMulticastSocketTypeError;
    729     SetResult(new base::FundamentalValue(result));
    730     return;
    731   }
    732 
    733   SocketPermission::CheckParam param(
    734       SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
    735       kWildcardAddress,
    736       kWildcardPort);
    737 
    738   if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
    739           APIPermission::kSocket, &param)) {
    740     error_ = kPermissionError;
    741     SetResult(new base::FundamentalValue(result));
    742     return;
    743   }
    744 
    745   result = static_cast<UDPSocket*>(socket)->JoinGroup(params_->address);
    746   if (result != 0) {
    747     error_ = net::ErrorToString(result);
    748   }
    749   SetResult(new base::FundamentalValue(result));
    750 }
    751 
    752 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
    753 
    754 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
    755 
    756 bool SocketLeaveGroupFunction::Prepare() {
    757   params_ = core_api::socket::LeaveGroup::Params::Create(*args_);
    758   EXTENSION_FUNCTION_VALIDATE(params_.get());
    759   return true;
    760 }
    761 
    762 void SocketLeaveGroupFunction::Work() {
    763   int result = -1;
    764   Socket* socket = GetSocket(params_->socket_id);
    765 
    766   if (!socket) {
    767     error_ = kSocketNotFoundError;
    768     SetResult(new base::FundamentalValue(result));
    769     return;
    770   }
    771 
    772   if (socket->GetSocketType() != Socket::TYPE_UDP) {
    773     error_ = kMulticastSocketTypeError;
    774     SetResult(new base::FundamentalValue(result));
    775     return;
    776   }
    777 
    778   SocketPermission::CheckParam param(
    779       SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
    780       kWildcardAddress,
    781       kWildcardPort);
    782   if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
    783           APIPermission::kSocket, &param)) {
    784     error_ = kPermissionError;
    785     SetResult(new base::FundamentalValue(result));
    786     return;
    787   }
    788 
    789   result = static_cast<UDPSocket*>(socket)->LeaveGroup(params_->address);
    790   if (result != 0)
    791     error_ = net::ErrorToString(result);
    792   SetResult(new base::FundamentalValue(result));
    793 }
    794 
    795 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
    796 
    797 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
    798 
    799 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
    800   params_ = core_api::socket::SetMulticastTimeToLive::Params::Create(*args_);
    801   EXTENSION_FUNCTION_VALIDATE(params_.get());
    802   return true;
    803 }
    804 void SocketSetMulticastTimeToLiveFunction::Work() {
    805   int result = -1;
    806   Socket* socket = GetSocket(params_->socket_id);
    807   if (!socket) {
    808     error_ = kSocketNotFoundError;
    809     SetResult(new base::FundamentalValue(result));
    810     return;
    811   }
    812 
    813   if (socket->GetSocketType() != Socket::TYPE_UDP) {
    814     error_ = kMulticastSocketTypeError;
    815     SetResult(new base::FundamentalValue(result));
    816     return;
    817   }
    818 
    819   result =
    820       static_cast<UDPSocket*>(socket)->SetMulticastTimeToLive(params_->ttl);
    821   if (result != 0)
    822     error_ = net::ErrorToString(result);
    823   SetResult(new base::FundamentalValue(result));
    824 }
    825 
    826 SocketSetMulticastLoopbackModeFunction::
    827     SocketSetMulticastLoopbackModeFunction() {}
    828 
    829 SocketSetMulticastLoopbackModeFunction::
    830     ~SocketSetMulticastLoopbackModeFunction() {}
    831 
    832 bool SocketSetMulticastLoopbackModeFunction::Prepare() {
    833   params_ = core_api::socket::SetMulticastLoopbackMode::Params::Create(*args_);
    834   EXTENSION_FUNCTION_VALIDATE(params_.get());
    835   return true;
    836 }
    837 
    838 void SocketSetMulticastLoopbackModeFunction::Work() {
    839   int result = -1;
    840   Socket* socket = GetSocket(params_->socket_id);
    841   if (!socket) {
    842     error_ = kSocketNotFoundError;
    843     SetResult(new base::FundamentalValue(result));
    844     return;
    845   }
    846 
    847   if (socket->GetSocketType() != Socket::TYPE_UDP) {
    848     error_ = kMulticastSocketTypeError;
    849     SetResult(new base::FundamentalValue(result));
    850     return;
    851   }
    852 
    853   result = static_cast<UDPSocket*>(socket)
    854                ->SetMulticastLoopbackMode(params_->enabled);
    855   if (result != 0)
    856     error_ = net::ErrorToString(result);
    857   SetResult(new base::FundamentalValue(result));
    858 }
    859 
    860 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
    861 
    862 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
    863 
    864 bool SocketGetJoinedGroupsFunction::Prepare() {
    865   params_ = core_api::socket::GetJoinedGroups::Params::Create(*args_);
    866   EXTENSION_FUNCTION_VALIDATE(params_.get());
    867   return true;
    868 }
    869 
    870 void SocketGetJoinedGroupsFunction::Work() {
    871   int result = -1;
    872   Socket* socket = GetSocket(params_->socket_id);
    873   if (!socket) {
    874     error_ = kSocketNotFoundError;
    875     SetResult(new base::FundamentalValue(result));
    876     return;
    877   }
    878 
    879   if (socket->GetSocketType() != Socket::TYPE_UDP) {
    880     error_ = kMulticastSocketTypeError;
    881     SetResult(new base::FundamentalValue(result));
    882     return;
    883   }
    884 
    885   SocketPermission::CheckParam param(
    886       SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
    887       kWildcardAddress,
    888       kWildcardPort);
    889   if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
    890           APIPermission::kSocket, &param)) {
    891     error_ = kPermissionError;
    892     SetResult(new base::FundamentalValue(result));
    893     return;
    894   }
    895 
    896   base::ListValue* values = new base::ListValue();
    897   values->AppendStrings((std::vector<std::string>&)static_cast<UDPSocket*>(
    898                             socket)->GetJoinedGroups());
    899   SetResult(values);
    900 }
    901 
    902 SocketSecureFunction::SocketSecureFunction() {
    903 }
    904 
    905 SocketSecureFunction::~SocketSecureFunction() {
    906 }
    907 
    908 bool SocketSecureFunction::Prepare() {
    909   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    910   params_ = core_api::socket::Secure::Params::Create(*args_);
    911   EXTENSION_FUNCTION_VALIDATE(params_.get());
    912   url_request_getter_ = browser_context()->GetRequestContext();
    913   return true;
    914 }
    915 
    916 // Override the regular implementation, which would call AsyncWorkCompleted
    917 // immediately after Work().
    918 void SocketSecureFunction::AsyncWorkStart() {
    919   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
    920 
    921   Socket* socket = GetSocket(params_->socket_id);
    922   if (!socket) {
    923     SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
    924     error_ = kSocketNotFoundError;
    925     AsyncWorkCompleted();
    926     return;
    927   }
    928 
    929   // Make sure that the socket is a TCP client socket.
    930   if (socket->GetSocketType() != Socket::TYPE_TCP ||
    931       static_cast<TCPSocket*>(socket)->ClientStream() == NULL) {
    932     SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
    933     error_ = kSecureSocketTypeError;
    934     AsyncWorkCompleted();
    935     return;
    936   }
    937 
    938   if (!socket->IsConnected()) {
    939     SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
    940     error_ = kSocketNotConnectedError;
    941     AsyncWorkCompleted();
    942     return;
    943   }
    944 
    945   net::URLRequestContext* url_request_context =
    946       url_request_getter_->GetURLRequestContext();
    947 
    948   TLSSocket::UpgradeSocketToTLS(
    949       socket,
    950       url_request_context->ssl_config_service(),
    951       url_request_context->cert_verifier(),
    952       url_request_context->transport_security_state(),
    953       extension_id(),
    954       params_->options.get(),
    955       base::Bind(&SocketSecureFunction::TlsConnectDone, this));
    956 }
    957 
    958 void SocketSecureFunction::TlsConnectDone(scoped_ptr<TLSSocket> socket,
    959                                           int result) {
    960   // if an error occurred, socket MUST be NULL.
    961   DCHECK(result == net::OK || socket == NULL);
    962 
    963   if (socket && result == net::OK) {
    964     ReplaceSocket(params_->socket_id, socket.release());
    965   } else {
    966     RemoveSocket(params_->socket_id);
    967     error_ = net::ErrorToString(result);
    968   }
    969 
    970   results_ = core_api::socket::Secure::Results::Create(result);
    971   AsyncWorkCompleted();
    972 }
    973 
    974 }  // namespace extensions
    975