103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/url_fetcher_downloader.h"
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <stdint.h>
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/logging.h"
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/sequenced_task_runner.h"
1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/component_updater_utils.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/base/load_flags.h"
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/url_request/url_fetcher.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "url/gurl.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace component_updater {
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)UrlFetcherDownloader::UrlFetcherDownloader(
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<CrxDownloader> successor,
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    net::URLRequestContextGetter* context_getter,
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    scoped_refptr<base::SequencedTaskRunner> task_runner)
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : CrxDownloader(successor.Pass()),
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      context_getter_(context_getter),
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      task_runner_(task_runner),
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      downloaded_bytes_(-1),
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      total_bytes_(-1) {
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)UrlFetcherDownloader::~UrlFetcherDownloader() {
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void UrlFetcherDownloader::DoStartDownload(const GURL& url) {
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  url_fetcher_.reset(
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      net::URLFetcher::Create(0, url, net::URLFetcher::GET, this));
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  url_fetcher_->SetRequestContext(context_getter_);
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             net::LOAD_DO_NOT_SAVE_COOKIES |
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             net::LOAD_DISABLE_CACHE);
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  url_fetcher_->SetAutomaticallyRetryOn5xx(false);
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  url_fetcher_->SaveResponseToTemporaryFile(task_runner_);
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  VLOG(1) << "Starting background download: " << url.spec();
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  url_fetcher_->Start();
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  download_start_time_ = base::Time::Now();
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  downloaded_bytes_ = -1;
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  total_bytes_ = -1;
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void UrlFetcherDownloader::OnURLFetchComplete(const net::URLFetcher* source) {
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::Time download_end_time(base::Time::Now());
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::TimeDelta download_time =
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      download_end_time >= download_start_time_
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          ? download_end_time - download_start_time_
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          : base::TimeDelta();
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Consider a 5xx response from the server as an indication to terminate
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // the request and avoid overloading the server in this case.
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // is not accepting requests for the moment.
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const int fetch_error(GetFetchError(*url_fetcher_));
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const bool is_handled = fetch_error == 0 || IsHttpServerError(fetch_error);
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Result result;
70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  result.error = fetch_error;
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!fetch_error) {
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    source->GetResponseAsFilePath(true, &result.response);
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  result.downloaded_bytes = downloaded_bytes_;
75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  result.total_bytes = total_bytes_;
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DownloadMetrics download_metrics;
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  download_metrics.url = url();
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  download_metrics.downloader = DownloadMetrics::kUrlFetcher;
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  download_metrics.error = fetch_error;
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  download_metrics.downloaded_bytes = downloaded_bytes_;
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  download_metrics.total_bytes = total_bytes_;
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  download_metrics.download_time_ms = download_time.InMilliseconds();
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::FilePath local_path_;
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  source->GetResponseAsFilePath(false, &local_path_);
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  VLOG(1) << "Downloaded " << downloaded_bytes_ << " bytes in "
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          << download_time.InMilliseconds() << "ms from "
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << source->GetURL().spec() << " to " << local_path_.value();
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CrxDownloader::OnDownloadComplete(is_handled, result, download_metrics);
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void UrlFetcherDownloader::OnURLFetchDownloadProgress(
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const net::URLFetcher* source,
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int64_t current,
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int64_t total) {
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  downloaded_bytes_ = current;
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  total_bytes_ = total;
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  Result result;
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  result.downloaded_bytes = downloaded_bytes_;
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  result.total_bytes = total_bytes_;
105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  OnDownloadProgress(result);
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace component_updater
110