root/chrome/test/chromedriver/net/test_http_server.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. message_action_
  2. Start
  3. Stop
  4. WaitForConnectionsToClose
  5. SetRequestAction
  6. SetMessageAction
  7. web_socket_url
  8. OnWebSocketRequest
  9. OnWebSocketMessage
  10. OnClose
  11. StartOnServerThread
  12. StopOnServerThread

// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/chromedriver/net/test_http_server.h"

#include "base/bind.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/server/http_server_request_info.h"
#include "net/socket/tcp_listen_socket.h"
#include "testing/gtest/include/gtest/gtest.h"

TestHttpServer::TestHttpServer()
    : thread_("ServerThread"),
      all_closed_event_(false, true),
      request_action_(kAccept),
      message_action_(kEchoMessage) {
}

TestHttpServer::~TestHttpServer() {
}

bool TestHttpServer::Start() {
  base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
  bool thread_started = thread_.StartWithOptions(options);
  EXPECT_TRUE(thread_started);
  if (!thread_started)
    return false;
  bool success;
  base::WaitableEvent event(false, false);
  thread_.message_loop_proxy()->PostTask(
      FROM_HERE,
      base::Bind(&TestHttpServer::StartOnServerThread,
                 base::Unretained(this), &success, &event));
  event.Wait();
  return success;
}

void TestHttpServer::Stop() {
  if (!thread_.IsRunning())
    return;
  base::WaitableEvent event(false, false);
  thread_.message_loop_proxy()->PostTask(
      FROM_HERE,
      base::Bind(&TestHttpServer::StopOnServerThread,
                 base::Unretained(this), &event));
  event.Wait();
  thread_.Stop();
}

bool TestHttpServer::WaitForConnectionsToClose() {
  return all_closed_event_.TimedWait(base::TimeDelta::FromSeconds(10));
}

void TestHttpServer::SetRequestAction(WebSocketRequestAction action) {
  base::AutoLock lock(action_lock_);
  request_action_ = action;
}

void TestHttpServer::SetMessageAction(WebSocketMessageAction action) {
  base::AutoLock lock(action_lock_);
  message_action_ = action;
}

GURL TestHttpServer::web_socket_url() const {
  base::AutoLock lock(url_lock_);
  return web_socket_url_;
}

void TestHttpServer::OnWebSocketRequest(
    int connection_id,
    const net::HttpServerRequestInfo& info) {
  WebSocketRequestAction action;
  {
    base::AutoLock lock(action_lock_);
    action = request_action_;
  }
  connections_.insert(connection_id);
  all_closed_event_.Reset();

  switch (action) {
    case kAccept:
      server_->AcceptWebSocket(connection_id, info);
      break;
    case kNotFound:
      server_->Send404(connection_id);
      break;
    case kClose:
      // net::HttpServer doesn't allow us to close connection during callback.
      base::MessageLoop::current()->PostTask(
          FROM_HERE,
          base::Bind(&net::HttpServer::Close, server_, connection_id));
      break;
  }
}

void TestHttpServer::OnWebSocketMessage(int connection_id,
                                        const std::string& data) {
  WebSocketMessageAction action;
  {
    base::AutoLock lock(action_lock_);
    action = message_action_;
  }
  switch (action) {
    case kEchoMessage:
      server_->SendOverWebSocket(connection_id, data);
      break;
    case kCloseOnMessage:
      // net::HttpServer doesn't allow us to close connection during callback.
      base::MessageLoop::current()->PostTask(
          FROM_HERE,
          base::Bind(&net::HttpServer::Close, server_, connection_id));
      break;
  }
}

void TestHttpServer::OnClose(int connection_id) {
  connections_.erase(connection_id);
  if (connections_.empty())
    all_closed_event_.Signal();
}

void TestHttpServer::StartOnServerThread(bool* success,
                                         base::WaitableEvent* event) {
  net::TCPListenSocketFactory factory("127.0.0.1", 0);
  server_ = new net::HttpServer(factory, this);

  net::IPEndPoint address;
  int error = server_->GetLocalAddress(&address);
  EXPECT_EQ(net::OK, error);
  if (error == net::OK) {
    base::AutoLock lock(url_lock_);
    web_socket_url_ = GURL(base::StringPrintf("ws://127.0.0.1:%d",
                                              address.port()));
  } else {
    server_ = NULL;
  }
  *success = server_.get();
  event->Signal();
}

void TestHttpServer::StopOnServerThread(base::WaitableEvent* event) {
  if (server_.get())
    server_ = NULL;
  event->Signal();
}

/* [<][>][^][v][top][bottom][index][help] */