OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "web_socket_proxy_controller.h" | 5 #include "web_socket_proxy_controller.h" |
6 | 6 |
7 #include <algorithm> | |
8 | |
7 #include <netinet/in.h> | 9 #include <netinet/in.h> |
8 #include <sys/wait.h> | 10 #include <sys/wait.h> |
9 #include <unistd.h> | 11 #include <unistd.h> |
10 | 12 |
13 #include "base/command_line.h" | |
11 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
12 #include "base/message_loop.h" | 15 #include "base/message_loop.h" |
16 #include "base/string_tokenizer.h" | |
13 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
14 #include "chrome/browser/browser_process.h" | 18 #include "chrome/browser/browser_process.h" |
15 #include "chrome/browser/chromeos/web_socket_proxy.h" | 19 #include "chrome/browser/chromeos/web_socket_proxy.h" |
20 #include "chrome/common/chrome_switches.h" | |
21 #include "chrome/common/extensions/extension.h" | |
16 #include "content/browser/browser_thread.h" | 22 #include "content/browser/browser_thread.h" |
23 #include "content/common/url_constants.h" | |
24 #include "googleurl/src/gurl.h" | |
17 | 25 |
18 namespace { | 26 namespace { |
19 | 27 |
28 const char* kWebAppId = "haiffjcadagjlijoggckpgfnoeiflnem"; | |
29 | |
30 const char* kAllowedIds[] = { | |
31 kWebAppId | |
32 }; | |
33 | |
34 class Clearance { | |
Dmitry Polukhin
2011/05/18 06:50:47
Class name is strange to me. What about OriginVali
Denis Lagno
2011/05/18 11:53:32
Done.
| |
35 public: | |
36 Clearance() | |
37 : allowed_ids_(kAllowedIds, kAllowedIds + arraysize(kAllowedIds)) { | |
38 CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
39 DCHECK(command_line); | |
40 std::string allowed_list = | |
41 command_line->GetSwitchValueASCII(switches::kAllowWebSocketProxy); | |
42 if (!allowed_list.empty()) { | |
43 StringTokenizer t(allowed_list, ","); | |
44 while (t.GetNext()) { | |
45 // It must be either extension id or origin. | |
46 if (Extension::IdIsValid(t.token())) { | |
47 allowed_ids_.push_back(t.token()); | |
48 } else { | |
49 // It is not extension id, check if it is an origin. | |
50 GURL origin = GURL(t.token()).GetOrigin(); | |
51 if (!origin.is_valid()) { | |
52 LOG(ERROR) << "Invalid extension id or origin specified via " | |
53 << switches::kAllowWebSocketProxy << " switch"; | |
54 break; | |
55 } | |
56 allowed_origins_.push_back(origin.spec()); | |
57 if (origin.SchemeIs(chrome::kExtensionScheme)) | |
58 allowed_ids_.push_back(origin.host()); | |
59 } | |
60 } | |
61 } | |
62 for (size_t i = 0; i < allowed_ids_.size(); ++i) { | |
63 allowed_origins_.push_back(Extension::GetBaseURLFromExtensionId( | |
64 allowed_ids_[i]).GetOrigin().spec()); | |
65 } | |
66 std::sort(allowed_ids_.begin(), allowed_ids_.end()); | |
67 allowed_ids_.resize(std::unique( | |
68 allowed_ids_.begin(), allowed_ids_.end()) - allowed_ids_.begin()); | |
69 std::sort(allowed_origins_.begin(), allowed_origins_.end()); | |
70 allowed_origins_.resize(std::unique(allowed_origins_.begin(), | |
71 allowed_origins_.end()) - allowed_origins_.begin()); | |
72 } | |
73 | |
74 bool CheckCredentials( | |
75 const std::string& extension_id, | |
76 const std::string& hostname, | |
77 unsigned short port, | |
78 chromeos::WebSocketProxyController::ConnectionFlags flags) { | |
79 if (flags & chromeos::WebSocketProxyController::TLS_OVER_TCP) { | |
80 NOTIMPLEMENTED(); | |
81 return false; | |
82 } | |
83 return std::binary_search( | |
84 allowed_ids_.begin(), allowed_ids_.end(), extension_id); | |
85 } | |
86 | |
87 const std::vector<std::string>& allowed_origins() { return allowed_origins_; } | |
88 | |
89 private: | |
90 std::vector<std::string> allowed_ids_; | |
91 std::vector<std::string> allowed_origins_; | |
92 }; | |
93 | |
94 base::LazyInstance<Clearance> g_clearance(base::LINKER_INITIALIZED); | |
95 | |
20 class ProxyTask : public Task { | 96 class ProxyTask : public Task { |
21 virtual void Run() OVERRIDE; | 97 virtual void Run() OVERRIDE; |
22 }; | 98 }; |
23 | 99 |
24 struct ProxyLifetime { | 100 struct ProxyLifetime { |
25 ProxyLifetime() : delay_ms(1000), shutdown_requested(false) { | 101 ProxyLifetime() : delay_ms(1000), shutdown_requested(false) { |
26 BrowserThread::PostTask( | 102 BrowserThread::PostTask( |
27 BrowserThread::WEB_SOCKET_PROXY, FROM_HERE, new ProxyTask()); | 103 BrowserThread::WEB_SOCKET_PROXY, FROM_HERE, new ProxyTask()); |
28 } | 104 } |
29 | 105 |
30 // Delay between next attempt to run proxy. | 106 // Delay between next attempt to run proxy. |
31 int delay_ms; | 107 int delay_ms; |
32 | 108 |
33 chromeos::WebSocketProxy* volatile server; | 109 chromeos::WebSocketProxy* volatile server; |
34 | 110 |
35 volatile bool shutdown_requested; | 111 volatile bool shutdown_requested; |
36 | 112 |
37 base::Lock shutdown_lock; | 113 base::Lock lock; |
38 }; | 114 }; |
39 | 115 |
40 base::LazyInstance<ProxyLifetime> g_proxy_lifetime(base::LINKER_INITIALIZED); | 116 base::LazyInstance<ProxyLifetime> g_proxy_lifetime(base::LINKER_INITIALIZED); |
41 | 117 |
42 void ProxyTask::Run() { | 118 void ProxyTask::Run() { |
43 LOG(INFO) << "Attempt to run web socket proxy task"; | 119 LOG(INFO) << "Attempt to run web socket proxy task"; |
44 const int kPort = 10101; | 120 const int kPort = 10101; |
45 | 121 |
46 // Configure allowed origins. Empty vector allows any origin. | |
47 std::vector<std::string> allowed_origins; | |
48 allowed_origins.push_back( | |
49 "chrome-extension://haiffjcadagjlijoggckpgfnoeiflnem"); | |
50 | |
51 struct sockaddr_in sa; | 122 struct sockaddr_in sa; |
52 memset(&sa, 0, sizeof(sa)); | 123 memset(&sa, 0, sizeof(sa)); |
53 sa.sin_family = AF_INET; | 124 sa.sin_family = AF_INET; |
54 sa.sin_port = htons(kPort); | 125 sa.sin_port = htons(kPort); |
55 sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | 126 sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
56 | 127 |
57 chromeos::WebSocketProxy* server = new chromeos::WebSocketProxy( | 128 chromeos::WebSocketProxy* server = new chromeos::WebSocketProxy( |
58 allowed_origins, reinterpret_cast<sockaddr*>(&sa), sizeof(sa)); | 129 g_clearance.Get().allowed_origins(), |
130 reinterpret_cast<sockaddr*>(&sa), sizeof(sa)); | |
59 { | 131 { |
60 base::AutoLock alk(g_proxy_lifetime.Get().shutdown_lock); | 132 base::AutoLock alk(g_proxy_lifetime.Get().lock); |
61 if (g_proxy_lifetime.Get().shutdown_requested) | 133 if (g_proxy_lifetime.Get().shutdown_requested) |
62 return; | 134 return; |
63 delete g_proxy_lifetime.Get().server; | 135 delete g_proxy_lifetime.Get().server; |
64 g_proxy_lifetime.Get().server = server; | 136 g_proxy_lifetime.Get().server = server; |
65 } | 137 } |
66 server->Run(); | 138 server->Run(); |
67 { | 139 { |
68 base::AutoLock alk(g_proxy_lifetime.Get().shutdown_lock); | 140 base::AutoLock alk(g_proxy_lifetime.Get().lock); |
69 delete server; | 141 delete server; |
70 g_proxy_lifetime.Get().server = NULL; | 142 g_proxy_lifetime.Get().server = NULL; |
71 if (!g_proxy_lifetime.Get().shutdown_requested) { | 143 if (!g_proxy_lifetime.Get().shutdown_requested) { |
72 // Proxy terminated unexpectedly or failed to start (it can happen due to | 144 // Proxy terminated unexpectedly or failed to start (it can happen due to |
73 // a network problem). Keep trying. | 145 // a network problem). Keep trying. |
74 if (g_proxy_lifetime.Get().delay_ms < 100 * 1000) | 146 if (g_proxy_lifetime.Get().delay_ms < 100 * 1000) |
75 (g_proxy_lifetime.Get().delay_ms *= 3) /= 2; | 147 (g_proxy_lifetime.Get().delay_ms *= 3) /= 2; |
76 BrowserThread::PostDelayedTask( | 148 BrowserThread::PostDelayedTask( |
77 BrowserThread::WEB_SOCKET_PROXY, FROM_HERE, new ProxyTask(), | 149 BrowserThread::WEB_SOCKET_PROXY, FROM_HERE, new ProxyTask(), |
78 g_proxy_lifetime.Get().delay_ms); | 150 g_proxy_lifetime.Get().delay_ms); |
(...skipping 13 matching lines...) Expand all Loading... | |
92 | 164 |
93 // static | 165 // static |
94 bool WebSocketProxyController::IsInitiated() { | 166 bool WebSocketProxyController::IsInitiated() { |
95 return !(g_proxy_lifetime == NULL); | 167 return !(g_proxy_lifetime == NULL); |
96 } | 168 } |
97 | 169 |
98 // static | 170 // static |
99 void WebSocketProxyController::Shutdown() { | 171 void WebSocketProxyController::Shutdown() { |
100 if (IsInitiated()) { | 172 if (IsInitiated()) { |
101 LOG(INFO) << "WebSocketProxyController shutdown"; | 173 LOG(INFO) << "WebSocketProxyController shutdown"; |
102 base::AutoLock alk(g_proxy_lifetime.Get().shutdown_lock); | 174 base::AutoLock alk(g_proxy_lifetime.Get().lock); |
103 g_proxy_lifetime.Get().shutdown_requested = true; | 175 g_proxy_lifetime.Get().shutdown_requested = true; |
104 if (g_proxy_lifetime.Get().server) | 176 if (g_proxy_lifetime.Get().server) |
105 g_proxy_lifetime.Get().server->Shutdown(); | 177 g_proxy_lifetime.Get().server->Shutdown(); |
106 } | 178 } |
107 } | 179 } |
108 | 180 |
181 // static | |
182 bool WebSocketProxyController::CheckCredentials( | |
183 const std::string& extension_id, | |
184 const std::string& hostname, | |
185 unsigned short port, | |
186 ConnectionFlags flags) { | |
187 return g_clearance.Get().CheckCredentials( | |
188 extension_id, hostname, port, flags); | |
189 } | |
190 | |
109 } // namespace chromeos | 191 } // namespace chromeos |
110 | 192 |
OLD | NEW |