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
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[] =
46    "Only UDP socket supports multicast.";
47const char kWildcardAddress[] = "*";
48const int kWildcardPort = 0;
49
50SocketAsyncApiFunction::SocketAsyncApiFunction() {
51}
52
53SocketAsyncApiFunction::~SocketAsyncApiFunction() {
54}
55
56bool SocketAsyncApiFunction::PrePrepare() {
57  manager_ = CreateSocketResourceManager();
58  return manager_->SetProfile(GetProfile());
59}
60
61bool SocketAsyncApiFunction::Respond() {
62  return error_.empty();
63}
64
65scoped_ptr<SocketResourceManagerInterface>
66    SocketAsyncApiFunction::CreateSocketResourceManager() {
67  return scoped_ptr<SocketResourceManagerInterface>(
68      new SocketResourceManager<Socket>()).Pass();
69}
70
71int SocketAsyncApiFunction::AddSocket(Socket* socket) {
72  return manager_->Add(socket);
73}
74
75Socket* SocketAsyncApiFunction::GetSocket(int api_resource_id) {
76  return manager_->Get(extension_->id(), api_resource_id);
77}
78
79base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() {
80  return manager_->GetResourceIds(extension_->id());
81}
82
83void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
84  manager_->Remove(extension_->id(), api_resource_id);
85}
86
87SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction()
88    : io_thread_(g_browser_process->io_thread()),
89      request_handle_(new net::HostResolver::RequestHandle),
90      addresses_(new net::AddressList) {
91}
92
93SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {
94}
95
96void 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
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}
135
136SocketCreateFunction::~SocketCreateFunction() {}
137
138bool 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
157void 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
171bool SocketDestroyFunction::Prepare() {
172  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
173  return true;
174}
175
176void SocketDestroyFunction::Work() {
177  RemoveSocket(socket_id_);
178}
179
180SocketConnectFunction::SocketConnectFunction()
181    : socket_id_(0),
182      hostname_(),
183      port_(0),
184      socket_(NULL) {
185}
186
187SocketConnectFunction::~SocketConnectFunction() {
188}
189
190bool 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
197void 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
232void 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
241void SocketConnectFunction::StartConnect() {
242  socket_->Connect(resolved_address_, port_,
243                   base::Bind(&SocketConnectFunction::OnConnect, this));
244}
245
246void SocketConnectFunction::OnConnect(int result) {
247  SetResult(new base::FundamentalValue(result));
248  AsyncWorkCompleted();
249}
250
251bool SocketDisconnectFunction::Prepare() {
252  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
253  return true;
254}
255
256void 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
265bool 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
272void 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
303SocketListenFunction::SocketListenFunction() {}
304
305SocketListenFunction::~SocketListenFunction() {}
306
307bool SocketListenFunction::Prepare() {
308  params_ = api::socket::Listen::Params::Create(*args_);
309  EXTENSION_FUNCTION_VALIDATE(params_.get());
310  return true;
311}
312
313void 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
341SocketAcceptFunction::SocketAcceptFunction() {}
342
343SocketAcceptFunction::~SocketAcceptFunction() {}
344
345bool SocketAcceptFunction::Prepare() {
346  params_ = api::socket::Accept::Params::Create(*args_);
347  EXTENSION_FUNCTION_VALIDATE(params_.get());
348  return true;
349}
350
351void 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
361void 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
374SocketReadFunction::SocketReadFunction() {}
375
376SocketReadFunction::~SocketReadFunction() {}
377
378bool SocketReadFunction::Prepare() {
379  params_ = api::socket::Read::Params::Create(*args_);
380  EXTENSION_FUNCTION_VALIDATE(params_.get());
381  return true;
382}
383
384void 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
396void 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
412SocketWriteFunction::SocketWriteFunction()
413    : socket_id_(0),
414      io_buffer_(NULL),
415      io_buffer_size_(0) {
416}
417
418SocketWriteFunction::~SocketWriteFunction() {}
419
420bool 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
430void 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
443void 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
451SocketRecvFromFunction::SocketRecvFromFunction() {}
452
453SocketRecvFromFunction::~SocketRecvFromFunction() {}
454
455bool SocketRecvFromFunction::Prepare() {
456  params_ = api::socket::RecvFrom::Params::Create(*args_);
457  EXTENSION_FUNCTION_VALIDATE(params_.get());
458  return true;
459}
460
461void 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
473void 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
493SocketSendToFunction::SocketSendToFunction()
494    : socket_id_(0),
495      io_buffer_(NULL),
496      io_buffer_size_(0),
497      port_(0),
498      socket_(NULL) {
499}
500
501SocketSendToFunction::~SocketSendToFunction() {}
502
503bool 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
515void 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
541void 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
550void SocketSendToFunction::StartSendTo() {
551  socket_->SendTo(io_buffer_, io_buffer_size_, resolved_address_, port_,
552                  base::Bind(&SocketSendToFunction::OnCompleted, this));
553}
554
555void 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
563SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
564
565SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
566
567bool SocketSetKeepAliveFunction::Prepare() {
568  params_ = api::socket::SetKeepAlive::Params::Create(*args_);
569  EXTENSION_FUNCTION_VALIDATE(params_.get());
570  return true;
571}
572
573void 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
587SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
588
589SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
590
591bool SocketSetNoDelayFunction::Prepare() {
592  params_ = api::socket::SetNoDelay::Params::Create(*args_);
593  EXTENSION_FUNCTION_VALIDATE(params_.get());
594  return true;
595}
596
597void 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
607SocketGetInfoFunction::SocketGetInfoFunction() {}
608
609SocketGetInfoFunction::~SocketGetInfoFunction() {}
610
611bool SocketGetInfoFunction::Prepare() {
612  params_ = api::socket::GetInfo::Params::Create(*args_);
613  EXTENSION_FUNCTION_VALIDATE(params_.get());
614  return true;
615}
616
617void 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
655bool SocketGetNetworkListFunction::RunImpl() {
656  content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
657      base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread,
658          this));
659  return true;
660}
661
662void 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
676void SocketGetNetworkListFunction::HandleGetNetworkListError() {
677  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
678  error_ = kNetworkListError;
679  SendResponse(false);
680}
681
682void 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
702SocketJoinGroupFunction::SocketJoinGroupFunction() {}
703
704SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
705
706bool SocketJoinGroupFunction::Prepare() {
707  params_ = api::socket::JoinGroup::Params::Create(*args_);
708  EXTENSION_FUNCTION_VALIDATE(params_.get());
709  return true;
710}
711
712void 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
746SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
747
748SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
749
750bool SocketLeaveGroupFunction::Prepare() {
751  params_ = api::socket::LeaveGroup::Params::Create(*args_);
752  EXTENSION_FUNCTION_VALIDATE(params_.get());
753  return true;
754}
755
756void 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
790SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
791
792SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
793
794bool SocketSetMulticastTimeToLiveFunction::Prepare() {
795  params_ = api::socket::SetMulticastTimeToLive::Params::Create(*args_);
796  EXTENSION_FUNCTION_VALIDATE(params_.get());
797  return true;
798}
799void 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
821SocketSetMulticastLoopbackModeFunction::
822    SocketSetMulticastLoopbackModeFunction() {}
823
824SocketSetMulticastLoopbackModeFunction::
825  ~SocketSetMulticastLoopbackModeFunction() {}
826
827bool SocketSetMulticastLoopbackModeFunction::Prepare() {
828  params_ = api::socket::SetMulticastLoopbackMode::Params::Create(*args_);
829  EXTENSION_FUNCTION_VALIDATE(params_.get());
830  return true;
831}
832
833void 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
855SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
856
857SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
858
859bool SocketGetJoinedGroupsFunction::Prepare() {
860  params_ = api::socket::GetJoinedGroups::Params::Create(*args_);
861  EXTENSION_FUNCTION_VALIDATE(params_.get());
862  return true;
863}
864
865void 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