Commit 18a64f8e authored by Sky Malice's avatar Sky Malice Committed by Commit Bot

[Feed] Implement SchedulerApi Java API and host skeleton.

No actual logic is added, simply the plumbing to call between Java and
native code. In subsequent patches logic will be added to the
FeedSchedulerHost.

Bug: 831642, 831644
Change-Id: Icec552cbf4d482739d7211a9cc81bb669e0df413
Reviewed-on: https://chromium-review.googlesource.com/1068199
Commit-Queue: Sky Malice <skym@chromium.org>
Reviewed-by: default avataragrieve <agrieve@chromium.org>
Reviewed-by: default avatarFilip Gorski <fgorski@chromium.org>
Cr-Commit-Position: refs/heads/master@{#563071}
parent db0edeaa
......@@ -337,6 +337,7 @@ android_library("chrome_java") {
# Include sources from feed_java_sources.gni.
java_files += feed_java_sources
srcjar_deps += feed_srcjar_deps
if (enable_vr) {
java_files += chrome_vr_java_sources
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.feed;
import com.google.android.libraries.feed.api.requestmanager.RequestManager;
import com.google.android.libraries.feed.host.scheduler.SchedulerApi;
import com.google.search.now.wire.feed.FeedQueryProto.FeedQuery.RequestReason;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.components.feed.NativeRequestBehavior;
/**
* Provides access to native implementations of SchedulerApi.
*/
@JNINamespace("feed")
public class FeedSchedulerBridge implements SchedulerApi {
private long mNativeBridge;
private RequestManager mRequestManager;
/**
* Creates a FeedSchedulerBridge for accessing native scheduling logic.
*
* @param profile Profile of the user we are rendering the Feed for.
*/
public FeedSchedulerBridge(Profile profile) {
mNativeBridge = nativeInit(profile);
}
/*
* Cleans up native half of this bridge.
*/
public void destroy() {
assert mNativeBridge != 0;
nativeDestroy(mNativeBridge);
mNativeBridge = 0;
}
/*
* Sets our copy of the RequestManager. Should be done as early as possible,
* as the scheduler will be unable to trigger refreshes until after it has a
* reference to a RequestManager. When this is called, it is assumed that
* the RequestManager is initialized and can be used.
*
* @param requestManager The interface that allows us make refresh requests.
*/
public void setRequestManager(RequestManager requestManager) {
mRequestManager = requestManager;
}
@Override
public int shouldSessionRequestData(SessionManagerState sessionManagerState) {
assert mNativeBridge != 0;
@NativeRequestBehavior
int nativeBehavior = nativeShouldSessionRequestData(mNativeBridge,
sessionManagerState.hasContent, sessionManagerState.contentCreationDateTimeMs,
sessionManagerState.hasOutstandingRequest);
// If this breaks, it is because SchedulerApi.RequestBehavior and the
// NativeRequestBehavior defined in feed_scheduler_host.h have diverged.
// If this happens during a feed DEPS roll, it likely means that the
// native side needs to be updated. Note that this will not catch new
// values and should handle value changes. Only removals/renames will
// cause compile failures.
switch (nativeBehavior) {
case NativeRequestBehavior.REQUEST_WITH_WAIT:
return SchedulerApi.RequestBehavior.REQUEST_WITH_WAIT;
case NativeRequestBehavior.REQUEST_WITH_CONTENT:
return SchedulerApi.RequestBehavior.REQUEST_WITH_CONTENT;
case NativeRequestBehavior.REQUEST_WITH_TIMEOUT:
return SchedulerApi.RequestBehavior.REQUEST_WITH_TIMEOUT;
case NativeRequestBehavior.NO_REQUEST_WITH_WAIT:
return SchedulerApi.RequestBehavior.NO_REQUEST_WITH_WAIT;
case NativeRequestBehavior.NO_REQUEST_WITH_CONTENT:
return SchedulerApi.RequestBehavior.NO_REQUEST_WITH_CONTENT;
case NativeRequestBehavior.NO_REQUEST_WITH_TIMEOUT:
return SchedulerApi.RequestBehavior.NO_REQUEST_WITH_TIMEOUT;
}
return SchedulerApi.RequestBehavior.UNKNOWN;
}
@Override
public void onReceiveNewContent(long contentCreationDateTimeMs) {
assert mNativeBridge != 0;
nativeOnReceiveNewContent(mNativeBridge);
}
@Override
public void onRequestError(int networkResponseCode) {
assert mNativeBridge != 0;
nativeOnRequestError(mNativeBridge, networkResponseCode);
}
@CalledByNative
private boolean triggerRefresh() {
if (mRequestManager != null) {
mRequestManager.triggerRefresh(RequestReason.SCHEDULED_REFRESH, ignored -> {});
return true;
}
return false;
}
private native long nativeInit(Profile profile);
private native void nativeDestroy(long nativeFeedSchedulerBridge);
private native @NativeRequestBehavior int nativeShouldSessionRequestData(
long nativeFeedSchedulerBridge, boolean hasContent, long contentCreationDateTimeMs,
boolean hasOutstandingRequest);
private native void nativeOnReceiveNewContent(long nativeFeedSchedulerBridge);
private native void nativeOnRequestError(
long nativeFeedSchedulerBridge, int networkResponseCode);
}
......@@ -13,9 +13,12 @@ if (enable_feed_in_chrome) {
"//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedImageLoaderBridge.java",
"//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNetworkBridge.java",
"//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java",
"//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java",
"//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/action/FeedActionHandler.java",
]
feed_srcjar_deps = [ "//components/feed/core:feed_core_java_enums_srcjar" ]
feed_conformance_test_sources = [ "//chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNetworkBridgeConformanceTest.java" ]
feed_conformance_test_deps = [
......@@ -24,6 +27,6 @@ if (enable_feed_in_chrome) {
]
} else {
feed_deps = []
feed_java_sources = [ "//chrome/android/feed/dummy/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java" ]
feed_srcjar_deps = []
}
......@@ -4240,6 +4240,8 @@ jumbo_split_static_library("browser") {
"android/feed/feed_image_loader_bridge.h",
"android/feed/feed_network_bridge.cc",
"android/feed/feed_network_bridge.h",
"android/feed/feed_scheduler_bridge.cc",
"android/feed/feed_scheduler_bridge.h",
]
deps += [ "//components/feed/core:feed_core" ]
}
......@@ -4496,6 +4498,7 @@ if (is_android) {
sources += [
"../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedImageLoaderBridge.java",
"../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNetworkBridge.java",
"../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java",
]
}
......
......@@ -14,6 +14,9 @@
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/common/channel_info.h"
#include "components/feed/core/feed_host_service.h"
#include "components/feed/core/feed_image_manager.h"
#include "components/feed/core/feed_networking_host.h"
#include "components/feed/core/feed_scheduler_host.h"
#include "components/image_fetcher/core/image_fetcher_impl.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/version_info/version_info.h"
......@@ -79,8 +82,11 @@ KeyedService* FeedHostServiceFactory::BuildServiceInstanceFor(
auto image_manager = std::make_unique<FeedImageManager>(
std::move(image_fetcher), std::move(image_database));
auto scheduler_host = std::make_unique<FeedSchedulerHost>();
return new FeedHostService(std::move(image_manager),
std::move(networking_host));
std::move(networking_host),
std::move(scheduler_host));
}
content::BrowserContext* FeedHostServiceFactory::GetBrowserContextToUse(
......
......@@ -4,8 +4,6 @@
#include "chrome/browser/android/feed/feed_network_bridge.h"
#include <jni.h>
#include <utility>
#include <vector>
......
......@@ -5,7 +5,10 @@
#ifndef CHROME_BROWSER_ANDROID_FEED_FEED_NETWORK_BRIDGE_H_
#define CHROME_BROWSER_ANDROID_FEED_FEED_NETWORK_BRIDGE_H_
#include <jni.h>
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
namespace feed {
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/feed/feed_scheduler_bridge.h"
#include "base/android/jni_android.h"
#include "base/bind.h"
#include "base/time/time.h"
#include "chrome/browser/android/feed/feed_host_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_android.h"
#include "components/feed/core/feed_host_service.h"
#include "components/feed/core/feed_scheduler_host.h"
#include "jni/FeedSchedulerBridge_jni.h"
using base::android::JavaRef;
using base::android::JavaParamRef;
using base::android::ScopedJavaGlobalRef;
namespace feed {
static jlong JNI_FeedSchedulerBridge_Init(
JNIEnv* env,
const JavaParamRef<jobject>& j_this,
const JavaParamRef<jobject>& j_profile) {
Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
FeedHostService* host_service =
FeedHostServiceFactory::GetForBrowserContext(profile);
return reinterpret_cast<intptr_t>(
new FeedSchedulerBridge(j_this, host_service->GetSchedulerHost()));
}
FeedSchedulerBridge::FeedSchedulerBridge(const JavaRef<jobject>& j_this,
FeedSchedulerHost* scheduler_host)
: j_this_(ScopedJavaGlobalRef<jobject>(j_this)),
scheduler_host_(scheduler_host),
weak_factory_(this) {
DCHECK(scheduler_host_);
scheduler_host_->RegisterTriggerRefreshCallback(base::BindRepeating(
&FeedSchedulerBridge::TriggerRefresh, weak_factory_.GetWeakPtr()));
}
FeedSchedulerBridge::~FeedSchedulerBridge() {}
void FeedSchedulerBridge::Destroy(JNIEnv* env, const JavaRef<jobject>& j_this) {
delete this;
}
jint FeedSchedulerBridge::ShouldSessionRequestData(
JNIEnv* env,
const JavaRef<jobject>& j_this,
const jboolean j_has_content,
const jlong j_content_creation_date_time_ms,
const jboolean j_has_outstanding_request) {
return static_cast<int>(scheduler_host_->ShouldSessionRequestData(
j_has_content, base::Time::FromJavaTime(j_content_creation_date_time_ms),
j_has_outstanding_request));
}
void FeedSchedulerBridge::OnReceiveNewContent(JNIEnv* env,
const JavaRef<jobject>& j_this) {
scheduler_host_->OnReceiveNewContent();
}
void FeedSchedulerBridge::OnRequestError(JNIEnv* env,
const JavaRef<jobject>& j_this,
const jint j_network_response_code) {
scheduler_host_->OnRequestError(j_network_response_code);
}
void FeedSchedulerBridge::TriggerRefresh() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_FeedSchedulerBridge_triggerRefresh(env, j_this_);
}
} // namespace feed
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ANDROID_FEED_FEED_SCHEDULER_BRIDGE_H_
#define CHROME_BROWSER_ANDROID_FEED_FEED_SCHEDULER_BRIDGE_H_
#include <jni.h>
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
namespace feed {
class FeedSchedulerHost;
// Native counterpart of FeedSchedulerBridge.java. Holds non-owning pointers to
// native implementation, to which operations are delegated. Also capable of
// calling back into Java half.
class FeedSchedulerBridge {
public:
FeedSchedulerBridge(const base::android::JavaRef<jobject>& j_this,
FeedSchedulerHost* scheduler_host);
~FeedSchedulerBridge();
void Destroy(JNIEnv* env, const base::android::JavaRef<jobject>& j_this);
jint ShouldSessionRequestData(JNIEnv* env,
const base::android::JavaRef<jobject>& j_this,
const jboolean j_has_content,
const jlong j_content_creation_date_time_ms,
const jboolean j_has_outstanding_request);
void OnReceiveNewContent(JNIEnv* env,
const base::android::JavaRef<jobject>& j_this);
void OnRequestError(JNIEnv* env,
const base::android::JavaRef<jobject>& j_this,
jint j_network_response_code);
// Callable by native code to invoke Java code. Sends a request to the Feed
// library to make the refresh call.
void TriggerRefresh();
private:
// Reference to the Java half of this bridge. Always valid.
base::android::ScopedJavaGlobalRef<jobject> j_this_;
// Object to which all Java to native calls are delegated.
FeedSchedulerHost* scheduler_host_;
base::WeakPtrFactory<FeedSchedulerBridge> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(FeedSchedulerBridge);
};
} // namespace feed
#endif // CHROME_BROWSER_ANDROID_FEED_FEED_SCHEDULER_BRIDGE_H_
......@@ -2,6 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
if (is_android) {
import("//build/config/android/rules.gni")
}
source_set("feed_core") {
sources = [
"feed_host_service.cc",
......@@ -12,6 +16,8 @@ source_set("feed_core") {
"feed_image_manager.h",
"feed_networking_host.cc",
"feed_networking_host.h",
"feed_scheduler_host.cc",
"feed_scheduler_host.h",
"time_serialization.cc",
"time_serialization.h",
]
......@@ -38,6 +44,14 @@ source_set("feed_core") {
]
}
if (is_android) {
java_cpp_enum("feed_core_java_enums_srcjar") {
sources = [
"feed_scheduler_host.h",
]
}
}
source_set("core_unit_tests") {
testonly = true
sources = [
......
......@@ -10,9 +10,11 @@ namespace feed {
FeedHostService::FeedHostService(
std::unique_ptr<FeedImageManager> image_manager,
std::unique_ptr<FeedNetworkingHost> networking_host)
std::unique_ptr<FeedNetworkingHost> networking_host,
std::unique_ptr<FeedSchedulerHost> scheduler_host)
: image_manager_(std::move(image_manager)),
networking_host_(std::move(networking_host)) {}
networking_host_(std::move(networking_host)),
scheduler_host_(std::move(scheduler_host)) {}
FeedHostService::~FeedHostService() = default;
......@@ -24,4 +26,8 @@ FeedNetworkingHost* FeedHostService::GetNetworkingHost() {
return networking_host_.get();
}
FeedSchedulerHost* FeedHostService::GetSchedulerHost() {
return scheduler_host_.get();
}
} // namespace feed
......@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "components/feed/core/feed_image_manager.h"
#include "components/feed/core/feed_networking_host.h"
#include "components/feed/core/feed_scheduler_host.h"
#include "components/keyed_service/core/keyed_service.h"
namespace feed {
......@@ -22,15 +23,18 @@ namespace feed {
class FeedHostService : public KeyedService {
public:
FeedHostService(std::unique_ptr<FeedImageManager> image_manager,
std::unique_ptr<FeedNetworkingHost> networking_host);
std::unique_ptr<FeedNetworkingHost> networking_host,
std::unique_ptr<FeedSchedulerHost> scheduler_host);
~FeedHostService() override;
FeedImageManager* GetImageManager();
FeedNetworkingHost* GetNetworkingHost();
FeedSchedulerHost* GetSchedulerHost();
private:
std::unique_ptr<FeedImageManager> image_manager_;
std::unique_ptr<FeedNetworkingHost> networking_host_;
std::unique_ptr<FeedSchedulerHost> scheduler_host_;
DISALLOW_COPY_AND_ASSIGN(FeedHostService);
};
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/feed/core/feed_scheduler_host.h"
#include <utility>
#include "base/time/time.h"
namespace feed {
FeedSchedulerHost::FeedSchedulerHost() {}
FeedSchedulerHost::~FeedSchedulerHost() {}
NativeRequestBehavior FeedSchedulerHost::ShouldSessionRequestData(
bool has_content,
base::Time content_creation_date_time,
bool has_outstanding_request) {
return REQUEST_WITH_CONTENT;
}
void FeedSchedulerHost::OnReceiveNewContent() {}
void FeedSchedulerHost::OnRequestError(int network_response_code) {}
void FeedSchedulerHost::RegisterTriggerRefreshCallback(
base::RepeatingClosure callback) {
// There should only ever be one scheduler host and bridge created. This may
// stop being true eventually.
DCHECK(trigger_refresh_.is_null());
trigger_refresh_ = std::move(callback);
}
} // namespace feed
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_FEED_CORE_FEED_SCHEDULER_HOST_H_
#define COMPONENTS_FEED_CORE_FEED_SCHEDULER_HOST_H_
#include "base/callback.h"
#include "base/macros.h"
namespace base {
class Time;
} // namespace base
namespace feed {
// The enum values and names are kept in sync with SchedulerApi.RequestBehavior
// through Java unit tests, new values however must be manually added. If any
// new values are added, also update FeedSchedulerBridgeTest.java.
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.feed
enum NativeRequestBehavior {
UNKNOWN = 0,
REQUEST_WITH_WAIT,
REQUEST_WITH_CONTENT,
REQUEST_WITH_TIMEOUT,
NO_REQUEST_WITH_WAIT,
NO_REQUEST_WITH_CONTENT,
NO_REQUEST_WITH_TIMEOUT
};
// Implementation of the Feed Scheduler Host API. The scheduler host decides
// what content is allowed to be shown, based on its age, and when to fetch new
// content.
class FeedSchedulerHost {
public:
FeedSchedulerHost();
~FeedSchedulerHost();
// Called when the NTP is opened to decide how to handle displaying and
// refreshing content.
NativeRequestBehavior ShouldSessionRequestData(
bool has_content,
base::Time content_creation_date_time,
bool has_outstanding_request);
// Called when a successful refresh completes.
void OnReceiveNewContent();
// Called when an unsuccessful refresh completes.
void OnRequestError(int network_response_code);
// Registers a callback to trigger a refresh.
void RegisterTriggerRefreshCallback(base::RepeatingClosure callback);
private:
base::RepeatingClosure trigger_refresh_;
DISALLOW_COPY_AND_ASSIGN(FeedSchedulerHost);
};
} // namespace feed
#endif // COMPONENTS_FEED_CORE_FEED_SCHEDULER_HOST_H_
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