favicon_helper.cc revision 010d83a9304c5a91596085d917d248abff47903a
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/android/favicon_helper.h" 6 7#include <jni.h> 8 9#include "base/android/jni_android.h" 10#include "base/android/jni_array.h" 11#include "base/android/jni_string.h" 12#include "base/android/scoped_java_ref.h" 13#include "base/bind.h" 14#include "base/strings/string_util.h" 15#include "base/strings/utf_string_conversions.h" 16#include "chrome/browser/favicon/favicon_service.h" 17#include "chrome/browser/favicon/favicon_service_factory.h" 18#include "chrome/browser/profiles/profile.h" 19#include "chrome/browser/profiles/profile_android.h" 20#include "chrome/browser/sync/open_tabs_ui_delegate.h" 21#include "chrome/browser/sync/profile_sync_service.h" 22#include "chrome/browser/sync/profile_sync_service_factory.h" 23#include "chrome/browser/sync/profile_sync_service_factory.h" 24#include "jni/FaviconHelper_jni.h" 25#include "third_party/skia/include/core/SkBitmap.h" 26#include "ui/gfx/android/java_bitmap.h" 27#include "ui/gfx/codec/png_codec.h" 28#include "ui/gfx/color_analysis.h" 29#include "ui/gfx/color_utils.h" 30 31using base::android::ScopedJavaGlobalRef; 32using base::android::ScopedJavaLocalRef; 33using base::android::AttachCurrentThread; 34using base::android::ConvertJavaStringToUTF16; 35using base::android::ConvertJavaStringToUTF8; 36using base::android::ConvertUTF8ToJavaString; 37 38namespace { 39 40void OnLocalFaviconAvailable( 41 ScopedJavaGlobalRef<jobject>* j_favicon_image_callback, 42 const favicon_base::FaviconImageResult& favicon_image_result) { 43 JNIEnv* env = AttachCurrentThread(); 44 45 // Convert favicon_image_result to java objects. 46 ScopedJavaLocalRef<jstring> j_icon_url = 47 ConvertUTF8ToJavaString(env, favicon_image_result.icon_url.spec()); 48 SkBitmap favicon_bitmap = favicon_image_result.image.AsBitmap(); 49 ScopedJavaLocalRef<jobject> j_favicon_bitmap; 50 if (!favicon_bitmap.isNull()) 51 j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap); 52 53 // Call java side OnLocalFaviconAvailable method. 54 Java_FaviconImageCallback_onFaviconAvailable(env, 55 j_favicon_image_callback->obj(), 56 j_favicon_bitmap.obj(), 57 j_icon_url.obj()); 58} 59 60void OnFaviconBitmapResultAvailable( 61 ScopedJavaGlobalRef<jobject>* j_favicon_image_callback, 62 const favicon_base::FaviconBitmapResult& favicon_bitmap_result) { 63 JNIEnv* env = AttachCurrentThread(); 64 65 // Convert favicon_image_result to java objects. 66 ScopedJavaLocalRef<jstring> j_icon_url = 67 ConvertUTF8ToJavaString(env, favicon_bitmap_result.icon_url.spec()); 68 69 SkBitmap favicon_bitmap; 70 if (favicon_bitmap_result.is_valid()) { 71 gfx::PNGCodec::Decode(favicon_bitmap_result.bitmap_data->front(), 72 favicon_bitmap_result.bitmap_data->size(), 73 &favicon_bitmap); 74 } 75 ScopedJavaLocalRef<jobject> j_favicon_bitmap; 76 if (!favicon_bitmap.isNull()) 77 j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap); 78 79 // Call java side OnLocalFaviconAvailable method. 80 Java_FaviconImageCallback_onFaviconAvailable(env, 81 j_favicon_image_callback->obj(), 82 j_favicon_bitmap.obj(), 83 j_icon_url.obj()); 84} 85 86} // namespace 87 88static jlong Init(JNIEnv* env, jclass clazz) { 89 return reinterpret_cast<intptr_t>(new FaviconHelper()); 90} 91 92FaviconHelper::FaviconHelper() { 93 cancelable_task_tracker_.reset(new base::CancelableTaskTracker()); 94} 95 96void FaviconHelper::Destroy(JNIEnv* env, jobject obj) { 97 delete this; 98} 99 100jboolean FaviconHelper::GetLocalFaviconImageForURL( 101 JNIEnv* env, 102 jobject obj, 103 jobject j_profile, 104 jstring j_page_url, 105 jint j_icon_types, 106 jint j_desired_size_in_dip, 107 jobject j_favicon_image_callback) { 108 Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); 109 DCHECK(profile); 110 if (!profile) 111 return false; 112 113 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( 114 profile, Profile::EXPLICIT_ACCESS); 115 DCHECK(favicon_service); 116 if (!favicon_service) 117 return false; 118 119 FaviconService::FaviconForURLParams params( 120 GURL(ConvertJavaStringToUTF16(env, j_page_url)), 121 static_cast<int>(j_icon_types), 122 static_cast<int>(j_desired_size_in_dip)); 123 124 ScopedJavaGlobalRef<jobject>* j_scoped_favicon_callback = 125 new ScopedJavaGlobalRef<jobject>(); 126 j_scoped_favicon_callback->Reset(env, j_favicon_image_callback); 127 128 FaviconService::FaviconImageCallback callback_runner = base::Bind( 129 &OnLocalFaviconAvailable, base::Owned(j_scoped_favicon_callback)); 130 131 favicon_service->GetFaviconImageForURL( 132 params, callback_runner, 133 cancelable_task_tracker_.get()); 134 135 return true; 136} 137 138void FaviconHelper::GetLargestRawFaviconForUrl( 139 JNIEnv* env, 140 jobject obj, 141 jobject j_profile, 142 jstring j_page_url, 143 jintArray j_icon_types, 144 jint j_min_size_threshold_px, 145 jobject j_favicon_image_callback) { 146 Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); 147 DCHECK(profile); 148 if (!profile) 149 return; 150 151 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( 152 profile, Profile::EXPLICIT_ACCESS); 153 DCHECK(favicon_service); 154 if (!favicon_service) 155 return; 156 157 std::vector<int> icon_types; 158 base::android::JavaIntArrayToIntVector(env, j_icon_types, &icon_types); 159 160 ScopedJavaGlobalRef<jobject>* j_scoped_favicon_callback = 161 new ScopedJavaGlobalRef<jobject>(); 162 j_scoped_favicon_callback->Reset(env, j_favicon_image_callback); 163 164 FaviconService::FaviconRawCallback callback_runner = base::Bind( 165 &OnFaviconBitmapResultAvailable, base::Owned(j_scoped_favicon_callback)); 166 favicon_service->GetLargestRawFaviconForURL( 167 profile, 168 GURL(ConvertJavaStringToUTF16(env, j_page_url)), 169 icon_types, 170 static_cast<int>(j_min_size_threshold_px), 171 callback_runner, 172 cancelable_task_tracker_.get()); 173} 174 175ScopedJavaLocalRef<jobject> FaviconHelper::GetSyncedFaviconImageForURL( 176 JNIEnv* env, 177 jobject obj, 178 jobject jprofile, 179 jstring j_page_url) { 180 Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile); 181 DCHECK(profile); 182 183 std::string page_url = ConvertJavaStringToUTF8(env, j_page_url); 184 185 ProfileSyncService* sync_service = 186 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); 187 DCHECK(sync_service); 188 189 scoped_refptr<base::RefCountedMemory> favicon_png; 190 browser_sync::OpenTabsUIDelegate* open_tabs = 191 sync_service->GetOpenTabsUIDelegate(); 192 DCHECK(open_tabs); 193 194 if (!open_tabs->GetSyncedFaviconForPageURL(page_url, &favicon_png)) 195 return ScopedJavaLocalRef<jobject>(); 196 197 // Convert favicon_image_result to java objects. 198 gfx::Image favicon_image = gfx::Image::CreateFrom1xPNGBytes(favicon_png); 199 SkBitmap favicon_bitmap = favicon_image.AsBitmap(); 200 201 ScopedJavaLocalRef<jobject> j_favicon_bitmap; 202 if (favicon_bitmap.isNull()) 203 return ScopedJavaLocalRef<jobject>(); 204 205 return gfx::ConvertToJavaBitmap(&favicon_bitmap); 206} 207 208FaviconHelper::~FaviconHelper() {} 209 210static jint GetDominantColorForBitmap(JNIEnv* env, 211 jclass clazz, 212 jobject bitmap) { 213 if (!bitmap) 214 return 0; 215 216 gfx::JavaBitmap bitmap_lock(bitmap); 217 SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(bitmap_lock); 218 return color_utils::CalculateKMeanColorOfBitmap(skbitmap); 219} 220 221// static 222bool FaviconHelper::RegisterFaviconHelper(JNIEnv* env) { 223 return RegisterNativesImpl(env); 224} 225