Home | History | Annotate | Download | only in url_request
      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 SetReferrerPolicy(
    108       URLRequest::ReferrerPolicy referrer_policy) OVERRIDE;
    109   virtual void SetExtraRequestHeaders(
    110       const std::string& extra_request_headers) OVERRIDE;
    111   virtual void AddExtraRequestHeader(const std::string& header_line) 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   void GetExtraRequestHeaders(HttpRequestHeaders* headers) const;
    153 
    154   // Sets owner of this class.  Set it to a non-NULL value if you want
    155   // to automatically unregister this fetcher from the owning factory
    156   // upon destruction.
    157   void set_owner(TestURLFetcherFactory* owner) { owner_ = owner; }
    158 
    159   // Unique ID in our factory.
    160   int id() const { return id_; }
    161 
    162   // Returns the data uploaded on this URLFetcher.
    163   const std::string& upload_data() const { return upload_data_; }
    164   const base::FilePath& upload_file_path() const { return upload_file_path_; }
    165 
    166   // Returns the chunks of data uploaded on this URLFetcher.
    167   const std::list<std::string>& upload_chunks() const { return chunks_; }
    168 
    169   // Checks whether the last call to |AppendChunkToUpload(...)| was final.
    170   bool did_receive_last_chunk() const { return did_receive_last_chunk_; }
    171 
    172   // Returns the delegate installed on the URLFetcher.
    173   URLFetcherDelegate* delegate() const { return delegate_; }
    174 
    175   void set_url(const GURL& url) { fake_url_ = url; }
    176   void set_status(const URLRequestStatus& status);
    177   void set_response_code(int response_code) {
    178     fake_response_code_ = response_code;
    179   }
    180   void set_cookies(const ResponseCookies& c) { fake_cookies_ = c; }
    181   void set_was_fetched_via_proxy(bool flag);
    182   void set_response_headers(scoped_refptr<HttpResponseHeaders> headers);
    183   void set_backoff_delay(base::TimeDelta backoff_delay);
    184   void SetDelegateForTests(DelegateForTests* delegate_for_tests);
    185 
    186   // Set string data.
    187   void SetResponseString(const std::string& response);
    188 
    189   // Set File data.
    190   void SetResponseFilePath(const base::FilePath& path);
    191 
    192  private:
    193   enum ResponseDestinationType {
    194     STRING,  // Default: In a std::string
    195     TEMP_FILE  // Write to a temp file
    196   };
    197 
    198   TestURLFetcherFactory* owner_;
    199   const int id_;
    200   const GURL original_url_;
    201   URLFetcherDelegate* delegate_;
    202   DelegateForTests* delegate_for_tests_;
    203   std::string upload_data_;
    204   base::FilePath upload_file_path_;
    205   std::list<std::string> chunks_;
    206   bool did_receive_last_chunk_;
    207 
    208   // User can use set_* methods to provide values returned by getters.
    209   // Setting the real values is not possible, because the real class
    210   // has no setters. The data is a private member of a class defined
    211   // in a .cc file, so we can't get at it with friendship.
    212   int fake_load_flags_;
    213   GURL fake_url_;
    214   URLRequestStatus fake_status_;
    215   int fake_response_code_;
    216   ResponseCookies fake_cookies_;
    217   ResponseDestinationType fake_response_destination_;
    218   std::string fake_response_string_;
    219   base::FilePath fake_response_file_path_;
    220   bool fake_was_fetched_via_proxy_;
    221   scoped_refptr<HttpResponseHeaders> fake_response_headers_;
    222   HttpRequestHeaders fake_extra_request_headers_;
    223   int fake_max_retries_;
    224   base::TimeDelta fake_backoff_delay_;
    225   scoped_ptr<URLFetcherResponseWriter> response_writer_;
    226 
    227   DISALLOW_COPY_AND_ASSIGN(TestURLFetcher);
    228 };
    229 
    230 typedef TestURLFetcher::DelegateForTests TestURLFetcherDelegateForTests;
    231 
    232 // Simple URLFetcherFactory method that creates TestURLFetchers. All fetchers
    233 // are registered in a map by the id passed to the create method.
    234 // Optionally, a fetcher may be automatically unregistered from the map upon
    235 // its destruction.
    236 class TestURLFetcherFactory : public URLFetcherFactory,
    237                               public ScopedURLFetcherFactory {
    238  public:
    239   TestURLFetcherFactory();
    240   virtual ~TestURLFetcherFactory();
    241 
    242   virtual URLFetcher* CreateURLFetcher(
    243       int id,
    244       const GURL& url,
    245       URLFetcher::RequestType request_type,
    246       URLFetcherDelegate* d) OVERRIDE;
    247   TestURLFetcher* GetFetcherByID(int id) const;
    248   void RemoveFetcherFromMap(int id);
    249   void SetDelegateForTests(TestURLFetcherDelegateForTests* delegate_for_tests);
    250   void set_remove_fetcher_on_delete(bool remove_fetcher_on_delete) {
    251     remove_fetcher_on_delete_ = remove_fetcher_on_delete;
    252   }
    253 
    254  private:
    255   // Maps from id passed to create to the returned URLFetcher.
    256   typedef std::map<int, TestURLFetcher*> Fetchers;
    257   Fetchers fetchers_;
    258   TestURLFetcherDelegateForTests* delegate_for_tests_;
    259   // Whether to automatically unregister a fetcher from this factory upon its
    260   // destruction, false by default.
    261   bool remove_fetcher_on_delete_;
    262 
    263   DISALLOW_COPY_AND_ASSIGN(TestURLFetcherFactory);
    264 };
    265 
    266 // The FakeURLFetcher and FakeURLFetcherFactory classes are similar to the
    267 // ones above but don't require you to know when exactly the URLFetcher objects
    268 // will be created.
    269 //
    270 // These classes let you set pre-baked HTTP responses for particular URLs.
    271 // E.g., if the user requests http://a.com/ then respond with an HTTP/500.
    272 //
    273 // We assume that the thread that is calling Start() on the URLFetcher object
    274 // has a message loop running.
    275 
    276 // FakeURLFetcher can be used to create a URLFetcher that will emit a fake
    277 // response when started. This class can be used in place of an actual
    278 // URLFetcher.
    279 //
    280 // Example usage:
    281 //  FakeURLFetcher fake_fetcher("http://a.com", some_delegate,
    282 //                              "<html><body>hello world</body></html>",
    283 //                              HTTP_OK);
    284 //
    285 // // Will schedule a call to some_delegate->OnURLFetchComplete(&fake_fetcher).
    286 // fake_fetcher.Start();
    287 class FakeURLFetcher : public TestURLFetcher {
    288  public:
    289   // Normal URL fetcher constructor but also takes in a pre-baked response.
    290   FakeURLFetcher(const GURL& url,
    291                  URLFetcherDelegate* d,
    292                  const std::string& response_data,
    293                  HttpStatusCode response_code,
    294                  URLRequestStatus::Status status);
    295 
    296   // Start the request.  This will call the given delegate asynchronously
    297   // with the pre-baked response as parameter.
    298   virtual void Start() OVERRIDE;
    299 
    300   virtual const GURL& GetURL() const OVERRIDE;
    301 
    302   virtual ~FakeURLFetcher();
    303 
    304  private:
    305   // This is the method which actually calls the delegate that is passed in the
    306   // constructor.
    307   void RunDelegate();
    308 
    309   base::WeakPtrFactory<FakeURLFetcher> weak_factory_;
    310 
    311   DISALLOW_COPY_AND_ASSIGN(FakeURLFetcher);
    312 };
    313 
    314 
    315 // FakeURLFetcherFactory is a factory for FakeURLFetcher objects. When
    316 // instantiated, it sets itself up as the default URLFetcherFactory. Fake
    317 // responses for given URLs can be set using SetFakeResponse.
    318 //
    319 // This class is not thread-safe.  You should not call SetFakeResponse or
    320 // ClearFakeResponse at the same time you call CreateURLFetcher.  However, it is
    321 // OK to start URLFetcher objects while setting or clearing fake responses
    322 // since already created URLFetcher objects will not be affected by any changes
    323 // made to the fake responses (once a URLFetcher object is created you cannot
    324 // change its fake response).
    325 //
    326 // Example usage:
    327 //  FakeURLFetcherFactory factory;
    328 //
    329 //  // You know that class SomeService will request http://a.com/success and you
    330 //  // want to respond with a simple html page and an HTTP/200 code.
    331 //  factory.SetFakeResponse("http://a.com/success",
    332 //                          "<html><body>hello world</body></html>",
    333 //                          HTTP_OK,
    334 //                          URLRequestStatus::SUCCESS);
    335 //  // You know that class SomeService will request url http://a.com/servererror
    336 //  // and you want to test the service class by returning a server error.
    337 //  factory.SetFakeResponse("http://a.com/servererror",
    338 //                          "",
    339 //                          HTTP_INTERNAL_SERVER_ERROR,
    340 //                          URLRequestStatus::SUCCESS);
    341 //  // You know that class SomeService will request url http://a.com/autherror
    342 //  // and you want to test the service class by returning a specific error
    343 //  // code, say, a HTTP/401 error.
    344 //  factory.SetFakeResponse("http://a.com/autherror",
    345 //                          "some_response",
    346 //                          HTTP_UNAUTHORIZED,
    347 //                          URLRequestStatus::SUCCESS);
    348 //
    349 //  // You know that class SomeService will request url http://a.com/failure
    350 //  // and you want to test the service class by returning a failure in the
    351 //  // network layer.
    352 //  factory.SetFakeResponse("http://a.com/failure",
    353 //                          "",
    354 //                          HTTP_INTERNAL_SERVER_ERROR,
    355 //                          URLRequestStatus::FAILURE);
    356 //
    357 //  SomeService service;
    358 //  service.Run();  // Will eventually request these three URLs.
    359 class FakeURLFetcherFactory : public URLFetcherFactory,
    360                               public ScopedURLFetcherFactory {
    361  public:
    362   // Parameters to FakeURLFetcherCreator: url, delegate, response_data,
    363   //                                      response_code
    364   // |url| URL for instantiated FakeURLFetcher
    365   // |delegate| Delegate for FakeURLFetcher
    366   // |response_data| response data for FakeURLFetcher
    367   // |response_code| response code for FakeURLFetcher
    368   // |status| URL fetch status for FakeURLFetcher
    369   // These arguments should by default be used in instantiating FakeURLFetcher
    370   // like so:
    371   // new FakeURLFetcher(url, delegate, response_data, response_code, status)
    372   typedef base::Callback<scoped_ptr<FakeURLFetcher>(
    373       const GURL&,
    374       URLFetcherDelegate*,
    375       const std::string&,
    376       HttpStatusCode,
    377       URLRequestStatus::Status)> FakeURLFetcherCreator;
    378 
    379   // |default_factory|, which can be NULL, is a URLFetcherFactory that
    380   // will be used to construct a URLFetcher in case the URL being created
    381   // has no pre-baked response. If it is NULL, a URLFetcherImpl will be
    382   // created in this case.
    383   explicit FakeURLFetcherFactory(URLFetcherFactory* default_factory);
    384 
    385   // |default_factory|, which can be NULL, is a URLFetcherFactory that
    386   // will be used to construct a URLFetcher in case the URL being created
    387   // has no pre-baked response. If it is NULL, a URLFetcherImpl will be
    388   // created in this case.
    389   // |creator| is a callback that returns will be called to create a
    390   // FakeURLFetcher if a response is found to a given URL. It can be
    391   // set to MakeFakeURLFetcher.
    392   FakeURLFetcherFactory(URLFetcherFactory* default_factory,
    393                         const FakeURLFetcherCreator& creator);
    394 
    395   virtual ~FakeURLFetcherFactory();
    396 
    397   // If no fake response is set for the given URL this method will delegate the
    398   // call to |default_factory_| if it is not NULL, or return NULL if it is
    399   // NULL.
    400   // Otherwise, it will return a URLFetcher object which will respond with the
    401   // pre-baked response that the client has set by calling SetFakeResponse().
    402   virtual URLFetcher* CreateURLFetcher(
    403       int id,
    404       const GURL& url,
    405       URLFetcher::RequestType request_type,
    406       URLFetcherDelegate* d) OVERRIDE;
    407 
    408   // Sets the fake response for a given URL. The |response_data| may be empty.
    409   // The |response_code| may be any HttpStatusCode. For instance, HTTP_OK will
    410   // return an HTTP/200 and HTTP_INTERNAL_SERVER_ERROR will return an HTTP/500.
    411   // The |status| argument may be any URLRequestStatus::Status value. Typically,
    412   // requests that return a valid HttpStatusCode have the SUCCESS status, while
    413   // requests that indicate a failure to connect to the server have the FAILED
    414   // status.
    415   void SetFakeResponse(const GURL& url,
    416                        const std::string& response_data,
    417                        HttpStatusCode response_code,
    418                        URLRequestStatus::Status status);
    419 
    420   // Clear all the fake responses that were previously set via
    421   // SetFakeResponse().
    422   void ClearFakeResponses();
    423 
    424  private:
    425   struct FakeURLResponse {
    426     std::string response_data;
    427     HttpStatusCode response_code;
    428     URLRequestStatus::Status status;
    429   };
    430   typedef std::map<GURL, FakeURLResponse> FakeResponseMap;
    431 
    432   const FakeURLFetcherCreator creator_;
    433   FakeResponseMap fake_responses_;
    434   URLFetcherFactory* const default_factory_;
    435 
    436   static scoped_ptr<FakeURLFetcher> DefaultFakeURLFetcherCreator(
    437       const GURL& url,
    438       URLFetcherDelegate* delegate,
    439       const std::string& response_data,
    440       HttpStatusCode response_code,
    441       URLRequestStatus::Status status);
    442   DISALLOW_COPY_AND_ASSIGN(FakeURLFetcherFactory);
    443 };
    444 
    445 // This is an implementation of URLFetcherFactory that will create a
    446 // URLFetcherImpl. It can be use in conjunction with a FakeURLFetcherFactory in
    447 // integration tests to control the behavior of some requests but execute
    448 // all the other ones.
    449 class URLFetcherImplFactory : public URLFetcherFactory {
    450  public:
    451   URLFetcherImplFactory();
    452   virtual ~URLFetcherImplFactory();
    453 
    454   // This method will create a real URLFetcher.
    455   virtual URLFetcher* CreateURLFetcher(
    456       int id,
    457       const GURL& url,
    458       URLFetcher::RequestType request_type,
    459       URLFetcherDelegate* d) OVERRIDE;
    460 };
    461 
    462 }  // namespace net
    463 
    464 #endif  // NET_URL_REQUEST_TEST_URL_FETCHER_FACTORY_H_
    465