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 26namespace 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). 30class 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 65class TestURLFetcherFactory; 66class 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 230typedef 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. 236class 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(); 287class 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. 359class 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. 449class 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