summaryrefslogtreecommitdiff
path: root/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
blob: aac1856ce92101aef71806a58fee0c4c8c03f235 (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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright 2017 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 "content/browser/background_fetch/background_fetch_job_controller.h"

#include <utility>

#include "content/browser/background_fetch/background_fetch_request_manager.h"
#include "content/public/browser/browser_thread.h"

namespace content {

BackgroundFetchJobController::BackgroundFetchJobController(
    BackgroundFetchDelegateProxy* delegate_proxy,
    const BackgroundFetchRegistrationId& registration_id,
    const BackgroundFetchOptions& options,
    const SkBitmap& icon,
    const BackgroundFetchRegistration& registration,
    BackgroundFetchRequestManager* request_manager,
    ProgressCallback progress_callback,
    BackgroundFetchScheduler::FinishedCallback finished_callback)
    : BackgroundFetchScheduler::Controller(registration_id,
                                           std::move(finished_callback)),
      options_(options),
      icon_(icon),
      complete_requests_downloaded_bytes_cache_(registration.downloaded),
      request_manager_(request_manager),
      delegate_proxy_(delegate_proxy),
      progress_callback_(std::move(progress_callback)),
      weak_ptr_factory_(this) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
}

void BackgroundFetchJobController::InitializeRequestStatus(
    int completed_downloads,
    int total_downloads,
    const std::vector<std::string>& outstanding_guids) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // Don't allow double initialization.
  DCHECK_GT(total_downloads, 0);
  DCHECK_EQ(total_downloads_, 0);

  completed_downloads_ = completed_downloads;
  total_downloads_ = total_downloads;

  // TODO(nator): Update this when we support uploads.
  int total_downloads_size = options_.download_total;

  auto fetch_description = std::make_unique<BackgroundFetchDescription>(
      registration_id().unique_id(), options_.title, registration_id().origin(),
      icon_, completed_downloads, total_downloads,
      complete_requests_downloaded_bytes_cache_, total_downloads_size,
      outstanding_guids);

  delegate_proxy_->CreateDownloadJob(GetWeakPtr(),
                                     std::move(fetch_description));
}

BackgroundFetchJobController::~BackgroundFetchJobController() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
}

bool BackgroundFetchJobController::HasMoreRequests() {
  return completed_downloads_ < total_downloads_;
}

void BackgroundFetchJobController::StartRequest(
    scoped_refptr<BackgroundFetchRequestInfo> request) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK_LT(completed_downloads_, total_downloads_);
  DCHECK(request);

  active_request_download_bytes_[request->download_guid()] = 0;

  delegate_proxy_->StartRequest(registration_id().unique_id(),
                                registration_id().origin(), request);
}

void BackgroundFetchJobController::DidStartRequest(
    const scoped_refptr<BackgroundFetchRequestInfo>& request) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  // TODO(delphick): Either add CORS check here or remove this function and do
  // the CORS check in BackgroundFetchDelegateImpl (since
  // download::Client::OnDownloadStarted returns a value that can abort the
  // download).
}

void BackgroundFetchJobController::DidUpdateRequest(
    const scoped_refptr<BackgroundFetchRequestInfo>& request,
    uint64_t bytes_downloaded) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  const std::string& download_guid = request->download_guid();
  if (active_request_download_bytes_[download_guid] == bytes_downloaded)
    return;

  active_request_download_bytes_[download_guid] = bytes_downloaded;

  progress_callback_.Run(registration_id().unique_id(), options_.download_total,
                         complete_requests_downloaded_bytes_cache_ +
                             GetInProgressDownloadedBytes());
}

void BackgroundFetchJobController::DidCompleteRequest(
    const scoped_refptr<BackgroundFetchRequestInfo>& request) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  active_request_download_bytes_.erase(request->download_guid());
  complete_requests_downloaded_bytes_cache_ += request->GetFileSize();
  ++completed_downloads_;

  request_manager_->MarkRequestAsComplete(registration_id(), request.get());
}

void BackgroundFetchJobController::UpdateUI(const std::string& title) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  delegate_proxy_->UpdateUI(registration_id().unique_id(), title);
}

uint64_t BackgroundFetchJobController::GetInProgressDownloadedBytes() {
  uint64_t sum = 0;
  for (const auto& entry : active_request_download_bytes_)
    sum += entry.second;
  return sum;
}

void BackgroundFetchJobController::Abort(
    BackgroundFetchReasonToAbort reason_to_abort) {
  delegate_proxy_->Abort(registration_id().unique_id());

  std::vector<std::string> aborted_guids;
  for (const auto& pair : active_request_download_bytes_)
    aborted_guids.push_back(pair.first);
  request_manager_->OnJobAborted(registration_id(), std::move(aborted_guids));
  if (reason_to_abort != BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER) {
    // Don't call Finish() here, so that we don't mark data for deletion while
    // there are active fetches.
    // Once the controller finishes processing, this function will be called
    // again. (BackgroundFetchScheduler's finished_callback_ will call
    // BackgroundFetchJobController::Abort() with |cancel_download| set to
    // true.)
    Finish(reason_to_abort);
  }
}

}  // namespace content