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