Commit b8723b73 authored by dominickn's avatar dominickn Committed by Commit bot

Expose the Site Engagement Service to Java.

This CL adds a Java-side interface to the Site Engagement Service, as
well as a basic integration test for the interface. This allows Java
code (particularly tests) to programatically adjust and retrieve the
score.

BUG=671100

Review-Url: https://codereview.chromium.org/2553013002
Cr-Commit-Position: refs/heads/master@{#437825}
parent 2e3d43f9
// Copyright 2016 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.engagement;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.chrome.browser.profiles.Profile;
/**
* Provides access to the Site Engagement Service for a profile.
*
* Site engagement measures the level of engagement that a user has with an origin. This class
* allows Java to retrieve and modify engagement scores for URLs.
*/
public class SiteEngagementService {
/** Pointer to the native side SiteEngagementServiceAndroid shim. */
private long mNativePointer;
/**
* Returns a SiteEngagementService for the provided profile.
* Must be called on the UI thread.
*/
public static SiteEngagementService getForProfile(Profile profile) {
assert ThreadUtils.runningOnUiThread();
return nativeSiteEngagementServiceForProfile(profile);
}
/**
* Returns the engagement score for the provided URL.
* Must be called on the UI thread.
*/
public double getScore(String url) {
assert ThreadUtils.runningOnUiThread();
if (mNativePointer == 0) return 0.0;
return nativeGetScore(mNativePointer, url);
}
/**
* Sets the provided URL to have the provided engagement score.
* Must be called on the UI thread.
*/
public void resetScoreForUrl(String url, double score) {
assert ThreadUtils.runningOnUiThread();
if (mNativePointer == 0) return;
nativeResetScoreForURL(mNativePointer, url, score);
}
@CalledByNative
private static SiteEngagementService create(long nativePointer) {
return new SiteEngagementService(nativePointer);
}
/** This object may only be created via the static getForProfile method. */
private SiteEngagementService(long nativePointer) {
mNativePointer = nativePointer;
}
@CalledByNative
private void onNativeDestroyed() {
mNativePointer = 0;
}
private static native SiteEngagementService nativeSiteEngagementServiceForProfile(
Profile profile);
private native double nativeGetScore(long nativeSiteEngagementServiceAndroid, String url);
private native void nativeResetScoreForURL(
long nativeSiteEngagementServiceAndroid, String url, double score);
}
...@@ -341,6 +341,7 @@ chrome_java_sources = [ ...@@ -341,6 +341,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java", "java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java",
"java/src/org/chromium/chrome/browser/download/ui/ThumbnailProvider.java", "java/src/org/chromium/chrome/browser/download/ui/ThumbnailProvider.java",
"java/src/org/chromium/chrome/browser/download/ui/ThumbnailProviderImpl.java", "java/src/org/chromium/chrome/browser/download/ui/ThumbnailProviderImpl.java",
"java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java",
"java/src/org/chromium/chrome/browser/externalauth/ExternalAuthUtils.java", "java/src/org/chromium/chrome/browser/externalauth/ExternalAuthUtils.java",
"java/src/org/chromium/chrome/browser/externalauth/UserRecoverableErrorHandler.java", "java/src/org/chromium/chrome/browser/externalauth/UserRecoverableErrorHandler.java",
"java/src/org/chromium/chrome/browser/externalauth/VerifiedHandler.java", "java/src/org/chromium/chrome/browser/externalauth/VerifiedHandler.java",
...@@ -1240,6 +1241,7 @@ chrome_test_java_sources = [ ...@@ -1240,6 +1241,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java", "javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java",
"javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java", "javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java",
"javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java", "javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java",
"javatests/src/org/chromium/chrome/browser/engagement/SiteEngagementServiceTest.java",
"javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java", "javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java",
"javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java", "javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java",
"javatests/src/org/chromium/chrome/browser/externalnav/IntentWithGesturesHandlerTest.java", "javatests/src/org/chromium/chrome/browser/externalnav/IntentWithGesturesHandlerTest.java",
......
// Copyright 2016 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.engagement;
import android.test.UiThreadTest;
import android.test.suitebuilder.annotation.SmallTest;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.test.ChromeActivityTestCaseBase;
/**
* Test for the Site Engagement Service Java binding.
*/
public class SiteEngagementServiceTest extends ChromeActivityTestCaseBase<ChromeActivity> {
public SiteEngagementServiceTest() {
super(ChromeActivity.class);
}
/**
* Verify that setting the engagement score for a URL and reading it back it works.
*/
@SmallTest
@UiThreadTest
@Feature({"Engagement"})
public void testSettingAndRetrievingScore() {
final String url = "https://www.google.com";
SiteEngagementService service = SiteEngagementService.getForProfile(
getActivity().getActivityTab().getProfile());
assertEquals(0.0, service.getScore(url));
service.resetScoreForUrl(url, 5.0);
assertEquals(5.0, service.getScore(url));
service.resetScoreForUrl(url, 2.0);
assertEquals(2.0, service.getScore(url));
}
/**
* Verify that repeatedly fetching and throwing away the SiteEngagementService works.
*/
@SmallTest
@UiThreadTest
@Feature({"Engagement"})
public void testRepeatedlyGettingService() {
final String url = "https://www.google.com";
Profile profile = getActivity().getActivityTab().getProfile();
assertEquals(0.0, SiteEngagementService.getForProfile(profile).getScore(url));
SiteEngagementService.getForProfile(profile).resetScoreForUrl(url, 5.0);
assertEquals(5.0, SiteEngagementService.getForProfile(profile).getScore(url));
SiteEngagementService.getForProfile(profile).resetScoreForUrl(url, 2.0);
assertEquals(2.0, SiteEngagementService.getForProfile(profile).getScore(url));
}
@Override
public void startMainActivity() throws InterruptedException {
startMainActivityOnBlankPage();
}
}
...@@ -3255,6 +3255,8 @@ split_static_library("browser") { ...@@ -3255,6 +3255,8 @@ split_static_library("browser") {
"dom_distiller/tab_utils_android.h", "dom_distiller/tab_utils_android.h",
"download/download_request_infobar_delegate_android.cc", "download/download_request_infobar_delegate_android.cc",
"download/download_request_infobar_delegate_android.h", "download/download_request_infobar_delegate_android.h",
"engagement/site_engagement_service_android.cc",
"engagement/site_engagement_service_android.h",
"geolocation/geolocation_infobar_delegate_android.cc", "geolocation/geolocation_infobar_delegate_android.cc",
"geolocation/geolocation_infobar_delegate_android.h", "geolocation/geolocation_infobar_delegate_android.h",
"history/android/android_history_provider_service.cc", "history/android/android_history_provider_service.cc",
...@@ -3907,6 +3909,7 @@ if (android_java_ui) { ...@@ -3907,6 +3909,7 @@ if (android_java_ui) {
"../android/java/src/org/chromium/chrome/browser/download/DownloadItem.java", "../android/java/src/org/chromium/chrome/browser/download/DownloadItem.java",
"../android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java", "../android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java",
"../android/java/src/org/chromium/chrome/browser/download/ui/ThumbnailProviderImpl.java", "../android/java/src/org/chromium/chrome/browser/download/ui/ThumbnailProviderImpl.java",
"../android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java",
"../android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java", "../android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java",
"../android/java/src/org/chromium/chrome/browser/favicon/LargeIconBridge.java", "../android/java/src/org/chromium/chrome/browser/favicon/LargeIconBridge.java",
"../android/java/src/org/chromium/chrome/browser/feedback/ConnectivityChecker.java", "../android/java/src/org/chromium/chrome/browser/feedback/ConnectivityChecker.java",
......
...@@ -109,6 +109,7 @@ ...@@ -109,6 +109,7 @@
#include "chrome/browser/autofill/android/personal_data_manager_android.h" #include "chrome/browser/autofill/android/personal_data_manager_android.h"
#include "chrome/browser/dom_distiller/dom_distiller_service_factory_android.h" #include "chrome/browser/dom_distiller/dom_distiller_service_factory_android.h"
#include "chrome/browser/dom_distiller/tab_utils_android.h" #include "chrome/browser/dom_distiller/tab_utils_android.h"
#include "chrome/browser/engagement/site_engagement_service_android.h"
#include "chrome/browser/history/android/sqlite_cursor.h" #include "chrome/browser/history/android/sqlite_cursor.h"
#include "chrome/browser/invalidation/invalidation_service_factory_android.h" #include "chrome/browser/invalidation/invalidation_service_factory_android.h"
#include "chrome/browser/media/android/cdm/media_drm_credential_manager.h" #include "chrome/browser/media/android/cdm/media_drm_credential_manager.h"
...@@ -373,6 +374,7 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = { ...@@ -373,6 +374,7 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = {
{"SigninInvestigator", SigninInvestigatorAndroid::Register}, {"SigninInvestigator", SigninInvestigatorAndroid::Register},
{"SigninManager", SigninManagerAndroid::Register}, {"SigninManager", SigninManagerAndroid::Register},
{"SingleTabModel", RegisterSingleTabModel}, {"SingleTabModel", RegisterSingleTabModel},
{"SiteEngagementService", SiteEngagementServiceAndroid::Register},
#if BUILDFLAG(ENABLE_SPELLCHECK) #if BUILDFLAG(ENABLE_SPELLCHECK)
{"SpellCheckerSessionBridge", spellcheck::android::RegisterSpellcheckJni}, {"SpellCheckerSessionBridge", spellcheck::android::RegisterSpellcheckJni},
#endif #endif
......
...@@ -36,6 +36,10 @@ ...@@ -36,6 +36,10 @@
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "url/gurl.h" #include "url/gurl.h"
#if defined(OS_ANDROID)
#include "chrome/browser/engagement/site_engagement_service_android.h"
#endif
namespace { namespace {
const int FOUR_WEEKS_IN_DAYS = 28; const int FOUR_WEEKS_IN_DAYS = 28;
...@@ -238,6 +242,17 @@ double SiteEngagementService::GetTotalEngagementPoints() const { ...@@ -238,6 +242,17 @@ double SiteEngagementService::GetTotalEngagementPoints() const {
return total_score; return total_score;
} }
#if defined(OS_ANDROID)
SiteEngagementServiceAndroid* SiteEngagementService::GetAndroidService() const {
return android_service_.get();
}
void SiteEngagementService::SetAndroidService(
std::unique_ptr<SiteEngagementServiceAndroid> android_service) {
android_service_ = std::move(android_service);
}
#endif
SiteEngagementService::SiteEngagementService(Profile* profile, SiteEngagementService::SiteEngagementService(Profile* profile,
std::unique_ptr<base::Clock> clock) std::unique_ptr<base::Clock> clock)
: profile_(profile), clock_(std::move(clock)), weak_factory_(this) { : profile_(profile), clock_(std::move(clock)), weak_factory_(this) {
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/engagement/site_engagement_metrics.h" #include "chrome/browser/engagement/site_engagement_metrics.h"
#include "chrome/browser/engagement/site_engagement_observer.h" #include "chrome/browser/engagement/site_engagement_observer.h"
#include "components/history/core/browser/history_service_observer.h" #include "components/history/core/browser/history_service_observer.h"
...@@ -37,6 +38,10 @@ class HostContentSettingsMap; ...@@ -37,6 +38,10 @@ class HostContentSettingsMap;
class Profile; class Profile;
class SiteEngagementScore; class SiteEngagementScore;
#if defined(OS_ANDROID)
class SiteEngagementServiceAndroid;
#endif
class SiteEngagementScoreProvider { class SiteEngagementScoreProvider {
public: public:
// Returns a non-negative integer representing the engagement score of the // Returns a non-negative integer representing the engagement score of the
...@@ -134,6 +139,7 @@ class SiteEngagementService : public KeyedService, ...@@ -134,6 +139,7 @@ class SiteEngagementService : public KeyedService,
private: private:
friend class SiteEngagementObserver; friend class SiteEngagementObserver;
friend class SiteEngagementServiceAndroid;
FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, CheckHistograms); FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, CheckHistograms);
FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, CleanupEngagementScores); FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, CleanupEngagementScores);
FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest,
...@@ -160,6 +166,13 @@ class SiteEngagementService : public KeyedService, ...@@ -160,6 +166,13 @@ class SiteEngagementService : public KeyedService,
FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, GetScoreFromSettings); FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, GetScoreFromSettings);
FRIEND_TEST_ALL_PREFIXES(AppBannerSettingsHelperTest, SiteEngagementTrigger); FRIEND_TEST_ALL_PREFIXES(AppBannerSettingsHelperTest, SiteEngagementTrigger);
#if defined(OS_ANDROID)
// Shim class to expose the service to Java.
SiteEngagementServiceAndroid* GetAndroidService() const;
void SetAndroidService(
std::unique_ptr<SiteEngagementServiceAndroid> android_service);
#endif
// Only used in tests. // Only used in tests.
SiteEngagementService(Profile* profile, std::unique_ptr<base::Clock> clock); SiteEngagementService(Profile* profile, std::unique_ptr<base::Clock> clock);
...@@ -253,6 +266,10 @@ class SiteEngagementService : public KeyedService, ...@@ -253,6 +266,10 @@ class SiteEngagementService : public KeyedService,
// The clock used to vend times. // The clock used to vend times.
std::unique_ptr<base::Clock> clock_; std::unique_ptr<base::Clock> clock_;
#if defined(OS_ANDROID)
std::unique_ptr<SiteEngagementServiceAndroid> android_service_;
#endif
// Metrics are recorded at non-incognito browser startup, and then // Metrics are recorded at non-incognito browser startup, and then
// approximately once per hour thereafter. Store the local time at which // approximately once per hour thereafter. Store the local time at which
// metrics were previously uploaded: the first event which affects any // metrics were previously uploaded: the first event which affects any
......
// Copyright 2016 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/engagement/site_engagement_service_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/memory/ptr_util.h"
#include "chrome/browser/profiles/profile_android.h"
#include "jni/SiteEngagementService_jni.h"
#include "url/gurl.h"
using base::android::JavaParamRef;
// static
bool SiteEngagementServiceAndroid::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
}
// static
const base::android::ScopedJavaGlobalRef<jobject>&
SiteEngagementServiceAndroid::GetOrCreate(JNIEnv* env,
SiteEngagementService* service) {
SiteEngagementServiceAndroid* android_service = service->GetAndroidService();
if (!android_service) {
service->SetAndroidService(
base::MakeUnique<SiteEngagementServiceAndroid>(env, service));
android_service = service->GetAndroidService();
}
return android_service->java_service_;
}
SiteEngagementServiceAndroid::SiteEngagementServiceAndroid(
JNIEnv* env,
SiteEngagementService* service)
: service_(service) {
java_service_.Reset(Java_SiteEngagementService_create(
env, reinterpret_cast<uintptr_t>(this)));
}
SiteEngagementServiceAndroid::~SiteEngagementServiceAndroid() {
Java_SiteEngagementService_onNativeDestroyed(
base::android::AttachCurrentThread(), java_service_);
java_service_.Reset();
}
double SiteEngagementServiceAndroid::GetScore(
JNIEnv* env,
const JavaParamRef<jobject>& caller,
const JavaParamRef<jstring>& jurl) const {
if (!jurl)
return 0;
return service_->GetScore(
GURL(base::android::ConvertJavaStringToUTF16(env, jurl)));
}
void SiteEngagementServiceAndroid::ResetScoreForURL(
JNIEnv* env,
const JavaParamRef<jobject>& caller,
const JavaParamRef<jstring>& jurl,
double score) {
if (jurl) {
service_->ResetScoreForURL(
GURL(base::android::ConvertJavaStringToUTF16(env, jurl)), score);
}
}
base::android::ScopedJavaLocalRef<jobject> SiteEngagementServiceForProfile(
JNIEnv* env,
const JavaParamRef<jclass>& clazz,
const JavaParamRef<jobject>& jprofile) {
Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
SiteEngagementService* service = SiteEngagementService::Get(profile);
DCHECK(service);
return base::android::ScopedJavaLocalRef<jobject>(
SiteEngagementServiceAndroid::GetOrCreate(env, service));
}
// Copyright 2016 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_ENGAGEMENT_SITE_ENGAGEMENT_SERVICE_ANDROID_H_
#define CHROME_BROWSER_ENGAGEMENT_SITE_ENGAGEMENT_SERVICE_ANDROID_H_
#include <jni.h>
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "chrome/browser/engagement/site_engagement_service.h"
// Wrapper class to expose the Site Engagement Service to Java. This object is
// owned by the |service_| which it wraps, and is lazily created when
// a Java-side SiteEngagementService is constructed. Once created, all future
// Java-side requests for a SiteEngagementService will use the same native
// object.
//
// This class may only be used on the UI thread.
class SiteEngagementServiceAndroid {
public:
static bool Register(JNIEnv* env);
// Returns the Java-side SiteEngagementService object corresponding to
// |service|.
static const base::android::ScopedJavaGlobalRef<jobject>& GetOrCreate(
JNIEnv* env,
SiteEngagementService* service);
SiteEngagementServiceAndroid(JNIEnv* env, SiteEngagementService* service);
~SiteEngagementServiceAndroid();
double GetScore(JNIEnv* env,
const base::android::JavaParamRef<jobject>& caller,
const base::android::JavaParamRef<jstring>& jurl) const;
void ResetScoreForURL(JNIEnv* env,
const base::android::JavaParamRef<jobject>& caller,
const base::android::JavaParamRef<jstring>& jurl,
double score);
private:
base::android::ScopedJavaGlobalRef<jobject> java_service_;
SiteEngagementService* service_;
DISALLOW_COPY_AND_ASSIGN(SiteEngagementServiceAndroid);
};
#endif // CHROME_BROWSER_ENGAGEMENT_SITE_ENGAGEMENT_SERVICE_ANDROID_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