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.
5 #include "chrome/browser/chromeos/web_socket_proxy_controller.h"
9 #include <netinet/in.h>
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.h"
18 #include "base/string_tokenizer.h"
19 #include "base/threading/thread.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/chromeos/web_socket_proxy.h"
22 #include "chrome/common/chrome_notification_types.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/extensions/extension.h"
25 #include "chrome/common/url_constants.h"
26 #include "content/public/browser/notification_observer.h"
27 #include "content/public/browser/notification_registrar.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/common/url_constants.h"
30 #include "googleurl/src/gurl.h"
31 #include "net/base/network_change_notifier.h"
36 : public net::NetworkChangeNotifier::ConnectionTypeObserver
,
37 public content::NotificationObserver
{
42 shutdown_requested_(false),
43 web_socket_proxy_thread_("Chrome_WebSocketproxyThread") {
44 DLOG(INFO
) << "WebSocketProxyController initiation";
45 base::Thread::Options
options(MessageLoop::TYPE_IO
, 0);
46 web_socket_proxy_thread_
.StartWithOptions(options
);
47 web_socket_proxy_thread_
.message_loop()->PostTask(
49 base::Bind(&ProxyLifetime::ProxyCallback
, base::Unretained(this)));
50 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
52 this, chrome::NOTIFICATION_WEB_SOCKET_PROXY_STARTED
,
53 content::NotificationService::AllSources());
56 virtual ~ProxyLifetime() {
57 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
60 virtual void Observe(int type
, const content::NotificationSource
& source
,
61 const content::NotificationDetails
& details
) OVERRIDE
{
62 base::AutoLock
alk(lock_
);
63 port_
= *content::Details
<int>(details
).ptr();
67 base::AutoLock
alk(lock_
);
72 // net::NetworkChangeNotifier::ConnectionTypeObserver implementation.
73 virtual void OnConnectionTypeChanged(
74 net::NetworkChangeNotifier::ConnectionType type
) OVERRIDE
{
75 DCHECK(chromeos::WebSocketProxyController::IsInitiated());
76 base::AutoLock
alk(lock_
);
78 server_
->OnNetworkChange();
81 void ProxyCallback() {
82 LOG(INFO
) << "Attempt to run web socket proxy task";
83 chromeos::WebSocketProxy
* server
= new chromeos::WebSocketProxy();
85 base::AutoLock
alk(lock_
);
86 if (shutdown_requested_
)
93 base::AutoLock
alk(lock_
);
96 if (!shutdown_requested_
) {
97 // Proxy terminated unexpectedly or failed to start (it can happen due
98 // to a network problem). Keep trying.
99 if (delay_ms_
< 100 * 1000)
100 (delay_ms_
*= 3) /= 2;
102 MessageLoop::current()->PostDelayedTask(
104 base::Bind(&ProxyLifetime::ProxyCallback
, base::Unretained(this)),
105 base::TimeDelta::FromMilliseconds(delay_ms_
));
110 // Delay in milliseconds between next attempt to run proxy.
111 int volatile delay_ms_
;
113 // Proxy listens for incoming websocket connections on this port.
116 chromeos::WebSocketProxy
* volatile server_
;
117 volatile bool shutdown_requested_
;
119 content::NotificationRegistrar registrar_
;
120 friend class chromeos::WebSocketProxyController
;
121 base::Thread web_socket_proxy_thread_
;
124 base::LazyInstance
<ProxyLifetime
> g_proxy_lifetime
= LAZY_INSTANCE_INITIALIZER
;
131 void WebSocketProxyController::Initiate() {
132 g_proxy_lifetime
.Get();
136 bool WebSocketProxyController::IsInitiated() {
137 return !(g_proxy_lifetime
== NULL
);
141 int WebSocketProxyController::GetPort() {
142 int port
= g_proxy_lifetime
.Get().GetPort();
143 DCHECK(IsInitiated());
148 void WebSocketProxyController::Shutdown() {
152 DLOG(INFO
) << "WebSocketProxyController shutdown";
154 base::AutoLock
alk(g_proxy_lifetime
.Get().lock_
);
155 g_proxy_lifetime
.Get().shutdown_requested_
= true;
156 if (g_proxy_lifetime
.Get().server_
)
157 g_proxy_lifetime
.Get().server_
->Shutdown();
159 g_proxy_lifetime
.Get().web_socket_proxy_thread_
.Stop();
162 } // namespace chromeos