summaryrefslogtreecommitdiffstats
path: root/components/update_client/url_fetcher_downloader.cc
blob: 4edc1c4c7377b1562b64405b10d8c129c1eeaa88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/update_client/url_fetcher_downloader.h"

#include <stdint.h>

#include "base/logging.h"
#include "base/sequenced_task_runner.h"
#include "components/update_client/utils.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_fetcher.h"
#include "url/gurl.h"

namespace update_client {

UrlFetcherDownloader::UrlFetcherDownloader(
    scoped_ptr<CrxDownloader> successor,
    net::URLRequestContextGetter* context_getter,
    scoped_refptr<base::SequencedTaskRunner> task_runner)
    : CrxDownloader(successor.Pass()),
      context_getter_(context_getter),
      task_runner_(task_runner),
      downloaded_bytes_(-1),
      total_bytes_(-1) {
}

UrlFetcherDownloader::~UrlFetcherDownloader() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

void UrlFetcherDownloader::DoStartDownload(const GURL& url) {
  DCHECK(thread_checker_.CalledOnValidThread());

  url_fetcher_ = net::URLFetcher::Create(0, url, net::URLFetcher::GET, this);
  url_fetcher_->SetRequestContext(context_getter_);
  url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
                             net::LOAD_DO_NOT_SAVE_COOKIES |
                             net::LOAD_DISABLE_CACHE);
  url_fetcher_->SetAutomaticallyRetryOn5xx(false);
  url_fetcher_->SaveResponseToTemporaryFile(task_runner_);

  VLOG(1) << "Starting background download: " << url.spec();
  url_fetcher_->Start();

  download_start_time_ = base::Time::Now();

  downloaded_bytes_ = -1;
  total_bytes_ = -1;
}

void UrlFetcherDownloader::OnURLFetchComplete(const net::URLFetcher* source) {
  DCHECK(thread_checker_.CalledOnValidThread());

  const base::Time download_end_time(base::Time::Now());
  const base::TimeDelta download_time =
      download_end_time >= download_start_time_
          ? download_end_time - download_start_time_
          : base::TimeDelta();

  // Consider a 5xx response from the server as an indication to terminate
  // the request and avoid overloading the server in this case.
  // is not accepting requests for the moment.
  const int fetch_error(GetFetchError(*url_fetcher_));
  const bool is_handled = fetch_error == 0 || IsHttpServerError(fetch_error);

  Result result;
  result.error = fetch_error;
  if (!fetch_error) {
    source->GetResponseAsFilePath(true, &result.response);
  }
  result.downloaded_bytes = downloaded_bytes_;
  result.total_bytes = total_bytes_;

  DownloadMetrics download_metrics;
  download_metrics.url = url();
  download_metrics.downloader = DownloadMetrics::kUrlFetcher;
  download_metrics.error = fetch_error;
  download_metrics.downloaded_bytes = downloaded_bytes_;
  download_metrics.total_bytes = total_bytes_;
  download_metrics.download_time_ms = download_time.InMilliseconds();

  base::FilePath local_path_;
  source->GetResponseAsFilePath(false, &local_path_);
  VLOG(1) << "Downloaded " << downloaded_bytes_ << " bytes in "
          << download_time.InMilliseconds() << "ms from "
          << source->GetURL().spec() << " to " << local_path_.value();
  CrxDownloader::OnDownloadComplete(is_handled, result, download_metrics);
}

void UrlFetcherDownloader::OnURLFetchDownloadProgress(
    const net::URLFetcher* source,
    int64_t current,
    int64_t total) {
  DCHECK(thread_checker_.CalledOnValidThread());

  downloaded_bytes_ = current;
  total_bytes_ = total;

  Result result;
  result.downloaded_bytes = downloaded_bytes_;
  result.total_bytes = total_bytes_;

  OnDownloadProgress(result);
}

}  // namespace update_client