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