| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/chromeos/web_socket_proxy_controller.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include <netinet/in.h> | |
| 10 #include <sys/wait.h> | |
| 11 #include <unistd.h> | |
| 12 | |
| 13 #include "base/bind.h" | |
| 14 #include "base/bind_helpers.h" | |
| 15 #include "base/command_line.h" | |
| 16 #include "base/lazy_instance.h" | |
| 17 #include "base/message_loop/message_loop.h" | |
| 18 #include "base/threading/thread.h" | |
| 19 #include "chrome/browser/browser_process.h" | |
| 20 #include "chrome/browser/chrome_notification_types.h" | |
| 21 #include "chrome/browser/chromeos/web_socket_proxy.h" | |
| 22 #include "chrome/common/chrome_switches.h" | |
| 23 #include "chrome/common/extensions/extension.h" | |
| 24 #include "chrome/common/url_constants.h" | |
| 25 #include "content/public/browser/notification_observer.h" | |
| 26 #include "content/public/browser/notification_registrar.h" | |
| 27 #include "content/public/browser/notification_service.h" | |
| 28 #include "content/public/common/url_constants.h" | |
| 29 #include "net/base/network_change_notifier.h" | |
| 30 #include "url/gurl.h" | |
| 31 | |
| 32 namespace { | |
| 33 | |
| 34 class ProxyLifetime | |
| 35 : public net::NetworkChangeNotifier::ConnectionTypeObserver, | |
| 36 public content::NotificationObserver { | |
| 37 public: | |
| 38 ProxyLifetime() | |
| 39 : delay_ms_(1000), | |
| 40 port_(-1), | |
| 41 shutdown_requested_(false), | |
| 42 web_socket_proxy_thread_("Chrome_WebSocketproxyThread") { | |
| 43 DLOG(INFO) << "WebSocketProxyController initiation"; | |
| 44 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0); | |
| 45 web_socket_proxy_thread_.StartWithOptions(options); | |
| 46 web_socket_proxy_thread_.message_loop()->PostTask( | |
| 47 FROM_HERE, | |
| 48 base::Bind(&ProxyLifetime::ProxyCallback, base::Unretained(this))); | |
| 49 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); | |
| 50 registrar_.Add( | |
| 51 this, chrome::NOTIFICATION_WEB_SOCKET_PROXY_STARTED, | |
| 52 content::NotificationService::AllSources()); | |
| 53 } | |
| 54 | |
| 55 virtual ~ProxyLifetime() { | |
| 56 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | |
| 57 } | |
| 58 | |
| 59 virtual void Observe(int type, const content::NotificationSource& source, | |
| 60 const content::NotificationDetails& details) OVERRIDE { | |
| 61 base::AutoLock alk(lock_); | |
| 62 port_ = *content::Details<int>(details).ptr(); | |
| 63 } | |
| 64 | |
| 65 int GetPort() { | |
| 66 base::AutoLock alk(lock_); | |
| 67 return port_; | |
| 68 } | |
| 69 | |
| 70 private: | |
| 71 // net::NetworkChangeNotifier::ConnectionTypeObserver implementation. | |
| 72 virtual void OnConnectionTypeChanged( | |
| 73 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE { | |
| 74 DCHECK(chromeos::WebSocketProxyController::IsInitiated()); | |
| 75 base::AutoLock alk(lock_); | |
| 76 if (server_) | |
| 77 server_->OnNetworkChange(); | |
| 78 } | |
| 79 | |
| 80 void ProxyCallback() { | |
| 81 LOG(INFO) << "Attempt to run web socket proxy task"; | |
| 82 chromeos::WebSocketProxy* server = new chromeos::WebSocketProxy(); | |
| 83 { | |
| 84 base::AutoLock alk(lock_); | |
| 85 if (shutdown_requested_) | |
| 86 return; | |
| 87 delete server_; | |
| 88 server_ = server; | |
| 89 } | |
| 90 server->Run(); | |
| 91 { | |
| 92 base::AutoLock alk(lock_); | |
| 93 delete server; | |
| 94 server_ = NULL; | |
| 95 if (!shutdown_requested_) { | |
| 96 // Proxy terminated unexpectedly or failed to start (it can happen due | |
| 97 // to a network problem). Keep trying. | |
| 98 if (delay_ms_ < 100 * 1000) | |
| 99 (delay_ms_ *= 3) /= 2; | |
| 100 | |
| 101 base::MessageLoop::current()->PostDelayedTask( | |
| 102 FROM_HERE, | |
| 103 base::Bind(&ProxyLifetime::ProxyCallback, base::Unretained(this)), | |
| 104 base::TimeDelta::FromMilliseconds(delay_ms_)); | |
| 105 } | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 // Delay in milliseconds between next attempt to run proxy. | |
| 110 int volatile delay_ms_; | |
| 111 | |
| 112 // Proxy listens for incoming websocket connections on this port. | |
| 113 int volatile port_; | |
| 114 | |
| 115 chromeos::WebSocketProxy* volatile server_; | |
| 116 volatile bool shutdown_requested_; | |
| 117 base::Lock lock_; | |
| 118 content::NotificationRegistrar registrar_; | |
| 119 friend class chromeos::WebSocketProxyController; | |
| 120 base::Thread web_socket_proxy_thread_; | |
| 121 }; | |
| 122 | |
| 123 base::LazyInstance<ProxyLifetime> g_proxy_lifetime = LAZY_INSTANCE_INITIALIZER; | |
| 124 | |
| 125 } // namespace | |
| 126 | |
| 127 namespace chromeos { | |
| 128 | |
| 129 // static | |
| 130 void WebSocketProxyController::Initiate() { | |
| 131 g_proxy_lifetime.Get(); | |
| 132 } | |
| 133 | |
| 134 // static | |
| 135 bool WebSocketProxyController::IsInitiated() { | |
| 136 return !(g_proxy_lifetime == NULL); | |
| 137 } | |
| 138 | |
| 139 // static | |
| 140 int WebSocketProxyController::GetPort() { | |
| 141 int port = g_proxy_lifetime.Get().GetPort(); | |
| 142 DCHECK(IsInitiated()); | |
| 143 return port; | |
| 144 } | |
| 145 | |
| 146 // static | |
| 147 void WebSocketProxyController::Shutdown() { | |
| 148 if (!IsInitiated()) | |
| 149 return; | |
| 150 | |
| 151 DLOG(INFO) << "WebSocketProxyController shutdown"; | |
| 152 { | |
| 153 base::AutoLock alk(g_proxy_lifetime.Get().lock_); | |
| 154 g_proxy_lifetime.Get().shutdown_requested_ = true; | |
| 155 if (g_proxy_lifetime.Get().server_) | |
| 156 g_proxy_lifetime.Get().server_->Shutdown(); | |
| 157 } | |
| 158 g_proxy_lifetime.Get().web_socket_proxy_thread_.Stop(); | |
| 159 } | |
| 160 | |
| 161 } // namespace chromeos | |
| OLD | NEW |