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 <algorithm> | 7 #include <algorithm> |
8 #include <iterator> | 8 #include <iterator> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "base/values.h" | 21 #include "base/values.h" |
22 #include "components/image_fetcher/image_decoder.h" | 22 #include "components/image_fetcher/image_decoder.h" |
23 #include "components/image_fetcher/image_fetcher.h" | 23 #include "components/image_fetcher/image_fetcher.h" |
24 #include "components/ntp_snippets/ntp_snippets_constants.h" | 24 #include "components/ntp_snippets/ntp_snippets_constants.h" |
25 #include "components/ntp_snippets/ntp_snippets_database.h" | 25 #include "components/ntp_snippets/ntp_snippets_database.h" |
26 #include "components/ntp_snippets/pref_names.h" | 26 #include "components/ntp_snippets/pref_names.h" |
27 #include "components/ntp_snippets/switches.h" | 27 #include "components/ntp_snippets/switches.h" |
28 #include "components/prefs/pref_registry_simple.h" | 28 #include "components/prefs/pref_registry_simple.h" |
29 #include "components/prefs/pref_service.h" | 29 #include "components/prefs/pref_service.h" |
30 #include "components/suggestions/proto/suggestions.pb.h" | 30 #include "components/suggestions/proto/suggestions.pb.h" |
31 #include "components/sync_driver/sync_service.h" | |
32 #include "components/variations/variations_associated_data.h" | 31 #include "components/variations/variations_associated_data.h" |
33 #include "ui/gfx/image/image.h" | 32 #include "ui/gfx/image/image.h" |
34 | 33 |
35 using image_fetcher::ImageDecoder; | 34 using image_fetcher::ImageDecoder; |
36 using image_fetcher::ImageFetcher; | 35 using image_fetcher::ImageFetcher; |
37 using suggestions::ChromeSuggestion; | 36 using suggestions::ChromeSuggestion; |
38 using suggestions::SuggestionsProfile; | 37 using suggestions::SuggestionsProfile; |
39 using suggestions::SuggestionsService; | 38 using suggestions::SuggestionsService; |
40 | 39 |
41 namespace ntp_snippets { | 40 namespace ntp_snippets { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 snippets->begin(), snippets->end(), | 174 snippets->begin(), snippets->end(), |
176 [](const std::unique_ptr<NTPSnippet>& snippet) { return !snippet; }), | 175 [](const std::unique_ptr<NTPSnippet>& snippet) { return !snippet; }), |
177 snippets->end()); | 176 snippets->end()); |
178 } | 177 } |
179 | 178 |
180 } // namespace | 179 } // namespace |
181 | 180 |
182 NTPSnippetsService::NTPSnippetsService( | 181 NTPSnippetsService::NTPSnippetsService( |
183 bool enabled, | 182 bool enabled, |
184 PrefService* pref_service, | 183 PrefService* pref_service, |
185 sync_driver::SyncService* sync_service, | |
186 SuggestionsService* suggestions_service, | 184 SuggestionsService* suggestions_service, |
187 const std::string& application_language_code, | 185 const std::string& application_language_code, |
188 NTPSnippetsScheduler* scheduler, | 186 NTPSnippetsScheduler* scheduler, |
189 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher, | 187 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher, |
190 std::unique_ptr<ImageFetcher> image_fetcher, | 188 std::unique_ptr<ImageFetcher> image_fetcher, |
191 std::unique_ptr<ImageDecoder> image_decoder, | 189 std::unique_ptr<ImageDecoder> image_decoder, |
192 std::unique_ptr<NTPSnippetsDatabase> database) | 190 std::unique_ptr<NTPSnippetsDatabase> database, |
| 191 std::unique_ptr<NTPSnippetsStatusService> status_service) |
193 : state_(State::NOT_INITED), | 192 : state_(State::NOT_INITED), |
194 explicitly_disabled_(!enabled), | |
195 pref_service_(pref_service), | 193 pref_service_(pref_service), |
196 sync_service_(sync_service), | |
197 sync_service_observer_(this), | |
198 suggestions_service_(suggestions_service), | 194 suggestions_service_(suggestions_service), |
199 application_language_code_(application_language_code), | 195 application_language_code_(application_language_code), |
200 scheduler_(scheduler), | 196 scheduler_(scheduler), |
201 snippets_fetcher_(std::move(snippets_fetcher)), | 197 snippets_fetcher_(std::move(snippets_fetcher)), |
202 image_fetcher_(std::move(image_fetcher)), | 198 image_fetcher_(std::move(image_fetcher)), |
203 image_decoder_(std::move(image_decoder)), | 199 image_decoder_(std::move(image_decoder)), |
204 database_(std::move(database)), | 200 database_(std::move(database)), |
| 201 snippets_status_service_(std::move(status_service)), |
205 fetch_after_load_(false) { | 202 fetch_after_load_(false) { |
206 // TODO(dgn) should be removed after branch point (https://crbug.com/617585). | 203 // TODO(dgn) should be removed after branch point (https://crbug.com/617585). |
207 ClearDeprecatedPrefs(); | 204 ClearDeprecatedPrefs(); |
208 | 205 |
209 if (explicitly_disabled_) { | 206 if (!enabled || database_->IsErrorState()) { |
210 EnterState(State::DISABLED); | 207 // Don't even bother loading the database. |
211 return; | |
212 } | |
213 | |
214 if (database_->IsErrorState()) { | |
215 EnterState(State::SHUT_DOWN); | 208 EnterState(State::SHUT_DOWN); |
216 return; | 209 return; |
217 } | 210 } |
218 | 211 |
219 database_->SetErrorCallback(base::Bind(&NTPSnippetsService::OnDatabaseError, | 212 database_->SetErrorCallback(base::Bind(&NTPSnippetsService::OnDatabaseError, |
220 base::Unretained(this))); | 213 base::Unretained(this))); |
221 | 214 |
222 // We transition to other states while finalizing the initialization, when the | 215 // We transition to other states while finalizing the initialization, when the |
223 // database is done loading. | 216 // database is done loading. |
224 database_->LoadSnippets(base::Bind(&NTPSnippetsService::OnDatabaseLoaded, | 217 database_->LoadSnippets(base::Bind(&NTPSnippetsService::OnDatabaseLoaded, |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 } | 334 } |
342 | 335 |
343 void NTPSnippetsService::AddObserver(NTPSnippetsServiceObserver* observer) { | 336 void NTPSnippetsService::AddObserver(NTPSnippetsServiceObserver* observer) { |
344 observers_.AddObserver(observer); | 337 observers_.AddObserver(observer); |
345 } | 338 } |
346 | 339 |
347 void NTPSnippetsService::RemoveObserver(NTPSnippetsServiceObserver* observer) { | 340 void NTPSnippetsService::RemoveObserver(NTPSnippetsServiceObserver* observer) { |
348 observers_.RemoveObserver(observer); | 341 observers_.RemoveObserver(observer); |
349 } | 342 } |
350 | 343 |
351 DisabledReason NTPSnippetsService::GetDisabledReason() const { | |
352 if (explicitly_disabled_) | |
353 return DisabledReason::EXPLICITLY_DISABLED; | |
354 | |
355 if (!sync_service_ || !sync_service_->CanSyncStart()) { | |
356 DVLOG(1) << "[GetDisabledReason] Sync disabled"; | |
357 return DisabledReason::HISTORY_SYNC_DISABLED; | |
358 } | |
359 | |
360 // !IsSyncActive in cases where CanSyncStart is true hints at the backend not | |
361 // being initialized. | |
362 // ConfigurationDone() verifies that the sync service has properly loaded its | |
363 // configuration and is aware of the different data types to sync. | |
364 if (!sync_service_->IsSyncActive() || !sync_service_->ConfigurationDone()) { | |
365 DVLOG(1) << "[GetDisabledReason] Sync initialization is not complete."; | |
366 return DisabledReason::HISTORY_SYNC_STATE_UNKNOWN; | |
367 } | |
368 | |
369 if (!sync_service_->GetActiveDataTypes().Has( | |
370 syncer::HISTORY_DELETE_DIRECTIVES)) { | |
371 DVLOG(1) << "[GetDisabledReason] History sync disabled"; | |
372 return DisabledReason::HISTORY_SYNC_DISABLED; | |
373 } | |
374 | |
375 DVLOG(1) << "[GetDisabledReason] Enabled"; | |
376 return DisabledReason::NONE; | |
377 } | |
378 | |
379 // static | 344 // static |
380 int NTPSnippetsService::GetMaxSnippetCountForTesting() { | 345 int NTPSnippetsService::GetMaxSnippetCountForTesting() { |
381 return kMaxSnippetCount; | 346 return kMaxSnippetCount; |
382 } | 347 } |
383 | 348 |
384 //////////////////////////////////////////////////////////////////////////////// | 349 //////////////////////////////////////////////////////////////////////////////// |
385 // Private methods | 350 // Private methods |
386 | 351 |
387 void NTPSnippetsService::OnStateChanged() { | |
388 if (state_ == State::SHUT_DOWN) | |
389 return; | |
390 | |
391 DVLOG(1) << "[OnStateChanged]"; | |
392 EnterState(GetStateForDependenciesStatus()); | |
393 } | |
394 | |
395 // image_fetcher::ImageFetcherDelegate implementation. | 352 // image_fetcher::ImageFetcherDelegate implementation. |
396 void NTPSnippetsService::OnImageDataFetched(const std::string& snippet_id, | 353 void NTPSnippetsService::OnImageDataFetched(const std::string& snippet_id, |
397 const std::string& image_data) { | 354 const std::string& image_data) { |
398 if (image_data.empty()) | 355 if (image_data.empty()) |
399 return; | 356 return; |
400 | 357 |
401 // Only save the image if the corresponding snippet still exists. | 358 // Only save the image if the corresponding snippet still exists. |
402 auto it = | 359 auto it = |
403 std::find_if(snippets_.begin(), snippets_.end(), | 360 std::find_if(snippets_.begin(), snippets_.end(), |
404 [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { | 361 [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 &NTPSnippetsService::OnSuggestionsChanged, base::Unretained(this))); | 644 &NTPSnippetsService::OnSuggestionsChanged, base::Unretained(this))); |
688 } | 645 } |
689 | 646 |
690 RescheduleFetching(); | 647 RescheduleFetching(); |
691 } | 648 } |
692 | 649 |
693 void NTPSnippetsService::EnterStateDisabled() { | 650 void NTPSnippetsService::EnterStateDisabled() { |
694 ClearSnippets(); | 651 ClearSnippets(); |
695 ClearDiscardedSnippets(); | 652 ClearDiscardedSnippets(); |
696 | 653 |
| 654 expiry_timer_.Stop(); |
697 suggestions_service_subscription_.reset(); | 655 suggestions_service_subscription_.reset(); |
698 expiry_timer_.Stop(); | |
699 | |
700 RescheduleFetching(); | 656 RescheduleFetching(); |
701 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, | |
702 NTPSnippetsServiceDisabled()); | |
703 } | 657 } |
704 | 658 |
705 void NTPSnippetsService::EnterStateShutdown() { | 659 void NTPSnippetsService::EnterStateShutdown() { |
706 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, | 660 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, |
707 NTPSnippetsServiceShutdown()); | 661 NTPSnippetsServiceShutdown()); |
708 | 662 |
709 expiry_timer_.Stop(); | 663 expiry_timer_.Stop(); |
710 suggestions_service_subscription_.reset(); | 664 suggestions_service_subscription_.reset(); |
| 665 RescheduleFetching(); |
711 | 666 |
712 if (sync_service_) | 667 snippets_status_service_.reset(); |
713 sync_service_observer_.Remove(sync_service_); | |
714 } | 668 } |
715 | 669 |
716 void NTPSnippetsService::FinishInitialization() { | 670 void NTPSnippetsService::FinishInitialization() { |
717 snippets_fetcher_->SetCallback( | 671 snippets_fetcher_->SetCallback( |
718 base::Bind(&NTPSnippetsService::OnFetchFinished, base::Unretained(this))); | 672 base::Bind(&NTPSnippetsService::OnFetchFinished, base::Unretained(this))); |
719 | 673 |
720 // |image_fetcher_| can be null in tests. | 674 // |image_fetcher_| can be null in tests. |
721 if (image_fetcher_) | 675 if (image_fetcher_) |
722 image_fetcher_->SetImageFetcherDelegate(this); | 676 image_fetcher_->SetImageFetcherDelegate(this); |
723 | 677 |
724 // |sync_service_| can be null in tests or if sync is disabled. | 678 // Note: Initializing the status service will run the callback right away with |
725 // This is a service we want to keep listening to all the time, independently | 679 // the current state. |
726 // from the state, since it will allow us to enable or disable the snippets | 680 snippets_status_service_->Init(base::Bind( |
727 // service. | 681 &NTPSnippetsService::UpdateStateForStatus, base::Unretained(this))); |
728 if (sync_service_) | |
729 sync_service_observer_.Add(sync_service_); | |
730 | |
731 // Change state after we started loading the snippets. During startup, the | |
732 // Sync service might not be completely loaded when we initialize this | |
733 // service, so we might stay in the NOT_INITED state until the sync state is | |
734 // updated. See |GetStateForDependenciesStatus|. | |
735 EnterState(GetStateForDependenciesStatus()); | |
736 | 682 |
737 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, | 683 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, |
738 NTPSnippetsServiceLoaded()); | 684 NTPSnippetsServiceLoaded()); |
739 | |
740 // Start a fetch if we don't have any snippets yet, or a fetch was requested | |
741 // earlier. | |
742 if (ready() && (snippets_.empty() || fetch_after_load_)) { | |
743 fetch_after_load_ = false; | |
744 FetchSnippets(); | |
745 } | |
746 } | 685 } |
747 | 686 |
748 NTPSnippetsService::State NTPSnippetsService::GetStateForDependenciesStatus() { | 687 void NTPSnippetsService::UpdateStateForStatus(DisabledReason disabled_reason) { |
749 switch (GetDisabledReason()) { | 688 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, |
| 689 NTPSnippetsServiceDisabledReasonChanged(disabled_reason)); |
| 690 |
| 691 State new_state; |
| 692 switch (disabled_reason) { |
750 case DisabledReason::NONE: | 693 case DisabledReason::NONE: |
751 return State::READY; | 694 new_state = State::READY; |
| 695 break; |
752 | 696 |
753 case DisabledReason::HISTORY_SYNC_STATE_UNKNOWN: | 697 case DisabledReason::HISTORY_SYNC_STATE_UNKNOWN: |
754 // HistorySync is not initialized yet, so we don't know what the actual | 698 // HistorySync is not initialized yet, so we don't know what the actual |
755 // state is and we just return the current one. If things change, | 699 // state is and we just return the current one. If things change, |
756 // |OnStateChanged| will call this function again to update the state. | 700 // |OnStateChanged| will call this function again to update the state. |
757 DVLOG(1) << "Sync configuration incomplete, continuing based on the " | 701 DVLOG(1) << "Sync configuration incomplete, continuing based on the " |
758 "current state."; | 702 "current state."; |
759 return state_; | 703 new_state = state_; |
| 704 break; |
760 | 705 |
761 case DisabledReason::EXPLICITLY_DISABLED: | 706 case DisabledReason::EXPLICITLY_DISABLED: |
| 707 case DisabledReason::SIGNED_OUT: |
| 708 case DisabledReason::SYNC_DISABLED: |
| 709 case DisabledReason::PASSPHRASE_ENCRYPTION_ENABLED: |
762 case DisabledReason::HISTORY_SYNC_DISABLED: | 710 case DisabledReason::HISTORY_SYNC_DISABLED: |
763 return State::DISABLED; | 711 new_state = State::DISABLED; |
| 712 break; |
| 713 |
| 714 default: |
| 715 // All cases should be handled by the above switch |
| 716 NOTREACHED(); |
| 717 new_state = State::DISABLED; |
| 718 break; |
764 } | 719 } |
765 | 720 |
766 // All cases should be handled by the above switch | 721 EnterState(new_state); |
767 NOTREACHED(); | |
768 return State::DISABLED; | |
769 } | 722 } |
770 | 723 |
771 void NTPSnippetsService::EnterState(State state) { | 724 void NTPSnippetsService::EnterState(State state) { |
772 if (state == state_) | 725 if (state == state_) |
773 return; | 726 return; |
774 | 727 |
775 switch (state) { | 728 switch (state) { |
776 case State::NOT_INITED: | 729 case State::NOT_INITED: |
777 // Initial state, it should not be possible to get back there. | 730 // Initial state, it should not be possible to get back there. |
778 NOTREACHED(); | 731 NOTREACHED(); |
779 return; | 732 return; |
780 | 733 |
781 case State::READY: { | 734 case State::READY: { |
782 DCHECK(state_ == State::NOT_INITED || state_ == State::DISABLED); | 735 DCHECK(state_ == State::NOT_INITED || state_ == State::DISABLED); |
783 | 736 |
784 // If the service was previously disabled, we will need to start a fetch | 737 bool fetch_snippets = snippets_.empty() || fetch_after_load_; |
785 // because otherwise there won't be any. | |
786 bool fetch_snippets = state_ == State::DISABLED || fetch_after_load_; | |
787 DVLOG(1) << "Entering state: READY"; | 738 DVLOG(1) << "Entering state: READY"; |
788 state_ = State::READY; | 739 state_ = State::READY; |
789 fetch_after_load_ = false; | 740 fetch_after_load_ = false; |
790 EnterStateEnabled(fetch_snippets); | 741 EnterStateEnabled(fetch_snippets); |
791 return; | 742 return; |
792 } | 743 } |
793 | 744 |
794 case State::DISABLED: | 745 case State::DISABLED: |
795 DCHECK(state_ == State::NOT_INITED || state_ == State::READY); | 746 DCHECK(state_ == State::NOT_INITED || state_ == State::READY); |
796 | 747 |
797 DVLOG(1) << "Entering state: DISABLED"; | 748 DVLOG(1) << "Entering state: DISABLED"; |
798 state_ = State::DISABLED; | 749 state_ = State::DISABLED; |
799 EnterStateDisabled(); | 750 EnterStateDisabled(); |
800 return; | 751 return; |
801 | 752 |
802 case State::SHUT_DOWN: | 753 case State::SHUT_DOWN: |
803 DVLOG(1) << "Entering state: SHUT_DOWN"; | 754 DVLOG(1) << "Entering state: SHUT_DOWN"; |
804 state_ = State::SHUT_DOWN; | 755 state_ = State::SHUT_DOWN; |
805 EnterStateShutdown(); | 756 EnterStateShutdown(); |
806 return; | 757 return; |
807 } | 758 } |
808 } | 759 } |
809 | 760 |
810 void NTPSnippetsService::ClearDeprecatedPrefs() { | 761 void NTPSnippetsService::ClearDeprecatedPrefs() { |
811 pref_service_->ClearPref(prefs::kDeprecatedSnippets); | 762 pref_service_->ClearPref(prefs::kDeprecatedSnippets); |
812 pref_service_->ClearPref(prefs::kDeprecatedDiscardedSnippets); | 763 pref_service_->ClearPref(prefs::kDeprecatedDiscardedSnippets); |
813 } | 764 } |
814 | 765 |
815 } // namespace ntp_snippets | 766 } // namespace ntp_snippets |
OLD | NEW |