| Index: chrome/browser/extensions/extension_web_socket_proxy_private_api.cc
|
| diff --git a/chrome/browser/extensions/extension_web_socket_proxy_private_api.cc b/chrome/browser/extensions/extension_web_socket_proxy_private_api.cc
|
| index 01f7ee1980e89ebd9b7f1b2f088899e58f175eff..b2cb933310eb8958e65432b5548307e193f94e87 100644
|
| --- a/chrome/browser/extensions/extension_web_socket_proxy_private_api.cc
|
| +++ b/chrome/browser/extensions/extension_web_socket_proxy_private_api.cc
|
| @@ -5,14 +5,22 @@
|
| #include "chrome/browser/extensions/extension_web_socket_proxy_private_api.h"
|
|
|
| #include "base/logging.h"
|
| -#include "base/values.h"
|
| +#include "base/stl_util.h"
|
| #include "base/string_number_conversions.h"
|
| +#include "base/values.h"
|
| +#include "chrome/browser/browser_process.h"
|
| #include "chrome/browser/internal_auth.h"
|
| +#include "chrome/browser/io_thread.h"
|
| #include "chrome/common/chrome_notification_types.h"
|
| #include "chrome/common/extensions/extension.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/notification_service.h"
|
| #include "content/public/browser/notification_details.h"
|
| #include "net/base/escape.h"
|
| +#include "net/base/net_errors.h"
|
| +#include "net/base/net_log.h"
|
| +#include "net/base/net_util.h"
|
| +#include "net/base/single_request_host_resolver.h"
|
|
|
| #if defined(OS_CHROMEOS)
|
| #include "chrome/browser/chromeos/web_socket_proxy_controller.h"
|
| @@ -24,25 +32,15 @@ const char kPermissionDeniedError[] =
|
| }
|
|
|
| WebSocketProxyPrivate::WebSocketProxyPrivate()
|
| - : is_finalized_(false), listening_port_(-1) {
|
| + : listening_port_(-1), do_tls_(false), is_finalized_(false){
|
| }
|
|
|
| WebSocketProxyPrivate::~WebSocketProxyPrivate() {
|
| }
|
|
|
| -void WebSocketProxyPrivate::Observe(
|
| - int type, const content::NotificationSource& source,
|
| - const content::NotificationDetails& details) {
|
| -#if defined(OS_CHROMEOS)
|
| - DCHECK_EQ(chrome::NOTIFICATION_WEB_SOCKET_PROXY_STARTED, type);
|
| -#else
|
| - NOTREACHED();
|
| -#endif
|
| - timer_.Stop(); // Cancel timeout timer.
|
| - Finalize();
|
| -}
|
| -
|
| void WebSocketProxyPrivate::Finalize() {
|
| + CustomFinalize();
|
| +
|
| if (is_finalized_)
|
| return;
|
| is_finalized_ = true;
|
| @@ -50,47 +48,63 @@ void WebSocketProxyPrivate::Finalize() {
|
| Release();
|
| }
|
|
|
| -void WebSocketProxyPrivateGetURLForTCPFunction::Observe(
|
| +void WebSocketProxyPrivate::Observe(
|
| int type, const content::NotificationSource& source,
|
| const content::NotificationDetails& details) {
|
| - listening_port_ = *content::Details<int>(details).ptr();
|
| - WebSocketProxyPrivate::Observe(type, source, details);
|
| +#if defined(OS_CHROMEOS)
|
| + DCHECK_EQ(chrome::NOTIFICATION_WEB_SOCKET_PROXY_STARTED, type);
|
| +#else
|
| + NOTREACHED();
|
| +#endif
|
| +
|
| + timer_.Stop(); // Cancel timeout timer.
|
| + ResolveHost();
|
| }
|
|
|
| -void WebSocketProxyPrivateGetURLForTCPFunction::Finalize() {
|
| +void WebSocketProxyPrivate::ResolveHost() {
|
| #if defined(OS_CHROMEOS)
|
| - if (listening_port_ < 1)
|
| - listening_port_ = chromeos::WebSocketProxyController::GetPort();
|
| - StringValue* url = Value::CreateStringValue(std::string(
|
| - "ws://127.0.0.1:" + base::IntToString(listening_port_) +
|
| - "/tcpproxy?" + query_));
|
| - result_.reset(url);
|
| + if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
|
| + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&WebSocketProxyPrivate::ResolveHost, this));
|
| + return;
|
| + }
|
| + DCHECK(resolver_ == NULL);
|
| + if (g_browser_process) {
|
| + IOThread* io_thread = g_browser_process->io_thread();
|
| + if (io_thread && io_thread->globals()) {
|
| + net::HostResolver* host_resolver =
|
| + io_thread->globals()->host_resolver.get();
|
| + if (host_resolver) {
|
| + resolver_.reset(new net::SingleRequestHostResolver(host_resolver));
|
| + net::HostResolver::RequestInfo info(net::HostPortPair(
|
| + hostname_, port_));
|
| + int result = resolver_->Resolve(info, &addr_,
|
| + base::Bind(&WebSocketProxyPrivate::OnHostResolution, this),
|
| + net::BoundNetLog());
|
| + if (result != net::ERR_IO_PENDING)
|
| + OnHostResolution(result);
|
| + return;
|
| + }
|
| + }
|
| + }
|
| + NOTREACHED();
|
| + OnHostResolution(net::ERR_UNEXPECTED);
|
| #endif
|
| - WebSocketProxyPrivate::Finalize();
|
| }
|
|
|
| -bool WebSocketProxyPrivateGetURLForTCPFunction::RunImpl() {
|
| +bool WebSocketProxyPrivate::RunImpl() {
|
| AddRef();
|
| - bool delay_response = false;
|
| result_.reset(Value::CreateStringValue(""));
|
|
|
| #if defined(OS_CHROMEOS)
|
| - std::string hostname;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &hostname));
|
| - int port = -1;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &port));
|
| - bool do_tls = false;
|
| - DictionaryValue* qualification = NULL;
|
| - if (args_->GetDictionary(2, &qualification)) {
|
| - const char kTlsOption[] = "tls";
|
| - if (qualification->HasKey(kTlsOption)) {
|
| - EXTENSION_FUNCTION_VALIDATE(qualification->GetBoolean(
|
| - kTlsOption, &do_tls));
|
| - }
|
| - }
|
| + bool delay_response = false;
|
| +
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &hostname_));
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &port_));
|
| +
|
| if (chromeos::WebSocketProxyController::CheckCredentials(
|
| - extension_id(), hostname, port,
|
| - do_tls ? chromeos::WebSocketProxyController::TLS_OVER_TCP :
|
| + extension_id(), hostname_, port_,
|
| + do_tls_ ? chromeos::WebSocketProxyController::TLS_OVER_TCP :
|
| chromeos::WebSocketProxyController::PLAIN_TCP)) {
|
| listening_port_ = chromeos::WebSocketProxyController::GetPort();
|
| if (listening_port_ < 1) {
|
| @@ -99,83 +113,102 @@ bool WebSocketProxyPrivateGetURLForTCPFunction::RunImpl() {
|
| this, chrome::NOTIFICATION_WEB_SOCKET_PROXY_STARTED,
|
| content::NotificationService::AllSources());
|
| }
|
| -
|
| - std::map<std::string, std::string> map;
|
| - map["hostname"] = hostname;
|
| - map["port"] = base::IntToString(port);
|
| - map["extension_id"] = extension_id();
|
| - map["tls"] = do_tls ? "true" : "false";
|
| - std::string passport = browser::InternalAuthGeneration::GeneratePassport(
|
| - "web_socket_proxy", map);
|
| - query_ = std::string("hostname=") +
|
| - net::EscapeQueryParamValue(hostname, false) + "&port=" + map["port"] +
|
| - "&tls=" + map["tls"] + "&passport=" +
|
| - net::EscapeQueryParamValue(passport, false);
|
| + map_["hostname"] = hostname_;
|
| + map_["port"] = base::IntToString(port_);
|
| + map_["extension_id"] = extension_id();
|
| } else {
|
| error_ = kPermissionDeniedError;
|
| return false;
|
| }
|
| -#endif // defined(OS_CHROMEOS)
|
|
|
| if (delay_response) {
|
| const int kTimeout = 12;
|
| timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kTimeout),
|
| - this, &WebSocketProxyPrivate::Finalize);
|
| + this, &WebSocketProxyPrivate::ResolveHost);
|
| } else {
|
| - Finalize();
|
| + ResolveHost();
|
| }
|
| +#else
|
| + Finalize();
|
| +#endif
|
| +
|
| return true;
|
| }
|
|
|
| -WebSocketProxyPrivateGetPassportForTCPFunction::
|
| - WebSocketProxyPrivateGetPassportForTCPFunction() {
|
| - // This obsolete API uses fixed port to listen websocket connections.
|
| - listening_port_ = 10101;
|
| +void WebSocketProxyPrivate::OnHostResolution(int result) {
|
| +#if defined(OS_CHROMEOS)
|
| + if (result == 0 && addr_.head() != NULL) {
|
| + std::string ip = net::NetAddressToString(addr_.head());
|
| + if (!ip.empty() && ip.find(':') != std::string::npos && ip[0] != '[')
|
| + ip = '[' + ip + ']';
|
| + map_["addr"] = ip;
|
| + }
|
| + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&WebSocketProxyPrivate::Finalize, this));
|
| +#endif
|
| }
|
|
|
| -bool WebSocketProxyPrivateGetPassportForTCPFunction::RunImpl() {
|
| - AddRef();
|
| - bool delay_response = false;
|
| - result_.reset(Value::CreateStringValue(""));
|
| +WebSocketProxyPrivateGetURLForTCPFunction::
|
| + WebSocketProxyPrivateGetURLForTCPFunction() {
|
| +}
|
| +
|
| +WebSocketProxyPrivateGetURLForTCPFunction::
|
| + ~WebSocketProxyPrivateGetURLForTCPFunction() {
|
| +}
|
|
|
| +void WebSocketProxyPrivateGetURLForTCPFunction::CustomFinalize() {
|
| #if defined(OS_CHROMEOS)
|
| - std::string hostname;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &hostname));
|
| - int port = -1;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &port));
|
| + std::string passport = browser::InternalAuthGeneration::GeneratePassport(
|
| + "web_socket_proxy", map_);
|
| + std::string query = std::string("hostname=") +
|
| + net::EscapeQueryParamValue(hostname_, false) + "&port=" + map_["port"] +
|
| + "&tls=" + map_["tls"] + "&passport=" +
|
| + net::EscapeQueryParamValue(passport, false);
|
| + if (ContainsKey(map_, "addr"))
|
| + query += std::string("&addr=") + map_["addr"];
|
|
|
| - if (chromeos::WebSocketProxyController::CheckCredentials(
|
| - extension_id(), hostname, port,
|
| - chromeos::WebSocketProxyController::PLAIN_TCP)) {
|
| + if (listening_port_ < 1)
|
| listening_port_ = chromeos::WebSocketProxyController::GetPort();
|
| - if (listening_port_ < 1) {
|
| - delay_response = true;
|
| - registrar_.Add(
|
| - this, chrome::NOTIFICATION_WEB_SOCKET_PROXY_STARTED,
|
| - content::NotificationService::AllSources());
|
| - }
|
| + StringValue* url = Value::CreateStringValue(std::string(
|
| + "ws://127.0.0.1:" + base::IntToString(listening_port_) +
|
| + "/tcpproxy?" + query));
|
| + result_.reset(url);
|
| +#endif
|
| +}
|
|
|
| - std::map<std::string, std::string> map;
|
| - map["hostname"] = hostname;
|
| - map["port"] = base::IntToString(port);
|
| - map["extension_id"] = extension_id();
|
| - StringValue* passport = Value::CreateStringValue(
|
| - browser::InternalAuthGeneration::GeneratePassport(
|
| - "web_socket_proxy", map));
|
| - result_.reset(passport);
|
| - } else {
|
| - error_ = kPermissionDeniedError;
|
| - return false;
|
| +bool WebSocketProxyPrivateGetURLForTCPFunction::RunImpl() {
|
| +#if defined(OS_CHROMEOS)
|
| + DictionaryValue* qualification = NULL;
|
| + if (args_->GetDictionary(2, &qualification)) {
|
| + const char kTlsOption[] = "tls";
|
| + if (qualification->HasKey(kTlsOption)) {
|
| + EXTENSION_FUNCTION_VALIDATE(qualification->GetBoolean(
|
| + kTlsOption, &do_tls_));
|
| + }
|
| }
|
| -#endif // defined(OS_CHROMEOS)
|
| + map_["tls"] = do_tls_ ? "true" : "false";
|
| +#endif
|
|
|
| - if (delay_response) {
|
| - const int kTimeout = 3;
|
| - timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kTimeout),
|
| - this, &WebSocketProxyPrivateGetPassportForTCPFunction::Finalize);
|
| - } else {
|
| - Finalize();
|
| - }
|
| - return true;
|
| + return WebSocketProxyPrivate::RunImpl();
|
| +}
|
| +
|
| +WebSocketProxyPrivateGetPassportForTCPFunction::
|
| + WebSocketProxyPrivateGetPassportForTCPFunction() {
|
| + // This obsolete API uses fixed port to listen websocket connections.
|
| + listening_port_ = 10101;
|
| }
|
|
|
| +WebSocketProxyPrivateGetPassportForTCPFunction::
|
| + ~WebSocketProxyPrivateGetPassportForTCPFunction() {
|
| +}
|
| +
|
| +void WebSocketProxyPrivateGetPassportForTCPFunction::CustomFinalize() {
|
| +#if defined(OS_CHROMEOS)
|
| + std::string passport =
|
| + browser::InternalAuthGeneration::GeneratePassport(
|
| + "web_socket_proxy", map_) + std::string(":");
|
| + if (ContainsKey(map_, "addr"))
|
| + passport += map_["addr"];
|
| + result_.reset(Value::CreateStringValue(passport));
|
| +#endif
|
| +}
|
|
|