Home | History | Annotate | Download | only in android
      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 
     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;
     37 
     38 namespace {
     39 
     40 void OnLocalFaviconAvailable(
     41     ScopedJavaGlobalRef<jobject>* j_favicon_image_callback,
     42     const favicon_base::FaviconRawBitmapResult& result) {
     43   JNIEnv* env = AttachCurrentThread();
     44 
     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(),
     53                           &favicon_bitmap);
     54     if (!favicon_bitmap.isNull())
     55       j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap);
     56   }
     57 
     58   // Call java side OnLocalFaviconAvailable method.
     59   Java_FaviconImageCallback_onFaviconAvailable(env,
     60                                                j_favicon_image_callback->obj(),
     61                                                j_favicon_bitmap.obj(),
     62                                                j_icon_url.obj());
     63 }
     64 
     65 void OnFaviconRawBitmapResultAvailable(
     66     ScopedJavaGlobalRef<jobject>* j_favicon_image_callback,
     67     const favicon_base::FaviconRawBitmapResult& favicon_bitmap_result) {
     68   JNIEnv* env = AttachCurrentThread();
     69 
     70   // Convert favicon_image_result to java objects.
     71   ScopedJavaLocalRef<jstring> j_icon_url =
     72       ConvertUTF8ToJavaString(env, favicon_bitmap_result.icon_url.spec());
     73 
     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(),
     78                           &favicon_bitmap);
     79   }
     80   ScopedJavaLocalRef<jobject> j_favicon_bitmap;
     81   if (!favicon_bitmap.isNull())
     82     j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap);
     83 
     84   // Call java side OnLocalFaviconAvailable method.
     85   Java_FaviconImageCallback_onFaviconAvailable(env,
     86                                                j_favicon_image_callback->obj(),
     87                                                j_favicon_bitmap.obj(),
     88                                                j_icon_url.obj());
     89 }
     90 
     91 }  // namespace
     92 
     93 static jlong Init(JNIEnv* env, jclass clazz) {
     94   return reinterpret_cast<intptr_t>(new FaviconHelper());
     95 }
     96 
     97 FaviconHelper::FaviconHelper() {
     98   cancelable_task_tracker_.reset(new base::CancelableTaskTracker());
     99 }
    100 
    101 void FaviconHelper::Destroy(JNIEnv* env, jobject obj) {
    102   delete this;
    103 }
    104 
    105 jboolean FaviconHelper::GetLocalFaviconImageForURL(
    106     JNIEnv* env,
    107     jobject obj,
    108     jobject j_profile,
    109     jstring j_page_url,
    110     jint j_icon_types,
    111     jint j_desired_size_in_pixel,
    112     jobject j_favicon_image_callback) {
    113   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
    114   DCHECK(profile);
    115   if (!profile)
    116     return false;
    117 
    118   FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(
    119       profile, Profile::EXPLICIT_ACCESS);
    120   DCHECK(favicon_service);
    121   if (!favicon_service)
    122     return false;
    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   favicon_base::FaviconRawBitmapCallback callback_runner = base::Bind(
    129       &OnLocalFaviconAvailable, base::Owned(j_scoped_favicon_callback));
    130 
    131   favicon_service->GetRawFaviconForPageURL(
    132       GURL(ConvertJavaStringToUTF16(env, j_page_url)),
    133       static_cast<int>(j_icon_types),
    134       static_cast<int>(j_desired_size_in_pixel),
    135       callback_runner,
    136       cancelable_task_tracker_.get());
    137 
    138   return true;
    139 }
    140 
    141 void FaviconHelper::GetLargestRawFaviconForUrl(
    142     JNIEnv* env,
    143     jobject obj,
    144     jobject j_profile,
    145     jstring j_page_url,
    146     jintArray j_icon_types,
    147     jint j_min_size_threshold_px,
    148     jobject j_favicon_image_callback) {
    149   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
    150   DCHECK(profile);
    151   if (!profile)
    152     return;
    153 
    154   FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(
    155       profile, Profile::EXPLICIT_ACCESS);
    156   DCHECK(favicon_service);
    157   if (!favicon_service)
    158     return;
    159 
    160   std::vector<int> icon_types;
    161   base::android::JavaIntArrayToIntVector(env, j_icon_types, &icon_types);
    162 
    163   ScopedJavaGlobalRef<jobject>* j_scoped_favicon_callback =
    164       new ScopedJavaGlobalRef<jobject>();
    165   j_scoped_favicon_callback->Reset(env, j_favicon_image_callback);
    166 
    167   favicon_base::FaviconRawBitmapCallback callback_runner =
    168       base::Bind(&OnFaviconRawBitmapResultAvailable,
    169                  base::Owned(j_scoped_favicon_callback));
    170   favicon_service->GetLargestRawFaviconForPageURL(
    171       GURL(ConvertJavaStringToUTF16(env, j_page_url)),
    172       icon_types,
    173       static_cast<int>(j_min_size_threshold_px),
    174       callback_runner,
    175       cancelable_task_tracker_.get());
    176 }
    177 
    178 ScopedJavaLocalRef<jobject> FaviconHelper::GetSyncedFaviconImageForURL(
    179     JNIEnv* env,
    180     jobject obj,
    181     jobject jprofile,
    182     jstring j_page_url) {
    183   Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
    184   DCHECK(profile);
    185 
    186   std::string page_url = ConvertJavaStringToUTF8(env, j_page_url);
    187 
    188   ProfileSyncService* sync_service =
    189       ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
    190   DCHECK(sync_service);
    191 
    192   scoped_refptr<base::RefCountedMemory> favicon_png;
    193   browser_sync::OpenTabsUIDelegate* open_tabs =
    194       sync_service->GetOpenTabsUIDelegate();
    195   DCHECK(open_tabs);
    196 
    197   if (!open_tabs->GetSyncedFaviconForPageURL(page_url, &favicon_png))
    198     return ScopedJavaLocalRef<jobject>();
    199 
    200   // Convert favicon_image_result to java objects.
    201   gfx::Image favicon_image = gfx::Image::CreateFrom1xPNGBytes(favicon_png);
    202   SkBitmap favicon_bitmap = favicon_image.AsBitmap();
    203 
    204   ScopedJavaLocalRef<jobject> j_favicon_bitmap;
    205   if (favicon_bitmap.isNull())
    206     return ScopedJavaLocalRef<jobject>();
    207 
    208   return gfx::ConvertToJavaBitmap(&favicon_bitmap);
    209 }
    210 
    211 FaviconHelper::~FaviconHelper() {}
    212 
    213 static jint GetDominantColorForBitmap(JNIEnv* env,
    214                                       jclass clazz,
    215                                       jobject bitmap) {
    216   if (!bitmap)
    217     return 0;
    218 
    219     gfx::JavaBitmap bitmap_lock(bitmap);
    220     SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(bitmap_lock);
    221     return color_utils::CalculateKMeanColorOfBitmap(skbitmap);
    222 }
    223 
    224 // static
    225 bool FaviconHelper::RegisterFaviconHelper(JNIEnv* env) {
    226   return RegisterNativesImpl(env);
    227 }
    228