1 // Copyright 2017 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 #ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_JOB_CONTROLLER_H_
6 #define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_JOB_CONTROLLER_H_
7 
8 #include <stdint.h>
9 #include <memory>
10 #include <string>
11 #include <vector>
12 
13 #include "base/callback.h"
14 #include "base/macros.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/optional.h"
18 #include "content/browser/background_fetch/background_fetch_delegate_proxy.h"
19 #include "content/browser/background_fetch/background_fetch_registration_id.h"
20 #include "content/browser/background_fetch/background_fetch_request_info.h"
21 #include "content/browser/background_fetch/background_fetch_scheduler.h"
22 #include "content/common/background_fetch/background_fetch_types.h"
23 #include "content/common/content_export.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "third_party/skia/include/core/SkBitmap.h"
26 
27 namespace content {
28 
29 class BackgroundFetchDataManager;
30 
31 // The JobController will be responsible for coordinating communication with the
32 // DownloadManager. It will get requests from the RequestManager and dispatch
33 // them to the DownloadService. It lives entirely on the service worker core
34 // thread.
35 //
36 // Lifetime: It is created lazily only once a Background Fetch registration
37 // starts downloading, and it is destroyed once no more communication with the
38 // DownloadService or Offline Items Collection is necessary (i.e. once the
39 // registration has been aborted, or once it has completed/failed and the
40 // waitUntil promise has been resolved so UpdateUI can no longer be called).
41 class CONTENT_EXPORT BackgroundFetchJobController
42     : public BackgroundFetchDelegateProxy::Controller {
43  public:
44   using ErrorCallback =
45       base::OnceCallback<void(blink::mojom::BackgroundFetchError)>;
46   using FinishedCallback =
47       base::OnceCallback<void(const BackgroundFetchRegistrationId&,
48                               blink::mojom::BackgroundFetchFailureReason,
49                               ErrorCallback)>;
50   using ProgressCallback = base::RepeatingCallback<void(
51       const std::string& unique_id,
52       const blink::mojom::BackgroundFetchRegistrationData&)>;
53   using RequestStartedCallback =
54       base::OnceCallback<void(const BackgroundFetchRegistrationId&,
55                               const BackgroundFetchRequestInfo*)>;
56   using RequestFinishedCallback =
57       base::OnceCallback<void(const BackgroundFetchRegistrationId&,
58                               scoped_refptr<BackgroundFetchRequestInfo>)>;
59 
60   BackgroundFetchJobController(
61       BackgroundFetchDataManager* data_manager,
62       BackgroundFetchDelegateProxy* delegate_proxy,
63       const BackgroundFetchRegistrationId& registration_id,
64       blink::mojom::BackgroundFetchOptionsPtr options,
65       const SkBitmap& icon,
66       uint64_t bytes_downloaded,
67       uint64_t bytes_uploaded,
68       uint64_t upload_total,
69       ProgressCallback progress_callback,
70       FinishedCallback finished_callback);
71   ~BackgroundFetchJobController() override;
72 
73   // Initializes the job controller with the status of the active and completed
74   // downloads, as well as the title to use.
75   // Only called when this has been loaded from the database.
76   void InitializeRequestStatus(
77       int completed_downloads,
78       int total_downloads,
79       std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
80           active_fetch_requests,
81       bool start_paused);
82 
83   // Gets the number of bytes downloaded/uploaded for jobs that are currently
84   // running.
85   uint64_t GetInProgressDownloadedBytes();
86   uint64_t GetInProgressUploadedBytes();
87 
88   // Returns a blink::mojom::BackgroundFetchRegistrationDataPtr object
89   // created with member fields.
90   blink::mojom::BackgroundFetchRegistrationDataPtr NewRegistrationData() const;
91 
registration_id()92   const BackgroundFetchRegistrationId& registration_id() const {
93     return registration_id_;
94   }
95 
96   // BackgroundFetchDelegateProxy::Controller implementation:
97   void DidStartRequest(
98       const std::string& guid,
99       std::unique_ptr<BackgroundFetchResponse> response) override;
100   void DidUpdateRequest(const std::string& guid,
101                         uint64_t bytes_uploaded,
102                         uint64_t bytes_downloaded) override;
103   void DidCompleteRequest(
104       const std::string& guid,
105       std::unique_ptr<BackgroundFetchResult> result) override;
106   void AbortFromDelegate(
107       blink::mojom::BackgroundFetchFailureReason failure_reason) override;
108   void GetUploadData(
109       const std::string& guid,
110       BackgroundFetchDelegate::GetUploadDataCallback callback) override;
111 
112   // Aborts the fetch. |callback| will run with the result of marking the
113   // registration for deletion.
114   void Abort(blink::mojom::BackgroundFetchFailureReason failure_reason,
115              ErrorCallback callback);
116 
117   // Request processing.
118   void PopNextRequest(RequestStartedCallback request_started_callback,
119                       RequestFinishedCallback request_finished_callback);
120   void DidPopNextRequest(
121       RequestStartedCallback request_started_callback,
122       RequestFinishedCallback request_finished_callback,
123       blink::mojom::BackgroundFetchError error,
124       scoped_refptr<BackgroundFetchRequestInfo> request_info);
125   void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request,
126                     RequestFinishedCallback request_finished_callback);
127   void MarkRequestAsComplete(scoped_refptr<BackgroundFetchRequestInfo> request);
128 
129   // Whether there are more requests to process as part of this job.
130   bool HasMoreRequests();
131 
pending_downloads()132   int pending_downloads() const { return pending_downloads_; }
133 
134  private:
135   struct InProgressRequestBytes {
136     uint64_t uploaded = 0u;
137     uint64_t downloaded = 0u;
138   };
139 
140   // Called after the request is completely processed, and the next one can be
141   // started.
142   void DidMarkRequestAsComplete(blink::mojom::BackgroundFetchError error);
143 
144   // Notifies the scheduler that the download is complete, and hands the result
145   // over.
146   void NotifyDownloadComplete(
147       scoped_refptr<BackgroundFetchRequestInfo> request);
148 
149   // Called when the job completes or has been aborted. |callback| will run
150   // with the result of marking the registration for deletion.
151   void Finish(blink::mojom::BackgroundFetchFailureReason reason_to_abort,
152               ErrorCallback callback);
153 
154   void DidGetUploadData(BackgroundFetchDelegate::GetUploadDataCallback callback,
155                         blink::mojom::BackgroundFetchError error,
156                         blink::mojom::SerializedBlobPtr blob);
157 
158   // Manager for interacting with the DB. It is owned by the
159   // BackgroundFetchContext.
160   BackgroundFetchDataManager* data_manager_;
161 
162   // Proxy for interacting with the BackgroundFetchDelegate across thread
163   // boundaries. It is owned by the BackgroundFetchContext.
164   BackgroundFetchDelegateProxy* delegate_proxy_;
165 
166   // A map from the download GUID to the active request.
167   std::map<std::string, scoped_refptr<BackgroundFetchRequestInfo>>
168       active_request_map_;
169 
170   // A map from the download GUID to the in-progress bytes.
171   std::map<std::string, InProgressRequestBytes> active_bytes_map_;
172 
173   // The registration ID of the fetch this controller represents.
174   BackgroundFetchRegistrationId registration_id_;
175 
176   // Options for the represented background fetch registration.
177   blink::mojom::BackgroundFetchOptionsPtr options_;
178 
179   // Icon for the represented background fetch registration.
180   SkBitmap icon_;
181 
182   // Finished callback to invoke when the active request has finished mapped by
183   // its download GUID.
184   std::map<std::string, RequestFinishedCallback>
185       active_request_finished_callbacks_;
186 
187   // Cache of downloaded byte count stored by the DataManager, to enable
188   // delivering progress events without having to read from the database.
189   uint64_t complete_requests_downloaded_bytes_cache_;
190 
191   // Overall number of bytes that have been uploaded.
192   uint64_t complete_requests_uploaded_bytes_cache_;
193 
194   // Total number of bytes to upload.
195   uint64_t upload_total_;
196 
197   // Callback run each time download progress updates.
198   ProgressCallback progress_callback_;
199 
200   // Number of requests that comprise the whole job.
201   int total_downloads_ = 0;
202 
203   // Number of the requests that have been completed so far.
204   int completed_downloads_ = 0;
205 
206   // The number of requests that are currently being processed.
207   int pending_downloads_ = 0;
208 
209   // The reason background fetch was aborted.
210   blink::mojom::BackgroundFetchFailureReason failure_reason_ =
211       blink::mojom::BackgroundFetchFailureReason::NONE;
212 
213   // Custom callback that runs after the controller is finished.
214   FinishedCallback finished_callback_;
215 
216   base::WeakPtrFactory<BackgroundFetchJobController> weak_ptr_factory_{this};
217 
218   DISALLOW_COPY_AND_ASSIGN(BackgroundFetchJobController);
219 };
220 
221 }  // namespace content
222 
223 #endif  // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_JOB_CONTROLLER_H_
224