In_progress_cache : Initial draft
Details:
1- Stores info into proto format and writes to a file.
2- The cache is instantiated & owned by ChromeDownloadManagerDelegate.
3- The entry is created when download starts and will be deleted as
soon as the download completes.
This is continued from this CL by shaktisahu@:
https://chromium-review.googlesource.com/c/chromium/src/+/731403.
Bug: 778425
Change-Id: I6bd3f6df2648ac7b812c464b572492fb670d32bb
Reviewed-on: https://chromium-review.googlesource.com/753537
Commit-Queue: Joy Ming <[email protected]>
Reviewed-by: David Trainor <[email protected]>
Reviewed-by: Min Qin <[email protected]>
Reviewed-by: John Abd-El-Malek <[email protected]>
Cr-Commit-Position: refs/heads/master@{#516024}
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 10b7af4..1204c531 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -40,6 +40,7 @@
"//cc/paint",
"//components/discardable_memory/common",
"//components/discardable_memory/service",
+ "//components/download/downloader/in_progress",
"//components/filesystem:lib",
"//components/leveldb:lib",
"//components/link_header_util",
diff --git a/content/browser/DEPS b/content/browser/DEPS
index f0b0a540..642746e 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -3,6 +3,7 @@
# See comment in content/DEPS for which components are allowed.
"+components/discardable_memory/common",
"+components/discardable_memory/service",
+ "+components/download/downloader/in_progress",
"+components/filesystem",
"+components/leveldb",
"+components/link_header_util",
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
index 3fba819..2e15955 100644
--- a/content/browser/download/download_item_impl.cc
+++ b/content/browser/download/download_item_impl.cc
@@ -37,6 +37,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_runner_util.h"
+#include "components/download/downloader/in_progress/in_progress_cache.h"
#include "content/browser/download/download_create_info.h"
#include "content/browser/download/download_file.h"
#include "content/browser/download/download_interrupt_reasons_impl.h"
@@ -2282,6 +2283,16 @@
download_params->set_hash_state(std::move(hash_state_));
download_params->set_fetch_error_body(fetch_error_body_);
+ auto* manager_delegate = GetBrowserContext()->GetDownloadManagerDelegate();
+ if (manager_delegate) {
+ download::InProgressCache* in_progress_cache =
+ manager_delegate->GetInProgressCache();
+ download::DownloadEntry* entry =
+ in_progress_cache->RetrieveEntry(GetGuid());
+ if (entry)
+ download_params->set_request_origin(entry->request_origin);
+ }
+
// Note that resumed downloads disallow redirects. Hence the referrer URL
// (which is the contents of the Referer header for the last download request)
// will only be sent to the URL returned by GetURL().
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 5492b4d..b8d5f6b 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -22,6 +22,8 @@
#include "base/supports_user_data.h"
#include "base/synchronization/lock.h"
#include "build/build_config.h"
+#include "components/download/downloader/in_progress/download_entry.h"
+#include "components/download/downloader/in_progress/in_progress_cache.h"
#include "content/browser/byte_stream.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/download/download_create_info.h"
@@ -279,6 +281,53 @@
} // namespace
+// Responsible for persisting the in-progress metadata associated with a
+// download.
+class InProgressDownloadObserver : public DownloadItem::Observer {
+ public:
+ explicit InProgressDownloadObserver(
+ download::InProgressCache* in_progress_cache);
+ ~InProgressDownloadObserver() override;
+
+ private:
+ // DownloadItem::Observer
+ void OnDownloadUpdated(DownloadItem* download) override;
+ void OnDownloadRemoved(DownloadItem* download) override;
+
+ // The persistent cache to store in-progress metadata.
+ download::InProgressCache* in_progress_cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(InProgressDownloadObserver);
+};
+
+InProgressDownloadObserver::InProgressDownloadObserver(
+ download::InProgressCache* in_progress_cache)
+ : in_progress_cache_(in_progress_cache) {}
+
+InProgressDownloadObserver::~InProgressDownloadObserver() = default;
+
+void InProgressDownloadObserver::OnDownloadUpdated(DownloadItem* download) {
+ // TODO(crbug.com/778425): Properly handle fail/resume/retry for downloads
+ // that are in the INTERRUPTED state for a long time.
+ switch (download->GetState()) {
+ case DownloadItem::DownloadState::COMPLETE:
+ case DownloadItem::DownloadState::CANCELLED:
+ if (in_progress_cache_)
+ in_progress_cache_->RemoveEntry(download->GetGuid());
+ break;
+ case DownloadItem::DownloadState::IN_PROGRESS:
+ // TODO(crbug.com/778425): After RetrieveEntry has been implemented, do a
+ // check to make sure the entry exists in the cache.
+ break;
+ default:
+ break;
+ }
+}
+
+void InProgressDownloadObserver::OnDownloadRemoved(DownloadItem* download) {
+ in_progress_cache_->RemoveEntry(download->GetGuid());
+}
+
DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context)
: item_factory_(new DownloadItemFactoryImpl()),
file_factory_(new DownloadFileFactory()),
@@ -473,6 +522,16 @@
}
#endif
+ if (delegate_) {
+ if (!in_progress_download_observer_) {
+ in_progress_download_observer_.reset(
+ new InProgressDownloadObserver(delegate_->GetInProgressCache()));
+ }
+ // May already observe this item, remove observer first.
+ download->RemoveObserver(in_progress_download_observer_.get());
+ download->AddObserver(in_progress_download_observer_.get());
+ }
+
std::unique_ptr<DownloadFile> download_file;
if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE) {
@@ -623,6 +682,7 @@
int render_view_route_id,
int render_frame_route_id,
bool do_not_prompt_for_login) {
+ LOG(ERROR) << "BeginDownloadRequest";
if (ResourceDispatcherHostImpl::Get()->is_shutdown())
return DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
@@ -860,6 +920,13 @@
void DownloadManagerImpl::BeginDownloadInternal(
std::unique_ptr<content::DownloadUrlParameters> params,
uint32_t id) {
+ download::InProgressCache* in_progress_cache =
+ GetBrowserContext()->GetDownloadManagerDelegate()->GetInProgressCache();
+ if (in_progress_cache) {
+ in_progress_cache->AddOrReplaceEntry(download::DownloadEntry(
+ params.get()->guid(), params.get()->request_origin()));
+ }
+
if (base::FeatureList::IsEnabled(features::kNetworkService)) {
std::unique_ptr<ResourceRequest> request = CreateResourceRequest(
params.get());
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
index 368a104..e73ec221 100644
--- a/content/browser/download/download_manager_impl.h
+++ b/content/browser/download/download_manager_impl.h
@@ -241,6 +241,9 @@
// Observers that want to be notified of changes to the set of downloads.
base::ObserverList<Observer> observers_;
+ // Stores information about in-progress download items.
+ std::unique_ptr<DownloadItem::Observer> in_progress_download_observer_;
+
// The current active browser context.
BrowserContext* browser_context_;
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc
index c59f97f..9d6350c 100644
--- a/content/browser/download/download_manager_impl_unittest.cc
+++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -126,6 +126,10 @@
// we don't keep dangling pointers.
void RemoveItem(int id);
+ // Sets |has_observer_calls_| to reflect whether we expect to add/remove
+ // observers during the CreateActiveItem.
+ void SetHasObserverCalls(bool observer_calls);
+
// Overridden methods from DownloadItemFactory.
DownloadItemImpl* CreatePersistedItem(
DownloadItemImplDelegate* delegate,
@@ -168,11 +172,13 @@
private:
std::map<uint32_t, MockDownloadItemImpl*> items_;
DownloadItemImplDelegate item_delegate_;
+ bool has_observer_calls_;
DISALLOW_COPY_AND_ASSIGN(MockDownloadItemFactory);
};
-MockDownloadItemFactory::MockDownloadItemFactory() {}
+MockDownloadItemFactory::MockDownloadItemFactory()
+ : has_observer_calls_(false) {}
MockDownloadItemFactory::~MockDownloadItemFactory() {}
@@ -198,6 +204,10 @@
items_.erase(id);
}
+void MockDownloadItemFactory::SetHasObserverCalls(bool has_observer_calls) {
+ has_observer_calls_ = has_observer_calls;
+}
+
DownloadItemImpl* MockDownloadItemFactory::CreatePersistedItem(
DownloadItemImplDelegate* delegate,
const std::string& guid,
@@ -253,6 +263,12 @@
// the download.
EXPECT_CALL(*result, MockStart(_, _));
+ // In the StartDownload case, expect the remove/add observer calls.
+ if (has_observer_calls_) {
+ EXPECT_CALL(*result, RemoveObserver(_));
+ EXPECT_CALL(*result, AddObserver(_));
+ }
+
return result;
}
@@ -501,6 +517,10 @@
base::Unretained(this)));
}
+ void SetHasObserverCalls(bool has_observer_calls) {
+ mock_download_item_factory_->SetHasObserverCalls(has_observer_calls);
+ }
+
protected:
// Key test variable; we'll keep it available to sub-classes.
std::unique_ptr<DownloadManagerImpl> download_manager_;
@@ -529,6 +549,8 @@
// Confirm the appropriate invocations occur when you start a download.
TEST_F(DownloadManagerTest, StartDownload) {
+ SetHasObserverCalls(true);
+
std::unique_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
std::unique_ptr<ByteStreamReader> stream(new MockByteStreamReader);
uint32_t local_id(5); // Random value
@@ -558,6 +580,8 @@
download_manager_->StartDownload(std::move(info), std::move(input_stream),
DownloadUrlParameters::OnStartedCallback());
EXPECT_TRUE(download_manager_->GetDownload(local_id));
+
+ SetHasObserverCalls(false);
}
// Confirm that calling DetermineDownloadTarget behaves properly if the delegate