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 OriginValidator { |
| 35 public: |
| 36 OriginValidator() |
| 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<OriginValidator> g_validator(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_validator.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_validator.Get().CheckCredentials( |
| 188 extension_id, hostname, port, flags); |
| 189 } |
| 190 |
109 } // namespace chromeos | 191 } // namespace chromeos |
110 | 192 |
OLD | NEW |