Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: extensions/browser/api/socket/socket_api.cc

Issue 965613002: Open a firewall hole when a TCP server or UDP socket is bound. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Actually use the thread_checker_ in FirewallHole. Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 "base/sys_info.h"
34 #include "chromeos/network/firewall_hole.h"
35 #include "content/public/browser/browser_thread.h"
36 #endif // OS_CHROMEOS
37
32 namespace extensions { 38 namespace extensions {
33 39
34 using content::SocketPermissionRequest; 40 using content::SocketPermissionRequest;
35 41
36 const char kAddressKey[] = "address"; 42 const char kAddressKey[] = "address";
37 const char kPortKey[] = "port"; 43 const char kPortKey[] = "port";
38 const char kBytesWrittenKey[] = "bytesWritten"; 44 const char kBytesWrittenKey[] = "bytesWritten";
39 const char kDataKey[] = "data"; 45 const char kDataKey[] = "data";
40 const char kResultCodeKey[] = "resultCode"; 46 const char kResultCodeKey[] = "resultCode";
41 const char kSocketIdKey[] = "socketId"; 47 const char kSocketIdKey[] = "socketId";
42 48
43 const char kSocketNotFoundError[] = "Socket not found"; 49 const char kSocketNotFoundError[] = "Socket not found";
44 const char kDnsLookupFailedError[] = "DNS resolution failed"; 50 const char kDnsLookupFailedError[] = "DNS resolution failed";
45 const char kPermissionError[] = "App does not have permission"; 51 const char kPermissionError[] = "App does not have permission";
46 const char kNetworkListError[] = "Network lookup failed or unsupported"; 52 const char kNetworkListError[] = "Network lookup failed or unsupported";
47 const char kTCPSocketBindError[] = 53 const char kTCPSocketBindError[] =
48 "TCP socket does not support bind. For TCP server please use listen."; 54 "TCP socket does not support bind. For TCP server please use listen.";
49 const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast."; 55 const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast.";
50 const char kSecureSocketTypeError[] = "Only TCP sockets are supported for TLS."; 56 const char kSecureSocketTypeError[] = "Only TCP sockets are supported for TLS.";
51 const char kSocketNotConnectedError[] = "Socket not connected"; 57 const char kSocketNotConnectedError[] = "Socket not connected";
52 const char kWildcardAddress[] = "*"; 58 const char kWildcardAddress[] = "*";
53 const uint16 kWildcardPort = 0; 59 const uint16 kWildcardPort = 0;
54 60
61 #if defined(OS_CHROMEOS)
62 const char kFirewallFailure[] = "Failed to open firewall port";
63 #endif // OS_CHROMEOS
64
55 SocketAsyncApiFunction::SocketAsyncApiFunction() {} 65 SocketAsyncApiFunction::SocketAsyncApiFunction() {}
56 66
57 SocketAsyncApiFunction::~SocketAsyncApiFunction() {} 67 SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
58 68
59 bool SocketAsyncApiFunction::PrePrepare() { 69 bool SocketAsyncApiFunction::PrePrepare() {
60 manager_ = CreateSocketResourceManager(); 70 manager_ = CreateSocketResourceManager();
61 return manager_->SetBrowserContext(browser_context()); 71 return manager_->SetBrowserContext(browser_context());
62 } 72 }
63 73
64 bool SocketAsyncApiFunction::Respond() { return error_.empty(); } 74 bool SocketAsyncApiFunction::Respond() { return error_.empty(); }
(...skipping 18 matching lines...) Expand all
83 } 93 }
84 94
85 base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() { 95 base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() {
86 return manager_->GetResourceIds(extension_->id()); 96 return manager_->GetResourceIds(extension_->id());
87 } 97 }
88 98
89 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) { 99 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
90 manager_->Remove(extension_->id(), api_resource_id); 100 manager_->Remove(extension_->id(), api_resource_id);
91 } 101 }
92 102
103 void SocketAsyncApiFunction::OpenFirewallHole(const std::string& address,
104 int socket_id,
105 Socket* socket) {
106 #if defined(OS_CHROMEOS)
107 if (base::SysInfo::IsRunningOnChromeOS() && !net::IsLocalhost(address)) {
108 net::IPEndPoint local_address;
109 if (!socket->GetLocalAddress(&local_address)) {
110 NOTREACHED() << "Cannot get address of recently bound socket.";
111 error_ = kFirewallFailure;
112 SetResult(new base::FundamentalValue(-1));
113 AsyncWorkCompleted();
114 return;
115 }
116
117 chromeos::FirewallHole::PortType port_type;
118 if (socket->GetSocketType() == Socket::TYPE_TCP) {
119 port_type = chromeos::FirewallHole::TCP;
120 } else {
121 port_type = chromeos::FirewallHole::UDP;
122 }
123
124 content::BrowserThread::PostTask(
125 content::BrowserThread::UI, FROM_HERE,
126 base::Bind(
127 &chromeos::FirewallHole::Open, port_type, local_address.port(), "",
128 base::Bind(&SocketAsyncApiFunction::OnFirewallHoleOpenedOnUIThread,
129 this, socket_id)));
130 return;
131 }
132 #endif
133 AsyncWorkCompleted();
134 }
135
136 #if defined(OS_CHROMEOS)
137
138 void SocketAsyncApiFunction::OnFirewallHoleOpenedOnUIThread(
139 int socket_id,
140 scoped_ptr<chromeos::FirewallHole> hole) {
141 content::BrowserThread::PostTask(
142 content::BrowserThread::IO, FROM_HERE,
143 base::Bind(&SocketAsyncApiFunction::OnFirewallHoleOpened, this, socket_id,
144 base::Passed(&hole)));
145 }
146
147 void SocketAsyncApiFunction::OnFirewallHoleOpened(
148 int socket_id,
149 scoped_ptr<chromeos::FirewallHole> hole) {
150 if (!hole) {
151 error_ = kFirewallFailure;
152 SetResult(new base::FundamentalValue(-1));
153 AsyncWorkCompleted();
154 return;
155 }
156
157 Socket* socket = GetSocket(socket_id);
158 if (!socket) {
159 error_ = kSocketNotFoundError;
160 SetResult(new base::FundamentalValue(-1));
161 AsyncWorkCompleted();
162 return;
163 }
164
165 socket->set_firewall_hole(hole.Pass());
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
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, &param)) {
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, &param)) {
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, &param)) {
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, &param)) {
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698