Chromium Code Reviews| Index: net/base/sdch_dictionary_fetcher.cc |
| diff --git a/net/base/sdch_dictionary_fetcher.cc b/net/base/sdch_dictionary_fetcher.cc |
| index f0a417e925954eebcd972793f9c72fccbe50d8bd..84db46abae4a984bd512a95e8b65a2ab1375c2ed 100644 |
| --- a/net/base/sdch_dictionary_fetcher.cc |
| +++ b/net/base/sdch_dictionary_fetcher.cc |
| @@ -4,13 +4,21 @@ |
| #include "net/base/sdch_dictionary_fetcher.h" |
| +#include <stdint.h> |
| + |
| #include "base/bind.h" |
| #include "base/compiler_specific.h" |
| -#include "base/message_loop/message_loop.h" |
| +#include "base/thread_task_runner_handle.h" |
| #include "net/base/load_flags.h" |
| -#include "net/url_request/url_fetcher.h" |
| #include "net/url_request/url_request_context_getter.h" |
| #include "net/url_request/url_request_status.h" |
| +#include "net/url_request/url_request_throttler_manager.h" |
| + |
| +namespace { |
| + |
| +const int kBufferSize = 4096; |
| + |
| +} // namespace |
| namespace net { |
| @@ -18,9 +26,8 @@ SdchDictionaryFetcher::SdchDictionaryFetcher( |
| SdchManager* manager, |
| scoped_refptr<URLRequestContextGetter> context) |
| : manager_(manager), |
| - weak_factory_(this), |
| - task_is_pending_(false), |
| - context_(context) { |
| + context_(context), |
| + weak_factory_(this) { |
| DCHECK(CalledOnValidThread()); |
| DCHECK(manager); |
| } |
| @@ -47,7 +54,7 @@ void SdchDictionaryFetcher::Schedule(const GURL& dictionary_url) { |
| } |
| attempted_load_.insert(dictionary_url); |
| fetch_queue_.push(dictionary_url); |
| - ScheduleDelayedRun(); |
| + DispatchRun(); |
| } |
| void SdchDictionaryFetcher::Cancel() { |
| @@ -57,49 +64,117 @@ void SdchDictionaryFetcher::Cancel() { |
| fetch_queue_.pop(); |
| attempted_load_.clear(); |
| weak_factory_.InvalidateWeakPtrs(); |
| - current_fetch_.reset(NULL); |
| + current_request_.reset(NULL); |
| + buffer_ = NULL; |
| + dictionary_ = ""; |
|
Ryan Sleevi
2014/08/25 20:00:00
s/""/std::string()
or just dictionary_.clear()
Randy Smith (Not in Mondays)
2014/08/26 15:34:17
Done.
|
| } |
| -void SdchDictionaryFetcher::ScheduleDelayedRun() { |
| - if (fetch_queue_.empty() || current_fetch_.get() || task_is_pending_) |
| - return; |
| - base::MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| - base::Bind(&SdchDictionaryFetcher::StartFetching, |
| - weak_factory_.GetWeakPtr()), |
| - base::TimeDelta::FromMilliseconds(kMsDelayFromRequestTillDownload)); |
| - task_is_pending_ = true; |
| +void SdchDictionaryFetcher::OnResponseStarted(URLRequest* request) { |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK_EQ(request, current_request_.get()); |
| + |
| + int bytes_read = 0; |
| + request->Read(buffer_.get(), kBufferSize, &bytes_read); |
|
Ryan Sleevi
2014/08/25 20:00:00
Read() returns a bool. Please check it before assu
Randy Smith (Not in Mondays)
2014/08/26 15:34:17
Done, but I'd like a bit more of a consult here.
|
| + OnReadCompleted(request, bytes_read); |
| +} |
| + |
| +void SdchDictionaryFetcher::OnReadCompleted(URLRequest* request, |
| + int bytes_read) { |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK_EQ(request, current_request_.get()); |
| + |
| + URLRequestThrottlerManager* throttler_manager = |
| + request->context()->throttler_manager(); |
| + if (throttler_manager) { |
| + url_throttler_entry_ = |
| + throttler_manager->RegisterRequestUrl(request->url()); |
| + } |
| + |
| + do { |
| + if (!current_request_->status().is_success() || bytes_read <= 0) |
| + break; |
| + |
| + dictionary_ += std::string(buffer_->data(), bytes_read); |
|
Ryan Sleevi
2014/08/25 20:00:00
dictionary_.append(), and avoid an unnecessary all
Randy Smith (Not in Mondays)
2014/08/26 15:34:17
Done.
|
| + } while (current_request_->Read(buffer_.get(), kBufferSize, &bytes_read)); |
| + |
| + const URLRequestStatus status = current_request_->status(); |
| + |
| + if (!status.is_io_pending()) { |
| + if (status.is_success()) |
| + manager_->AddSdchDictionary(dictionary_, current_request_->url()); |
| + |
| + current_request_.reset(); |
| + buffer_ = NULL; |
| + dictionary_ = ""; |
|
Ryan Sleevi
2014/08/25 20:00:00
.clear()
Randy Smith (Not in Mondays)
2014/08/26 15:34:17
Done.
|
| + |
| + DispatchRun(); |
| + } |
| } |
| -void SdchDictionaryFetcher::StartFetching() { |
| +void SdchDictionaryFetcher::DispatchRun() { |
| DCHECK(CalledOnValidThread()); |
| - DCHECK(task_is_pending_); |
| - task_is_pending_ = false; |
| + DCHECK(context_.get()); |
| - // Handle losing the race against Cancel(). |
| - if (fetch_queue_.empty()) |
| + if (fetch_queue_.empty() || current_request_.get()) |
| return; |
| + int64 delay = INT64_C(0); |
| + if (!original_url_throttler_entry_.get()) { |
| + URLRequestThrottlerManager* manager = |
| + context_->GetURLRequestContext()->throttler_manager(); |
| + if (manager) { |
| + original_url_throttler_entry_ = |
| + manager->RegisterRequestUrl(fetch_queue_.front()); |
| + } |
| + } |
| + if (original_url_throttler_entry_.get()) { |
| + delay = original_url_throttler_entry_->ReserveSendingTimeForNextRequest( |
| + GetBackoffReleaseTime()); |
| + } |
| + |
| + if (delay != INT64_C(0)) { |
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| + FROM_HERE, base::Bind(&SdchDictionaryFetcher::StartURLRequest, |
| + weak_factory_.GetWeakPtr()), |
| + base::TimeDelta::FromMilliseconds(delay)); |
| + return; |
| + } |
| + |
| + StartURLRequest(); |
|
Ryan Sleevi
2014/08/25 20:00:01
DANGER: This potentially leads to large recursion.
Randy Smith (Not in Mondays)
2014/09/02 19:35:03
See top level comments; we need to hash a bit here
|
| +} |
| + |
| +void SdchDictionaryFetcher::StartURLRequest() { |
| + DCHECK(CalledOnValidThread()); |
| DCHECK(context_.get()); |
| - current_fetch_.reset(URLFetcher::Create( |
| - fetch_queue_.front(), URLFetcher::GET, this)); |
| + DCHECK(!current_request_.get()); |
| + |
| + current_request_ = context_->GetURLRequestContext()->CreateRequest( |
| + fetch_queue_.front(), IDLE, this, NULL); |
|
Ryan Sleevi
2014/08/25 20:00:01
Can this fail?
Randy Smith (Not in Mondays)
2014/08/26 15:34:17
The header is silent on the topic. As I read the
|
| + current_request_->SetLoadFlags(LOAD_DO_NOT_SEND_COOKIES | |
| + LOAD_DO_NOT_SAVE_COOKIES); |
| + buffer_ = new IOBuffer(kBufferSize); |
| fetch_queue_.pop(); |
| - current_fetch_->SetRequestContext(context_.get()); |
| - current_fetch_->SetLoadFlags(LOAD_DO_NOT_SEND_COOKIES | |
| - LOAD_DO_NOT_SAVE_COOKIES); |
| - current_fetch_->Start(); |
| + |
| + current_request_->Start(); |
| } |
| -void SdchDictionaryFetcher::OnURLFetchComplete( |
| - const URLFetcher* source) { |
| +base::TimeTicks SdchDictionaryFetcher::GetBackoffReleaseTime() { |
| DCHECK(CalledOnValidThread()); |
| - if ((200 == source->GetResponseCode()) && |
| - (source->GetStatus().status() == URLRequestStatus::SUCCESS)) { |
| - std::string data; |
| - source->GetResponseAsString(&data); |
| - manager_->AddSdchDictionary(data, source->GetURL()); |
| + |
| + if (!original_url_throttler_entry_.get()) |
| + return base::TimeTicks(); |
| + |
| + base::TimeTicks original_url_backoff = |
| + original_url_throttler_entry_->GetExponentialBackoffReleaseTime(); |
| + base::TimeTicks destination_url_backoff; |
| + if (url_throttler_entry_.get() && |
| + original_url_throttler_entry_.get() != url_throttler_entry_.get()) { |
| + destination_url_backoff = |
| + url_throttler_entry_->GetExponentialBackoffReleaseTime(); |
| } |
| - current_fetch_.reset(NULL); |
| - ScheduleDelayedRun(); |
| + |
| + return original_url_backoff > destination_url_backoff ? |
| + original_url_backoff : destination_url_backoff; |
| } |
| } // namespace net |