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