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