favicon_helper.cc revision f2477e01787aa58f445919b809d89e252beef54f
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" 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/sync/open_tabs_ui_delegate.h" 2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h" 2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h" 2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h" 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "jni/FaviconHelper_jni.h" 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "third_party/skia/include/core/SkBitmap.h" 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/android/java_bitmap.h" 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/gfx/color_analysis.h" 274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/gfx/color_utils.h" 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::android::ScopedJavaGlobalRef; 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::android::ScopedJavaLocalRef; 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::android::AttachCurrentThread; 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::android::ConvertJavaStringToUTF16; 3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)using base::android::ConvertJavaStringToUTF8; 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::android::ConvertUTF8ToJavaString; 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace { 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void OnLocalFaviconAvailable( 3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedJavaGlobalRef<jobject>* j_favicon_image_callback, 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const chrome::FaviconImageResult& favicon_image_result) { 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch JNIEnv* env = AttachCurrentThread(); 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Convert favicon_image_result to java objects. 4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedJavaLocalRef<jstring> j_icon_url = 4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ConvertUTF8ToJavaString(env, favicon_image_result.icon_url.spec()); 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkBitmap favicon_bitmap = favicon_image_result.image.AsBitmap(); 4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedJavaLocalRef<jobject> j_favicon_bitmap; 4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!favicon_bitmap.isNull()) 4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap); 5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Call java side OnLocalFaviconAvailable method. 5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Java_FaviconImageCallback_onFaviconAvailable(env, 5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_favicon_image_callback->obj(), 5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_favicon_bitmap.obj(), 5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_icon_url.obj()); 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static jlong Init(JNIEnv* env, jclass clazz) { 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return reinterpret_cast<intptr_t>(new FaviconHelper()); 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochFaviconHelper::FaviconHelper() { 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch cancelable_task_tracker_.reset(new CancelableTaskTracker()); 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid FaviconHelper::Destroy(JNIEnv* env, jobject obj) { 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delete this; 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)jboolean FaviconHelper::GetLocalFaviconImageForURL( 7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) JNIEnv* env, 7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jobject obj, 7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jobject j_profile, 7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jstring j_page_url, 7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jint j_icon_types, 7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jint j_desired_size_in_dip, 7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jobject j_favicon_image_callback) { 8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(profile); 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!profile) 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch profile, Profile::EXPLICIT_ACCESS); 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(favicon_service); 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!favicon_service) 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FaviconService::FaviconForURLParams params( 9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) GURL(ConvertJavaStringToUTF16(env, j_page_url)), 9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) static_cast<int>(j_icon_types), 9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) static_cast<int>(j_desired_size_in_dip)); 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ScopedJavaGlobalRef<jobject>* j_scoped_favicon_callback = 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch new ScopedJavaGlobalRef<jobject>(); 9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_scoped_favicon_callback->Reset(env, j_favicon_image_callback); 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FaviconService::FaviconImageCallback callback_runner = base::Bind( 10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) &OnLocalFaviconAvailable, base::Owned(j_scoped_favicon_callback)); 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch favicon_service->GetFaviconImageForURL( 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch params, callback_runner, 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch cancelable_task_tracker_.get()); 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)ScopedJavaLocalRef<jobject> FaviconHelper::GetSyncedFaviconImageForURL( 11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) JNIEnv* env, 11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jobject obj, 11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jobject jprofile, 11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jstring j_page_url) { 11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile); 11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK(profile); 11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string page_url = ConvertJavaStringToUTF8(env, j_page_url); 11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ProfileSyncService* sync_service = 12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK(sync_service); 12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_refptr<base::RefCountedMemory> favicon_png; 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser_sync::OpenTabsUIDelegate* open_tabs = 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) sync_service->GetOpenTabsUIDelegate(); 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(open_tabs); 12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!open_tabs->GetSyncedFaviconForPageURL(page_url, &favicon_png)) 13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return ScopedJavaLocalRef<jobject>(); 13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Convert favicon_image_result to java objects. 13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Image favicon_image = gfx::Image::CreateFrom1xPNGBytes( 13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) favicon_png->front(), favicon_png->size()); 13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) SkBitmap favicon_bitmap = favicon_image.AsBitmap(); 13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedJavaLocalRef<jobject> j_favicon_bitmap; 13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (favicon_bitmap.isNull()) 13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return ScopedJavaLocalRef<jobject>(); 14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return gfx::ConvertToJavaBitmap(&favicon_bitmap); 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)jint FaviconHelper::GetDominantColorForBitmap(JNIEnv* env, 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) jobject obj, 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) jobject bitmap) { 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!bitmap) 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return 0; 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::JavaBitmap bitmap_lock(bitmap); 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(bitmap_lock); 1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) skbitmap.setImmutable(); 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_refptr<base::RefCountedMemory> png_data = 1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Image::CreateFrom1xBitmap(skbitmap).As1xPNGBytes(); 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uint32_t max_brightness = 665; 1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uint32_t min_darkness = 100; 1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) color_utils::GridSampler sampler; 1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return color_utils::CalculateKMeanColorOfPNG( 1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) png_data, min_darkness, max_brightness, &sampler); 1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)FaviconHelper::~FaviconHelper() {} 16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool FaviconHelper::RegisterFaviconHelper(JNIEnv* env) { 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return RegisterNativesImpl(env); 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 168