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/tls_socket.h"
17 #include "extensions/browser/api/socket/udp_socket.h"
18 #include "extensions/browser/extension_system.h"
19 #include "extensions/common/extension.h"
20 #include "extensions/common/permissions/permissions_data.h"
21 #include "extensions/common/permissions/socket_permission.h"
22 #include "net/base/host_port_pair.h"
23 #include "net/base/io_buffer.h"
24 #include "net/base/ip_endpoint.h"
25 #include "net/base/net_errors.h"
26 #include "net/base/net_log.h"
27 #include "net/base/net_util.h"
28 #include "net/url_request/url_request_context.h"
29 #include "net/url_request/url_request_context_getter.h"
30
31 namespace extensions {
32
33 using content::SocketPermissionRequest;
34
35 const char kAddressKey[] = "address";
36 const char kPortKey[] = "port";
37 const char kBytesWrittenKey[] = "bytesWritten";
38 const char kDataKey[] = "data";
39 const char kResultCodeKey[] = "resultCode";
40 const char kSocketIdKey[] = "socketId";
41
42 const char kSocketNotFoundError[] = "Socket not found";
43 const char kDnsLookupFailedError[] = "DNS resolution failed";
44 const char kPermissionError[] = "App does not have permission";
45 const char kNetworkListError[] = "Network lookup failed or unsupported";
46 const char kTCPSocketBindError[] =
47 "TCP socket does not support bind. For TCP server please use listen.";
48 const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast.";
49 const char kSecureSocketTypeError[] = "Only TCP sockets are supported for TLS.";
50 const char kSocketNotConnectedError[] = "Socket not connected";
51 const char kWildcardAddress[] = "*";
52 const int kWildcardPort = 0;
53
SocketAsyncApiFunction()54 SocketAsyncApiFunction::SocketAsyncApiFunction() {}
55
~SocketAsyncApiFunction()56 SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
57
PrePrepare()58 bool SocketAsyncApiFunction::PrePrepare() {
59 manager_ = CreateSocketResourceManager();
60 return manager_->SetBrowserContext(browser_context());
61 }
62
Respond()63 bool SocketAsyncApiFunction::Respond() { return error_.empty(); }
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
ReplaceSocket(int api_resource_id,Socket * socket)79 void SocketAsyncApiFunction::ReplaceSocket(int api_resource_id,
80 Socket* socket) {
81 manager_->Replace(extension_->id(), api_resource_id, socket);
82 }
83
GetSocketIds()84 base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() {
85 return manager_->GetResourceIds(extension_->id());
86 }
87
RemoveSocket(int api_resource_id)88 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
89 manager_->Remove(extension_->id(), api_resource_id);
90 }
91
SocketExtensionWithDnsLookupFunction()92 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction()
93 : resource_context_(NULL),
94 request_handle_(new net::HostResolver::RequestHandle),
95 addresses_(new net::AddressList) {}
96
~SocketExtensionWithDnsLookupFunction()97 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {}
98
PrePrepare()99 bool SocketExtensionWithDnsLookupFunction::PrePrepare() {
100 if (!SocketAsyncApiFunction::PrePrepare())
101 return false;
102 resource_context_ = browser_context()->GetResourceContext();
103 return resource_context_ != NULL;
104 }
105
StartDnsLookup(const std::string & hostname)106 void SocketExtensionWithDnsLookupFunction::StartDnsLookup(
107 const std::string& hostname) {
108 net::HostResolver* host_resolver =
109 HostResolverWrapper::GetInstance()->GetHostResolver(resource_context_);
110 DCHECK(host_resolver);
111
112 // Yes, we are passing zero as the port. There are some interesting but not
113 // presently relevant reasons why HostResolver asks for the port of the
114 // hostname you'd like to resolve, even though it doesn't use that value in
115 // determining its answer.
116 net::HostPortPair host_port_pair(hostname, 0);
117
118 net::HostResolver::RequestInfo request_info(host_port_pair);
119 int resolve_result = host_resolver->Resolve(
120 request_info,
121 net::DEFAULT_PRIORITY,
122 addresses_.get(),
123 base::Bind(&SocketExtensionWithDnsLookupFunction::OnDnsLookup, this),
124 request_handle_.get(),
125 net::BoundNetLog());
126
127 if (resolve_result != net::ERR_IO_PENDING)
128 OnDnsLookup(resolve_result);
129 }
130
OnDnsLookup(int resolve_result)131 void SocketExtensionWithDnsLookupFunction::OnDnsLookup(int resolve_result) {
132 if (resolve_result == net::OK) {
133 DCHECK(!addresses_->empty());
134 resolved_address_ = addresses_->front().ToStringWithoutPort();
135 } else {
136 error_ = kDnsLookupFailedError;
137 }
138 AfterDnsLookup(resolve_result);
139 }
140
SocketCreateFunction()141 SocketCreateFunction::SocketCreateFunction()
142 : socket_type_(kSocketTypeInvalid) {}
143
~SocketCreateFunction()144 SocketCreateFunction::~SocketCreateFunction() {}
145
Prepare()146 bool SocketCreateFunction::Prepare() {
147 params_ = core_api::socket::Create::Params::Create(*args_);
148 EXTENSION_FUNCTION_VALIDATE(params_.get());
149
150 switch (params_->type) {
151 case extensions::core_api::socket::SOCKET_TYPE_TCP:
152 socket_type_ = kSocketTypeTCP;
153 break;
154 case extensions::core_api::socket::SOCKET_TYPE_UDP:
155 socket_type_ = kSocketTypeUDP;
156 break;
157 case extensions::core_api::socket::SOCKET_TYPE_NONE:
158 NOTREACHED();
159 break;
160 }
161
162 return true;
163 }
164
Work()165 void SocketCreateFunction::Work() {
166 Socket* socket = NULL;
167 if (socket_type_ == kSocketTypeTCP) {
168 socket = new TCPSocket(extension_->id());
169 } else if (socket_type_ == kSocketTypeUDP) {
170 socket = new UDPSocket(extension_->id());
171 }
172 DCHECK(socket);
173
174 base::DictionaryValue* result = new base::DictionaryValue();
175 result->SetInteger(kSocketIdKey, AddSocket(socket));
176 SetResult(result);
177 }
178
Prepare()179 bool SocketDestroyFunction::Prepare() {
180 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
181 return true;
182 }
183
Work()184 void SocketDestroyFunction::Work() { RemoveSocket(socket_id_); }
185
SocketConnectFunction()186 SocketConnectFunction::SocketConnectFunction()
187 : socket_id_(0), hostname_(), port_(0), socket_(NULL) {}
188
~SocketConnectFunction()189 SocketConnectFunction::~SocketConnectFunction() {}
190
Prepare()191 bool SocketConnectFunction::Prepare() {
192 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
193 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &hostname_));
194 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_));
195 return true;
196 }
197
AsyncWorkStart()198 void SocketConnectFunction::AsyncWorkStart() {
199 socket_ = GetSocket(socket_id_);
200 if (!socket_) {
201 error_ = kSocketNotFoundError;
202 SetResult(new base::FundamentalValue(-1));
203 AsyncWorkCompleted();
204 return;
205 }
206
207 socket_->set_hostname(hostname_);
208
209 SocketPermissionRequest::OperationType operation_type;
210 switch (socket_->GetSocketType()) {
211 case Socket::TYPE_TCP:
212 operation_type = SocketPermissionRequest::TCP_CONNECT;
213 break;
214 case Socket::TYPE_UDP:
215 operation_type = SocketPermissionRequest::UDP_SEND_TO;
216 break;
217 default:
218 NOTREACHED() << "Unknown socket type.";
219 operation_type = SocketPermissionRequest::NONE;
220 break;
221 }
222
223 SocketPermission::CheckParam param(operation_type, hostname_, port_);
224 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
225 APIPermission::kSocket, ¶m)) {
226 error_ = kPermissionError;
227 SetResult(new base::FundamentalValue(-1));
228 AsyncWorkCompleted();
229 return;
230 }
231
232 StartDnsLookup(hostname_);
233 }
234
AfterDnsLookup(int lookup_result)235 void SocketConnectFunction::AfterDnsLookup(int lookup_result) {
236 if (lookup_result == net::OK) {
237 StartConnect();
238 } else {
239 SetResult(new base::FundamentalValue(lookup_result));
240 AsyncWorkCompleted();
241 }
242 }
243
StartConnect()244 void SocketConnectFunction::StartConnect() {
245 socket_->Connect(resolved_address_,
246 port_,
247 base::Bind(&SocketConnectFunction::OnConnect, this));
248 }
249
OnConnect(int result)250 void SocketConnectFunction::OnConnect(int result) {
251 SetResult(new base::FundamentalValue(result));
252 AsyncWorkCompleted();
253 }
254
Prepare()255 bool SocketDisconnectFunction::Prepare() {
256 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
257 return true;
258 }
259
Work()260 void SocketDisconnectFunction::Work() {
261 Socket* socket = GetSocket(socket_id_);
262 if (socket)
263 socket->Disconnect();
264 else
265 error_ = kSocketNotFoundError;
266 SetResult(base::Value::CreateNullValue());
267 }
268
Prepare()269 bool SocketBindFunction::Prepare() {
270 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
271 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_));
272 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_));
273 return true;
274 }
275
Work()276 void SocketBindFunction::Work() {
277 int result = -1;
278 Socket* socket = GetSocket(socket_id_);
279
280 if (!socket) {
281 error_ = kSocketNotFoundError;
282 SetResult(new base::FundamentalValue(result));
283 return;
284 }
285
286 if (socket->GetSocketType() == Socket::TYPE_UDP) {
287 SocketPermission::CheckParam param(
288 SocketPermissionRequest::UDP_BIND, address_, port_);
289 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
290 APIPermission::kSocket, ¶m)) {
291 error_ = kPermissionError;
292 SetResult(new base::FundamentalValue(result));
293 return;
294 }
295 } else if (socket->GetSocketType() == Socket::TYPE_TCP) {
296 error_ = kTCPSocketBindError;
297 SetResult(new base::FundamentalValue(result));
298 return;
299 }
300
301 result = socket->Bind(address_, port_);
302 SetResult(new base::FundamentalValue(result));
303 }
304
SocketListenFunction()305 SocketListenFunction::SocketListenFunction() {}
306
~SocketListenFunction()307 SocketListenFunction::~SocketListenFunction() {}
308
Prepare()309 bool SocketListenFunction::Prepare() {
310 params_ = core_api::socket::Listen::Params::Create(*args_);
311 EXTENSION_FUNCTION_VALIDATE(params_.get());
312 return true;
313 }
314
Work()315 void SocketListenFunction::Work() {
316 int result = -1;
317
318 Socket* socket = GetSocket(params_->socket_id);
319 if (socket) {
320 SocketPermission::CheckParam param(
321 SocketPermissionRequest::TCP_LISTEN, params_->address, params_->port);
322 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
323 APIPermission::kSocket, ¶m)) {
324 error_ = kPermissionError;
325 SetResult(new base::FundamentalValue(result));
326 return;
327 }
328
329 result =
330 socket->Listen(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_ = core_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_ = core_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), io_buffer_(NULL), io_buffer_size_(0) {}
414
~SocketWriteFunction()415 SocketWriteFunction::~SocketWriteFunction() {}
416
Prepare()417 bool SocketWriteFunction::Prepare() {
418 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
419 base::BinaryValue* data = NULL;
420 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data));
421
422 io_buffer_size_ = data->GetSize();
423 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer());
424 return true;
425 }
426
AsyncWorkStart()427 void SocketWriteFunction::AsyncWorkStart() {
428 Socket* socket = GetSocket(socket_id_);
429
430 if (!socket) {
431 error_ = kSocketNotFoundError;
432 OnCompleted(-1);
433 return;
434 }
435
436 socket->Write(io_buffer_,
437 io_buffer_size_,
438 base::Bind(&SocketWriteFunction::OnCompleted, this));
439 }
440
OnCompleted(int bytes_written)441 void SocketWriteFunction::OnCompleted(int bytes_written) {
442 base::DictionaryValue* result = new base::DictionaryValue();
443 result->SetInteger(kBytesWrittenKey, bytes_written);
444 SetResult(result);
445
446 AsyncWorkCompleted();
447 }
448
SocketRecvFromFunction()449 SocketRecvFromFunction::SocketRecvFromFunction() {}
450
~SocketRecvFromFunction()451 SocketRecvFromFunction::~SocketRecvFromFunction() {}
452
Prepare()453 bool SocketRecvFromFunction::Prepare() {
454 params_ = core_api::socket::RecvFrom::Params::Create(*args_);
455 EXTENSION_FUNCTION_VALIDATE(params_.get());
456 return true;
457 }
458
AsyncWorkStart()459 void SocketRecvFromFunction::AsyncWorkStart() {
460 Socket* socket = GetSocket(params_->socket_id);
461 if (!socket) {
462 error_ = kSocketNotFoundError;
463 OnCompleted(-1, NULL, std::string(), 0);
464 return;
465 }
466
467 socket->RecvFrom(params_->buffer_size.get() ? *params_->buffer_size : 4096,
468 base::Bind(&SocketRecvFromFunction::OnCompleted, this));
469 }
470
OnCompleted(int bytes_read,scoped_refptr<net::IOBuffer> io_buffer,const std::string & address,int port)471 void SocketRecvFromFunction::OnCompleted(int bytes_read,
472 scoped_refptr<net::IOBuffer> io_buffer,
473 const std::string& address,
474 int port) {
475 base::DictionaryValue* result = new base::DictionaryValue();
476 result->SetInteger(kResultCodeKey, bytes_read);
477 if (bytes_read > 0) {
478 result->Set(kDataKey,
479 base::BinaryValue::CreateWithCopiedBuffer(io_buffer->data(),
480 bytes_read));
481 } else {
482 result->Set(kDataKey, new base::BinaryValue());
483 }
484 result->SetString(kAddressKey, address);
485 result->SetInteger(kPortKey, port);
486 SetResult(result);
487
488 AsyncWorkCompleted();
489 }
490
SocketSendToFunction()491 SocketSendToFunction::SocketSendToFunction()
492 : socket_id_(0),
493 io_buffer_(NULL),
494 io_buffer_size_(0),
495 port_(0),
496 socket_(NULL) {}
497
~SocketSendToFunction()498 SocketSendToFunction::~SocketSendToFunction() {}
499
Prepare()500 bool SocketSendToFunction::Prepare() {
501 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
502 base::BinaryValue* data = NULL;
503 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data));
504 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &hostname_));
505 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(3, &port_));
506
507 io_buffer_size_ = data->GetSize();
508 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer());
509 return true;
510 }
511
AsyncWorkStart()512 void SocketSendToFunction::AsyncWorkStart() {
513 socket_ = GetSocket(socket_id_);
514 if (!socket_) {
515 error_ = kSocketNotFoundError;
516 SetResult(new base::FundamentalValue(-1));
517 AsyncWorkCompleted();
518 return;
519 }
520
521 if (socket_->GetSocketType() == Socket::TYPE_UDP) {
522 SocketPermission::CheckParam param(
523 SocketPermissionRequest::UDP_SEND_TO, hostname_, port_);
524 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
525 APIPermission::kSocket, ¶m)) {
526 error_ = kPermissionError;
527 SetResult(new base::FundamentalValue(-1));
528 AsyncWorkCompleted();
529 return;
530 }
531 }
532
533 StartDnsLookup(hostname_);
534 }
535
AfterDnsLookup(int lookup_result)536 void SocketSendToFunction::AfterDnsLookup(int lookup_result) {
537 if (lookup_result == net::OK) {
538 StartSendTo();
539 } else {
540 SetResult(new base::FundamentalValue(lookup_result));
541 AsyncWorkCompleted();
542 }
543 }
544
StartSendTo()545 void SocketSendToFunction::StartSendTo() {
546 socket_->SendTo(io_buffer_,
547 io_buffer_size_,
548 resolved_address_,
549 port_,
550 base::Bind(&SocketSendToFunction::OnCompleted, this));
551 }
552
OnCompleted(int bytes_written)553 void SocketSendToFunction::OnCompleted(int bytes_written) {
554 base::DictionaryValue* result = new base::DictionaryValue();
555 result->SetInteger(kBytesWrittenKey, bytes_written);
556 SetResult(result);
557
558 AsyncWorkCompleted();
559 }
560
SocketSetKeepAliveFunction()561 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
562
~SocketSetKeepAliveFunction()563 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
564
Prepare()565 bool SocketSetKeepAliveFunction::Prepare() {
566 params_ = core_api::socket::SetKeepAlive::Params::Create(*args_);
567 EXTENSION_FUNCTION_VALIDATE(params_.get());
568 return true;
569 }
570
Work()571 void SocketSetKeepAliveFunction::Work() {
572 bool result = false;
573 Socket* socket = GetSocket(params_->socket_id);
574 if (socket) {
575 int delay = 0;
576 if (params_->delay.get())
577 delay = *params_->delay;
578 result = socket->SetKeepAlive(params_->enable, delay);
579 } else {
580 error_ = kSocketNotFoundError;
581 }
582 SetResult(new base::FundamentalValue(result));
583 }
584
SocketSetNoDelayFunction()585 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
586
~SocketSetNoDelayFunction()587 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
588
Prepare()589 bool SocketSetNoDelayFunction::Prepare() {
590 params_ = core_api::socket::SetNoDelay::Params::Create(*args_);
591 EXTENSION_FUNCTION_VALIDATE(params_.get());
592 return true;
593 }
594
Work()595 void SocketSetNoDelayFunction::Work() {
596 bool result = false;
597 Socket* socket = GetSocket(params_->socket_id);
598 if (socket)
599 result = socket->SetNoDelay(params_->no_delay);
600 else
601 error_ = kSocketNotFoundError;
602 SetResult(new base::FundamentalValue(result));
603 }
604
SocketGetInfoFunction()605 SocketGetInfoFunction::SocketGetInfoFunction() {}
606
~SocketGetInfoFunction()607 SocketGetInfoFunction::~SocketGetInfoFunction() {}
608
Prepare()609 bool SocketGetInfoFunction::Prepare() {
610 params_ = core_api::socket::GetInfo::Params::Create(*args_);
611 EXTENSION_FUNCTION_VALIDATE(params_.get());
612 return true;
613 }
614
Work()615 void SocketGetInfoFunction::Work() {
616 Socket* socket = GetSocket(params_->socket_id);
617 if (!socket) {
618 error_ = kSocketNotFoundError;
619 return;
620 }
621
622 core_api::socket::SocketInfo info;
623 // This represents what we know about the socket, and does not call through
624 // to the system.
625 if (socket->GetSocketType() == Socket::TYPE_TCP)
626 info.socket_type = extensions::core_api::socket::SOCKET_TYPE_TCP;
627 else
628 info.socket_type = extensions::core_api::socket::SOCKET_TYPE_UDP;
629 info.connected = socket->IsConnected();
630
631 // Grab the peer address as known by the OS. This and the call below will
632 // always succeed while the socket is connected, even if the socket has
633 // been remotely closed by the peer; only reading the socket will reveal
634 // that it should be closed locally.
635 net::IPEndPoint peerAddress;
636 if (socket->GetPeerAddress(&peerAddress)) {
637 info.peer_address.reset(new std::string(peerAddress.ToStringWithoutPort()));
638 info.peer_port.reset(new int(peerAddress.port()));
639 }
640
641 // Grab the local address as known by the OS.
642 net::IPEndPoint localAddress;
643 if (socket->GetLocalAddress(&localAddress)) {
644 info.local_address.reset(
645 new std::string(localAddress.ToStringWithoutPort()));
646 info.local_port.reset(new int(localAddress.port()));
647 }
648
649 SetResult(info.ToValue().release());
650 }
651
RunAsync()652 bool SocketGetNetworkListFunction::RunAsync() {
653 content::BrowserThread::PostTask(
654 content::BrowserThread::FILE,
655 FROM_HERE,
656 base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread,
657 this));
658 return true;
659 }
660
GetNetworkListOnFileThread()661 void SocketGetNetworkListFunction::GetNetworkListOnFileThread() {
662 net::NetworkInterfaceList interface_list;
663 if (GetNetworkList(&interface_list,
664 net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
665 content::BrowserThread::PostTask(
666 content::BrowserThread::UI,
667 FROM_HERE,
668 base::Bind(&SocketGetNetworkListFunction::SendResponseOnUIThread,
669 this,
670 interface_list));
671 return;
672 }
673
674 content::BrowserThread::PostTask(
675 content::BrowserThread::UI,
676 FROM_HERE,
677 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError,
678 this));
679 }
680
HandleGetNetworkListError()681 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
682 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
683 error_ = kNetworkListError;
684 SendResponse(false);
685 }
686
SendResponseOnUIThread(const net::NetworkInterfaceList & interface_list)687 void SocketGetNetworkListFunction::SendResponseOnUIThread(
688 const net::NetworkInterfaceList& interface_list) {
689 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
690
691 std::vector<linked_ptr<core_api::socket::NetworkInterface> > create_arg;
692 create_arg.reserve(interface_list.size());
693 for (net::NetworkInterfaceList::const_iterator i = interface_list.begin();
694 i != interface_list.end();
695 ++i) {
696 linked_ptr<core_api::socket::NetworkInterface> info =
697 make_linked_ptr(new core_api::socket::NetworkInterface);
698 info->name = i->name;
699 info->address = net::IPAddressToString(i->address);
700 info->prefix_length = i->network_prefix;
701 create_arg.push_back(info);
702 }
703
704 results_ = core_api::socket::GetNetworkList::Results::Create(create_arg);
705 SendResponse(true);
706 }
707
SocketJoinGroupFunction()708 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
709
~SocketJoinGroupFunction()710 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
711
Prepare()712 bool SocketJoinGroupFunction::Prepare() {
713 params_ = core_api::socket::JoinGroup::Params::Create(*args_);
714 EXTENSION_FUNCTION_VALIDATE(params_.get());
715 return true;
716 }
717
Work()718 void SocketJoinGroupFunction::Work() {
719 int result = -1;
720 Socket* socket = GetSocket(params_->socket_id);
721 if (!socket) {
722 error_ = kSocketNotFoundError;
723 SetResult(new base::FundamentalValue(result));
724 return;
725 }
726
727 if (socket->GetSocketType() != Socket::TYPE_UDP) {
728 error_ = kMulticastSocketTypeError;
729 SetResult(new base::FundamentalValue(result));
730 return;
731 }
732
733 SocketPermission::CheckParam param(
734 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
735 kWildcardAddress,
736 kWildcardPort);
737
738 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
739 APIPermission::kSocket, ¶m)) {
740 error_ = kPermissionError;
741 SetResult(new base::FundamentalValue(result));
742 return;
743 }
744
745 result = static_cast<UDPSocket*>(socket)->JoinGroup(params_->address);
746 if (result != 0) {
747 error_ = net::ErrorToString(result);
748 }
749 SetResult(new base::FundamentalValue(result));
750 }
751
SocketLeaveGroupFunction()752 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
753
~SocketLeaveGroupFunction()754 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
755
Prepare()756 bool SocketLeaveGroupFunction::Prepare() {
757 params_ = core_api::socket::LeaveGroup::Params::Create(*args_);
758 EXTENSION_FUNCTION_VALIDATE(params_.get());
759 return true;
760 }
761
Work()762 void SocketLeaveGroupFunction::Work() {
763 int result = -1;
764 Socket* socket = GetSocket(params_->socket_id);
765
766 if (!socket) {
767 error_ = kSocketNotFoundError;
768 SetResult(new base::FundamentalValue(result));
769 return;
770 }
771
772 if (socket->GetSocketType() != Socket::TYPE_UDP) {
773 error_ = kMulticastSocketTypeError;
774 SetResult(new base::FundamentalValue(result));
775 return;
776 }
777
778 SocketPermission::CheckParam param(
779 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
780 kWildcardAddress,
781 kWildcardPort);
782 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
783 APIPermission::kSocket, ¶m)) {
784 error_ = kPermissionError;
785 SetResult(new base::FundamentalValue(result));
786 return;
787 }
788
789 result = static_cast<UDPSocket*>(socket)->LeaveGroup(params_->address);
790 if (result != 0)
791 error_ = net::ErrorToString(result);
792 SetResult(new base::FundamentalValue(result));
793 }
794
SocketSetMulticastTimeToLiveFunction()795 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
796
~SocketSetMulticastTimeToLiveFunction()797 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
798
Prepare()799 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
800 params_ = core_api::socket::SetMulticastTimeToLive::Params::Create(*args_);
801 EXTENSION_FUNCTION_VALIDATE(params_.get());
802 return true;
803 }
Work()804 void SocketSetMulticastTimeToLiveFunction::Work() {
805 int result = -1;
806 Socket* socket = GetSocket(params_->socket_id);
807 if (!socket) {
808 error_ = kSocketNotFoundError;
809 SetResult(new base::FundamentalValue(result));
810 return;
811 }
812
813 if (socket->GetSocketType() != Socket::TYPE_UDP) {
814 error_ = kMulticastSocketTypeError;
815 SetResult(new base::FundamentalValue(result));
816 return;
817 }
818
819 result =
820 static_cast<UDPSocket*>(socket)->SetMulticastTimeToLive(params_->ttl);
821 if (result != 0)
822 error_ = net::ErrorToString(result);
823 SetResult(new base::FundamentalValue(result));
824 }
825
826 SocketSetMulticastLoopbackModeFunction::
SocketSetMulticastLoopbackModeFunction()827 SocketSetMulticastLoopbackModeFunction() {}
828
829 SocketSetMulticastLoopbackModeFunction::
~SocketSetMulticastLoopbackModeFunction()830 ~SocketSetMulticastLoopbackModeFunction() {}
831
Prepare()832 bool SocketSetMulticastLoopbackModeFunction::Prepare() {
833 params_ = core_api::socket::SetMulticastLoopbackMode::Params::Create(*args_);
834 EXTENSION_FUNCTION_VALIDATE(params_.get());
835 return true;
836 }
837
Work()838 void SocketSetMulticastLoopbackModeFunction::Work() {
839 int result = -1;
840 Socket* socket = GetSocket(params_->socket_id);
841 if (!socket) {
842 error_ = kSocketNotFoundError;
843 SetResult(new base::FundamentalValue(result));
844 return;
845 }
846
847 if (socket->GetSocketType() != Socket::TYPE_UDP) {
848 error_ = kMulticastSocketTypeError;
849 SetResult(new base::FundamentalValue(result));
850 return;
851 }
852
853 result = static_cast<UDPSocket*>(socket)
854 ->SetMulticastLoopbackMode(params_->enabled);
855 if (result != 0)
856 error_ = net::ErrorToString(result);
857 SetResult(new base::FundamentalValue(result));
858 }
859
SocketGetJoinedGroupsFunction()860 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
861
~SocketGetJoinedGroupsFunction()862 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
863
Prepare()864 bool SocketGetJoinedGroupsFunction::Prepare() {
865 params_ = core_api::socket::GetJoinedGroups::Params::Create(*args_);
866 EXTENSION_FUNCTION_VALIDATE(params_.get());
867 return true;
868 }
869
Work()870 void SocketGetJoinedGroupsFunction::Work() {
871 int result = -1;
872 Socket* socket = GetSocket(params_->socket_id);
873 if (!socket) {
874 error_ = kSocketNotFoundError;
875 SetResult(new base::FundamentalValue(result));
876 return;
877 }
878
879 if (socket->GetSocketType() != Socket::TYPE_UDP) {
880 error_ = kMulticastSocketTypeError;
881 SetResult(new base::FundamentalValue(result));
882 return;
883 }
884
885 SocketPermission::CheckParam param(
886 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
887 kWildcardAddress,
888 kWildcardPort);
889 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
890 APIPermission::kSocket, ¶m)) {
891 error_ = kPermissionError;
892 SetResult(new base::FundamentalValue(result));
893 return;
894 }
895
896 base::ListValue* values = new base::ListValue();
897 values->AppendStrings((std::vector<std::string>&)static_cast<UDPSocket*>(
898 socket)->GetJoinedGroups());
899 SetResult(values);
900 }
901
SocketSecureFunction()902 SocketSecureFunction::SocketSecureFunction() {
903 }
904
~SocketSecureFunction()905 SocketSecureFunction::~SocketSecureFunction() {
906 }
907
Prepare()908 bool SocketSecureFunction::Prepare() {
909 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
910 params_ = core_api::socket::Secure::Params::Create(*args_);
911 EXTENSION_FUNCTION_VALIDATE(params_.get());
912 url_request_getter_ = browser_context()->GetRequestContext();
913 return true;
914 }
915
916 // Override the regular implementation, which would call AsyncWorkCompleted
917 // immediately after Work().
AsyncWorkStart()918 void SocketSecureFunction::AsyncWorkStart() {
919 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
920
921 Socket* socket = GetSocket(params_->socket_id);
922 if (!socket) {
923 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
924 error_ = kSocketNotFoundError;
925 AsyncWorkCompleted();
926 return;
927 }
928
929 // Make sure that the socket is a TCP client socket.
930 if (socket->GetSocketType() != Socket::TYPE_TCP ||
931 static_cast<TCPSocket*>(socket)->ClientStream() == NULL) {
932 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
933 error_ = kSecureSocketTypeError;
934 AsyncWorkCompleted();
935 return;
936 }
937
938 if (!socket->IsConnected()) {
939 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
940 error_ = kSocketNotConnectedError;
941 AsyncWorkCompleted();
942 return;
943 }
944
945 net::URLRequestContext* url_request_context =
946 url_request_getter_->GetURLRequestContext();
947
948 TLSSocket::UpgradeSocketToTLS(
949 socket,
950 url_request_context->ssl_config_service(),
951 url_request_context->cert_verifier(),
952 url_request_context->transport_security_state(),
953 extension_id(),
954 params_->options.get(),
955 base::Bind(&SocketSecureFunction::TlsConnectDone, this));
956 }
957
TlsConnectDone(scoped_ptr<TLSSocket> socket,int result)958 void SocketSecureFunction::TlsConnectDone(scoped_ptr<TLSSocket> socket,
959 int result) {
960 // if an error occurred, socket MUST be NULL.
961 DCHECK(result == net::OK || socket == NULL);
962
963 if (socket && result == net::OK) {
964 ReplaceSocket(params_->socket_id, socket.release());
965 } else {
966 RemoveSocket(params_->socket_id);
967 error_ = net::ErrorToString(result);
968 }
969
970 results_ = core_api::socket::Secure::Results::Create(result);
971 AsyncWorkCompleted();
972 }
973
974 } // namespace extensions
975