| 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 |