OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "net/test/embedded_test_server/embedded_test_server.h" | 5 #include "net/test/embedded_test_server/embedded_test_server.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 | 92 |
93 void HttpListenSocket::Listen() { | 93 void HttpListenSocket::Listen() { |
94 DCHECK(thread_checker_.CalledOnValidThread()); | 94 DCHECK(thread_checker_.CalledOnValidThread()); |
95 TCPListenSocket::Listen(); | 95 TCPListenSocket::Listen(); |
96 } | 96 } |
97 | 97 |
98 HttpListenSocket::~HttpListenSocket() { | 98 HttpListenSocket::~HttpListenSocket() { |
99 DCHECK(thread_checker_.CalledOnValidThread()); | 99 DCHECK(thread_checker_.CalledOnValidThread()); |
100 } | 100 } |
101 | 101 |
102 EmbeddedTestServer::EmbeddedTestServer( | 102 EmbeddedTestServer::EmbeddedTestServer() |
103 const scoped_refptr<base::SingleThreadTaskRunner>& io_thread) | 103 : io_thread_("EmbeddedTestServer io thread"), |
104 : io_thread_(io_thread), | |
105 port_(-1), | 104 port_(-1), |
106 weak_factory_(this) { | 105 weak_factory_(this) { |
107 DCHECK(io_thread_.get()); | |
108 DCHECK(thread_checker_.CalledOnValidThread()); | 106 DCHECK(thread_checker_.CalledOnValidThread()); |
| 107 |
| 108 base::Thread::Options thread_options; |
| 109 thread_options.message_loop_type = base::MessageLoop::TYPE_IO; |
| 110 CHECK(io_thread_.StartWithOptions(thread_options)); |
109 } | 111 } |
110 | 112 |
111 EmbeddedTestServer::~EmbeddedTestServer() { | 113 EmbeddedTestServer::~EmbeddedTestServer() { |
112 DCHECK(thread_checker_.CalledOnValidThread()); | 114 DCHECK(thread_checker_.CalledOnValidThread()); |
113 | 115 |
114 if (Started() && !ShutdownAndWaitUntilComplete()) { | 116 if (Started() && !ShutdownAndWaitUntilComplete()) { |
115 LOG(ERROR) << "EmbeddedTestServer failed to shut down."; | 117 LOG(ERROR) << "EmbeddedTestServer failed to shut down."; |
116 } | 118 } |
117 } | 119 } |
118 | 120 |
119 bool EmbeddedTestServer::InitializeAndWaitUntilReady() { | 121 bool EmbeddedTestServer::InitializeAndWaitUntilReady() { |
120 DCHECK(thread_checker_.CalledOnValidThread()); | 122 DCHECK(thread_checker_.CalledOnValidThread()); |
121 | 123 |
122 if (!PostTaskToIOThreadAndWait(base::Bind( | 124 if (!PostTaskToIOThreadAndWait(base::Bind( |
123 &EmbeddedTestServer::InitializeOnIOThread, base::Unretained(this)))) { | 125 &EmbeddedTestServer::InitializeOnIOThread, base::Unretained(this)))) { |
124 return false; | 126 return false; |
125 } | 127 } |
126 | 128 |
127 return Started() && base_url_.is_valid(); | 129 return Started() && base_url_.is_valid(); |
128 } | 130 } |
129 | 131 |
130 bool EmbeddedTestServer::ShutdownAndWaitUntilComplete() { | 132 bool EmbeddedTestServer::ShutdownAndWaitUntilComplete() { |
131 DCHECK(thread_checker_.CalledOnValidThread()); | 133 DCHECK(thread_checker_.CalledOnValidThread()); |
132 | 134 |
133 return PostTaskToIOThreadAndWait(base::Bind( | 135 return PostTaskToIOThreadAndWait(base::Bind( |
134 &EmbeddedTestServer::ShutdownOnIOThread, base::Unretained(this))); | 136 &EmbeddedTestServer::ShutdownOnIOThread, base::Unretained(this))); |
135 } | 137 } |
136 | 138 |
137 void EmbeddedTestServer::InitializeOnIOThread() { | 139 void EmbeddedTestServer::InitializeOnIOThread() { |
138 DCHECK(io_thread_->BelongsToCurrentThread()); | 140 DCHECK(io_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
139 DCHECK(!Started()); | 141 DCHECK(!Started()); |
140 | 142 |
141 SocketDescriptor socket_descriptor = | 143 SocketDescriptor socket_descriptor = |
142 TCPListenSocket::CreateAndBindAnyPort("127.0.0.1", &port_); | 144 TCPListenSocket::CreateAndBindAnyPort("127.0.0.1", &port_); |
143 if (socket_descriptor == kInvalidSocket) | 145 if (socket_descriptor == kInvalidSocket) |
144 return; | 146 return; |
145 | 147 |
146 listen_socket_.reset(new HttpListenSocket(socket_descriptor, this)); | 148 listen_socket_.reset(new HttpListenSocket(socket_descriptor, this)); |
147 listen_socket_->Listen(); | 149 listen_socket_->Listen(); |
148 | 150 |
149 IPEndPoint address; | 151 IPEndPoint address; |
150 int result = listen_socket_->GetLocalAddress(&address); | 152 int result = listen_socket_->GetLocalAddress(&address); |
151 if (result == OK) { | 153 if (result == OK) { |
152 base_url_ = GURL(std::string("http://") + address.ToString()); | 154 base_url_ = GURL(std::string("http://") + address.ToString()); |
153 } else { | 155 } else { |
154 LOG(ERROR) << "GetLocalAddress failed: " << ErrorToString(result); | 156 LOG(ERROR) << "GetLocalAddress failed: " << ErrorToString(result); |
155 } | 157 } |
156 } | 158 } |
157 | 159 |
158 void EmbeddedTestServer::ShutdownOnIOThread() { | 160 void EmbeddedTestServer::ShutdownOnIOThread() { |
159 DCHECK(io_thread_->BelongsToCurrentThread()); | 161 DCHECK(io_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
160 | 162 |
161 listen_socket_.reset(); | 163 listen_socket_.reset(); |
162 STLDeleteContainerPairSecondPointers(connections_.begin(), | 164 STLDeleteContainerPairSecondPointers(connections_.begin(), |
163 connections_.end()); | 165 connections_.end()); |
164 connections_.clear(); | 166 connections_.clear(); |
165 } | 167 } |
166 | 168 |
167 void EmbeddedTestServer::HandleRequest(HttpConnection* connection, | 169 void EmbeddedTestServer::HandleRequest(HttpConnection* connection, |
168 scoped_ptr<HttpRequest> request) { | 170 scoped_ptr<HttpRequest> request) { |
169 DCHECK(io_thread_->BelongsToCurrentThread()); | 171 DCHECK(io_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
170 | 172 |
171 bool request_handled = false; | 173 bool request_handled = false; |
172 | 174 |
173 for (size_t i = 0; i < request_handlers_.size(); ++i) { | 175 for (size_t i = 0; i < request_handlers_.size(); ++i) { |
174 scoped_ptr<HttpResponse> response = | 176 scoped_ptr<HttpResponse> response = |
175 request_handlers_[i].Run(*request.get()); | 177 request_handlers_[i].Run(*request.get()); |
176 if (response.get()) { | 178 if (response.get()) { |
177 connection->SendResponse(response.Pass()); | 179 connection->SendResponse(response.Pass()); |
178 request_handled = true; | 180 request_handled = true; |
179 break; | 181 break; |
(...skipping 28 matching lines...) Expand all Loading... |
208 } | 210 } |
209 | 211 |
210 void EmbeddedTestServer::RegisterRequestHandler( | 212 void EmbeddedTestServer::RegisterRequestHandler( |
211 const HandleRequestCallback& callback) { | 213 const HandleRequestCallback& callback) { |
212 request_handlers_.push_back(callback); | 214 request_handlers_.push_back(callback); |
213 } | 215 } |
214 | 216 |
215 void EmbeddedTestServer::DidAccept( | 217 void EmbeddedTestServer::DidAccept( |
216 StreamListenSocket* server, | 218 StreamListenSocket* server, |
217 scoped_ptr<StreamListenSocket> connection) { | 219 scoped_ptr<StreamListenSocket> connection) { |
218 DCHECK(io_thread_->BelongsToCurrentThread()); | 220 DCHECK(io_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
219 | 221 |
220 HttpConnection* http_connection = new HttpConnection( | 222 HttpConnection* http_connection = new HttpConnection( |
221 connection.Pass(), | 223 connection.Pass(), |
222 base::Bind(&EmbeddedTestServer::HandleRequest, | 224 base::Bind(&EmbeddedTestServer::HandleRequest, |
223 weak_factory_.GetWeakPtr())); | 225 weak_factory_.GetWeakPtr())); |
224 // TODO(szym): Make HttpConnection the StreamListenSocket delegate. | 226 // TODO(szym): Make HttpConnection the StreamListenSocket delegate. |
225 connections_[http_connection->socket_.get()] = http_connection; | 227 connections_[http_connection->socket_.get()] = http_connection; |
226 } | 228 } |
227 | 229 |
228 void EmbeddedTestServer::DidRead(StreamListenSocket* connection, | 230 void EmbeddedTestServer::DidRead(StreamListenSocket* connection, |
229 const char* data, | 231 const char* data, |
230 int length) { | 232 int length) { |
231 DCHECK(io_thread_->BelongsToCurrentThread()); | 233 DCHECK(io_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
232 | 234 |
233 HttpConnection* http_connection = FindConnection(connection); | 235 HttpConnection* http_connection = FindConnection(connection); |
234 if (http_connection == NULL) { | 236 if (http_connection == NULL) { |
235 LOG(WARNING) << "Unknown connection."; | 237 LOG(WARNING) << "Unknown connection."; |
236 return; | 238 return; |
237 } | 239 } |
238 http_connection->ReceiveData(std::string(data, length)); | 240 http_connection->ReceiveData(std::string(data, length)); |
239 } | 241 } |
240 | 242 |
241 void EmbeddedTestServer::DidClose(StreamListenSocket* connection) { | 243 void EmbeddedTestServer::DidClose(StreamListenSocket* connection) { |
242 DCHECK(io_thread_->BelongsToCurrentThread()); | 244 DCHECK(io_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
243 | 245 |
244 HttpConnection* http_connection = FindConnection(connection); | 246 HttpConnection* http_connection = FindConnection(connection); |
245 if (http_connection == NULL) { | 247 if (http_connection == NULL) { |
246 LOG(WARNING) << "Unknown connection."; | 248 LOG(WARNING) << "Unknown connection."; |
247 return; | 249 return; |
248 } | 250 } |
249 delete http_connection; | 251 delete http_connection; |
250 connections_.erase(connection); | 252 connections_.erase(connection); |
251 } | 253 } |
252 | 254 |
253 HttpConnection* EmbeddedTestServer::FindConnection( | 255 HttpConnection* EmbeddedTestServer::FindConnection( |
254 StreamListenSocket* socket) { | 256 StreamListenSocket* socket) { |
255 DCHECK(io_thread_->BelongsToCurrentThread()); | 257 DCHECK(io_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
256 | 258 |
257 std::map<StreamListenSocket*, HttpConnection*>::iterator it = | 259 std::map<StreamListenSocket*, HttpConnection*>::iterator it = |
258 connections_.find(socket); | 260 connections_.find(socket); |
259 if (it == connections_.end()) { | 261 if (it == connections_.end()) { |
260 return NULL; | 262 return NULL; |
261 } | 263 } |
262 return it->second; | 264 return it->second; |
263 } | 265 } |
264 | 266 |
265 bool EmbeddedTestServer::PostTaskToIOThreadAndWait( | 267 bool EmbeddedTestServer::PostTaskToIOThreadAndWait( |
266 const base::Closure& closure) { | 268 const base::Closure& closure) { |
267 // Note that PostTaskAndReply below requires base::MessageLoopProxy::current() | 269 // Note that PostTaskAndReply below requires base::MessageLoopProxy::current() |
268 // to return a loop for posting the reply task. However, in order to make | 270 // to return a loop for posting the reply task. However, in order to make |
269 // EmbeddedTestServer universally usable, it needs to cope with the situation | 271 // EmbeddedTestServer universally usable, it needs to cope with the situation |
270 // where it's running on a thread on which a message loop is not (yet) | 272 // where it's running on a thread on which a message loop is not (yet) |
271 // available or as has been destroyed already. | 273 // available or as has been destroyed already. |
272 // | 274 // |
273 // To handle this situation, create temporary message loop to support the | 275 // To handle this situation, create temporary message loop to support the |
274 // PostTaskAndReply operation if the current thread as no message loop. | 276 // PostTaskAndReply operation if the current thread as no message loop. |
275 scoped_ptr<base::MessageLoop> temporary_loop; | 277 scoped_ptr<base::MessageLoop> temporary_loop; |
276 if (!base::MessageLoop::current()) | 278 if (!base::MessageLoop::current()) |
277 temporary_loop.reset(new base::MessageLoop()); | 279 temporary_loop.reset(new base::MessageLoop()); |
278 | 280 |
279 base::RunLoop run_loop; | 281 base::RunLoop run_loop; |
280 if (!io_thread_->PostTaskAndReply(FROM_HERE, closure, run_loop.QuitClosure())) | 282 if (!io_thread_.message_loop_proxy()->PostTaskAndReply( |
| 283 FROM_HERE, closure, run_loop.QuitClosure())) { |
281 return false; | 284 return false; |
| 285 } |
282 run_loop.Run(); | 286 run_loop.Run(); |
283 | 287 |
284 return true; | 288 return true; |
285 } | 289 } |
286 | 290 |
287 } // namespace test_server | 291 } // namespace test_server |
288 } // namespace net | 292 } // namespace net |
OLD | NEW |