socket_api.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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
28namespace extensions {
29
30using content::SocketPermissionRequest;
31
32const char kAddressKey[] = "address";
33const char kPortKey[] = "port";
34const char kBytesWrittenKey[] = "bytesWritten";
35const char kDataKey[] = "data";
36const char kResultCodeKey[] = "resultCode";
37const char kSocketIdKey[] = "socketId";
38
39const char kSocketNotFoundError[] = "Socket not found";
40const char kDnsLookupFailedError[] = "DNS resolution failed";
41const char kPermissionError[] = "App does not have permission";
42const char kNetworkListError[] = "Network lookup failed or unsupported";
43const char kTCPSocketBindError[] =
44    "TCP socket does not support bind. For TCP server please use listen.";
45const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast.";
46const char kWildcardAddress[] = "*";
47const int kWildcardPort = 0;
48
49SocketAsyncApiFunction::SocketAsyncApiFunction() {}
50
51SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
52
53bool SocketAsyncApiFunction::PrePrepare() {
54  manager_ = CreateSocketResourceManager();
55  return manager_->SetBrowserContext(browser_context());
56}
57
58bool SocketAsyncApiFunction::Respond() { return error_.empty(); }
59
60scoped_ptr<SocketResourceManagerInterface>
61SocketAsyncApiFunction::CreateSocketResourceManager() {
62  return scoped_ptr<SocketResourceManagerInterface>(
63             new SocketResourceManager<Socket>()).Pass();
64}
65
66int SocketAsyncApiFunction::AddSocket(Socket* socket) {
67  return manager_->Add(socket);
68}
69
70Socket* SocketAsyncApiFunction::GetSocket(int api_resource_id) {
71  return manager_->Get(extension_->id(), api_resource_id);
72}
73
74base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() {
75  return manager_->GetResourceIds(extension_->id());
76}
77
78void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
79  manager_->Remove(extension_->id(), api_resource_id);
80}
81
82SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction()
83    : resource_context_(NULL),
84      request_handle_(new net::HostResolver::RequestHandle),
85      addresses_(new net::AddressList) {}
86
87SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {}
88
89bool SocketExtensionWithDnsLookupFunction::PrePrepare() {
90  if (!SocketAsyncApiFunction::PrePrepare())
91    return false;
92  resource_context_ = browser_context()->GetResourceContext();
93  return resource_context_ != NULL;
94}
95
96void 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
122void 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
132SocketCreateFunction::SocketCreateFunction()
133    : socket_type_(kSocketTypeInvalid) {}
134
135SocketCreateFunction::~SocketCreateFunction() {}
136
137bool 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
156void 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
170bool SocketDestroyFunction::Prepare() {
171  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
172  return true;
173}
174
175void SocketDestroyFunction::Work() { RemoveSocket(socket_id_); }
176
177SocketConnectFunction::SocketConnectFunction()
178    : socket_id_(0), hostname_(), port_(0), socket_(NULL) {}
179
180SocketConnectFunction::~SocketConnectFunction() {}
181
182bool 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
189void 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 (!PermissionsData::CheckAPIPermissionWithParam(
214          GetExtension(), APIPermission::kSocket, &param)) {
215    error_ = kPermissionError;
216    SetResult(new base::FundamentalValue(-1));
217    AsyncWorkCompleted();
218    return;
219  }
220
221  StartDnsLookup(hostname_);
222}
223
224void 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
233void SocketConnectFunction::StartConnect() {
234  socket_->Connect(resolved_address_,
235                   port_,
236                   base::Bind(&SocketConnectFunction::OnConnect, this));
237}
238
239void SocketConnectFunction::OnConnect(int result) {
240  SetResult(new base::FundamentalValue(result));
241  AsyncWorkCompleted();
242}
243
244bool SocketDisconnectFunction::Prepare() {
245  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
246  return true;
247}
248
249void 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
258bool 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
265void 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 (!PermissionsData::CheckAPIPermissionWithParam(
279            GetExtension(), 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
294SocketListenFunction::SocketListenFunction() {}
295
296SocketListenFunction::~SocketListenFunction() {}
297
298bool SocketListenFunction::Prepare() {
299  params_ = core_api::socket::Listen::Params::Create(*args_);
300  EXTENSION_FUNCTION_VALIDATE(params_.get());
301  return true;
302}
303
304void 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 (!PermissionsData::CheckAPIPermissionWithParam(
312            GetExtension(), 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
330SocketAcceptFunction::SocketAcceptFunction() {}
331
332SocketAcceptFunction::~SocketAcceptFunction() {}
333
334bool SocketAcceptFunction::Prepare() {
335  params_ = core_api::socket::Accept::Params::Create(*args_);
336  EXTENSION_FUNCTION_VALIDATE(params_.get());
337  return true;
338}
339
340void 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
350void 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
363SocketReadFunction::SocketReadFunction() {}
364
365SocketReadFunction::~SocketReadFunction() {}
366
367bool SocketReadFunction::Prepare() {
368  params_ = core_api::socket::Read::Params::Create(*args_);
369  EXTENSION_FUNCTION_VALIDATE(params_.get());
370  return true;
371}
372
373void 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
385void 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
401SocketWriteFunction::SocketWriteFunction()
402    : socket_id_(0), io_buffer_(NULL), io_buffer_size_(0) {}
403
404SocketWriteFunction::~SocketWriteFunction() {}
405
406bool 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
416void 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
430void 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
438SocketRecvFromFunction::SocketRecvFromFunction() {}
439
440SocketRecvFromFunction::~SocketRecvFromFunction() {}
441
442bool SocketRecvFromFunction::Prepare() {
443  params_ = core_api::socket::RecvFrom::Params::Create(*args_);
444  EXTENSION_FUNCTION_VALIDATE(params_.get());
445  return true;
446}
447
448void 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
460void 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
480SocketSendToFunction::SocketSendToFunction()
481    : socket_id_(0),
482      io_buffer_(NULL),
483      io_buffer_size_(0),
484      port_(0),
485      socket_(NULL) {}
486
487SocketSendToFunction::~SocketSendToFunction() {}
488
489bool 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
501void 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 (!PermissionsData::CheckAPIPermissionWithParam(
514            GetExtension(), APIPermission::kSocket, &param)) {
515      error_ = kPermissionError;
516      SetResult(new base::FundamentalValue(-1));
517      AsyncWorkCompleted();
518      return;
519    }
520  }
521
522  StartDnsLookup(hostname_);
523}
524
525void 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
534void SocketSendToFunction::StartSendTo() {
535  socket_->SendTo(io_buffer_,
536                  io_buffer_size_,
537                  resolved_address_,
538                  port_,
539                  base::Bind(&SocketSendToFunction::OnCompleted, this));
540}
541
542void 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
550SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
551
552SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
553
554bool SocketSetKeepAliveFunction::Prepare() {
555  params_ = core_api::socket::SetKeepAlive::Params::Create(*args_);
556  EXTENSION_FUNCTION_VALIDATE(params_.get());
557  return true;
558}
559
560void 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
574SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
575
576SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
577
578bool SocketSetNoDelayFunction::Prepare() {
579  params_ = core_api::socket::SetNoDelay::Params::Create(*args_);
580  EXTENSION_FUNCTION_VALIDATE(params_.get());
581  return true;
582}
583
584void 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
594SocketGetInfoFunction::SocketGetInfoFunction() {}
595
596SocketGetInfoFunction::~SocketGetInfoFunction() {}
597
598bool SocketGetInfoFunction::Prepare() {
599  params_ = core_api::socket::GetInfo::Params::Create(*args_);
600  EXTENSION_FUNCTION_VALIDATE(params_.get());
601  return true;
602}
603
604void 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
641bool SocketGetNetworkListFunction::RunImpl() {
642  content::BrowserThread::PostTask(
643      content::BrowserThread::FILE,
644      FROM_HERE,
645      base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread,
646                 this));
647  return true;
648}
649
650void 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
670void SocketGetNetworkListFunction::HandleGetNetworkListError() {
671  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
672  error_ = kNetworkListError;
673  SendResponse(false);
674}
675
676void 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
697SocketJoinGroupFunction::SocketJoinGroupFunction() {}
698
699SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
700
701bool SocketJoinGroupFunction::Prepare() {
702  params_ = core_api::socket::JoinGroup::Params::Create(*args_);
703  EXTENSION_FUNCTION_VALIDATE(params_.get());
704  return true;
705}
706
707void 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 (!PermissionsData::CheckAPIPermissionWithParam(
728          GetExtension(), 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
741SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
742
743SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
744
745bool SocketLeaveGroupFunction::Prepare() {
746  params_ = core_api::socket::LeaveGroup::Params::Create(*args_);
747  EXTENSION_FUNCTION_VALIDATE(params_.get());
748  return true;
749}
750
751void 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 (!PermissionsData::CheckAPIPermissionWithParam(
772          GetExtension(), 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
784SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
785
786SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
787
788bool SocketSetMulticastTimeToLiveFunction::Prepare() {
789  params_ = core_api::socket::SetMulticastTimeToLive::Params::Create(*args_);
790  EXTENSION_FUNCTION_VALIDATE(params_.get());
791  return true;
792}
793void 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
815SocketSetMulticastLoopbackModeFunction::
816    SocketSetMulticastLoopbackModeFunction() {}
817
818SocketSetMulticastLoopbackModeFunction::
819    ~SocketSetMulticastLoopbackModeFunction() {}
820
821bool SocketSetMulticastLoopbackModeFunction::Prepare() {
822  params_ = core_api::socket::SetMulticastLoopbackMode::Params::Create(*args_);
823  EXTENSION_FUNCTION_VALIDATE(params_.get());
824  return true;
825}
826
827void 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
849SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
850
851SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
852
853bool SocketGetJoinedGroupsFunction::Prepare() {
854  params_ = core_api::socket::GetJoinedGroups::Params::Create(*args_);
855  EXTENSION_FUNCTION_VALIDATE(params_.get());
856  return true;
857}
858
859void 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 (!PermissionsData::CheckAPIPermissionWithParam(
879          GetExtension(), 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