12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/test/embedded_test_server/embedded_test_server.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/files/file_path.h"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/message_loop/message_loop.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/path_service.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/process/process_metrics.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/run_loop.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/threading/thread_restrictions.h"
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/ip_endpoint.h"
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/net_errors.h"
20b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/test/embedded_test_server/http_connection.h"
21b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/test/embedded_test_server/http_request.h"
22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/test/embedded_test_server/http_response.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace net {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace test_server {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass CustomHttpResponse : public HttpResponse {
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CustomHttpResponse(const std::string& headers, const std::string& contents)
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : headers_(headers), contents_(contents) {
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual std::string ToResponseString() const OVERRIDE {
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return headers_ + "\r\n" + contents_;
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string headers_;
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string contents_;
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(CustomHttpResponse);
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Handles |request| by serving a file from under |server_root|.
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)scoped_ptr<HttpResponse> HandleFileRequest(
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& server_root,
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const HttpRequest& request) {
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // This is a test-only server. Ignore I/O thread restrictions.
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::ThreadRestrictions::ScopedAllowIO allow_io;
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Trim the first byte ('/').
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string request_path(request.relative_url.substr(1));
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Remove the query string if present.
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t query_pos = request_path.find('?');
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (query_pos != std::string::npos)
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    request_path = request_path.substr(0, query_pos);
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::FilePath file_path(server_root.AppendASCII(request_path));
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string file_contents;
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!base::ReadFileToString(file_path, &file_contents))
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return scoped_ptr<HttpResponse>();
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::FilePath headers_path(
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      file_path.AddExtension(FILE_PATH_LITERAL("mock-http-headers")));
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (base::PathExists(headers_path)) {
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string headers_contents;
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!base::ReadFileToString(headers_path, &headers_contents))
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return scoped_ptr<HttpResponse>();
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<CustomHttpResponse> http_response(
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        new CustomHttpResponse(headers_contents, file_contents));
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return http_response.PassAs<HttpResponse>();
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  http_response->set_code(HTTP_OK);
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  http_response->set_content(file_contents);
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return http_response.PassAs<HttpResponse>();
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HttpListenSocket::HttpListenSocket(const SocketDescriptor socket_descriptor,
88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                   StreamListenSocket::Delegate* delegate)
89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    : TCPListenSocket(socket_descriptor, delegate) {
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HttpListenSocket::Listen() {
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  TCPListenSocket::Listen();
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid HttpListenSocket::ListenOnIOThread() {
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(thread_checker_.CalledOnValidThread());
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if !defined(OS_POSIX)
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // This method may be called after the IO thread is changed, thus we need to
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // call |WatchSocket| again to make sure it listens on the current IO thread.
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Only needed for non POSIX platforms, since on POSIX platforms
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // StreamListenSocket::Listen already calls WatchSocket inside the function.
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WatchSocket(WAITING_ACCEPT);
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Listen();
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HttpListenSocket::~HttpListenSocket() {
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HttpListenSocket::DetachFromThread() {
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  thread_checker_.DetachFromThread();
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)EmbeddedTestServer::EmbeddedTestServer()
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : port_(-1),
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this) {
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
124b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)EmbeddedTestServer::~EmbeddedTestServer() {
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (Started() && !ShutdownAndWaitUntilComplete()) {
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "EmbeddedTestServer failed to shut down.";
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool EmbeddedTestServer::InitializeAndWaitUntilReady() {
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  StartThread();
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!PostTaskToIOThreadAndWait(base::Bind(
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          &EmbeddedTestServer::InitializeOnIOThread, base::Unretained(this)))) {
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return Started() && base_url_.is_valid();
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void EmbeddedTestServer::StopThread() {
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(io_thread_ && io_thread_->IsRunning());
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_LINUX)
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const int thread_count =
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::GetNumberOfThreads(base::GetCurrentProcessHandle());
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  io_thread_->Stop();
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  io_thread_.reset();
152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  thread_checker_.DetachFromThread();
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  listen_socket_->DetachFromThread();
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_LINUX)
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Busy loop to wait for thread count to decrease. This is needed because
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // pthread_join does not guarantee that kernel stat is updated when it
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // returns. Thus, GetNumberOfThreads does not immediately reflect the stopped
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // thread and hits the thread number DCHECK in render_sandbox_host_linux.cc
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // in browser_tests.
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  while (thread_count ==
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         base::GetNumberOfThreads(base::GetCurrentProcessHandle())) {
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::PlatformThread::YieldCurrentThread();
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void EmbeddedTestServer::RestartThreadAndListen() {
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  StartThread();
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CHECK(PostTaskToIOThreadAndWait(base::Bind(
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      &EmbeddedTestServer::ListenOnIOThread, base::Unretained(this))));
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool EmbeddedTestServer::ShutdownAndWaitUntilComplete() {
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return PostTaskToIOThreadAndWait(base::Bind(
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &EmbeddedTestServer::ShutdownOnIOThread, base::Unretained(this)));
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void EmbeddedTestServer::StartThread() {
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(!io_thread_.get());
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::Thread::Options thread_options;
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  io_thread_.reset(new base::Thread("EmbeddedTestServer io thread"));
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CHECK(io_thread_->StartWithOptions(thread_options));
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::InitializeOnIOThread() {
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!Started());
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SocketDescriptor socket_descriptor =
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      TCPListenSocket::CreateAndBindAnyPort("127.0.0.1", &port_);
195424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (socket_descriptor == kInvalidSocket)
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  listen_socket_.reset(new HttpListenSocket(socket_descriptor, this));
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  listen_socket_->Listen();
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  IPEndPoint address;
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int result = listen_socket_->GetLocalAddress(&address);
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (result == OK) {
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base_url_ = GURL(std::string("http://") + address.ToString());
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "GetLocalAddress failed: " << ErrorToString(result);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void EmbeddedTestServer::ListenOnIOThread() {
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(Started());
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  listen_socket_->ListenOnIOThread();
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::ShutdownOnIOThread() {
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  listen_socket_.reset();
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteContainerPairSecondPointers(connections_.begin(),
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       connections_.end());
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connections_.clear();
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
225b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::HandleRequest(HttpConnection* connection,
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               scoped_ptr<HttpRequest> request) {
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool request_handled = false;
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < request_handlers_.size(); ++i) {
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<HttpResponse> response =
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request_handlers_[i].Run(*request.get());
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (response.get()) {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      connection->SendResponse(response.Pass());
23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      request_handled = true;
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!request_handled) {
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(WARNING) << "Request not handled. Returning 404: "
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 << request->relative_url;
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_ptr<BasicHttpResponse> not_found_response(new BasicHttpResponse);
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    not_found_response->set_code(HTTP_NOT_FOUND);
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    connection->SendResponse(
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        not_found_response.PassAs<HttpResponse>());
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Drop the connection, since we do not support multiple requests per
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // connection.
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connections_.erase(connection->socket_.get());
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete connection;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)GURL EmbeddedTestServer::GetURL(const std::string& relative_url) const {
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(Started()) << "You must start the server first.";
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(StartsWithASCII(relative_url, "/", true /* case_sensitive */))
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << relative_url;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base_url_.Resolve(relative_url);
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EmbeddedTestServer::ServeFilesFromDirectory(
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& directory) {
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RegisterRequestHandler(base::Bind(&HandleFileRequest, directory));
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::RegisterRequestHandler(
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const HandleRequestCallback& callback) {
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_handlers_.push_back(callback);
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void EmbeddedTestServer::DidAccept(
27458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    StreamListenSocket* server,
27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_ptr<StreamListenSocket> connection) {
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpConnection* http_connection = new HttpConnection(
27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      connection.Pass(),
280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&EmbeddedTestServer::HandleRequest,
281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 weak_factory_.GetWeakPtr()));
28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // TODO(szym): Make HttpConnection the StreamListenSocket delegate.
28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  connections_[http_connection->socket_.get()] = http_connection;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::DidRead(StreamListenSocket* connection,
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const char* data,
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         int length) {
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpConnection* http_connection = FindConnection(connection);
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (http_connection == NULL) {
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Unknown connection.";
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  http_connection->ReceiveData(std::string(data, length));
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::DidClose(StreamListenSocket* connection) {
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpConnection* http_connection = FindConnection(connection);
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (http_connection == NULL) {
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Unknown connection.";
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete http_connection;
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connections_.erase(connection);
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)HttpConnection* EmbeddedTestServer::FindConnection(
312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    StreamListenSocket* socket) {
313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
315b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  std::map<StreamListenSocket*, HttpConnection*>::iterator it =
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      connections_.find(socket);
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it == connections_.end()) {
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return it->second;
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool EmbeddedTestServer::PostTaskToIOThreadAndWait(
32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const base::Closure& closure) {
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Note that PostTaskAndReply below requires base::MessageLoopProxy::current()
32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // to return a loop for posting the reply task. However, in order to make
32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // EmbeddedTestServer universally usable, it needs to cope with the situation
32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // where it's running on a thread on which a message loop is not (yet)
32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // available or as has been destroyed already.
33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // To handle this situation, create temporary message loop to support the
33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // PostTaskAndReply operation if the current thread as no message loop.
33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<base::MessageLoop> temporary_loop;
33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!base::MessageLoop::current())
33558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    temporary_loop.reset(new base::MessageLoop());
33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::RunLoop run_loop;
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!io_thread_->message_loop_proxy()->PostTaskAndReply(
3391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          FROM_HERE, closure, run_loop.QuitClosure())) {
34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return false;
3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  run_loop.Run();
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return true;
34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace test_server
348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}  // namespace net
349