| // Copyright 2015 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "components/favicon/android/large_icon_bridge.h" | 
 |  | 
 | #include <jni.h> | 
 |  | 
 | #include "base/android/jni_android.h" | 
 | #include "base/android/scoped_java_ref.h" | 
 | #include "base/functional/bind.h" | 
 | #include "components/favicon/content/large_icon_service_getter.h" | 
 | #include "components/favicon/core/large_icon_service.h" | 
 | #include "components/favicon_base/fallback_icon_style.h" | 
 | #include "components/favicon_base/favicon_callback.h" | 
 | #include "components/favicon_base/favicon_types.h" | 
 | #include "content/public/browser/android/browser_context_handle.h" | 
 | #include "net/traffic_annotation/network_traffic_annotation.h" | 
 | #include "third_party/skia/include/core/SkBitmap.h" | 
 | #include "ui/gfx/android/java_bitmap.h" | 
 | #include "ui/gfx/codec/png_codec.h" | 
 | #include "url/android/gurl_android.h" | 
 | #include "url/gurl.h" | 
 |  | 
 | // Must come after all headers that specialize FromJniType() / ToJniType(). | 
 | #include "components/favicon/android/jni_headers/LargeIconBridge_jni.h" | 
 |  | 
 | using base::android::AttachCurrentThread; | 
 | using base::android::JavaParamRef; | 
 | using base::android::JavaRef; | 
 | using base::android::ScopedJavaGlobalRef; | 
 | using base::android::ScopedJavaLocalRef; | 
 |  | 
 | namespace favicon { | 
 |  | 
 | namespace { | 
 |  | 
 | void OnLargeIconAvailable(const JavaRef<jobject>& j_callback, | 
 |                           const favicon_base::LargeIconResult& result) { | 
 |   // Convert the result to a Java Bitmap. | 
 |   SkBitmap bitmap; | 
 |   ScopedJavaLocalRef<jobject> j_bitmap; | 
 |   if (result.bitmap.is_valid()) { | 
 |     if (gfx::PNGCodec::Decode(result.bitmap.bitmap_data->front(), | 
 |                               result.bitmap.bitmap_data->size(), &bitmap)) | 
 |       j_bitmap = gfx::ConvertToJavaBitmap(bitmap); | 
 |   } | 
 |  | 
 |   favicon_base::FallbackIconStyle fallback; | 
 |   if (result.fallback_icon_style) | 
 |     fallback = *result.fallback_icon_style; | 
 |  | 
 |   JNIEnv* env = AttachCurrentThread(); | 
 |   Java_LargeIconCallback_onLargeIconAvailable( | 
 |       env, j_callback, j_bitmap, fallback.background_color, | 
 |       fallback.is_default_background_color, | 
 |       static_cast<int>(result.bitmap.icon_type)); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | static jlong JNI_LargeIconBridge_Init(JNIEnv* env) { | 
 |   return reinterpret_cast<intptr_t>(new LargeIconBridge()); | 
 | } | 
 |  | 
 | LargeIconBridge::LargeIconBridge() = default; | 
 | LargeIconBridge::~LargeIconBridge() = default; | 
 |  | 
 | void LargeIconBridge::Destroy(JNIEnv* env) { | 
 |   delete this; | 
 | } | 
 |  | 
 | jboolean LargeIconBridge::GetLargeIconForURL( | 
 |     JNIEnv* env, | 
 |     const JavaParamRef<jobject>& j_browser_context, | 
 |     const JavaParamRef<jobject>& j_page_url, | 
 |     jint min_source_size_px, | 
 |     jint desired_source_size_px, | 
 |     const JavaParamRef<jobject>& j_callback) { | 
 |   content::BrowserContext* browser_context = | 
 |       content::BrowserContextFromJavaHandle(j_browser_context); | 
 |   if (!browser_context) | 
 |     return false; | 
 |  | 
 |   LargeIconService* large_icon_service = GetLargeIconService(browser_context); | 
 |   if (!large_icon_service) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   favicon_base::LargeIconCallback callback_runner = base::BindOnce( | 
 |       &OnLargeIconAvailable, ScopedJavaGlobalRef<jobject>(env, j_callback)); | 
 |  | 
 |   GURL url = url::GURLAndroid::ToNativeGURL(env, j_page_url); | 
 |  | 
 |   // Use desired_size = 0 for getting the icon from the cache (so that | 
 |   // the icon is not poorly rescaled by LargeIconService). | 
 |   large_icon_service->GetLargeIconRawBitmapOrFallbackStyleForPageUrl( | 
 |       url, min_source_size_px, desired_source_size_px, | 
 |       std::move(callback_runner), &cancelable_task_tracker_); | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | void LargeIconBridge:: | 
 |     GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( | 
 |         JNIEnv* env, | 
 |         const base::android::JavaParamRef<jobject>& j_browser_context, | 
 |         const base::android::JavaParamRef<jobject>& j_page_url, | 
 |         jboolean should_trim_page_url_path, | 
 |         jint j_network_annotation_hash_code, | 
 |         const base::android::JavaParamRef<jobject>& j_callback) { | 
 |   content::BrowserContext* browser_context = | 
 |       content::BrowserContextFromJavaHandle(j_browser_context); | 
 |   if (!browser_context) { | 
 |     return; | 
 |   } | 
 |  | 
 |   LargeIconService* large_icon_service = GetLargeIconService(browser_context); | 
 |   if (!large_icon_service) { | 
 |     return; | 
 |   } | 
 |  | 
 |   GURL page_url = url::GURLAndroid::ToNativeGURL(env, j_page_url); | 
 |   favicon_base::GoogleFaviconServerCallback callback = | 
 |       base::BindOnce(&LargeIconBridge::OnGoogleFaviconServerResponse, | 
 |                      weak_factory_.GetWeakPtr(), | 
 |                      ScopedJavaGlobalRef<jobject>(env, j_callback)); | 
 |   large_icon_service | 
 |       ->GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( | 
 |           page_url, should_trim_page_url_path, | 
 |           net::NetworkTrafficAnnotationTag::FromJavaAnnotation( | 
 |               j_network_annotation_hash_code), | 
 |           std::move(callback)); | 
 | } | 
 |  | 
 | void LargeIconBridge::TouchIconFromGoogleServer( | 
 |     JNIEnv* env, | 
 |     const base::android::JavaParamRef<jobject>& j_browser_context, | 
 |     const base::android::JavaParamRef<jobject>& j_icon_url) { | 
 |   content::BrowserContext* browser_context = | 
 |       content::BrowserContextFromJavaHandle(j_browser_context); | 
 |   if (!browser_context) { | 
 |     return; | 
 |   } | 
 |  | 
 |   LargeIconService* large_icon_service = GetLargeIconService(browser_context); | 
 |   if (!large_icon_service) { | 
 |     return; | 
 |   } | 
 |  | 
 |   GURL icon_url = url::GURLAndroid::ToNativeGURL(env, j_icon_url); | 
 |   large_icon_service->TouchIconFromGoogleServer(icon_url); | 
 | } | 
 |  | 
 | void LargeIconBridge::OnGoogleFaviconServerResponse( | 
 |     const JavaRef<jobject>& j_callback, | 
 |     favicon_base::GoogleFaviconServerRequestStatus status) const { | 
 |   JNIEnv* env = AttachCurrentThread(); | 
 |   Java_GoogleFaviconServerCallback_onRequestComplete(env, j_callback, | 
 |                                                      static_cast<int>(status)); | 
 | } | 
 |  | 
 | }  // namespace favicon |