| 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 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| 11 #include "base/files/scoped_temp_dir.h" | 11 #include "base/files/scoped_temp_dir.h" |
| 12 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
| 13 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
| 14 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
| 15 #include "base/strings/string16.h" | 15 #include "base/strings/string16.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.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_node.h" | 19 #include "components/bookmarks/browser/bookmark_node.h" |
| 20 #include "components/bookmarks/test/test_bookmark_client.h" |
| 19 #include "components/offline_pages/offline_page_item.h" | 21 #include "components/offline_pages/offline_page_item.h" |
| 20 #include "components/offline_pages/offline_page_metadata_store.h" | 22 #include "components/offline_pages/offline_page_metadata_store.h" |
| 21 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 22 #include "url/gurl.h" | 24 #include "url/gurl.h" |
| 23 | 25 |
| 24 using SavePageResult = offline_pages::OfflinePageModel::SavePageResult; | 26 using SavePageResult = offline_pages::OfflinePageModel::SavePageResult; |
| 25 using DeletePageResult = offline_pages::OfflinePageModel::DeletePageResult; | 27 using DeletePageResult = offline_pages::OfflinePageModel::DeletePageResult; |
| 26 | 28 |
| 27 namespace offline_pages { | 29 namespace offline_pages { |
| 28 | 30 |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 | 210 |
| 209 // OfflinePageMetadataStore callbacks. | 211 // OfflinePageMetadataStore callbacks. |
| 210 void OnStoreUpdateDone(bool /* success */); | 212 void OnStoreUpdateDone(bool /* success */); |
| 211 | 213 |
| 212 scoped_ptr<OfflinePageTestArchiver> BuildArchiver( | 214 scoped_ptr<OfflinePageTestArchiver> BuildArchiver( |
| 213 const GURL& url, | 215 const GURL& url, |
| 214 OfflinePageArchiver::ArchiverResult result); | 216 OfflinePageArchiver::ArchiverResult result); |
| 215 scoped_ptr<OfflinePageMetadataStore> BuildStore(); | 217 scoped_ptr<OfflinePageMetadataStore> BuildStore(); |
| 216 scoped_ptr<OfflinePageModel> BuildModel( | 218 scoped_ptr<OfflinePageModel> BuildModel( |
| 217 scoped_ptr<OfflinePageMetadataStore> store); | 219 scoped_ptr<OfflinePageMetadataStore> store); |
| 218 void ResetModel(); | 220 void ResetModel(bookmarks::BookmarkModel* bookmarks); |
| 219 | 221 |
| 220 // Utility methods. | 222 // Utility methods. |
| 221 void PumpLoop(); | 223 void PumpLoop(); |
| 222 void ResetResults(); | 224 void ResetResults(); |
| 223 | 225 |
| 224 scoped_refptr<base::SingleThreadTaskRunner> task_runner() { | 226 scoped_refptr<base::SingleThreadTaskRunner> task_runner() { |
| 225 return message_loop_.task_runner(); | 227 return message_loop_.task_runner(); |
| 226 } | 228 } |
| 227 | 229 |
| 228 OfflinePageModel* model() { return model_.get(); } | 230 OfflinePageModel* model() { return model_.get(); } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 return scoped_ptr<OfflinePageMetadataStore>( | 355 return scoped_ptr<OfflinePageMetadataStore>( |
| 354 new OfflinePageTestStore(task_runner())); | 356 new OfflinePageTestStore(task_runner())); |
| 355 } | 357 } |
| 356 | 358 |
| 357 scoped_ptr<OfflinePageModel> OfflinePageModelTest::BuildModel( | 359 scoped_ptr<OfflinePageModel> OfflinePageModelTest::BuildModel( |
| 358 scoped_ptr<OfflinePageMetadataStore> store) { | 360 scoped_ptr<OfflinePageMetadataStore> store) { |
| 359 return scoped_ptr<OfflinePageModel>( | 361 return scoped_ptr<OfflinePageModel>( |
| 360 new OfflinePageModel(store.Pass(), temp_dir_.path(), task_runner())); | 362 new OfflinePageModel(store.Pass(), temp_dir_.path(), task_runner())); |
| 361 } | 363 } |
| 362 | 364 |
| 363 void OfflinePageModelTest::ResetModel() { | 365 void OfflinePageModelTest::ResetModel(bookmarks::BookmarkModel* bookmarks) { |
| 364 model_->RemoveObserver(this); | 366 model_->RemoveObserver(this); |
| 365 OfflinePageTestStore* old_store = GetStore(); | 367 OfflinePageTestStore* old_store = GetStore(); |
| 366 scoped_ptr<OfflinePageMetadataStore> new_store( | 368 scoped_ptr<OfflinePageMetadataStore> new_store( |
| 367 new OfflinePageTestStore(*old_store)); | 369 new OfflinePageTestStore(*old_store)); |
| 368 model_ = BuildModel(new_store.Pass()).Pass(); | 370 model_ = BuildModel(new_store.Pass()).Pass(); |
| 369 model_->AddObserver(this); | 371 model_->AddObserver(this); |
| 372 if (bookmarks) |
| 373 model_->Start(bookmarks); |
| 370 PumpLoop(); | 374 PumpLoop(); |
| 371 } | 375 } |
| 372 | 376 |
| 373 void OfflinePageModelTest::PumpLoop() { | 377 void OfflinePageModelTest::PumpLoop() { |
| 374 base::RunLoop().RunUntilIdle(); | 378 base::RunLoop().RunUntilIdle(); |
| 375 } | 379 } |
| 376 | 380 |
| 377 void OfflinePageModelTest::ResetResults() { | 381 void OfflinePageModelTest::ResetResults() { |
| 378 last_save_result_ = SavePageResult::CANCELLED; | 382 last_save_result_ = SavePageResult::CANCELLED; |
| 379 last_delete_result_ = DeletePageResult::CANCELLED; | 383 last_delete_result_ = DeletePageResult::CANCELLED; |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 // Try to delete this page. | 720 // Try to delete this page. |
| 717 GetStore()->set_test_scenario( | 721 GetStore()->set_test_scenario( |
| 718 OfflinePageTestStore::TestScenario::REMOVE_FAILED); | 722 OfflinePageTestStore::TestScenario::REMOVE_FAILED); |
| 719 model()->DeletePageByBookmarkId( | 723 model()->DeletePageByBookmarkId( |
| 720 kTestPageBookmarkId1, base::Bind(&OfflinePageModelTest::OnDeletePageDone, | 724 kTestPageBookmarkId1, base::Bind(&OfflinePageModelTest::OnDeletePageDone, |
| 721 AsWeakPtr())); | 725 AsWeakPtr())); |
| 722 PumpLoop(); | 726 PumpLoop(); |
| 723 EXPECT_EQ(DeletePageResult::STORE_FAILURE, last_delete_result()); | 727 EXPECT_EQ(DeletePageResult::STORE_FAILURE, last_delete_result()); |
| 724 } | 728 } |
| 725 | 729 |
| 730 // Test for case, where offline copy is missing and it is detected by a |
| 731 // metadata check called directly. |
| 726 TEST_F(OfflinePageModelTest, DetectThatOfflineCopyIsMissing) { | 732 TEST_F(OfflinePageModelTest, DetectThatOfflineCopyIsMissing) { |
| 733 bookmarks::TestBookmarkClient test_bookmark_client; |
| 734 scoped_ptr<bookmarks::BookmarkModel> bookmarks_model( |
| 735 test_bookmark_client.CreateModel()); |
| 736 model()->Start(bookmarks_model.get()); |
| 737 |
| 738 const bookmarks::BookmarkNode* root = bookmarks_model->bookmark_bar_node(); |
| 739 const base::string16 title(base::ASCIIToUTF16("foo")); |
| 740 const bookmarks::BookmarkNode* new_node = |
| 741 bookmarks_model->AddURL(root, 0, title, kTestUrl); |
| 742 |
| 743 // Save a page. |
| 744 scoped_ptr<OfflinePageTestArchiver> archiver( |
| 745 BuildArchiver(kTestUrl, |
| 746 OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) |
| 747 .Pass()); |
| 748 model()->SavePage( |
| 749 kTestUrl, new_node->id(), archiver.Pass(), |
| 750 base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr())); |
| 751 PumpLoop(); |
| 752 |
| 753 ResetResults(); |
| 754 |
| 755 const OfflinePageItem* page = model()->GetPageByBookmarkId(new_node->id()); |
| 756 // Delete the offline copy of the page and check the metadata. |
| 757 base::DeleteFile(page->file_path, false); |
| 758 model()->CheckMetadataConsistency(false); |
| 759 PumpLoop(); |
| 760 |
| 761 EXPECT_EQ(last_deleted_bookmark_id(), new_node->id()); |
| 762 EXPECT_EQ(0UL, model()->GetAllPages().size()); |
| 763 } |
| 764 |
| 765 // Test for case, where offline copy is missing and it is detected by a |
| 766 // metadata check initiated as part of offline page model load. |
| 767 TEST_F(OfflinePageModelTest, DetectThatOfflineCopyIsMissingAfterLoad) { |
| 768 bookmarks::TestBookmarkClient test_bookmark_client; |
| 769 scoped_ptr<bookmarks::BookmarkModel> bookmarks_model( |
| 770 test_bookmark_client.CreateModel()); |
| 771 model()->Start(bookmarks_model.get()); |
| 772 |
| 773 const bookmarks::BookmarkNode* root = bookmarks_model->bookmark_bar_node(); |
| 774 const base::string16 title(base::ASCIIToUTF16("foo")); |
| 775 const bookmarks::BookmarkNode* new_node = |
| 776 bookmarks_model->AddURL(root, 0, title, kTestUrl); |
| 777 |
| 778 // Save a page. |
| 779 scoped_ptr<OfflinePageTestArchiver> archiver( |
| 780 BuildArchiver(kTestUrl, |
| 781 OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) |
| 782 .Pass()); |
| 783 model()->SavePage( |
| 784 kTestUrl, new_node->id(), archiver.Pass(), |
| 785 base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr())); |
| 786 PumpLoop(); |
| 787 |
| 788 ResetResults(); |
| 789 |
| 790 const OfflinePageItem* page = model()->GetPageByBookmarkId(new_node->id()); |
| 791 // Delete the offline copy of the page and check the metadata. |
| 792 base::DeleteFile(page->file_path, false); |
| 793 ResetModel(bookmarks_model.get()); |
| 794 // Reseting the model should trigger the metadata consistency check as well. |
| 795 PumpLoop(); |
| 796 |
| 797 EXPECT_EQ(last_deleted_bookmark_id(), new_node->id()); |
| 798 EXPECT_EQ(0UL, model()->GetAllPages().size()); |
| 799 } |
| 800 |
| 801 // Test for offline page missing a bookmark in the bookmarks model. |
| 802 TEST_F(OfflinePageModelTest, DetectThatBookmarkIsMissingAfterLoad) { |
| 727 // Save a page. | 803 // Save a page. |
| 728 scoped_ptr<OfflinePageTestArchiver> archiver( | 804 scoped_ptr<OfflinePageTestArchiver> archiver( |
| 729 BuildArchiver(kTestUrl, | 805 BuildArchiver(kTestUrl, |
| 730 OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) | 806 OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) |
| 731 .Pass()); | 807 .Pass()); |
| 732 model()->SavePage( | 808 model()->SavePage( |
| 733 kTestUrl, kTestPageBookmarkId1, archiver.Pass(), | 809 kTestUrl, kTestPageBookmarkId1, archiver.Pass(), |
| 734 base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr())); | 810 base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr())); |
| 735 PumpLoop(); | 811 PumpLoop(); |
| 736 | 812 |
| 737 ResetResults(); | 813 ResetResults(); |
| 738 | 814 |
| 739 const OfflinePageItem* page = | 815 // There will be a bookmark model to check against, where the bookmark ID |
| 740 model()->GetPageByBookmarkId(kTestPageBookmarkId1); | 816 // cannot be found. |
| 741 // Delete the offline copy of the page and check the metadata. | 817 bookmarks::TestBookmarkClient test_bookmark_client; |
| 742 base::DeleteFile(page->file_path, false); | 818 scoped_ptr<bookmarks::BookmarkModel> bookmarks_model( |
| 743 model()->CheckForExternalFileDeletion(); | 819 test_bookmark_client.CreateModel()); |
| 820 ResetModel(bookmarks_model.get()); |
| 744 PumpLoop(); | 821 PumpLoop(); |
| 745 | 822 |
| 746 EXPECT_EQ(last_deleted_bookmark_id(), kTestPageBookmarkId1); | 823 EXPECT_EQ(last_deleted_bookmark_id(), kTestPageBookmarkId1); |
| 747 EXPECT_EQ(0UL, model()->GetAllPages().size()); | |
| 748 } | |
| 749 | |
| 750 TEST_F(OfflinePageModelTest, DetectThatOfflineCopyIsMissingAfterLoad) { | |
| 751 // Save a page. | |
| 752 scoped_ptr<OfflinePageTestArchiver> archiver( | |
| 753 BuildArchiver(kTestUrl, | |
| 754 OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) | |
| 755 .Pass()); | |
| 756 model()->SavePage( | |
| 757 kTestUrl, kTestPageBookmarkId1, archiver.Pass(), | |
| 758 base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr())); | |
| 759 PumpLoop(); | |
| 760 | |
| 761 ResetResults(); | |
| 762 | |
| 763 const OfflinePageItem* page = | |
| 764 model()->GetPageByBookmarkId(kTestPageBookmarkId1); | |
| 765 // Delete the offline copy of the page and check the metadata. | |
| 766 base::DeleteFile(page->file_path, false); | |
| 767 // Reseting the model should trigger the metadata consistency check as well. | |
| 768 ResetModel(); | |
| 769 PumpLoop(); | |
| 770 | |
| 771 EXPECT_EQ(last_deleted_bookmark_id(), kTestPageBookmarkId1); | |
| 772 EXPECT_EQ(0UL, model()->GetAllPages().size()); | 824 EXPECT_EQ(0UL, model()->GetAllPages().size()); |
| 773 } | 825 } |
| 774 | 826 |
| 775 TEST_F(OfflinePageModelTest, GetPageByBookmarkId) { | 827 TEST_F(OfflinePageModelTest, GetPageByBookmarkId) { |
| 776 scoped_ptr<OfflinePageTestArchiver> archiver( | 828 scoped_ptr<OfflinePageTestArchiver> archiver( |
| 777 BuildArchiver(kTestUrl, | 829 BuildArchiver(kTestUrl, |
| 778 OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) | 830 OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) |
| 779 .Pass()); | 831 .Pass()); |
| 780 model()->SavePage( | 832 model()->SavePage( |
| 781 kTestUrl, kTestPageBookmarkId1, archiver.Pass(), | 833 kTestUrl, kTestPageBookmarkId1, archiver.Pass(), |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 911 BuildArchiver(kTestUrl3, | 963 BuildArchiver(kTestUrl3, |
| 912 OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) | 964 OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) |
| 913 .Pass()); | 965 .Pass()); |
| 914 model()->SavePage( | 966 model()->SavePage( |
| 915 kTestUrl3, kTestPageBookmarkId3, archiver3.Pass(), | 967 kTestUrl3, kTestPageBookmarkId3, archiver3.Pass(), |
| 916 base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr())); | 968 base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr())); |
| 917 PumpLoop(); | 969 PumpLoop(); |
| 918 GetStore()->UpdateLastAccessTime(kTestPageBookmarkId3, | 970 GetStore()->UpdateLastAccessTime(kTestPageBookmarkId3, |
| 919 now - base::TimeDelta::FromDays(29)); | 971 now - base::TimeDelta::FromDays(29)); |
| 920 | 972 |
| 921 ResetModel(); | 973 ResetModel(nullptr); |
| 922 | 974 |
| 923 // Only page_1 and page_2 are expected to be picked up by the model as page_3 | 975 // Only page_1 and page_2 are expected to be picked up by the model as page_3 |
| 924 // has not been in the store long enough. | 976 // has not been in the store long enough. |
| 925 std::vector<OfflinePageItem> pages_to_clean_up = model()->GetPagesToCleanUp(); | 977 std::vector<OfflinePageItem> pages_to_clean_up = model()->GetPagesToCleanUp(); |
| 926 EXPECT_EQ(2UL, pages_to_clean_up.size()); | 978 EXPECT_EQ(2UL, pages_to_clean_up.size()); |
| 927 EXPECT_EQ(kTestUrl, pages_to_clean_up[0].url); | 979 EXPECT_EQ(kTestUrl, pages_to_clean_up[0].url); |
| 928 EXPECT_EQ(kTestPageBookmarkId1, pages_to_clean_up[0].bookmark_id); | 980 EXPECT_EQ(kTestPageBookmarkId1, pages_to_clean_up[0].bookmark_id); |
| 929 EXPECT_EQ(kTestUrl2, pages_to_clean_up[1].url); | 981 EXPECT_EQ(kTestUrl2, pages_to_clean_up[1].url); |
| 930 EXPECT_EQ(kTestPageBookmarkId2, pages_to_clean_up[1].bookmark_id); | 982 EXPECT_EQ(kTestPageBookmarkId2, pages_to_clean_up[1].bookmark_id); |
| 931 } | 983 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 | 1060 |
| 1009 // Chrome should not crash when a bookmark with no offline copy is changed. | 1061 // Chrome should not crash when a bookmark with no offline copy is changed. |
| 1010 // http://crbug.com/560518 | 1062 // http://crbug.com/560518 |
| 1011 bookmark_node.set_url(kTestUrl); | 1063 bookmark_node.set_url(kTestUrl); |
| 1012 model()->BookmarkNodeChanged(nullptr, &bookmark_node); | 1064 model()->BookmarkNodeChanged(nullptr, &bookmark_node); |
| 1013 PumpLoop(); | 1065 PumpLoop(); |
| 1014 EXPECT_EQ(0UL, model()->GetAllPages().size()); | 1066 EXPECT_EQ(0UL, model()->GetAllPages().size()); |
| 1015 } | 1067 } |
| 1016 | 1068 |
| 1017 } // namespace offline_pages | 1069 } // namespace offline_pages |
| OLD | NEW |