sdch_dictionary_fetcher.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
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