| Index: extensions/browser/api/socket/socket_api.cc
|
| diff --git a/extensions/browser/api/socket/socket_api.cc b/extensions/browser/api/socket/socket_api.cc
|
| index dca379ab144f381e4f4db4720eeeb230ac7b914a..20f9c62bbfb04affd948e58ac5c9e2916ce89a8a 100644
|
| --- a/extensions/browser/api/socket/socket_api.cc
|
| +++ b/extensions/browser/api/socket/socket_api.cc
|
| @@ -29,6 +29,12 @@
|
| #include "net/url_request/url_request_context.h"
|
| #include "net/url_request/url_request_context_getter.h"
|
|
|
| +#if defined(OS_CHROMEOS)
|
| +#include "base/sys_info.h"
|
| +#include "chromeos/network/firewall_hole.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +#endif // OS_CHROMEOS
|
| +
|
| namespace extensions {
|
|
|
| using content::SocketPermissionRequest;
|
| @@ -52,6 +58,10 @@ const char kSocketNotConnectedError[] = "Socket not connected";
|
| const char kWildcardAddress[] = "*";
|
| const uint16 kWildcardPort = 0;
|
|
|
| +#if defined(OS_CHROMEOS)
|
| +const char kFirewallFailure[] = "Failed to open firewall port";
|
| +#endif // OS_CHROMEOS
|
| +
|
| SocketAsyncApiFunction::SocketAsyncApiFunction() {}
|
|
|
| SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
|
| @@ -90,6 +100,73 @@ void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
|
| manager_->Remove(extension_->id(), api_resource_id);
|
| }
|
|
|
| +void SocketAsyncApiFunction::OpenFirewallHole(const std::string& address,
|
| + int socket_id,
|
| + Socket* socket) {
|
| +#if defined(OS_CHROMEOS)
|
| + if (base::SysInfo::IsRunningOnChromeOS() && !net::IsLocalhost(address)) {
|
| + net::IPEndPoint local_address;
|
| + if (!socket->GetLocalAddress(&local_address)) {
|
| + NOTREACHED() << "Cannot get address of recently bound socket.";
|
| + error_ = kFirewallFailure;
|
| + SetResult(new base::FundamentalValue(-1));
|
| + AsyncWorkCompleted();
|
| + return;
|
| + }
|
| +
|
| + chromeos::FirewallHole::PortType port_type;
|
| + if (socket->GetSocketType() == Socket::TYPE_TCP) {
|
| + port_type = chromeos::FirewallHole::TCP;
|
| + } else {
|
| + port_type = chromeos::FirewallHole::UDP;
|
| + }
|
| +
|
| + content::BrowserThread::PostTask(
|
| + content::BrowserThread::UI, FROM_HERE,
|
| + base::Bind(
|
| + &chromeos::FirewallHole::Open, port_type, local_address.port(), "",
|
| + base::Bind(&SocketAsyncApiFunction::OnFirewallHoleOpenedOnUIThread,
|
| + this, socket_id)));
|
| + return;
|
| + }
|
| +#endif
|
| + AsyncWorkCompleted();
|
| +}
|
| +
|
| +#if defined(OS_CHROMEOS)
|
| +
|
| +void SocketAsyncApiFunction::OnFirewallHoleOpenedOnUIThread(
|
| + int socket_id,
|
| + scoped_ptr<chromeos::FirewallHole> hole) {
|
| + content::BrowserThread::PostTask(
|
| + content::BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&SocketAsyncApiFunction::OnFirewallHoleOpened, this, socket_id,
|
| + base::Passed(&hole)));
|
| +}
|
| +
|
| +void SocketAsyncApiFunction::OnFirewallHoleOpened(
|
| + int socket_id,
|
| + scoped_ptr<chromeos::FirewallHole> hole) {
|
| + if (!hole) {
|
| + error_ = kFirewallFailure;
|
| + SetResult(new base::FundamentalValue(-1));
|
| + AsyncWorkCompleted();
|
| + return;
|
| + }
|
| +
|
| + Socket* socket = GetSocket(socket_id);
|
| + if (!socket) {
|
| + error_ = kSocketNotFoundError;
|
| + SetResult(new base::FundamentalValue(-1));
|
| + AsyncWorkCompleted();
|
| + return;
|
| + }
|
| +
|
| + socket->set_firewall_hole(hole.Pass());
|
| +}
|
| +
|
| +#endif // OS_CHROMEOS
|
| +
|
| SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction()
|
| : resource_context_(NULL),
|
| request_handle_(new net::HostResolver::RequestHandle),
|
| @@ -294,33 +371,41 @@ bool SocketBindFunction::Prepare() {
|
| return true;
|
| }
|
|
|
| -void SocketBindFunction::Work() {
|
| - int result = -1;
|
| +void SocketBindFunction::AsyncWorkStart() {
|
| Socket* socket = GetSocket(socket_id_);
|
| -
|
| if (!socket) {
|
| error_ = kSocketNotFoundError;
|
| - SetResult(new base::FundamentalValue(result));
|
| + SetResult(new base::FundamentalValue(-1));
|
| + AsyncWorkCompleted();
|
| return;
|
| }
|
|
|
| - if (socket->GetSocketType() == Socket::TYPE_UDP) {
|
| - SocketPermission::CheckParam param(
|
| - SocketPermissionRequest::UDP_BIND, address_, port_);
|
| - if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
|
| - APIPermission::kSocket, ¶m)) {
|
| - error_ = kPermissionError;
|
| - SetResult(new base::FundamentalValue(result));
|
| - return;
|
| - }
|
| - } else if (socket->GetSocketType() == Socket::TYPE_TCP) {
|
| + if (socket->GetSocketType() == Socket::TYPE_TCP) {
|
| error_ = kTCPSocketBindError;
|
| - SetResult(new base::FundamentalValue(result));
|
| + SetResult(new base::FundamentalValue(-1));
|
| + AsyncWorkCompleted();
|
| + return;
|
| + }
|
| +
|
| + CHECK(socket->GetSocketType() == Socket::TYPE_UDP);
|
| + SocketPermission::CheckParam param(SocketPermissionRequest::UDP_BIND,
|
| + address_, port_);
|
| + if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
|
| + APIPermission::kSocket, ¶m)) {
|
| + error_ = kPermissionError;
|
| + SetResult(new base::FundamentalValue(-1));
|
| + AsyncWorkCompleted();
|
| return;
|
| }
|
|
|
| - result = socket->Bind(address_, port_);
|
| + int result = socket->Bind(address_, port_);
|
| SetResult(new base::FundamentalValue(result));
|
| + if (result != net::OK) {
|
| + AsyncWorkCompleted();
|
| + return;
|
| + }
|
| +
|
| + OpenFirewallHole(address_, socket_id_, socket);
|
| }
|
|
|
| SocketListenFunction::SocketListenFunction() {}
|
| @@ -333,30 +418,35 @@ bool SocketListenFunction::Prepare() {
|
| return true;
|
| }
|
|
|
| -void SocketListenFunction::Work() {
|
| - int result = -1;
|
| -
|
| +void SocketListenFunction::AsyncWorkStart() {
|
| Socket* socket = GetSocket(params_->socket_id);
|
| - if (socket) {
|
| - SocketPermission::CheckParam param(
|
| - SocketPermissionRequest::TCP_LISTEN, params_->address, params_->port);
|
| - if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
|
| - APIPermission::kSocket, ¶m)) {
|
| - error_ = kPermissionError;
|
| - SetResult(new base::FundamentalValue(result));
|
| - return;
|
| - }
|
| -
|
| - result =
|
| - socket->Listen(params_->address,
|
| - params_->port,
|
| - params_->backlog.get() ? *params_->backlog.get() : 5,
|
| - &error_);
|
| - } else {
|
| + if (!socket) {
|
| error_ = kSocketNotFoundError;
|
| + SetResult(new base::FundamentalValue(-1));
|
| + AsyncWorkCompleted();
|
| + return;
|
| + }
|
| +
|
| + SocketPermission::CheckParam param(SocketPermissionRequest::TCP_LISTEN,
|
| + params_->address, params_->port);
|
| + if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
|
| + APIPermission::kSocket, ¶m)) {
|
| + error_ = kPermissionError;
|
| + SetResult(new base::FundamentalValue(-1));
|
| + AsyncWorkCompleted();
|
| + return;
|
| }
|
|
|
| + int result = socket->Listen(
|
| + params_->address, params_->port,
|
| + params_->backlog.get() ? *params_->backlog.get() : 5, &error_);
|
| SetResult(new base::FundamentalValue(result));
|
| + if (result != net::OK) {
|
| + AsyncWorkCompleted();
|
| + return;
|
| + }
|
| +
|
| + OpenFirewallHole(params_->address, params_->socket_id, socket);
|
| }
|
|
|
| SocketAcceptFunction::SocketAcceptFunction() {}
|
|
|