| Index: chrome/browser/android/logo_bridge.cc
|
| diff --git a/chrome/browser/android/logo_bridge.cc b/chrome/browser/android/logo_bridge.cc
|
| index b86e97c9cb1750fda75e1ccea57c775415a6ae6a..78b7074fa3f1ce34c3196b658085f7e3fab3ba0b 100644
|
| --- a/chrome/browser/android/logo_bridge.cc
|
| +++ b/chrome/browser/android/logo_bridge.cc
|
| @@ -11,10 +11,15 @@
|
| #include "base/android/jni_array.h"
|
| #include "base/android/jni_string.h"
|
| #include "base/android/scoped_java_ref.h"
|
| +#include "base/bind.h"
|
| +#include "base/feature_list.h"
|
| #include "base/metrics/histogram_macros.h"
|
| #include "chrome/browser/android/logo_service.h"
|
| +#include "chrome/browser/doodle/doodle_service_factory.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| #include "chrome/browser/profiles/profile_android.h"
|
| +#include "chrome/browser/search/suggestions/image_decoder_impl.h"
|
| +#include "components/image_fetcher/image_fetcher_impl.h"
|
| #include "components/search_provider_logos/logo_tracker.h"
|
| #include "jni/LogoBridge_jni.h"
|
| #include "net/url_request/url_fetcher.h"
|
| @@ -23,6 +28,7 @@
|
| #include "net/url_request/url_request_status.h"
|
| #include "third_party/skia/include/core/SkBitmap.h"
|
| #include "ui/gfx/android/java_bitmap.h"
|
| +#include "ui/gfx/image/image.h"
|
| #include "url/gurl.h"
|
|
|
| using base::android::ConvertJavaStringToUTF8;
|
| @@ -33,31 +39,44 @@ using base::android::ToJavaByteArray;
|
|
|
| namespace {
|
|
|
| -// Converts a C++ Logo to a Java Logo.
|
| -ScopedJavaLocalRef<jobject> ConvertLogoToJavaObject(
|
| - JNIEnv* env,
|
| - const search_provider_logos::Logo* logo) {
|
| - if (!logo)
|
| - return ScopedJavaLocalRef<jobject>();
|
| +const base::Feature kUseNewDoodleApi{"UseNewDoodleApi",
|
| + base::FEATURE_DISABLED_BY_DEFAULT};
|
|
|
| - ScopedJavaLocalRef<jobject> j_bitmap = gfx::ConvertToJavaBitmap(&logo->image);
|
| +ScopedJavaLocalRef<jobject> MakeJavaLogo(JNIEnv* env,
|
| + const SkBitmap* bitmap,
|
| + const GURL& on_click_url,
|
| + const std::string& alt_text,
|
| + const GURL& animated_url) {
|
| + ScopedJavaLocalRef<jobject> j_bitmap = gfx::ConvertToJavaBitmap(bitmap);
|
|
|
| ScopedJavaLocalRef<jstring> j_on_click_url;
|
| - if (!logo->metadata.on_click_url.empty())
|
| - j_on_click_url = ConvertUTF8ToJavaString(env, logo->metadata.on_click_url);
|
| + if (on_click_url.is_valid())
|
| + j_on_click_url = ConvertUTF8ToJavaString(env, on_click_url.spec());
|
|
|
| ScopedJavaLocalRef<jstring> j_alt_text;
|
| - if (!logo->metadata.alt_text.empty())
|
| - j_alt_text = ConvertUTF8ToJavaString(env, logo->metadata.alt_text);
|
| + if (!alt_text.empty())
|
| + j_alt_text = ConvertUTF8ToJavaString(env, alt_text);
|
|
|
| ScopedJavaLocalRef<jstring> j_animated_url;
|
| - if (!logo->metadata.animated_url.empty())
|
| - j_animated_url = ConvertUTF8ToJavaString(env, logo->metadata.animated_url);
|
| + if (animated_url.is_valid())
|
| + j_animated_url = ConvertUTF8ToJavaString(env, animated_url.spec());
|
|
|
| return Java_LogoBridge_createLogo(env, j_bitmap, j_on_click_url, j_alt_text,
|
| j_animated_url);
|
| }
|
|
|
| +// Converts a C++ Logo to a Java Logo.
|
| +ScopedJavaLocalRef<jobject> ConvertLogoToJavaObject(
|
| + JNIEnv* env,
|
| + const search_provider_logos::Logo* logo) {
|
| + if (!logo)
|
| + return ScopedJavaLocalRef<jobject>();
|
| +
|
| + return MakeJavaLogo(env, &logo->image, GURL(logo->metadata.on_click_url),
|
| + logo->metadata.alt_text,
|
| + GURL(logo->metadata.animated_url));
|
| +}
|
| +
|
| class LogoObserverAndroid : public search_provider_logos::LogoObserver {
|
| public:
|
| LogoObserverAndroid(base::WeakPtr<LogoBridge> logo_bridge,
|
| @@ -172,10 +191,24 @@ static jlong Init(JNIEnv* env,
|
| }
|
|
|
| LogoBridge::LogoBridge(jobject j_profile)
|
| - : logo_service_(nullptr), weak_ptr_factory_(this) {
|
| + : logo_service_(nullptr),
|
| + doodle_service_(nullptr),
|
| + doodle_observer_(this),
|
| + weak_ptr_factory_(this) {
|
| Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
|
| DCHECK(profile);
|
| - logo_service_ = LogoServiceFactory::GetForProfile(profile);
|
| +
|
| + if (base::FeatureList::IsEnabled(kUseNewDoodleApi)) {
|
| + doodle_service_ = DoodleServiceFactory::GetForProfile(profile);
|
| + image_fetcher_ = base::MakeUnique<image_fetcher::ImageFetcherImpl>(
|
| + base::MakeUnique<suggestions::ImageDecoderImpl>(),
|
| + profile->GetRequestContext());
|
| +
|
| + doodle_observer_.Add(doodle_service_);
|
| + } else {
|
| + logo_service_ = LogoServiceFactory::GetForProfile(profile);
|
| + }
|
| +
|
| animated_logo_fetcher_ = base::MakeUnique<AnimatedLogoFetcher>(
|
| profile->GetRequestContext());
|
| }
|
| @@ -189,10 +222,19 @@ void LogoBridge::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) {
|
| void LogoBridge::GetCurrentLogo(JNIEnv* env,
|
| const JavaParamRef<jobject>& obj,
|
| const JavaParamRef<jobject>& j_logo_observer) {
|
| - // |observer| is deleted in LogoObserverAndroid::OnObserverRemoved().
|
| - LogoObserverAndroid* observer = new LogoObserverAndroid(
|
| - weak_ptr_factory_.GetWeakPtr(), env, j_logo_observer);
|
| - logo_service_->GetLogo(observer);
|
| + if (doodle_service_) {
|
| + j_logo_observer_.Reset(j_logo_observer);
|
| +
|
| + // Immediately hand out any current cached config.
|
| + DoodleConfigReceived(doodle_service_->config(), /*from_cache=*/true);
|
| + // Also request a refresh, in case something changed.
|
| + doodle_service_->Refresh();
|
| + } else {
|
| + // |observer| is deleted in LogoObserverAndroid::OnObserverRemoved().
|
| + LogoObserverAndroid* observer = new LogoObserverAndroid(
|
| + weak_ptr_factory_.GetWeakPtr(), env, j_logo_observer);
|
| + logo_service_->GetLogo(observer);
|
| + }
|
| }
|
|
|
| void LogoBridge::GetAnimatedLogo(JNIEnv* env,
|
| @@ -203,6 +245,66 @@ void LogoBridge::GetAnimatedLogo(JNIEnv* env,
|
| animated_logo_fetcher_->Start(env, url, j_callback);
|
| }
|
|
|
| +void LogoBridge::OnDoodleConfigUpdated(
|
| + const base::Optional<doodle::DoodleConfig>& maybe_doodle_config) {
|
| + if (j_logo_observer_.is_null()) {
|
| + return;
|
| + }
|
| + DoodleConfigReceived(maybe_doodle_config, /*from_cache=*/false);
|
| +}
|
| +
|
| +void LogoBridge::DoodleConfigReceived(
|
| + const base::Optional<doodle::DoodleConfig>& maybe_doodle_config,
|
| + bool from_cache) {
|
| + DCHECK(!j_logo_observer_.is_null());
|
| +
|
| + if (!maybe_doodle_config.has_value()) {
|
| + JNIEnv* env = base::android::AttachCurrentThread();
|
| + Java_LogoObserver_onLogoAvailable(
|
| + env, j_logo_observer_, ScopedJavaLocalRef<jobject>(), from_cache);
|
| + return;
|
| + }
|
| + const doodle::DoodleConfig& doodle_config = maybe_doodle_config.value();
|
| + // If there is a CTA image, that means the main image is animated. Show the
|
| + // non-animated CTA image first, and load the animated one only when the
|
| + // user requests it.
|
| + bool has_cta = doodle_config.large_cta_image.has_value();
|
| + const GURL& image_url = has_cta ? doodle_config.large_cta_image->url
|
| + : doodle_config.large_image.url;
|
| + const GURL& animated_image_url =
|
| + has_cta ? doodle_config.large_image.url : GURL::EmptyGURL();
|
| + // TODO(treib): For interactive doodles, use |fullpage_interactive_url|
|
| + // instead of |target_url|?
|
| + const GURL& on_click_url = doodle_config.target_url;
|
| + const std::string& alt_text = doodle_config.alt_text;
|
| + image_fetcher_->StartOrQueueNetworkRequest(
|
| + image_url.spec(), image_url,
|
| + base::Bind(&LogoBridge::DoodleImageFetched, base::Unretained(this),
|
| + from_cache, on_click_url, alt_text, animated_image_url));
|
| +}
|
| +
|
| +void LogoBridge::DoodleImageFetched(bool config_from_cache,
|
| + const GURL& on_click_url,
|
| + const std::string& alt_text,
|
| + const GURL& animated_image_url,
|
| + const std::string& image_fetch_id,
|
| + const gfx::Image& image) {
|
| + JNIEnv* env = base::android::AttachCurrentThread();
|
| +
|
| + if (image.IsEmpty()) {
|
| + DLOG(WARNING) << "Failed to download doodle image";
|
| + Java_LogoObserver_onLogoAvailable(env, j_logo_observer_,
|
| + ScopedJavaLocalRef<jobject>(),
|
| + config_from_cache);
|
| + return;
|
| + }
|
| +
|
| + ScopedJavaLocalRef<jobject> j_logo = MakeJavaLogo(
|
| + env, image.ToSkBitmap(), on_click_url, alt_text, animated_image_url);
|
| + Java_LogoObserver_onLogoAvailable(env, j_logo_observer_, j_logo,
|
| + config_from_cache);
|
| +}
|
| +
|
| // static
|
| bool RegisterLogoBridge(JNIEnv* env) {
|
| return RegisterNativesImpl(env);
|
|
|