Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/common/net/url_fetcher.h" | 5 #include "chrome/common/net/url_fetcher.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/lock.h" | 11 #include "base/lock.h" |
| 12 #include "base/message_loop_proxy.h" | 12 #include "base/message_loop_proxy.h" |
| 13 #include "base/scoped_ptr.h" | 13 #include "base/scoped_ptr.h" |
| 14 #include "base/stl_util-inl.h" | 14 #include "base/stl_util-inl.h" |
| 15 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 16 #include "base/thread.h" | 16 #include "base/thread.h" |
| 17 #include "chrome/common/net/url_fetcher_protect.h" | |
| 18 #include "chrome/common/net/url_request_context_getter.h" | 17 #include "chrome/common/net/url_request_context_getter.h" |
| 19 #include "googleurl/src/gurl.h" | 18 #include "googleurl/src/gurl.h" |
| 20 #include "net/base/load_flags.h" | 19 #include "net/base/load_flags.h" |
| 21 #include "net/base/io_buffer.h" | 20 #include "net/base/io_buffer.h" |
| 21 #include "net/base/net_errors.h" | |
| 22 #include "net/http/http_request_headers.h" | 22 #include "net/http/http_request_headers.h" |
| 23 #include "net/http/http_response_headers.h" | 23 #include "net/http/http_response_headers.h" |
| 24 #include "net/url_request/request_throttler_manager.h" | |
| 24 #include "net/url_request/url_request.h" | 25 #include "net/url_request/url_request.h" |
| 25 #include "net/url_request/url_request_context.h" | 26 #include "net/url_request/url_request_context.h" |
| 26 | 27 |
| 27 static const int kBufferSize = 4096; | 28 static const int kBufferSize = 4096; |
| 28 | 29 |
| 29 bool URLFetcher::g_interception_enabled = false; | 30 bool URLFetcher::g_interception_enabled = false; |
| 30 | 31 |
| 31 class URLFetcher::Core | 32 class URLFetcher::Core |
| 32 : public base::RefCountedThreadSafe<URLFetcher::Core>, | 33 : public base::RefCountedThreadSafe<URLFetcher::Core>, |
| 33 public URLRequest::Delegate { | 34 public URLRequest::Delegate { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 46 // us. If our caller hasn't had time to fully construct us and take a | 47 // us. If our caller hasn't had time to fully construct us and take a |
| 47 // reference, the IO thread could interrupt things, run a task, Release() | 48 // reference, the IO thread could interrupt things, run a task, Release() |
| 48 // us, and destroy us, leaving the caller with an already-destroyed object | 49 // us, and destroy us, leaving the caller with an already-destroyed object |
| 49 // when construction finishes. | 50 // when construction finishes. |
| 50 void Start(); | 51 void Start(); |
| 51 | 52 |
| 52 // Stops any in-progress load and ensures no callback will happen. It is | 53 // Stops any in-progress load and ensures no callback will happen. It is |
| 53 // safe to call this multiple times. | 54 // safe to call this multiple times. |
| 54 void Stop(); | 55 void Stop(); |
| 55 | 56 |
| 57 // Reports that the received content was malformed. | |
| 58 void ReceivedContentWasMalformed(); | |
| 59 | |
| 56 // URLRequest::Delegate implementation. | 60 // URLRequest::Delegate implementation. |
| 57 virtual void OnResponseStarted(URLRequest* request); | 61 virtual void OnResponseStarted(URLRequest* request); |
| 58 virtual void OnReadCompleted(URLRequest* request, int bytes_read); | 62 virtual void OnReadCompleted(URLRequest* request, int bytes_read); |
| 59 | 63 |
| 60 URLFetcher::Delegate* delegate() const { return delegate_; } | 64 URLFetcher::Delegate* delegate() const { return delegate_; } |
| 61 | 65 |
| 62 static void CancelAll(); | 66 static void CancelAll(); |
| 63 | 67 |
| 64 private: | 68 private: |
| 65 friend class base::RefCountedThreadSafe<URLFetcher::Core>; | 69 friend class base::RefCountedThreadSafe<URLFetcher::Core>; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 77 private: | 81 private: |
| 78 std::set<Core*> fetchers_; | 82 std::set<Core*> fetchers_; |
| 79 | 83 |
| 80 DISALLOW_COPY_AND_ASSIGN(Registry); | 84 DISALLOW_COPY_AND_ASSIGN(Registry); |
| 81 }; | 85 }; |
| 82 | 86 |
| 83 ~Core(); | 87 ~Core(); |
| 84 | 88 |
| 85 // Wrapper functions that allow us to ensure actions happen on the right | 89 // Wrapper functions that allow us to ensure actions happen on the right |
| 86 // thread. | 90 // thread. |
| 91 void StartURLRequestNow(); | |
| 87 void StartURLRequest(); | 92 void StartURLRequest(); |
|
Jói
2010/11/21 19:31:40
It might be more readable to name this one StartUR
yzshen
2010/11/22 17:35:01
Done.
Since the method tries to decide an appropri
| |
| 88 void CancelURLRequest(); | 93 void CancelURLRequest(); |
| 89 void OnCompletedURLRequest(const URLRequestStatus& status); | 94 void OnCompletedURLRequest(const URLRequestStatus& status); |
| 95 void NotifyMalformedContent(); | |
| 90 | 96 |
| 91 // Deletes the request, removes it from the registry, and removes the | 97 // Deletes the request, removes it from the registry, and removes the |
| 92 // destruction observer. | 98 // destruction observer. |
| 93 void ReleaseRequest(); | 99 void ReleaseRequest(); |
| 94 | 100 |
| 101 // Returns the max value of exponential back-off release time for | |
| 102 // |original_url_| and |url_|. | |
| 103 base::TimeTicks GetBackoffReleaseTime(); | |
| 104 | |
| 95 URLFetcher* fetcher_; // Corresponding fetcher object | 105 URLFetcher* fetcher_; // Corresponding fetcher object |
| 96 GURL original_url_; // The URL we were asked to fetch | 106 GURL original_url_; // The URL we were asked to fetch |
| 97 GURL url_; // The URL we eventually wound up at | 107 GURL url_; // The URL we eventually wound up at |
| 98 RequestType request_type_; // What type of request is this? | 108 RequestType request_type_; // What type of request is this? |
| 99 URLFetcher::Delegate* delegate_; // Object to notify on completion | 109 URLFetcher::Delegate* delegate_; // Object to notify on completion |
| 100 MessageLoop* delegate_loop_; // Message loop of the creating thread | 110 MessageLoop* delegate_loop_; // Message loop of the creating thread |
| 101 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; | 111 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; |
| 102 // The message loop proxy for the thread | 112 // The message loop proxy for the thread |
| 103 // on which the request IO happens. | 113 // on which the request IO happens. |
| 104 scoped_ptr<URLRequest> request_; // The actual request this wraps | 114 scoped_ptr<URLRequest> request_; // The actual request this wraps |
| 105 int load_flags_; // Flags for the load operation | 115 int load_flags_; // Flags for the load operation |
| 106 int response_code_; // HTTP status code for the request | 116 int response_code_; // HTTP status code for the request |
| 107 std::string data_; // Results of the request | 117 std::string data_; // Results of the request |
| 108 scoped_refptr<net::IOBuffer> buffer_; | 118 scoped_refptr<net::IOBuffer> buffer_; |
| 109 // Read buffer | 119 // Read buffer |
| 110 scoped_refptr<URLRequestContextGetter> request_context_getter_; | 120 scoped_refptr<URLRequestContextGetter> request_context_getter_; |
| 111 // Cookie/cache info for the request | 121 // Cookie/cache info for the request |
| 112 ResponseCookies cookies_; // Response cookies | 122 ResponseCookies cookies_; // Response cookies |
| 113 net::HttpRequestHeaders extra_request_headers_; | 123 net::HttpRequestHeaders extra_request_headers_; |
| 114 scoped_refptr<net::HttpResponseHeaders> response_headers_; | 124 scoped_refptr<net::HttpResponseHeaders> response_headers_; |
| 115 | 125 |
| 116 std::string upload_content_; // HTTP POST payload | 126 std::string upload_content_; // HTTP POST payload |
| 117 std::string upload_content_type_; // MIME type of POST payload | 127 std::string upload_content_type_; // MIME type of POST payload |
| 118 | 128 |
| 119 // The overload protection entry for this URL. This is used to | 129 // Used to determine how long to wait before making a request or doing a |
| 120 // incrementally back off how rapidly we'll send requests to a particular | 130 // retry. |
| 121 // URL, to avoid placing too much demand on the remote resource. We update | 131 // Both of them can only be accessed on the IO thread. |
| 122 // this with the status of all requests as they return, and in turn use it | 132 scoped_refptr<RequestThrottlerEntryInterface> original_url_throttler_entry_; |
|
Jói
2010/11/21 19:31:40
It's non-obvious why you need two (entry vs. origi
yzshen
2010/11/22 17:35:01
Done.
| |
| 123 // to determine how long to wait before making another request. | 133 scoped_refptr<RequestThrottlerEntryInterface> url_throttler_entry_; |
| 124 URLFetcherProtectEntry* protect_entry_; | 134 |
| 125 // |num_retries_| indicates how many times we've failed to successfully | 135 // |num_retries_| indicates how many times we've failed to successfully |
| 126 // fetch this URL. Once this value exceeds the maximum number of retries | 136 // fetch this URL. Once this value exceeds the maximum number of retries |
| 127 // specified by the protection manager, we'll give up. | 137 // specified by the owner URLFetcher instance, we'll give up. |
| 128 int num_retries_; | 138 int num_retries_; |
| 129 | 139 |
| 130 // True if the URLFetcher has been cancelled. | 140 // True if the URLFetcher has been cancelled. |
| 131 bool was_cancelled_; | 141 bool was_cancelled_; |
| 132 | 142 |
| 143 // Since GetBackoffReleaseTime() can only be called on the IO thread, we cache | |
| 144 // its value to be used on the creating thread. | |
| 145 base::TimeTicks backoff_release_time_; | |
|
Jói
2010/11/21 19:31:40
I only see this set in Core::OnReadCompleted but i
yzshen
2010/11/22 17:35:01
Since OnCompletedURLRequest is only called by OnRe
Jói
2010/11/22 21:16:27
OK.
| |
| 146 | |
| 133 static base::LazyInstance<Registry> g_registry; | 147 static base::LazyInstance<Registry> g_registry; |
| 134 | 148 |
| 135 friend class URLFetcher; | 149 friend class URLFetcher; |
| 136 DISALLOW_COPY_AND_ASSIGN(Core); | 150 DISALLOW_COPY_AND_ASSIGN(Core); |
| 137 }; | 151 }; |
| 138 | 152 |
| 139 URLFetcher::Core::Registry::Registry() {} | 153 URLFetcher::Core::Registry::Registry() {} |
| 140 URLFetcher::Core::Registry::~Registry() {} | 154 URLFetcher::Core::Registry::~Registry() {} |
| 141 | 155 |
| 142 void URLFetcher::Core::Registry::AddURLFetcherCore(Core* core) { | 156 void URLFetcher::Core::Registry::AddURLFetcherCore(Core* core) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 163 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); | 177 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); |
| 164 | 178 |
| 165 // static | 179 // static |
| 166 URLFetcher::Factory* URLFetcher::factory_ = NULL; | 180 URLFetcher::Factory* URLFetcher::factory_ = NULL; |
| 167 | 181 |
| 168 URLFetcher::URLFetcher(const GURL& url, | 182 URLFetcher::URLFetcher(const GURL& url, |
| 169 RequestType request_type, | 183 RequestType request_type, |
| 170 Delegate* d) | 184 Delegate* d) |
| 171 : ALLOW_THIS_IN_INITIALIZER_LIST( | 185 : ALLOW_THIS_IN_INITIALIZER_LIST( |
| 172 core_(new Core(this, url, request_type, d))), | 186 core_(new Core(this, url, request_type, d))), |
| 173 automatically_retry_on_5xx_(true) { | 187 automatically_retry_on_5xx_(true), |
| 188 max_retries_(0) { | |
| 174 } | 189 } |
| 175 | 190 |
| 176 URLFetcher::~URLFetcher() { | 191 URLFetcher::~URLFetcher() { |
| 177 core_->Stop(); | 192 core_->Stop(); |
| 178 } | 193 } |
| 179 | 194 |
| 180 // static | 195 // static |
| 181 URLFetcher* URLFetcher::Create(int id, const GURL& url, | 196 URLFetcher* URLFetcher::Create(int id, const GURL& url, |
| 182 RequestType request_type, Delegate* d) { | 197 RequestType request_type, Delegate* d) { |
| 183 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : | 198 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : |
| 184 new URLFetcher(url, request_type, d); | 199 new URLFetcher(url, request_type, d); |
| 185 } | 200 } |
| 186 | 201 |
| 187 URLFetcher::Core::Core(URLFetcher* fetcher, | 202 URLFetcher::Core::Core(URLFetcher* fetcher, |
| 188 const GURL& original_url, | 203 const GURL& original_url, |
| 189 RequestType request_type, | 204 RequestType request_type, |
| 190 URLFetcher::Delegate* d) | 205 URLFetcher::Delegate* d) |
| 191 : fetcher_(fetcher), | 206 : fetcher_(fetcher), |
| 192 original_url_(original_url), | 207 original_url_(original_url), |
| 193 request_type_(request_type), | 208 request_type_(request_type), |
| 194 delegate_(d), | 209 delegate_(d), |
| 195 delegate_loop_(MessageLoop::current()), | 210 delegate_loop_(MessageLoop::current()), |
| 196 request_(NULL), | 211 request_(NULL), |
| 197 load_flags_(net::LOAD_NORMAL), | 212 load_flags_(net::LOAD_NORMAL), |
| 198 response_code_(-1), | 213 response_code_(-1), |
| 199 buffer_(new net::IOBuffer(kBufferSize)), | 214 buffer_(new net::IOBuffer(kBufferSize)), |
| 200 protect_entry_(URLFetcherProtectManager::GetInstance()->Register( | 215 original_url_throttler_entry_( |
| 201 original_url_.host())), | 216 RequestThrottlerManager::GetInstance()->RegisterRequestUrl( |
| 217 original_url)), | |
| 202 num_retries_(0), | 218 num_retries_(0), |
| 203 was_cancelled_(false) { | 219 was_cancelled_(false) { |
| 204 } | 220 } |
| 205 | 221 |
| 206 URLFetcher::Core::~Core() { | 222 URLFetcher::Core::~Core() { |
| 207 // |request_| should be NULL. If not, it's unsafe to delete it here since we | 223 // |request_| should be NULL. If not, it's unsafe to delete it here since we |
| 208 // may not be on the IO thread. | 224 // may not be on the IO thread. |
| 209 DCHECK(!request_.get()); | 225 DCHECK(!request_.get()); |
| 210 } | 226 } |
| 211 | 227 |
| 212 void URLFetcher::Core::Start() { | 228 void URLFetcher::Core::Start() { |
| 213 DCHECK(delegate_loop_); | 229 DCHECK(delegate_loop_); |
| 214 CHECK(request_context_getter_) << "We need an URLRequestContext!"; | 230 CHECK(request_context_getter_) << "We need an URLRequestContext!"; |
| 215 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); | 231 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); |
| 216 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; | 232 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; |
| 217 io_message_loop_proxy_->PostDelayedTask( | 233 |
| 218 FROM_HERE, | 234 io_message_loop_proxy_->PostTask( |
| 219 NewRunnableMethod(this, &Core::StartURLRequest), | 235 FROM_HERE, NewRunnableMethod(this, &Core::StartURLRequest)); |
| 220 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND)); | |
| 221 } | 236 } |
| 222 | 237 |
| 223 void URLFetcher::Core::Stop() { | 238 void URLFetcher::Core::Stop() { |
| 224 DCHECK_EQ(MessageLoop::current(), delegate_loop_); | 239 DCHECK_EQ(MessageLoop::current(), delegate_loop_); |
| 225 delegate_ = NULL; | 240 delegate_ = NULL; |
| 226 fetcher_ = NULL; | 241 fetcher_ = NULL; |
| 227 if (io_message_loop_proxy_.get()) { | 242 if (io_message_loop_proxy_.get()) { |
| 228 io_message_loop_proxy_->PostTask( | 243 io_message_loop_proxy_->PostTask( |
| 229 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); | 244 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); |
| 230 } | 245 } |
| 231 } | 246 } |
| 232 | 247 |
| 248 void URLFetcher::Core::ReceivedContentWasMalformed() { | |
| 249 DCHECK_EQ(MessageLoop::current(), delegate_loop_); | |
| 250 if (io_message_loop_proxy_.get()) { | |
| 251 io_message_loop_proxy_->PostTask( | |
| 252 FROM_HERE, NewRunnableMethod(this, &Core::NotifyMalformedContent)); | |
| 253 } | |
| 254 } | |
| 255 | |
| 233 void URLFetcher::Core::CancelAll() { | 256 void URLFetcher::Core::CancelAll() { |
| 234 g_registry.Get().CancelAll(); | 257 g_registry.Get().CancelAll(); |
| 235 } | 258 } |
| 236 | 259 |
| 237 void URLFetcher::Core::OnResponseStarted(URLRequest* request) { | 260 void URLFetcher::Core::OnResponseStarted(URLRequest* request) { |
| 238 DCHECK_EQ(request, request_.get()); | 261 DCHECK_EQ(request, request_.get()); |
| 239 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 262 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 240 if (request_->status().is_success()) { | 263 if (request_->status().is_success()) { |
| 241 response_code_ = request_->GetResponseCode(); | 264 response_code_ = request_->GetResponseCode(); |
| 242 response_headers_ = request_->response_headers(); | 265 response_headers_ = request_->response_headers(); |
| 243 } | 266 } |
| 244 | 267 |
| 245 int bytes_read = 0; | 268 int bytes_read = 0; |
| 246 // Some servers may treat HEAD requests as GET requests. To free up the | 269 // Some servers may treat HEAD requests as GET requests. To free up the |
| 247 // network connection as soon as possible, signal that the request has | 270 // network connection as soon as possible, signal that the request has |
| 248 // completed immediately, without trying to read any data back (all we care | 271 // completed immediately, without trying to read any data back (all we care |
| 249 // about is the response code and headers, which we already have). | 272 // about is the response code and headers, which we already have). |
| 250 if (request_->status().is_success() && (request_type_ != HEAD)) | 273 if (request_->status().is_success() && (request_type_ != HEAD)) |
| 251 request_->Read(buffer_, kBufferSize, &bytes_read); | 274 request_->Read(buffer_, kBufferSize, &bytes_read); |
| 252 OnReadCompleted(request_.get(), bytes_read); | 275 OnReadCompleted(request_.get(), bytes_read); |
| 253 } | 276 } |
| 254 | 277 |
| 255 void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) { | 278 void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) { |
| 256 DCHECK(request == request_); | 279 DCHECK(request == request_); |
| 257 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 280 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 258 | 281 |
| 259 url_ = request->url(); | 282 url_ = request->url(); |
| 283 url_throttler_entry_ = | |
| 284 RequestThrottlerManager::GetInstance()->RegisterRequestUrl(url_); | |
| 260 | 285 |
| 261 do { | 286 do { |
| 262 if (!request_->status().is_success() || bytes_read <= 0) | 287 if (!request_->status().is_success() || bytes_read <= 0) |
| 263 break; | 288 break; |
| 264 data_.append(buffer_->data(), bytes_read); | 289 data_.append(buffer_->data(), bytes_read); |
| 265 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); | 290 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); |
| 266 | 291 |
| 267 if (request_->status().is_success()) | 292 if (request_->status().is_success()) |
| 268 request_->GetResponseCookies(&cookies_); | 293 request_->GetResponseCookies(&cookies_); |
| 269 | 294 |
| 270 // See comments re: HEAD requests in OnResponseStarted(). | 295 // See comments re: HEAD requests in OnResponseStarted(). |
| 271 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) { | 296 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) { |
| 297 backoff_release_time_ = GetBackoffReleaseTime(); | |
| 298 | |
| 272 delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 299 delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
| 273 this, &Core::OnCompletedURLRequest, request_->status())); | 300 this, &Core::OnCompletedURLRequest, request_->status())); |
| 274 ReleaseRequest(); | 301 ReleaseRequest(); |
| 275 } | 302 } |
| 276 } | 303 } |
| 277 | 304 |
| 278 void URLFetcher::Core::StartURLRequest() { | 305 void URLFetcher::Core::StartURLRequestNow() { |
| 279 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 306 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 280 | 307 |
| 281 if (was_cancelled_) { | 308 if (was_cancelled_) { |
| 282 // Since StartURLRequest() is posted as a *delayed* task, it may | 309 // Since StartURLRequestNow() is posted as a *delayed* task, it may |
| 283 // run after the URLFetcher was already stopped. | 310 // run after the URLFetcher was already stopped. |
| 284 return; | 311 return; |
| 285 } | 312 } |
| 286 | 313 |
| 287 CHECK(request_context_getter_); | 314 CHECK(request_context_getter_); |
| 288 DCHECK(!request_.get()); | 315 DCHECK(!request_.get()); |
| 289 | 316 |
| 290 g_registry.Get().AddURLFetcherCore(this); | 317 g_registry.Get().AddURLFetcherCore(this); |
| 291 request_.reset(new URLRequest(original_url_, this)); | 318 request_.reset(new URLRequest(original_url_, this)); |
| 292 int flags = request_->load_flags() | load_flags_; | 319 int flags = request_->load_flags() | load_flags_; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 318 default: | 345 default: |
| 319 NOTREACHED(); | 346 NOTREACHED(); |
| 320 } | 347 } |
| 321 | 348 |
| 322 if (!extra_request_headers_.IsEmpty()) | 349 if (!extra_request_headers_.IsEmpty()) |
| 323 request_->SetExtraRequestHeaders(extra_request_headers_); | 350 request_->SetExtraRequestHeaders(extra_request_headers_); |
| 324 | 351 |
| 325 request_->Start(); | 352 request_->Start(); |
| 326 } | 353 } |
| 327 | 354 |
| 355 void URLFetcher::Core::StartURLRequest() { | |
| 356 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | |
| 357 | |
| 358 if (was_cancelled_) | |
| 359 return; | |
| 360 | |
| 361 int64 delay = original_url_throttler_entry_->ReserveSendingTimeForNextRequest( | |
| 362 GetBackoffReleaseTime()); | |
| 363 if (delay == 0) { | |
| 364 StartURLRequestNow(); | |
| 365 } else { | |
| 366 MessageLoop::current()->PostDelayedTask( | |
| 367 FROM_HERE, | |
| 368 NewRunnableMethod(this, &Core::StartURLRequestNow), | |
| 369 delay); | |
| 370 } | |
| 371 } | |
| 372 | |
| 328 void URLFetcher::Core::CancelURLRequest() { | 373 void URLFetcher::Core::CancelURLRequest() { |
| 329 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 374 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 330 | 375 |
| 331 if (request_.get()) { | 376 if (request_.get()) { |
| 332 request_->Cancel(); | 377 request_->Cancel(); |
| 333 ReleaseRequest(); | 378 ReleaseRequest(); |
| 334 } | 379 } |
| 335 // Release the reference to the request context. There could be multiple | 380 // Release the reference to the request context. There could be multiple |
| 336 // references to URLFetcher::Core at this point so it may take a while to | 381 // references to URLFetcher::Core at this point so it may take a while to |
| 337 // delete the object, but we cannot delay the destruction of the request | 382 // delete the object, but we cannot delay the destruction of the request |
| 338 // context. | 383 // context. |
| 339 request_context_getter_ = NULL; | 384 request_context_getter_ = NULL; |
| 340 was_cancelled_ = true; | 385 was_cancelled_ = true; |
| 341 } | 386 } |
| 342 | 387 |
| 343 void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) { | 388 void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) { |
| 344 DCHECK(MessageLoop::current() == delegate_loop_); | 389 DCHECK(MessageLoop::current() == delegate_loop_); |
| 345 | 390 |
| 346 // Checks the response from server. | 391 // Checks the response from server. |
| 347 if (response_code_ >= 500) { | 392 if (response_code_ >= 500 || |
| 393 status.os_error() == net::ERR_TEMPORARILY_THROTTLED_BY_DDOS) { | |
| 348 // When encountering a server error, we will send the request again | 394 // When encountering a server error, we will send the request again |
| 349 // after backoff time. | 395 // after backoff time. |
| 350 int64 back_off_time = | |
| 351 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE); | |
| 352 if (delegate_) { | |
| 353 fetcher_->backoff_delay_ = | |
| 354 base::TimeDelta::FromMilliseconds(back_off_time); | |
| 355 } | |
| 356 ++num_retries_; | 396 ++num_retries_; |
| 357 // Restarts the request if we still need to notify the delegate. | 397 // Restarts the request if we still need to notify the delegate. |
| 358 if (delegate_) { | 398 if (delegate_) { |
| 399 fetcher_->backoff_delay_ = backoff_release_time_ - base::TimeTicks::Now(); | |
| 400 if (fetcher_->backoff_delay_ < base::TimeDelta()) | |
| 401 fetcher_->backoff_delay_ = base::TimeDelta(); | |
| 402 | |
| 359 if (fetcher_->automatically_retry_on_5xx_ && | 403 if (fetcher_->automatically_retry_on_5xx_ && |
| 360 num_retries_ <= protect_entry_->max_retries()) { | 404 num_retries_ <= fetcher_->max_retries()) { |
| 361 io_message_loop_proxy_->PostDelayedTask( | 405 io_message_loop_proxy_->PostTask( |
| 362 FROM_HERE, | 406 FROM_HERE, |
| 363 NewRunnableMethod(this, &Core::StartURLRequest), back_off_time); | 407 NewRunnableMethod(this, &Core::StartURLRequest)); |
| 364 } else { | 408 } else { |
| 365 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, | 409 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, |
| 366 cookies_, data_); | 410 cookies_, data_); |
| 367 } | 411 } |
| 368 } | 412 } |
| 369 } else { | 413 } else { |
| 370 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS); | |
| 371 if (delegate_) { | 414 if (delegate_) { |
| 372 fetcher_->backoff_delay_ = base::TimeDelta(); | 415 fetcher_->backoff_delay_ = base::TimeDelta(); |
| 373 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, | 416 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, |
| 374 cookies_, data_); | 417 cookies_, data_); |
| 375 } | 418 } |
| 376 } | 419 } |
| 377 } | 420 } |
| 378 | 421 |
| 422 void URLFetcher::Core::NotifyMalformedContent() { | |
| 423 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | |
| 424 if (url_throttler_entry_ != NULL) | |
| 425 url_throttler_entry_->ReceivedContentWasMalformed(); | |
| 426 } | |
| 427 | |
| 379 void URLFetcher::Core::ReleaseRequest() { | 428 void URLFetcher::Core::ReleaseRequest() { |
| 380 request_.reset(); | 429 request_.reset(); |
| 381 g_registry.Get().RemoveURLFetcherCore(this); | 430 g_registry.Get().RemoveURLFetcherCore(this); |
| 382 } | 431 } |
| 383 | 432 |
| 433 base::TimeTicks URLFetcher::Core::GetBackoffReleaseTime() { | |
| 434 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | |
| 435 | |
| 436 base::TimeTicks original_url_backoff = | |
| 437 original_url_throttler_entry_->GetExponentialBackoffReleaseTime(); | |
| 438 base::TimeTicks destination_url_backoff; | |
| 439 if (url_throttler_entry_ != NULL && | |
| 440 original_url_throttler_entry_ != url_throttler_entry_) { | |
| 441 destination_url_backoff = | |
| 442 url_throttler_entry_->GetExponentialBackoffReleaseTime(); | |
| 443 } | |
| 444 | |
| 445 return original_url_backoff > destination_url_backoff ? | |
| 446 original_url_backoff : destination_url_backoff; | |
| 447 } | |
| 448 | |
| 384 void URLFetcher::set_upload_data(const std::string& upload_content_type, | 449 void URLFetcher::set_upload_data(const std::string& upload_content_type, |
| 385 const std::string& upload_content) { | 450 const std::string& upload_content) { |
| 386 core_->upload_content_type_ = upload_content_type; | 451 core_->upload_content_type_ = upload_content_type; |
| 387 core_->upload_content_ = upload_content; | 452 core_->upload_content_ = upload_content; |
| 388 } | 453 } |
| 389 | 454 |
| 390 const std::string& URLFetcher::upload_data() const { | 455 const std::string& URLFetcher::upload_data() const { |
| 391 return core_->upload_content_; | 456 return core_->upload_content_; |
| 392 } | 457 } |
| 393 | 458 |
| 394 void URLFetcher::set_load_flags(int load_flags) { | 459 void URLFetcher::set_load_flags(int load_flags) { |
| 395 core_->load_flags_ = load_flags; | 460 core_->load_flags_ = load_flags; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 419 } | 484 } |
| 420 | 485 |
| 421 void URLFetcher::Start() { | 486 void URLFetcher::Start() { |
| 422 core_->Start(); | 487 core_->Start(); |
| 423 } | 488 } |
| 424 | 489 |
| 425 const GURL& URLFetcher::url() const { | 490 const GURL& URLFetcher::url() const { |
| 426 return core_->url_; | 491 return core_->url_; |
| 427 } | 492 } |
| 428 | 493 |
| 494 void URLFetcher::ReceivedContentWasMalformed() { | |
| 495 core_->ReceivedContentWasMalformed(); | |
| 496 } | |
| 497 | |
| 429 // static | 498 // static |
| 430 void URLFetcher::CancelAll() { | 499 void URLFetcher::CancelAll() { |
| 431 Core::CancelAll(); | 500 Core::CancelAll(); |
| 432 } | 501 } |
| 433 | 502 |
| 434 URLFetcher::Delegate* URLFetcher::delegate() const { | 503 URLFetcher::Delegate* URLFetcher::delegate() const { |
| 435 return core_->delegate(); | 504 return core_->delegate(); |
| 436 } | 505 } |
| OLD | NEW |