1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/test/chromedriver/net/test_http_server.h" 6 7 #include "base/bind.h" 8 #include "base/location.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop_proxy.h" 11 #include "base/strings/stringprintf.h" 12 #include "base/time/time.h" 13 #include "net/base/ip_endpoint.h" 14 #include "net/base/net_errors.h" 15 #include "net/server/http_server_request_info.h" 16 #include "net/socket/tcp_server_socket.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 const int kBufferSize = 100 * 1024 * 1024; // 100 MB 20 21 TestHttpServer::TestHttpServer() 22 : thread_("ServerThread"), 23 all_closed_event_(false, true), 24 request_action_(kAccept), 25 message_action_(kEchoMessage) { 26 } 27 28 TestHttpServer::~TestHttpServer() { 29 } 30 31 bool TestHttpServer::Start() { 32 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0); 33 bool thread_started = thread_.StartWithOptions(options); 34 EXPECT_TRUE(thread_started); 35 if (!thread_started) 36 return false; 37 bool success; 38 base::WaitableEvent event(false, false); 39 thread_.message_loop_proxy()->PostTask( 40 FROM_HERE, 41 base::Bind(&TestHttpServer::StartOnServerThread, 42 base::Unretained(this), &success, &event)); 43 event.Wait(); 44 return success; 45 } 46 47 void TestHttpServer::Stop() { 48 if (!thread_.IsRunning()) 49 return; 50 base::WaitableEvent event(false, false); 51 thread_.message_loop_proxy()->PostTask( 52 FROM_HERE, 53 base::Bind(&TestHttpServer::StopOnServerThread, 54 base::Unretained(this), &event)); 55 event.Wait(); 56 thread_.Stop(); 57 } 58 59 bool TestHttpServer::WaitForConnectionsToClose() { 60 return all_closed_event_.TimedWait(base::TimeDelta::FromSeconds(10)); 61 } 62 63 void TestHttpServer::SetRequestAction(WebSocketRequestAction action) { 64 base::AutoLock lock(action_lock_); 65 request_action_ = action; 66 } 67 68 void TestHttpServer::SetMessageAction(WebSocketMessageAction action) { 69 base::AutoLock lock(action_lock_); 70 message_action_ = action; 71 } 72 73 GURL TestHttpServer::web_socket_url() const { 74 base::AutoLock lock(url_lock_); 75 return web_socket_url_; 76 } 77 78 void TestHttpServer::OnConnect(int connection_id) { 79 server_->SetSendBufferSize(connection_id, kBufferSize); 80 server_->SetReceiveBufferSize(connection_id, kBufferSize); 81 } 82 83 void TestHttpServer::OnWebSocketRequest( 84 int connection_id, 85 const net::HttpServerRequestInfo& info) { 86 WebSocketRequestAction action; 87 { 88 base::AutoLock lock(action_lock_); 89 action = request_action_; 90 } 91 connections_.insert(connection_id); 92 all_closed_event_.Reset(); 93 94 switch (action) { 95 case kAccept: 96 server_->AcceptWebSocket(connection_id, info); 97 break; 98 case kNotFound: 99 server_->Send404(connection_id); 100 break; 101 case kClose: 102 server_->Close(connection_id); 103 break; 104 } 105 } 106 107 void TestHttpServer::OnWebSocketMessage(int connection_id, 108 const std::string& data) { 109 WebSocketMessageAction action; 110 { 111 base::AutoLock lock(action_lock_); 112 action = message_action_; 113 } 114 switch (action) { 115 case kEchoMessage: 116 server_->SendOverWebSocket(connection_id, data); 117 break; 118 case kCloseOnMessage: 119 server_->Close(connection_id); 120 break; 121 } 122 } 123 124 void TestHttpServer::OnClose(int connection_id) { 125 connections_.erase(connection_id); 126 if (connections_.empty()) 127 all_closed_event_.Signal(); 128 } 129 130 void TestHttpServer::StartOnServerThread(bool* success, 131 base::WaitableEvent* event) { 132 scoped_ptr<net::ServerSocket> server_socket( 133 new net::TCPServerSocket(NULL, net::NetLog::Source())); 134 server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1); 135 server_.reset(new net::HttpServer(server_socket.Pass(), this)); 136 137 net::IPEndPoint address; 138 int error = server_->GetLocalAddress(&address); 139 EXPECT_EQ(net::OK, error); 140 if (error == net::OK) { 141 base::AutoLock lock(url_lock_); 142 web_socket_url_ = GURL(base::StringPrintf("ws://127.0.0.1:%d", 143 address.port())); 144 } else { 145 server_.reset(NULL); 146 } 147 *success = server_.get(); 148 event->Signal(); 149 } 150 151 void TestHttpServer::StopOnServerThread(base::WaitableEvent* event) { 152 server_.reset(NULL); 153 event->Signal(); 154 } 155