Commit b08b62ec authored by Shakti Sahu's avatar Shakti Sahu Committed by Commit Bot

Video Tutorials : Added glue logic to TutorialServiceImpl and JNI

This CL adds the JNI glue for all the public methods from Java to all
the way till native TutorialServiceImpl. Also glued TutorialManager
and TutorialFetcher to the service.

Bug: 1130460
Change-Id: I1e62d419b0883b2d02c4da9a83fc2c8c8abc3f12
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2421248
Commit-Queue: Shakti Sahu <shaktisahu@chromium.org>
Reviewed-by: default avatarXing Liu <xingliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809363}
parent 9893ae7f
...@@ -17,4 +17,25 @@ public interface VideoTutorialService { ...@@ -17,4 +17,25 @@ public interface VideoTutorialService {
* Called to get the list of video tutorials available. * Called to get the list of video tutorials available.
*/ */
void getTutorials(Callback<List<Tutorial>> callback); void getTutorials(Callback<List<Tutorial>> callback);
/**
* Called to get the {@link Tutorial} associated with a feature. Returns null if a matching
* tutorial doesn't exist.
*/
void getTutorial(@FeatureType int feature, Callback<Tutorial> callback);
/**
* @return The list of locales in which video tutorials are available.
*/
List<String> getSupportedLocales();
/**
* @return The preferred locale to show the video tutorial.
*/
String getPreferredLocale();
/**
* Called to set the preferred locale for showing the video tutorials.
*/
void setPreferredLocale(String locale);
} }
...@@ -7,11 +7,11 @@ package org.chromium.chrome.browser.video_tutorials.bridges; ...@@ -7,11 +7,11 @@ package org.chromium.chrome.browser.video_tutorials.bridges;
import org.chromium.base.Callback; import org.chromium.base.Callback;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.video_tutorials.FeatureType; import org.chromium.chrome.browser.video_tutorials.FeatureType;
import org.chromium.chrome.browser.video_tutorials.Tutorial; import org.chromium.chrome.browser.video_tutorials.Tutorial;
import org.chromium.chrome.browser.video_tutorials.VideoTutorialService; import org.chromium.chrome.browser.video_tutorials.VideoTutorialService;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
...@@ -32,26 +32,55 @@ public class VideoTutorialServiceBridge implements VideoTutorialService { ...@@ -32,26 +32,55 @@ public class VideoTutorialServiceBridge implements VideoTutorialService {
@Override @Override
public void getTutorials(Callback<List<Tutorial>> callback) { public void getTutorials(Callback<List<Tutorial>> callback) {
callback.onResult(getSampleData()); if (mNativeVideoTutorialServiceBridge == 0) return;
VideoTutorialServiceBridgeJni.get().getTutorials(
mNativeVideoTutorialServiceBridge, this, callback);
} }
private List<Tutorial> getSampleData() { @Override
List<Tutorial> list = new ArrayList<>(); public void getTutorial(@FeatureType int feature, Callback<Tutorial> callback) {
list.add(new Tutorial(FeatureType.DOWNLOAD, if (mNativeVideoTutorialServiceBridge == 0) return;
"How to use Google Chrome's download functionality", VideoTutorialServiceBridgeJni.get().getTutorial(
"https://storage.googleapis.com/stock-wizard.appspot.com/portrait.jpg", mNativeVideoTutorialServiceBridge, this, feature, callback);
"https://storage.googleapis.com/stock-wizard.appspot.com/portrait.jpg", }
"caption url", "share url", 35));
@Override
public List<String> getSupportedLocales() {
if (mNativeVideoTutorialServiceBridge == 0) return null;
return VideoTutorialServiceBridgeJni.get().getSupportedLocales(
mNativeVideoTutorialServiceBridge, this);
}
list.add(new Tutorial(FeatureType.SEARCH, "How to efficiently search with Google Chrome", @Override
"https://storage.googleapis.com/stock-wizard.appspot.com/elephant.jpg ", public String getPreferredLocale() {
"https://storage.googleapis.com/stock-wizard.appspot.com/elephant.jpg", if (mNativeVideoTutorialServiceBridge == 0) return null;
"caption url", "share url", 35)); return VideoTutorialServiceBridgeJni.get().getPreferredLocale(
return list; mNativeVideoTutorialServiceBridge, this);
}
@Override
public void setPreferredLocale(String locale) {
if (mNativeVideoTutorialServiceBridge == 0) return;
VideoTutorialServiceBridgeJni.get().setPreferredLocale(
mNativeVideoTutorialServiceBridge, this, locale);
} }
@CalledByNative @CalledByNative
private void clearNativePtr() { private void clearNativePtr() {
mNativeVideoTutorialServiceBridge = 0; mNativeVideoTutorialServiceBridge = 0;
} }
@NativeMethods
interface Natives {
void getTutorials(long nativeVideoTutorialServiceBridge, VideoTutorialServiceBridge caller,
Callback<List<Tutorial>> callback);
void getTutorial(long nativeVideoTutorialServiceBridge, VideoTutorialServiceBridge caller,
int feature, Callback<Tutorial> callback);
List<String> getSupportedLocales(
long nativeVideoTutorialServiceBridge, VideoTutorialServiceBridge caller);
String getPreferredLocale(
long nativeVideoTutorialServiceBridge, VideoTutorialServiceBridge caller);
void setPreferredLocale(long nativeVideoTutorialServiceBridge,
VideoTutorialServiceBridge caller, String locale);
}
} }
...@@ -42,4 +42,16 @@ ScopedJavaLocalRef<jobject> TutorialConversionBridge::CreateJavaTutorials( ...@@ -42,4 +42,16 @@ ScopedJavaLocalRef<jobject> TutorialConversionBridge::CreateJavaTutorials(
return jlist; return jlist;
} }
ScopedJavaLocalRef<jobject> TutorialConversionBridge::CreateJavaTutorial(
JNIEnv* env,
base::Optional<Tutorial> tutorial) {
ScopedJavaLocalRef<jobject> jobj;
if (tutorial.has_value()) {
jobj = CreateJavaTutorialAndMaybeAddToList(
env, ScopedJavaLocalRef<jobject>(), tutorial.value());
}
return jobj;
}
} // namespace video_tutorials } // namespace video_tutorials
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <vector> #include <vector>
#include "base/android/jni_android.h" #include "base/android/jni_android.h"
#include "base/optional.h"
#include "chrome/browser/video_tutorials/tutorial.h" #include "chrome/browser/video_tutorials/tutorial.h"
using base::android::ScopedJavaLocalRef; using base::android::ScopedJavaLocalRef;
...@@ -21,6 +22,10 @@ class TutorialConversionBridge { ...@@ -21,6 +22,10 @@ class TutorialConversionBridge {
static ScopedJavaLocalRef<jobject> CreateJavaTutorials( static ScopedJavaLocalRef<jobject> CreateJavaTutorials(
JNIEnv* env, JNIEnv* env,
const std::vector<Tutorial>& tutorials); const std::vector<Tutorial>& tutorials);
static ScopedJavaLocalRef<jobject> CreateJavaTutorial(
JNIEnv* env,
base::Optional<Tutorial> tutorial);
}; };
} // namespace video_tutorials } // namespace video_tutorials
......
...@@ -8,9 +8,12 @@ ...@@ -8,9 +8,12 @@
#include <vector> #include <vector>
#include "base/android/callback_android.h" #include "base/android/callback_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/bind.h" #include "base/bind.h"
#include "chrome/browser/video_tutorials/internal/android/tutorial_conversion_bridge.h"
#include "chrome/browser/video_tutorials/internal/jni_headers/VideoTutorialServiceBridge_jni.h" #include "chrome/browser/video_tutorials/internal/jni_headers/VideoTutorialServiceBridge_jni.h"
#include "chrome/browser/video_tutorials/tutorial.h"
using base::android::AttachCurrentThread; using base::android::AttachCurrentThread;
...@@ -19,6 +22,21 @@ namespace { ...@@ -19,6 +22,21 @@ namespace {
const char kVideoTutorialServiceBridgeKey[] = "video_tutorial_service_bridge"; const char kVideoTutorialServiceBridgeKey[] = "video_tutorial_service_bridge";
void RunGetMultipleTutorialsCallback(const JavaRef<jobject>& j_callback,
std::vector<Tutorial> tutorials) {
JNIEnv* env = AttachCurrentThread();
RunObjectCallbackAndroid(
j_callback,
TutorialConversionBridge::CreateJavaTutorials(env, std::move(tutorials)));
}
void RunGetSingleTutorialCallback(const JavaRef<jobject>& j_callback,
base::Optional<Tutorial> tutorial) {
JNIEnv* env = AttachCurrentThread();
RunObjectCallbackAndroid(
j_callback, TutorialConversionBridge::CreateJavaTutorial(env, tutorial));
}
} // namespace } // namespace
// static // static
...@@ -52,4 +70,47 @@ VideoTutorialServiceBridge::~VideoTutorialServiceBridge() { ...@@ -52,4 +70,47 @@ VideoTutorialServiceBridge::~VideoTutorialServiceBridge() {
Java_VideoTutorialServiceBridge_clearNativePtr(env, java_obj_); Java_VideoTutorialServiceBridge_clearNativePtr(env, java_obj_);
} }
void VideoTutorialServiceBridge::GetTutorials(
JNIEnv* env,
const JavaParamRef<jobject>& jcaller,
const JavaParamRef<jobject>& jcallback) {
video_tutorial_service_->GetTutorials(
base::BindOnce(&RunGetMultipleTutorialsCallback,
ScopedJavaGlobalRef<jobject>(jcallback)));
}
void VideoTutorialServiceBridge::GetTutorial(
JNIEnv* env,
const JavaParamRef<jobject>& jcaller,
jint j_feature,
const JavaParamRef<jobject>& jcallback) {
video_tutorial_service_->GetTutorial(
static_cast<FeatureType>(j_feature),
base::BindOnce(&RunGetSingleTutorialCallback,
ScopedJavaGlobalRef<jobject>(jcallback)));
}
ScopedJavaLocalRef<jobject> VideoTutorialServiceBridge::GetSupportedLocales(
JNIEnv* env,
const JavaParamRef<jobject>& jcaller) {
std::vector<std::string> locales =
video_tutorial_service_->GetSupportedLocales();
return base::android::ToJavaArrayOfStrings(env, locales);
}
ScopedJavaLocalRef<jstring> VideoTutorialServiceBridge::GetPreferredLocale(
JNIEnv* env,
const JavaParamRef<jobject>& jcaller) {
std::string locale = video_tutorial_service_->GetPreferredLocale();
return base::android::ConvertUTF8ToJavaString(env, locale);
}
void VideoTutorialServiceBridge::SetPreferredLocale(
JNIEnv* env,
const JavaParamRef<jobject>& jcaller,
jstring j_locale) {
std::string locale = base::android::ConvertJavaStringToUTF8(env, j_locale);
video_tutorial_service_->SetPreferredLocale(locale);
}
} // namespace video_tutorials } // namespace video_tutorials
...@@ -29,6 +29,24 @@ class VideoTutorialServiceBridge : public base::SupportsUserData::Data { ...@@ -29,6 +29,24 @@ class VideoTutorialServiceBridge : public base::SupportsUserData::Data {
VideoTutorialService* video_tutorial_service); VideoTutorialService* video_tutorial_service);
~VideoTutorialServiceBridge() override; ~VideoTutorialServiceBridge() override;
// Methods called from Java via JNI.
void GetTutorials(JNIEnv* env,
const JavaParamRef<jobject>& jcaller,
const JavaParamRef<jobject>& jcallback);
void GetTutorial(JNIEnv* env,
const JavaParamRef<jobject>& jcaller,
jint j_feature,
const JavaParamRef<jobject>& jcallback);
ScopedJavaLocalRef<jobject> GetSupportedLocales(
JNIEnv* env,
const JavaParamRef<jobject>& jcaller);
ScopedJavaLocalRef<jstring> GetPreferredLocale(
JNIEnv* env,
const JavaParamRef<jobject>& jcaller);
void SetPreferredLocale(JNIEnv* env,
const JavaParamRef<jobject>& jcaller,
jstring j_locale);
private: private:
// A reference to the Java counterpart of this class. See // A reference to the Java counterpart of this class. See
// VideoTutorialServiceBridge.java. // VideoTutorialServiceBridge.java.
......
...@@ -24,6 +24,11 @@ constexpr char kBaseURLKey[] = "base_url"; ...@@ -24,6 +24,11 @@ constexpr char kBaseURLKey[] = "base_url";
constexpr char kPreferredLocaleConfigKey[] = "default_locale"; constexpr char kPreferredLocaleConfigKey[] = "default_locale";
constexpr char kFetchFrequencyKey[] = "fetch_frequency";
// Default frequency in days for fetching tutorial metatada from server.
constexpr int kDefaultFetchFrequencyDays = 15;
namespace { namespace {
const GURL BuildGetTutorialsEndpoint(const GURL& base_url, const char* path) { const GURL BuildGetTutorialsEndpoint(const GURL& base_url, const char* path) {
GURL::Replacements replacements; GURL::Replacements replacements;
...@@ -51,4 +56,12 @@ std::string Config::GetDefaultPreferredLocale() { ...@@ -51,4 +56,12 @@ std::string Config::GetDefaultPreferredLocale() {
: default_locale_from_finch; : default_locale_from_finch;
} }
// static
base::TimeDelta Config::GetFetchFrequency() {
int frequency_in_days = base::GetFieldTrialParamByFeatureAsInt(
features::kVideoTutorials, kFetchFrequencyKey,
kDefaultFetchFrequencyDays);
return base::TimeDelta::FromDays(frequency_in_days);
}
} // namespace video_tutorials } // namespace video_tutorials
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "base/time/time.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace video_tutorials { namespace video_tutorials {
...@@ -27,6 +28,9 @@ extern const char kPreferredLocaleConfigKey[]; ...@@ -27,6 +28,9 @@ extern const char kPreferredLocaleConfigKey[];
// Default preferred locale setting before users pick. // Default preferred locale setting before users pick.
extern const char kDefaultPreferredLocale[]; extern const char kDefaultPreferredLocale[];
// Finch parameter key for the fetch frequency to retrieve the tutorials.
extern const char kFetchFrequencyKey[];
class Config { class Config {
public: public:
// Get video tutorials metadata server URL. // Get video tutorials metadata server URL.
...@@ -34,6 +38,9 @@ class Config { ...@@ -34,6 +38,9 @@ class Config {
// Get the default locale before users choice. // Get the default locale before users choice.
static std::string GetDefaultPreferredLocale(); static std::string GetDefaultPreferredLocale();
// Get the default fetch frequency.
static base::TimeDelta GetFetchFrequency();
}; };
} // namespace video_tutorials } // namespace video_tutorials
......
...@@ -6,4 +6,73 @@ ...@@ -6,4 +6,73 @@
#include <utility> #include <utility>
namespace video_tutorials {} // namespace video_tutorials #include "base/bind.h"
#include "base/bind_helpers.h"
#include "chrome/browser/video_tutorials/internal/config.h"
#include "chrome/browser/video_tutorials/prefs.h"
namespace video_tutorials {
TutorialServiceImpl::TutorialServiceImpl(
std::unique_ptr<TutorialManager> tutorial_manager,
std::unique_ptr<TutorialFetcher> tutorial_fetcher,
PrefService* pref_service)
: tutorial_manager_(std::move(tutorial_manager)),
tutorial_fetcher_(std::move(tutorial_fetcher)),
pref_service_(pref_service) {}
TutorialServiceImpl::~TutorialServiceImpl() = default;
void TutorialServiceImpl::GetTutorials(MultipleItemCallback callback) {
tutorial_manager_->GetTutorials(std::move(callback));
}
void TutorialServiceImpl::GetTutorial(FeatureType feature_type,
SingleItemCallback callback) {
tutorial_manager_->GetTutorials(base::BindOnce(
&TutorialServiceImpl::OnGetTutorials, weak_ptr_factory_.GetWeakPtr(),
std::move(callback), feature_type));
}
void TutorialServiceImpl::OnGetTutorials(SingleItemCallback callback,
FeatureType feature_type,
std::vector<Tutorial> tutorials) {
for (const Tutorial& tutorial : tutorials) {
if (tutorial.feature == feature_type) {
std::move(callback).Run(tutorial);
return;
}
}
std::move(callback).Run(base::nullopt);
}
void TutorialServiceImpl::StartFetchIfNecessary() {
base::Time last_update_time = pref_service_->GetTime(kLastUpdatedTimeKey);
bool needs_update =
((base::Time::Now() - last_update_time) > Config::GetFetchFrequency());
if (needs_update) {
tutorial_fetcher_->StartFetchForTutorials(base::BindOnce(
&TutorialServiceImpl::OnFetchFinished, weak_ptr_factory_.GetWeakPtr()));
}
}
void TutorialServiceImpl::OnFetchFinished(
bool success,
std::unique_ptr<std::string> response_body) {
// TODO(shaktisahu): Save tutorials to the database.
}
std::vector<std::string> TutorialServiceImpl::GetSupportedLocales() {
return tutorial_manager_->GetSupportedLocales();
}
std::string TutorialServiceImpl::GetPreferredLocale() {
return tutorial_manager_->GetPreferredLocale();
}
void TutorialServiceImpl::SetPreferredLocale(const std::string& locale) {
tutorial_manager_->SetPreferredLocale(locale);
}
} // namespace video_tutorials
...@@ -7,12 +7,49 @@ ...@@ -7,12 +7,49 @@
#include "chrome/browser/video_tutorials/video_tutorial_service.h" #include "chrome/browser/video_tutorials/video_tutorial_service.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/video_tutorials/internal/tutorial_fetcher.h"
#include "chrome/browser/video_tutorials/internal/tutorial_manager.h"
#include "components/prefs/pref_service.h"
namespace video_tutorials { namespace video_tutorials {
class TutorialServiceImpl : public VideoTutorialService { class TutorialServiceImpl : public VideoTutorialService {
public: public:
TutorialServiceImpl() = default; TutorialServiceImpl(std::unique_ptr<TutorialManager> tutorial_manager,
~TutorialServiceImpl() override = default; std::unique_ptr<TutorialFetcher> tutorial_fetcher,
PrefService* pref_service);
~TutorialServiceImpl() override;
// TutorialService implementation.
void GetTutorials(MultipleItemCallback callback) override;
void GetTutorial(FeatureType feature_type,
SingleItemCallback callback) override;
std::vector<std::string> GetSupportedLocales() override;
std::string GetPreferredLocale() override;
void SetPreferredLocale(const std::string& locale) override;
private:
void OnGetTutorials(SingleItemCallback callback,
FeatureType feature_type,
std::vector<Tutorial> tutorials);
// Called at service startup to determine if a network fetch is necessary
// based on the last fetch timestamp.
void StartFetchIfNecessary();
void OnFetchFinished(bool success,
std::unique_ptr<std::string> response_body);
// Manages in memory tutorial metadata and coordinates with TutorialStore.
std::unique_ptr<TutorialManager> tutorial_manager_;
// Fetcher to execute download jobs from Google server.
std::unique_ptr<TutorialFetcher> tutorial_fetcher_;
// PrefService.
PrefService* pref_service_;
base::WeakPtrFactory<TutorialServiceImpl> weak_ptr_factory_{this};
}; };
} // namespace video_tutorials } // namespace video_tutorials
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
namespace video_tutorials { namespace video_tutorials {
std::unique_ptr<VideoTutorialService> CreateVideoTutorialService() { std::unique_ptr<VideoTutorialService> CreateVideoTutorialService() {
return std::make_unique<TutorialServiceImpl>(); // TODO(shaktisahu): Pass correct values.
return std::make_unique<TutorialServiceImpl>(nullptr, nullptr, nullptr);
} }
} // namespace video_tutorials } // namespace video_tutorials
...@@ -5,16 +5,42 @@ ...@@ -5,16 +5,42 @@
#ifndef CHROME_BROWSER_VIDEO_TUTORIALS_VIDEO_TUTORIAL_SERVICE_H_ #ifndef CHROME_BROWSER_VIDEO_TUTORIALS_VIDEO_TUTORIAL_SERVICE_H_
#define CHROME_BROWSER_VIDEO_TUTORIALS_VIDEO_TUTORIAL_SERVICE_H_ #define CHROME_BROWSER_VIDEO_TUTORIALS_VIDEO_TUTORIAL_SERVICE_H_
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/optional.h"
#include "base/supports_user_data.h" #include "base/supports_user_data.h"
#include "chrome/browser/video_tutorials/tutorial.h"
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
namespace video_tutorials { namespace video_tutorials {
using TutorialList = std::vector<Tutorial>;
using MultipleItemCallback = base::OnceCallback<void(std::vector<Tutorial>)>;
using SingleItemCallback = base::OnceCallback<void(base::Optional<Tutorial>)>;
// The central class on chrome client responsible for managing, storing, and // The central class on chrome client responsible for managing, storing, and
// serving video tutorials in chrome. // serving video tutorials in chrome.
class VideoTutorialService : public KeyedService, class VideoTutorialService : public KeyedService,
public base::SupportsUserData { public base::SupportsUserData {
public: public:
// Called to retrieve all the tutorials.
virtual void GetTutorials(MultipleItemCallback callback) = 0;
// Called to retrieve the tutorial associated with |feature_type|.
virtual void GetTutorial(FeatureType feature_type,
SingleItemCallback callback) = 0;
// Called to retrieve all the supported locales.
virtual std::vector<std::string> GetSupportedLocales() = 0;
// Called to retrieve the preferred locale.
virtual std::string GetPreferredLocale() = 0;
// Called to set the preferred locale.
virtual void SetPreferredLocale(const std::string& locale) = 0;
VideoTutorialService() = default; VideoTutorialService() = default;
~VideoTutorialService() override = default; ~VideoTutorialService() override = default;
......
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