| Index: chrome/browser/android/offline_pages/recent_tab_helper.cc
|
| diff --git a/chrome/browser/android/offline_pages/recent_tab_helper.cc b/chrome/browser/android/offline_pages/recent_tab_helper.cc
|
| index 94b2c50df795d55b46a9046c62d201d56b4add2a..416a99249df41b8dd0eed741743355f86fe0e504 100644
|
| --- a/chrome/browser/android/offline_pages/recent_tab_helper.cc
|
| +++ b/chrome/browser/android/offline_pages/recent_tab_helper.cc
|
| @@ -9,13 +9,15 @@
|
|
|
| #include "base/bind.h"
|
| #include "base/location.h"
|
| -#include "base/logging.h"
|
| #include "base/macros.h"
|
| +#include "base/memory/ptr_util.h"
|
| #include "base/metrics/histogram_macros.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| #include "base/threading/thread_task_runner_handle.h"
|
| #include "base/time/time.h"
|
| #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h"
|
| #include "chrome/browser/android/offline_pages/offline_page_model_factory.h"
|
| +#include "chrome/browser/android/tab_android.h"
|
| #include "components/offline_pages/client_namespace_constants.h"
|
| #include "components/offline_pages/offline_page_item.h"
|
| #include "components/offline_pages/offline_page_model.h"
|
| @@ -27,19 +29,27 @@
|
| DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::RecentTabHelper);
|
|
|
| namespace {
|
| -
|
| -// Max number of pages to keep. The oldest pages that are over this count are
|
| -// deleted before the next one is saved.
|
| -const size_t kMaxPagesToKeep = 50;
|
| -
|
| -// Predicate for priority_queue used to compute the oldest pages.
|
| -struct ComparePagesForPurge {
|
| - bool operator()(const offline_pages::OfflinePageItem* left,
|
| - const offline_pages::OfflinePageItem* right) const {
|
| - return left->creation_time > right->creation_time;
|
| +class DefaultDelegate: public offline_pages::RecentTabHelper::Delegate {
|
| + public:
|
| + DefaultDelegate() {}
|
| +
|
| + // offline_pages::RecentTabHelper::Delegate
|
| + std::unique_ptr<offline_pages::OfflinePageArchiver> CreatePageArchiver(
|
| + content::WebContents* web_contents) override {
|
| + return base::MakeUnique<offline_pages::OfflinePageMHTMLArchiver>(
|
| + web_contents);
|
| + }
|
| + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override {
|
| + return base::ThreadTaskRunnerHandle::Get();
|
| + }
|
| + bool GetTabId(content::WebContents* web_contents, int* tab_id) override {
|
| + TabAndroid* tab_android = TabAndroid::FromWebContents(web_contents);
|
| + if (!tab_android)
|
| + return false;
|
| + *tab_id = tab_android->GetAndroidId();
|
| + return true;
|
| }
|
| };
|
| -
|
| } // namespace
|
|
|
| namespace offline_pages {
|
| @@ -47,23 +57,46 @@ namespace offline_pages {
|
| RecentTabHelper::RecentTabHelper(content::WebContents* web_contents)
|
| : content::WebContentsObserver(web_contents),
|
| page_model_(nullptr),
|
| + delegate_(new DefaultDelegate()),
|
| weak_ptr_factory_(this) {
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| - snapshot_controller_.reset(new SnapshotController(
|
| - base::ThreadTaskRunnerHandle::Get(), this));
|
| +}
|
| +
|
| +RecentTabHelper::~RecentTabHelper() {
|
| +}
|
| +
|
| +void RecentTabHelper::SetDelegate(
|
| + std::unique_ptr<RecentTabHelper::Delegate> delegate) {
|
| + DCHECK(delegate);
|
| + delegate_ = std::move(delegate);
|
| +}
|
| +
|
| +void RecentTabHelper::LazyInitialize() {
|
| + snapshot_controller_.reset(new SnapshotController(delegate_->GetTaskRunner(),
|
| + this));
|
| + int tab_id_number = 0;
|
| + tab_id_.clear();
|
| +
|
| + if (delegate_->GetTabId(web_contents(), &tab_id_number))
|
| + tab_id_ = base::IntToString(tab_id_number);
|
| +
|
| page_model_ = OfflinePageModelFactory::GetForBrowserContext(
|
| - web_contents->GetBrowserContext());
|
| + web_contents()->GetBrowserContext());
|
|
|
| // TODO(dimich): When we have BackgroundOffliner, avoid capturing prerenderer
|
| // WebContents with its origin as well.
|
| - never_do_snapshots_ = web_contents->GetBrowserContext()->IsOffTheRecord();
|
| -}
|
| -
|
| -RecentTabHelper::~RecentTabHelper() {
|
| + never_do_snapshots_ = tab_id_.empty() ||
|
| + web_contents()->GetBrowserContext()->IsOffTheRecord();
|
| }
|
|
|
| void RecentTabHelper::DidFinishNavigation(
|
| content::NavigationHandle* navigation_handle) {
|
| + // Initialize lazily. It needs TabAndroid for initization, which is also a
|
| + // TabHelper - so can't initialize in constructor because of uncertain order
|
| + // of creation of TabHelpers.
|
| + if (!snapshot_controller_)
|
| + LazyInitialize();
|
| +
|
| if (navigation_handle->IsInMainFrame() &&
|
| navigation_handle->HasCommitted()) {
|
| // Cancel tasks in flight that relate to the previous page.
|
| @@ -106,54 +139,18 @@ void RecentTabHelper::DocumentOnLoadCompletedInMainFrame() {
|
| // Along the chain, the original URL is passed and compared, to detect
|
| // possible navigation and cancel snapshot in that case.
|
| void RecentTabHelper::StartSnapshot() {
|
| - // TODO(dimich): Implement automatic cleanup as per design doc, based on
|
| - // storage limits and page age.
|
| - // This algorithm (remove pages before making sure the save was successful)
|
| - // prefers keeping the storage use low and under control by potentially
|
| - // sacrificing the current snapshot.
|
| + // Remove previously captured pages for this tab.
|
| page_model_->GetOfflineIdsForClientId(
|
| client_id(),
|
| base::Bind(&RecentTabHelper::ContinueSnapshotWithIdsToPurge,
|
| weak_ptr_factory_.GetWeakPtr()));
|
| }
|
|
|
| -// Collects following pages from lastN namespace:
|
| -// - the ones with the same online URL
|
| -// - the oldest pages, enough to keep kMaxPagesToKeep limit.
|
| void RecentTabHelper::ContinueSnapshotWithIdsToPurge(
|
| const std::vector<int64_t>& page_ids) {
|
| -
|
| - std::vector<int64_t> pages_to_purge;
|
| - // Use priority queue to figure out the set of oldest pages to purge.
|
| - std::priority_queue<const OfflinePageItem*,
|
| - std::vector<const OfflinePageItem*>,
|
| - ComparePagesForPurge> pages_queue;
|
| -
|
| - for (const auto& offline_id : page_ids) {
|
| - // TODO(dimich): get rid of 'Maybe'. Maybe make it return multiple pages.
|
| - const OfflinePageItem* page =
|
| - page_model_->MaybeGetPageByOfflineId(offline_id);
|
| - // If there is already a snapshot of this page, remove it so we don't
|
| - // have multiple snapshots of the same page.
|
| - if (page->url == snapshot_url_) {
|
| - pages_to_purge.push_back(offline_id);
|
| - } else {
|
| - pages_queue.push(page);
|
| - }
|
| - }
|
| -
|
| - // Negative counter means nothing else to purge.
|
| - int count_to_purge =
|
| - page_ids.size() - kMaxPagesToKeep - pages_to_purge.size();
|
| -
|
| - for (int count = 0; count < count_to_purge; ++count) {
|
| - pages_to_purge.push_back(pages_queue.top()->offline_id);
|
| - pages_queue.pop();
|
| - }
|
| -
|
| page_model_->DeletePagesByOfflineId(
|
| - pages_to_purge, base::Bind(&RecentTabHelper::ContinueSnapshotAfterPurge,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| + page_ids, base::Bind(&RecentTabHelper::ContinueSnapshotAfterPurge,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| }
|
|
|
| void RecentTabHelper::ContinueSnapshotAfterPurge(
|
| @@ -169,16 +166,9 @@ void RecentTabHelper::ContinueSnapshotAfterPurge(
|
| return;
|
| }
|
|
|
| - // Create either test Archiver or a regular one.
|
| - std::unique_ptr<OfflinePageArchiver> archiver;
|
| - if (test_archive_factory_.get()) {
|
| - archiver = test_archive_factory_->CreateArchiver(web_contents());
|
| - } else {
|
| - archiver.reset(new OfflinePageMHTMLArchiver(web_contents()));
|
| - }
|
| -
|
| page_model_->SavePage(
|
| - snapshot_url_, client_id(), std::move(archiver),
|
| + snapshot_url_, client_id(),
|
| + delegate_->CreatePageArchiver(web_contents()),
|
| base::Bind(&RecentTabHelper::SavePageCallback,
|
| weak_ptr_factory_.GetWeakPtr()));
|
| }
|
| @@ -198,17 +188,7 @@ bool RecentTabHelper::IsSamePage() const {
|
| }
|
|
|
| ClientId RecentTabHelper::client_id() const {
|
| - return ClientId(kLastNNamespace, "");
|
| -}
|
| -
|
| -void RecentTabHelper::SetArchiveFactoryForTest(
|
| - std::unique_ptr<TestArchiveFactory> test_archive_factory) {
|
| - test_archive_factory_ = std::move(test_archive_factory);
|
| -}
|
| -
|
| -void RecentTabHelper::SetTaskRunnerForTest(
|
| - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
|
| - snapshot_controller_.reset(new SnapshotController(task_runner, this));
|
| + return ClientId(kLastNNamespace, tab_id_);
|
| }
|
|
|
| } // namespace offline_pages
|
|
|