OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |