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