| // 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. |
| |
| #ifndef CHROME_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DELEGATE_IMPL_H_ |
| #define CHROME_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DELEGATE_IMPL_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/containers/flat_set.h" |
| #include "base/memory/weak_ptr.h" |
| #include "components/download/public/background_service/download_params.h" |
| #include "components/keyed_service/core/keyed_service.h" |
| #include "components/offline_items_collection/core/offline_content_provider.h" |
| #include "components/offline_items_collection/core/offline_item.h" |
| #include "content/public/browser/background_fetch_delegate.h" |
| #include "ui/gfx/image/image.h" |
| #include "url/origin.h" |
| |
| class Profile; |
| |
| namespace download { |
| class DownloadService; |
| } // namespace download |
| |
| namespace offline_items_collection { |
| class OfflineContentAggregator; |
| } // namespace offline_items_collection |
| |
| // Implementation of BackgroundFetchDelegate using the DownloadService. This |
| // also implements OfflineContentProvider which allows it to show notifications |
| // for its downloads. |
| class BackgroundFetchDelegateImpl |
| : public content::BackgroundFetchDelegate, |
| public offline_items_collection::OfflineContentProvider, |
| public KeyedService { |
| public: |
| BackgroundFetchDelegateImpl(Profile* profile, |
| const std::string& provider_namespace); |
| |
| ~BackgroundFetchDelegateImpl() override; |
| |
| // Lazily initializes and returns the DownloadService. |
| download::DownloadService* GetDownloadService(); |
| |
| // KeyedService implementation: |
| void Shutdown() override; |
| |
| // BackgroundFetchDelegate implementation: |
| void GetIconDisplaySize(GetIconDisplaySizeCallback callback) override; |
| void GetPermissionForOrigin( |
| const url::Origin& origin, |
| const content::ResourceRequestInfo::WebContentsGetter& wc_getter, |
| GetPermissionForOriginCallback callback) override; |
| void CreateDownloadJob(base::WeakPtr<Client> client, |
| std::unique_ptr<content::BackgroundFetchDescription> |
| fetch_description) override; |
| void DownloadUrl(const std::string& job_unique_id, |
| const std::string& guid, |
| const std::string& method, |
| const GURL& url, |
| const net::NetworkTrafficAnnotationTag& traffic_annotation, |
| const net::HttpRequestHeaders& headers, |
| bool has_request_body) override; |
| void Abort(const std::string& job_unique_id) override; |
| void MarkJobComplete(const std::string& job_unique_id) override; |
| void UpdateUI(const std::string& job_unique_id, |
| const base::Optional<std::string>& title, |
| const base::Optional<SkBitmap>& icon) override; |
| |
| // Abort all ongoing downloads and fail the fetch. Currently only used when |
| // the bytes downloaded exceed the total download size, if specified. |
| void FailFetch(const std::string& job_unique_id); |
| |
| void OnDownloadStarted( |
| const std::string& guid, |
| std::unique_ptr<content::BackgroundFetchResponse> response); |
| |
| void OnDownloadUpdated(const std::string& guid, |
| uint64_t bytes_uploaded, |
| uint64_t bytes_downloaded); |
| |
| void OnDownloadFailed(const std::string& guid, |
| std::unique_ptr<content::BackgroundFetchResult> result); |
| |
| void OnDownloadSucceeded( |
| const std::string& guid, |
| std::unique_ptr<content::BackgroundFetchResult> result); |
| |
| // OfflineContentProvider implementation: |
| void OpenItem(offline_items_collection::LaunchLocation location, |
| const offline_items_collection::ContentId& id) override; |
| void RemoveItem(const offline_items_collection::ContentId& id) override; |
| void CancelDownload(const offline_items_collection::ContentId& id) override; |
| void PauseDownload(const offline_items_collection::ContentId& id) override; |
| void ResumeDownload(const offline_items_collection::ContentId& id, |
| bool has_user_gesture) override; |
| void GetItemById(const offline_items_collection::ContentId& id, |
| SingleItemCallback callback) override; |
| void GetAllItems(MultipleItemCallback callback) override; |
| void GetVisualsForItem(const offline_items_collection::ContentId& id, |
| VisualsCallback callback) override; |
| void GetShareInfoForItem(const offline_items_collection::ContentId& id, |
| ShareCallback callback) override; |
| void AddObserver(Observer* observer) override; |
| void RemoveObserver(Observer* observer) override; |
| |
| // Whether the provided GUID is resuming from the perspective of Background |
| // Fetch. |
| bool IsGuidOutstanding(const std::string& guid) const; |
| |
| // Notifies the OfflineContentAggregator of an interrupted download that is |
| // in a paused state. |
| void RestartPausedDownload(const std::string& download_guid); |
| |
| // Returns the set of download GUIDs that have started but did not finish |
| // according to Background Fetch. Clears out all references to outstanding |
| // GUIDs. |
| std::set<std::string> TakeOutstandingGuids(); |
| |
| // Gets the upload data, if any, associated with the |download_guid|. |
| void GetUploadData(const std::string& download_guid, |
| download::GetUploadDataCallback callback); |
| |
| base::WeakPtr<BackgroundFetchDelegateImpl> GetWeakPtr() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| private: |
| FRIEND_TEST_ALL_PREFIXES(BackgroundFetchBrowserTest, |
| FetchesRunToCompletionAndUpdateTitle_Fetched); |
| |
| struct JobDetails { |
| // If a job is part of the |job_details_map_|, it will have one of these |
| // states. |
| enum class State { |
| kPendingWillStartPaused, |
| kPendingWillStartDownloading, |
| kStartedButPaused, |
| kStartedAndDownloading, |
| kCancelled, |
| }; |
| |
| JobDetails(JobDetails&&); |
| JobDetails( |
| base::WeakPtr<Client> client, |
| std::unique_ptr<content::BackgroundFetchDescription> fetch_description, |
| const std::string& provider_namespace, |
| bool is_off_the_record); |
| ~JobDetails(); |
| |
| void UpdateOfflineItem(); |
| void MarkJobAsStarted(); |
| |
| // Returns how many bytes have been processed by the Download Service so |
| // far. |
| uint64_t GetProcessedDataSize() const; |
| |
| struct UploadData { |
| enum class Status { |
| kAbsent, |
| kIncluded, |
| }; |
| |
| explicit UploadData(bool has_upload_data); |
| ~UploadData(); |
| |
| Status status = Status::kAbsent; |
| |
| // The request body blob will be stored here after the Download Service |
| // queries the upload data. The blob handle needs to be kept alive |
| // while the request is sent out, and will be cleared after. |
| blink::mojom::SerializedBlobPtr request_body_blob = nullptr; |
| }; |
| |
| // The client to report the Background Fetch updates to. |
| base::WeakPtr<Client> client; |
| |
| // Set of DownloadService GUIDs that are currently processed. They are |
| // added by DownloadUrl and are removed when the fetch completes, fails, |
| // or is cancelled. The GUID maps to whether the fetch has upload data. |
| std::map<std::string, UploadData> current_fetch_guids; |
| |
| offline_items_collection::OfflineItem offline_item; |
| State job_state; |
| std::unique_ptr<content::BackgroundFetchDescription> fetch_description; |
| uint64_t in_progress_parts_size = 0u; |
| |
| base::OnceClosure on_resume; |
| |
| private: |
| // Whether we should report progress of the job in terms of size of |
| // downloads or in terms of the number of files being downloaded. |
| bool ShouldReportProgressBySize(); |
| |
| DISALLOW_COPY_AND_ASSIGN(JobDetails); |
| }; |
| |
| // Starts a download according to |params| belonging to |job_unique_id|. |
| void StartDownload(const std::string& job_unique_id, |
| const download::DownloadParams& params, |
| bool has_request_body); |
| |
| // Updates the OfflineItem that controls the contents of download |
| // notifications and notifies any OfflineContentProvider::Observer that was |
| // registered with this instance. |
| void UpdateOfflineItemAndUpdateObservers(JobDetails* job_details); |
| |
| void OnDownloadReceived(const std::string& guid, |
| download::DownloadParams::StartResult result); |
| |
| // The callback passed to DownloadRequestLimiter::CanDownload(). |
| void DidGetPermissionFromDownloadRequestLimiter( |
| GetPermissionForOriginCallback callback, |
| bool has_permission); |
| |
| void DidGetUploadData(const std::string& unique_id, |
| const std::string& download_guid, |
| download::GetUploadDataCallback callback, |
| blink::mojom::SerializedBlobPtr blob); |
| |
| // Returns the client for a given |job_unique_id|. |
| base::WeakPtr<Client> GetClient(const std::string& job_unique_id); |
| |
| // The profile this service is being created for. |
| Profile* profile_; |
| |
| // The namespace provided to the |offline_content_aggregator_| and used when |
| // creating Content IDs. |
| std::string provider_namespace_; |
| |
| // The BackgroundFetchDelegateImplFactory depends on the |
| // DownloadServiceFactory, so |download_service_| should outlive |this|. |
| download::DownloadService* download_service_ = nullptr; |
| |
| // Map from individual download GUIDs to job unique ids. |
| std::map<std::string, std::string> download_job_unique_id_map_; |
| |
| // Map from job unique ids to the details of the job. |
| std::map<std::string, JobDetails> job_details_map_; |
| |
| offline_items_collection::OfflineContentAggregator* |
| offline_content_aggregator_; |
| |
| // Set of Observers to be notified of any changes to the shown notifications. |
| std::set<Observer*> observers_; |
| |
| base::WeakPtrFactory<BackgroundFetchDelegateImpl> weak_ptr_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(BackgroundFetchDelegateImpl); |
| }; |
| |
| #endif // CHROME_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DELEGATE_IMPL_H_ |