summaryrefslogtreecommitdiffstats
path: root/content/common/url_fetcher.h
blob: 64aa3ea6b2e58fa41576251dea4b80e3e5eafaad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file contains URLFetcher, a wrapper around net::URLRequest that handles
// low-level details like thread safety, ref counting, and incremental buffer
// reading.  This is useful for callers who simply want to get the data from a
// URL and don't care about all the nitty-gritty details.
//
// NOTE(willchan): Only one "IO" thread is supported for URLFetcher.  This is a
// temporary situation.  We will work on allowing support for multiple "io"
// threads per process.

#ifndef CONTENT_COMMON_NET_URL_FETCHER_H_
#define CONTENT_COMMON_NET_URL_FETCHER_H_
#pragma once

#include <string>
#include <vector>

#include "base/memory/ref_counted.h"
#include "base/message_loop.h"
#include "base/platform_file.h"
#include "base/time.h"

class FilePath;
class GURL;

namespace base {
class MessageLoopProxy;
}  // namespace base

namespace net {
class HostPortPair;
class HttpResponseHeaders;
class HttpRequestHeaders;
class URLRequestContextGetter;
class URLRequestStatus;
typedef std::vector<std::string> ResponseCookies;
}  // namespace net

// To use this class, create an instance with the desired URL and a pointer to
// the object to be notified when the URL has been loaded:
//   URLFetcher* fetcher = new URLFetcher("http://www.google.com",
//                                        URLFetcher::GET, this);
//
// Then, optionally set properties on this object, like the request context or
// extra headers:
//   fetcher->SetExtraRequestHeaders("X-Foo: bar");
//
// Finally, start the request:
//   fetcher->Start();
//
//
// The object you supply as a delegate must inherit from URLFetcher::Delegate;
// when the fetch is completed, OnURLFetchComplete() will be called with a
// pointer to the URLFetcher.  From that point until the original URLFetcher
// instance is destroyed, you may use accessor methods to see the result of
// the fetch. You should copy these objects if you need them to live longer
// than the URLFetcher instance. If the URLFetcher instance is destroyed
// before the callback happens, the fetch will be canceled and no callback
// will occur.
//
// You may create the URLFetcher instance on any thread; OnURLFetchComplete()
// will be called back on the same thread you use to create the instance.
//
//
// NOTE: By default URLFetcher requests are NOT intercepted, except when
// interception is explicitly enabled in tests.

class URLFetcher {
 public:
  enum RequestType {
    GET,
    POST,
    HEAD,
  };

  // Imposible http response code. Used to signal that no http response code
  // was received.
  static const int kInvalidHttpResponseCode;

  class Delegate {
   public:
    // TODO(skerner): This will be removed in favor of the |source|-only
    // version below. Leaving this for now to make the initial code review
    // easy to read.
    virtual void OnURLFetchComplete(const URLFetcher* source,
                                    const GURL& url,
                                    const net::URLRequestStatus& status,
                                    int response_code,
                                    const net::ResponseCookies& cookies,
                                    const std::string& data);

    // This will be called when the URL has been fetched, successfully or not.
    // Use accessor methods on |source| to get the results.
    virtual void OnURLFetchComplete(const URLFetcher* source);

   protected:
    virtual ~Delegate() {}
  };

  // URLFetcher::Create uses the currently registered Factory to create the
  // URLFetcher. Factory is intended for testing.
  class Factory {
   public:
    virtual URLFetcher* CreateURLFetcher(int id,
                                         const GURL& url,
                                         RequestType request_type,
                                         Delegate* d) = 0;

   protected:
    virtual ~Factory() {}
  };

  // |url| is the URL to send the request to.
  // |request_type| is the type of request to make.
  // |d| the object that will receive the callback on fetch completion.
  URLFetcher(const GURL& url, RequestType request_type, Delegate* d);

  virtual ~URLFetcher();

  // Sets the factory used by the static method Create to create a URLFetcher.
  // URLFetcher does not take ownership of |factory|. A value of NULL results
  // in a URLFetcher being created directly.
#if defined(UNIT_TEST)
  static void set_factory(Factory* factory) {
    factory_ = factory;
  }
#endif

  // Normally interception is disabled for URLFetcher, but you can use this
  // to enable it for tests. Also see the set_factory method for another way
  // of testing code that uses an URLFetcher.
  static void enable_interception_for_tests(bool enabled) {
    g_interception_enabled = enabled;
  }

  // Creates a URLFetcher, ownership returns to the caller. If there is no
  // Factory (the default) this creates and returns a new URLFetcher. See the
  // constructor for a description of the args. |id| may be used during testing
  // to identify who is creating the URLFetcher.
  static URLFetcher* Create(int id, const GURL& url, RequestType request_type,
                            Delegate* d);

  // Sets data only needed by POSTs.  All callers making POST requests should
  // call this before the request is started.  |upload_content_type| is the MIME
  // type of the content, while |upload_content| is the data to be sent (the
  // Content-Length header value will be set to the length of this data).
  void set_upload_data(const std::string& upload_content_type,
                       const std::string& upload_content);

  // Indicates that the POST data is sent via chunked transfer encoding.
  // This may only be called before calling Start().
  // Use AppendChunkToUpload() to give the data chunks after calling Start().
  void set_chunked_upload(const std::string& upload_content_type);

  // Adds the given bytes to a request's POST data transmitted using chunked
  // transfer encoding.
  // This method should be called ONLY after calling Start().
  virtual void AppendChunkToUpload(const std::string& data, bool is_last_chunk);

  // Set one or more load flags as defined in net/base/load_flags.h.  Must be
  // called before the request is started.
  void set_load_flags(int load_flags);

  // Returns the current load flags.
  int load_flags() const;

  // The referrer URL for the request. Must be called before the request is
  // started.
  void set_referrer(const std::string& referrer);

  // Set extra headers on the request.  Must be called before the request
  // is started.
  void set_extra_request_headers(const std::string& extra_request_headers);

  void GetExtraRequestHeaders(net::HttpRequestHeaders* headers);

  // Set the net::URLRequestContext on the request.  Must be called before the
  // request is started.
  void set_request_context(
      net::URLRequestContextGetter* request_context_getter);

  // If |retry| is false, 5xx responses will be propagated to the observer,
  // if it is true URLFetcher will automatically re-execute the request,
  // after backoff_delay() elapses. URLFetcher has it set to true by default.
  void set_automatically_retry_on_5xx(bool retry);

  int max_retries() const { return max_retries_; }

  void set_max_retries(int max_retries) { max_retries_ = max_retries; }

  // Returns the back-off delay before the request will be retried,
  // when a 5xx response was received.
  base::TimeDelta backoff_delay() const { return backoff_delay_; }

  // Sets the back-off delay, allowing to mock 5xx requests in unit-tests.
#if defined(UNIT_TEST)
  void set_backoff_delay(base::TimeDelta backoff_delay) {
    backoff_delay_ = backoff_delay;
  }
#endif  // defined(UNIT_TEST)

  // By default, the response is saved in a string. Call this method to save the
  // response to a temporary file instead. Must be called before Start().
  // |file_message_loop_proxy| will be used for all file operations.
  void SaveResponseToTemporaryFile(
      scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy);

  // Retrieve the response headers from the request.  Must only be called after
  // the OnURLFetchComplete callback has run.
  virtual net::HttpResponseHeaders* response_headers() const;

  // Retrieve the remote socket address from the request.  Must only
  // be called after the OnURLFetchComplete callback has run and if
  // the request has not failed.
  net::HostPortPair socket_address() const;

  // Returns true if the request was delivered through a proxy.  Must only
  // be called after the OnURLFetchComplete callback has run and the request
  // has not failed.
  bool was_fetched_via_proxy() const;

  // Start the request.  After this is called, you may not change any other
  // settings.
  virtual void Start();

  // Return the URL that this fetcher is processing.
  virtual const GURL& url() const;

  // The status of the URL fetch.
  virtual const net::URLRequestStatus& status() const;

  // The http response code received. Will return
  // URLFetcher::kInvalidHttpResponseCode if an error prevented any response
  // from being received.
  virtual int response_code() const;

  // Cookies recieved.
  virtual const net::ResponseCookies& cookies() const;

  // Return true if any file system operation failed.  If so, set |error_code|
  // to the error code. File system errors are only possible if user called
  // SaveResponseToTemporaryFile().
  virtual bool FileErrorOccurred(base::PlatformFileError* out_error_code) const;

  // Reports that the received content was malformed.
  void ReceivedContentWasMalformed();

  // Get the response as a string. Return false if the fetcher was not
  // set to store the response as a string.
  virtual bool GetResponseAsString(std::string* out_response_string) const;

  // Get the path to the file containing the response body. Returns false
  // if the response body was not saved to a file. If take_ownership is
  // true, caller takes responsibility for the temp file, and it will not
  // be removed once the URLFetcher is destroyed.
  virtual bool GetResponseAsFilePath(bool take_ownership,
                                     FilePath* out_response_path) const;

  // Cancels all existing URLFetchers.  Will notify the URLFetcher::Delegates.
  // Note that any new URLFetchers created while this is running will not be
  // cancelled.  Typically, one would call this in the CleanUp() method of an IO
  // thread, so that no new URLRequests would be able to start on the IO thread
  // anyway.  This doesn't prevent new URLFetchers from trying to post to the IO
  // thread though, even though the task won't ever run.
  static void CancelAll();

 protected:
  // How should the response be stored?
  enum ResponseDestinationType {
    STRING,  // Default: In a std::string
    TEMP_FILE  // Write to a temp file
  };

  // Returns the delegate.
  Delegate* delegate() const;

  // Used by tests.
  const std::string& upload_data() const;

  // Return a reference to the string data fetched.  Response type must
  // be STRING, or this will CHECK.  This method exists to support the
  // old signiture to OnURLFetchComplete(), and will be removed as part
  // of crbug.com/83592 .
  const std::string& GetResponseStringRef() const;

  void SetResponseDestinationForTesting(ResponseDestinationType);
  ResponseDestinationType GetResponseDestinationForTesting() const;

 private:
  friend class URLFetcherTest;
  friend class TestURLFetcher;

  // Only used by URLFetcherTest, returns the number of URLFetcher::Core objects
  // actively running.
  static int GetNumFetcherCores();

  class Core;
  scoped_refptr<Core> core_;

  static Factory* factory_;

  // If |automatically_retry_on_5xx_| is false, 5xx responses will be
  // propagated to the observer, if it is true URLFetcher will automatically
  // re-execute the request, after the back-off delay has expired.
  // true by default.
  bool automatically_retry_on_5xx_;
  // Back-off time delay. 0 by default.
  base::TimeDelta backoff_delay_;
  // Maximum retries allowed.
  int max_retries_;

  static bool g_interception_enabled;

  DISALLOW_COPY_AND_ASSIGN(URLFetcher);
};

#endif  // CONTENT_COMMON_NET_URL_FETCHER_H_