Loosen up heuristics for detecting account creation forms.
[chromium-blink-merge.git] / chrome_frame / test / test_server.h
blob04da1265556ba8a278f9f7b1cb2e907ba10e8409
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.
5 #ifndef CHROME_FRAME_TEST_TEST_SERVER_H_
6 #define CHROME_FRAME_TEST_TEST_SERVER_H_
8 // Implementation of an HTTP server for tests.
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.
11 // The server uses two basic concepts, a request and a response.
12 // The Response interface represents an item (e.g. a document) available from
13 // the server. A Request object represents a request from a client (e.g. a
14 // browser). There are several basic Response classes implemented in this file,
15 // all derived from the Response interface.
17 // Here's a simple example that starts a web server that can serve up
18 // a single document (http://<server.host()>:1337/foo).
19 // All other requests will get a 404.
21 // MessageLoopForUI loop;
22 // test_server::SimpleWebServer server(1337);
23 // test_server::SimpleResponse document("/foo", "Hello World!");
24 // test_server.AddResponse(&document);
25 // loop.MessageLoop::Run();
27 // To close the web server, just go to http://<server.host()>:1337/quit.
29 // All Response classes count how many times they have been accessed. Just
30 // call Response::accessed().
32 // To implement a custom response object (e.g. to match against a request
33 // based on some data, serve up dynamic content or take some action on 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
36 // response objects.
38 #include <list>
39 #include <string>
41 #include "base/basictypes.h"
42 #include "base/file_util.h"
43 #include "base/message_loop.h"
44 #include "net/base/stream_listen_socket.h"
46 namespace test_server {
48 class Request {
49 public:
50 Request() : content_length_(0) {
53 void ParseHeaders(const std::string& headers);
55 const std::string& method() const {
56 return method_;
59 const std::string& path() const {
60 return path_;
63 // Returns the argument section of a GET path.
64 // Note: does currently not work for POST request.
65 std::string arguments() const {
66 std::string ret;
67 std::string::size_type pos = path_.find('?');
68 if (pos != std::string::npos)
69 ret = path_.substr(pos + 1);
70 return ret;
73 const std::string& headers() const {
74 return headers_;
77 const std::string& content() const {
78 return content_;
81 size_t content_length() const {
82 return content_length_;
85 bool AllContentReceived() const {
86 return method_.length() && content_.size() >= content_length_;
89 void OnDataReceived(const std::string& data);
91 protected:
92 std::string method_;
93 std::string path_;
94 std::string version_;
95 std::string headers_;
96 std::string content_;
97 size_t content_length_;
99 private:
100 DISALLOW_COPY_AND_ASSIGN(Request);
103 // Manages request headers for a single request.
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
106 // shut down.
107 class Connection {
108 public:
109 explicit Connection(net::StreamListenSocket* sock) : socket_(sock) {
112 ~Connection() {
115 bool IsSame(const net::StreamListenSocket* socket) const {
116 return socket_ == socket;
119 const Request& request() const {
120 return request_;
123 Request& request() {
124 return request_;
127 void OnSocketClosed() {
128 socket_ = NULL;
131 protected:
132 scoped_refptr<net::StreamListenSocket> socket_;
133 Request request_;
135 private:
136 DISALLOW_COPY_AND_ASSIGN(Connection);
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.
141 class Response {
142 public:
143 Response() : accessed_(0) {
146 virtual ~Response() {
149 // Returns true if this response object should be used for a given request.
150 virtual bool Matches(const Request& r) const = 0;
152 // Response objects can optionally supply their own HTTP headers, completely
153 // bypassing the default ones.
154 virtual bool GetCustomHeaders(std::string* headers) const {
155 return false;
158 // Optionally provide a content type. Return false if you don't specify
159 // a content type.
160 virtual bool GetContentType(std::string* content_type) const {
161 return false;
164 virtual size_t ContentLength() const {
165 return 0;
168 virtual void WriteContents(net::StreamListenSocket* socket) const {
171 virtual void IncrementAccessCounter() {
172 accessed_++;
175 size_t accessed() const {
176 return accessed_;
179 protected:
180 size_t accessed_;
182 private:
183 DISALLOW_COPY_AND_ASSIGN(Response);
186 // Partial implementation of Response that matches a request's path.
187 // This is just a convenience implementation for the boilerplate implementation
188 // of Matches(). Don't instantiate directly.
189 class ResponseForPath : public Response {
190 public:
191 explicit ResponseForPath(const char* request_path)
192 : request_path_(request_path) {
195 virtual ~ResponseForPath();
197 virtual bool Matches(const Request& r) const {
198 std::string path = r.path();
199 std::string::size_type pos = path.find('?');
200 if (pos != std::string::npos)
201 path = path.substr(0, pos);
202 return path.compare(request_path_) == 0;
205 protected:
206 std::string request_path_;
208 private:
209 DISALLOW_COPY_AND_ASSIGN(ResponseForPath);
212 // A very basic implementation of a response.
213 // A simple response matches a single document path on the server
214 // (e.g. "/foo") and returns a document in the form of a string.
215 class SimpleResponse : public ResponseForPath {
216 public:
217 SimpleResponse(const char* request_path, const std::string& contents)
218 : ResponseForPath(request_path), contents_(contents) {
221 virtual ~SimpleResponse();
223 virtual void WriteContents(net::StreamListenSocket* socket) const {
224 socket->Send(contents_.c_str(), contents_.length(), false);
227 virtual size_t ContentLength() const {
228 return contents_.length();
231 protected:
232 std::string contents_;
234 private:
235 DISALLOW_COPY_AND_ASSIGN(SimpleResponse);
238 // To serve up files from the web server, create an instance of FileResponse
239 // and add it to the server's list of responses. The content type of the
240 // file will be determined by calling FindMimeFromData which examines the
241 // contents of the file and performs registry lookups.
242 class FileResponse : public ResponseForPath {
243 public:
244 FileResponse(const char* request_path, const FilePath& file_path)
245 : ResponseForPath(request_path), file_path_(file_path) {
248 virtual bool GetContentType(std::string* content_type) const;
249 virtual void WriteContents(net::StreamListenSocket* socket) const;
250 virtual size_t ContentLength() const;
252 protected:
253 FilePath file_path_;
254 mutable scoped_ptr<file_util::MemoryMappedFile> file_;
256 private:
257 DISALLOW_COPY_AND_ASSIGN(FileResponse);
260 // Returns a 302 (temporary redirect) to redirect the client from a path
261 // on the test server to a different URL.
262 class RedirectResponse : public ResponseForPath {
263 public:
264 RedirectResponse(const char* request_path, const std::string& redirect_url)
265 : ResponseForPath(request_path), redirect_url_(redirect_url) {
268 virtual bool GetCustomHeaders(std::string* headers) const;
270 protected:
271 std::string redirect_url_;
273 private:
274 DISALLOW_COPY_AND_ASSIGN(RedirectResponse);
277 // typedef for a list of connections. Used by SimpleWebServer.
278 typedef std::list<Connection*> ConnectionList;
280 // Implementation of a simple http server.
281 // Before creating an instance of the server, make sure the current thread
282 // has a message loop.
283 class SimpleWebServer : public net::StreamListenSocket::Delegate {
284 public:
285 // Constructs a server listening at the given port on a local IPv4 address.
286 // An address on a NIC is preferred over the loopback address.
287 explicit SimpleWebServer(int port);
289 // Constructs a server listening at the given address:port.
290 SimpleWebServer(const std::string& address, int port);
291 virtual ~SimpleWebServer();
293 void AddResponse(Response* response);
295 // Ownership of response objects is by default assumed to be outside
296 // of the SimpleWebServer class.
297 // However, if the caller doesn't wish to maintain a list of response objects
298 // but rather let this class hold the only references to those objects,
299 // the caller can call this method to delete the objects as part of
300 // the cleanup process.
301 void DeleteAllResponses();
303 // StreamListenSocket::Delegate overrides.
304 virtual void DidAccept(net::StreamListenSocket* server,
305 net::StreamListenSocket* connection);
306 virtual void DidRead(net::StreamListenSocket* connection,
307 const char* data,
308 int len);
309 virtual void DidClose(net::StreamListenSocket* sock);
311 // Returns the host on which the server is listening. This is suitable for
312 // use in URLs for resources served by this instance.
313 const std::string& host() const {
314 return host_;
317 const ConnectionList& connections() const {
318 return connections_;
321 protected:
322 class QuitResponse : public SimpleResponse {
323 public:
324 QuitResponse()
325 : SimpleResponse("/quit", "So long and thanks for all the fish.") {
328 virtual void WriteContents(net::StreamListenSocket* socket) const {
329 SimpleResponse::WriteContents(socket);
330 MessageLoop::current()->Quit();
334 Response* FindResponse(const Request& request) const;
335 Connection* FindConnection(const net::StreamListenSocket* socket) const;
337 std::string host_;
338 scoped_refptr<net::StreamListenSocket> server_;
339 ConnectionList connections_;
340 std::list<Response*> responses_;
341 QuitResponse quit_;
343 private:
344 void Construct(const std::string& address, int port);
345 DISALLOW_COPY_AND_ASSIGN(SimpleWebServer);
348 // Simple class holding incoming HTTP request. Can send the HTTP response
349 // at different rate - small chunks, on regular interval.
350 class ConfigurableConnection : public base::RefCounted<ConfigurableConnection> {
351 public:
352 struct SendOptions {
353 enum Speed { IMMEDIATE, DELAYED, IMMEDIATE_HEADERS_DELAYED_CONTENT };
354 SendOptions() : speed_(IMMEDIATE), chunk_size_(0), timeout_(0) { }
355 SendOptions(Speed speed, int chunk_size, int64 timeout)
356 : speed_(speed), chunk_size_(chunk_size), timeout_(timeout) {
359 Speed speed_;
360 int chunk_size_;
361 int64 timeout_;
364 explicit ConfigurableConnection(net::StreamListenSocket* sock)
365 : socket_(sock),
366 cur_pos_(0) {}
368 // Send HTTP response with provided |headers| and |content|. Appends
369 // "Context-Length:" header if the |content| is not empty.
370 void Send(const std::string& headers, const std::string& content);
372 // Send HTTP response with provided |headers| and |content|. Appends
373 // "Context-Length:" header if the |content| is not empty.
374 // Use the |options| to tweak the network speed behaviour.
375 void SendWithOptions(const std::string& headers, const std::string& content,
376 const SendOptions& options);
378 private:
379 friend class HTTPTestServer;
380 // Sends a chunk of the response and queues itself as a task for sending
381 // next chunk of |data_|.
382 void SendChunk();
384 // Closes the connection by releasing this instance's reference on its socket.
385 void Close();
387 scoped_refptr<net::StreamListenSocket> socket_;
388 Request r_;
389 SendOptions options_;
390 std::string data_;
391 int cur_pos_;
393 DISALLOW_COPY_AND_ASSIGN(ConfigurableConnection);
396 // Simple class used as a base class for mock webserver.
397 // Override virtual functions Get and Post and use passed ConfigurableConnection
398 // instance to send the response.
399 class HTTPTestServer : public net::StreamListenSocket::Delegate {
400 public:
401 HTTPTestServer(int port, const std::wstring& address, FilePath root_dir);
402 virtual ~HTTPTestServer();
404 // HTTP GET request is received. Override in derived classes.
405 // |connection| can be used to send the response.
406 virtual void Get(ConfigurableConnection* connection,
407 const std::wstring& path, const Request& r) = 0;
409 // HTTP POST request is received. Override in derived classes.
410 // |connection| can be used to send the response
411 virtual void Post(ConfigurableConnection* connection,
412 const std::wstring& path, const Request& r) = 0;
414 // Return the appropriate url with the specified path for this server.
415 std::wstring Resolve(const std::wstring& path);
417 FilePath root_dir() { return root_dir_; }
419 protected:
420 int port_;
421 std::wstring address_;
422 FilePath root_dir_;
424 private:
425 typedef std::list<scoped_refptr<ConfigurableConnection> > ConnectionList;
426 ConnectionList::iterator FindConnection(
427 const net::StreamListenSocket* socket);
428 scoped_refptr<ConfigurableConnection> ConnectionFromSocket(
429 const net::StreamListenSocket* socket);
431 // StreamListenSocket::Delegate overrides.
432 virtual void DidAccept(net::StreamListenSocket* server,
433 net::StreamListenSocket* socket);
434 virtual void DidRead(net::StreamListenSocket* socket,
435 const char* data, int len);
436 virtual void DidClose(net::StreamListenSocket* socket);
438 scoped_refptr<net::StreamListenSocket> server_;
439 ConnectionList connection_list_;
441 DISALLOW_COPY_AND_ASSIGN(HTTPTestServer);
444 } // namespace test_server
446 #endif // CHROME_FRAME_TEST_TEST_SERVER_H_