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, ¶m)) {
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 ¶m)) {
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 ¶m)) {
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 ¶m)) {
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, ¶m)) {
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 ¶m)) {
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 ¶m)) {
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