1// Copyright 2014 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#include "net/base/sdch_dictionary_fetcher.h" 6 7#include "base/bind.h" 8#include "base/compiler_specific.h" 9#include "base/message_loop/message_loop.h" 10#include "net/base/load_flags.h" 11#include "net/url_request/url_fetcher.h" 12#include "net/url_request/url_request_context_getter.h" 13#include "net/url_request/url_request_status.h" 14 15namespace net { 16 17SdchDictionaryFetcher::SdchDictionaryFetcher( 18 SdchManager* manager, 19 URLRequestContextGetter* context) 20 : manager_(manager), 21 weak_factory_(this), 22 task_is_pending_(false), 23 context_(context) { 24 DCHECK(CalledOnValidThread()); 25 DCHECK(manager); 26} 27 28SdchDictionaryFetcher::~SdchDictionaryFetcher() { 29 DCHECK(CalledOnValidThread()); 30} 31 32void SdchDictionaryFetcher::Schedule(const GURL& dictionary_url) { 33 DCHECK(CalledOnValidThread()); 34 35 // Avoid pushing duplicate copy onto queue. We may fetch this url again later 36 // and get a different dictionary, but there is no reason to have it in the 37 // queue twice at one time. 38 if (!fetch_queue_.empty() && fetch_queue_.back() == dictionary_url) { 39 SdchManager::SdchErrorRecovery( 40 SdchManager::DICTIONARY_ALREADY_SCHEDULED_TO_DOWNLOAD); 41 return; 42 } 43 if (attempted_load_.find(dictionary_url) != attempted_load_.end()) { 44 SdchManager::SdchErrorRecovery( 45 SdchManager::DICTIONARY_ALREADY_TRIED_TO_DOWNLOAD); 46 return; 47 } 48 attempted_load_.insert(dictionary_url); 49 fetch_queue_.push(dictionary_url); 50 ScheduleDelayedRun(); 51} 52 53void SdchDictionaryFetcher::Cancel() { 54 DCHECK(CalledOnValidThread()); 55 56 while (!fetch_queue_.empty()) 57 fetch_queue_.pop(); 58 attempted_load_.clear(); 59 weak_factory_.InvalidateWeakPtrs(); 60 current_fetch_.reset(NULL); 61} 62 63void SdchDictionaryFetcher::ScheduleDelayedRun() { 64 if (fetch_queue_.empty() || current_fetch_.get() || task_is_pending_) 65 return; 66 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, 67 base::Bind(&SdchDictionaryFetcher::StartFetching, 68 weak_factory_.GetWeakPtr()), 69 base::TimeDelta::FromMilliseconds(kMsDelayFromRequestTillDownload)); 70 task_is_pending_ = true; 71} 72 73void SdchDictionaryFetcher::StartFetching() { 74 DCHECK(CalledOnValidThread()); 75 DCHECK(task_is_pending_); 76 task_is_pending_ = false; 77 78 // Handle losing the race against Cancel(). 79 if (fetch_queue_.empty()) 80 return; 81 82 DCHECK(context_.get()); 83 current_fetch_.reset(URLFetcher::Create( 84 fetch_queue_.front(), URLFetcher::GET, this)); 85 fetch_queue_.pop(); 86 current_fetch_->SetRequestContext(context_.get()); 87 current_fetch_->SetLoadFlags(LOAD_DO_NOT_SEND_COOKIES | 88 LOAD_DO_NOT_SAVE_COOKIES); 89 current_fetch_->Start(); 90} 91 92void SdchDictionaryFetcher::OnURLFetchComplete( 93 const URLFetcher* source) { 94 DCHECK(CalledOnValidThread()); 95 if ((200 == source->GetResponseCode()) && 96 (source->GetStatus().status() == URLRequestStatus::SUCCESS)) { 97 std::string data; 98 source->GetResponseAsString(&data); 99 manager_->AddSdchDictionary(data, source->GetURL()); 100 } 101 current_fetch_.reset(NULL); 102 ScheduleDelayedRun(); 103} 104 105} // namespace net 106