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_string.h" 11 #include "base/android/scoped_java_ref.h" 12 #include "base/bind.h" 13 #include "base/strings/string_util.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "chrome/browser/favicon/favicon_service.h" 16 #include "chrome/browser/favicon/favicon_service_factory.h" 17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile_android.h" 19 #include "chrome/browser/sync/open_tabs_ui_delegate.h" 20 #include "chrome/browser/sync/profile_sync_service.h" 21 #include "chrome/browser/sync/profile_sync_service_factory.h" 22 #include "chrome/browser/sync/profile_sync_service_factory.h" 23 #include "jni/FaviconHelper_jni.h" 24 #include "third_party/skia/include/core/SkBitmap.h" 25 #include "ui/gfx/android/java_bitmap.h" 26 #include "ui/gfx/color_analysis.h" 27 #include "ui/gfx/color_utils.h" 28 29 using base::android::ScopedJavaGlobalRef; 30 using base::android::ScopedJavaLocalRef; 31 using base::android::AttachCurrentThread; 32 using base::android::ConvertJavaStringToUTF16; 33 using base::android::ConvertJavaStringToUTF8; 34 using base::android::ConvertUTF8ToJavaString; 35 36 namespace { 37 38 void OnLocalFaviconAvailable( 39 ScopedJavaGlobalRef<jobject>* j_favicon_image_callback, 40 const chrome::FaviconImageResult& favicon_image_result) { 41 JNIEnv* env = AttachCurrentThread(); 42 43 // Convert favicon_image_result to java objects. 44 ScopedJavaLocalRef<jstring> j_icon_url = 45 ConvertUTF8ToJavaString(env, favicon_image_result.icon_url.spec()); 46 SkBitmap favicon_bitmap = favicon_image_result.image.AsBitmap(); 47 ScopedJavaLocalRef<jobject> j_favicon_bitmap; 48 if (!favicon_bitmap.isNull()) 49 j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap); 50 51 // Call java side OnLocalFaviconAvailable method. 52 Java_FaviconImageCallback_onFaviconAvailable(env, 53 j_favicon_image_callback->obj(), 54 j_favicon_bitmap.obj(), 55 j_icon_url.obj()); 56 } 57 58 } // namespace 59 60 static jlong Init(JNIEnv* env, jclass clazz) { 61 return reinterpret_cast<intptr_t>(new FaviconHelper()); 62 } 63 64 FaviconHelper::FaviconHelper() { 65 cancelable_task_tracker_.reset(new CancelableTaskTracker()); 66 } 67 68 void FaviconHelper::Destroy(JNIEnv* env, jobject obj) { 69 delete this; 70 } 71 72 jboolean FaviconHelper::GetLocalFaviconImageForURL( 73 JNIEnv* env, 74 jobject obj, 75 jobject j_profile, 76 jstring j_page_url, 77 jint j_icon_types, 78 jint j_desired_size_in_dip, 79 jobject j_favicon_image_callback) { 80 Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); 81 DCHECK(profile); 82 if (!profile) 83 return false; 84 85 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( 86 profile, Profile::EXPLICIT_ACCESS); 87 DCHECK(favicon_service); 88 if (!favicon_service) 89 return false; 90 91 FaviconService::FaviconForURLParams params( 92 GURL(ConvertJavaStringToUTF16(env, j_page_url)), 93 static_cast<int>(j_icon_types), 94 static_cast<int>(j_desired_size_in_dip)); 95 96 ScopedJavaGlobalRef<jobject>* j_scoped_favicon_callback = 97 new ScopedJavaGlobalRef<jobject>(); 98 j_scoped_favicon_callback->Reset(env, j_favicon_image_callback); 99 100 FaviconService::FaviconImageCallback callback_runner = base::Bind( 101 &OnLocalFaviconAvailable, base::Owned(j_scoped_favicon_callback)); 102 103 favicon_service->GetFaviconImageForURL( 104 params, callback_runner, 105 cancelable_task_tracker_.get()); 106 107 return true; 108 } 109 110 ScopedJavaLocalRef<jobject> FaviconHelper::GetSyncedFaviconImageForURL( 111 JNIEnv* env, 112 jobject obj, 113 jobject jprofile, 114 jstring j_page_url) { 115 Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile); 116 DCHECK(profile); 117 118 std::string page_url = ConvertJavaStringToUTF8(env, j_page_url); 119 120 ProfileSyncService* sync_service = 121 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); 122 DCHECK(sync_service); 123 124 scoped_refptr<base::RefCountedMemory> favicon_png; 125 browser_sync::OpenTabsUIDelegate* open_tabs = 126 sync_service->GetOpenTabsUIDelegate(); 127 DCHECK(open_tabs); 128 129 if (!open_tabs->GetSyncedFaviconForPageURL(page_url, &favicon_png)) 130 return ScopedJavaLocalRef<jobject>(); 131 132 // Convert favicon_image_result to java objects. 133 gfx::Image favicon_image = gfx::Image::CreateFrom1xPNGBytes( 134 favicon_png->front(), favicon_png->size()); 135 SkBitmap favicon_bitmap = favicon_image.AsBitmap(); 136 137 ScopedJavaLocalRef<jobject> j_favicon_bitmap; 138 if (favicon_bitmap.isNull()) 139 return ScopedJavaLocalRef<jobject>(); 140 141 return gfx::ConvertToJavaBitmap(&favicon_bitmap); 142 } 143 144 jint FaviconHelper::GetDominantColorForBitmap(JNIEnv* env, 145 jobject obj, 146 jobject bitmap) { 147 if (!bitmap) 148 return 0; 149 150 gfx::JavaBitmap bitmap_lock(bitmap); 151 SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(bitmap_lock); 152 skbitmap.setImmutable(); 153 scoped_refptr<base::RefCountedMemory> png_data = 154 gfx::Image::CreateFrom1xBitmap(skbitmap).As1xPNGBytes(); 155 uint32_t max_brightness = 665; 156 uint32_t min_darkness = 100; 157 color_utils::GridSampler sampler; 158 return color_utils::CalculateKMeanColorOfPNG( 159 png_data, min_darkness, max_brightness, &sampler); 160 } 161 162 FaviconHelper::~FaviconHelper() {} 163 164 // static 165 bool FaviconHelper::RegisterFaviconHelper(JNIEnv* env) { 166 return RegisterNativesImpl(env); 167 } 168