Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(357)

Side by Side Diff: components/offline_pages/offline_page_model.cc

Issue 1480723002: [Offline pages] Detecting offline pages missing bookmarks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/offline_pages/offline_page_model.h" 5 #include "components/offline_pages/offline_page_model.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
15 #include "base/sequenced_task_runner.h" 15 #include "base/sequenced_task_runner.h"
16 #include "base/thread_task_runner_handle.h" 16 #include "base/thread_task_runner_handle.h"
17 #include "base/time/time.h" 17 #include "base/time/time.h"
18 #include "components/bookmarks/browser/bookmark_model.h" 18 #include "components/bookmarks/browser/bookmark_model.h"
19 #include "components/bookmarks/browser/bookmark_node.h" 19 #include "components/bookmarks/browser/bookmark_node.h"
20 #include "components/bookmarks/browser/bookmark_utils.h"
20 #include "components/offline_pages/offline_page_item.h" 21 #include "components/offline_pages/offline_page_item.h"
21 #include "url/gurl.h" 22 #include "url/gurl.h"
22 23
23 using ArchiverResult = offline_pages::OfflinePageArchiver::ArchiverResult; 24 using ArchiverResult = offline_pages::OfflinePageArchiver::ArchiverResult;
24 using SavePageResult = offline_pages::OfflinePageModel::SavePageResult; 25 using SavePageResult = offline_pages::OfflinePageModel::SavePageResult;
25 26
26 namespace offline_pages { 27 namespace offline_pages {
27 28
28 namespace { 29 namespace {
29 30
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 return url.SchemeIsHTTPOrHTTPS(); 109 return url.SchemeIsHTTPOrHTTPS();
109 } 110 }
110 111
111 OfflinePageModel::OfflinePageModel( 112 OfflinePageModel::OfflinePageModel(
112 scoped_ptr<OfflinePageMetadataStore> store, 113 scoped_ptr<OfflinePageMetadataStore> store,
113 const base::FilePath& archives_dir, 114 const base::FilePath& archives_dir,
114 const scoped_refptr<base::SequencedTaskRunner>& task_runner) 115 const scoped_refptr<base::SequencedTaskRunner>& task_runner)
115 : store_(store.Pass()), 116 : store_(store.Pass()),
116 archives_dir_(archives_dir), 117 archives_dir_(archives_dir),
117 is_loaded_(false), 118 is_loaded_(false),
119 metadata_check_in_progress_(false),
118 task_runner_(task_runner), 120 task_runner_(task_runner),
121 bookmarks_model_(nullptr),
119 scoped_observer_(this), 122 scoped_observer_(this),
120 weak_ptr_factory_(this) { 123 weak_ptr_factory_(this) {
121 task_runner_->PostTaskAndReply( 124 task_runner_->PostTaskAndReply(
122 FROM_HERE, base::Bind(EnsureArchivesDirCreated, archives_dir_), 125 FROM_HERE, base::Bind(EnsureArchivesDirCreated, archives_dir_),
123 base::Bind(&OfflinePageModel::OnEnsureArchivesDirCreatedDone, 126 base::Bind(&OfflinePageModel::OnEnsureArchivesDirCreatedDone,
124 weak_ptr_factory_.GetWeakPtr())); 127 weak_ptr_factory_.GetWeakPtr()));
125 } 128 }
126 129
127 OfflinePageModel::~OfflinePageModel() { 130 OfflinePageModel::~OfflinePageModel() {
128 } 131 }
129 132
130 void OfflinePageModel::Start(bookmarks::BookmarkModel* model) { 133 void OfflinePageModel::Start(bookmarks::BookmarkModel* model) {
134 bookmarks_model_ = model;
131 scoped_observer_.Add(model); 135 scoped_observer_.Add(model);
132 } 136 }
133 137
134 void OfflinePageModel::Shutdown() { 138 void OfflinePageModel::Shutdown() {
135 scoped_observer_.RemoveAll(); 139 scoped_observer_.RemoveAll();
136 } 140 }
137 141
138 void OfflinePageModel::AddObserver(Observer* observer) { 142 void OfflinePageModel::AddObserver(Observer* observer) {
139 observers_.AddObserver(observer); 143 observers_.AddObserver(observer);
140 } 144 }
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 const OfflinePageItem* OfflinePageModel::GetPageByOnlineURL( 304 const OfflinePageItem* OfflinePageModel::GetPageByOnlineURL(
301 const GURL& online_url) const { 305 const GURL& online_url) const {
302 for (auto iter = offline_pages_.begin(); iter != offline_pages_.end(); 306 for (auto iter = offline_pages_.begin(); iter != offline_pages_.end();
303 ++iter) { 307 ++iter) {
304 if (iter->second.url == online_url) 308 if (iter->second.url == online_url)
305 return &(iter->second); 309 return &(iter->second);
306 } 310 }
307 return nullptr; 311 return nullptr;
308 } 312 }
309 313
310 void OfflinePageModel::CheckForExternalFileDeletion() { 314 void OfflinePageModel::CheckMetadataConsistency(bool finalize_deletion) {
311 DCHECK(is_loaded_); 315 if (metadata_check_in_progress_ || !is_loaded_ || !bookmarks_model_ ||
312 316 !bookmarks_model_->loaded()) {
313 std::vector<std::pair<int64, base::FilePath>> id_path_pairs; 317 return;
314 for (const auto& id_page_pair : offline_pages_) {
315 id_path_pairs.push_back(
316 std::make_pair(id_page_pair.first, id_page_pair.second.file_path));
317 } 318 }
318 319
319 std::vector<int64>* ids_of_pages_missing_archive_file = 320 metadata_check_in_progress_ = true;
320 new std::vector<int64>(); 321
321 task_runner_->PostTaskAndReply( 322 std::vector<int64> ids_of_pages_to_delete;
322 FROM_HERE, base::Bind(&FindPagesMissingArchiveFile, id_path_pairs, 323 for (const auto& iter : offline_pages_) {
323 ids_of_pages_missing_archive_file), 324 if (!bookmarks::GetBookmarkNodeByID(bookmarks_model_, iter.first) ||
324 base::Bind(&OfflinePageModel::OnFindPagesMissingArchiveFile, 325 (finalize_deletion && iter.second.IsMarkedForDeletion())) {
325 weak_ptr_factory_.GetWeakPtr(), 326 ids_of_pages_to_delete.push_back(iter.first);
326 base::Owned(ids_of_pages_missing_archive_file))); 327 }
328 }
329
330 DeletePagesByBookmarkId(
331 ids_of_pages_to_delete,
332 base::Bind(&OfflinePageModel::CheckForExternalFileDeletion,
333 weak_ptr_factory_.GetWeakPtr()));
327 } 334 }
328 335
329 OfflinePageMetadataStore* OfflinePageModel::GetStoreForTesting() { 336 OfflinePageMetadataStore* OfflinePageModel::GetStoreForTesting() {
330 return store_.get(); 337 return store_.get();
331 } 338 }
332 339
333 void OfflinePageModel::OnCreateArchiveDone(const GURL& requested_url, 340 void OfflinePageModel::OnCreateArchiveDone(const GURL& requested_url,
334 int64 bookmark_id, 341 int64 bookmark_id,
335 const base::Time& start_time, 342 const base::Time& start_time,
336 const SavePageCallback& callback, 343 const SavePageCallback& callback,
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 offline_page_item.ClearMarkForDeletion(); 462 offline_page_item.ClearMarkForDeletion();
456 store_->AddOrUpdateOfflinePage( 463 store_->AddOrUpdateOfflinePage(
457 offline_page_item, 464 offline_page_item,
458 base::Bind(&OfflinePageModel::OnUndoOfflinePageDone, 465 base::Bind(&OfflinePageModel::OnUndoOfflinePageDone,
459 weak_ptr_factory_.GetWeakPtr(), offline_page_item)); 466 weak_ptr_factory_.GetWeakPtr(), offline_page_item));
460 } 467 }
461 468
462 void OfflinePageModel::BookmarkModelChanged() { 469 void OfflinePageModel::BookmarkModelChanged() {
463 } 470 }
464 471
472 void OfflinePageModel::BookmarkModelLoaded(bookmarks::BookmarkModel* model,
473 bool ids_reassigned) {
474 CheckMetadataConsistency(true);
475 }
476
477 void OfflinePageModel::BookmarkModelBeingDeleted(
478 bookmarks::BookmarkModel* model) {
479 bookmarks_model_ = nullptr;
480 }
481
465 void OfflinePageModel::BookmarkNodeAdded(bookmarks::BookmarkModel* model, 482 void OfflinePageModel::BookmarkNodeAdded(bookmarks::BookmarkModel* model,
466 const bookmarks::BookmarkNode* parent, 483 const bookmarks::BookmarkNode* parent,
467 int index) { 484 int index) {
468 const bookmarks::BookmarkNode* node = parent->GetChild(index); 485 const bookmarks::BookmarkNode* node = parent->GetChild(index);
469 DCHECK(node); 486 DCHECK(node);
470 UndoPageDeletion(node->id()); 487 UndoPageDeletion(node->id());
471 } 488 }
472 489
473 void OfflinePageModel::BookmarkNodeRemoved( 490 void OfflinePageModel::BookmarkNodeRemoved(
474 bookmarks::BookmarkModel* model, 491 bookmarks::BookmarkModel* model,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 // TODO(jianli): rebuild the store upon failure. 528 // TODO(jianli): rebuild the store upon failure.
512 529
513 if (load_status == OfflinePageMetadataStore::LOAD_SUCCEEDED) 530 if (load_status == OfflinePageMetadataStore::LOAD_SUCCEEDED)
514 CacheLoadedData(offline_pages); 531 CacheLoadedData(offline_pages);
515 532
516 // Run all the delayed tasks. 533 // Run all the delayed tasks.
517 for (const auto& delayed_task : delayed_tasks_) 534 for (const auto& delayed_task : delayed_tasks_)
518 delayed_task.Run(); 535 delayed_task.Run();
519 delayed_tasks_.clear(); 536 delayed_tasks_.clear();
520 537
521 // If there are pages that are marked for deletion, but not yet deleted and
522 // OfflinePageModel gets reloaded. Delete the pages now.
523 FinalizePageDeletion();
524
525 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelLoaded(this)); 538 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelLoaded(this));
526 539
527 CheckForExternalFileDeletion(); 540 // Fix problems with offline page metadata:
541 // * remove pages missing archive files
542 // * remove pages that don't have a matching bookmark node
543 // * remove pages pending finalization.
544 CheckMetadataConsistency(true);
528 } 545 }
529 546
530 void OfflinePageModel::InformSavePageDone(const SavePageCallback& callback, 547 void OfflinePageModel::InformSavePageDone(const SavePageCallback& callback,
531 SavePageResult result) { 548 SavePageResult result) {
532 UMA_HISTOGRAM_ENUMERATION( 549 UMA_HISTOGRAM_ENUMERATION(
533 "OfflinePages.SavePageResult", 550 "OfflinePages.SavePageResult",
534 static_cast<int>(result), 551 static_cast<int>(result),
535 static_cast<int>(SavePageResult::RESULT_COUNT)); 552 static_cast<int>(SavePageResult::RESULT_COUNT));
536 callback.Run(result); 553 callback.Run(result);
537 } 554 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 void OfflinePageModel::InformDeletePageDone(const DeletePageCallback& callback, 635 void OfflinePageModel::InformDeletePageDone(const DeletePageCallback& callback,
619 DeletePageResult result) { 636 DeletePageResult result) {
620 UMA_HISTOGRAM_ENUMERATION( 637 UMA_HISTOGRAM_ENUMERATION(
621 "OfflinePages.DeletePageResult", 638 "OfflinePages.DeletePageResult",
622 static_cast<int>(result), 639 static_cast<int>(result),
623 static_cast<int>(DeletePageResult::RESULT_COUNT)); 640 static_cast<int>(DeletePageResult::RESULT_COUNT));
624 if (!callback.is_null()) 641 if (!callback.is_null())
625 callback.Run(result); 642 callback.Run(result);
626 } 643 }
627 644
645 void OfflinePageModel::CheckForExternalFileDeletion(
646 DeletePageResult /* result */) {
647 std::vector<std::pair<int64, base::FilePath>> id_path_pairs;
648 for (const auto& id_page_pair : offline_pages_) {
649 id_path_pairs.push_back(
650 std::make_pair(id_page_pair.first, id_page_pair.second.file_path));
651 }
652
653 std::vector<int64>* ids_of_pages_missing_archive_file =
654 new std::vector<int64>();
655 task_runner_->PostTaskAndReply(
656 FROM_HERE, base::Bind(&FindPagesMissingArchiveFile, id_path_pairs,
657 ids_of_pages_missing_archive_file),
658 base::Bind(&OfflinePageModel::OnFindPagesMissingArchiveFile,
659 weak_ptr_factory_.GetWeakPtr(),
660 base::Owned(ids_of_pages_missing_archive_file)));
661 }
662
628 void OfflinePageModel::OnFindPagesMissingArchiveFile( 663 void OfflinePageModel::OnFindPagesMissingArchiveFile(
629 const std::vector<int64>* ids_of_pages_missing_archive_file) { 664 const std::vector<int64>* ids_of_pages_missing_archive_file) {
630 DCHECK(ids_of_pages_missing_archive_file); 665 DCHECK(ids_of_pages_missing_archive_file);
631 if (ids_of_pages_missing_archive_file->empty()) 666 if (ids_of_pages_missing_archive_file->empty())
632 return; 667 return;
633 668
634 DeletePageCallback done_callback( 669 DeletePageCallback done_callback(
635 base::Bind(&OfflinePageModel::OnRemoveOfflinePagesMissingArchiveFileDone, 670 base::Bind(&OfflinePageModel::OnRemoveOfflinePagesMissingArchiveFileDone,
636 weak_ptr_factory_.GetWeakPtr(), 671 weak_ptr_factory_.GetWeakPtr(),
637 *ids_of_pages_missing_archive_file)); 672 *ids_of_pages_missing_archive_file));
638 673
639 store_->RemoveOfflinePages( 674 store_->RemoveOfflinePages(
640 *ids_of_pages_missing_archive_file, 675 *ids_of_pages_missing_archive_file,
641 base::Bind(&OfflinePageModel::OnRemoveOfflinePagesDone, 676 base::Bind(&OfflinePageModel::OnRemoveOfflinePagesDone,
642 weak_ptr_factory_.GetWeakPtr(), 677 weak_ptr_factory_.GetWeakPtr(),
643 *ids_of_pages_missing_archive_file, 678 *ids_of_pages_missing_archive_file,
644 done_callback)); 679 done_callback));
645 } 680 }
646 681
647 void OfflinePageModel::OnRemoveOfflinePagesMissingArchiveFileDone( 682 void OfflinePageModel::OnRemoveOfflinePagesMissingArchiveFileDone(
648 const std::vector<int64>& bookmark_ids, 683 const std::vector<int64>& bookmark_ids,
649 OfflinePageModel::DeletePageResult /* result */) { 684 OfflinePageModel::DeletePageResult /* result */) {
650 for (int64 bookmark_id : bookmark_ids) { 685 for (int64 bookmark_id : bookmark_ids) {
651 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageDeleted(bookmark_id)); 686 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageDeleted(bookmark_id));
652 } 687 }
688 // Metadata check is concluded here.
689 metadata_check_in_progress_ = false;
653 } 690 }
654 691
655 void OfflinePageModel::OnRemoveAllFilesDoneForClearAll( 692 void OfflinePageModel::OnRemoveAllFilesDoneForClearAll(
656 const base::Closure& callback, 693 const base::Closure& callback,
657 DeletePageResult result) { 694 DeletePageResult result) {
658 store_->Reset(base::Bind(&OfflinePageModel::OnResetStoreDoneForClearAll, 695 store_->Reset(base::Bind(&OfflinePageModel::OnResetStoreDoneForClearAll,
659 weak_ptr_factory_.GetWeakPtr(), 696 weak_ptr_factory_.GetWeakPtr(),
660 callback)); 697 callback));
661 } 698 }
662 699
(...skipping 26 matching lines...) Expand all
689 } 726 }
690 727
691 void OfflinePageModel::CacheLoadedData( 728 void OfflinePageModel::CacheLoadedData(
692 const std::vector<OfflinePageItem>& offline_pages) { 729 const std::vector<OfflinePageItem>& offline_pages) {
693 offline_pages_.clear(); 730 offline_pages_.clear();
694 for (const auto& offline_page : offline_pages) 731 for (const auto& offline_page : offline_pages)
695 offline_pages_[offline_page.bookmark_id] = offline_page; 732 offline_pages_[offline_page.bookmark_id] = offline_page;
696 } 733 }
697 734
698 } // namespace offline_pages 735 } // namespace offline_pages
OLDNEW
« no previous file with comments | « components/offline_pages/offline_page_model.h ('k') | components/offline_pages/offline_page_model_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698