| 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/ntp_snippets/ntp_snippets_service.h" | 5 #include "components/ntp_snippets/ntp_snippets_service.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); | 328 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); |
| 329 char json_str_format[] = | 329 char json_str_format[] = |
| 330 "{ \"recos\": [ " | 330 "{ \"recos\": [ " |
| 331 "{ \"contentInfo\": {" | 331 "{ \"contentInfo\": {" |
| 332 "\"url\" : \"%s\"," | 332 "\"url\" : \"%s\"," |
| 333 "\"title\" : \"Title\"," | 333 "\"title\" : \"Title\"," |
| 334 "\"snippet\" : \"Snippet\"," | 334 "\"snippet\" : \"Snippet\"," |
| 335 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," | 335 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," |
| 336 "\"creationTimestampSec\" : \"%s\"," | 336 "\"creationTimestampSec\" : \"%s\"," |
| 337 "\"expiryTimestampSec\" : \"%s\"," | 337 "\"expiryTimestampSec\" : \"%s\"," |
| 338 "\"sourceCorpusInfo\" : [{\"corpusId\": \"http://first\"," | 338 "\"sourceCorpusInfo\" : [{\"corpusId\": \"%s\"," |
| 339 "\"publisherData\": {" | 339 "\"publisherData\": {" |
| 340 "\"sourceName\": \"Source 1\"" | 340 "\"sourceName\": \"Source 1\"" |
| 341 "}," | 341 "}," |
| 342 "\"ampUrl\": \"\"}]" | 342 "\"ampUrl\": \"\"}]" |
| 343 "}}" | 343 "}}" |
| 344 "]}"; | 344 "]}"; |
| 345 const std::string first_url = "http://first"; |
| 345 std::string json_str(base::StringPrintf( | 346 std::string json_str(base::StringPrintf( |
| 346 json_str_format, "http://first", | 347 json_str_format, first_url.c_str(), |
| 347 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), | 348 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), |
| 348 NTPSnippet::TimeToJsonString(expiry_time).c_str())); | 349 NTPSnippet::TimeToJsonString(expiry_time).c_str(), first_url.c_str())); |
| 349 | 350 |
| 350 LoadFromJSONString(json_str); | 351 LoadFromJSONString(json_str); |
| 351 | 352 |
| 352 EXPECT_THAT(service()->snippets(), ElementsAre(IdEq("http://first"))); | 353 EXPECT_THAT(service()->snippets(), ElementsAre(IdEq(first_url))); |
| 353 | 354 |
| 355 const std::string second_url = "http://second"; |
| 354 json_str = base::StringPrintf( | 356 json_str = base::StringPrintf( |
| 355 json_str_format, "http://second", | 357 json_str_format, second_url.c_str(), |
| 356 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), | 358 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), |
| 357 NTPSnippet::TimeToJsonString(expiry_time).c_str()); | 359 NTPSnippet::TimeToJsonString(expiry_time).c_str(), second_url.c_str()); |
| 358 | 360 |
| 359 LoadFromJSONString(json_str); | 361 LoadFromJSONString(json_str); |
| 360 | 362 |
| 361 // The snippet loaded last should be at the first position in the list now. | 363 // The snippet loaded last should be at the first position in the list now. |
| 362 EXPECT_THAT(service()->snippets(), | 364 EXPECT_THAT(service()->snippets(), |
| 363 ElementsAre(IdEq("http://second"), IdEq("http://first"))); | 365 ElementsAre(IdEq(second_url), IdEq(first_url))); |
| 364 } | 366 } |
| 365 | 367 |
| 366 TEST_F(NTPSnippetsServiceTest, LimitNumSnippets) { | 368 TEST_F(NTPSnippetsServiceTest, LimitNumSnippets) { |
| 367 int max_snippet_count = NTPSnippetsService::GetMaxSnippetCountForTesting(); | 369 int max_snippet_count = NTPSnippetsService::GetMaxSnippetCountForTesting(); |
| 368 int snippets_per_load = max_snippet_count / 2 + 1; | 370 int snippets_per_load = max_snippet_count / 2 + 1; |
| 369 | 371 |
| 370 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); | 372 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); |
| 371 char json_str_format[] = | 373 char json_str_format[] = |
| 372 "{ \"contentInfo\": {" | 374 "{ \"contentInfo\": {" |
| 373 "\"url\" : \"http://localhost/%i\"," | 375 "\"url\" : \"http://localhost/%i\"," |
| 374 "\"title\" : \"Title\"," | 376 "\"title\" : \"Title\"," |
| 375 "\"snippet\" : \"Snippet\"," | 377 "\"snippet\" : \"Snippet\"," |
| 376 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," | 378 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," |
| 377 "\"creationTimestampSec\" : \"%s\"," | 379 "\"creationTimestampSec\" : \"%s\"," |
| 378 "\"expiryTimestampSec\" : \"%s\"," | 380 "\"expiryTimestampSec\" : \"%s\"," |
| 379 "\"sourceCorpusInfo\" : [{\"corpusId\": \"http://first\"," | 381 "\"sourceCorpusInfo\" : [{\"corpusId\": \"http://localhost/%i\"," |
| 380 "\"publisherData\": {" | 382 "\"publisherData\": {" |
| 381 "\"sourceName\": \"Source 1\"" | 383 "\"sourceName\": \"Source 1\"" |
| 382 "}," | 384 "}," |
| 383 "\"ampUrl\": \"\"}]" | 385 "\"ampUrl\": \"\"}]" |
| 384 "}}"; | 386 "}}"; |
| 385 | 387 |
| 386 std::vector<std::string> snippets1; | 388 std::vector<std::string> snippets1; |
| 387 std::vector<std::string> snippets2; | 389 std::vector<std::string> snippets2; |
| 388 for (int i = 0; i < snippets_per_load; i++) { | 390 for (int i = 0; i < snippets_per_load; i++) { |
| 389 snippets1.push_back(base::StringPrintf( | 391 snippets1.push_back(base::StringPrintf( |
| 390 json_str_format, i, | 392 json_str_format, i, |
| 391 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), | 393 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), |
| 392 NTPSnippet::TimeToJsonString(expiry_time).c_str())); | 394 NTPSnippet::TimeToJsonString(expiry_time).c_str(), i /* for corpusId */ |
| 395 )); |
| 393 snippets2.push_back(base::StringPrintf( | 396 snippets2.push_back(base::StringPrintf( |
| 394 json_str_format, snippets_per_load + i, | 397 json_str_format, snippets_per_load + i, |
| 395 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), | 398 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), |
| 396 NTPSnippet::TimeToJsonString(expiry_time).c_str())); | 399 NTPSnippet::TimeToJsonString(expiry_time).c_str(), |
| 400 snippets_per_load + i /* for corpusId */)); |
| 397 } | 401 } |
| 398 | 402 |
| 399 LoadFromJSONString( | 403 LoadFromJSONString( |
| 400 "{ \"recos\": [ " + base::JoinString(snippets1, ", ") + "]}"); | 404 "{ \"recos\": [ " + base::JoinString(snippets1, ", ") + "]}"); |
| 401 ASSERT_THAT(service()->snippets(), SizeIs(snippets1.size())); | 405 ASSERT_THAT(service()->snippets(), SizeIs(snippets1.size())); |
| 402 | 406 |
| 403 LoadFromJSONString( | 407 LoadFromJSONString( |
| 404 "{ \"recos\": [ " + base::JoinString(snippets2, ", ") + "]}"); | 408 "{ \"recos\": [ " + base::JoinString(snippets2, ", ") + "]}"); |
| 405 EXPECT_THAT(service()->snippets(), SizeIs(max_snippet_count)); | 409 EXPECT_THAT(service()->snippets(), SizeIs(max_snippet_count)); |
| 406 } | 410 } |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 base::Bucket(/*min=*/1, /*count=*/3))); | 773 base::Bucket(/*min=*/1, /*count=*/3))); |
| 770 EXPECT_THAT( | 774 EXPECT_THAT( |
| 771 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), | 775 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), |
| 772 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); | 776 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); |
| 773 // Recreating the service and loading from prefs shouldn't count as fetched | 777 // Recreating the service and loading from prefs shouldn't count as fetched |
| 774 // articles. | 778 // articles. |
| 775 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); | 779 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); |
| 776 CreateSnippetsService(/*enabled=*/true); | 780 CreateSnippetsService(/*enabled=*/true); |
| 777 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4); | 781 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4); |
| 778 } | 782 } |
| 783 |
| 784 const char kChromeReaderResponseMultipleUrls[] = |
| 785 "{ \"recos\": [{ " |
| 786 " \"contentInfo\": { " |
| 787 " \"url\": \"%s\", " |
| 788 " \"creationTimestampSec\": \"%s\", " |
| 789 " \"expiryTimestampSec\" : \"%s\"," |
| 790 " \"title\": \"Stolen doggie finally gets returned to owner\", " |
| 791 " \"snippet\": \"It\'s at least this man\'s best friend.\", " |
| 792 " \"thumbnailUrl\": \"http://t0.gstatic.com/images?q=tbn:1\", " |
| 793 " \"sourceCorpusInfo\": [{" |
| 794 " \"type\" : \"CHROME_LOGS\", " |
| 795 " \"corpusId\": \"http://mashable.com/2016/05/11/stolen\", " |
| 796 " \"publisherData\": { " |
| 797 " \"sourceName\": \"Mashable\", " |
| 798 " \"sourceLogoUrl\": \"http://t3.gstatic.com/images?q=tbn:2\" " |
| 799 " }, " |
| 800 " \"ampUrl\": \"http://mashable-amphtml.googleusercontent.com/1\" " |
| 801 " }, { " |
| 802 " \"type\": \"CHROME_LOGS\", " |
| 803 " \"corpusId\": \"http://www.aol.com/article/2016/05/stolen-doggie\", " |
| 804 " \"publisherData\": { " |
| 805 " \"sourceName\": \"AOL\", " |
| 806 " \"sourceLogoUrl\": \"http://t2.gstatic.com/images?q=tbn:3\" " |
| 807 " }, " |
| 808 " \"ampUrl\": \"http://mashable-amphtml.googleusercontent.com/1\" " |
| 809 " }, { " |
| 810 " \"type\": \"CHROME_LOGS\", " |
| 811 " \"corpusId\": \"http://mashable.com/2016/05/11/stolen?utm_cid=1\", " |
| 812 " \"publisherData\": { " |
| 813 " \"sourceName\": \"Mashable\", " |
| 814 " \"sourceLogoUrl\": \"http://t3.gstatic.com/images?q=tbn:2\" " |
| 815 " }, " |
| 816 " \"ampUrl\": \"http://mashable-amphtml.googleusercontent.com/1\" " |
| 817 " }] " |
| 818 " }, " |
| 819 " \"score\" : \"0.099307865\" " |
| 820 "}]} "; |
| 821 |
| 822 TEST_F(NTPSnippetsServiceTest, DiscardShouldRespectAllKnownUrls) { |
| 823 const std::string url_mashable = "http://mashable.com/2016/05/11/stolen"; |
| 824 const std::string url_aol = |
| 825 "http://www.aol.com/article/2016/05/stolen-doggie"; |
| 826 |
| 827 LoadFromJSONString(base::StringPrintf( |
| 828 kChromeReaderResponseMultipleUrls, url_mashable.c_str(), |
| 829 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), |
| 830 NTPSnippet::TimeToJsonString(base::Time::Now() + |
| 831 base::TimeDelta::FromHours(1)) |
| 832 .c_str())); |
| 833 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 834 // Discard the snippet via the mashable source corpus ID. |
| 835 EXPECT_TRUE(service()->DiscardSnippet(url_mashable)); |
| 836 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 837 |
| 838 // The same article from the AOL domain should now be detected as discarded. |
| 839 LoadFromJSONString(base::StringPrintf( |
| 840 kChromeReaderResponseMultipleUrls, url_aol.c_str(), |
| 841 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), |
| 842 NTPSnippet::TimeToJsonString(base::Time::Now() + |
| 843 base::TimeDelta::FromHours(1)) |
| 844 .c_str())); |
| 845 ASSERT_THAT(service()->snippets(), IsEmpty()); |
| 846 } |
| 847 |
| 779 } // namespace ntp_snippets | 848 } // namespace ntp_snippets |
| OLD | NEW |