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