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. set_owner(TestURLFetcherFactory * owner)157 void set_owner(TestURLFetcherFactory* owner) { owner_ = owner; } 158 159 // Unique ID in our factory. id()160 int id() const { return id_; } 161 162 // Returns the data uploaded on this URLFetcher. upload_data()163 const std::string& upload_data() const { return upload_data_; } upload_file_path()164 const base::FilePath& upload_file_path() const { return upload_file_path_; } 165 166 // Returns the chunks of data uploaded on this URLFetcher. upload_chunks()167 const std::list<std::string>& upload_chunks() const { return chunks_; } 168 169 // Checks whether the last call to |AppendChunkToUpload(...)| was final. did_receive_last_chunk()170 bool did_receive_last_chunk() const { return did_receive_last_chunk_; } 171 172 // Returns the delegate installed on the URLFetcher. delegate()173 URLFetcherDelegate* delegate() const { return delegate_; } 174 set_url(const GURL & url)175 void set_url(const GURL& url) { fake_url_ = url; } 176 void set_status(const URLRequestStatus& status); set_response_code(int response_code)177 void set_response_code(int response_code) { 178 fake_response_code_ = response_code; 179 } set_cookies(const ResponseCookies & c)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); set_remove_fetcher_on_delete(bool remove_fetcher_on_delete)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