| Index: components/offline_pages/offline_page_model.cc
|
| diff --git a/components/offline_pages/offline_page_model.cc b/components/offline_pages/offline_page_model.cc
|
| index 17e499bde753056e803db37f02ff624147ada661..3e93bf9b86b157b8db4373d286061ebf12a76b80 100644
|
| --- a/components/offline_pages/offline_page_model.cc
|
| +++ b/components/offline_pages/offline_page_model.cc
|
| @@ -12,6 +12,7 @@
|
| #include "base/logging.h"
|
| #include "base/metrics/histogram_macros.h"
|
| #include "base/sequenced_task_runner.h"
|
| +#include "base/thread_task_runner_handle.h"
|
| #include "base/time/time.h"
|
| #include "components/bookmarks/browser/bookmark_model.h"
|
| #include "components/bookmarks/browser/bookmark_node.h"
|
| @@ -30,6 +31,11 @@ namespace {
|
| // delete it to free up space.
|
| const base::TimeDelta kPageCleanUpThreshold = base::TimeDelta::FromDays(30);
|
|
|
| +// The delay for the final deletion to kick in after the page is marked for
|
| +// deletion. The value set here is a bit longer that the duration of the
|
| +// snackbar that offers undo.
|
| +const base::TimeDelta kFinalDeletionDelay = base::TimeDelta::FromSeconds(6);
|
| +
|
| SavePageResult ToSavePageResult(ArchiverResult archiver_result) {
|
| SavePageResult result;
|
| switch (archiver_result) {
|
| @@ -125,10 +131,29 @@ void OfflinePageModel::MarkPageAccessed(int64 bookmark_id) {
|
| offline_page_item.access_count++;
|
| store_->AddOrUpdateOfflinePage(
|
| offline_page_item,
|
| - base::Bind(&OfflinePageModel::OnUpdateOfflinePageDone,
|
| + base::Bind(&OfflinePageModel::OnMarkPageAccesseDone,
|
| weak_ptr_factory_.GetWeakPtr(), offline_page_item));
|
| }
|
|
|
| +void OfflinePageModel::MarkPageForDeletion(int64 bookmark_id,
|
| + const DeletePageCallback& callback) {
|
| + DCHECK(is_loaded_);
|
| + auto iter = offline_pages_.find(bookmark_id);
|
| + if (iter == offline_pages_.end()) {
|
| + InformDeletePageDone(callback, DeletePageResult::NOT_FOUND);
|
| + return;
|
| + }
|
| +
|
| + // Make a copy of the cached item and update it. The cached item should only
|
| + // be updated upon the successful store operation.
|
| + OfflinePageItem offline_page_item = iter->second;
|
| + offline_page_item.MarkForDeletion();
|
| + store_->AddOrUpdateOfflinePage(
|
| + offline_page_item,
|
| + base::Bind(&OfflinePageModel::OnMarkPageForDeletionDone,
|
| + weak_ptr_factory_.GetWeakPtr(), offline_page_item, callback));
|
| +}
|
| +
|
| void OfflinePageModel::DeletePageByBookmarkId(
|
| int64 bookmark_id,
|
| const DeletePageCallback& callback) {
|
| @@ -170,8 +195,11 @@ void OfflinePageModel::DeletePagesByBookmarkId(
|
| const std::vector<OfflinePageItem> OfflinePageModel::GetAllPages() const {
|
| DCHECK(is_loaded_);
|
| std::vector<OfflinePageItem> offline_pages;
|
| - for (const auto& id_page_pair : offline_pages_)
|
| + for (const auto& id_page_pair : offline_pages_) {
|
| + if (id_page_pair.second.IsMarkedForDeletion())
|
| + continue;
|
| offline_pages.push_back(id_page_pair.second);
|
| + }
|
| return offline_pages;
|
| }
|
|
|
| @@ -180,8 +208,10 @@ const std::vector<OfflinePageItem> OfflinePageModel::GetPagesToCleanUp() const {
|
| std::vector<OfflinePageItem> offline_pages;
|
| base::Time now = base::Time::Now();
|
| for (const auto& id_page_pair : offline_pages_) {
|
| - if (now - id_page_pair.second.last_access_time > kPageCleanUpThreshold)
|
| + if (!id_page_pair.second.IsMarkedForDeletion() &&
|
| + now - id_page_pair.second.last_access_time > kPageCleanUpThreshold) {
|
| offline_pages.push_back(id_page_pair.second);
|
| + }
|
| }
|
| return offline_pages;
|
| }
|
| @@ -255,18 +285,93 @@ void OfflinePageModel::OnAddOfflinePageDone(OfflinePageArchiver* archiver,
|
| }
|
| InformSavePageDone(callback, result);
|
| DeletePendingArchiver(archiver);
|
| +
|
| + FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelChanged(this));
|
| }
|
|
|
| -void OfflinePageModel::OnUpdateOfflinePageDone(
|
| +void OfflinePageModel::OnMarkPageAccesseDone(
|
| const OfflinePageItem& offline_page_item, bool success) {
|
| // Update the item in the cache only upon success.
|
| if (success)
|
| offline_pages_[offline_page_item.bookmark_id] = offline_page_item;
|
| +
|
| + // No need to fire OfflinePageModelChanged event since updating access info
|
| + // should not have any impact to the UI.
|
| +}
|
| +
|
| +void OfflinePageModel::OnMarkPageForDeletionDone(
|
| + const OfflinePageItem& offline_page_item,
|
| + const DeletePageCallback& callback,
|
| + bool success) {
|
| + // Update the item in the cache only upon success.
|
| + if (success)
|
| + offline_pages_[offline_page_item.bookmark_id] = offline_page_item;
|
| +
|
| + InformDeletePageDone(callback, success ? DeletePageResult::SUCCESS
|
| + : DeletePageResult::STORE_FAILURE);
|
| +
|
| + if (!success)
|
| + return;
|
| +
|
| + // Schedule to do the final deletion.
|
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::Bind(&OfflinePageModel::FinalizePageDeletion,
|
| + weak_ptr_factory_.GetWeakPtr()),
|
| + kFinalDeletionDelay);
|
| +
|
| + FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelChanged(this));
|
| +}
|
| +
|
| +void OfflinePageModel::OnUndoOfflinePageDone(
|
| + const OfflinePageItem& offline_page, bool success) {
|
| + if (!success)
|
| + return;
|
| + offline_pages_[offline_page.bookmark_id] = offline_page;
|
| +
|
| + FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelChanged(this));
|
| +}
|
| +
|
| +void OfflinePageModel::FinalizePageDeletion() {
|
| + std::vector<int64> bookmark_ids_pending_deletion;
|
| + for (const auto& id_page_pair : offline_pages_) {
|
| + if (!id_page_pair.second.IsMarkedForDeletion())
|
| + continue;
|
| + bookmark_ids_pending_deletion.push_back(id_page_pair.second.bookmark_id);
|
| + }
|
| + DeletePagesByBookmarkId(bookmark_ids_pending_deletion, DeletePageCallback());
|
| +}
|
| +
|
| +void OfflinePageModel::UndoPageDeletion(int64 bookmark_id) {
|
| + auto iter = offline_pages_.find(bookmark_id);
|
| + if (iter == offline_pages_.end())
|
| + return;
|
| +
|
| + // Make a copy of the cached item and update it. The cached item should only
|
| + // be updated upon the successful store operation.
|
| + OfflinePageItem offline_page_item = iter->second;
|
| + if (!offline_page_item.IsMarkedForDeletion())
|
| + return;
|
| +
|
| + // Clear the flag to bring it back.
|
| + offline_page_item.ClearMarkForDeletion();
|
| + store_->AddOrUpdateOfflinePage(
|
| + offline_page_item,
|
| + base::Bind(&OfflinePageModel::OnUndoOfflinePageDone,
|
| + weak_ptr_factory_.GetWeakPtr(), offline_page_item));
|
| }
|
|
|
| void OfflinePageModel::BookmarkModelChanged() {
|
| }
|
|
|
| +void OfflinePageModel::BookmarkNodeAdded(bookmarks::BookmarkModel* model,
|
| + const bookmarks::BookmarkNode* parent,
|
| + int index) {
|
| + const bookmarks::BookmarkNode* node = parent->GetChild(index);
|
| + DCHECK(node);
|
| + UndoPageDeletion(node->id());
|
| +}
|
| +
|
| void OfflinePageModel::BookmarkNodeRemoved(
|
| bookmarks::BookmarkModel* model,
|
| const bookmarks::BookmarkNode* parent,
|
| @@ -275,13 +380,13 @@ void OfflinePageModel::BookmarkNodeRemoved(
|
| const std::set<GURL>& removed_urls) {
|
| if (!is_loaded_) {
|
| delayed_tasks_.push_back(
|
| - base::Bind(&OfflinePageModel::DeletePageByBookmarkId,
|
| + base::Bind(&OfflinePageModel::MarkPageForDeletion,
|
| weak_ptr_factory_.GetWeakPtr(),
|
| node->id(),
|
| base::Bind(&EmptyDeleteCallback)));
|
| return;
|
| }
|
| - DeletePageByBookmarkId(node->id(), base::Bind(&EmptyDeleteCallback));
|
| + MarkPageForDeletion(node->id(), base::Bind(&EmptyDeleteCallback));
|
| }
|
|
|
| void OfflinePageModel::OnLoadDone(
|
| @@ -300,6 +405,10 @@ void OfflinePageModel::OnLoadDone(
|
| delayed_task.Run();
|
| delayed_tasks_.clear();
|
|
|
| + // If there are pages that are marked for deletion, but not yet deleted and
|
| + // OfflinePageModel gets reloaded. Delete the pages now.
|
| + FinalizePageDeletion();
|
| +
|
| FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelLoaded(this));
|
| }
|
|
|
| @@ -365,7 +474,8 @@ void OfflinePageModel::InformDeletePageDone(const DeletePageCallback& callback,
|
| "OfflinePages.DeletePageResult",
|
| static_cast<int>(result),
|
| static_cast<int>(DeletePageResult::RESULT_COUNT));
|
| - callback.Run(result);
|
| + if (!callback.is_null())
|
| + callback.Run(result);
|
| }
|
|
|
| } // namespace offline_pages
|
|
|