Commit 92eb7422 authored by Sky Malice's avatar Sky Malice Committed by Commit Bot

[Feed] Trigger refresh after sign in and out.

Previously the scheduler was being directly called by the
ChromeBrowsingDataRemoverDelegate when history was deleted. When this
happened, we cleared internal state and suppressed refreshes. This
sometimes coincided with when the FeedAppLifecycle cleared all stored
articles, but not very well. Particularly, when:
* Signing in
* Signing out
* Clear the cache

So instead, the scheduler is notified by the FeedAppLifecycle exactly
when all articles are cleared. A boolean is also passed along to inform
the scheduler which of the two states are we in. Did something get cleared
and we should suppress refreshing? Or do we now have no data and need to
refresh immediately.

Bug: 905959
Change-Id: I25c57022a0da52cc42746d265beae1c55f84d3ec
Reviewed-on: https://chromium-review.googlesource.com/c/1355994
Commit-Queue: Sky Malice <skym@chromium.org>
Reviewed-by: default avatarFilip Gorski <fgorski@chromium.org>
Reviewed-by: default avatarMartin Šrámek <msramek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612848}
parent 3fd8a163
...@@ -102,7 +102,7 @@ public class FeedAppLifecycle ...@@ -102,7 +102,7 @@ public class FeedAppLifecycle
* We call onClearAll to avoid presenting personalized suggestions based on deleted history. * We call onClearAll to avoid presenting personalized suggestions based on deleted history.
*/ */
public void onHistoryDeleted() { public void onHistoryDeleted() {
onClearAll(); onClearAll(/*suppressRefreshes*/ true);
} }
/** /**
...@@ -110,7 +110,7 @@ public class FeedAppLifecycle ...@@ -110,7 +110,7 @@ public class FeedAppLifecycle
* Feed deletes its cached browsing data. * Feed deletes its cached browsing data.
*/ */
public void onCachedDataCleared() { public void onCachedDataCleared() {
onClearAll(); onClearAll(/*suppressRefreshes*/ false);
} }
/** /**
...@@ -152,12 +152,12 @@ public class FeedAppLifecycle ...@@ -152,12 +152,12 @@ public class FeedAppLifecycle
@Override @Override
public void onSignedIn() { public void onSignedIn() {
onClearAll(); onClearAll(/*suppressRefreshes*/ false);
} }
@Override @Override
public void onSignedOut() { public void onSignedOut() {
onClearAll(); onClearAll(/*suppressRefreshes*/ false);
} }
private void onEnterForeground() { private void onEnterForeground() {
...@@ -170,9 +170,14 @@ public class FeedAppLifecycle ...@@ -170,9 +170,14 @@ public class FeedAppLifecycle
mAppLifecycleListener.onEnterBackground(); mAppLifecycleListener.onEnterBackground();
} }
private void onClearAll() { private void onClearAll(boolean suppressRefreshes) {
reportEvent(AppLifecycleEvent.CLEAR_ALL); reportEvent(AppLifecycleEvent.CLEAR_ALL);
// It is important that #onClearAll() is called before notifying the scheduler, otherwise
// the clear all could wipe out the new results. These are both async operations that are
// kicked off here, but the Feed is responsible for tracking them and making sure they're
// correctly respected.
mAppLifecycleListener.onClearAll(); mAppLifecycleListener.onClearAll();
mFeedScheduler.onArticlesCleared(suppressRefreshes);
} }
private void initialize() { private void initialize() {
......
...@@ -17,9 +17,19 @@ public interface FeedScheduler extends SchedulerApi { ...@@ -17,9 +17,19 @@ public interface FeedScheduler extends SchedulerApi {
/** To be called whenever the browser is foregrounded. */ /** To be called whenever the browser is foregrounded. */
void onForegrounded(); void onForegrounded();
/** To be called when a background scheduling task wakes up the browser. */ /**
* To be called when a background scheduling task wakes up the browser.
* @param onCompletion to be run when the fixed timer logic is complete.
*/
void onFixedTimer(Runnable onCompletion); void onFixedTimer(Runnable onCompletion);
/** To be called when an article is consumed, influencing future scheduling. */ /** To be called when an article is consumed, influencing future scheduling. */
void onSuggestionConsumed(); void onSuggestionConsumed();
/**
* To be called when articles are cleared.
* @param suppressRefreshes whether the scheduler should temporarily avoid kicking off
* refreshes. This is used, for example, when history data is deleted.
*/
void onArticlesCleared(boolean suppressRefreshes);
} }
...@@ -124,6 +124,12 @@ public class FeedSchedulerBridge implements FeedScheduler { ...@@ -124,6 +124,12 @@ public class FeedSchedulerBridge implements FeedScheduler {
nativeOnSuggestionConsumed(mNativeBridge); nativeOnSuggestionConsumed(mNativeBridge);
} }
@Override
public void onArticlesCleared(boolean suppressRefreshes) {
assert mNativeBridge != 0;
nativeOnArticlesCleared(mNativeBridge, suppressRefreshes);
}
@CalledByNative @CalledByNative
private boolean triggerRefresh() { private boolean triggerRefresh() {
if (mRequestManager != null && mSessionManager != null) { if (mRequestManager != null && mSessionManager != null) {
...@@ -156,4 +162,6 @@ public class FeedSchedulerBridge implements FeedScheduler { ...@@ -156,4 +162,6 @@ public class FeedSchedulerBridge implements FeedScheduler {
private native void nativeOnFixedTimer( private native void nativeOnFixedTimer(
long nativeFeedSchedulerBridge, Callback<Void> onCompletion); long nativeFeedSchedulerBridge, Callback<Void> onCompletion);
private native void nativeOnSuggestionConsumed(long nativeFeedSchedulerBridge); private native void nativeOnSuggestionConsumed(long nativeFeedSchedulerBridge);
private native void nativeOnArticlesCleared(
long nativeFeedSchedulerBridge, boolean suppressRefreshes);
} }
...@@ -161,6 +161,7 @@ public class FeedAppLifecycleTest { ...@@ -161,6 +161,7 @@ public class FeedAppLifecycleTest {
assertEquals(1, assertEquals(1,
RecordHistogram.getHistogramValueCountForTesting( RecordHistogram.getHistogramValueCountForTesting(
mHistogramAppLifecycleEvents, AppLifecycleEvent.CLEAR_ALL)); mHistogramAppLifecycleEvents, AppLifecycleEvent.CLEAR_ALL));
verify(mFeedScheduler, times(1)).onArticlesCleared(true);
} }
@Test @Test
...@@ -173,6 +174,7 @@ public class FeedAppLifecycleTest { ...@@ -173,6 +174,7 @@ public class FeedAppLifecycleTest {
assertEquals(1, assertEquals(1,
RecordHistogram.getHistogramValueCountForTesting( RecordHistogram.getHistogramValueCountForTesting(
mHistogramAppLifecycleEvents, AppLifecycleEvent.CLEAR_ALL)); mHistogramAppLifecycleEvents, AppLifecycleEvent.CLEAR_ALL));
verify(mFeedScheduler, times(1)).onArticlesCleared(false);
} }
@Test @Test
...@@ -185,6 +187,7 @@ public class FeedAppLifecycleTest { ...@@ -185,6 +187,7 @@ public class FeedAppLifecycleTest {
assertEquals(1, assertEquals(1,
RecordHistogram.getHistogramValueCountForTesting( RecordHistogram.getHistogramValueCountForTesting(
mHistogramAppLifecycleEvents, AppLifecycleEvent.CLEAR_ALL)); mHistogramAppLifecycleEvents, AppLifecycleEvent.CLEAR_ALL));
verify(mFeedScheduler, times(1)).onArticlesCleared(false);
} }
@Test @Test
...@@ -197,6 +200,7 @@ public class FeedAppLifecycleTest { ...@@ -197,6 +200,7 @@ public class FeedAppLifecycleTest {
assertEquals(1, assertEquals(1,
RecordHistogram.getHistogramValueCountForTesting( RecordHistogram.getHistogramValueCountForTesting(
mHistogramAppLifecycleEvents, AppLifecycleEvent.CLEAR_ALL)); mHistogramAppLifecycleEvents, AppLifecycleEvent.CLEAR_ALL));
verify(mFeedScheduler, times(1)).onArticlesCleared(false);
} }
@Test @Test
......
...@@ -100,6 +100,13 @@ void FeedSchedulerBridge::OnSuggestionConsumed( ...@@ -100,6 +100,13 @@ void FeedSchedulerBridge::OnSuggestionConsumed(
scheduler_host_->OnSuggestionConsumed(); scheduler_host_->OnSuggestionConsumed();
} }
void FeedSchedulerBridge::OnArticlesCleared(
JNIEnv* env,
const base::android::JavaRef<jobject>& j_this,
jboolean j_suppress_refreshes) {
scheduler_host_->OnArticlesCleared(j_suppress_refreshes);
}
void FeedSchedulerBridge::TriggerRefresh() { void FeedSchedulerBridge::TriggerRefresh() {
JNIEnv* env = base::android::AttachCurrentThread(); JNIEnv* env = base::android::AttachCurrentThread();
Java_FeedSchedulerBridge_triggerRefresh(env, j_this_); Java_FeedSchedulerBridge_triggerRefresh(env, j_this_);
......
...@@ -56,6 +56,10 @@ class FeedSchedulerBridge { ...@@ -56,6 +56,10 @@ class FeedSchedulerBridge {
void OnSuggestionConsumed(JNIEnv* env, void OnSuggestionConsumed(JNIEnv* env,
const base::android::JavaRef<jobject>& j_this); const base::android::JavaRef<jobject>& j_this);
void OnArticlesCleared(JNIEnv* env,
const base::android::JavaRef<jobject>& j_this,
jboolean j_suppress_refreshes);
private: private:
// Callable by native code to invoke Java code. Sends a request to the Feed // Callable by native code to invoke Java code. Sends a request to the Feed
// library to make the refresh call. // library to make the refresh call.
......
...@@ -72,7 +72,6 @@ ...@@ -72,7 +72,6 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
#include "components/device_event_log/device_event_log.h" #include "components/device_event_log/device_event_log.h"
#include "components/feed/content/feed_host_service.h" #include "components/feed/content/feed_host_service.h"
#include "components/feed/core/feed_scheduler_host.h"
#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service.h"
#include "components/language/core/browser/url_language_histogram.h" #include "components/language/core/browser/url_language_histogram.h"
#include "components/nacl/browser/nacl_browser.h" #include "components/nacl/browser/nacl_browser.h"
...@@ -418,16 +417,6 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( ...@@ -418,16 +417,6 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData(
filter, bookmark_model); filter, bookmark_model);
} }
#if defined(OS_ANDROID)
#if BUILDFLAG(ENABLE_FEED_IN_CHROME)
feed::FeedHostService* feed_host_service =
feed::FeedHostServiceFactory::GetForBrowserContext(profile_);
if (feed_host_service) {
feed_host_service->GetSchedulerHost()->OnHistoryCleared();
}
#endif // BUILDFLAG(ENABLE_FEED_IN_CHROME)
#endif // defined(OS_ANDROID)
language::UrlLanguageHistogram* language_histogram = language::UrlLanguageHistogram* language_histogram =
UrlLanguageHistogramFactory::GetForBrowserContext(profile_); UrlLanguageHistogramFactory::GetForBrowserContext(profile_);
if (language_histogram) { if (language_histogram) {
......
...@@ -73,7 +73,6 @@ ...@@ -73,7 +73,6 @@
#include "components/domain_reliability/clear_mode.h" #include "components/domain_reliability/clear_mode.h"
#include "components/domain_reliability/monitor.h" #include "components/domain_reliability/monitor.h"
#include "components/favicon/core/favicon_service.h" #include "components/favicon/core/favicon_service.h"
#include "components/feed/core/pref_names.h"
#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service.h"
#include "components/language/core/browser/url_language_histogram.h" #include "components/language/core/browser/url_language_histogram.h"
#include "components/ntp_snippets/bookmarks/bookmark_last_visit_utils.h" #include "components/ntp_snippets/bookmarks/bookmark_last_visit_utils.h"
...@@ -2903,17 +2902,4 @@ TEST_F(ChromeBrowsingDataRemoverDelegateTest, WipeOriginVerifierData) { ...@@ -2903,17 +2902,4 @@ TEST_F(ChromeBrowsingDataRemoverDelegateTest, WipeOriginVerifierData) {
EXPECT_EQ(before + 1, EXPECT_EQ(before + 1,
customtabs::OriginVerifier::GetClearBrowsingDataCallCountForTesting()); customtabs::OriginVerifier::GetClearBrowsingDataCallCountForTesting());
} }
#if BUILDFLAG(ENABLE_FEED_IN_CHROME)
TEST_F(ChromeBrowsingDataRemoverDelegateTest, FeedClearsLastFetchAttempt) {
PrefService* prefs = GetProfile()->GetPrefs();
prefs->SetTime(feed::prefs::kLastFetchAttemptTime, base::Time::Now());
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY, false);
EXPECT_EQ(base::Time(), prefs->GetTime(feed::prefs::kLastFetchAttemptTime));
}
#endif // BUILDFLAG(ENABLE_FEED_IN_CHROME)
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
...@@ -316,15 +316,20 @@ void FeedSchedulerHost::OnSuggestionsShown() { ...@@ -316,15 +316,20 @@ void FeedSchedulerHost::OnSuggestionsShown() {
user_classifier_.OnEvent(UserClassifier::Event::kSuggestionsViewed); user_classifier_.OnEvent(UserClassifier::Event::kSuggestionsViewed);
} }
void FeedSchedulerHost::OnHistoryCleared() { void FeedSchedulerHost::OnArticlesCleared(bool suppress_refreshes) {
// Due to privacy, we should not fetch for a while (unless the user explicitly // Since there are no stored articles, a refresh will be needed soon.
// asks for new suggestions) to give sync the time to propagate the changes in
// history to the server.
suppress_refreshes_until_ =
clock_->Now() +
base::TimeDelta::FromMinutes(kSuppressRefreshDurationMinutes.Get());
// After that time elapses, we should fetch as soon as possible.
profile_prefs_->ClearPref(prefs::kLastFetchAttemptTime); profile_prefs_->ClearPref(prefs::kLastFetchAttemptTime);
if (suppress_refreshes) {
// Due to privacy, we should not fetch for a while (unless the user
// explicitly asks for new suggestions) to give sync the time to propagate
// the changes in history to the server.
suppress_refreshes_until_ =
clock_->Now() +
base::TimeDelta::FromMinutes(kSuppressRefreshDurationMinutes.Get());
} else if (ShouldRefresh(TriggerType::kNtpShown)) {
refresh_callback_.Run();
}
} }
void FeedSchedulerHost::OnEulaAccepted() { void FeedSchedulerHost::OnEulaAccepted() {
......
...@@ -109,9 +109,10 @@ class FeedSchedulerHost : web_resource::EulaAcceptedNotifier::Observer { ...@@ -109,9 +109,10 @@ class FeedSchedulerHost : web_resource::EulaAcceptedNotifier::Observer {
// users to track the kind of user, and optimize refresh frequency. // users to track the kind of user, and optimize refresh frequency.
void OnSuggestionsShown(); void OnSuggestionsShown();
// When the user clears history, the scheduler will clear out some stored data // Should be called when something happens to clear stored articles. The
// and stop requesting refreshes for a period of time. // scheduler updates its internal state and treats this event as a kNtpShown
void OnHistoryCleared(); // trigger.
void OnArticlesCleared(bool suppress_refreshes);
private: private:
FRIEND_TEST_ALL_PREFIXES(FeedSchedulerHostTest, GetTriggerThreshold); FRIEND_TEST_ALL_PREFIXES(FeedSchedulerHostTest, GetTriggerThreshold);
......
...@@ -786,13 +786,13 @@ TEST_F(FeedSchedulerHostTest, DisableBogusTriggers) { ...@@ -786,13 +786,13 @@ TEST_F(FeedSchedulerHostTest, DisableBogusTriggers) {
/*has_outstanding_request*/ false)); /*has_outstanding_request*/ false));
} }
TEST_F(FeedSchedulerHostTest, OnHistoryCleared) { TEST_F(FeedSchedulerHostTest, OnArticlesCleared) {
// OnForegrounded() does nothing because content is fresher than threshold. // OnForegrounded() does nothing because content is fresher than threshold.
scheduler()->OnReceiveNewContent(test_clock()->Now()); scheduler()->OnReceiveNewContent(test_clock()->Now());
scheduler()->OnForegrounded(); scheduler()->OnForegrounded();
EXPECT_EQ(0, refresh_call_count()); EXPECT_EQ(0, refresh_call_count());
scheduler()->OnHistoryCleared(); scheduler()->OnArticlesCleared(/*suppress_refreshes*/ true);
scheduler()->OnForegrounded(); scheduler()->OnForegrounded();
EXPECT_EQ(0, refresh_call_count()); EXPECT_EQ(0, refresh_call_count());
...@@ -823,7 +823,7 @@ TEST_F(FeedSchedulerHostTest, SuppressRefreshDuration) { ...@@ -823,7 +823,7 @@ TEST_F(FeedSchedulerHostTest, SuppressRefreshDuration) {
kInterestFeedContentSuggestions.name, kInterestFeedContentSuggestions.name,
{{kSuppressRefreshDurationMinutes.name, "100"}}, {{kSuppressRefreshDurationMinutes.name, "100"}},
{kInterestFeedContentSuggestions.name}); {kInterestFeedContentSuggestions.name});
scheduler()->OnHistoryCleared(); scheduler()->OnArticlesCleared(/*suppress_refreshes*/ true);
test_clock()->Advance(TimeDelta::FromMinutes(99)); test_clock()->Advance(TimeDelta::FromMinutes(99));
scheduler()->OnForegrounded(); scheduler()->OnForegrounded();
...@@ -834,6 +834,24 @@ TEST_F(FeedSchedulerHostTest, SuppressRefreshDuration) { ...@@ -834,6 +834,24 @@ TEST_F(FeedSchedulerHostTest, SuppressRefreshDuration) {
EXPECT_EQ(1, refresh_call_count()); EXPECT_EQ(1, refresh_call_count());
} }
TEST_F(FeedSchedulerHostTest, OnArticlesClearedNoSupress) {
EXPECT_EQ(0, refresh_call_count());
scheduler()->OnArticlesCleared(/*suppress_refreshes*/ false);
EXPECT_EQ(1, refresh_call_count());
scheduler()->OnReceiveNewContent(test_clock()->Now());
scheduler()->OnArticlesCleared(/*suppress_refreshes*/ false);
EXPECT_EQ(2, refresh_call_count());
scheduler()->OnReceiveNewContent(test_clock()->Now());
scheduler()->OnArticlesCleared(/*suppress_refreshes*/ true);
EXPECT_EQ(2, refresh_call_count());
scheduler()->OnArticlesCleared(/*suppress_refreshes*/ false);
EXPECT_EQ(2, refresh_call_count());
}
TEST_F(FeedSchedulerHostTest, OustandingRequest) { TEST_F(FeedSchedulerHostTest, OustandingRequest) {
scheduler()->OnForegrounded(); scheduler()->OnForegrounded();
EXPECT_EQ(1, refresh_call_count()); EXPECT_EQ(1, refresh_call_count());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment