Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: components/ntp_snippets/ntp_snippets_service.cc

Issue 2000233002: [NTP Snippets] Unschedule fetches when the service should be disabled (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@SnippetsDB
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 NTPSnippetsService::NTPSnippetsService( 187 NTPSnippetsService::NTPSnippetsService(
188 PrefService* pref_service, 188 PrefService* pref_service,
189 sync_driver::SyncService* sync_service, 189 sync_driver::SyncService* sync_service,
190 SuggestionsService* suggestions_service, 190 SuggestionsService* suggestions_service,
191 const std::string& application_language_code, 191 const std::string& application_language_code,
192 NTPSnippetsScheduler* scheduler, 192 NTPSnippetsScheduler* scheduler,
193 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher, 193 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher,
194 std::unique_ptr<ImageFetcher> image_fetcher, 194 std::unique_ptr<ImageFetcher> image_fetcher,
195 std::unique_ptr<NTPSnippetsDatabase> database) 195 std::unique_ptr<NTPSnippetsDatabase> database)
196 : state_(State::NOT_INITED), 196 : state_(State::NOT_INITED),
197 enabled_(false), 197 explicitly_disabled_(false),
198 pref_service_(pref_service), 198 pref_service_(pref_service),
199 sync_service_(sync_service), 199 sync_service_(sync_service),
200 sync_service_observer_(this), 200 sync_service_observer_(this),
201 suggestions_service_(suggestions_service), 201 suggestions_service_(suggestions_service),
202 application_language_code_(application_language_code), 202 application_language_code_(application_language_code),
203 scheduler_(scheduler), 203 scheduler_(scheduler),
204 snippets_fetcher_(std::move(snippets_fetcher)), 204 snippets_fetcher_(std::move(snippets_fetcher)),
205 image_fetcher_(std::move(image_fetcher)), 205 image_fetcher_(std::move(image_fetcher)),
206 database_(std::move(database)) { 206 database_(std::move(database)) {
207 snippets_fetcher_->SetCallback(base::Bind( 207 snippets_fetcher_->SetCallback(base::Bind(
208 &NTPSnippetsService::OnFetchFinished, base::Unretained(this))); 208 &NTPSnippetsService::OnFetchFinished, base::Unretained(this)));
209 209
210 // |sync_service_| can be null in tests or if sync is disabled. 210 // |sync_service_| can be null in tests or if sync is disabled.
211 if (sync_service_) 211 if (sync_service_)
212 sync_service_observer_.Add(sync_service_); 212 sync_service_observer_.Add(sync_service_);
213 } 213 }
214 214
215 NTPSnippetsService::~NTPSnippetsService() { 215 NTPSnippetsService::~NTPSnippetsService() {
216 DCHECK(state_ == State::NOT_INITED || state_ == State::SHUT_DOWN); 216 DCHECK(state_ == State::NOT_INITED || state_ == State::SHUT_DOWN);
217 } 217 }
218 218
219 // static 219 // static
220 void NTPSnippetsService::RegisterProfilePrefs(PrefRegistrySimple* registry) { 220 void NTPSnippetsService::RegisterProfilePrefs(PrefRegistrySimple* registry) {
221 registry->RegisterListPref(prefs::kSnippets); 221 registry->RegisterListPref(prefs::kSnippets);
222 registry->RegisterListPref(prefs::kDiscardedSnippets); 222 registry->RegisterListPref(prefs::kDiscardedSnippets);
223 registry->RegisterListPref(prefs::kSnippetHosts); 223 registry->RegisterListPref(prefs::kSnippetHosts);
224 } 224 }
225 225
226 void NTPSnippetsService::Init(bool enabled) { 226 void NTPSnippetsService::Init(bool enabled) {
Marc Treib 2016/05/24 09:04:46 Heads-up: Michael's https://codereview.chromium.or
dgn 2016/05/24 18:13:30 Acknowledged.
227 DCHECK(state_ == State::NOT_INITED); 227 DCHECK(state_ == State::NOT_INITED);
228 state_ = State::INITED; 228 explicitly_disabled_ = !enabled;
229 229 EnterState(GetDisabledReason() == DisabledReason::NONE ? State::INITED
230 enabled_ = enabled; 230 : State::DISABLED);
231 if (enabled_) {
232 database_->Load(base::Bind(&NTPSnippetsService::OnSnippetsLoaded,
233 base::Unretained(this)));
234 }
235
236 RescheduleFetching();
237 } 231 }
238 232
233 // Inherited from KeyedService.
239 void NTPSnippetsService::Shutdown() { 234 void NTPSnippetsService::Shutdown() {
240 DCHECK(state_ == State::INITED || state_ == State::LOADED); 235 EnterState(State::SHUT_DOWN);
241 state_ = State::SHUT_DOWN;
242 236
243 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, 237 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_,
244 NTPSnippetsServiceShutdown()); 238 NTPSnippetsServiceShutdown());
245 expiry_timer_.Stop(); 239 expiry_timer_.Stop();
246 suggestions_service_subscription_.reset(); 240 suggestions_service_subscription_.reset();
247 enabled_ = false;
248 } 241 }
249 242
250 void NTPSnippetsService::FetchSnippets() { 243 void NTPSnippetsService::FetchSnippets() {
251 FetchSnippetsFromHosts(GetSuggestionsHosts()); 244 FetchSnippetsFromHosts(GetSuggestionsHosts());
252 } 245 }
253 246
254 void NTPSnippetsService::FetchSnippetsFromHosts( 247 void NTPSnippetsService::FetchSnippetsFromHosts(
255 const std::set<std::string>& hosts) { 248 const std::set<std::string>& hosts) {
256 if (!loaded()) 249 if (!loaded())
257 return; 250 return;
258 snippets_fetcher_->FetchSnippetsFromHosts(hosts, application_language_code_, 251 snippets_fetcher_->FetchSnippetsFromHosts(hosts, application_language_code_,
259 kMaxSnippetCount); 252 kMaxSnippetCount);
260 } 253 }
261 254
262 void NTPSnippetsService::RescheduleFetching() { 255 void NTPSnippetsService::RescheduleFetching() {
263 // The scheduler only exists on Android so far, it's null on other platforms. 256 // The scheduler only exists on Android so far, it's null on other platforms.
264 if (!scheduler_) 257 if (!scheduler_)
265 return; 258 return;
266 259
267 if (enabled_) { 260 if (state_ == State::INITED || state_ == State::READY) {
268 base::Time now = base::Time::Now(); 261 base::Time now = base::Time::Now();
269 scheduler_->Schedule( 262 scheduler_->Schedule(
270 GetFetchingIntervalWifiCharging(), GetFetchingIntervalWifi(now), 263 GetFetchingIntervalWifiCharging(), GetFetchingIntervalWifi(now),
271 GetFetchingIntervalFallback(), GetRescheduleTime(now)); 264 GetFetchingIntervalFallback(), GetRescheduleTime(now));
272 } else { 265 } else {
273 scheduler_->Unschedule(); 266 scheduler_->Unschedule();
274 } 267 }
275 } 268 }
276 269
277 void NTPSnippetsService::FetchSnippetImage( 270 void NTPSnippetsService::FetchSnippetImage(
(...skipping 13 matching lines...) Expand all
291 const NTPSnippet& snippet = *it->get(); 284 const NTPSnippet& snippet = *it->get();
292 // TODO(treib): Make ImageFetcher take a string instead of a GURL as an 285 // TODO(treib): Make ImageFetcher take a string instead of a GURL as an
293 // identifier. 286 // identifier.
294 image_fetcher_->StartOrQueueNetworkRequest( 287 image_fetcher_->StartOrQueueNetworkRequest(
295 GURL(snippet.id()), snippet.salient_image_url(), 288 GURL(snippet.id()), snippet.salient_image_url(),
296 base::Bind(WrapImageFetchedCallback, callback)); 289 base::Bind(WrapImageFetchedCallback, callback));
297 // TODO(treib): Cache/persist the snippet image. 290 // TODO(treib): Cache/persist the snippet image.
298 } 291 }
299 292
300 void NTPSnippetsService::ClearSnippets() { 293 void NTPSnippetsService::ClearSnippets() {
301 if (!loaded()) 294 if (!loaded() && state_ != State::DISABLED)
302 return; 295 return;
303 296
304 database_->Delete(snippets_); 297 database_->Delete(snippets_);
305 snippets_.clear(); 298 snippets_.clear();
306 299
307 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, 300 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_,
308 NTPSnippetsServiceLoaded()); 301 NTPSnippetsServiceLoaded());
309 } 302 }
310 303
311 std::set<std::string> NTPSnippetsService::GetSuggestionsHosts() const { 304 std::set<std::string> NTPSnippetsService::GetSuggestionsHosts() const {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 } 346 }
354 347
355 void NTPSnippetsService::AddObserver(NTPSnippetsServiceObserver* observer) { 348 void NTPSnippetsService::AddObserver(NTPSnippetsServiceObserver* observer) {
356 observers_.AddObserver(observer); 349 observers_.AddObserver(observer);
357 } 350 }
358 351
359 void NTPSnippetsService::RemoveObserver(NTPSnippetsServiceObserver* observer) { 352 void NTPSnippetsService::RemoveObserver(NTPSnippetsServiceObserver* observer) {
360 observers_.RemoveObserver(observer); 353 observers_.RemoveObserver(observer);
361 } 354 }
362 355
356 DisabledReason NTPSnippetsService::GetDisabledReason() {
357 if (explicitly_disabled_)
358 return DisabledReason::EXPLICITLY_DISABLED;
359
360 if (!sync_service_ || !sync_service_->CanSyncStart() ||
361 !sync_service_->GetActiveDataTypes().Has(
362 syncer::HISTORY_DELETE_DIRECTIVES))
363 return DisabledReason::HISTORY_SYNC_DISABLED;
364
365 return DisabledReason::NONE;
366 }
367
363 // static 368 // static
364 int NTPSnippetsService::GetMaxSnippetCountForTesting() { 369 int NTPSnippetsService::GetMaxSnippetCountForTesting() {
365 return kMaxSnippetCount; 370 return kMaxSnippetCount;
366 } 371 }
367 372
368 //////////////////////////////////////////////////////////////////////////////// 373 ////////////////////////////////////////////////////////////////////////////////
369 // Private methods 374 // Private methods
370 375
371 // sync_driver::SyncServiceObserver implementation. 376 // sync_driver::SyncServiceObserver implementation.
372 void NTPSnippetsService::OnStateChanged() { 377 void NTPSnippetsService::OnStateChanged() {
373 if (IsSyncStateIncompatible()) { 378 bool enabled = GetDisabledReason() == DisabledReason::NONE;
374 ClearSnippets(); 379
375 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, 380 if (enabled == (state_ != State::DISABLED))
376 NTPSnippetsServiceDisabled()); 381 return;
382
383 // |GetDisabledReason| is strict and marks the state as disabled even in cases
384 // where we miss some data. During initialization or when the user is changing
385 // the sync settings, we can run in false negatives where we mark the state
386 // as disabled. We wait do nothing here until the configuration is completely
387 // loaded to avoid unnecessary state changes.
Marc Treib 2016/05/24 09:04:46 Hm, this kinda seems wrong. IMO we should have a c
dgn 2016/05/24 18:13:30 I explicitly handle the UNKNOWN state now. WDYT?
Marc Treib 2016/05/25 14:47:32 SGTM!
388 if (sync_service_ && sync_service_->IsSyncActive() &&
389 !sync_service_->ConfigurationDone()) {
390 DVLOG(1) << "Sync configuration not done, skipping a state change.";
377 return; 391 return;
378 } 392 }
379 393
380 // TODO(dgn): When the data sources change, we may want to not fetch here, 394 EnterState(enabled ? State::INITED : State::DISABLED);
Marc Treib 2016/05/24 09:04:46 What if we were already in the READY state?
dgn 2016/05/24 18:13:30 Handled same state transitions as noops in EnterSt
381 // as we will get notified of changes from the snippet sources as well, and
382 // start multiple fetches.
383 FetchSnippets();
384 } 395 }
385 396
386 void NTPSnippetsService::OnSnippetsLoaded(NTPSnippet::PtrVector snippets) { 397 void NTPSnippetsService::OnSnippetsLoaded(NTPSnippet::PtrVector snippets) {
387 DCHECK(state_ == State::INITED || state_ == State::SHUT_DOWN); 398 DCHECK(state_ == State::INITED || state_ == State::SHUT_DOWN);
388 if (state_ == State::SHUT_DOWN) 399 if (state_ == State::SHUT_DOWN)
389 return; 400 return; // TODO(dgn) how can we get here? Just race conditons?
Marc Treib 2016/05/24 09:04:46 I think it can happen if we started a fetch, then
dgn 2016/05/24 18:13:30 Acknowledged.
390 state_ = State::LOADED; 401 EnterState(State::LOADED);
391 402
392 DCHECK(snippets_.empty()); 403 DCHECK(snippets_.empty());
393 DCHECK(discarded_snippets_.empty()); 404 DCHECK(discarded_snippets_.empty());
394 for (std::unique_ptr<NTPSnippet>& snippet : snippets) { 405 for (std::unique_ptr<NTPSnippet>& snippet : snippets) {
395 if (snippet->is_discarded()) 406 if (snippet->is_discarded())
396 discarded_snippets_.emplace_back(std::move(snippet)); 407 discarded_snippets_.emplace_back(std::move(snippet));
397 else 408 else
398 snippets_.emplace_back(std::move(snippet)); 409 snippets_.emplace_back(std::move(snippet));
399 } 410 }
400 std::sort(snippets_.begin(), snippets_.end(), 411 std::sort(snippets_.begin(), snippets_.end(),
(...skipping 11 matching lines...) Expand all
412 &NTPSnippetsService::OnSuggestionsChanged, base::Unretained(this))); 423 &NTPSnippetsService::OnSuggestionsChanged, base::Unretained(this)));
413 } 424 }
414 425
415 // If we don't have any snippets yet, start a fetch. 426 // If we don't have any snippets yet, start a fetch.
416 if (snippets_.empty()) 427 if (snippets_.empty())
417 FetchSnippets(); 428 FetchSnippets();
418 } 429 }
419 430
420 void NTPSnippetsService::OnSuggestionsChanged( 431 void NTPSnippetsService::OnSuggestionsChanged(
421 const SuggestionsProfile& suggestions) { 432 const SuggestionsProfile& suggestions) {
422 DCHECK(loaded()); 433 DCHECK(loaded() || state_ == State::DISABLED);
423 434
424 std::set<std::string> hosts = GetSuggestionsHostsImpl(suggestions); 435 std::set<std::string> hosts = GetSuggestionsHostsImpl(suggestions);
425 if (hosts == GetSnippetHostsFromPrefs()) 436 if (hosts == GetSnippetHostsFromPrefs())
426 return; 437 return;
427 438
428 // Remove existing snippets that aren't in the suggestions anymore. 439 // Remove existing snippets that aren't in the suggestions anymore.
429 // TODO(treib,maybelle): If there is another source with an allowed host, 440 // TODO(treib,maybelle): If there is another source with an allowed host,
430 // then we should fall back to that. 441 // then we should fall back to that.
431 // First, move them over into |to_delete|. 442 // First, move them over into |to_delete|.
432 NTPSnippet::PtrVector to_delete; 443 NTPSnippet::PtrVector to_delete;
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 for (const auto& snippet : discarded_snippets_) { 612 for (const auto& snippet : discarded_snippets_) {
602 if (snippet->expiry_date() < next_expiry) 613 if (snippet->expiry_date() < next_expiry)
603 next_expiry = snippet->expiry_date(); 614 next_expiry = snippet->expiry_date();
604 } 615 }
605 DCHECK_GT(next_expiry, expiry); 616 DCHECK_GT(next_expiry, expiry);
606 expiry_timer_.Start(FROM_HERE, next_expiry - expiry, 617 expiry_timer_.Start(FROM_HERE, next_expiry - expiry,
607 base::Bind(&NTPSnippetsService::LoadingSnippetsFinished, 618 base::Bind(&NTPSnippetsService::LoadingSnippetsFinished,
608 base::Unretained(this))); 619 base::Unretained(this)));
609 } 620 }
610 621
611 bool NTPSnippetsService::IsSyncStateIncompatible() { 622 void NTPSnippetsService::Enable() {
612 if (!sync_service_ || !sync_service_->CanSyncStart()) 623 database_->Load(base::Bind(&NTPSnippetsService::OnSnippetsLoaded,
613 return true; 624 base::Unretained(this)));
614 if (!sync_service_->IsSyncActive() || !sync_service_->ConfigurationDone()) 625 RescheduleFetching();
615 return false; // Sync service is not initialized, yet not disabled. 626 }
616 return !sync_service_->GetActiveDataTypes().Has( 627
617 syncer::HISTORY_DELETE_DIRECTIVES); 628 void NTPSnippetsService::Disable() {
629 state_ = State::DISABLED;
Marc Treib 2016/05/24 09:04:46 IMO only EnterState should change state_. I think
dgn 2016/05/24 18:13:30 Done.
630 ClearSnippets();
631 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_,
632 NTPSnippetsServiceDisabled());
633 RescheduleFetching();
634 }
635
636 void NTPSnippetsService::EnterState(State state) {
637 switch (state) {
638 case State::NOT_INITED:
639 // Initial state, should not be possible to get back there.
640 NOTREACHED();
641 break;
642 case State::INITED:
643 DCHECK(state_ == State::NOT_INITED || state_ == State::DISABLED);
644 Enable();
645 break;
646 case State::READY:
647 DCHECK(state_ == State::INITED);
648 // TODO
649 break;
650 case State::DISABLED:
651 DCHECK(state_ == State::NOT_INITED || state_ == State::READY);
652 Disable();
653 break;
654 case State::SHUT_DOWN:
655 DCHECK(state_ == State::INITED || state_ == State::DISABLED ||
656 state_ == State::READY);
657 break;
658 }
659 state_ = state;
618 } 660 }
619 661
620 } // namespace ntp_snippets 662 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698