| 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 |