OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/net/url_fetcher.h" | 5 #include "chrome/browser/net/url_fetcher.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/message_loop_proxy.h" |
8 #include "base/string_util.h" | 9 #include "base/string_util.h" |
9 #include "base/thread.h" | 10 #include "base/thread.h" |
10 #include "chrome/browser/browser_process.h" | |
11 #include "chrome/browser/chrome_thread.h" | |
12 #include "chrome/browser/net/url_fetcher_protect.h" | 11 #include "chrome/browser/net/url_fetcher_protect.h" |
13 #include "chrome/browser/net/url_request_context_getter.h" | 12 #include "chrome/browser/net/url_request_context_getter.h" |
14 #include "googleurl/src/gurl.h" | 13 #include "googleurl/src/gurl.h" |
15 #include "net/base/load_flags.h" | 14 #include "net/base/load_flags.h" |
16 #include "net/base/io_buffer.h" | 15 #include "net/base/io_buffer.h" |
17 #include "net/http/http_response_headers.h" | 16 #include "net/http/http_response_headers.h" |
18 #include "net/url_request/url_request.h" | 17 #include "net/url_request/url_request.h" |
19 #include "net/url_request/url_request_context.h" | 18 #include "net/url_request/url_request_context.h" |
20 | 19 |
21 static const int kBufferSize = 4096; | 20 static const int kBufferSize = 4096; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 void StartURLRequest(); | 62 void StartURLRequest(); |
64 void CancelURLRequest(); | 63 void CancelURLRequest(); |
65 void OnCompletedURLRequest(const URLRequestStatus& status); | 64 void OnCompletedURLRequest(const URLRequestStatus& status); |
66 | 65 |
67 URLFetcher* fetcher_; // Corresponding fetcher object | 66 URLFetcher* fetcher_; // Corresponding fetcher object |
68 GURL original_url_; // The URL we were asked to fetch | 67 GURL original_url_; // The URL we were asked to fetch |
69 GURL url_; // The URL we eventually wound up at | 68 GURL url_; // The URL we eventually wound up at |
70 RequestType request_type_; // What type of request is this? | 69 RequestType request_type_; // What type of request is this? |
71 URLFetcher::Delegate* delegate_; // Object to notify on completion | 70 URLFetcher::Delegate* delegate_; // Object to notify on completion |
72 MessageLoop* delegate_loop_; // Message loop of the creating thread | 71 MessageLoop* delegate_loop_; // Message loop of the creating thread |
| 72 scoped_refptr<MessageLoopProxy> io_message_loop_proxy_; |
| 73 // The message loop proxy for the thread |
| 74 // on which the request IO happens. |
73 URLRequest* request_; // The actual request this wraps | 75 URLRequest* request_; // The actual request this wraps |
74 int load_flags_; // Flags for the load operation | 76 int load_flags_; // Flags for the load operation |
75 int response_code_; // HTTP status code for the request | 77 int response_code_; // HTTP status code for the request |
76 std::string data_; // Results of the request | 78 std::string data_; // Results of the request |
77 scoped_refptr<net::IOBuffer> buffer_; | 79 scoped_refptr<net::IOBuffer> buffer_; |
78 // Read buffer | 80 // Read buffer |
79 scoped_refptr<URLRequestContextGetter> request_context_getter_; | 81 scoped_refptr<URLRequestContextGetter> request_context_getter_; |
80 // Cookie/cache info for the request | 82 // Cookie/cache info for the request |
81 ResponseCookies cookies_; // Response cookies | 83 ResponseCookies cookies_; // Response cookies |
82 std::string extra_request_headers_;// Extra headers for the request, if any | 84 std::string extra_request_headers_;// Extra headers for the request, if any |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 buffer_(new net::IOBuffer(kBufferSize)), | 142 buffer_(new net::IOBuffer(kBufferSize)), |
141 protect_entry_(URLFetcherProtectManager::GetInstance()->Register( | 143 protect_entry_(URLFetcherProtectManager::GetInstance()->Register( |
142 original_url_.host())), | 144 original_url_.host())), |
143 num_retries_(0), | 145 num_retries_(0), |
144 was_cancelled_(false) { | 146 was_cancelled_(false) { |
145 } | 147 } |
146 | 148 |
147 void URLFetcher::Core::Start() { | 149 void URLFetcher::Core::Start() { |
148 DCHECK(delegate_loop_); | 150 DCHECK(delegate_loop_); |
149 CHECK(request_context_getter_) << "We need an URLRequestContext!"; | 151 CHECK(request_context_getter_) << "We need an URLRequestContext!"; |
150 ChromeThread::PostDelayedTask( | 152 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); |
151 ChromeThread::IO, FROM_HERE, | 153 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; |
| 154 io_message_loop_proxy_->PostDelayedTask( |
| 155 FROM_HERE, |
152 NewRunnableMethod(this, &Core::StartURLRequest), | 156 NewRunnableMethod(this, &Core::StartURLRequest), |
153 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND)); | 157 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND)); |
154 } | 158 } |
155 | 159 |
156 void URLFetcher::Core::Stop() { | 160 void URLFetcher::Core::Stop() { |
157 DCHECK_EQ(MessageLoop::current(), delegate_loop_); | 161 DCHECK_EQ(MessageLoop::current(), delegate_loop_); |
158 delegate_ = NULL; | 162 delegate_ = NULL; |
159 fetcher_ = NULL; | 163 fetcher_ = NULL; |
160 ChromeThread::PostTask( | 164 if (io_message_loop_proxy_.get()) { |
161 ChromeThread::IO, FROM_HERE, | 165 io_message_loop_proxy_->PostTask( |
162 NewRunnableMethod(this, &Core::CancelURLRequest)); | 166 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); |
| 167 } |
163 } | 168 } |
164 | 169 |
165 void URLFetcher::Core::OnResponseStarted(URLRequest* request) { | 170 void URLFetcher::Core::OnResponseStarted(URLRequest* request) { |
166 DCHECK(request == request_); | 171 DCHECK(request == request_); |
167 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 172 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
168 if (request_->status().is_success()) { | 173 if (request_->status().is_success()) { |
169 response_code_ = request_->GetResponseCode(); | 174 response_code_ = request_->GetResponseCode(); |
170 response_headers_ = request_->response_headers(); | 175 response_headers_ = request_->response_headers(); |
171 } | 176 } |
172 | 177 |
173 int bytes_read = 0; | 178 int bytes_read = 0; |
174 // Some servers may treat HEAD requests as GET requests. To free up the | 179 // Some servers may treat HEAD requests as GET requests. To free up the |
175 // network connection as soon as possible, signal that the request has | 180 // network connection as soon as possible, signal that the request has |
176 // completed immediately, without trying to read any data back (all we care | 181 // completed immediately, without trying to read any data back (all we care |
177 // about is the response code and headers, which we already have). | 182 // about is the response code and headers, which we already have). |
178 if (request_->status().is_success() && (request_type_ != HEAD)) | 183 if (request_->status().is_success() && (request_type_ != HEAD)) |
179 request_->Read(buffer_, kBufferSize, &bytes_read); | 184 request_->Read(buffer_, kBufferSize, &bytes_read); |
180 OnReadCompleted(request_, bytes_read); | 185 OnReadCompleted(request_, bytes_read); |
181 } | 186 } |
182 | 187 |
183 void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) { | 188 void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) { |
184 DCHECK(request == request_); | 189 DCHECK(request == request_); |
185 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 190 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
186 | 191 |
187 url_ = request->url(); | 192 url_ = request->url(); |
188 | 193 |
189 do { | 194 do { |
190 if (!request_->status().is_success() || bytes_read <= 0) | 195 if (!request_->status().is_success() || bytes_read <= 0) |
191 break; | 196 break; |
192 data_.append(buffer_->data(), bytes_read); | 197 data_.append(buffer_->data(), bytes_read); |
193 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); | 198 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); |
194 | 199 |
195 if (request_->status().is_success()) | 200 if (request_->status().is_success()) |
196 request_->GetResponseCookies(&cookies_); | 201 request_->GetResponseCookies(&cookies_); |
197 | 202 |
198 // See comments re: HEAD requests in OnResponseStarted(). | 203 // See comments re: HEAD requests in OnResponseStarted(). |
199 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) { | 204 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) { |
200 delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 205 delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
201 this, &Core::OnCompletedURLRequest, request_->status())); | 206 this, &Core::OnCompletedURLRequest, request_->status())); |
202 delete request_; | 207 delete request_; |
203 request_ = NULL; | 208 request_ = NULL; |
204 } | 209 } |
205 } | 210 } |
206 | 211 |
207 void URLFetcher::Core::StartURLRequest() { | 212 void URLFetcher::Core::StartURLRequest() { |
208 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 213 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
209 | 214 |
210 if (was_cancelled_) { | 215 if (was_cancelled_) { |
211 // Since StartURLRequest() is posted as a *delayed* task, it may | 216 // Since StartURLRequest() is posted as a *delayed* task, it may |
212 // run after the URLFetcher was already stopped. | 217 // run after the URLFetcher was already stopped. |
213 return; | 218 return; |
214 } | 219 } |
215 | 220 |
216 CHECK(request_context_getter_); | 221 CHECK(request_context_getter_); |
217 DCHECK(!request_); | 222 DCHECK(!request_); |
218 | 223 |
(...skipping 30 matching lines...) Expand all Loading... |
249 NOTREACHED(); | 254 NOTREACHED(); |
250 } | 255 } |
251 | 256 |
252 if (!extra_request_headers_.empty()) | 257 if (!extra_request_headers_.empty()) |
253 request_->SetExtraRequestHeaders(extra_request_headers_); | 258 request_->SetExtraRequestHeaders(extra_request_headers_); |
254 | 259 |
255 request_->Start(); | 260 request_->Start(); |
256 } | 261 } |
257 | 262 |
258 void URLFetcher::Core::CancelURLRequest() { | 263 void URLFetcher::Core::CancelURLRequest() { |
259 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 264 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 265 |
260 if (request_) { | 266 if (request_) { |
261 request_->Cancel(); | 267 request_->Cancel(); |
262 delete request_; | 268 delete request_; |
263 request_ = NULL; | 269 request_ = NULL; |
264 } | 270 } |
265 // Release the reference to the request context. There could be multiple | 271 // Release the reference to the request context. There could be multiple |
266 // references to URLFetcher::Core at this point so it may take a while to | 272 // references to URLFetcher::Core at this point so it may take a while to |
267 // delete the object, but we cannot delay the destruction of the request | 273 // delete the object, but we cannot delay the destruction of the request |
268 // context. | 274 // context. |
269 request_context_getter_ = NULL; | 275 request_context_getter_ = NULL; |
(...skipping 11 matching lines...) Expand all Loading... |
281 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE); | 287 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE); |
282 if (delegate_) { | 288 if (delegate_) { |
283 fetcher_->backoff_delay_ = | 289 fetcher_->backoff_delay_ = |
284 base::TimeDelta::FromMilliseconds(back_off_time); | 290 base::TimeDelta::FromMilliseconds(back_off_time); |
285 } | 291 } |
286 ++num_retries_; | 292 ++num_retries_; |
287 // Restarts the request if we still need to notify the delegate. | 293 // Restarts the request if we still need to notify the delegate. |
288 if (delegate_) { | 294 if (delegate_) { |
289 if (fetcher_->automatically_retry_on_5xx_ && | 295 if (fetcher_->automatically_retry_on_5xx_ && |
290 num_retries_ <= protect_entry_->max_retries()) { | 296 num_retries_ <= protect_entry_->max_retries()) { |
291 ChromeThread::PostDelayedTask( | 297 io_message_loop_proxy_->PostDelayedTask( |
292 ChromeThread::IO, FROM_HERE, | 298 FROM_HERE, |
293 NewRunnableMethod(this, &Core::StartURLRequest), back_off_time); | 299 NewRunnableMethod(this, &Core::StartURLRequest), back_off_time); |
294 } else { | 300 } else { |
295 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, | 301 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, |
296 cookies_, data_); | 302 cookies_, data_); |
297 } | 303 } |
298 } | 304 } |
299 } else { | 305 } else { |
300 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS); | 306 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS); |
301 if (delegate_) { | 307 if (delegate_) { |
302 fetcher_->backoff_delay_ = base::TimeDelta(); | 308 fetcher_->backoff_delay_ = base::TimeDelta(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 core_->Start(); | 352 core_->Start(); |
347 } | 353 } |
348 | 354 |
349 const GURL& URLFetcher::url() const { | 355 const GURL& URLFetcher::url() const { |
350 return core_->url_; | 356 return core_->url_; |
351 } | 357 } |
352 | 358 |
353 URLFetcher::Delegate* URLFetcher::delegate() const { | 359 URLFetcher::Delegate* URLFetcher::delegate() const { |
354 return core_->delegate(); | 360 return core_->delegate(); |
355 } | 361 } |
OLD | NEW |