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

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: Rebased. 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/command_line.h"
34 #include "chromeos/chromeos_switches.h"
35 #include "chromeos/network/firewall_hole.h"
36 #include "content/public/browser/browser_thread.h"
37 #endif // OS_CHROMEOS
38
32 namespace extensions { 39 namespace extensions {
33 40
34 using content::SocketPermissionRequest; 41 using content::SocketPermissionRequest;
35 42
36 const char kAddressKey[] = "address"; 43 const char kAddressKey[] = "address";
37 const char kPortKey[] = "port"; 44 const char kPortKey[] = "port";
38 const char kBytesWrittenKey[] = "bytesWritten"; 45 const char kBytesWrittenKey[] = "bytesWritten";
39 const char kDataKey[] = "data"; 46 const char kDataKey[] = "data";
40 const char kResultCodeKey[] = "resultCode"; 47 const char kResultCodeKey[] = "resultCode";
41 const char kSocketIdKey[] = "socketId"; 48 const char kSocketIdKey[] = "socketId";
42 49
43 const char kSocketNotFoundError[] = "Socket not found"; 50 const char kSocketNotFoundError[] = "Socket not found";
44 const char kDnsLookupFailedError[] = "DNS resolution failed"; 51 const char kDnsLookupFailedError[] = "DNS resolution failed";
45 const char kPermissionError[] = "App does not have permission"; 52 const char kPermissionError[] = "App does not have permission";
46 const char kNetworkListError[] = "Network lookup failed or unsupported"; 53 const char kNetworkListError[] = "Network lookup failed or unsupported";
47 const char kTCPSocketBindError[] = 54 const char kTCPSocketBindError[] =
48 "TCP socket does not support bind. For TCP server please use listen."; 55 "TCP socket does not support bind. For TCP server please use listen.";
49 const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast."; 56 const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast.";
50 const char kSecureSocketTypeError[] = "Only TCP sockets are supported for TLS."; 57 const char kSecureSocketTypeError[] = "Only TCP sockets are supported for TLS.";
51 const char kSocketNotConnectedError[] = "Socket not connected"; 58 const char kSocketNotConnectedError[] = "Socket not connected";
52 const char kWildcardAddress[] = "*"; 59 const char kWildcardAddress[] = "*";
53 const uint16 kWildcardPort = 0; 60 const uint16 kWildcardPort = 0;
54 61
62 #if defined(OS_CHROMEOS)
63 const char kFirewallFailure[] = "Failed to open firewall port";
64 #endif // OS_CHROMEOS
65
55 SocketAsyncApiFunction::SocketAsyncApiFunction() {} 66 SocketAsyncApiFunction::SocketAsyncApiFunction() {}
56 67
57 SocketAsyncApiFunction::~SocketAsyncApiFunction() {} 68 SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
58 69
59 bool SocketAsyncApiFunction::PrePrepare() { 70 bool SocketAsyncApiFunction::PrePrepare() {
60 manager_ = CreateSocketResourceManager(); 71 manager_ = CreateSocketResourceManager();
61 return manager_->SetBrowserContext(browser_context()); 72 return manager_->SetBrowserContext(browser_context());
62 } 73 }
63 74
64 bool SocketAsyncApiFunction::Respond() { return error_.empty(); } 75 bool SocketAsyncApiFunction::Respond() { return error_.empty(); }
(...skipping 18 matching lines...) Expand all
83 } 94 }
84 95
85 base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() { 96 base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() {
86 return manager_->GetResourceIds(extension_->id()); 97 return manager_->GetResourceIds(extension_->id());
87 } 98 }
88 99
89 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) { 100 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
90 manager_->Remove(extension_->id(), api_resource_id); 101 manager_->Remove(extension_->id(), api_resource_id);
91 } 102 }
92 103
104 void SocketAsyncApiFunction::OpenFirewallHole(const std::string& address,
105 int socket_id,
106 Socket* socket) {
107 #if defined(OS_CHROMEOS)
108 if (!net::IsLocalhost(address) &&
109 base::CommandLine::ForCurrentProcess()->HasSwitch(
110 chromeos::switches::kEnableFirewallHolePunching)) {
111 net::IPEndPoint local_address;
112 if (!socket->GetLocalAddress(&local_address)) {
113 NOTREACHED() << "Cannot get address of recently bound socket.";
114 error_ = kFirewallFailure;
115 SetResult(new base::FundamentalValue(-1));
116 AsyncWorkCompleted();
117 return;
118 }
119
120 chromeos::FirewallHole::PortType port_type;
121 if (socket->GetSocketType() == Socket::TYPE_TCP) {
122 port_type = chromeos::FirewallHole::PortType::TCP;
123 } else {
124 port_type = chromeos::FirewallHole::PortType::UDP;
125 }
126
127 content::BrowserThread::PostTask(
128 content::BrowserThread::UI, FROM_HERE,
129 base::Bind(
130 &chromeos::FirewallHole::Open, port_type, local_address.port(),
131 "" /* all interfaces */,
132 base::Bind(&SocketAsyncApiFunction::OnFirewallHoleOpenedOnUIThread,
133 this, socket_id)));
134 return;
135 }
136 #endif
137 AsyncWorkCompleted();
138 }
139
140 #if defined(OS_CHROMEOS)
141
142 void SocketAsyncApiFunction::OnFirewallHoleOpenedOnUIThread(
143 int socket_id,
144 scoped_ptr<chromeos::FirewallHole> hole) {
145 content::BrowserThread::PostTask(
146 content::BrowserThread::IO, FROM_HERE,
147 base::Bind(&SocketAsyncApiFunction::OnFirewallHoleOpened, this, socket_id,
148 base::Passed(&hole)));
149 }
150
151 void SocketAsyncApiFunction::OnFirewallHoleOpened(
152 int socket_id,
153 scoped_ptr<chromeos::FirewallHole> hole) {
154 if (!hole) {
155 error_ = kFirewallFailure;
156 SetResult(new base::FundamentalValue(-1));
157 AsyncWorkCompleted();
158 return;
159 }
160
161 Socket* socket = GetSocket(socket_id);
162 if (!socket) {
163 error_ = kSocketNotFoundError;
164 SetResult(new base::FundamentalValue(-1));
165 AsyncWorkCompleted();
166 return;
167 }
168
169 socket->set_firewall_hole(hole.Pass());
170 AsyncWorkCompleted();
171 }
172
173 #endif // OS_CHROMEOS
174
93 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction() 175 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction()
94 : resource_context_(NULL), 176 : resource_context_(NULL),
95 request_handle_(new net::HostResolver::RequestHandle), 177 request_handle_(new net::HostResolver::RequestHandle),
96 addresses_(new net::AddressList) {} 178 addresses_(new net::AddressList) {}
97 179
98 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {} 180 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {}
99 181
100 bool SocketExtensionWithDnsLookupFunction::PrePrepare() { 182 bool SocketExtensionWithDnsLookupFunction::PrePrepare() {
101 if (!SocketAsyncApiFunction::PrePrepare()) 183 if (!SocketAsyncApiFunction::PrePrepare())
102 return false; 184 return false;
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 bool SocketBindFunction::Prepare() { 369 bool SocketBindFunction::Prepare() {
288 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); 370 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
289 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_)); 371 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_));
290 int port; 372 int port;
291 EXTENSION_FUNCTION_VALIDATE( 373 EXTENSION_FUNCTION_VALIDATE(
292 args_->GetInteger(2, &port) && port >= 0 && port <= 65535); 374 args_->GetInteger(2, &port) && port >= 0 && port <= 65535);
293 port_ = static_cast<uint16>(port); 375 port_ = static_cast<uint16>(port);
294 return true; 376 return true;
295 } 377 }
296 378
297 void SocketBindFunction::Work() { 379 void SocketBindFunction::AsyncWorkStart() {
298 int result = -1;
299 Socket* socket = GetSocket(socket_id_); 380 Socket* socket = GetSocket(socket_id_);
300
301 if (!socket) { 381 if (!socket) {
302 error_ = kSocketNotFoundError; 382 error_ = kSocketNotFoundError;
303 SetResult(new base::FundamentalValue(result)); 383 SetResult(new base::FundamentalValue(-1));
384 AsyncWorkCompleted();
304 return; 385 return;
305 } 386 }
306 387
307 if (socket->GetSocketType() == Socket::TYPE_UDP) { 388 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; 389 error_ = kTCPSocketBindError;
318 SetResult(new base::FundamentalValue(result)); 390 SetResult(new base::FundamentalValue(-1));
391 AsyncWorkCompleted();
319 return; 392 return;
320 } 393 }
321 394
322 result = socket->Bind(address_, port_); 395 CHECK(socket->GetSocketType() == Socket::TYPE_UDP);
396 SocketPermission::CheckParam param(SocketPermissionRequest::UDP_BIND,
397 address_, port_);
398 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
399 APIPermission::kSocket, &param)) {
400 error_ = kPermissionError;
401 SetResult(new base::FundamentalValue(-1));
402 AsyncWorkCompleted();
403 return;
404 }
405
406 int result = socket->Bind(address_, port_);
323 SetResult(new base::FundamentalValue(result)); 407 SetResult(new base::FundamentalValue(result));
408 if (result != net::OK) {
409 AsyncWorkCompleted();
410 return;
411 }
412
413 OpenFirewallHole(address_, socket_id_, socket);
324 } 414 }
325 415
326 SocketListenFunction::SocketListenFunction() {} 416 SocketListenFunction::SocketListenFunction() {}
327 417
328 SocketListenFunction::~SocketListenFunction() {} 418 SocketListenFunction::~SocketListenFunction() {}
329 419
330 bool SocketListenFunction::Prepare() { 420 bool SocketListenFunction::Prepare() {
331 params_ = core_api::socket::Listen::Params::Create(*args_); 421 params_ = core_api::socket::Listen::Params::Create(*args_);
332 EXTENSION_FUNCTION_VALIDATE(params_.get()); 422 EXTENSION_FUNCTION_VALIDATE(params_.get());
333 return true; 423 return true;
334 } 424 }
335 425
336 void SocketListenFunction::Work() { 426 void SocketListenFunction::AsyncWorkStart() {
337 int result = -1;
338
339 Socket* socket = GetSocket(params_->socket_id); 427 Socket* socket = GetSocket(params_->socket_id);
340 if (socket) { 428 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; 429 error_ = kSocketNotFoundError;
430 SetResult(new base::FundamentalValue(-1));
431 AsyncWorkCompleted();
432 return;
357 } 433 }
358 434
435 SocketPermission::CheckParam param(SocketPermissionRequest::TCP_LISTEN,
436 params_->address, params_->port);
437 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
438 APIPermission::kSocket, &param)) {
439 error_ = kPermissionError;
440 SetResult(new base::FundamentalValue(-1));
441 AsyncWorkCompleted();
442 return;
443 }
444
445 int result = socket->Listen(
446 params_->address, params_->port,
447 params_->backlog.get() ? *params_->backlog.get() : 5, &error_);
359 SetResult(new base::FundamentalValue(result)); 448 SetResult(new base::FundamentalValue(result));
449 if (result != net::OK) {
450 AsyncWorkCompleted();
451 return;
452 }
453
454 OpenFirewallHole(params_->address, params_->socket_id, socket);
360 } 455 }
361 456
362 SocketAcceptFunction::SocketAcceptFunction() {} 457 SocketAcceptFunction::SocketAcceptFunction() {}
363 458
364 SocketAcceptFunction::~SocketAcceptFunction() {} 459 SocketAcceptFunction::~SocketAcceptFunction() {}
365 460
366 bool SocketAcceptFunction::Prepare() { 461 bool SocketAcceptFunction::Prepare() {
367 params_ = core_api::socket::Accept::Params::Create(*args_); 462 params_ = core_api::socket::Accept::Params::Create(*args_);
368 EXTENSION_FUNCTION_VALIDATE(params_.get()); 463 EXTENSION_FUNCTION_VALIDATE(params_.get());
369 return true; 464 return true;
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 } else { 1089 } else {
995 RemoveSocket(params_->socket_id); 1090 RemoveSocket(params_->socket_id);
996 error_ = net::ErrorToString(result); 1091 error_ = net::ErrorToString(result);
997 } 1092 }
998 1093
999 results_ = core_api::socket::Secure::Results::Create(result); 1094 results_ = core_api::socket::Secure::Results::Create(result);
1000 AsyncWorkCompleted(); 1095 AsyncWorkCompleted();
1001 } 1096 }
1002 1097
1003 } // namespace extensions 1098 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/api/socket/socket_api.h ('k') | extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698