// Copyright 2013 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/favicon_helper.h" #include #include "base/android/jni_android.h" #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/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/favicon/favicon_service.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" #include "chrome/browser/sync/open_tabs_ui_delegate.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "jni/FaviconHelper_jni.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/android/java_bitmap.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/color_analysis.h" #include "ui/gfx/color_utils.h" using base::android::ScopedJavaGlobalRef; using base::android::ScopedJavaLocalRef; using base::android::AttachCurrentThread; using base::android::ConvertJavaStringToUTF16; using base::android::ConvertJavaStringToUTF8; using base::android::ConvertUTF8ToJavaString; namespace { void OnLocalFaviconAvailable( ScopedJavaGlobalRef* j_favicon_image_callback, const favicon_base::FaviconRawBitmapResult& result) { JNIEnv* env = AttachCurrentThread(); // Convert favicon_image_result to java objects. ScopedJavaLocalRef j_icon_url = ConvertUTF8ToJavaString(env, result.icon_url.spec()); ScopedJavaLocalRef j_favicon_bitmap; if (result.is_valid()) { SkBitmap favicon_bitmap; gfx::PNGCodec::Decode(result.bitmap_data->front(), result.bitmap_data->size(), &favicon_bitmap); if (!favicon_bitmap.isNull()) j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap); } // Call java side OnLocalFaviconAvailable method. Java_FaviconImageCallback_onFaviconAvailable(env, j_favicon_image_callback->obj(), j_favicon_bitmap.obj(), j_icon_url.obj()); } void OnFaviconRawBitmapResultAvailable( ScopedJavaGlobalRef* j_favicon_image_callback, const favicon_base::FaviconRawBitmapResult& favicon_bitmap_result) { JNIEnv* env = AttachCurrentThread(); // Convert favicon_image_result to java objects. ScopedJavaLocalRef j_icon_url = ConvertUTF8ToJavaString(env, favicon_bitmap_result.icon_url.spec()); SkBitmap favicon_bitmap; if (favicon_bitmap_result.is_valid()) { gfx::PNGCodec::Decode(favicon_bitmap_result.bitmap_data->front(), favicon_bitmap_result.bitmap_data->size(), &favicon_bitmap); } ScopedJavaLocalRef j_favicon_bitmap; if (!favicon_bitmap.isNull()) j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap); // Call java side OnLocalFaviconAvailable method. Java_FaviconImageCallback_onFaviconAvailable(env, j_favicon_image_callback->obj(), j_favicon_bitmap.obj(), j_icon_url.obj()); } } // namespace static jlong Init(JNIEnv* env, jclass clazz) { return reinterpret_cast(new FaviconHelper()); } FaviconHelper::FaviconHelper() { cancelable_task_tracker_.reset(new base::CancelableTaskTracker()); } void FaviconHelper::Destroy(JNIEnv* env, jobject obj) { delete this; } jboolean FaviconHelper::GetLocalFaviconImageForURL( JNIEnv* env, jobject obj, jobject j_profile, jstring j_page_url, jint j_icon_types, jint j_desired_size_in_pixel, jobject j_favicon_image_callback) { Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); DCHECK(profile); if (!profile) return false; FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( profile, Profile::EXPLICIT_ACCESS); DCHECK(favicon_service); if (!favicon_service) return false; ScopedJavaGlobalRef* j_scoped_favicon_callback = new ScopedJavaGlobalRef(); j_scoped_favicon_callback->Reset(env, j_favicon_image_callback); favicon_base::FaviconRawBitmapCallback callback_runner = base::Bind( &OnLocalFaviconAvailable, base::Owned(j_scoped_favicon_callback)); favicon_service->GetRawFaviconForPageURL( GURL(ConvertJavaStringToUTF16(env, j_page_url)), static_cast(j_icon_types), static_cast(j_desired_size_in_pixel), callback_runner, cancelable_task_tracker_.get()); return true; } void FaviconHelper::GetLargestRawFaviconForUrl( JNIEnv* env, jobject obj, jobject j_profile, jstring j_page_url, jintArray j_icon_types, jint j_min_size_threshold_px, jobject j_favicon_image_callback) { Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); DCHECK(profile); if (!profile) return; FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( profile, Profile::EXPLICIT_ACCESS); DCHECK(favicon_service); if (!favicon_service) return; std::vector icon_types; base::android::JavaIntArrayToIntVector(env, j_icon_types, &icon_types); ScopedJavaGlobalRef* j_scoped_favicon_callback = new ScopedJavaGlobalRef(); j_scoped_favicon_callback->Reset(env, j_favicon_image_callback); favicon_base::FaviconRawBitmapCallback callback_runner = base::Bind(&OnFaviconRawBitmapResultAvailable, base::Owned(j_scoped_favicon_callback)); favicon_service->GetLargestRawFaviconForPageURL( GURL(ConvertJavaStringToUTF16(env, j_page_url)), icon_types, static_cast(j_min_size_threshold_px), callback_runner, cancelable_task_tracker_.get()); } ScopedJavaLocalRef FaviconHelper::GetSyncedFaviconImageForURL( JNIEnv* env, jobject obj, jobject jprofile, jstring j_page_url) { Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile); DCHECK(profile); std::string page_url = ConvertJavaStringToUTF8(env, j_page_url); ProfileSyncService* sync_service = ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); DCHECK(sync_service); scoped_refptr favicon_png; browser_sync::OpenTabsUIDelegate* open_tabs = sync_service->GetOpenTabsUIDelegate(); DCHECK(open_tabs); if (!open_tabs->GetSyncedFaviconForPageURL(page_url, &favicon_png)) return ScopedJavaLocalRef(); // Convert favicon_image_result to java objects. gfx::Image favicon_image = gfx::Image::CreateFrom1xPNGBytes(favicon_png); SkBitmap favicon_bitmap = favicon_image.AsBitmap(); ScopedJavaLocalRef j_favicon_bitmap; if (favicon_bitmap.isNull()) return ScopedJavaLocalRef(); return gfx::ConvertToJavaBitmap(&favicon_bitmap); } FaviconHelper::~FaviconHelper() {} static jint GetDominantColorForBitmap(JNIEnv* env, jclass clazz, jobject bitmap) { if (!bitmap) return 0; gfx::JavaBitmap bitmap_lock(bitmap); SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(bitmap_lock); return color_utils::CalculateKMeanColorOfBitmap(skbitmap); } // static bool FaviconHelper::RegisterFaviconHelper(JNIEnv* env) { return RegisterNativesImpl(env); }