favicon_helper.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/android/favicon_helper.h" 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <jni.h> 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/android/jni_android.h" 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/android/jni_string.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/android/scoped_java_ref.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/bind.h" 1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/strings/string_util.h" 1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/favicon/favicon_service.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/favicon/favicon_service_factory.h" 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/profiles/profile.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/profiles/profile_android.h" 1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/sync/glue/session_model_associator.h" 2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/sync/glue/session_model_associator.h" 2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h" 2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h" 2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h" 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "jni/FaviconHelper_jni.h" 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "third_party/skia/include/core/SkBitmap.h" 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/android/java_bitmap.h" 274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/gfx/color_analysis.h" 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/gfx/color_utils.h" 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::android::ScopedJavaGlobalRef; 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::android::ScopedJavaLocalRef; 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::android::AttachCurrentThread; 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::android::ConvertJavaStringToUTF16; 3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)using base::android::ConvertJavaStringToUTF8; 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::android::ConvertUTF8ToJavaString; 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace { 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void OnLocalFaviconAvailable( 4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedJavaGlobalRef<jobject>* j_favicon_image_callback, 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const chrome::FaviconImageResult& favicon_image_result) { 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch JNIEnv* env = AttachCurrentThread(); 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Convert favicon_image_result to java objects. 4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedJavaLocalRef<jstring> j_icon_url = 4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ConvertUTF8ToJavaString(env, favicon_image_result.icon_url.spec()); 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkBitmap favicon_bitmap = favicon_image_result.image.AsBitmap(); 4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedJavaLocalRef<jobject> j_favicon_bitmap; 4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!favicon_bitmap.isNull()) 5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap); 5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Call java side OnLocalFaviconAvailable method. 5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Java_FaviconImageCallback_onFaviconAvailable(env, 5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_favicon_image_callback->obj(), 5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_favicon_bitmap.obj(), 5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_icon_url.obj()); 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic jint Init(JNIEnv* env, jclass clazz) { 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return reinterpret_cast<jint>(new FaviconHelper()); 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochFaviconHelper::FaviconHelper() { 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch cancelable_task_tracker_.reset(new CancelableTaskTracker()); 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid FaviconHelper::Destroy(JNIEnv* env, jobject obj) { 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delete this; 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)jboolean FaviconHelper::GetLocalFaviconImageForURL( 7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) JNIEnv* env, 7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jobject obj, 7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jobject j_profile, 7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jstring j_page_url, 7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jint j_icon_types, 7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jint j_desired_size_in_dip, 8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jobject j_favicon_image_callback) { 8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(profile); 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!profile) 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch profile, Profile::EXPLICIT_ACCESS); 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(favicon_service); 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!favicon_service) 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FaviconService::FaviconForURLParams params( 9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) profile, 9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) GURL(ConvertJavaStringToUTF16(env, j_page_url)), 9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) static_cast<int>(j_icon_types), 9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) static_cast<int>(j_desired_size_in_dip)); 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ScopedJavaGlobalRef<jobject>* j_scoped_favicon_callback = 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch new ScopedJavaGlobalRef<jobject>(); 10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_scoped_favicon_callback->Reset(env, j_favicon_image_callback); 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FaviconService::FaviconImageCallback callback_runner = base::Bind( 10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) &OnLocalFaviconAvailable, base::Owned(j_scoped_favicon_callback)); 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch favicon_service->GetFaviconImageForURL( 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch params, callback_runner, 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch cancelable_task_tracker_.get()); 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)ScopedJavaLocalRef<jobject> FaviconHelper::GetSyncedFaviconImageForURL( 11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) JNIEnv* env, 11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jobject obj, 11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jobject jprofile, 11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jstring j_page_url) { 11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile); 11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK(profile); 11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string page_url = ConvertJavaStringToUTF8(env, j_page_url); 12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ProfileSyncService* sync_service = 12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); 12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK(sync_service); 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_refptr<base::RefCountedMemory> favicon_png; 12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) browser_sync::SessionModelAssociator* associator = 12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) sync_service->GetSessionModelAssociator(); 12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK(associator); 13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!associator->GetSyncedFaviconForPageURL(page_url, &favicon_png)) 13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return ScopedJavaLocalRef<jobject>(); 13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Convert favicon_image_result to java objects. 13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Image favicon_image = gfx::Image::CreateFrom1xPNGBytes( 13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) favicon_png->front(), favicon_png->size()); 13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) SkBitmap favicon_bitmap = favicon_image.AsBitmap(); 13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedJavaLocalRef<jobject> j_favicon_bitmap; 14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (favicon_bitmap.isNull()) 14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return ScopedJavaLocalRef<jobject>(); 14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return gfx::ConvertToJavaBitmap(&favicon_bitmap); 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)jint FaviconHelper::GetDominantColorForBitmap(JNIEnv* env, 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) jobject obj, 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) jobject bitmap) { 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!bitmap) 1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return 0; 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::JavaBitmap bitmap_lock(bitmap); 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(bitmap_lock); 1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) skbitmap.setImmutable(); 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_refptr<base::RefCountedMemory> png_data = 1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Image::CreateFrom1xBitmap(skbitmap).As1xPNGBytes(); 1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uint32_t max_brightness = 665; 1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uint32_t min_darkness = 100; 1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) color_utils::GridSampler sampler; 1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return color_utils::CalculateKMeanColorOfPNG( 1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) png_data, min_darkness, max_brightness, &sampler); 1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)FaviconHelper::~FaviconHelper() {} 16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool FaviconHelper::RegisterFaviconHelper(JNIEnv* env) { 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return RegisterNativesImpl(env); 169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 170