| 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" |
| 11 #include "base/files/file_path.h" |
| 12 #include "base/files/scoped_temp_dir.h" |
| 11 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
| 12 #include "base/macros.h" | 14 #include "base/macros.h" |
| 13 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 14 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 15 #include "base/run_loop.h" | 17 #include "base/run_loop.h" |
| 16 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 18 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
| 19 #include "base/test/histogram_tester.h" | 21 #include "base/test/histogram_tester.h" |
| 20 #include "base/threading/thread_task_runner_handle.h" | 22 #include "base/threading/thread_task_runner_handle.h" |
| 21 #include "base/time/time.h" | 23 #include "base/time/time.h" |
| 22 #include "components/image_fetcher/image_fetcher.h" | 24 #include "components/image_fetcher/image_fetcher.h" |
| 23 #include "components/ntp_snippets/ntp_snippet.h" | 25 #include "components/ntp_snippets/ntp_snippet.h" |
| 26 #include "components/ntp_snippets/ntp_snippets_database.h" |
| 24 #include "components/ntp_snippets/ntp_snippets_fetcher.h" | 27 #include "components/ntp_snippets/ntp_snippets_fetcher.h" |
| 25 #include "components/ntp_snippets/ntp_snippets_scheduler.h" | 28 #include "components/ntp_snippets/ntp_snippets_scheduler.h" |
| 26 #include "components/ntp_snippets/switches.h" | 29 #include "components/ntp_snippets/switches.h" |
| 27 #include "components/prefs/testing_pref_service.h" | 30 #include "components/prefs/testing_pref_service.h" |
| 28 #include "components/signin/core/browser/account_tracker_service.h" | 31 #include "components/signin/core/browser/account_tracker_service.h" |
| 29 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" | 32 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" |
| 30 #include "components/signin/core/browser/fake_signin_manager.h" | 33 #include "components/signin/core/browser/fake_signin_manager.h" |
| 31 #include "components/signin/core/browser/test_signin_client.h" | 34 #include "components/signin/core/browser/test_signin_client.h" |
| 32 #include "components/sync_driver/fake_sync_service.h" | 35 #include "components/sync_driver/fake_sync_service.h" |
| 33 #include "google_apis/google_api_keys.h" | 36 #include "google_apis/google_api_keys.h" |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 MOCK_CONST_METHOD0(GetActiveDataTypes, syncer::ModelTypeSet()); | 232 MOCK_CONST_METHOD0(GetActiveDataTypes, syncer::ModelTypeSet()); |
| 230 }; | 233 }; |
| 231 | 234 |
| 232 class MockServiceObserver : public NTPSnippetsServiceObserver { | 235 class MockServiceObserver : public NTPSnippetsServiceObserver { |
| 233 public: | 236 public: |
| 234 MOCK_METHOD0(NTPSnippetsServiceLoaded, void()); | 237 MOCK_METHOD0(NTPSnippetsServiceLoaded, void()); |
| 235 MOCK_METHOD0(NTPSnippetsServiceShutdown, void()); | 238 MOCK_METHOD0(NTPSnippetsServiceShutdown, void()); |
| 236 MOCK_METHOD0(NTPSnippetsServiceDisabled, void()); | 239 MOCK_METHOD0(NTPSnippetsServiceDisabled, void()); |
| 237 }; | 240 }; |
| 238 | 241 |
| 242 class WaitForDBLoad : public NTPSnippetsServiceObserver { |
| 243 public: |
| 244 WaitForDBLoad(NTPSnippetsService* service) : service_(service) { |
| 245 EXPECT_TRUE(!service_->loaded()); |
| 246 service_->AddObserver(this); |
| 247 run_loop_.Run(); |
| 248 } |
| 249 |
| 250 ~WaitForDBLoad() override { |
| 251 service_->RemoveObserver(this); |
| 252 } |
| 253 |
| 254 private: |
| 255 void NTPSnippetsServiceLoaded() override { |
| 256 EXPECT_TRUE(service_->loaded()); |
| 257 run_loop_.Quit(); |
| 258 } |
| 259 |
| 260 void NTPSnippetsServiceShutdown() override {}; |
| 261 void NTPSnippetsServiceDisabled() override {}; |
| 262 |
| 263 NTPSnippetsService* service_; |
| 264 base::RunLoop run_loop_; |
| 265 |
| 266 DISALLOW_COPY_AND_ASSIGN(WaitForDBLoad); |
| 267 }; |
| 268 |
| 239 } // namespace | 269 } // namespace |
| 240 | 270 |
| 241 class NTPSnippetsServiceTest : public testing::Test { | 271 class NTPSnippetsServiceTest : public testing::Test { |
| 242 public: | 272 public: |
| 243 NTPSnippetsServiceTest() | 273 NTPSnippetsServiceTest() |
| 244 : fake_url_fetcher_factory_( | 274 : fake_url_fetcher_factory_( |
| 245 /*default_factory=*/&failing_url_fetcher_factory_), | 275 /*default_factory=*/&failing_url_fetcher_factory_), |
| 246 test_url_(base::StringPrintf(kTestContentSnippetsServerFormat, | 276 test_url_(base::StringPrintf(kTestContentSnippetsServerFormat, |
| 247 google_apis::GetAPIKey().c_str())), | 277 google_apis::GetAPIKey().c_str())), |
| 248 pref_service_(new TestingPrefServiceSimple()), | 278 pref_service_(new TestingPrefServiceSimple()), |
| 249 signin_client_(new TestSigninClient(nullptr)), | 279 signin_client_(new TestSigninClient(nullptr)), |
| 250 account_tracker_(new AccountTrackerService()), | 280 account_tracker_(new AccountTrackerService()), |
| 251 fake_signin_manager_(new FakeSigninManagerBase(signin_client_.get(), | 281 fake_signin_manager_(new FakeSigninManagerBase(signin_client_.get(), |
| 252 account_tracker_.get())), | 282 account_tracker_.get())), |
| 253 fake_token_service_(new FakeProfileOAuth2TokenService()) { | 283 fake_token_service_(new FakeProfileOAuth2TokenService()) { |
| 254 NTPSnippetsService::RegisterProfilePrefs(pref_service_->registry()); | 284 NTPSnippetsService::RegisterProfilePrefs(pref_service_->registry()); |
| 255 // Since no SuggestionsService is injected in tests, we need to force the | 285 // Since no SuggestionsService is injected in tests, we need to force the |
| 256 // service to fetch from all hosts. | 286 // service to fetch from all hosts. |
| 257 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 287 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 258 switches::kDontRestrict); | 288 switches::kDontRestrict); |
| 289 EXPECT_TRUE(database_dir_.CreateUniqueTempDir()); |
| 259 } | 290 } |
| 260 | 291 |
| 261 ~NTPSnippetsServiceTest() override { | 292 ~NTPSnippetsServiceTest() override { |
| 262 if (service_) | 293 if (service_) |
| 263 service_->Shutdown(); | 294 service_->Shutdown(); |
| 264 } | 295 } |
| 265 | 296 |
| 266 void SetUp() override { | 297 void SetUp() override { |
| 298 ResetSyncServiceMock(); |
| 267 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); | 299 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); |
| 268 CreateSnippetsService(/*enabled=*/true); | 300 CreateSnippetsService(/*enabled=*/true); |
| 269 } | 301 } |
| 270 | 302 |
| 271 void CreateSnippetsService(bool enabled) { | 303 void CreateSnippetsService(bool enabled) { |
| 272 if (service_) | 304 if (service_) |
| 273 service_->Shutdown(); | 305 service_->Shutdown(); |
| 274 | 306 |
| 275 scoped_refptr<base::SingleThreadTaskRunner> task_runner( | 307 scoped_refptr<base::SingleThreadTaskRunner> task_runner( |
| 276 base::ThreadTaskRunnerHandle::Get()); | 308 base::ThreadTaskRunnerHandle::Get()); |
| 277 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter = | 309 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter = |
| 278 new net::TestURLRequestContextGetter(task_runner.get()); | 310 new net::TestURLRequestContextGetter(task_runner.get()); |
| 279 | 311 |
| 312 // Delete the current service, so that the database is destroyed before we |
| 313 // create the new one, otherwise opening the new database will fail. |
| 314 service_.reset(); |
| 315 |
| 280 service_.reset(new NTPSnippetsService( | 316 service_.reset(new NTPSnippetsService( |
| 281 pref_service_.get(), mock_sync_service_.get(), nullptr, task_runner, | 317 pref_service_.get(), mock_sync_service_.get(), nullptr, |
| 282 std::string("fr"), &scheduler_, | 318 std::string("fr"), &scheduler_, |
| 283 base::WrapUnique(new NTPSnippetsFetcher( | 319 base::WrapUnique(new NTPSnippetsFetcher( |
| 284 fake_signin_manager_.get(), fake_token_service_.get(), | 320 fake_signin_manager_.get(), fake_token_service_.get(), |
| 285 std::move(request_context_getter), base::Bind(&ParseJson), | 321 std::move(request_context_getter), base::Bind(&ParseJson), |
| 286 /*is_stable_channel=*/true)), | 322 /*is_stable_channel=*/true)), |
| 287 /*image_fetcher=*/nullptr)); | 323 /*image_fetcher=*/nullptr, |
| 324 base::WrapUnique(new NTPSnippetsDatabase(database_dir_.path(), |
| 325 task_runner)))); |
| 288 service_->Init(enabled); | 326 service_->Init(enabled); |
| 327 if (enabled) |
| 328 WaitForDBLoad(service_.get()); |
| 289 } | 329 } |
| 290 | 330 |
| 291 protected: | 331 protected: |
| 292 const GURL& test_url() { return test_url_; } | 332 const GURL& test_url() { return test_url_; } |
| 293 NTPSnippetsService* service() { return service_.get(); } | 333 NTPSnippetsService* service() { return service_.get(); } |
| 294 MockScheduler& mock_scheduler() { return scheduler_; } | 334 MockScheduler& mock_scheduler() { return scheduler_; } |
| 295 MockSyncService* mock_sync_service() { return mock_sync_service_.get(); } | 335 MockSyncService* mock_sync_service() { return mock_sync_service_.get(); } |
| 296 | 336 |
| 297 // Provide the json to be returned by the fake fetcher. | 337 // Provide the json to be returned by the fake fetcher. |
| 298 void SetUpFetchResponse(const std::string& json) { | 338 void SetUpFetchResponse(const std::string& json) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 std::unique_ptr<TestingPrefServiceSimple> pref_service_; | 372 std::unique_ptr<TestingPrefServiceSimple> pref_service_; |
| 333 std::unique_ptr<TestSigninClient> signin_client_; | 373 std::unique_ptr<TestSigninClient> signin_client_; |
| 334 std::unique_ptr<AccountTrackerService> account_tracker_; | 374 std::unique_ptr<AccountTrackerService> account_tracker_; |
| 335 std::unique_ptr<MockSyncService> mock_sync_service_; // Null by default. | 375 std::unique_ptr<MockSyncService> mock_sync_service_; // Null by default. |
| 336 std::unique_ptr<SigninManagerBase> fake_signin_manager_; | 376 std::unique_ptr<SigninManagerBase> fake_signin_manager_; |
| 337 std::unique_ptr<OAuth2TokenService> fake_token_service_; | 377 std::unique_ptr<OAuth2TokenService> fake_token_service_; |
| 338 MockScheduler scheduler_; | 378 MockScheduler scheduler_; |
| 339 // Last so that the dependencies are deleted after the service. | 379 // Last so that the dependencies are deleted after the service. |
| 340 std::unique_ptr<NTPSnippetsService> service_; | 380 std::unique_ptr<NTPSnippetsService> service_; |
| 341 | 381 |
| 382 base::ScopedTempDir database_dir_; |
| 383 |
| 342 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest); | 384 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest); |
| 343 }; | 385 }; |
| 344 | 386 |
| 345 class NTPSnippetsServiceWithSyncTest : public NTPSnippetsServiceTest { | 387 class NTPSnippetsServiceWithSyncTest : public NTPSnippetsServiceTest { |
| 346 public: | 388 public: |
| 347 void SetUp() override { | 389 void SetUp() override { |
| 348 ResetSyncServiceMock(); | 390 // ResetSyncServiceMock(); |
| 349 NTPSnippetsServiceTest::SetUp(); | 391 NTPSnippetsServiceTest::SetUp(); |
| 350 } | 392 } |
| 351 }; | 393 }; |
| 352 | 394 |
| 353 class NTPSnippetsServiceDisabledTest : public NTPSnippetsServiceTest { | 395 class NTPSnippetsServiceDisabledTest : public NTPSnippetsServiceTest { |
| 354 public: | 396 public: |
| 355 void SetUp() override { | 397 void SetUp() override { |
| 356 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(1); | 398 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(1); |
| 357 CreateSnippetsService(/*enabled=*/false); | 399 CreateSnippetsService(/*enabled=*/false); |
| 358 } | 400 } |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 830 EXPECT_THAT(service()->snippets(), IsEmpty()); | 872 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 831 | 873 |
| 832 // The same article from the AOL domain should now be detected as discarded. | 874 // The same article from the AOL domain should now be detected as discarded. |
| 833 LoadFromJSONString(GetTestJson({GetSnippetWithUrlAndTimesAndSources( | 875 LoadFromJSONString(GetTestJson({GetSnippetWithUrlAndTimesAndSources( |
| 834 source_urls[1], creation, expiry, source_urls, publishers, amp_urls)})); | 876 source_urls[1], creation, expiry, source_urls, publishers, amp_urls)})); |
| 835 ASSERT_THAT(service()->snippets(), IsEmpty()); | 877 ASSERT_THAT(service()->snippets(), IsEmpty()); |
| 836 } | 878 } |
| 837 | 879 |
| 838 TEST_F(NTPSnippetsServiceWithSyncTest, SyncStateCompatibility) { | 880 TEST_F(NTPSnippetsServiceWithSyncTest, SyncStateCompatibility) { |
| 839 // The default test setup has a compatible sync state. | 881 // The default test setup has a compatible sync state. |
| 840 EXPECT_FALSE(service()->IsSyncStateIncompatible()); | 882 EXPECT_EQ(DisabledReason::NONE, service()->GetDisabledReason()); |
| 841 | 883 |
| 842 // History sync disabled. | 884 // History sync disabled. |
| 843 ON_CALL(*mock_sync_service(), GetActiveDataTypes()) | 885 ON_CALL(*mock_sync_service(), GetActiveDataTypes()) |
| 844 .WillByDefault(Return(syncer::ModelTypeSet())); | 886 .WillByDefault(Return(syncer::ModelTypeSet())); |
| 845 EXPECT_TRUE(service()->IsSyncStateIncompatible()); | 887 EXPECT_EQ(DisabledReason::HISTORY_SYNC_DISABLED, service()->GetDisabledReason(
)); |
| 846 ResetSyncServiceMock(); | 888 ResetSyncServiceMock(); |
| 847 | 889 |
| 848 // Not done loading. | 890 // Not done loading. |
| 849 ON_CALL(*mock_sync_service(), ConfigurationDone()) | 891 ON_CALL(*mock_sync_service(), ConfigurationDone()) |
| 850 .WillByDefault(Return(false)); | 892 .WillByDefault(Return(false)); |
| 851 ON_CALL(*mock_sync_service(), GetActiveDataTypes()) | 893 ON_CALL(*mock_sync_service(), GetActiveDataTypes()) |
| 852 .WillByDefault(Return(syncer::ModelTypeSet())); | 894 .WillByDefault(Return(syncer::ModelTypeSet())); |
| 853 EXPECT_FALSE(service()->IsSyncStateIncompatible()); | 895 EXPECT_EQ(DisabledReason::HISTORY_SYNC_DISABLED, service()->GetDisabledReason(
)); |
| 854 ResetSyncServiceMock(); | 896 ResetSyncServiceMock(); |
| 855 | 897 |
| 856 // Sync disabled. | 898 // Sync disabled. |
| 857 ON_CALL(*mock_sync_service(), CanSyncStart()).WillByDefault(Return(false)); | 899 ON_CALL(*mock_sync_service(), CanSyncStart()).WillByDefault(Return(false)); |
| 858 EXPECT_TRUE(service()->IsSyncStateIncompatible()); | 900 EXPECT_EQ(DisabledReason::HISTORY_SYNC_DISABLED, service()->GetDisabledReason(
)); |
| 859 ResetSyncServiceMock(); | 901 ResetSyncServiceMock(); |
| 860 | 902 |
| 861 // No service. | 903 // No service. |
| 862 service()->sync_service_ = nullptr; | 904 service()->sync_service_ = nullptr; |
| 863 EXPECT_TRUE(service()->IsSyncStateIncompatible()); | 905 EXPECT_EQ(DisabledReason::HISTORY_SYNC_DISABLED, service()->GetDisabledReason(
)); |
| 864 } | 906 } |
| 865 | 907 |
| 866 TEST_F(NTPSnippetsServiceWithSyncTest, HistorySyncStateChanges) { | 908 TEST_F(NTPSnippetsServiceWithSyncTest, HistorySyncStateChanges) { |
| 867 MockServiceObserver mock_observer; | 909 MockServiceObserver mock_observer; |
| 868 service()->AddObserver(&mock_observer); | 910 service()->AddObserver(&mock_observer); |
| 869 | 911 |
| 870 // Simulate user disabled sync. | 912 // Simulate user disabled sync. |
| 871 ON_CALL(*mock_sync_service(), CanSyncStart()).WillByDefault(Return(false)); | 913 ON_CALL(*mock_sync_service(), CanSyncStart()).WillByDefault(Return(false)); |
| 872 // The service should notify observers it's been disabled and clear the | 914 // The service should notify observers it's been disabled and clear the |
| 873 // snippets instead of pulling new ones. | 915 // snippets instead of pulling new ones. |
| 874 EXPECT_CALL(mock_observer, NTPSnippetsServiceDisabled()); | 916 EXPECT_CALL(mock_observer, NTPSnippetsServiceDisabled()); |
| 875 SetUpFetchResponse(GetTestJson({GetSnippet()})); | 917 SetUpFetchResponse(GetTestJson({GetSnippet()})); |
| 876 service()->OnStateChanged(); | 918 service()->OnStateChanged(); |
| 877 base::RunLoop().RunUntilIdle(); | 919 base::RunLoop().RunUntilIdle(); |
| 920 EXPECT_EQ(NTPSnippetsService::State::DISABLED, service()->state_); |
| 878 EXPECT_THAT(service()->snippets(), IsEmpty()); // No fetch should be made. | 921 EXPECT_THAT(service()->snippets(), IsEmpty()); // No fetch should be made. |
| 879 | 922 |
| 880 // Simulate user sign in. | 923 // Simulate user sign in. |
| 881 ResetSyncServiceMock(); | 924 ResetSyncServiceMock(); |
| 882 // The service should be ready again and load snippets. | 925 // The service should be ready again and load snippets. |
| 883 SetUpFetchResponse(GetTestJson({GetSnippet()})); | 926 SetUpFetchResponse(GetTestJson({GetSnippet()})); |
| 884 service()->OnStateChanged(); | 927 service()->OnStateChanged(); |
| 885 base::RunLoop().RunUntilIdle(); | 928 base::RunLoop().RunUntilIdle(); |
| 929 EXPECT_EQ(NTPSnippetsService::State::READY, service()->state_); |
| 886 EXPECT_FALSE(service()->snippets().empty()); | 930 EXPECT_FALSE(service()->snippets().empty()); |
| 887 | 931 |
| 888 service()->RemoveObserver(&mock_observer); | 932 service()->RemoveObserver(&mock_observer); |
| 889 } | 933 } |
| 890 | 934 |
| 891 } // namespace ntp_snippets | 935 } // namespace ntp_snippets |
| OLD | NEW |