Chromium Code Reviews| 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..19dfbfbd8954fd658e0897854152340a3354b8ba 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,98 @@ 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) |
| + map_["addr"] = net::NetAddressToString(addr_.head()); |
| + 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"]; |
|
Denis Lagno
2011/11/18 23:05:25
nit: this will fail if hostname resolved into IPv6
altimofeev
2011/11/21 17:29:42
Good point, thanks! Fixed parsing on the WebSocket
|
| + result_.reset(Value::CreateStringValue(passport)); |
| +#endif |
| +} |