OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/browser/api/socket/socket_api.h" | 5 #include "extensions/browser/api/socket/socket_api.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
(...skipping 11 matching lines...) Expand all Loading... | |
22 #include "extensions/common/permissions/socket_permission.h" | 22 #include "extensions/common/permissions/socket_permission.h" |
23 #include "net/base/host_port_pair.h" | 23 #include "net/base/host_port_pair.h" |
24 #include "net/base/io_buffer.h" | 24 #include "net/base/io_buffer.h" |
25 #include "net/base/ip_endpoint.h" | 25 #include "net/base/ip_endpoint.h" |
26 #include "net/base/net_errors.h" | 26 #include "net/base/net_errors.h" |
27 #include "net/base/net_log.h" | 27 #include "net/base/net_log.h" |
28 #include "net/base/net_util.h" | 28 #include "net/base/net_util.h" |
29 #include "net/url_request/url_request_context.h" | 29 #include "net/url_request/url_request_context.h" |
30 #include "net/url_request/url_request_context_getter.h" | 30 #include "net/url_request/url_request_context_getter.h" |
31 | 31 |
32 #if defined(OS_CHROMEOS) | |
33 #include "chromeos/network/firewall_hole.h" | |
34 #include "content/public/browser/browser_thread.h" | |
35 #endif // OS_CHROMEOS | |
36 | |
32 namespace extensions { | 37 namespace extensions { |
33 | 38 |
34 using content::SocketPermissionRequest; | 39 using content::SocketPermissionRequest; |
35 | 40 |
36 const char kAddressKey[] = "address"; | 41 const char kAddressKey[] = "address"; |
37 const char kPortKey[] = "port"; | 42 const char kPortKey[] = "port"; |
38 const char kBytesWrittenKey[] = "bytesWritten"; | 43 const char kBytesWrittenKey[] = "bytesWritten"; |
39 const char kDataKey[] = "data"; | 44 const char kDataKey[] = "data"; |
40 const char kResultCodeKey[] = "resultCode"; | 45 const char kResultCodeKey[] = "resultCode"; |
41 const char kSocketIdKey[] = "socketId"; | 46 const char kSocketIdKey[] = "socketId"; |
42 | 47 |
43 const char kSocketNotFoundError[] = "Socket not found"; | 48 const char kSocketNotFoundError[] = "Socket not found"; |
44 const char kDnsLookupFailedError[] = "DNS resolution failed"; | 49 const char kDnsLookupFailedError[] = "DNS resolution failed"; |
45 const char kPermissionError[] = "App does not have permission"; | 50 const char kPermissionError[] = "App does not have permission"; |
46 const char kNetworkListError[] = "Network lookup failed or unsupported"; | 51 const char kNetworkListError[] = "Network lookup failed or unsupported"; |
47 const char kTCPSocketBindError[] = | 52 const char kTCPSocketBindError[] = |
48 "TCP socket does not support bind. For TCP server please use listen."; | 53 "TCP socket does not support bind. For TCP server please use listen."; |
49 const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast."; | 54 const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast."; |
50 const char kSecureSocketTypeError[] = "Only TCP sockets are supported for TLS."; | 55 const char kSecureSocketTypeError[] = "Only TCP sockets are supported for TLS."; |
51 const char kSocketNotConnectedError[] = "Socket not connected"; | 56 const char kSocketNotConnectedError[] = "Socket not connected"; |
52 const char kWildcardAddress[] = "*"; | 57 const char kWildcardAddress[] = "*"; |
53 const uint16 kWildcardPort = 0; | 58 const uint16 kWildcardPort = 0; |
54 | 59 |
60 #if defined(OS_CHROMEOS) | |
61 const char kFirewallFailure[] = "Failed to open firewall port"; | |
62 #endif // OS_CHROMEOS | |
63 | |
55 SocketAsyncApiFunction::SocketAsyncApiFunction() {} | 64 SocketAsyncApiFunction::SocketAsyncApiFunction() {} |
56 | 65 |
57 SocketAsyncApiFunction::~SocketAsyncApiFunction() {} | 66 SocketAsyncApiFunction::~SocketAsyncApiFunction() {} |
58 | 67 |
59 bool SocketAsyncApiFunction::PrePrepare() { | 68 bool SocketAsyncApiFunction::PrePrepare() { |
60 manager_ = CreateSocketResourceManager(); | 69 manager_ = CreateSocketResourceManager(); |
61 return manager_->SetBrowserContext(browser_context()); | 70 return manager_->SetBrowserContext(browser_context()); |
62 } | 71 } |
63 | 72 |
64 bool SocketAsyncApiFunction::Respond() { return error_.empty(); } | 73 bool SocketAsyncApiFunction::Respond() { return error_.empty(); } |
(...skipping 18 matching lines...) Expand all Loading... | |
83 } | 92 } |
84 | 93 |
85 base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() { | 94 base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() { |
86 return manager_->GetResourceIds(extension_->id()); | 95 return manager_->GetResourceIds(extension_->id()); |
87 } | 96 } |
88 | 97 |
89 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) { | 98 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) { |
90 manager_->Remove(extension_->id(), api_resource_id); | 99 manager_->Remove(extension_->id(), api_resource_id); |
91 } | 100 } |
92 | 101 |
102 void SocketAsyncApiFunction::OpenFirewallHole(const std::string& address, | |
103 int socket_id, | |
104 Socket* socket) { | |
105 #if defined(OS_CHROMEOS) | |
106 if (!net::IsLocalhost(address)) { | |
107 net::IPEndPoint local_address; | |
108 if (!socket->GetLocalAddress(&local_address)) { | |
109 NOTREACHED() << "Cannot get address of recently bound socket."; | |
110 error_ = kFirewallFailure; | |
111 SetResult(new base::FundamentalValue(-1)); | |
112 AsyncWorkCompleted(); | |
113 return; | |
114 } | |
115 | |
116 chromeos::FirewallHole::PortType port_type; | |
117 if (socket->GetSocketType() == Socket::TYPE_TCP) { | |
118 port_type = chromeos::FirewallHole::PortType::TCP; | |
119 } else { | |
120 port_type = chromeos::FirewallHole::PortType::UDP; | |
121 } | |
122 | |
123 content::BrowserThread::PostTask( | |
124 content::BrowserThread::UI, FROM_HERE, | |
125 base::Bind( | |
126 &chromeos::FirewallHole::Open, port_type, local_address.port(), "", | |
pneubeck (no reviews)
2015/03/10 08:49:22
please add a comment /* all interfaces */ after ""
Reilly Grant (use Gerrit)
2015/03/10 20:15:17
Done.
| |
127 base::Bind(&SocketAsyncApiFunction::OnFirewallHoleOpenedOnUIThread, | |
128 this, socket_id))); | |
129 return; | |
130 } | |
131 #endif | |
132 AsyncWorkCompleted(); | |
133 } | |
134 | |
135 #if defined(OS_CHROMEOS) | |
136 | |
137 void SocketAsyncApiFunction::OnFirewallHoleOpenedOnUIThread( | |
138 int socket_id, | |
139 scoped_ptr<chromeos::FirewallHole> hole) { | |
140 content::BrowserThread::PostTask( | |
141 content::BrowserThread::IO, FROM_HERE, | |
142 base::Bind(&SocketAsyncApiFunction::OnFirewallHoleOpened, this, socket_id, | |
143 base::Passed(&hole))); | |
144 } | |
145 | |
146 void SocketAsyncApiFunction::OnFirewallHoleOpened( | |
147 int socket_id, | |
148 scoped_ptr<chromeos::FirewallHole> hole) { | |
149 if (!hole) { | |
150 error_ = kFirewallFailure; | |
151 SetResult(new base::FundamentalValue(-1)); | |
152 AsyncWorkCompleted(); | |
153 return; | |
154 } | |
155 | |
156 Socket* socket = GetSocket(socket_id); | |
157 if (!socket) { | |
158 error_ = kSocketNotFoundError; | |
159 SetResult(new base::FundamentalValue(-1)); | |
160 AsyncWorkCompleted(); | |
161 return; | |
162 } | |
163 | |
164 socket->set_firewall_hole(hole.Pass()); | |
165 AsyncWorkCompleted(); | |
166 } | |
167 | |
168 #endif // OS_CHROMEOS | |
169 | |
93 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction() | 170 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction() |
94 : resource_context_(NULL), | 171 : resource_context_(NULL), |
95 request_handle_(new net::HostResolver::RequestHandle), | 172 request_handle_(new net::HostResolver::RequestHandle), |
96 addresses_(new net::AddressList) {} | 173 addresses_(new net::AddressList) {} |
97 | 174 |
98 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {} | 175 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {} |
99 | 176 |
100 bool SocketExtensionWithDnsLookupFunction::PrePrepare() { | 177 bool SocketExtensionWithDnsLookupFunction::PrePrepare() { |
101 if (!SocketAsyncApiFunction::PrePrepare()) | 178 if (!SocketAsyncApiFunction::PrePrepare()) |
102 return false; | 179 return false; |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
287 bool SocketBindFunction::Prepare() { | 364 bool SocketBindFunction::Prepare() { |
288 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); | 365 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); |
289 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_)); | 366 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_)); |
290 int port; | 367 int port; |
291 EXTENSION_FUNCTION_VALIDATE( | 368 EXTENSION_FUNCTION_VALIDATE( |
292 args_->GetInteger(2, &port) && port >= 0 && port <= 65535); | 369 args_->GetInteger(2, &port) && port >= 0 && port <= 65535); |
293 port_ = static_cast<uint16>(port); | 370 port_ = static_cast<uint16>(port); |
294 return true; | 371 return true; |
295 } | 372 } |
296 | 373 |
297 void SocketBindFunction::Work() { | 374 void SocketBindFunction::AsyncWorkStart() { |
298 int result = -1; | |
299 Socket* socket = GetSocket(socket_id_); | 375 Socket* socket = GetSocket(socket_id_); |
300 | |
301 if (!socket) { | 376 if (!socket) { |
302 error_ = kSocketNotFoundError; | 377 error_ = kSocketNotFoundError; |
303 SetResult(new base::FundamentalValue(result)); | 378 SetResult(new base::FundamentalValue(-1)); |
379 AsyncWorkCompleted(); | |
304 return; | 380 return; |
305 } | 381 } |
306 | 382 |
307 if (socket->GetSocketType() == Socket::TYPE_UDP) { | 383 if (socket->GetSocketType() == Socket::TYPE_TCP) { |
308 SocketPermission::CheckParam param( | |
309 SocketPermissionRequest::UDP_BIND, address_, port_); | |
310 if (!extension()->permissions_data()->CheckAPIPermissionWithParam( | |
311 APIPermission::kSocket, ¶m)) { | |
312 error_ = kPermissionError; | |
313 SetResult(new base::FundamentalValue(result)); | |
314 return; | |
315 } | |
316 } else if (socket->GetSocketType() == Socket::TYPE_TCP) { | |
317 error_ = kTCPSocketBindError; | 384 error_ = kTCPSocketBindError; |
318 SetResult(new base::FundamentalValue(result)); | 385 SetResult(new base::FundamentalValue(-1)); |
386 AsyncWorkCompleted(); | |
319 return; | 387 return; |
320 } | 388 } |
321 | 389 |
322 result = socket->Bind(address_, port_); | 390 CHECK(socket->GetSocketType() == Socket::TYPE_UDP); |
391 SocketPermission::CheckParam param(SocketPermissionRequest::UDP_BIND, | |
392 address_, port_); | |
393 if (!extension()->permissions_data()->CheckAPIPermissionWithParam( | |
394 APIPermission::kSocket, ¶m)) { | |
395 error_ = kPermissionError; | |
396 SetResult(new base::FundamentalValue(-1)); | |
397 AsyncWorkCompleted(); | |
398 return; | |
399 } | |
400 | |
401 int result = socket->Bind(address_, port_); | |
323 SetResult(new base::FundamentalValue(result)); | 402 SetResult(new base::FundamentalValue(result)); |
403 if (result != net::OK) { | |
404 AsyncWorkCompleted(); | |
405 return; | |
406 } | |
407 | |
408 OpenFirewallHole(address_, socket_id_, socket); | |
324 } | 409 } |
325 | 410 |
326 SocketListenFunction::SocketListenFunction() {} | 411 SocketListenFunction::SocketListenFunction() {} |
327 | 412 |
328 SocketListenFunction::~SocketListenFunction() {} | 413 SocketListenFunction::~SocketListenFunction() {} |
329 | 414 |
330 bool SocketListenFunction::Prepare() { | 415 bool SocketListenFunction::Prepare() { |
331 params_ = core_api::socket::Listen::Params::Create(*args_); | 416 params_ = core_api::socket::Listen::Params::Create(*args_); |
332 EXTENSION_FUNCTION_VALIDATE(params_.get()); | 417 EXTENSION_FUNCTION_VALIDATE(params_.get()); |
333 return true; | 418 return true; |
334 } | 419 } |
335 | 420 |
336 void SocketListenFunction::Work() { | 421 void SocketListenFunction::AsyncWorkStart() { |
337 int result = -1; | |
338 | |
339 Socket* socket = GetSocket(params_->socket_id); | 422 Socket* socket = GetSocket(params_->socket_id); |
340 if (socket) { | 423 if (!socket) { |
341 SocketPermission::CheckParam param( | |
342 SocketPermissionRequest::TCP_LISTEN, params_->address, params_->port); | |
343 if (!extension()->permissions_data()->CheckAPIPermissionWithParam( | |
344 APIPermission::kSocket, ¶m)) { | |
345 error_ = kPermissionError; | |
346 SetResult(new base::FundamentalValue(result)); | |
347 return; | |
348 } | |
349 | |
350 result = | |
351 socket->Listen(params_->address, | |
352 params_->port, | |
353 params_->backlog.get() ? *params_->backlog.get() : 5, | |
354 &error_); | |
355 } else { | |
356 error_ = kSocketNotFoundError; | 424 error_ = kSocketNotFoundError; |
425 SetResult(new base::FundamentalValue(-1)); | |
426 AsyncWorkCompleted(); | |
427 return; | |
357 } | 428 } |
358 | 429 |
430 SocketPermission::CheckParam param(SocketPermissionRequest::TCP_LISTEN, | |
431 params_->address, params_->port); | |
432 if (!extension()->permissions_data()->CheckAPIPermissionWithParam( | |
433 APIPermission::kSocket, ¶m)) { | |
434 error_ = kPermissionError; | |
435 SetResult(new base::FundamentalValue(-1)); | |
436 AsyncWorkCompleted(); | |
437 return; | |
438 } | |
439 | |
440 int result = socket->Listen( | |
441 params_->address, params_->port, | |
442 params_->backlog.get() ? *params_->backlog.get() : 5, &error_); | |
359 SetResult(new base::FundamentalValue(result)); | 443 SetResult(new base::FundamentalValue(result)); |
444 if (result != net::OK) { | |
445 AsyncWorkCompleted(); | |
446 return; | |
447 } | |
448 | |
449 OpenFirewallHole(params_->address, params_->socket_id, socket); | |
360 } | 450 } |
361 | 451 |
362 SocketAcceptFunction::SocketAcceptFunction() {} | 452 SocketAcceptFunction::SocketAcceptFunction() {} |
363 | 453 |
364 SocketAcceptFunction::~SocketAcceptFunction() {} | 454 SocketAcceptFunction::~SocketAcceptFunction() {} |
365 | 455 |
366 bool SocketAcceptFunction::Prepare() { | 456 bool SocketAcceptFunction::Prepare() { |
367 params_ = core_api::socket::Accept::Params::Create(*args_); | 457 params_ = core_api::socket::Accept::Params::Create(*args_); |
368 EXTENSION_FUNCTION_VALIDATE(params_.get()); | 458 EXTENSION_FUNCTION_VALIDATE(params_.get()); |
369 return true; | 459 return true; |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
994 } else { | 1084 } else { |
995 RemoveSocket(params_->socket_id); | 1085 RemoveSocket(params_->socket_id); |
996 error_ = net::ErrorToString(result); | 1086 error_ = net::ErrorToString(result); |
997 } | 1087 } |
998 | 1088 |
999 results_ = core_api::socket::Secure::Results::Create(result); | 1089 results_ = core_api::socket::Secure::Results::Create(result); |
1000 AsyncWorkCompleted(); | 1090 AsyncWorkCompleted(); |
1001 } | 1091 } |
1002 | 1092 |
1003 } // namespace extensions | 1093 } // namespace extensions |
OLD | NEW |