download_client.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright 2021 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. #include "components/background_fetch/download_client.h"
  5. #include <memory>
  6. #include <set>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/bind.h"
  11. #include "base/threading/sequenced_task_runner_handle.h"
  12. #include "components/background_fetch/background_fetch_delegate_base.h"
  13. #include "components/download/public/background_service/background_download_service.h"
  14. #include "components/download/public/background_service/download_metadata.h"
  15. #include "content/public/browser/background_fetch_response.h"
  16. #include "content/public/browser/browser_context.h"
  17. #include "content/public/browser/browser_thread.h"
  18. #include "services/network/public/cpp/resource_request_body.h"
  19. #include "url/origin.h"
  20. namespace background_fetch {
  21. namespace {
  22. using BackgroundFetchFailureReason =
  23. content::BackgroundFetchResult::FailureReason;
  24. BackgroundFetchFailureReason ToBackgroundFetchFailureReason(
  25. download::Client::FailureReason reason) {
  26. switch (reason) {
  27. case download::Client::FailureReason::NETWORK:
  28. return BackgroundFetchFailureReason::NETWORK;
  29. case download::Client::FailureReason::UPLOAD_TIMEDOUT:
  30. case download::Client::FailureReason::TIMEDOUT:
  31. return BackgroundFetchFailureReason::TIMEDOUT;
  32. case download::Client::FailureReason::UNKNOWN:
  33. return BackgroundFetchFailureReason::FETCH_ERROR;
  34. case download::Client::FailureReason::ABORTED:
  35. case download::Client::FailureReason::CANCELLED:
  36. return BackgroundFetchFailureReason::CANCELLED;
  37. }
  38. }
  39. } // namespace
  40. DownloadClient::DownloadClient(content::BrowserContext* context)
  41. : browser_context_(context) {}
  42. DownloadClient::~DownloadClient() = default;
  43. void DownloadClient::OnServiceInitialized(
  44. bool state_lost,
  45. const std::vector<download::DownloadMetaData>& downloads) {
  46. std::set<std::string> outstanding_guids =
  47. GetDelegate()->TakeOutstandingGuids();
  48. for (const auto& download : downloads) {
  49. if (!outstanding_guids.count(download.guid)) {
  50. // Background Fetch is not aware of this GUID, so it successfully
  51. // completed but the information is still around.
  52. continue;
  53. }
  54. if (download.completion_info) {
  55. // The download finished but was not persisted.
  56. OnDownloadSucceeded(download.guid, *download.completion_info);
  57. return;
  58. }
  59. // The download is active, and will call the appropriate functions.
  60. if (download.paused) {
  61. // We need to resurface the notification in a paused state.
  62. content::BrowserThread::PostBestEffortTask(
  63. FROM_HERE, base::SequencedTaskRunnerHandle::Get(),
  64. base::BindOnce(&BackgroundFetchDelegateBase::RestartPausedDownload,
  65. GetDelegate()->GetWeakPtr(), download.guid));
  66. }
  67. }
  68. // There is also the case that the Download Service is not aware of the GUID.
  69. // i.e. there is a guid in |outstanding_guids| not in |downloads|.
  70. // This can be due to:
  71. // 1. The browser crashing before the download started.
  72. // 2. The download failing before persisting the state.
  73. // 3. The browser was forced to clean-up the the download.
  74. // In either case the download should be allowed to restart, so there is
  75. // nothing to do here.
  76. }
  77. void DownloadClient::OnServiceUnavailable() {}
  78. void DownloadClient::OnDownloadStarted(
  79. const std::string& guid,
  80. const std::vector<GURL>& url_chain,
  81. const scoped_refptr<const net::HttpResponseHeaders>& headers) {
  82. // TODO(crbug.com/884672): Validate the chain/headers and cancel the download
  83. // if invalid.
  84. auto response =
  85. std::make_unique<content::BackgroundFetchResponse>(url_chain, headers);
  86. GetDelegate()->OnDownloadStarted(guid, std::move(response));
  87. }
  88. void DownloadClient::OnDownloadUpdated(const std::string& guid,
  89. uint64_t bytes_uploaded,
  90. uint64_t bytes_downloaded) {
  91. GetDelegate()->OnDownloadUpdated(guid, bytes_uploaded, bytes_downloaded);
  92. }
  93. void DownloadClient::OnDownloadFailed(const std::string& guid,
  94. const download::CompletionInfo& info,
  95. download::Client::FailureReason reason) {
  96. auto response = std::make_unique<content::BackgroundFetchResponse>(
  97. info.url_chain, info.response_headers);
  98. auto result = std::make_unique<content::BackgroundFetchResult>(
  99. std::move(response), base::Time::Now(),
  100. ToBackgroundFetchFailureReason(reason));
  101. GetDelegate()->OnDownloadFailed(guid, std::move(result));
  102. }
  103. void DownloadClient::OnDownloadSucceeded(const std::string& guid,
  104. const download::CompletionInfo& info) {
  105. if (browser_context_->IsOffTheRecord())
  106. DCHECK(info.blob_handle);
  107. else
  108. DCHECK(!info.path.empty());
  109. auto response = std::make_unique<content::BackgroundFetchResponse>(
  110. info.url_chain, info.response_headers);
  111. auto result = std::make_unique<content::BackgroundFetchResult>(
  112. std::move(response), base::Time::Now(), info.path, info.blob_handle,
  113. info.bytes_downloaded);
  114. GetDelegate()->OnDownloadSucceeded(guid, std::move(result));
  115. }
  116. bool DownloadClient::CanServiceRemoveDownloadedFile(const std::string& guid,
  117. bool force_delete) {
  118. // If |force_delete| is true the file will be removed anyway.
  119. // TODO(rayankans): Add UMA to see how often this happens.
  120. return force_delete || GetDelegate()->IsGuidOutstanding(guid);
  121. }
  122. void DownloadClient::GetUploadData(const std::string& guid,
  123. download::GetUploadDataCallback callback) {
  124. GetDelegate()->GetUploadData(guid, std::move(callback));
  125. }
  126. BackgroundFetchDelegateBase* DownloadClient::GetDelegate() {
  127. return static_cast<BackgroundFetchDelegateBase*>(
  128. browser_context_->GetBackgroundFetchDelegate());
  129. }
  130. } // namespace background_fetch