Chromium Code Reviews| 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)); | 42 DCHECK(thread_checker_.CalledOnValidThread()); |
| 46 } | 43 } |
| 47 | 44 |
| 48 void HttpListenSocket::Listen() { | 45 void HttpListenSocket::Listen() { |
| 49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 46 DCHECK(thread_checker_.CalledOnValidThread()); |
| 50 net::TCPListenSocket::Listen(); | 47 net::TCPListenSocket::Listen(); |
| 51 } | 48 } |
| 52 | 49 |
| 53 HttpListenSocket::~HttpListenSocket() { | 50 HttpListenSocket::~HttpListenSocket() { |
| 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 51 DCHECK(thread_checker_.CalledOnValidThread()); |
| 55 } | 52 } |
| 56 | 53 |
| 57 HttpServer::HttpServer() | 54 HttpServer::HttpServer( |
| 58 : port_(-1), | 55 const scoped_refptr<base::SingleThreadTaskRunner>& io_thread) |
| 56 : io_thread_(io_thread), | |
| 57 port_(-1), | |
| 59 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 58 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 59 DCHECK(io_thread_); |
| 60 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 61 } | 61 } |
| 62 | 62 |
| 63 HttpServer::~HttpServer() { | 63 HttpServer::~HttpServer() { |
| 64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 64 DCHECK(thread_checker_.CalledOnValidThread()); |
| 65 } | 65 } |
| 66 | 66 |
| 67 bool HttpServer::InitializeAndWaitUntilReady() { | 67 bool HttpServer::InitializeAndWaitUntilReady() { |
| 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 68 DCHECK(thread_checker_.CalledOnValidThread()); |
| 69 | 69 |
| 70 BrowserThread::PostTask( | 70 base::WaitableEvent event(false, false); |
| 71 BrowserThread::IO, | 71 if (!io_thread_->PostTask(FROM_HERE, |
| 72 FROM_HERE, | 72 base::Bind(&HttpServer::InitializeOnIOThread, |
| 73 base::Bind(&HttpServer::InitializeOnIOThread, | 73 base::Unretained(this), &event))) { |
| 74 base::Unretained(this))); | 74 return false; |
| 75 } | |
| 75 | 76 |
| 76 // Wait for the task completion. | 77 event.Wait(); |
| 77 content::RunAllPendingInMessageLoop(BrowserThread::IO); | |
| 78 | 78 |
| 79 return Started(); | 79 return Started(); |
| 80 } | 80 } |
| 81 | 81 |
| 82 void HttpServer::ShutdownAndWaitUntilComplete() { | 82 bool HttpServer::ShutdownAndWaitUntilComplete() { |
| 83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 83 DCHECK(thread_checker_.CalledOnValidThread()); |
| 84 | 84 |
| 85 BrowserThread::PostTask( | 85 base::WaitableEvent event(false, false); |
| 86 BrowserThread::IO, | 86 if (!io_thread_->PostTask(FROM_HERE, |
| 87 FROM_HERE, | 87 base::Bind(&HttpServer::ShutdownOnIOThread, |
| 88 base::Bind(&HttpServer::ShutdownOnIOThread, | 88 base::Unretained(this), &event))) { |
| 89 base::Unretained(this))); | 89 return false; |
| 90 } | |
| 90 | 91 |
| 91 // Wait for the task completion. | 92 event.Wait(); |
|
satorux1
2013/04/23 07:57:05
What about doing this:
base::RunLoop run_loop;
io
Paweł Hajdan Jr.
2013/04/23 22:12:42
Done! Thank you for the great suggestion, it looks
satorux1
2013/04/23 23:39:53
Glad you liked it.
| |
| 92 content::RunAllPendingInMessageLoop(BrowserThread::IO); | 93 |
| 94 return true; | |
| 93 } | 95 } |
| 94 | 96 |
| 95 void HttpServer::InitializeOnIOThread() { | 97 void HttpServer::InitializeOnIOThread(base::WaitableEvent* event) { |
| 96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 98 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 97 DCHECK(!Started()); | 99 DCHECK(!Started()); |
| 98 | 100 |
| 99 int retries_left = kRetries + 1; | 101 int retries_left = kRetries + 1; |
| 100 int try_port = kPort; | 102 int try_port = kPort; |
| 101 | 103 |
| 102 while (retries_left > 0) { | 104 while (retries_left > 0) { |
| 103 SocketDescriptor socket_descriptor = net::TCPListenSocket::CreateAndBind( | 105 SocketDescriptor socket_descriptor = net::TCPListenSocket::CreateAndBind( |
| 104 kIp, | 106 kIp, |
| 105 try_port); | 107 try_port); |
| 106 if (socket_descriptor != net::TCPListenSocket::kInvalidSocket) { | 108 if (socket_descriptor != net::TCPListenSocket::kInvalidSocket) { |
| 107 listen_socket_ = new HttpListenSocket(socket_descriptor, this); | 109 listen_socket_ = new HttpListenSocket(socket_descriptor, this); |
| 108 listen_socket_->Listen(); | 110 listen_socket_->Listen(); |
| 109 base_url_ = GURL(base::StringPrintf("http://%s:%d", kIp, try_port)); | 111 base_url_ = GURL(base::StringPrintf("http://%s:%d", kIp, try_port)); |
| 110 port_ = try_port; | 112 port_ = try_port; |
| 111 break; | 113 break; |
| 112 } | 114 } |
| 113 retries_left--; | 115 retries_left--; |
| 114 try_port++; | 116 try_port++; |
| 115 } | 117 } |
| 118 | |
| 119 event->Signal(); | |
| 116 } | 120 } |
| 117 | 121 |
| 118 void HttpServer::ShutdownOnIOThread() { | 122 void HttpServer::ShutdownOnIOThread(base::WaitableEvent* event) { |
| 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 123 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 120 | 124 |
| 121 listen_socket_ = NULL; // Release the listen socket. | 125 listen_socket_ = NULL; // Release the listen socket. |
| 122 STLDeleteContainerPairSecondPointers(connections_.begin(), | 126 STLDeleteContainerPairSecondPointers(connections_.begin(), |
| 123 connections_.end()); | 127 connections_.end()); |
| 124 connections_.clear(); | 128 connections_.clear(); |
| 129 | |
| 130 event->Signal(); | |
| 125 } | 131 } |
| 126 | 132 |
| 127 void HttpServer::HandleRequest(HttpConnection* connection, | 133 void HttpServer::HandleRequest(HttpConnection* connection, |
| 128 scoped_ptr<HttpRequest> request) { | 134 scoped_ptr<HttpRequest> request) { |
| 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 135 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 130 | 136 |
| 131 for (size_t i = 0; i < request_handlers_.size(); ++i) { | 137 for (size_t i = 0; i < request_handlers_.size(); ++i) { |
| 132 scoped_ptr<HttpResponse> response = | 138 scoped_ptr<HttpResponse> response = |
| 133 request_handlers_[i].Run(*request.get()); | 139 request_handlers_[i].Run(*request.get()); |
| 134 if (response.get()) { | 140 if (response.get()) { |
| 135 connection->SendResponse(response.Pass()); | 141 connection->SendResponse(response.Pass()); |
| 136 return; | 142 return; |
| 137 } | 143 } |
| 138 } | 144 } |
| 139 | 145 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 155 return base_url_.Resolve(relative_url); | 161 return base_url_.Resolve(relative_url); |
| 156 } | 162 } |
| 157 | 163 |
| 158 void HttpServer::RegisterRequestHandler( | 164 void HttpServer::RegisterRequestHandler( |
| 159 const HandleRequestCallback& callback) { | 165 const HandleRequestCallback& callback) { |
| 160 request_handlers_.push_back(callback); | 166 request_handlers_.push_back(callback); |
| 161 } | 167 } |
| 162 | 168 |
| 163 void HttpServer::DidAccept(net::StreamListenSocket* server, | 169 void HttpServer::DidAccept(net::StreamListenSocket* server, |
| 164 net::StreamListenSocket* connection) { | 170 net::StreamListenSocket* connection) { |
| 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 171 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 166 | 172 |
| 167 HttpConnection* http_connection = new HttpConnection( | 173 HttpConnection* http_connection = new HttpConnection( |
| 168 connection, | 174 connection, |
| 169 base::Bind(&HttpServer::HandleRequest, weak_factory_.GetWeakPtr())); | 175 base::Bind(&HttpServer::HandleRequest, weak_factory_.GetWeakPtr())); |
| 170 connections_[connection] = http_connection; | 176 connections_[connection] = http_connection; |
| 171 } | 177 } |
| 172 | 178 |
| 173 void HttpServer::DidRead(net::StreamListenSocket* connection, | 179 void HttpServer::DidRead(net::StreamListenSocket* connection, |
| 174 const char* data, | 180 const char* data, |
| 175 int length) { | 181 int length) { |
| 176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 182 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 177 | 183 |
| 178 HttpConnection* http_connection = FindConnection(connection); | 184 HttpConnection* http_connection = FindConnection(connection); |
| 179 if (http_connection == NULL) { | 185 if (http_connection == NULL) { |
| 180 LOG(WARNING) << "Unknown connection."; | 186 LOG(WARNING) << "Unknown connection."; |
| 181 return; | 187 return; |
| 182 } | 188 } |
| 183 http_connection->ReceiveData(std::string(data, length)); | 189 http_connection->ReceiveData(std::string(data, length)); |
| 184 } | 190 } |
| 185 | 191 |
| 186 void HttpServer::DidClose(net::StreamListenSocket* connection) { | 192 void HttpServer::DidClose(net::StreamListenSocket* connection) { |
| 187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 193 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 188 | 194 |
| 189 HttpConnection* http_connection = FindConnection(connection); | 195 HttpConnection* http_connection = FindConnection(connection); |
| 190 if (http_connection == NULL) { | 196 if (http_connection == NULL) { |
| 191 LOG(WARNING) << "Unknown connection."; | 197 LOG(WARNING) << "Unknown connection."; |
| 192 return; | 198 return; |
| 193 } | 199 } |
| 194 delete http_connection; | 200 delete http_connection; |
| 195 connections_.erase(connection); | 201 connections_.erase(connection); |
| 196 } | 202 } |
| 197 | 203 |
| 198 HttpConnection* HttpServer::FindConnection( | 204 HttpConnection* HttpServer::FindConnection( |
| 199 net::StreamListenSocket* socket) { | 205 net::StreamListenSocket* socket) { |
| 200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 206 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 201 | 207 |
| 202 std::map<net::StreamListenSocket*, HttpConnection*>::iterator it = | 208 std::map<net::StreamListenSocket*, HttpConnection*>::iterator it = |
| 203 connections_.find(socket); | 209 connections_.find(socket); |
| 204 if (it == connections_.end()) { | 210 if (it == connections_.end()) { |
| 205 return NULL; | 211 return NULL; |
| 206 } | 212 } |
| 207 return it->second; | 213 return it->second; |
| 208 } | 214 } |
| 209 | 215 |
| 210 } // namespace test_server | 216 } // namespace test_server |
| 211 } // namespace google_apis | 217 } // namespace google_apis |
| OLD | NEW |