• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 NET_URL_REQUEST_TEST_URL_FETCHER_FACTORY_H_
6 #define NET_URL_REQUEST_TEST_URL_FETCHER_FACTORY_H_
7 
8 #include <list>
9 #include <map>
10 #include <string>
11 #include <utility>
12 
13 #include "base/basictypes.h"
14 #include "base/callback.h"
15 #include "base/compiler_specific.h"
16 #include "base/files/file_path.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/threading/non_thread_safe.h"
20 #include "net/http/http_request_headers.h"
21 #include "net/http/http_status_code.h"
22 #include "net/url_request/url_fetcher_factory.h"
23 #include "net/url_request/url_request_status.h"
24 #include "url/gurl.h"
25 
26 namespace net {
27 
28 // Changes URLFetcher's Factory for the lifetime of the object.
29 // Note that this scoper cannot be nested (to make it even harder to misuse).
30 class ScopedURLFetcherFactory : public base::NonThreadSafe {
31  public:
32   explicit ScopedURLFetcherFactory(URLFetcherFactory* factory);
33   virtual ~ScopedURLFetcherFactory();
34 
35  private:
36   DISALLOW_COPY_AND_ASSIGN(ScopedURLFetcherFactory);
37 };
38 
39 // TestURLFetcher and TestURLFetcherFactory are used for testing consumers of
40 // URLFetcher. TestURLFetcherFactory is a URLFetcherFactory that creates
41 // TestURLFetchers. TestURLFetcher::Start is overriden to do nothing. It is
42 // expected that you'll grab the delegate from the TestURLFetcher and invoke
43 // the callback method when appropriate. In this way it's easy to mock a
44 // URLFetcher.
45 // Typical usage:
46 //   // TestURLFetcher requires a MessageLoop.
47 //   MessageLoop message_loop;
48 //   // And an IO thread to release URLRequestContextGetter in URLFetcher::Core.
49 //   BrowserThreadImpl io_thread(BrowserThread::IO, &message_loop);
50 //   // Create factory (it automatically sets itself as URLFetcher's factory).
51 //   TestURLFetcherFactory factory;
52 //   // Do something that triggers creation of a URLFetcher.
53 //   ...
54 //   TestURLFetcher* fetcher = factory.GetFetcherByID(expected_id);
55 //   DCHECK(fetcher);
56 //   // Notify delegate with whatever data you want.
57 //   fetcher->delegate()->OnURLFetchComplete(...);
58 //   // Make sure consumer of URLFetcher does the right thing.
59 //   ...
60 //
61 // Note: if you don't know when your request objects will be created you
62 // might want to use the FakeURLFetcher and FakeURLFetcherFactory classes
63 // below.
64 
65 class TestURLFetcherFactory;
66 class TestURLFetcher : public URLFetcher {
67  public:
68   // Interface for tests to intercept production code classes using URLFetcher.
69   // Allows even-driven mock server classes to analyze the correctness of
70   // requests / uploads events and forge responses back at the right moment.
71   class DelegateForTests {
72    public:
73     // Callback issued correspondingly to the call to the |Start()| method.
74     virtual void OnRequestStart(int fetcher_id) = 0;
75 
76     // Callback issued correspondingly to the call to |AppendChunkToUpload|.
77     // Uploaded chunks can be retrieved with the |upload_chunks()| getter.
78     virtual void OnChunkUpload(int fetcher_id) = 0;
79 
80     // Callback issued correspondingly to the destructor.
81     virtual void OnRequestEnd(int fetcher_id) = 0;
82   };
83 
84   TestURLFetcher(int id,
85                  const GURL& url,
86                  URLFetcherDelegate* d);
87   virtual ~TestURLFetcher();
88 
89   // URLFetcher implementation
90   virtual void SetUploadData(const std::string& upload_content_type,
91                              const std::string& upload_content) OVERRIDE;
92   virtual void SetUploadFilePath(
93       const std::string& upload_content_type,
94       const base::FilePath& file_path,
95       uint64 range_offset,
96       uint64 range_length,
97       scoped_refptr<base::TaskRunner> file_task_runner) OVERRIDE;
98   virtual void SetChunkedUpload(
99       const std::string& upload_content_type) OVERRIDE;
100   // Overriden to cache the chunks uploaded. Caller can read back the uploaded
101   // chunks with the upload_chunks() accessor.
102   virtual void AppendChunkToUpload(const std::string& data,
103                                    bool is_last_chunk) OVERRIDE;
104   virtual void SetLoadFlags(int load_flags) OVERRIDE;
105   virtual int GetLoadFlags() const OVERRIDE;
106   virtual void SetReferrer(const std::string& referrer) OVERRIDE;
107   virtual void SetExtraRequestHeaders(
108       const std::string& extra_request_headers) OVERRIDE;
109   virtual void AddExtraRequestHeader(const std::string& header_line) OVERRIDE;
110   virtual void GetExtraRequestHeaders(
111       HttpRequestHeaders* headers) const OVERRIDE;
112   virtual void SetRequestContext(
113       URLRequestContextGetter* request_context_getter) OVERRIDE;
114   virtual void SetFirstPartyForCookies(
115       const GURL& first_party_for_cookies) OVERRIDE;
116   virtual void SetURLRequestUserData(
117       const void* key,
118       const CreateDataCallback& create_data_callback) OVERRIDE;
119   virtual void SetStopOnRedirect(bool stop_on_redirect) OVERRIDE;
120   virtual void SetAutomaticallyRetryOn5xx(bool retry) OVERRIDE;
121   virtual void SetMaxRetriesOn5xx(int max_retries) OVERRIDE;
122   virtual int GetMaxRetriesOn5xx() const OVERRIDE;
123   virtual base::TimeDelta GetBackoffDelay() const OVERRIDE;
124   virtual void SetAutomaticallyRetryOnNetworkChanges(int max_retries) OVERRIDE;
125   virtual void SaveResponseToFileAtPath(
126       const base::FilePath& file_path,
127       scoped_refptr<base::SequencedTaskRunner> file_task_runner) OVERRIDE;
128   virtual void SaveResponseToTemporaryFile(
129       scoped_refptr<base::SequencedTaskRunner> file_task_runner) OVERRIDE;
130   virtual void SaveResponseWithWriter(
131       scoped_ptr<URLFetcherResponseWriter> response_writer) OVERRIDE;
132   virtual HttpResponseHeaders* GetResponseHeaders() const OVERRIDE;
133   virtual HostPortPair GetSocketAddress() const OVERRIDE;
134   virtual bool WasFetchedViaProxy() const OVERRIDE;
135   virtual void Start() OVERRIDE;
136 
137   // URL we were created with. Because of how we're using URLFetcher GetURL()
138   // always returns an empty URL. Chances are you'll want to use
139   // GetOriginalURL() in your tests.
140   virtual const GURL& GetOriginalURL() const OVERRIDE;
141   virtual const GURL& GetURL() const OVERRIDE;
142   virtual const URLRequestStatus& GetStatus() const OVERRIDE;
143   virtual int GetResponseCode() const OVERRIDE;
144   virtual const ResponseCookies& GetCookies() const OVERRIDE;
145   virtual void ReceivedContentWasMalformed() OVERRIDE;
146   // Override response access functions to return fake data.
147   virtual bool GetResponseAsString(
148       std::string* out_response_string) const OVERRIDE;
149   virtual bool GetResponseAsFilePath(
150       bool take_ownership, base::FilePath* out_response_path) const OVERRIDE;
151 
152   // Sets owner of this class.  Set it to a non-NULL value if you want
153   // to automatically unregister this fetcher from the owning factory
154   // upon destruction.
set_owner(TestURLFetcherFactory * owner)155   void set_owner(TestURLFetcherFactory* owner) { owner_ = owner; }
156 
157   // Unique ID in our factory.
id()158   int id() const { return id_; }
159 
160   // Returns the data uploaded on this URLFetcher.
upload_data()161   const std::string& upload_data() const { return upload_data_; }
upload_file_path()162   const base::FilePath& upload_file_path() const { return upload_file_path_; }
163 
164   // Returns the chunks of data uploaded on this URLFetcher.
upload_chunks()165   const std::list<std::string>& upload_chunks() const { return chunks_; }
166 
167   // Checks whether the last call to |AppendChunkToUpload(...)| was final.
did_receive_last_chunk()168   bool did_receive_last_chunk() const { return did_receive_last_chunk_; }
169 
170   // Returns the delegate installed on the URLFetcher.
delegate()171   URLFetcherDelegate* delegate() const { return delegate_; }
172 
set_url(const GURL & url)173   void set_url(const GURL& url) { fake_url_ = url; }
174   void set_status(const URLRequestStatus& status);
set_response_code(int response_code)175   void set_response_code(int response_code) {
176     fake_response_code_ = response_code;
177   }
set_cookies(const ResponseCookies & c)178   void set_cookies(const ResponseCookies& c) { fake_cookies_ = c; }
179   void set_was_fetched_via_proxy(bool flag);
180   void set_response_headers(scoped_refptr<HttpResponseHeaders> headers);
181   void set_backoff_delay(base::TimeDelta backoff_delay);
182   void SetDelegateForTests(DelegateForTests* delegate_for_tests);
183 
184   // Set string data.
185   void SetResponseString(const std::string& response);
186 
187   // Set File data.
188   void SetResponseFilePath(const base::FilePath& path);
189 
190  private:
191   enum ResponseDestinationType {
192     STRING,  // Default: In a std::string
193     TEMP_FILE  // Write to a temp file
194   };
195 
196   TestURLFetcherFactory* owner_;
197   const int id_;
198   const GURL original_url_;
199   URLFetcherDelegate* delegate_;
200   DelegateForTests* delegate_for_tests_;
201   std::string upload_data_;
202   base::FilePath upload_file_path_;
203   std::list<std::string> chunks_;
204   bool did_receive_last_chunk_;
205 
206   // User can use set_* methods to provide values returned by getters.
207   // Setting the real values is not possible, because the real class
208   // has no setters. The data is a private member of a class defined
209   // in a .cc file, so we can't get at it with friendship.
210   int fake_load_flags_;
211   GURL fake_url_;
212   URLRequestStatus fake_status_;
213   int fake_response_code_;
214   ResponseCookies fake_cookies_;
215   ResponseDestinationType fake_response_destination_;
216   std::string fake_response_string_;
217   base::FilePath fake_response_file_path_;
218   bool fake_was_fetched_via_proxy_;
219   scoped_refptr<HttpResponseHeaders> fake_response_headers_;
220   HttpRequestHeaders fake_extra_request_headers_;
221   int fake_max_retries_;
222   base::TimeDelta fake_backoff_delay_;
223 
224   DISALLOW_COPY_AND_ASSIGN(TestURLFetcher);
225 };
226 
227 typedef TestURLFetcher::DelegateForTests TestURLFetcherDelegateForTests;
228 
229 // Simple URLFetcherFactory method that creates TestURLFetchers. All fetchers
230 // are registered in a map by the id passed to the create method.
231 // Optionally, a fetcher may be automatically unregistered from the map upon
232 // its destruction.
233 class TestURLFetcherFactory : public URLFetcherFactory,
234                               public ScopedURLFetcherFactory {
235  public:
236   TestURLFetcherFactory();
237   virtual ~TestURLFetcherFactory();
238 
239   virtual URLFetcher* CreateURLFetcher(
240       int id,
241       const GURL& url,
242       URLFetcher::RequestType request_type,
243       URLFetcherDelegate* d) OVERRIDE;
244   TestURLFetcher* GetFetcherByID(int id) const;
245   void RemoveFetcherFromMap(int id);
246   void SetDelegateForTests(TestURLFetcherDelegateForTests* delegate_for_tests);
set_remove_fetcher_on_delete(bool remove_fetcher_on_delete)247   void set_remove_fetcher_on_delete(bool remove_fetcher_on_delete) {
248     remove_fetcher_on_delete_ = remove_fetcher_on_delete;
249   }
250 
251  private:
252   // Maps from id passed to create to the returned URLFetcher.
253   typedef std::map<int, TestURLFetcher*> Fetchers;
254   Fetchers fetchers_;
255   TestURLFetcherDelegateForTests* delegate_for_tests_;
256   // Whether to automatically unregister a fetcher from this factory upon its
257   // destruction, false by default.
258   bool remove_fetcher_on_delete_;
259 
260   DISALLOW_COPY_AND_ASSIGN(TestURLFetcherFactory);
261 };
262 
263 // The FakeURLFetcher and FakeURLFetcherFactory classes are similar to the
264 // ones above but don't require you to know when exactly the URLFetcher objects
265 // will be created.
266 //
267 // These classes let you set pre-baked HTTP responses for particular URLs.
268 // E.g., if the user requests http://a.com/ then respond with an HTTP/500.
269 //
270 // We assume that the thread that is calling Start() on the URLFetcher object
271 // has a message loop running.
272 
273 // FakeURLFetcher can be used to create a URLFetcher that will emit a fake
274 // response when started. This class can be used in place of an actual
275 // URLFetcher.
276 //
277 // Example usage:
278 //  FakeURLFetcher fake_fetcher("http://a.com", some_delegate,
279 //                              "<html><body>hello world</body></html>",
280 //                              HTTP_OK);
281 //
282 // // Will schedule a call to some_delegate->OnURLFetchComplete(&fake_fetcher).
283 // fake_fetcher.Start();
284 class FakeURLFetcher : public TestURLFetcher {
285  public:
286   // Normal URL fetcher constructor but also takes in a pre-baked response.
287   FakeURLFetcher(const GURL& url,
288                  URLFetcherDelegate* d,
289                  const std::string& response_data,
290                  HttpStatusCode response_code,
291                  URLRequestStatus::Status status);
292 
293   // Start the request.  This will call the given delegate asynchronously
294   // with the pre-baked response as parameter.
295   virtual void Start() OVERRIDE;
296 
297   virtual const GURL& GetURL() const OVERRIDE;
298 
299   virtual ~FakeURLFetcher();
300 
301  private:
302   // This is the method which actually calls the delegate that is passed in the
303   // constructor.
304   void RunDelegate();
305 
306   base::WeakPtrFactory<FakeURLFetcher> weak_factory_;
307 
308   DISALLOW_COPY_AND_ASSIGN(FakeURLFetcher);
309 };
310 
311 
312 // FakeURLFetcherFactory is a factory for FakeURLFetcher objects. When
313 // instantiated, it sets itself up as the default URLFetcherFactory. Fake
314 // responses for given URLs can be set using SetFakeResponse.
315 //
316 // This class is not thread-safe.  You should not call SetFakeResponse or
317 // ClearFakeResponse at the same time you call CreateURLFetcher.  However, it is
318 // OK to start URLFetcher objects while setting or clearing fake responses
319 // since already created URLFetcher objects will not be affected by any changes
320 // made to the fake responses (once a URLFetcher object is created you cannot
321 // change its fake response).
322 //
323 // Example usage:
324 //  FakeURLFetcherFactory factory;
325 //
326 //  // You know that class SomeService will request http://a.com/success and you
327 //  // want to respond with a simple html page and an HTTP/200 code.
328 //  factory.SetFakeResponse("http://a.com/success",
329 //                          "<html><body>hello world</body></html>",
330 //                          HTTP_OK,
331 //                          URLRequestStatus::SUCCESS);
332 //  // You know that class SomeService will request url http://a.com/servererror
333 //  // and you want to test the service class by returning a server error.
334 //  factory.SetFakeResponse("http://a.com/servererror",
335 //                          "",
336 //                          HTTP_INTERNAL_SERVER_ERROR,
337 //                          URLRequestStatus::SUCCESS);
338 //  // You know that class SomeService will request url http://a.com/autherror
339 //  // and you want to test the service class by returning a specific error
340 //  // code, say, a HTTP/401 error.
341 //  factory.SetFakeResponse("http://a.com/autherror",
342 //                          "some_response",
343 //                          HTTP_UNAUTHORIZED,
344 //                          URLRequestStatus::SUCCESS);
345 //
346 //  // You know that class SomeService will request url http://a.com/failure
347 //  // and you want to test the service class by returning a failure in the
348 //  // network layer.
349 //  factory.SetFakeResponse("http://a.com/failure",
350 //                          "",
351 //                          HTTP_INTERNAL_SERVER_ERROR,
352 //                          URLRequestStatus::FAILURE);
353 //
354 //  SomeService service;
355 //  service.Run();  // Will eventually request these three URLs.
356 class FakeURLFetcherFactory : public URLFetcherFactory,
357                               public ScopedURLFetcherFactory {
358  public:
359   // Parameters to FakeURLFetcherCreator: url, delegate, response_data,
360   //                                      response_code
361   // |url| URL for instantiated FakeURLFetcher
362   // |delegate| Delegate for FakeURLFetcher
363   // |response_data| response data for FakeURLFetcher
364   // |response_code| response code for FakeURLFetcher
365   // |status| URL fetch status for FakeURLFetcher
366   // These arguments should by default be used in instantiating FakeURLFetcher
367   // like so:
368   // new FakeURLFetcher(url, delegate, response_data, response_code, status)
369   typedef base::Callback<scoped_ptr<FakeURLFetcher>(
370       const GURL&,
371       URLFetcherDelegate*,
372       const std::string&,
373       HttpStatusCode,
374       URLRequestStatus::Status)> FakeURLFetcherCreator;
375 
376   // |default_factory|, which can be NULL, is a URLFetcherFactory that
377   // will be used to construct a URLFetcher in case the URL being created
378   // has no pre-baked response. If it is NULL, a URLFetcherImpl will be
379   // created in this case.
380   explicit FakeURLFetcherFactory(URLFetcherFactory* default_factory);
381 
382   // |default_factory|, which can be NULL, is a URLFetcherFactory that
383   // will be used to construct a URLFetcher in case the URL being created
384   // has no pre-baked response. If it is NULL, a URLFetcherImpl will be
385   // created in this case.
386   // |creator| is a callback that returns will be called to create a
387   // FakeURLFetcher if a response is found to a given URL. It can be
388   // set to MakeFakeURLFetcher.
389   FakeURLFetcherFactory(URLFetcherFactory* default_factory,
390                         const FakeURLFetcherCreator& creator);
391 
392   virtual ~FakeURLFetcherFactory();
393 
394   // If no fake response is set for the given URL this method will delegate the
395   // call to |default_factory_| if it is not NULL, or return NULL if it is
396   // NULL.
397   // Otherwise, it will return a URLFetcher object which will respond with the
398   // pre-baked response that the client has set by calling SetFakeResponse().
399   virtual URLFetcher* CreateURLFetcher(
400       int id,
401       const GURL& url,
402       URLFetcher::RequestType request_type,
403       URLFetcherDelegate* d) OVERRIDE;
404 
405   // Sets the fake response for a given URL. The |response_data| may be empty.
406   // The |response_code| may be any HttpStatusCode. For instance, HTTP_OK will
407   // return an HTTP/200 and HTTP_INTERNAL_SERVER_ERROR will return an HTTP/500.
408   // The |status| argument may be any URLRequestStatus::Status value. Typically,
409   // requests that return a valid HttpStatusCode have the SUCCESS status, while
410   // requests that indicate a failure to connect to the server have the FAILED
411   // status.
412   void SetFakeResponse(const GURL& url,
413                        const std::string& response_data,
414                        HttpStatusCode response_code,
415                        URLRequestStatus::Status status);
416 
417   // Clear all the fake responses that were previously set via
418   // SetFakeResponse().
419   void ClearFakeResponses();
420 
421  private:
422   struct FakeURLResponse {
423     std::string response_data;
424     HttpStatusCode response_code;
425     URLRequestStatus::Status status;
426   };
427   typedef std::map<GURL, FakeURLResponse> FakeResponseMap;
428 
429   const FakeURLFetcherCreator creator_;
430   FakeResponseMap fake_responses_;
431   URLFetcherFactory* const default_factory_;
432 
433   static scoped_ptr<FakeURLFetcher> DefaultFakeURLFetcherCreator(
434       const GURL& url,
435       URLFetcherDelegate* delegate,
436       const std::string& response_data,
437       HttpStatusCode response_code,
438       URLRequestStatus::Status status);
439   DISALLOW_COPY_AND_ASSIGN(FakeURLFetcherFactory);
440 };
441 
442 // This is an implementation of URLFetcherFactory that will create a
443 // URLFetcherImpl. It can be use in conjunction with a FakeURLFetcherFactory in
444 // integration tests to control the behavior of some requests but execute
445 // all the other ones.
446 class URLFetcherImplFactory : public URLFetcherFactory {
447  public:
448   URLFetcherImplFactory();
449   virtual ~URLFetcherImplFactory();
450 
451   // This method will create a real URLFetcher.
452   virtual URLFetcher* CreateURLFetcher(
453       int id,
454       const GURL& url,
455       URLFetcher::RequestType request_type,
456       URLFetcherDelegate* d) OVERRIDE;
457 
458 };
459 
460 }  // namespace net
461 
462 #endif  // NET_URL_REQUEST_TEST_URL_FETCHER_FACTORY_H_
463