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 #ifndef CHROME_FRAME_TEST_TEST_SERVER_H_ | 5 #ifndef CHROME_FRAME_TEST_TEST_SERVER_H_ |
6 #define CHROME_FRAME_TEST_TEST_SERVER_H_ | 6 #define CHROME_FRAME_TEST_TEST_SERVER_H_ |
7 | 7 |
8 // Implementation of an HTTP server for tests. | 8 // Implementation of an HTTP server for tests. |
9 // To instantiate the server, make sure you have a message loop on the | 9 // To instantiate the server, make sure you have a message loop on the |
10 // current thread and then create an instance of the SimpleWebServer class. | 10 // current thread and then create an instance of the SimpleWebServer class. |
(...skipping 23 matching lines...) Expand all Loading... |
34 // server), just inherit from one of the response classes or directly from the | 34 // server), just inherit from one of the response classes or directly from the |
35 // Response interface and add your response object to the server's list of | 35 // Response interface and add your response object to the server's list of |
36 // response objects. | 36 // response objects. |
37 | 37 |
38 #include <list> | 38 #include <list> |
39 #include <string> | 39 #include <string> |
40 | 40 |
41 #include "base/basictypes.h" | 41 #include "base/basictypes.h" |
42 #include "base/file_util.h" | 42 #include "base/file_util.h" |
43 #include "base/message_loop.h" | 43 #include "base/message_loop.h" |
44 #include "net/base/listen_socket.h" | 44 #include "net/base/stream_listen_socket.h" |
45 | 45 |
46 namespace test_server { | 46 namespace test_server { |
47 | 47 |
48 class Request { | 48 class Request { |
49 public: | 49 public: |
50 Request() : content_length_(0) { | 50 Request() : content_length_(0) { |
51 } | 51 } |
52 | 52 |
53 void ParseHeaders(const std::string& headers); | 53 void ParseHeaders(const std::string& headers); |
54 | 54 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 private: | 99 private: |
100 DISALLOW_COPY_AND_ASSIGN(Request); | 100 DISALLOW_COPY_AND_ASSIGN(Request); |
101 }; | 101 }; |
102 | 102 |
103 // Manages request headers for a single request. | 103 // Manages request headers for a single request. |
104 // For each successful request that's made, the server will keep an instance | 104 // For each successful request that's made, the server will keep an instance |
105 // of this class so that they can be checked even after the server has been | 105 // of this class so that they can be checked even after the server has been |
106 // shut down. | 106 // shut down. |
107 class Connection { | 107 class Connection { |
108 public: | 108 public: |
109 explicit Connection(net::ListenSocket* sock) : socket_(sock) { | 109 explicit Connection(net::StreamListenSocket* sock) : socket_(sock) { |
110 } | 110 } |
111 | 111 |
112 ~Connection() { | 112 ~Connection() { |
113 } | 113 } |
114 | 114 |
115 bool IsSame(const net::ListenSocket* socket) const { | 115 bool IsSame(const net::StreamListenSocket* socket) const { |
116 return socket_ == socket; | 116 return socket_ == socket; |
117 } | 117 } |
118 | 118 |
119 const Request& request() const { | 119 const Request& request() const { |
120 return request_; | 120 return request_; |
121 } | 121 } |
122 | 122 |
123 Request& request() { | 123 Request& request() { |
124 return request_; | 124 return request_; |
125 } | 125 } |
126 | 126 |
127 void OnSocketClosed() { | 127 void OnSocketClosed() { |
128 socket_ = NULL; | 128 socket_ = NULL; |
129 } | 129 } |
130 | 130 |
131 protected: | 131 protected: |
132 scoped_refptr<net::ListenSocket> socket_; | 132 scoped_refptr<net::StreamListenSocket> socket_; |
133 Request request_; | 133 Request request_; |
134 | 134 |
135 private: | 135 private: |
136 DISALLOW_COPY_AND_ASSIGN(Connection); | 136 DISALLOW_COPY_AND_ASSIGN(Connection); |
137 }; | 137 }; |
138 | 138 |
139 // Abstract interface with default implementations for some of the methods and | 139 // Abstract interface with default implementations for some of the methods and |
140 // a counter for how many times the response object has served requests. | 140 // a counter for how many times the response object has served requests. |
141 class Response { | 141 class Response { |
142 public: | 142 public: |
(...skipping 15 matching lines...) Expand all Loading... |
158 // Optionally provide a content type. Return false if you don't specify | 158 // Optionally provide a content type. Return false if you don't specify |
159 // a content type. | 159 // a content type. |
160 virtual bool GetContentType(std::string* content_type) const { | 160 virtual bool GetContentType(std::string* content_type) const { |
161 return false; | 161 return false; |
162 } | 162 } |
163 | 163 |
164 virtual size_t ContentLength() const { | 164 virtual size_t ContentLength() const { |
165 return 0; | 165 return 0; |
166 } | 166 } |
167 | 167 |
168 virtual void WriteContents(net::ListenSocket* socket) const { | 168 virtual void WriteContents(net::StreamListenSocket* socket) const { |
169 } | 169 } |
170 | 170 |
171 virtual void IncrementAccessCounter() { | 171 virtual void IncrementAccessCounter() { |
172 accessed_++; | 172 accessed_++; |
173 } | 173 } |
174 | 174 |
175 size_t accessed() const { | 175 size_t accessed() const { |
176 return accessed_; | 176 return accessed_; |
177 } | 177 } |
178 | 178 |
179 protected: | 179 protected: |
180 size_t accessed_; | 180 size_t accessed_; |
181 | 181 |
182 private: | 182 private: |
183 DISALLOW_COPY_AND_ASSIGN(Response); | 183 DISALLOW_COPY_AND_ASSIGN(Response); |
184 }; | 184 }; |
185 | 185 |
186 // Partial implementation of Response that matches a request's path. | 186 // Partial implementation of Response that matches a request's path. |
187 // This is just a convenience implementation for the boilerplate implementation | 187 // This is just a convenience implementation for the boilerplate implementation |
188 // of Matches(). Don't instantiate directly. | 188 // of Matches(). Don't instantiate directly. |
189 class ResponseForPath : public Response { | 189 class ResponseForPath : public Response { |
190 public: | 190 public: |
191 explicit ResponseForPath(const char* request_path) | 191 explicit ResponseForPath(const char* request_path) |
192 : request_path_(request_path) { | 192 : request_path_(request_path) { |
193 } | 193 } |
194 | 194 |
| 195 virtual ~ResponseForPath(); |
| 196 |
195 virtual bool Matches(const Request& r) const { | 197 virtual bool Matches(const Request& r) const { |
196 std::string path = r.path(); | 198 std::string path = r.path(); |
197 std::string::size_type pos = path.find('?'); | 199 std::string::size_type pos = path.find('?'); |
198 if (pos != std::string::npos) | 200 if (pos != std::string::npos) |
199 path = path.substr(0, pos); | 201 path = path.substr(0, pos); |
200 return path.compare(request_path_) == 0; | 202 return path.compare(request_path_) == 0; |
201 } | 203 } |
202 | 204 |
203 protected: | 205 protected: |
204 std::string request_path_; | 206 std::string request_path_; |
205 | 207 |
206 private: | 208 private: |
207 DISALLOW_COPY_AND_ASSIGN(ResponseForPath); | 209 DISALLOW_COPY_AND_ASSIGN(ResponseForPath); |
208 }; | 210 }; |
209 | 211 |
210 // A very basic implementation of a response. | 212 // A very basic implementation of a response. |
211 // A simple response matches a single document path on the server | 213 // A simple response matches a single document path on the server |
212 // (e.g. "/foo") and returns a document in the form of a string. | 214 // (e.g. "/foo") and returns a document in the form of a string. |
213 class SimpleResponse : public ResponseForPath { | 215 class SimpleResponse : public ResponseForPath { |
214 public: | 216 public: |
215 SimpleResponse(const char* request_path, const std::string& contents) | 217 SimpleResponse(const char* request_path, const std::string& contents) |
216 : ResponseForPath(request_path), contents_(contents) { | 218 : ResponseForPath(request_path), contents_(contents) { |
217 } | 219 } |
218 | 220 |
219 virtual void WriteContents(net::ListenSocket* socket) const { | 221 virtual ~SimpleResponse(); |
| 222 |
| 223 virtual void WriteContents(net::StreamListenSocket* socket) const { |
220 socket->Send(contents_.c_str(), contents_.length(), false); | 224 socket->Send(contents_.c_str(), contents_.length(), false); |
221 } | 225 } |
222 | 226 |
223 virtual size_t ContentLength() const { | 227 virtual size_t ContentLength() const { |
224 return contents_.length(); | 228 return contents_.length(); |
225 } | 229 } |
226 | 230 |
227 protected: | 231 protected: |
228 std::string contents_; | 232 std::string contents_; |
229 | 233 |
230 private: | 234 private: |
231 DISALLOW_COPY_AND_ASSIGN(SimpleResponse); | 235 DISALLOW_COPY_AND_ASSIGN(SimpleResponse); |
232 }; | 236 }; |
233 | 237 |
234 // To serve up files from the web server, create an instance of FileResponse | 238 // To serve up files from the web server, create an instance of FileResponse |
235 // and add it to the server's list of responses. The content type of the | 239 // and add it to the server's list of responses. The content type of the |
236 // file will be determined by calling FindMimeFromData which examines the | 240 // file will be determined by calling FindMimeFromData which examines the |
237 // contents of the file and performs registry lookups. | 241 // contents of the file and performs registry lookups. |
238 class FileResponse : public ResponseForPath { | 242 class FileResponse : public ResponseForPath { |
239 public: | 243 public: |
240 FileResponse(const char* request_path, const FilePath& file_path) | 244 FileResponse(const char* request_path, const FilePath& file_path) |
241 : ResponseForPath(request_path), file_path_(file_path) { | 245 : ResponseForPath(request_path), file_path_(file_path) { |
242 } | 246 } |
243 | 247 |
244 virtual bool GetContentType(std::string* content_type) const; | 248 virtual bool GetContentType(std::string* content_type) const; |
245 virtual void WriteContents(net::ListenSocket* socket) const; | 249 virtual void WriteContents(net::StreamListenSocket* socket) const; |
246 virtual size_t ContentLength() const; | 250 virtual size_t ContentLength() const; |
247 | 251 |
248 protected: | 252 protected: |
249 FilePath file_path_; | 253 FilePath file_path_; |
250 mutable scoped_ptr<file_util::MemoryMappedFile> file_; | 254 mutable scoped_ptr<file_util::MemoryMappedFile> file_; |
251 | 255 |
252 private: | 256 private: |
253 DISALLOW_COPY_AND_ASSIGN(FileResponse); | 257 DISALLOW_COPY_AND_ASSIGN(FileResponse); |
254 }; | 258 }; |
255 | 259 |
(...skipping 13 matching lines...) Expand all Loading... |
269 private: | 273 private: |
270 DISALLOW_COPY_AND_ASSIGN(RedirectResponse); | 274 DISALLOW_COPY_AND_ASSIGN(RedirectResponse); |
271 }; | 275 }; |
272 | 276 |
273 // typedef for a list of connections. Used by SimpleWebServer. | 277 // typedef for a list of connections. Used by SimpleWebServer. |
274 typedef std::list<Connection*> ConnectionList; | 278 typedef std::list<Connection*> ConnectionList; |
275 | 279 |
276 // Implementation of a simple http server. | 280 // Implementation of a simple http server. |
277 // Before creating an instance of the server, make sure the current thread | 281 // Before creating an instance of the server, make sure the current thread |
278 // has a message loop. | 282 // has a message loop. |
279 class SimpleWebServer : public net::ListenSocket::ListenSocketDelegate { | 283 class SimpleWebServer : public net::StreamListenSocket::Delegate { |
280 public: | 284 public: |
281 explicit SimpleWebServer(int port); | 285 explicit SimpleWebServer(int port); |
282 virtual ~SimpleWebServer(); | 286 virtual ~SimpleWebServer(); |
283 | 287 |
284 void AddResponse(Response* response); | 288 void AddResponse(Response* response); |
285 | 289 |
286 // Ownership of response objects is by default assumed to be outside | 290 // Ownership of response objects is by default assumed to be outside |
287 // of the SimpleWebServer class. | 291 // of the SimpleWebServer class. |
288 // However, if the caller doesn't wish to maintain a list of response objects | 292 // However, if the caller doesn't wish to maintain a list of response objects |
289 // but rather let this class hold the only references to those objects, | 293 // but rather let this class hold the only references to those objects, |
290 // the caller can call this method to delete the objects as part of | 294 // the caller can call this method to delete the objects as part of |
291 // the cleanup process. | 295 // the cleanup process. |
292 void DeleteAllResponses(); | 296 void DeleteAllResponses(); |
293 | 297 |
294 // ListenSocketDelegate overrides. | 298 // StreamListenSocket::Delegate overrides. |
295 virtual void DidAccept(net::ListenSocket* server, | 299 virtual void DidAccept(net::StreamListenSocket* server, |
296 net::ListenSocket* connection); | 300 net::StreamListenSocket* connection); |
297 virtual void DidRead(net::ListenSocket* connection, | 301 virtual void DidRead(net::StreamListenSocket* connection, |
298 const char* data, | 302 const char* data, |
299 int len); | 303 int len); |
300 virtual void DidClose(net::ListenSocket* sock); | 304 virtual void DidClose(net::StreamListenSocket* sock); |
301 | 305 |
302 const ConnectionList& connections() const { | 306 const ConnectionList& connections() const { |
303 return connections_; | 307 return connections_; |
304 } | 308 } |
305 | 309 |
306 protected: | 310 protected: |
307 class QuitResponse : public SimpleResponse { | 311 class QuitResponse : public SimpleResponse { |
308 public: | 312 public: |
309 QuitResponse() | 313 QuitResponse() |
310 : SimpleResponse("/quit", "So long and thanks for all the fish.") { | 314 : SimpleResponse("/quit", "So long and thanks for all the fish.") { |
311 } | 315 } |
312 | 316 |
313 virtual void QuitResponse::WriteContents(net::ListenSocket* socket) const { | 317 virtual void WriteContents(net::StreamListenSocket* socket) const { |
314 SimpleResponse::WriteContents(socket); | 318 SimpleResponse::WriteContents(socket); |
315 MessageLoop::current()->Quit(); | 319 MessageLoop::current()->Quit(); |
316 } | 320 } |
317 }; | 321 }; |
318 | 322 |
319 Response* FindResponse(const Request& request) const; | 323 Response* FindResponse(const Request& request) const; |
320 Connection* FindConnection(const net::ListenSocket* socket) const; | 324 Connection* FindConnection(const net::StreamListenSocket* socket) const; |
321 | 325 |
322 protected: | 326 protected: |
323 scoped_refptr<net::ListenSocket> server_; | 327 scoped_refptr<net::StreamListenSocket> server_; |
324 ConnectionList connections_; | 328 ConnectionList connections_; |
325 std::list<Response*> responses_; | 329 std::list<Response*> responses_; |
326 QuitResponse quit_; | 330 QuitResponse quit_; |
327 | 331 |
328 private: | 332 private: |
329 DISALLOW_COPY_AND_ASSIGN(SimpleWebServer); | 333 DISALLOW_COPY_AND_ASSIGN(SimpleWebServer); |
330 }; | 334 }; |
331 | 335 |
332 // Simple class holding incoming HTTP request. Can send the HTTP response | 336 // Simple class holding incoming HTTP request. Can send the HTTP response |
333 // at different rate - small chunks, on regular interval. | 337 // at different rate - small chunks, on regular interval. |
334 class ConfigurableConnection : public base::RefCounted<ConfigurableConnection> { | 338 class ConfigurableConnection : public base::RefCounted<ConfigurableConnection> { |
335 public: | 339 public: |
336 struct SendOptions { | 340 struct SendOptions { |
337 enum Speed { IMMEDIATE, DELAYED, IMMEDIATE_HEADERS_DELAYED_CONTENT }; | 341 enum Speed { IMMEDIATE, DELAYED, IMMEDIATE_HEADERS_DELAYED_CONTENT }; |
338 SendOptions() : speed_(IMMEDIATE), chunk_size_(0), timeout_(0) { } | 342 SendOptions() : speed_(IMMEDIATE), chunk_size_(0), timeout_(0) { } |
339 SendOptions(Speed speed, int chunk_size, int64 timeout) | 343 SendOptions(Speed speed, int chunk_size, int64 timeout) |
340 : speed_(speed), chunk_size_(chunk_size), timeout_(timeout) { | 344 : speed_(speed), chunk_size_(chunk_size), timeout_(timeout) { |
341 } | 345 } |
342 | 346 |
343 Speed speed_; | 347 Speed speed_; |
344 int chunk_size_; | 348 int chunk_size_; |
345 int64 timeout_; | 349 int64 timeout_; |
346 }; | 350 }; |
347 | 351 |
348 explicit ConfigurableConnection(net::ListenSocket* sock) | 352 explicit ConfigurableConnection(net::StreamListenSocket* sock) |
349 : socket_(sock), | 353 : socket_(sock), |
350 cur_pos_(0) {} | 354 cur_pos_(0) {} |
351 | 355 |
352 // Send HTTP response with provided |headers| and |content|. Appends | 356 // Send HTTP response with provided |headers| and |content|. Appends |
353 // "Context-Length:" header if the |content| is not empty. | 357 // "Context-Length:" header if the |content| is not empty. |
354 void Send(const std::string& headers, const std::string& content); | 358 void Send(const std::string& headers, const std::string& content); |
355 | 359 |
356 // Send HTTP response with provided |headers| and |content|. Appends | 360 // Send HTTP response with provided |headers| and |content|. Appends |
357 // "Context-Length:" header if the |content| is not empty. | 361 // "Context-Length:" header if the |content| is not empty. |
358 // Use the |options| to tweak the network speed behaviour. | 362 // Use the |options| to tweak the network speed behaviour. |
359 void SendWithOptions(const std::string& headers, const std::string& content, | 363 void SendWithOptions(const std::string& headers, const std::string& content, |
360 const SendOptions& options); | 364 const SendOptions& options); |
361 | 365 |
362 private: | 366 private: |
363 friend class HTTPTestServer; | 367 friend class HTTPTestServer; |
364 // Sends a chunk of the response and queues itself as a task for sending | 368 // Sends a chunk of the response and queues itself as a task for sending |
365 // next chunk of |data_|. | 369 // next chunk of |data_|. |
366 void SendChunk(); | 370 void SendChunk(); |
367 | 371 |
368 // Closes the connection by releasing this instance's reference on its socket. | 372 // Closes the connection by releasing this instance's reference on its socket. |
369 void Close(); | 373 void Close(); |
370 | 374 |
371 scoped_refptr<net::ListenSocket> socket_; | 375 scoped_refptr<net::StreamListenSocket> socket_; |
372 Request r_; | 376 Request r_; |
373 SendOptions options_; | 377 SendOptions options_; |
374 std::string data_; | 378 std::string data_; |
375 int cur_pos_; | 379 int cur_pos_; |
376 | 380 |
377 DISALLOW_COPY_AND_ASSIGN(ConfigurableConnection); | 381 DISALLOW_COPY_AND_ASSIGN(ConfigurableConnection); |
378 }; | 382 }; |
379 | 383 |
380 // Simple class used as a base class for mock webserver. | 384 // Simple class used as a base class for mock webserver. |
381 // Override virtual functions Get and Post and use passed ConfigurableConnection | 385 // Override virtual functions Get and Post and use passed ConfigurableConnection |
382 // instance to send the response. | 386 // instance to send the response. |
383 class HTTPTestServer : public net::ListenSocket::ListenSocketDelegate { | 387 class HTTPTestServer : public net::StreamListenSocket::Delegate { |
384 public: | 388 public: |
385 HTTPTestServer(int port, const std::wstring& address, FilePath root_dir); | 389 HTTPTestServer(int port, const std::wstring& address, FilePath root_dir); |
386 virtual ~HTTPTestServer(); | 390 virtual ~HTTPTestServer(); |
387 | 391 |
388 // HTTP GET request is received. Override in derived classes. | 392 // HTTP GET request is received. Override in derived classes. |
389 // |connection| can be used to send the response. | 393 // |connection| can be used to send the response. |
390 virtual void Get(ConfigurableConnection* connection, | 394 virtual void Get(ConfigurableConnection* connection, |
391 const std::wstring& path, const Request& r) = 0; | 395 const std::wstring& path, const Request& r) = 0; |
392 | 396 |
393 // HTTP POST request is received. Override in derived classes. | 397 // HTTP POST request is received. Override in derived classes. |
394 // |connection| can be used to send the response | 398 // |connection| can be used to send the response |
395 virtual void Post(ConfigurableConnection* connection, | 399 virtual void Post(ConfigurableConnection* connection, |
396 const std::wstring& path, const Request& r) = 0; | 400 const std::wstring& path, const Request& r) = 0; |
397 | 401 |
398 // Return the appropriate url with the specified path for this server. | 402 // Return the appropriate url with the specified path for this server. |
399 std::wstring Resolve(const std::wstring& path); | 403 std::wstring Resolve(const std::wstring& path); |
400 | 404 |
401 FilePath root_dir() { return root_dir_; } | 405 FilePath root_dir() { return root_dir_; } |
402 | 406 |
403 protected: | 407 protected: |
404 int port_; | 408 int port_; |
405 std::wstring address_; | 409 std::wstring address_; |
406 FilePath root_dir_; | 410 FilePath root_dir_; |
407 | 411 |
408 private: | 412 private: |
409 typedef std::list<scoped_refptr<ConfigurableConnection> > ConnectionList; | 413 typedef std::list<scoped_refptr<ConfigurableConnection> > ConnectionList; |
410 ConnectionList::iterator FindConnection(const net::ListenSocket* socket); | 414 ConnectionList::iterator FindConnection( |
| 415 const net::StreamListenSocket* socket); |
411 scoped_refptr<ConfigurableConnection> ConnectionFromSocket( | 416 scoped_refptr<ConfigurableConnection> ConnectionFromSocket( |
412 const net::ListenSocket* socket); | 417 const net::StreamListenSocket* socket); |
413 | 418 |
414 // ListenSocketDelegate overrides. | 419 // StreamListenSocket::Delegate overrides. |
415 virtual void DidAccept(net::ListenSocket* server, net::ListenSocket* socket); | 420 virtual void DidAccept(net::StreamListenSocket* server, |
416 virtual void DidRead(net::ListenSocket* socket, const char* data, int len); | 421 net::StreamListenSocket* socket); |
417 virtual void DidClose(net::ListenSocket* socket); | 422 virtual void DidRead(net::StreamListenSocket* socket, |
| 423 const char* data, int len); |
| 424 virtual void DidClose(net::StreamListenSocket* socket); |
418 | 425 |
419 scoped_refptr<net::ListenSocket> server_; | 426 scoped_refptr<net::StreamListenSocket> server_; |
420 ConnectionList connection_list_; | 427 ConnectionList connection_list_; |
421 | 428 |
422 DISALLOW_COPY_AND_ASSIGN(HTTPTestServer); | 429 DISALLOW_COPY_AND_ASSIGN(HTTPTestServer); |
423 }; | 430 }; |
424 | 431 |
425 } // namespace test_server | 432 } // namespace test_server |
426 | 433 |
427 #endif // CHROME_FRAME_TEST_TEST_SERVER_H_ | 434 #endif // CHROME_FRAME_TEST_TEST_SERVER_H_ |
OLD | NEW |