OLD | NEW |
| (Empty) |
1 // Copyright (c) 2006-2008 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 // This file contains URLFetcher, a wrapper around URLRequest that handles | |
6 // low-level details like thread safety, ref counting, and incremental buffer | |
7 // reading. This is useful for callers who simply want to get the data from a | |
8 // URL and don't care about all the nitty-gritty details. | |
9 | |
10 #ifndef CHROME_BROWSER_URL_FETCHER_H__ | |
11 #define CHROME_BROWSER_URL_FETCHER_H__ | |
12 | |
13 #include "base/message_loop.h" | |
14 #include "base/ref_counted.h" | |
15 #include "chrome/browser/url_fetcher_protect.h" | |
16 #include "net/url_request/url_request.h" | |
17 | |
18 class URLRequestContext; | |
19 | |
20 // To use this class, create an instance with the desired URL and a pointer to | |
21 // the object to be notified when the URL has been loaded: | |
22 // URLFetcher* fetcher = new URLFetcher("http://www.google.com", this); | |
23 // | |
24 // Then, optionally set properties on this object, like the request context or | |
25 // extra headers: | |
26 // fetcher->SetExtraRequestHeaders("X-Foo: bar"); | |
27 // | |
28 // Finally, start the request: | |
29 // fetcher->Start(); | |
30 // | |
31 // The object you supply as a delegate must inherit from URLFetcher::Delegate; | |
32 // when the fetch is completed, OnURLFetchComplete() will be called with the | |
33 // resulting status and (if applicable) HTTP response code. From that point | |
34 // until the original URLFetcher instance is destroyed, you may examine the | |
35 // provided status and data for the URL. (You should copy these objects if you | |
36 // need them to live longer than the URLFetcher instance.) If the URLFetcher | |
37 // instance is destroyed before the callback happens, the fetch will be | |
38 // canceled and no callback will occur. | |
39 // | |
40 // You may create the URLFetcher instance on any thread; OnURLFetchComplete() | |
41 // will be called back on the same thread you use to create the instance. | |
42 // | |
43 // NOTE: Take extra care when using URLFetcher in services that live on the | |
44 // BrowserProcess; all URLFetcher instances need to be destroyed before | |
45 // the IO thread goes away, since the URLFetcher destructor requests an | |
46 // InvokeLater operation on that thread. | |
47 // | |
48 // NOTE: URLFetcher requests will NOT be intercepted. | |
49 | |
50 class URLFetcher { | |
51 public: | |
52 enum RequestType { | |
53 GET, | |
54 POST, | |
55 HEAD, | |
56 }; | |
57 | |
58 class Delegate { | |
59 public: | |
60 // This will be called when the URL has been fetched, successfully or not. | |
61 // |response_code| is the HTTP response code (200, 404, etc.) if | |
62 // applicable. |url|, |status| and |data| are all valid until the | |
63 // URLFetcher instance is destroyed. | |
64 virtual void OnURLFetchComplete(const URLFetcher* source, | |
65 const GURL& url, | |
66 const URLRequestStatus& status, | |
67 int response_code, | |
68 const ResponseCookies& cookies, | |
69 const std::string& data) = 0; | |
70 }; | |
71 | |
72 // |url| is the URL to send the request to. | |
73 // |request_type| is the type of request to make. | |
74 // |d| the object that will receive the callback on fetch completion. | |
75 URLFetcher(const GURL& url, RequestType request_type, Delegate* d); | |
76 | |
77 // This should only be used by unittests, where g_browser_process->io_thread() | |
78 // does not exist and we must specify an alternate loop. Unfortunately, we | |
79 // can't put it under #ifdef UNIT_TEST since some callers (which themselves | |
80 // should only be reached in unit tests) use this. See | |
81 // chrome/browser/feeds/feed_manager.cc. | |
82 void set_io_loop(MessageLoop* io_loop) { | |
83 core_->io_loop_ = io_loop; | |
84 } | |
85 | |
86 // Sets data only needed by POSTs. All callers making POST requests should | |
87 // call this before the request is started. |upload_content_type| is the MIME | |
88 // type of the content, while |upload_content| is the data to be sent (the | |
89 // Content-Length header value will be set to the length of this data). | |
90 void set_upload_data(const std::string& upload_content_type, | |
91 const std::string& upload_content) { | |
92 core_->upload_content_type_ = upload_content_type; | |
93 core_->upload_content_ = upload_content; | |
94 } | |
95 | |
96 // Set one or more load flags as defined in net/base/load_flags.h. Must be | |
97 // called before the request is started. | |
98 void set_load_flags(int load_flags) { | |
99 core_->load_flags_ = load_flags; | |
100 } | |
101 | |
102 // Set extra headers on the request. Must be called before the request | |
103 // is started. | |
104 void set_extra_request_headers(const std::string& extra_request_headers) { | |
105 core_->extra_request_headers_ = extra_request_headers; | |
106 } | |
107 | |
108 // Set the URLRequestContext on the request. Must be called before the | |
109 // request is started. | |
110 void set_request_context(URLRequestContext* request_context) { | |
111 core_->request_context_ = request_context; | |
112 } | |
113 | |
114 // Retrieve the response headers from the request. Must only be called after | |
115 // the OnURLFetchComplete callback has run. | |
116 net::HttpResponseHeaders* response_headers() const { | |
117 return core_->response_headers_; | |
118 } | |
119 | |
120 // Start the request. After this is called, you may not change any other | |
121 // settings. | |
122 void Start() { core_->Start(); } | |
123 | |
124 // Return the URL that this fetcher is processing. | |
125 const GURL& url() const { | |
126 return core_->url_; | |
127 } | |
128 | |
129 ~URLFetcher(); | |
130 | |
131 private: | |
132 // This class is the real guts of URLFetcher. | |
133 // | |
134 // When created, delegate_loop_ is set to the message loop of the current | |
135 // thread, while io_loop_ is set to the message loop of the IO thread. These | |
136 // are used to ensure that all handling of URLRequests happens on the IO | |
137 // thread (since that class is not currently threadsafe and relies on | |
138 // underlying Microsoft APIs that we don't know to be threadsafe), while | |
139 // keeping the delegate callback on the delegate's thread. | |
140 class Core : public base::RefCountedThreadSafe<URLFetcher::Core>, | |
141 public URLRequest::Delegate { | |
142 public: | |
143 // For POST requests, set |content_type| to the MIME type of the content | |
144 // and set |content| to the data to upload. |flags| are flags to apply to | |
145 // the load operation--these should be one or more of the LOAD_* flags | |
146 // defined in url_request.h. | |
147 Core(URLFetcher* fetcher, | |
148 const GURL& original_url, | |
149 RequestType request_type, | |
150 URLFetcher::Delegate* d); | |
151 | |
152 // Starts the load. It's important that this not happen in the constructor | |
153 // because it causes the IO thread to begin AddRef()ing and Release()ing | |
154 // us. If our caller hasn't had time to fully construct us and take a | |
155 // reference, the IO thread could interrupt things, run a task, Release() | |
156 // us, and destroy us, leaving the caller with an already-destroyed object | |
157 // when construction finishes. | |
158 void Start(); | |
159 | |
160 // Stops any in-progress load and ensures no callback will happen. It is | |
161 // safe to call this multiple times. | |
162 void Stop(); | |
163 | |
164 // URLRequest::Delegate implementations | |
165 virtual void OnReceivedRedirect(URLRequest* request, | |
166 const GURL& new_url) { } | |
167 virtual void OnResponseStarted(URLRequest* request); | |
168 virtual void OnReadCompleted(URLRequest* request, int bytes_read); | |
169 | |
170 private: | |
171 // Wrapper functions that allow us to ensure actions happen on the right | |
172 // thread. | |
173 void StartURLRequest(); | |
174 void CancelURLRequest(); | |
175 void OnCompletedURLRequest(const URLRequestStatus& status); | |
176 | |
177 URLFetcher* fetcher_; // Corresponding fetcher object | |
178 GURL original_url_; // The URL we were asked to fetch | |
179 GURL url_; // The URL we eventually wound up at | |
180 RequestType request_type_; // What type of request is this? | |
181 URLFetcher::Delegate* delegate_; // Object to notify on completion | |
182 MessageLoop* delegate_loop_; // Message loop of the creating thread | |
183 MessageLoop* io_loop_; // Message loop of the IO thread | |
184 URLRequest* request_; // The actual request this wraps | |
185 int load_flags_; // Flags for the load operation | |
186 int response_code_; // HTTP status code for the request | |
187 std::string data_; // Results of the request | |
188 char buffer_[4096]; // Read buffer | |
189 scoped_refptr<URLRequestContext> request_context_; | |
190 // Cookie/cache info for the request | |
191 ResponseCookies cookies_; // Response cookies | |
192 std::string extra_request_headers_;// Extra headers for the request, if any | |
193 scoped_refptr<net::HttpResponseHeaders> response_headers_; | |
194 | |
195 std::string upload_content_; // HTTP POST payload | |
196 std::string upload_content_type_; // MIME type of POST payload | |
197 | |
198 // The overload protection entry for this URL. This is used to | |
199 // incrementally back off how rapidly we'll send requests to a particular | |
200 // URL, to avoid placing too much demand on the remote resource. We update | |
201 // this with the status of all requests as they return, and in turn use it | |
202 // to determine how long to wait before making another request. | |
203 URLFetcherProtectEntry* protect_entry_; | |
204 // |num_retries_| indicates how many times we've failed to successfully | |
205 // fetch this URL. Once this value exceeds the maximum number of retries | |
206 // specified by the protection manager, we'll give up. | |
207 int num_retries_; | |
208 | |
209 friend class URLFetcher; | |
210 DISALLOW_EVIL_CONSTRUCTORS(Core); | |
211 }; | |
212 | |
213 scoped_refptr<Core> core_; | |
214 | |
215 DISALLOW_EVIL_CONSTRUCTORS(URLFetcher); | |
216 }; | |
217 | |
218 #endif // CHROME_BROWSER_URL_FETCHER_H__ | |
219 | |
OLD | NEW |