Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Side by Side Diff: chrome/browser/chromeos/drive/test_servers/http_test_server.cc

Issue 11088073: HTTP server for testing Google Drive. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Addressed comments and simplified. Added tests. Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/drive/test_servers/http_test_server.h"
6
7 #include "base/bind.h"
8 #include "base/stl_util.h"
9 #include "base/file_util.h"
10 #include "base/stringprintf.h"
11 #include "chrome/browser/chromeos/drive/test_servers/http_request.h"
12 #include "chrome/browser/chromeos/drive/test_servers/http_response.h"
13 #include "chrome/browser/google_apis/gdata_test_util.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "net/tools/fetch/http_listen_socket.h"
16
17 #include <sstream>
18
19 namespace drive {
20 namespace test_servers {
21
22 using content::BrowserThread;
23
24 namespace {
25
26 const int kPort = 8040;
27 const char kIp[] = "127.0.0.1";
28 const int kRetries = 10;
29
30 // Callback about success or failure in creating a server. |result| is a pointer
31 // to result passed back to HttpTestServer::CreateForTesting. |server| is a
32 // pointer to the created server or NULL in case of failure.
33 static void OnCreatedForTesting(HttpTestServer** result,
34 HttpTestServer* server) {
35 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
36 *result = server;
37 MessageLoop::current()->Quit();
38 }
39
40 // Callback to handle requests with default predefined response for requests
41 // matching the address |url|.
42 scoped_ptr<HttpResponse> HandleDefaultRequest(const GURL& url,
43 const HttpResponse& response,
44 const HttpRequest* request) {
45 if (url.path() != request->uri.path())
46 return scoped_ptr<HttpResponse>(NULL);
47 return scoped_ptr<HttpResponse>(new HttpResponse(response));
48 }
49
50 } // namespace
51
52 // static
53 scoped_ptr<HttpTestServer> HttpTestServer::CreateForTesting() {
54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
55
56 HttpTestServer* result = NULL;
57 BrowserThread::PostTask(
58 BrowserThread::IO,
59 FROM_HERE,
60 base::Bind(
61 &HttpTestServer::CreateOnIOThread,
62 base::Bind(&OnCreatedForTesting, &result)));
63
64 // Wait for the task completion.
65 MessageLoop::current()->Run();
satorux1 2012/11/12 06:34:15 Can you do this instead? content::RunAllPendingIn
mtomasz 2012/11/14 03:23:35 Done.
66 return scoped_ptr<HttpTestServer>(result);
67 }
68
69 // static
70 void HttpTestServer::CreateOnIOThread(const CreateCallback& callback) {
71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
72
73 int retries_left = kRetries + 1;
74 int try_port = kPort;
75 HttpTestServer* server = NULL;
76
77 while (retries_left) {
satorux1 2012/11/12 06:34:15 retries_left > 0
mtomasz 2012/11/12 12:17:44 Done.
78 SocketDescriptor socket_descriptor = net::TCPListenSocket::CreateAndBind(
79 kIp,
80 try_port);
81 if (socket_descriptor != net::TCPListenSocket::kInvalidSocket) {
82 server = new HttpTestServer(try_port, socket_descriptor);
83 break;
84 }
85 retries_left--;
86 try_port++;
87 }
88
89 BrowserThread::PostTask(BrowserThread::UI,
90 FROM_HERE,
91 base::Bind(callback, server));
92 }
93
94 HttpTestServer::HttpTestServer(int port,
95 const SocketDescriptor& socket_descriptor)
96 : listen_socket_(new HttpListenSocket(
97 socket_descriptor,
98 ALLOW_THIS_IN_INITIALIZER_LIST(this))),
99 port_(port),
100 last_unique_id_(0),
101 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
satorux1 2012/11/12 06:34:15 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::I
mtomasz 2012/11/13 12:23:07 Done.
102 listen_socket_->Listen();
103 base_url_ = GURL(base::StringPrintf("http://%s:%d", kIp, port_));
104 }
105
106 HttpTestServer::~HttpTestServer() {
satorux1 2012/11/12 06:34:15 on what thread this has to be deleted? I guess it'
mtomasz 2012/11/14 03:23:35 UI. Done.
107 STLDeleteContainerPairSecondPointers(connections_.begin(),
108 connections_.end());
109 }
110
111 void HttpTestServer::HandleRequest(HttpConnection* connection,
112 scoped_ptr<HttpRequest> request) {
113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
114
115 std::vector<HandleRequestCallback>::iterator current_handler =
116 request_handlers_.begin();
117 while (current_handler != request_handlers_.end()) {
satorux1 2012/11/12 06:34:15 Why not a for loop? for (size_t i = 0; i < reques
mtomasz 2012/11/12 12:17:44 Done. Do we in general prefer simple loops over it
118 scoped_ptr<HttpResponse> response = current_handler->Run(request.get());
119 if (response.get()) {
120 connection->SendResponse(response.Pass());
121 return;
122 }
123 current_handler++;
124 }
125
126 LOG(WARNING) << "Request not handled. Returning 404.";
127 scoped_ptr<HttpResponse> not_found_response(new HttpResponse());
128 not_found_response->code = NOT_FOUND;
129 connection->SendResponse(not_found_response.Pass());
130 }
131
132 GURL HttpTestServer::GetBaseURL() {
133 return base_url_;
134 }
135
136 void HttpTestServer::RegisterRequestHandler(
137 const HandleRequestCallback& callback) {
138 request_handlers_.push_back(callback);
139 }
140
141 GURL HttpTestServer::RegisterDefaultResponse(
142 const std::string& relative_path,
143 const HttpResponse& default_response) {
144 GURL request_url = base_url_.Resolve(relative_path);
145 const HandleRequestCallback callback =
146 base::Bind(&HandleDefaultRequest,
147 request_url,
148 default_response);
149 request_handlers_.push_back(callback);
150
151 return request_url;
152 }
153
154 GURL HttpTestServer::RegisterTextResponse(
155 const std::string& relative_path,
156 const std::string& content,
157 const std::string& content_type,
158 const ResponseCode response_code) {
159 HttpResponse default_response;
160 default_response.content = content;
161 default_response.content_type = content_type;
162 default_response.code = response_code;
163
164 return RegisterDefaultResponse(relative_path, default_response);
165 }
166
167 GURL HttpTestServer::RegisterTextResponse(
satorux1 2012/11/12 06:34:15 Function overloading like this is not allowed per
mtomasz 2012/11/12 12:17:44 Done.
168 const std::string& content,
169 const std::string& content_type) {
170 return RegisterTextResponse(GenerateUniqueIdentifier(),
171 content,
172 content_type,
173 SUCCESS);
174 }
175
176 GURL HttpTestServer::RegisterFileResponse(
177 const std::string& relative_path,
178 const FilePath& file_path,
179 const std::string& content_type,
180 const ResponseCode response_code) {
181 HttpResponse default_response;
182
183 DCHECK(file_util::ReadFileToString(file_path, &default_response.content)) <<
184 "Failed to open the file: " << file_path.value();
185
186 default_response.content_type = content_type;
187 default_response.code = response_code;
188
189 return RegisterDefaultResponse(relative_path, default_response);
190 }
191
192 GURL HttpTestServer::RegisterFileResponse(
satorux1 2012/11/12 06:34:15 ditto.
mtomasz 2012/11/12 12:17:44 Done.
193 const FilePath& file_path,
194 const std::string& content_type) {
195 return RegisterFileResponse(
196 GenerateUniqueIdentifier() + "/" + file_path.BaseName().value(),
197 file_path,
198 content_type,
199 SUCCESS);
200 }
201
202 std::string HttpTestServer::GenerateUniqueIdentifier() {
203 std::stringstream result_builder;
204 result_builder << ++last_unique_id_;
205 return result_builder.str();
206 }
207
208 void HttpTestServer::DidAccept(net::StreamListenSocket* server,
209 net::StreamListenSocket* connection) {
210 HttpConnection* http_connection = new HttpConnection(
211 connection,
212 base::Bind(&HttpTestServer::HandleRequest, weak_factory_.GetWeakPtr()));
213 connections_[connection] = http_connection;
214 }
215
216 void HttpTestServer::DidRead(net::StreamListenSocket* connection,
217 const char* data,
218 int length) {
219 HttpConnection* http_connection = FindConnection(connection);
220 if (http_connection == NULL) {
221 LOG(WARNING) << "Unknown connection.";
222 return;
223 }
224 http_connection->ReceiveData(data, length);
225 }
226
227 void HttpTestServer::DidClose(net::StreamListenSocket* connection) {
228 HttpConnection* http_connection = FindConnection(connection);
229 if (http_connection == NULL) {
230 LOG(WARNING) << "Unknown connection.";
231 return;
232 }
233 delete http_connection;
234 connections_.erase(connection);
235 }
236
237 HttpConnection* HttpTestServer::FindConnection(
238 net::StreamListenSocket* socket) {
239 std::map<net::StreamListenSocket*, HttpConnection*>::iterator it =
240 connections_.find(socket);
241 if (it == connections_.end()) {
242 return NULL;
243 }
244 return it->second;
245 }
246
247 } // namespace test_servers
248 } // namespace drive
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698