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.
5 #include "chrome/browser/android/favicon_helper.h"
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_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 "components/favicon/core/favicon_service.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"
31 using base::android::ScopedJavaGlobalRef
;
32 using base::android::ScopedJavaLocalRef
;
33 using base::android::AttachCurrentThread
;
34 using base::android::ConvertJavaStringToUTF16
;
35 using base::android::ConvertJavaStringToUTF8
;
36 using base::android::ConvertUTF8ToJavaString
;
40 void OnLocalFaviconAvailable(
41 ScopedJavaGlobalRef
<jobject
>* j_favicon_image_callback
,
42 const favicon_base::FaviconRawBitmapResult
& result
) {
43 JNIEnv
* env
= AttachCurrentThread();
45 // Convert favicon_image_result to java objects.
46 ScopedJavaLocalRef
<jstring
> j_icon_url
=
47 ConvertUTF8ToJavaString(env
, result
.icon_url
.spec());
48 ScopedJavaLocalRef
<jobject
> j_favicon_bitmap
;
49 if (result
.is_valid()) {
50 SkBitmap favicon_bitmap
;
51 gfx::PNGCodec::Decode(result
.bitmap_data
->front(),
52 result
.bitmap_data
->size(),
54 if (!favicon_bitmap
.isNull())
55 j_favicon_bitmap
= gfx::ConvertToJavaBitmap(&favicon_bitmap
);
58 // Call java side OnLocalFaviconAvailable method.
59 Java_FaviconImageCallback_onFaviconAvailable(env
,
60 j_favicon_image_callback
->obj(),
61 j_favicon_bitmap
.obj(),
65 void OnFaviconRawBitmapResultAvailable(
66 ScopedJavaGlobalRef
<jobject
>* j_favicon_image_callback
,
67 const favicon_base::FaviconRawBitmapResult
& favicon_bitmap_result
) {
68 JNIEnv
* env
= AttachCurrentThread();
70 // Convert favicon_image_result to java objects.
71 ScopedJavaLocalRef
<jstring
> j_icon_url
=
72 ConvertUTF8ToJavaString(env
, favicon_bitmap_result
.icon_url
.spec());
74 SkBitmap favicon_bitmap
;
75 if (favicon_bitmap_result
.is_valid()) {
76 gfx::PNGCodec::Decode(favicon_bitmap_result
.bitmap_data
->front(),
77 favicon_bitmap_result
.bitmap_data
->size(),
80 ScopedJavaLocalRef
<jobject
> j_favicon_bitmap
;
81 if (!favicon_bitmap
.isNull())
82 j_favicon_bitmap
= gfx::ConvertToJavaBitmap(&favicon_bitmap
);
84 // Call java side OnLocalFaviconAvailable method.
85 Java_FaviconImageCallback_onFaviconAvailable(env
,
86 j_favicon_image_callback
->obj(),
87 j_favicon_bitmap
.obj(),
93 static jlong
Init(JNIEnv
* env
, jclass clazz
) {
94 return reinterpret_cast<intptr_t>(new FaviconHelper());
97 FaviconHelper::FaviconHelper() {
98 cancelable_task_tracker_
.reset(new base::CancelableTaskTracker());
101 void FaviconHelper::Destroy(JNIEnv
* env
, jobject obj
) {
105 jboolean
FaviconHelper::GetLocalFaviconImageForURL(
111 jint j_desired_size_in_pixel
,
112 jobject j_favicon_image_callback
) {
113 Profile
* profile
= ProfileAndroid::FromProfileAndroid(j_profile
);
118 favicon::FaviconService
* favicon_service
=
119 FaviconServiceFactory::GetForProfile(profile
,
120 ServiceAccessType::EXPLICIT_ACCESS
);
121 DCHECK(favicon_service
);
122 if (!favicon_service
)
125 ScopedJavaGlobalRef
<jobject
>* j_scoped_favicon_callback
=
126 new ScopedJavaGlobalRef
<jobject
>();
127 j_scoped_favicon_callback
->Reset(env
, j_favicon_image_callback
);
129 favicon_base::FaviconRawBitmapCallback callback_runner
= base::Bind(
130 &OnLocalFaviconAvailable
, base::Owned(j_scoped_favicon_callback
));
132 favicon_service
->GetRawFaviconForPageURL(
133 GURL(ConvertJavaStringToUTF16(env
, j_page_url
)),
134 static_cast<int>(j_icon_types
),
135 static_cast<int>(j_desired_size_in_pixel
),
137 cancelable_task_tracker_
.get());
142 void FaviconHelper::GetLargestRawFaviconForUrl(
147 jintArray j_icon_types
,
148 jint j_min_size_threshold_px
,
149 jobject j_favicon_image_callback
) {
150 Profile
* profile
= ProfileAndroid::FromProfileAndroid(j_profile
);
155 favicon::FaviconService
* favicon_service
=
156 FaviconServiceFactory::GetForProfile(profile
,
157 ServiceAccessType::EXPLICIT_ACCESS
);
158 DCHECK(favicon_service
);
159 if (!favicon_service
)
162 std::vector
<int> icon_types
;
163 base::android::JavaIntArrayToIntVector(env
, j_icon_types
, &icon_types
);
165 ScopedJavaGlobalRef
<jobject
>* j_scoped_favicon_callback
=
166 new ScopedJavaGlobalRef
<jobject
>();
167 j_scoped_favicon_callback
->Reset(env
, j_favicon_image_callback
);
169 favicon_base::FaviconRawBitmapCallback callback_runner
=
170 base::Bind(&OnFaviconRawBitmapResultAvailable
,
171 base::Owned(j_scoped_favicon_callback
));
172 favicon_service
->GetLargestRawFaviconForPageURL(
173 GURL(ConvertJavaStringToUTF16(env
, j_page_url
)),
175 static_cast<int>(j_min_size_threshold_px
),
177 cancelable_task_tracker_
.get());
180 ScopedJavaLocalRef
<jobject
> FaviconHelper::GetSyncedFaviconImageForURL(
184 jstring j_page_url
) {
185 Profile
* profile
= ProfileAndroid::FromProfileAndroid(jprofile
);
188 std::string page_url
= ConvertJavaStringToUTF8(env
, j_page_url
);
190 ProfileSyncService
* sync_service
=
191 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile
);
192 DCHECK(sync_service
);
194 scoped_refptr
<base::RefCountedMemory
> favicon_png
;
195 browser_sync::OpenTabsUIDelegate
* open_tabs
=
196 sync_service
->GetOpenTabsUIDelegate();
199 if (!open_tabs
->GetSyncedFaviconForPageURL(page_url
, &favicon_png
))
200 return ScopedJavaLocalRef
<jobject
>();
202 // Convert favicon_image_result to java objects.
203 gfx::Image favicon_image
= gfx::Image::CreateFrom1xPNGBytes(favicon_png
);
204 SkBitmap favicon_bitmap
= favicon_image
.AsBitmap();
206 ScopedJavaLocalRef
<jobject
> j_favicon_bitmap
;
207 if (favicon_bitmap
.isNull())
208 return ScopedJavaLocalRef
<jobject
>();
210 return gfx::ConvertToJavaBitmap(&favicon_bitmap
);
213 FaviconHelper::~FaviconHelper() {}
215 static jint
GetDominantColorForBitmap(JNIEnv
* env
,
221 gfx::JavaBitmap
bitmap_lock(bitmap
);
222 SkBitmap skbitmap
= gfx::CreateSkBitmapFromJavaBitmap(bitmap_lock
);
223 return color_utils::CalculateKMeanColorOfBitmap(skbitmap
);
227 bool FaviconHelper::RegisterFaviconHelper(JNIEnv
* env
) {
228 return RegisterNativesImpl(env
);