| 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 "chrome/browser/google_apis/test_server/http_server.h" | 5 #include "chrome/browser/google_apis/test_server/http_server.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| 11 #include "base/synchronization/waitable_event.h" |
| 11 #include "chrome/browser/google_apis/test_server/http_connection.h" | 12 #include "chrome/browser/google_apis/test_server/http_connection.h" |
| 12 #include "chrome/browser/google_apis/test_server/http_request.h" | 13 #include "chrome/browser/google_apis/test_server/http_request.h" |
| 13 #include "chrome/browser/google_apis/test_server/http_response.h" | 14 #include "chrome/browser/google_apis/test_server/http_response.h" |
| 14 #include "content/public/browser/browser_thread.h" | |
| 15 #include "content/public/test/test_utils.h" | |
| 16 #include "net/tools/fetch/http_listen_socket.h" | 15 #include "net/tools/fetch/http_listen_socket.h" |
| 17 | 16 |
| 18 namespace google_apis { | 17 namespace google_apis { |
| 19 namespace test_server { | 18 namespace test_server { |
| 20 | 19 |
| 21 using content::BrowserThread; | |
| 22 | |
| 23 namespace { | 20 namespace { |
| 24 | 21 |
| 25 const int kPort = 8040; | 22 const int kPort = 8040; |
| 26 const char kIp[] = "127.0.0.1"; | 23 const char kIp[] = "127.0.0.1"; |
| 27 const int kRetries = 10; | 24 const int kRetries = 10; |
| 28 | 25 |
| 29 // Callback to handle requests with default predefined response for requests | 26 // Callback to handle requests with default predefined response for requests |
| 30 // matching the address |url|. | 27 // matching the address |url|. |
| 31 scoped_ptr<HttpResponse> HandleDefaultRequest(const GURL& url, | 28 scoped_ptr<HttpResponse> HandleDefaultRequest(const GURL& url, |
| 32 const HttpResponse& response, | 29 const HttpResponse& response, |
| 33 const HttpRequest& request) { | 30 const HttpRequest& request) { |
| 34 const GURL request_url = url.Resolve(request.relative_url); | 31 const GURL request_url = url.Resolve(request.relative_url); |
| 35 if (url.path() != request_url.path()) | 32 if (url.path() != request_url.path()) |
| 36 return scoped_ptr<HttpResponse>(NULL); | 33 return scoped_ptr<HttpResponse>(NULL); |
| 37 return scoped_ptr<HttpResponse>(new HttpResponse(response)); | 34 return scoped_ptr<HttpResponse>(new HttpResponse(response)); |
| 38 } | 35 } |
| 39 | 36 |
| 40 } // namespace | 37 } // namespace |
| 41 | 38 |
| 42 HttpListenSocket::HttpListenSocket(const SocketDescriptor socket_descriptor, | 39 HttpListenSocket::HttpListenSocket(const SocketDescriptor socket_descriptor, |
| 43 net::StreamListenSocket::Delegate* delegate) | 40 net::StreamListenSocket::Delegate* delegate) |
| 44 : net::TCPListenSocket(socket_descriptor, delegate) { | 41 : net::TCPListenSocket(socket_descriptor, delegate) { |
| 45 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 46 } | 42 } |
| 47 | 43 |
| 48 void HttpListenSocket::Listen() { | 44 void HttpListenSocket::Listen() { |
| 49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 45 DCHECK(CalledOnValidThread()); |
| 50 net::TCPListenSocket::Listen(); | 46 net::TCPListenSocket::Listen(); |
| 51 } | 47 } |
| 52 | 48 |
| 53 HttpListenSocket::~HttpListenSocket() { | 49 HttpListenSocket::~HttpListenSocket() { |
| 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 55 } | 50 } |
| 56 | 51 |
| 57 HttpServer::HttpServer() | 52 HttpServer::HttpServer( |
| 58 : port_(-1), | 53 const scoped_refptr<base::SingleThreadTaskRunner>& io_thread) |
| 54 : io_thread_(io_thread), |
| 55 port_(-1), |
| 59 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 56 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 57 DCHECK(io_thread_); |
| 61 } | 58 } |
| 62 | 59 |
| 63 HttpServer::~HttpServer() { | 60 HttpServer::~HttpServer() { |
| 64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 65 } | 61 } |
| 66 | 62 |
| 67 bool HttpServer::InitializeAndWaitUntilReady() { | 63 bool HttpServer::InitializeAndWaitUntilReady() { |
| 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 64 DCHECK(CalledOnValidThread()); |
| 69 | 65 |
| 70 BrowserThread::PostTask( | 66 base::WaitableEvent event(false, false); |
| 71 BrowserThread::IO, | 67 if (!io_thread_->PostTask(FROM_HERE, |
| 72 FROM_HERE, | 68 base::Bind(&HttpServer::InitializeOnIOThread, |
| 73 base::Bind(&HttpServer::InitializeOnIOThread, | 69 base::Unretained(this), &event))) { |
| 74 base::Unretained(this))); | 70 return false; |
| 71 } |
| 75 | 72 |
| 76 // Wait for the task completion. | 73 event.Wait(); |
| 77 content::RunAllPendingInMessageLoop(BrowserThread::IO); | |
| 78 | 74 |
| 79 return Started(); | 75 return Started(); |
| 80 } | 76 } |
| 81 | 77 |
| 82 void HttpServer::ShutdownAndWaitUntilComplete() { | 78 bool HttpServer::ShutdownAndWaitUntilComplete() { |
| 83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 79 DCHECK(CalledOnValidThread()); |
| 84 | 80 |
| 85 BrowserThread::PostTask( | 81 base::WaitableEvent event(false, false); |
| 86 BrowserThread::IO, | 82 if (!io_thread_->PostTask(FROM_HERE, |
| 87 FROM_HERE, | 83 base::Bind(&HttpServer::ShutdownOnIOThread, |
| 88 base::Bind(&HttpServer::ShutdownOnIOThread, | 84 base::Unretained(this), &event))) { |
| 89 base::Unretained(this))); | 85 return false; |
| 86 } |
| 90 | 87 |
| 91 // Wait for the task completion. | 88 event.Wait(); |
| 92 content::RunAllPendingInMessageLoop(BrowserThread::IO); | 89 |
| 90 return true; |
| 93 } | 91 } |
| 94 | 92 |
| 95 void HttpServer::InitializeOnIOThread() { | 93 void HttpServer::InitializeOnIOThread(base::WaitableEvent* event) { |
| 96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 94 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 97 DCHECK(!Started()); | 95 DCHECK(!Started()); |
| 98 | 96 |
| 99 int retries_left = kRetries + 1; | 97 int retries_left = kRetries + 1; |
| 100 int try_port = kPort; | 98 int try_port = kPort; |
| 101 | 99 |
| 102 while (retries_left > 0) { | 100 while (retries_left > 0) { |
| 103 SocketDescriptor socket_descriptor = net::TCPListenSocket::CreateAndBind( | 101 SocketDescriptor socket_descriptor = net::TCPListenSocket::CreateAndBind( |
| 104 kIp, | 102 kIp, |
| 105 try_port); | 103 try_port); |
| 106 if (socket_descriptor != net::TCPListenSocket::kInvalidSocket) { | 104 if (socket_descriptor != net::TCPListenSocket::kInvalidSocket) { |
| 107 listen_socket_ = new HttpListenSocket(socket_descriptor, this); | 105 listen_socket_ = new HttpListenSocket(socket_descriptor, this); |
| 108 listen_socket_->Listen(); | 106 listen_socket_->Listen(); |
| 109 base_url_ = GURL(base::StringPrintf("http://%s:%d", kIp, try_port)); | 107 base_url_ = GURL(base::StringPrintf("http://%s:%d", kIp, try_port)); |
| 110 port_ = try_port; | 108 port_ = try_port; |
| 111 break; | 109 break; |
| 112 } | 110 } |
| 113 retries_left--; | 111 retries_left--; |
| 114 try_port++; | 112 try_port++; |
| 115 } | 113 } |
| 114 |
| 115 event->Signal(); |
| 116 } | 116 } |
| 117 | 117 |
| 118 void HttpServer::ShutdownOnIOThread() { | 118 void HttpServer::ShutdownOnIOThread(base::WaitableEvent* event) { |
| 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 119 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 120 | 120 |
| 121 listen_socket_ = NULL; // Release the listen socket. | 121 listen_socket_ = NULL; // Release the listen socket. |
| 122 STLDeleteContainerPairSecondPointers(connections_.begin(), | 122 STLDeleteContainerPairSecondPointers(connections_.begin(), |
| 123 connections_.end()); | 123 connections_.end()); |
| 124 connections_.clear(); | 124 connections_.clear(); |
| 125 |
| 126 event->Signal(); |
| 125 } | 127 } |
| 126 | 128 |
| 127 void HttpServer::HandleRequest(HttpConnection* connection, | 129 void HttpServer::HandleRequest(HttpConnection* connection, |
| 128 scoped_ptr<HttpRequest> request) { | 130 scoped_ptr<HttpRequest> request) { |
| 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 131 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 130 | 132 |
| 131 for (size_t i = 0; i < request_handlers_.size(); ++i) { | 133 for (size_t i = 0; i < request_handlers_.size(); ++i) { |
| 132 scoped_ptr<HttpResponse> response = | 134 scoped_ptr<HttpResponse> response = |
| 133 request_handlers_[i].Run(*request.get()); | 135 request_handlers_[i].Run(*request.get()); |
| 134 if (response.get()) { | 136 if (response.get()) { |
| 135 connection->SendResponse(response.Pass()); | 137 connection->SendResponse(response.Pass()); |
| 136 return; | 138 return; |
| 137 } | 139 } |
| 138 } | 140 } |
| 139 | 141 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 155 return base_url_.Resolve(relative_url); | 157 return base_url_.Resolve(relative_url); |
| 156 } | 158 } |
| 157 | 159 |
| 158 void HttpServer::RegisterRequestHandler( | 160 void HttpServer::RegisterRequestHandler( |
| 159 const HandleRequestCallback& callback) { | 161 const HandleRequestCallback& callback) { |
| 160 request_handlers_.push_back(callback); | 162 request_handlers_.push_back(callback); |
| 161 } | 163 } |
| 162 | 164 |
| 163 void HttpServer::DidAccept(net::StreamListenSocket* server, | 165 void HttpServer::DidAccept(net::StreamListenSocket* server, |
| 164 net::StreamListenSocket* connection) { | 166 net::StreamListenSocket* connection) { |
| 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 167 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 166 | 168 |
| 167 HttpConnection* http_connection = new HttpConnection( | 169 HttpConnection* http_connection = new HttpConnection( |
| 168 connection, | 170 connection, |
| 169 base::Bind(&HttpServer::HandleRequest, weak_factory_.GetWeakPtr())); | 171 base::Bind(&HttpServer::HandleRequest, weak_factory_.GetWeakPtr())); |
| 170 connections_[connection] = http_connection; | 172 connections_[connection] = http_connection; |
| 171 } | 173 } |
| 172 | 174 |
| 173 void HttpServer::DidRead(net::StreamListenSocket* connection, | 175 void HttpServer::DidRead(net::StreamListenSocket* connection, |
| 174 const char* data, | 176 const char* data, |
| 175 int length) { | 177 int length) { |
| 176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 178 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 177 | 179 |
| 178 HttpConnection* http_connection = FindConnection(connection); | 180 HttpConnection* http_connection = FindConnection(connection); |
| 179 if (http_connection == NULL) { | 181 if (http_connection == NULL) { |
| 180 LOG(WARNING) << "Unknown connection."; | 182 LOG(WARNING) << "Unknown connection."; |
| 181 return; | 183 return; |
| 182 } | 184 } |
| 183 http_connection->ReceiveData(std::string(data, length)); | 185 http_connection->ReceiveData(std::string(data, length)); |
| 184 } | 186 } |
| 185 | 187 |
| 186 void HttpServer::DidClose(net::StreamListenSocket* connection) { | 188 void HttpServer::DidClose(net::StreamListenSocket* connection) { |
| 187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 189 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 188 | 190 |
| 189 HttpConnection* http_connection = FindConnection(connection); | 191 HttpConnection* http_connection = FindConnection(connection); |
| 190 if (http_connection == NULL) { | 192 if (http_connection == NULL) { |
| 191 LOG(WARNING) << "Unknown connection."; | 193 LOG(WARNING) << "Unknown connection."; |
| 192 return; | 194 return; |
| 193 } | 195 } |
| 194 delete http_connection; | 196 delete http_connection; |
| 195 connections_.erase(connection); | 197 connections_.erase(connection); |
| 196 } | 198 } |
| 197 | 199 |
| 198 HttpConnection* HttpServer::FindConnection( | 200 HttpConnection* HttpServer::FindConnection( |
| 199 net::StreamListenSocket* socket) { | 201 net::StreamListenSocket* socket) { |
| 200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 202 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 201 | 203 |
| 202 std::map<net::StreamListenSocket*, HttpConnection*>::iterator it = | 204 std::map<net::StreamListenSocket*, HttpConnection*>::iterator it = |
| 203 connections_.find(socket); | 205 connections_.find(socket); |
| 204 if (it == connections_.end()) { | 206 if (it == connections_.end()) { |
| 205 return NULL; | 207 return NULL; |
| 206 } | 208 } |
| 207 return it->second; | 209 return it->second; |
| 208 } | 210 } |
| 209 | 211 |
| 210 } // namespace test_server | 212 } // namespace test_server |
| 211 } // namespace google_apis | 213 } // namespace google_apis |
| OLD | NEW |