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