Commit f8734fcf authored by Sky Malice's avatar Sky Malice Committed by Commit Bot

[Feed] Flesh out FeedSchedulerHost structure.

Bug: 831648
Change-Id: I1154abdb22295cac7f396dd61c2c4f833b56dccf
Reviewed-on: https://chromium-review.googlesource.com/1093988
Commit-Queue: Sky Malice <skym@chromium.org>
Reviewed-by: default avatarPatrick Noland <pnoland@chromium.org>
Reviewed-by: default avatarFilip Gorski <fgorski@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567305}
parent e84da8c6
......@@ -93,6 +93,16 @@ public class FeedSchedulerBridge implements SchedulerApi {
nativeOnRequestError(mNativeBridge, networkResponseCode);
}
public void onForegrounded() {
assert mNativeBridge != 0;
nativeOnForegrounded(mNativeBridge);
}
public void onFixedTimer() {
assert mNativeBridge != 0;
nativeOnFixedTimer(mNativeBridge);
}
@CalledByNative
private boolean triggerRefresh() {
if (mRequestManager != null) {
......@@ -110,4 +120,6 @@ public class FeedSchedulerBridge implements SchedulerApi {
long nativeFeedSchedulerBridge, long contentCreationDateTimeMs);
private native void nativeOnRequestError(
long nativeFeedSchedulerBridge, int networkResponseCode);
private native void nativeOnForegrounded(long nativeFeedSchedulerBridge);
private native void nativeOnFixedTimer(long nativeFeedSchedulerBridge);
}
......@@ -72,6 +72,16 @@ void FeedSchedulerBridge::OnRequestError(JNIEnv* env,
scheduler_host_->OnRequestError(j_network_response_code);
}
void FeedSchedulerBridge::OnForegrounded(JNIEnv* env,
const JavaRef<jobject>& j_this) {
scheduler_host_->OnForegrounded();
}
void FeedSchedulerBridge::OnFixedTimer(JNIEnv* env,
const JavaRef<jobject>& j_this) {
scheduler_host_->OnFixedTimer();
}
void FeedSchedulerBridge::TriggerRefresh() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_FeedSchedulerBridge_triggerRefresh(env, j_this_);
......
......@@ -40,6 +40,11 @@ class FeedSchedulerBridge {
const base::android::JavaRef<jobject>& j_this,
jint j_network_response_code);
void OnForegrounded(JNIEnv* env,
const base::android::JavaRef<jobject>& j_this);
void OnFixedTimer(JNIEnv* env, const base::android::JavaRef<jobject>& j_this);
// Callable by native code to invoke Java code. Sends a request to the Feed
// library to make the refresh call.
void TriggerRefresh();
......
......@@ -14,6 +14,13 @@
namespace feed {
enum class FeedSchedulerHost::TriggerType {
NTP_SHOWN = 0,
FOREGROUNDED = 1,
FIXED_TIMER = 2,
COUNT
};
FeedSchedulerHost::FeedSchedulerHost(PrefService* pref_service,
base::Clock* clock)
: pref_service_(pref_service), clock_(clock) {}
......@@ -29,7 +36,24 @@ NativeRequestBehavior FeedSchedulerHost::ShouldSessionRequestData(
bool has_content,
base::Time content_creation_date_time,
bool has_outstanding_request) {
return REQUEST_WITH_WAIT;
// TODO(skym): Record requested behavior into histogram.
if (!has_outstanding_request && ShouldRefresh(TriggerType::NTP_SHOWN)) {
if (!has_content) {
return REQUEST_WITH_WAIT;
} else if (IsContentStale(content_creation_date_time)) {
return REQUEST_WITH_TIMEOUT;
} else {
return REQUEST_WITH_CONTENT;
}
} else {
if (!has_content) {
return NO_REQUEST_WITH_WAIT;
} else if (IsContentStale(content_creation_date_time)) {
return NO_REQUEST_WITH_TIMEOUT;
} else {
return NO_REQUEST_WITH_CONTENT;
}
}
}
void FeedSchedulerHost::OnReceiveNewContent(
......@@ -42,6 +66,20 @@ void FeedSchedulerHost::OnRequestError(int network_response_code) {
pref_service_->SetTime(prefs::kLastFetchAttemptTime, clock_->Now());
}
void FeedSchedulerHost::OnForegrounded() {
DCHECK(trigger_refresh_);
if (ShouldRefresh(TriggerType::FOREGROUNDED)) {
trigger_refresh_.Run();
}
}
void FeedSchedulerHost::OnFixedTimer() {
DCHECK(trigger_refresh_);
if (ShouldRefresh(TriggerType::FIXED_TIMER)) {
trigger_refresh_.Run();
}
}
void FeedSchedulerHost::RegisterTriggerRefreshCallback(
base::RepeatingClosure callback) {
// There should only ever be one scheduler host and bridge created. This may
......@@ -51,6 +89,22 @@ void FeedSchedulerHost::RegisterTriggerRefreshCallback(
trigger_refresh_ = std::move(callback);
}
bool FeedSchedulerHost::ShouldRefresh(TriggerType trigger) {
// TODO(skym): Check various criteria are met, record metrics.
return true;
}
bool FeedSchedulerHost::IsContentStale(base::Time content_creation_date_time) {
// TODO(skym): Compare |content_creation_date_time| to foregrounded trigger's
// threshold.
return false;
}
base::TimeDelta FeedSchedulerHost::GetTriggerThreshold(TriggerType trigger) {
// TODO(skym): Select Finch param based on trigger and user classification.
return base::TimeDelta();
}
void FeedSchedulerHost::ScheduleFixedTimerWakeUp() {
// TODO(skym): Implementation, call out to injected scheduling dependency.
}
......
......@@ -56,12 +56,37 @@ class FeedSchedulerHost {
// Called when an unsuccessful refresh completes.
void OnRequestError(int network_response_code);
// Called when browser is opened, launched, or foregrounded.
void OnForegrounded();
// Called when the scheduled fixed timer wakes up.
void OnFixedTimer();
// Registers a callback to trigger a refresh.
void RegisterTriggerRefreshCallback(base::RepeatingClosure callback);
private:
// The TriggerType enum specifies values for the events that can trigger
// refreshing articles.
enum class TriggerType;
// Determines whether a refresh should be performed for the given |trigger|.
// If this method is called and returns true we presume the refresh will
// happen, therefore we report metrics respectively.
bool ShouldRefresh(TriggerType trigger);
// Decides if content whose age is the difference between now and
// |content_creation_date_time| is old enough to be considered stale.
bool IsContentStale(base::Time content_creation_date_time);
// Schedules a task to wakeup and try to refresh. Overrides previously
// scheduled tasks.
void ScheduleFixedTimerWakeUp();
// Returns the time threshold for content or previous refresh attempt to be
// considered old enough for a given trigger to warrant a refresh.
base::TimeDelta GetTriggerThreshold(TriggerType trigger);
// Callback to request that an async refresh be started.
base::RepeatingClosure trigger_refresh_;
......
......@@ -4,6 +4,7 @@
#include "components/feed/core/feed_scheduler_host.h"
#include "base/bind.h"
#include "base/test/simple_test_clock.h"
#include "components/feed/core/pref_names.h"
#include "components/prefs/testing_pref_service.h"
......@@ -20,10 +21,12 @@ using base::Time;
class FeedSchedulerHostTest : public ::testing::Test {
public:
void TriggerRefresh() { trigger_refresh_count_++; }
protected:
FeedSchedulerHostTest() : scheduler_(&pref_service_, &test_clock_) {
base::Time now;
CHECK(base::Time::FromUTCString(kNowString, &now));
Time now;
CHECK(Time::FromUTCString(kNowString, &now));
test_clock_.SetNow(now);
FeedSchedulerHost::RegisterProfilePrefs(pref_service_.registry());
......@@ -32,27 +35,64 @@ class FeedSchedulerHostTest : public ::testing::Test {
PrefService* pref_service() { return &pref_service_; }
base::SimpleTestClock* test_clock() { return &test_clock_; }
FeedSchedulerHost* scheduler() { return &scheduler_; }
int trigger_refresh_count() { return trigger_refresh_count_; }
private:
TestingPrefServiceSimple pref_service_;
base::SimpleTestClock test_clock_;
FeedSchedulerHost scheduler_;
int trigger_refresh_count_ = 0;
};
TEST_F(FeedSchedulerHostTest, OnReceiveNewContent) {
TEST_F(FeedSchedulerHostTest, ShouldSessionRequestDataSimple) {
EXPECT_EQ(REQUEST_WITH_WAIT,
scheduler()->ShouldSessionRequestData(
/*has_content*/ false, /*content_creation_date_time*/ Time(),
/*has_outstanding_request*/ false));
// TODO(skym): REQUEST_WITH_TIMEOUT.
EXPECT_EQ(REQUEST_WITH_CONTENT,
scheduler()->ShouldSessionRequestData(
/*has_content*/ true, /*content_creation_date_time*/ Time(),
/*has_outstanding_request*/ false));
EXPECT_EQ(NO_REQUEST_WITH_WAIT,
scheduler()->ShouldSessionRequestData(
/*has_content*/ false, /*content_creation_date_time*/ Time(),
/*has_outstanding_request*/ true));
// TODO(skym): NO_REQUEST_WITH_TIMEOUT.
EXPECT_EQ(NO_REQUEST_WITH_CONTENT,
scheduler()->ShouldSessionRequestData(
/*has_content*/ true, /*content_creation_date_time*/ Time(),
/*has_outstanding_request*/ true));
}
TEST_F(FeedSchedulerHostTest, OnReceiveNewContentVerifyPref) {
EXPECT_EQ(Time(), pref_service()->GetTime(prefs::kLastFetchAttemptTime));
scheduler()->OnReceiveNewContent(Time());
EXPECT_EQ(test_clock()->Now(),
pref_service()->GetTime(prefs::kLastFetchAttemptTime));
}
TEST_F(FeedSchedulerHostTest, OnRequestError) {
TEST_F(FeedSchedulerHostTest, OnRequestErrorVerifyPref) {
EXPECT_EQ(Time(), pref_service()->GetTime(prefs::kLastFetchAttemptTime));
scheduler()->OnRequestError(0);
EXPECT_EQ(test_clock()->Now(),
pref_service()->GetTime(prefs::kLastFetchAttemptTime));
}
TEST_F(FeedSchedulerHostTest, OnForegroundedTriggersRefresh) {
scheduler()->RegisterTriggerRefreshCallback(base::BindRepeating(
&FeedSchedulerHostTest::TriggerRefresh, base::Unretained(this)));
scheduler()->OnForegrounded();
EXPECT_EQ(1, trigger_refresh_count());
}
TEST_F(FeedSchedulerHostTest, OnFixedTimerTriggersRefresh) {
scheduler()->RegisterTriggerRefreshCallback(base::BindRepeating(
&FeedSchedulerHostTest::TriggerRefresh, base::Unretained(this)));
scheduler()->OnFixedTimer();
EXPECT_EQ(1, trigger_refresh_count());
}
} // namespace
} // namespace feed
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