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