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