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 |
+} |