| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "chrome/browser/ntp_snippets/download_suggestions_provider.h" | 5 #include "chrome/browser/ntp_snippets/download_suggestions_provider.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 os << "LOADING_ERROR"; | 83 os << "LOADING_ERROR"; |
| 84 break; | 84 break; |
| 85 } | 85 } |
| 86 return os; | 86 return os; |
| 87 } | 87 } |
| 88 | 88 |
| 89 } // namespace ntp_snippets | 89 } // namespace ntp_snippets |
| 90 | 90 |
| 91 namespace { | 91 namespace { |
| 92 | 92 |
| 93 const int kDefaultMaxDownloadAgeHours = 6 * 7 * 24; |
| 94 |
| 95 // Tue, 31 Jan 2017 13:00:00 UTC |
| 96 const base::Time now = base::Time::FromJavaTime(1485867600000); |
| 97 |
| 93 // TODO(vitaliii): Move this and outputting functions above to common file and | 98 // TODO(vitaliii): Move this and outputting functions above to common file and |
| 94 // replace remaining |Property(&ContentSuggestion::url, GURL("some_url"))|. | 99 // replace remaining |Property(&ContentSuggestion::url, GURL("some_url"))|. |
| 95 // See crbug.com/655513. | 100 // See crbug.com/655513. |
| 96 MATCHER_P(HasUrl, url, "") { | 101 MATCHER_P(HasUrl, url, "") { |
| 97 *result_listener << "expected URL: " << url | 102 *result_listener << "expected URL: " << url |
| 98 << "has URL: " << arg.url().spec(); | 103 << "has URL: " << arg.url().spec(); |
| 99 return arg.url().spec() == url; | 104 return arg.url().spec() == url; |
| 100 } | 105 } |
| 101 | 106 |
| 102 MATCHER_P3(HasDownloadSuggestionExtra, | 107 MATCHER_P3(HasDownloadSuggestionExtra, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 std::vector<OfflinePageItem> CreateDummyOfflinePages( | 142 std::vector<OfflinePageItem> CreateDummyOfflinePages( |
| 138 const std::vector<int>& ids) { | 143 const std::vector<int>& ids) { |
| 139 std::vector<OfflinePageItem> result; | 144 std::vector<OfflinePageItem> result; |
| 140 for (int id : ids) { | 145 for (int id : ids) { |
| 141 result.push_back(CreateDummyOfflinePage(id)); | 146 result.push_back(CreateDummyOfflinePage(id)); |
| 142 } | 147 } |
| 143 | 148 |
| 144 return result; | 149 return result; |
| 145 } | 150 } |
| 146 | 151 |
| 147 OfflinePageItem CreateDummyOfflinePage(int id, base::Time time) { | |
| 148 OfflinePageItem item = CreateDummyOfflinePage(id); | |
| 149 item.creation_time = time; | |
| 150 return item; | |
| 151 } | |
| 152 | |
| 153 std::unique_ptr<FakeDownloadItem> CreateDummyAssetDownload(int id) { | 152 std::unique_ptr<FakeDownloadItem> CreateDummyAssetDownload(int id) { |
| 154 std::unique_ptr<FakeDownloadItem> item = base::MakeUnique<FakeDownloadItem>(); | 153 std::unique_ptr<FakeDownloadItem> item = base::MakeUnique<FakeDownloadItem>(); |
| 155 item->SetId(id); | 154 item->SetId(id); |
| 156 std::string id_string = base::IntToString(id); | 155 std::string id_string = base::IntToString(id); |
| 157 item->SetTargetFilePath( | 156 item->SetTargetFilePath( |
| 158 base::FilePath::FromUTF8Unsafe("folder/file" + id_string + ".mhtml")); | 157 base::FilePath::FromUTF8Unsafe("folder/file" + id_string + ".mhtml")); |
| 159 item->SetURL(GURL("http://download.com/redirected" + id_string)); | 158 item->SetURL(GURL("http://download.com/redirected" + id_string)); |
| 160 item->SetOriginalUrl(GURL("http://download.com/" + id_string)); | 159 item->SetOriginalUrl(GURL("http://download.com/" + id_string)); |
| 161 item->SetStartTime(base::Time::Now()); | 160 item->SetStartTime(base::Time::Now()); |
| 162 item->SetFileExternallyRemoved(false); | 161 item->SetFileExternallyRemoved(false); |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 HasUrl("http://dummy.com/2"), | 465 HasUrl("http://dummy.com/2"), |
| 467 HasUrl("http://download.com/1"), | 466 HasUrl("http://download.com/1"), |
| 468 HasUrl("http://download.com/2")))); | 467 HasUrl("http://download.com/2")))); |
| 469 FireDownloadCreated(asset_downloads[1].get()); | 468 FireDownloadCreated(asset_downloads[1].get()); |
| 470 } | 469 } |
| 471 | 470 |
| 472 TEST_F(DownloadSuggestionsProviderTest, ShouldSortSuggestions) { | 471 TEST_F(DownloadSuggestionsProviderTest, ShouldSortSuggestions) { |
| 473 IgnoreOnCategoryStatusChangedToAvailable(); | 472 IgnoreOnCategoryStatusChangedToAvailable(); |
| 474 IgnoreOnSuggestionInvalidated(); | 473 IgnoreOnSuggestionInvalidated(); |
| 475 | 474 |
| 476 base::Time now = base::Time::Now(); | 475 std::vector<OfflinePageItem> offline_pages = CreateDummyOfflinePages({0, 1}); |
| 477 base::Time yesterday = now - base::TimeDelta::FromDays(1); | |
| 478 base::Time tomorrow = now + base::TimeDelta::FromDays(1); | |
| 479 base::Time next_week = now + base::TimeDelta::FromDays(7); | |
| 480 | 476 |
| 481 (*offline_pages_model()->mutable_items()) | 477 offline_pages[0].url = GURL("http://dummy.com/0"); |
| 482 .push_back(CreateDummyOfflinePage(1, yesterday)); | 478 offline_pages[0].creation_time = now - base::TimeDelta::FromMinutes(10); |
| 483 (*offline_pages_model()->mutable_items()) | 479 offline_pages[0].last_access_time = offline_pages[0].creation_time; |
| 484 .push_back(CreateDummyOfflinePage(2, tomorrow)); | 480 |
| 481 offline_pages[1].url = GURL("http://dummy.com/1"); |
| 482 offline_pages[1].creation_time = now - base::TimeDelta::FromMinutes(5); |
| 483 offline_pages[1].last_access_time = offline_pages[1].creation_time; |
| 484 |
| 485 *(offline_pages_model()->mutable_items()) = offline_pages; |
| 486 |
| 487 auto test_clock = base::MakeUnique<base::SimpleTestClock>(); |
| 488 test_clock->SetNow(now); |
| 489 EXPECT_CALL(*observer(), |
| 490 OnNewSuggestions(_, downloads_category(), |
| 491 ElementsAre(HasUrl("http://dummy.com/1"), |
| 492 HasUrl("http://dummy.com/0")))); |
| 493 CreateLoadedProvider(/*show_assets=*/true, /*show_offline_pages=*/true, |
| 494 std::move(test_clock)); |
| 495 |
| 496 std::vector<std::unique_ptr<FakeDownloadItem>> asset_downloads = |
| 497 CreateDummyAssetDownloads({2, 3}); |
| 498 |
| 499 asset_downloads[0]->SetURL(GURL("http://download.com/2")); |
| 500 asset_downloads[0]->SetStartTime(now - base::TimeDelta::FromMinutes(3)); |
| 501 |
| 502 asset_downloads[1]->SetURL(GURL("http://download.com/3")); |
| 503 asset_downloads[1]->SetStartTime(now - base::TimeDelta::FromMinutes(7)); |
| 485 | 504 |
| 486 EXPECT_CALL(*observer(), | 505 EXPECT_CALL(*observer(), |
| 487 OnNewSuggestions(_, downloads_category(), | 506 OnNewSuggestions(_, downloads_category(), |
| 488 ElementsAre(HasUrl("http://dummy.com/2"), | 507 ElementsAre(HasUrl("http://download.com/2"), |
| 489 HasUrl("http://dummy.com/1")))); | 508 HasUrl("http://dummy.com/1"), |
| 490 CreateLoadedProvider(/*show_assets=*/true, /*show_offline_pages=*/true, | 509 HasUrl("http://dummy.com/0")))); |
| 491 base::MakeUnique<base::DefaultClock>()); | |
| 492 | |
| 493 std::vector<std::unique_ptr<FakeDownloadItem>> asset_downloads; | |
| 494 asset_downloads.push_back(CreateDummyAssetDownload(3, next_week)); | |
| 495 asset_downloads.push_back(CreateDummyAssetDownload(4, now)); | |
| 496 | |
| 497 EXPECT_CALL(*observer(), | |
| 498 OnNewSuggestions(_, downloads_category(), | |
| 499 ElementsAre(HasUrl("http://download.com/3"), | |
| 500 HasUrl("http://dummy.com/2"), | |
| 501 HasUrl("http://dummy.com/1")))); | |
| 502 FireDownloadCreated(asset_downloads[0].get()); | 510 FireDownloadCreated(asset_downloads[0].get()); |
| 503 | 511 |
| 504 EXPECT_CALL(*observer(), | 512 EXPECT_CALL(*observer(), |
| 505 OnNewSuggestions(_, downloads_category(), | 513 OnNewSuggestions(_, downloads_category(), |
| 506 ElementsAre(HasUrl("http://download.com/3"), | 514 ElementsAre(HasUrl("http://download.com/2"), |
| 507 HasUrl("http://dummy.com/2"), | 515 HasUrl("http://dummy.com/1"), |
| 508 HasUrl("http://download.com/4"), | 516 HasUrl("http://download.com/3"), |
| 509 HasUrl("http://dummy.com/1")))); | 517 HasUrl("http://dummy.com/0")))); |
| 510 FireDownloadCreated(asset_downloads[1].get()); | 518 FireDownloadCreated(asset_downloads[1].get()); |
| 511 } | 519 } |
| 512 | 520 |
| 513 TEST_F(DownloadSuggestionsProviderTest, | 521 TEST_F(DownloadSuggestionsProviderTest, |
| 514 ShouldDismissWithoutNotifyingObservers) { | 522 ShouldDismissWithoutNotifyingObservers) { |
| 515 IgnoreOnCategoryStatusChangedToAvailable(); | 523 IgnoreOnCategoryStatusChangedToAvailable(); |
| 516 | 524 |
| 517 *(offline_pages_model()->mutable_items()) = CreateDummyOfflinePages({1, 2}); | 525 *(offline_pages_model()->mutable_items()) = CreateDummyOfflinePages({1, 2}); |
| 518 *(downloads_manager()->mutable_items()) = CreateDummyAssetDownloads({1, 2}); | 526 *(downloads_manager()->mutable_items()) = CreateDummyAssetDownloads({1, 2}); |
| 519 EXPECT_CALL( | 527 EXPECT_CALL( |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 | 1034 |
| 1027 *(downloads_manager()->mutable_items()) = CreateDummyAssetDownloads({1}); | 1035 *(downloads_manager()->mutable_items()) = CreateDummyAssetDownloads({1}); |
| 1028 // Once the manager has been loaded, the ids should be pruned. | 1036 // Once the manager has been loaded, the ids should be pruned. |
| 1029 EXPECT_THAT(GetDismissedSuggestions(), IsEmpty()); | 1037 EXPECT_THAT(GetDismissedSuggestions(), IsEmpty()); |
| 1030 } | 1038 } |
| 1031 | 1039 |
| 1032 TEST_F(DownloadSuggestionsProviderTest, ShouldNotShowOutdatedDownloads) { | 1040 TEST_F(DownloadSuggestionsProviderTest, ShouldNotShowOutdatedDownloads) { |
| 1033 IgnoreOnCategoryStatusChangedToAvailable(); | 1041 IgnoreOnCategoryStatusChangedToAvailable(); |
| 1034 IgnoreOnSuggestionInvalidated(); | 1042 IgnoreOnSuggestionInvalidated(); |
| 1035 | 1043 |
| 1036 const int kDefaultMaxDownloadAgeHours = 6 * 7 * 24; | |
| 1037 | |
| 1038 base::Time now; | |
| 1039 ASSERT_TRUE(base::Time::FromString("Tue, 31 Jan 2017 13:00:00", &now)); | |
| 1040 const base::Time not_outdated = | 1044 const base::Time not_outdated = |
| 1041 now - base::TimeDelta::FromHours(kDefaultMaxDownloadAgeHours) + | 1045 now - base::TimeDelta::FromHours(kDefaultMaxDownloadAgeHours) + |
| 1042 base::TimeDelta::FromSeconds(1); | 1046 base::TimeDelta::FromSeconds(1); |
| 1043 const base::Time outdated = | 1047 const base::Time outdated = |
| 1044 now - base::TimeDelta::FromHours(kDefaultMaxDownloadAgeHours) - | 1048 now - base::TimeDelta::FromHours(kDefaultMaxDownloadAgeHours) - |
| 1045 base::TimeDelta::FromSeconds(1); | 1049 base::TimeDelta::FromSeconds(1); |
| 1050 |
| 1046 *(offline_pages_model()->mutable_items()) = CreateDummyOfflinePages({0, 1}); | 1051 *(offline_pages_model()->mutable_items()) = CreateDummyOfflinePages({0, 1}); |
| 1052 |
| 1047 offline_pages_model()->mutable_items()->at(0).url = | 1053 offline_pages_model()->mutable_items()->at(0).url = |
| 1048 GURL("http://dummy.com/0"); | 1054 GURL("http://dummy.com/0"); |
| 1049 offline_pages_model()->mutable_items()->at(0).creation_time = not_outdated; | 1055 offline_pages_model()->mutable_items()->at(0).creation_time = not_outdated; |
| 1056 offline_pages_model()->mutable_items()->at(0).last_access_time = not_outdated; |
| 1057 |
| 1050 offline_pages_model()->mutable_items()->at(1).url = | 1058 offline_pages_model()->mutable_items()->at(1).url = |
| 1051 GURL("http://dummy.com/1"); | 1059 GURL("http://dummy.com/1"); |
| 1052 offline_pages_model()->mutable_items()->at(1).creation_time = outdated; | 1060 offline_pages_model()->mutable_items()->at(1).creation_time = outdated; |
| 1061 offline_pages_model()->mutable_items()->at(1).last_access_time = outdated; |
| 1062 |
| 1053 *(downloads_manager()->mutable_items()) = CreateDummyAssetDownloads({0, 1}); | 1063 *(downloads_manager()->mutable_items()) = CreateDummyAssetDownloads({0, 1}); |
| 1064 |
| 1054 downloads_manager()->mutable_items()->at(0)->SetURL( | 1065 downloads_manager()->mutable_items()->at(0)->SetURL( |
| 1055 GURL("http://download.com/0")); | 1066 GURL("http://download.com/0")); |
| 1056 downloads_manager()->mutable_items()->at(0)->SetStartTime(not_outdated); | 1067 downloads_manager()->mutable_items()->at(0)->SetStartTime(not_outdated); |
| 1068 |
| 1057 downloads_manager()->mutable_items()->at(1)->SetURL( | 1069 downloads_manager()->mutable_items()->at(1)->SetURL( |
| 1058 GURL("http://download.com/1")); | 1070 GURL("http://download.com/1")); |
| 1059 downloads_manager()->mutable_items()->at(1)->SetStartTime(outdated); | 1071 downloads_manager()->mutable_items()->at(1)->SetStartTime(outdated); |
| 1060 | 1072 |
| 1061 EXPECT_CALL( | 1073 EXPECT_CALL( |
| 1062 *observer(), | 1074 *observer(), |
| 1063 OnNewSuggestions(_, downloads_category(), | 1075 OnNewSuggestions(_, downloads_category(), |
| 1064 UnorderedElementsAre(HasUrl("http://dummy.com/0"), | 1076 UnorderedElementsAre(HasUrl("http://dummy.com/0"), |
| 1065 HasUrl("http://download.com/0")))); | 1077 HasUrl("http://download.com/0")))); |
| 1066 auto test_clock = base::MakeUnique<base::SimpleTestClock>(); | 1078 auto test_clock = base::MakeUnique<base::SimpleTestClock>(); |
| 1067 test_clock->SetNow(now); | 1079 test_clock->SetNow(now); |
| 1068 CreateLoadedProvider(/*show_assets=*/true, /*show_offline_pages=*/true, | 1080 CreateLoadedProvider(/*show_assets=*/true, /*show_offline_pages=*/true, |
| 1069 std::move(test_clock)); | 1081 std::move(test_clock)); |
| 1070 } | 1082 } |
| 1083 |
| 1084 TEST_F(DownloadSuggestionsProviderTest, |
| 1085 ShouldShowRecentlyVisitedOfflinePageDownloads) { |
| 1086 IgnoreOnCategoryStatusChangedToAvailable(); |
| 1087 IgnoreOnSuggestionInvalidated(); |
| 1088 |
| 1089 const base::Time not_outdated = |
| 1090 now - base::TimeDelta::FromHours(kDefaultMaxDownloadAgeHours) + |
| 1091 base::TimeDelta::FromSeconds(1); |
| 1092 const base::Time outdated = |
| 1093 now - base::TimeDelta::FromHours(kDefaultMaxDownloadAgeHours) - |
| 1094 base::TimeDelta::FromSeconds(1); |
| 1095 |
| 1096 std::vector<OfflinePageItem> offline_pages = CreateDummyOfflinePages({0, 1}); |
| 1097 |
| 1098 offline_pages[0].url = GURL("http://dummy.com/0"); |
| 1099 offline_pages[0].creation_time = outdated; |
| 1100 offline_pages[0].last_access_time = not_outdated; |
| 1101 |
| 1102 offline_pages[1].url = GURL("http://dummy.com/1"); |
| 1103 offline_pages[1].creation_time = outdated; |
| 1104 offline_pages[1].last_access_time = offline_pages[1].creation_time; |
| 1105 |
| 1106 *(offline_pages_model()->mutable_items()) = offline_pages; |
| 1107 |
| 1108 // Even though page 0 was created long time ago, it should be reported because |
| 1109 // it has been visited recently. |
| 1110 EXPECT_CALL( |
| 1111 *observer(), |
| 1112 OnNewSuggestions(_, downloads_category(), |
| 1113 UnorderedElementsAre(HasUrl("http://dummy.com/0")))); |
| 1114 auto test_clock = base::MakeUnique<base::SimpleTestClock>(); |
| 1115 test_clock->SetNow(now); |
| 1116 CreateProvider(/*show_assets=*/false, /*show_offline_pages=*/true, |
| 1117 std::move(test_clock)); |
| 1118 } |
| OLD | NEW |