Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / android / favicon_helper.cc
blob67f0c3ef47e279428af07f53a8a1ee01a0aa090e
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"
7 #include <jni.h>
9 #include <vector>
11 #include "base/android/jni_android.h"
12 #include "base/android/jni_array.h"
13 #include "base/android/jni_string.h"
14 #include "base/android/scoped_java_ref.h"
15 #include "base/bind.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "chrome/browser/favicon/favicon_service_factory.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/profiles/profile_android.h"
21 #include "chrome/browser/sync/profile_sync_service.h"
22 #include "chrome/browser/sync/profile_sync_service_factory.h"
23 #include "components/favicon/core/favicon_service.h"
24 #include "components/favicon_base/favicon_util.h"
25 #include "components/favicon_base/select_favicon_frames.h"
26 #include "components/sync_driver/open_tabs_ui_delegate.h"
27 #include "content/public/browser/web_contents.h"
28 #include "jni/FaviconHelper_jni.h"
29 #include "third_party/skia/include/core/SkBitmap.h"
30 #include "ui/gfx/android/java_bitmap.h"
31 #include "ui/gfx/codec/png_codec.h"
32 #include "ui/gfx/color_analysis.h"
33 #include "ui/gfx/color_utils.h"
34 #include "ui/gfx/favicon_size.h"
35 #include "ui/gfx/image/image_skia.h"
37 using base::android::ScopedJavaGlobalRef;
38 using base::android::ScopedJavaLocalRef;
39 using base::android::AttachCurrentThread;
40 using base::android::ConvertJavaStringToUTF16;
41 using base::android::ConvertJavaStringToUTF8;
42 using base::android::ConvertUTF8ToJavaString;
44 namespace {
46 void OnLocalFaviconAvailable(
47 ScopedJavaGlobalRef<jobject>* j_favicon_image_callback,
48 const favicon_base::FaviconRawBitmapResult& result) {
49 JNIEnv* env = AttachCurrentThread();
51 // Convert favicon_image_result to java objects.
52 ScopedJavaLocalRef<jstring> j_icon_url =
53 ConvertUTF8ToJavaString(env, result.icon_url.spec());
54 ScopedJavaLocalRef<jobject> j_favicon_bitmap;
55 if (result.is_valid()) {
56 SkBitmap favicon_bitmap;
57 gfx::PNGCodec::Decode(result.bitmap_data->front(),
58 result.bitmap_data->size(),
59 &favicon_bitmap);
60 if (!favicon_bitmap.isNull())
61 j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap);
64 // Call java side OnLocalFaviconAvailable method.
65 Java_FaviconImageCallback_onFaviconAvailable(env,
66 j_favicon_image_callback->obj(),
67 j_favicon_bitmap.obj(),
68 j_icon_url.obj());
71 void OnFaviconDownloaded(
72 const ScopedJavaGlobalRef<jobject>& j_availability_callback,
73 Profile* profile,
74 const GURL& page_url,
75 int download_request_id,
76 int http_status_code,
77 const GURL& image_url,
78 const std::vector<SkBitmap>& bitmaps,
79 const std::vector<gfx::Size>& original_sizes) {
80 bool success = !bitmaps.empty();
81 if (success) {
82 gfx::Image image = gfx::Image(CreateFaviconImageSkia(bitmaps,
83 original_sizes,
84 gfx::kFaviconSize,
85 nullptr));
86 favicon_base::SetFaviconColorSpace(&image);
87 favicon::FaviconService* service = FaviconServiceFactory::GetForProfile(
88 profile, ServiceAccessType::IMPLICIT_ACCESS);
89 service->SetFavicons(page_url, image_url, favicon_base::FAVICON, image);
92 JNIEnv* env = AttachCurrentThread();
93 Java_FaviconAvailabilityCallback_onFaviconAvailabilityChecked(
94 env, j_availability_callback.obj(), success);
97 void OnFaviconImageResultAvailable(
98 const ScopedJavaGlobalRef<jobject>& j_availability_callback,
99 Profile* profile,
100 content::WebContents* web_contents,
101 const GURL& page_url,
102 const GURL& favicon_url,
103 const favicon_base::FaviconImageResult& result) {
104 // If there already is a favicon, return immediately.
105 if (!result.image.IsEmpty()) {
106 JNIEnv* env = AttachCurrentThread();
107 Java_FaviconAvailabilityCallback_onFaviconAvailabilityChecked(
108 env, j_availability_callback.obj(), false);
109 return;
112 web_contents->DownloadImage(favicon_url, true, 0, false,
113 base::Bind(OnFaviconDownloaded,
114 j_availability_callback,
115 profile, page_url));
118 } // namespace
120 static jlong Init(JNIEnv* env, const JavaParamRef<jclass>& clazz) {
121 return reinterpret_cast<intptr_t>(new FaviconHelper());
124 FaviconHelper::FaviconHelper() {
125 cancelable_task_tracker_.reset(new base::CancelableTaskTracker());
128 void FaviconHelper::Destroy(JNIEnv* env, jobject obj) {
129 delete this;
132 jboolean FaviconHelper::GetLocalFaviconImageForURL(
133 JNIEnv* env,
134 jobject obj,
135 jobject j_profile,
136 jstring j_page_url,
137 jint j_icon_types,
138 jint j_desired_size_in_pixel,
139 jobject j_favicon_image_callback) {
140 Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
141 DCHECK(profile);
142 if (!profile)
143 return false;
145 favicon::FaviconService* favicon_service =
146 FaviconServiceFactory::GetForProfile(profile,
147 ServiceAccessType::EXPLICIT_ACCESS);
148 DCHECK(favicon_service);
149 if (!favicon_service)
150 return false;
152 ScopedJavaGlobalRef<jobject>* j_scoped_favicon_callback =
153 new ScopedJavaGlobalRef<jobject>();
154 j_scoped_favicon_callback->Reset(env, j_favicon_image_callback);
156 favicon_base::FaviconRawBitmapCallback callback_runner = base::Bind(
157 &OnLocalFaviconAvailable, base::Owned(j_scoped_favicon_callback));
159 favicon_service->GetRawFaviconForPageURL(
160 GURL(ConvertJavaStringToUTF16(env, j_page_url)),
161 static_cast<int>(j_icon_types),
162 static_cast<int>(j_desired_size_in_pixel),
163 callback_runner,
164 cancelable_task_tracker_.get());
166 return true;
169 ScopedJavaLocalRef<jobject> FaviconHelper::GetSyncedFaviconImageForURL(
170 JNIEnv* env,
171 jobject obj,
172 jobject jprofile,
173 jstring j_page_url) {
174 Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
175 DCHECK(profile);
177 std::string page_url = ConvertJavaStringToUTF8(env, j_page_url);
179 ProfileSyncService* sync_service =
180 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
181 DCHECK(sync_service);
183 scoped_refptr<base::RefCountedMemory> favicon_png;
184 sync_driver::OpenTabsUIDelegate* open_tabs =
185 sync_service->GetOpenTabsUIDelegate();
186 DCHECK(open_tabs);
188 if (!open_tabs->GetSyncedFaviconForPageURL(page_url, &favicon_png))
189 return ScopedJavaLocalRef<jobject>();
191 // Convert favicon_image_result to java objects.
192 gfx::Image favicon_image = gfx::Image::CreateFrom1xPNGBytes(favicon_png);
193 SkBitmap favicon_bitmap = favicon_image.AsBitmap();
195 ScopedJavaLocalRef<jobject> j_favicon_bitmap;
196 if (favicon_bitmap.isNull())
197 return ScopedJavaLocalRef<jobject>();
199 return gfx::ConvertToJavaBitmap(&favicon_bitmap);
202 void FaviconHelper::EnsureFaviconIsAvailable(
203 JNIEnv* env,
204 jobject obj,
205 jobject j_profile,
206 jobject j_web_contents,
207 jstring j_page_url,
208 jstring j_favicon_url,
209 jobject j_availability_callback) {
210 Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
211 DCHECK(profile);
212 content::WebContents* web_contents =
213 content::WebContents::FromJavaWebContents(j_web_contents);
214 DCHECK(web_contents);
215 GURL page_url(ConvertJavaStringToUTF8(env, j_page_url));
216 GURL favicon_url(ConvertJavaStringToUTF8(env, j_favicon_url));
218 // TODO(treib): Optimize this by creating a FaviconService::HasFavicon method
219 // so that we don't have to actually get the image.
220 ScopedJavaGlobalRef<jobject> j_scoped_callback(env, j_availability_callback);
221 favicon_base::FaviconImageCallback callback_runner =
222 base::Bind(&OnFaviconImageResultAvailable, j_scoped_callback,
223 profile, web_contents, page_url, favicon_url);
224 favicon::FaviconService* service = FaviconServiceFactory::GetForProfile(
225 profile, ServiceAccessType::IMPLICIT_ACCESS);
226 service->GetFaviconImageForPageURL(page_url, callback_runner,
227 cancelable_task_tracker_.get());
230 FaviconHelper::~FaviconHelper() {}
232 static jint GetDominantColorForBitmap(JNIEnv* env,
233 const JavaParamRef<jclass>& clazz,
234 const JavaParamRef<jobject>& bitmap) {
235 if (!bitmap)
236 return 0;
238 gfx::JavaBitmap bitmap_lock(bitmap);
239 SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(bitmap_lock);
240 return color_utils::CalculateKMeanColorOfBitmap(skbitmap);
243 // static
244 bool FaviconHelper::RegisterFaviconHelper(JNIEnv* env) {
245 return RegisterNativesImpl(env);