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