- add sources.
[platform/framework/web/crosswalk.git] / src / chrome_frame / test / test_server.h
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 #ifndef CHROME_FRAME_TEST_TEST_SERVER_H_
6 #define CHROME_FRAME_TEST_TEST_SERVER_H_
7
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.
16 //
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.
20 //
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();
26 //
27 // To close the web server, just go to http://<server.host()>:1337/quit.
28 //
29 // All Response classes count how many times they have been accessed.  Just
30 // call Response::accessed().
31 //
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.
37
38 #include <list>
39 #include <string>
40
41 #include "base/basictypes.h"
42 #include "base/files/file_path.h"
43 #include "base/files/memory_mapped_file.h"
44 #include "base/message_loop/message_loop.h"
45 #include "net/socket/stream_listen_socket.h"
46
47 namespace test_server {
48
49 class Request {
50  public:
51   Request() : content_length_(0) {
52   }
53
54   void ParseHeaders(const std::string& headers);
55
56   const std::string& method() const {
57     return method_;
58   }
59
60   const std::string& path() const {
61     return path_;
62   }
63
64   // Returns the argument section of a GET path.
65   // Note: does currently not work for POST request.
66   std::string arguments() const {
67     std::string ret;
68     std::string::size_type pos = path_.find('?');
69     if (pos != std::string::npos)
70       ret = path_.substr(pos + 1);
71     return ret;
72   }
73
74   const std::string& headers() const {
75     return headers_;
76   }
77
78   const std::string& content() const {
79     return content_;
80   }
81
82   size_t content_length() const {
83     return content_length_;
84   }
85
86   bool AllContentReceived() const {
87     return method_.length() && content_.size() >= content_length_;
88   }
89
90   void OnDataReceived(const std::string& data);
91
92  protected:
93   std::string method_;
94   std::string path_;
95   std::string version_;
96   std::string headers_;
97   std::string content_;
98   size_t content_length_;
99
100  private:
101   DISALLOW_COPY_AND_ASSIGN(Request);
102 };
103
104 // Manages request headers for a single request.
105 // For each successful request that's made, the server will keep an instance
106 // of this class so that they can be checked even after the server has been
107 // shut down.
108 class Connection {
109  public:
110   explicit Connection(scoped_ptr<net::StreamListenSocket> sock)
111       : socket_(sock.Pass()) {
112   }
113
114   ~Connection() {
115   }
116
117   bool IsSame(const net::StreamListenSocket* socket) const {
118     return socket_ == socket;
119   }
120
121   const Request& request() const {
122     return request_;
123   }
124
125   Request& request() {
126     return request_;
127   }
128
129   void OnSocketClosed() {
130     socket_.reset();
131   }
132
133  protected:
134   scoped_ptr<net::StreamListenSocket> socket_;
135   Request request_;
136
137  private:
138   DISALLOW_COPY_AND_ASSIGN(Connection);
139 };
140
141 // Abstract interface with default implementations for some of the methods and
142 // a counter for how many times the response object has served requests.
143 class Response {
144  public:
145   Response() : accessed_(0) {
146   }
147
148   virtual ~Response() {
149   }
150
151   // Returns true if this response object should be used for a given request.
152   virtual bool Matches(const Request& r) const = 0;
153
154   // Response objects can optionally supply their own HTTP headers, completely
155   // bypassing the default ones.
156   virtual bool GetCustomHeaders(std::string* headers) const {
157     return false;
158   }
159
160   // Optionally provide a content type.  Return false if you don't specify
161   // a content type.
162   virtual bool GetContentType(std::string* content_type) const {
163     return false;
164   }
165
166   virtual size_t ContentLength() const {
167     return 0;
168   }
169
170   virtual void WriteContents(net::StreamListenSocket* socket) const {
171   }
172
173   virtual void IncrementAccessCounter() {
174     accessed_++;
175   }
176
177   size_t accessed() const {
178     return accessed_;
179   }
180
181  protected:
182   size_t accessed_;
183
184  private:
185   DISALLOW_COPY_AND_ASSIGN(Response);
186 };
187
188 // Partial implementation of Response that matches a request's path.
189 // This is just a convenience implementation for the boilerplate implementation
190 // of Matches().  Don't instantiate directly.
191 class ResponseForPath : public Response {
192  public:
193   explicit ResponseForPath(const char* request_path)
194       : request_path_(request_path) {
195   }
196
197   virtual ~ResponseForPath();
198
199   virtual bool Matches(const Request& r) const {
200     std::string path = r.path();
201     std::string::size_type pos = path.find('?');
202     if (pos != std::string::npos)
203       path = path.substr(0, pos);
204     return path.compare(request_path_) == 0;
205   }
206
207  protected:
208   std::string request_path_;
209
210  private:
211   DISALLOW_COPY_AND_ASSIGN(ResponseForPath);
212 };
213
214 // A very basic implementation of a response.
215 // A simple response matches a single document path on the server
216 // (e.g. "/foo") and returns a document in the form of a string.
217 class SimpleResponse : public ResponseForPath {
218  public:
219   SimpleResponse(const char* request_path, const std::string& contents)
220       : ResponseForPath(request_path), contents_(contents) {
221   }
222
223   virtual ~SimpleResponse();
224
225   virtual void WriteContents(net::StreamListenSocket* socket) const {
226     socket->Send(contents_.c_str(), contents_.length(), false);
227   }
228
229   virtual size_t ContentLength() const {
230     return contents_.length();
231   }
232
233  protected:
234   std::string contents_;
235
236  private:
237   DISALLOW_COPY_AND_ASSIGN(SimpleResponse);
238 };
239
240 // To serve up files from the web server, create an instance of FileResponse
241 // and add it to the server's list of responses.  The content type of the
242 // file will be determined by calling FindMimeFromData which examines the
243 // contents of the file and performs registry lookups.
244 class FileResponse : public ResponseForPath {
245  public:
246   FileResponse(const char* request_path, const base::FilePath& file_path)
247       : ResponseForPath(request_path), file_path_(file_path) {
248   }
249
250   virtual bool GetContentType(std::string* content_type) const;
251   virtual void WriteContents(net::StreamListenSocket* socket) const;
252   virtual size_t ContentLength() const;
253
254  protected:
255   base::FilePath file_path_;
256   mutable scoped_ptr<base::MemoryMappedFile> file_;
257
258  private:
259   DISALLOW_COPY_AND_ASSIGN(FileResponse);
260 };
261
262 // Returns a 302 (temporary redirect) to redirect the client from a path
263 // on the test server to a different URL.
264 class RedirectResponse : public ResponseForPath {
265  public:
266   RedirectResponse(const char* request_path, const std::string& redirect_url)
267       : ResponseForPath(request_path), redirect_url_(redirect_url) {
268   }
269
270   virtual bool GetCustomHeaders(std::string* headers) const;
271
272  protected:
273   std::string redirect_url_;
274
275  private:
276   DISALLOW_COPY_AND_ASSIGN(RedirectResponse);
277 };
278
279 // typedef for a list of connections.  Used by SimpleWebServer.
280 typedef std::list<Connection*> ConnectionList;
281
282 // Implementation of a simple http server.
283 // Before creating an instance of the server, make sure the current thread
284 // has a message loop.
285 class SimpleWebServer : public net::StreamListenSocket::Delegate {
286  public:
287   // Constructs a server listening at the given port on a local IPv4 address.
288   // An address on a NIC is preferred over the loopback address.
289   explicit SimpleWebServer(int port);
290
291   // Constructs a server listening at the given address:port.
292   SimpleWebServer(const std::string& address, int port);
293   virtual ~SimpleWebServer();
294
295   void AddResponse(Response* response);
296
297   // Ownership of response objects is by default assumed to be outside
298   // of the SimpleWebServer class.
299   // However, if the caller doesn't wish to maintain a list of response objects
300   // but rather let this class hold the only references to those objects,
301   // the caller can call this method to delete the objects as part of
302   // the cleanup process.
303   void DeleteAllResponses();
304
305   // StreamListenSocket::Delegate overrides.
306   virtual void DidAccept(net::StreamListenSocket* server,
307                          scoped_ptr<net::StreamListenSocket> connection);
308   virtual void DidRead(net::StreamListenSocket* connection,
309                        const char* data,
310                        int len);
311   virtual void DidClose(net::StreamListenSocket* sock);
312
313   // Returns the host on which the server is listening.  This is suitable for
314   // use in URLs for resources served by this instance.
315   const std::string& host() const {
316     return host_;
317   }
318
319   const ConnectionList& connections() const {
320     return connections_;
321   }
322
323  protected:
324   class QuitResponse : public SimpleResponse {
325    public:
326     QuitResponse()
327         : SimpleResponse("/quit", "So long and thanks for all the fish.") {
328     }
329
330     virtual void WriteContents(net::StreamListenSocket* socket) const {
331       SimpleResponse::WriteContents(socket);
332       base::MessageLoop::current()->Quit();
333     }
334   };
335
336   Response* FindResponse(const Request& request) const;
337   Connection* FindConnection(const net::StreamListenSocket* socket) const;
338
339   std::string host_;
340   scoped_ptr<net::StreamListenSocket> server_;
341   ConnectionList connections_;
342   std::list<Response*> responses_;
343   QuitResponse quit_;
344
345  private:
346   void Construct(const std::string& address, int port);
347   DISALLOW_COPY_AND_ASSIGN(SimpleWebServer);
348 };
349
350 // Simple class holding incoming HTTP request. Can send the HTTP response
351 // at different rate - small chunks, on regular interval.
352 class ConfigurableConnection : public base::RefCounted<ConfigurableConnection> {
353  public:
354   struct SendOptions {
355     enum Speed { IMMEDIATE, DELAYED, IMMEDIATE_HEADERS_DELAYED_CONTENT };
356     SendOptions() : speed_(IMMEDIATE), chunk_size_(0), timeout_(0) { }
357     SendOptions(Speed speed, int chunk_size, int64 timeout)
358         : speed_(speed), chunk_size_(chunk_size), timeout_(timeout) {
359     }
360
361     Speed speed_;
362     int chunk_size_;
363     int64 timeout_;
364   };
365
366   explicit ConfigurableConnection(scoped_ptr<net::StreamListenSocket> sock)
367       : socket_(sock.Pass()),
368         cur_pos_(0) {}
369
370   // Send HTTP response with provided |headers| and |content|. Appends
371   // "Context-Length:" header if the |content| is not empty.
372   void Send(const std::string& headers, const std::string& content);
373
374   // Send HTTP response with provided |headers| and |content|. Appends
375   // "Context-Length:" header if the |content| is not empty.
376   // Use the |options| to tweak the network speed behaviour.
377   void SendWithOptions(const std::string& headers, const std::string& content,
378                        const SendOptions& options);
379
380  private:
381   friend class HTTPTestServer;
382   // Sends a chunk of the response and queues itself as a task for sending
383   // next chunk of |data_|.
384   void SendChunk();
385
386   // Closes the connection by releasing this instance's reference on its socket.
387   void Close();
388
389   scoped_ptr<net::StreamListenSocket> socket_;
390   Request r_;
391   SendOptions options_;
392   std::string data_;
393   int cur_pos_;
394
395   DISALLOW_COPY_AND_ASSIGN(ConfigurableConnection);
396 };
397
398 // Simple class used as a base class for mock webserver.
399 // Override virtual functions Get and Post and use passed ConfigurableConnection
400 // instance to send the response.
401 class HTTPTestServer : public net::StreamListenSocket::Delegate {
402  public:
403   HTTPTestServer(int port, const std::wstring& address,
404                  base::FilePath root_dir);
405   virtual ~HTTPTestServer();
406
407   // HTTP GET request is received. Override in derived classes.
408   // |connection| can be used to send the response.
409   virtual void Get(ConfigurableConnection* connection,
410                    const std::wstring& path, const Request& r) = 0;
411
412   // HTTP POST request is received. Override in derived classes.
413   // |connection| can be used to send the response
414   virtual void Post(ConfigurableConnection* connection,
415                     const std::wstring& path, const Request& r) = 0;
416
417   // Return the appropriate url with the specified path for this server.
418   std::wstring Resolve(const std::wstring& path);
419
420   base::FilePath root_dir() { return root_dir_; }
421
422  protected:
423   int port_;
424   std::wstring address_;
425   base::FilePath root_dir_;
426
427  private:
428   typedef std::list<scoped_refptr<ConfigurableConnection> > ConnectionList;
429   ConnectionList::iterator FindConnection(
430       const net::StreamListenSocket* socket);
431   scoped_refptr<ConfigurableConnection> ConnectionFromSocket(
432       const net::StreamListenSocket* socket);
433
434   // StreamListenSocket::Delegate overrides.
435   virtual void DidAccept(net::StreamListenSocket* server,
436                          scoped_ptr<net::StreamListenSocket> socket);
437   virtual void DidRead(net::StreamListenSocket* socket,
438                        const char* data, int len);
439   virtual void DidClose(net::StreamListenSocket* socket);
440
441   scoped_ptr<net::StreamListenSocket> server_;
442   ConnectionList connection_list_;
443
444   DISALLOW_COPY_AND_ASSIGN(HTTPTestServer);
445 };
446
447 }  // namespace test_server
448
449 #endif  // CHROME_FRAME_TEST_TEST_SERVER_H_