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/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 | 186 |
187 void EmbeddedTestServer::StartThread() { | 187 void EmbeddedTestServer::StartThread() { |
188 DCHECK(!io_thread_.get()); | 188 DCHECK(!io_thread_.get()); |
189 base::Thread::Options thread_options; | 189 base::Thread::Options thread_options; |
190 thread_options.message_loop_type = base::MessageLoop::TYPE_IO; | 190 thread_options.message_loop_type = base::MessageLoop::TYPE_IO; |
191 io_thread_.reset(new base::Thread("EmbeddedTestServer io thread")); | 191 io_thread_.reset(new base::Thread("EmbeddedTestServer io thread")); |
192 CHECK(io_thread_->StartWithOptions(thread_options)); | 192 CHECK(io_thread_->StartWithOptions(thread_options)); |
193 } | 193 } |
194 | 194 |
195 void EmbeddedTestServer::InitializeOnIOThread() { | 195 void EmbeddedTestServer::InitializeOnIOThread() { |
196 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 196 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); |
197 DCHECK(!Started()); | 197 DCHECK(!Started()); |
198 | 198 |
199 SocketDescriptor socket_descriptor = | 199 SocketDescriptor socket_descriptor = |
200 TCPListenSocket::CreateAndBindAnyPort("127.0.0.1", &port_); | 200 TCPListenSocket::CreateAndBindAnyPort("127.0.0.1", &port_); |
201 if (socket_descriptor == kInvalidSocket) | 201 if (socket_descriptor == kInvalidSocket) |
202 return; | 202 return; |
203 | 203 |
204 listen_socket_.reset(new HttpListenSocket(socket_descriptor, this)); | 204 listen_socket_.reset(new HttpListenSocket(socket_descriptor, this)); |
205 listen_socket_->Listen(); | 205 listen_socket_->Listen(); |
206 | 206 |
207 IPEndPoint address; | 207 IPEndPoint address; |
208 int result = listen_socket_->GetLocalAddress(&address); | 208 int result = listen_socket_->GetLocalAddress(&address); |
209 if (result == OK) { | 209 if (result == OK) { |
210 base_url_ = GURL(std::string("http://") + address.ToString()); | 210 base_url_ = GURL(std::string("http://") + address.ToString()); |
211 } else { | 211 } else { |
212 LOG(ERROR) << "GetLocalAddress failed: " << ErrorToString(result); | 212 LOG(ERROR) << "GetLocalAddress failed: " << ErrorToString(result); |
213 } | 213 } |
214 } | 214 } |
215 | 215 |
216 void EmbeddedTestServer::ListenOnIOThread() { | 216 void EmbeddedTestServer::ListenOnIOThread() { |
217 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 217 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); |
218 DCHECK(Started()); | 218 DCHECK(Started()); |
219 listen_socket_->ListenOnIOThread(); | 219 listen_socket_->ListenOnIOThread(); |
220 } | 220 } |
221 | 221 |
222 void EmbeddedTestServer::ShutdownOnIOThread() { | 222 void EmbeddedTestServer::ShutdownOnIOThread() { |
223 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 223 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); |
224 | 224 |
225 listen_socket_.reset(); | 225 listen_socket_.reset(); |
226 STLDeleteContainerPairSecondPointers(connections_.begin(), | 226 STLDeleteContainerPairSecondPointers(connections_.begin(), |
227 connections_.end()); | 227 connections_.end()); |
228 connections_.clear(); | 228 connections_.clear(); |
229 } | 229 } |
230 | 230 |
231 void EmbeddedTestServer::HandleRequest(HttpConnection* connection, | 231 void EmbeddedTestServer::HandleRequest(HttpConnection* connection, |
232 scoped_ptr<HttpRequest> request) { | 232 scoped_ptr<HttpRequest> request) { |
233 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 233 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); |
234 | 234 |
235 bool request_handled = false; | 235 bool request_handled = false; |
236 | 236 |
237 for (size_t i = 0; i < request_handlers_.size(); ++i) { | 237 for (size_t i = 0; i < request_handlers_.size(); ++i) { |
238 scoped_ptr<HttpResponse> response = | 238 scoped_ptr<HttpResponse> response = |
239 request_handlers_[i].Run(*request.get()); | 239 request_handlers_[i].Run(*request.get()); |
240 if (response.get()) { | 240 if (response.get()) { |
241 connection->SendResponse(response.Pass()); | 241 connection->SendResponse(response.Pass()); |
242 request_handled = true; | 242 request_handled = true; |
243 break; | 243 break; |
244 } | 244 } |
245 } | 245 } |
246 | 246 |
247 if (!request_handled) { | 247 if (!request_handled) { |
248 LOG(WARNING) << "Request not handled. Returning 404: " | 248 LOG(WARNING) << "Request not handled. Returning 404: " |
249 << request->relative_url; | 249 << request->relative_url; |
250 scoped_ptr<BasicHttpResponse> not_found_response(new BasicHttpResponse); | 250 scoped_ptr<BasicHttpResponse> not_found_response(new BasicHttpResponse); |
251 not_found_response->set_code(HTTP_NOT_FOUND); | 251 not_found_response->set_code(HTTP_NOT_FOUND); |
252 connection->SendResponse(not_found_response.Pass()); | 252 connection->SendResponse(not_found_response.Pass()); |
253 } | 253 } |
254 | 254 |
255 // Drop the connection, since we do not support multiple requests per | 255 // Drop the connection, since we do not support multiple requests per |
256 // connection. | 256 // connection. |
257 connections_.erase(connection->socket_.get()); | 257 connections_.erase(connection->socket_.get()); |
258 delete connection; | 258 delete connection; |
259 } | 259 } |
260 | 260 |
261 GURL EmbeddedTestServer::GetURL(const std::string& relative_url) const { | 261 GURL EmbeddedTestServer::GetURL(const std::string& relative_url) const { |
262 DCHECK(Started()) << "You must start the server first."; | 262 DCHECK(Started()) << "You must start the server first."; |
263 DCHECK(StartsWithASCII(relative_url, "/", true /* case_sensitive */)) | 263 DCHECK(base::StartsWith(relative_url, "/", base::CompareCase::SENSITIVE)) |
264 << relative_url; | 264 << relative_url; |
265 return base_url_.Resolve(relative_url); | 265 return base_url_.Resolve(relative_url); |
266 } | 266 } |
267 | 267 |
268 GURL EmbeddedTestServer::GetURL( | 268 GURL EmbeddedTestServer::GetURL( |
269 const std::string& hostname, | 269 const std::string& hostname, |
270 const std::string& relative_url) const { | 270 const std::string& relative_url) const { |
271 GURL local_url = GetURL(relative_url); | 271 GURL local_url = GetURL(relative_url); |
272 GURL::Replacements replace_host; | 272 GURL::Replacements replace_host; |
273 replace_host.SetHostStr(hostname); | 273 replace_host.SetHostStr(hostname); |
274 return local_url.ReplaceComponents(replace_host); | 274 return local_url.ReplaceComponents(replace_host); |
275 } | 275 } |
276 | 276 |
277 void EmbeddedTestServer::ServeFilesFromDirectory( | 277 void EmbeddedTestServer::ServeFilesFromDirectory( |
278 const base::FilePath& directory) { | 278 const base::FilePath& directory) { |
279 RegisterRequestHandler(base::Bind(&HandleFileRequest, directory)); | 279 RegisterRequestHandler(base::Bind(&HandleFileRequest, directory)); |
280 } | 280 } |
281 | 281 |
282 void EmbeddedTestServer::RegisterRequestHandler( | 282 void EmbeddedTestServer::RegisterRequestHandler( |
283 const HandleRequestCallback& callback) { | 283 const HandleRequestCallback& callback) { |
284 request_handlers_.push_back(callback); | 284 request_handlers_.push_back(callback); |
285 } | 285 } |
286 | 286 |
287 void EmbeddedTestServer::DidAccept( | 287 void EmbeddedTestServer::DidAccept( |
288 StreamListenSocket* server, | 288 StreamListenSocket* server, |
289 scoped_ptr<StreamListenSocket> connection) { | 289 scoped_ptr<StreamListenSocket> connection) { |
290 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 290 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); |
291 | 291 |
292 HttpConnection* http_connection = new HttpConnection( | 292 HttpConnection* http_connection = new HttpConnection( |
293 connection.Pass(), | 293 connection.Pass(), |
294 base::Bind(&EmbeddedTestServer::HandleRequest, | 294 base::Bind(&EmbeddedTestServer::HandleRequest, |
295 weak_factory_.GetWeakPtr())); | 295 weak_factory_.GetWeakPtr())); |
296 // TODO(szym): Make HttpConnection the StreamListenSocket delegate. | 296 // TODO(szym): Make HttpConnection the StreamListenSocket delegate. |
297 connections_[http_connection->socket_.get()] = http_connection; | 297 connections_[http_connection->socket_.get()] = http_connection; |
298 } | 298 } |
299 | 299 |
300 void EmbeddedTestServer::DidRead(StreamListenSocket* connection, | 300 void EmbeddedTestServer::DidRead(StreamListenSocket* connection, |
301 const char* data, | 301 const char* data, |
302 int length) { | 302 int length) { |
303 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 303 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); |
304 | 304 |
305 HttpConnection* http_connection = FindConnection(connection); | 305 HttpConnection* http_connection = FindConnection(connection); |
306 if (http_connection == NULL) { | 306 if (http_connection == NULL) { |
307 LOG(WARNING) << "Unknown connection."; | 307 LOG(WARNING) << "Unknown connection."; |
308 return; | 308 return; |
309 } | 309 } |
310 http_connection->ReceiveData(std::string(data, length)); | 310 http_connection->ReceiveData(std::string(data, length)); |
311 } | 311 } |
312 | 312 |
313 void EmbeddedTestServer::DidClose(StreamListenSocket* connection) { | 313 void EmbeddedTestServer::DidClose(StreamListenSocket* connection) { |
314 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 314 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); |
315 | 315 |
316 HttpConnection* http_connection = FindConnection(connection); | 316 HttpConnection* http_connection = FindConnection(connection); |
317 if (http_connection == NULL) { | 317 if (http_connection == NULL) { |
318 LOG(WARNING) << "Unknown connection."; | 318 LOG(WARNING) << "Unknown connection."; |
319 return; | 319 return; |
320 } | 320 } |
321 delete http_connection; | 321 delete http_connection; |
322 connections_.erase(connection); | 322 connections_.erase(connection); |
323 } | 323 } |
324 | 324 |
325 HttpConnection* EmbeddedTestServer::FindConnection( | 325 HttpConnection* EmbeddedTestServer::FindConnection( |
326 StreamListenSocket* socket) { | 326 StreamListenSocket* socket) { |
327 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 327 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); |
328 | 328 |
329 std::map<StreamListenSocket*, HttpConnection*>::iterator it = | 329 std::map<StreamListenSocket*, HttpConnection*>::iterator it = |
330 connections_.find(socket); | 330 connections_.find(socket); |
331 if (it == connections_.end()) { | 331 if (it == connections_.end()) { |
332 return NULL; | 332 return NULL; |
333 } | 333 } |
334 return it->second; | 334 return it->second; |
335 } | 335 } |
336 | 336 |
337 bool EmbeddedTestServer::PostTaskToIOThreadAndWait( | 337 bool EmbeddedTestServer::PostTaskToIOThreadAndWait( |
338 const base::Closure& closure) { | 338 const base::Closure& closure) { |
339 // Note that PostTaskAndReply below requires base::MessageLoopProxy::current() | 339 // Note that PostTaskAndReply below requires base::MessageLoop::current() |
340 // to return a loop for posting the reply task. However, in order to make | 340 // to return a loop for posting the reply task. However, in order to make |
341 // EmbeddedTestServer universally usable, it needs to cope with the situation | 341 // EmbeddedTestServer universally usable, it needs to cope with the situation |
342 // where it's running on a thread on which a message loop is not (yet) | 342 // where it's running on a thread on which a message loop is not (yet) |
343 // available or as has been destroyed already. | 343 // available or as has been destroyed already. |
344 // | 344 // |
345 // To handle this situation, create temporary message loop to support the | 345 // To handle this situation, create temporary message loop to support the |
346 // PostTaskAndReply operation if the current thread as no message loop. | 346 // PostTaskAndReply operation if the current thread as no message loop. |
347 scoped_ptr<base::MessageLoop> temporary_loop; | 347 scoped_ptr<base::MessageLoop> temporary_loop; |
348 if (!base::MessageLoop::current()) | 348 if (!base::MessageLoop::current()) |
349 temporary_loop.reset(new base::MessageLoop()); | 349 temporary_loop.reset(new base::MessageLoop()); |
350 | 350 |
351 base::RunLoop run_loop; | 351 base::RunLoop run_loop; |
352 if (!io_thread_->message_loop_proxy()->PostTaskAndReply( | 352 if (!io_thread_->task_runner()->PostTaskAndReply(FROM_HERE, closure, |
353 FROM_HERE, closure, run_loop.QuitClosure())) { | 353 run_loop.QuitClosure())) { |
354 return false; | 354 return false; |
355 } | 355 } |
356 run_loop.Run(); | 356 run_loop.Run(); |
357 | 357 |
358 return true; | 358 return true; |
359 } | 359 } |
360 | 360 |
361 } // namespace test_server | 361 } // namespace test_server |
362 } // namespace net | 362 } // namespace net |
OLD | NEW |