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