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::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 
     60 void OnFaviconRawBitmapResultAvailable(
     61     ScopedJavaGlobalRef<jobject>* j_favicon_image_callback,
     62     const favicon_base::FaviconRawBitmapResult& 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 
     88 static jlong Init(JNIEnv* env, jclass clazz) {
     89   return reinterpret_cast<intptr_t>(new FaviconHelper());
     90 }
     91 
     92 FaviconHelper::FaviconHelper() {
     93   cancelable_task_tracker_.reset(new base::CancelableTaskTracker());
     94 }
     95 
     96 void FaviconHelper::Destroy(JNIEnv* env, jobject obj) {
     97   delete this;
     98 }
     99 
    100 jboolean 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::FaviconForPageURLParams 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   favicon_base::FaviconImageCallback callback_runner = base::Bind(
    129       &OnLocalFaviconAvailable, base::Owned(j_scoped_favicon_callback));
    130 
    131   favicon_service->GetFaviconImageForPageURL(
    132       params, callback_runner,
    133       cancelable_task_tracker_.get());
    134 
    135   return true;
    136 }
    137 
    138 void 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   favicon_base::FaviconRawBitmapCallback callback_runner =
    165       base::Bind(&OnFaviconRawBitmapResultAvailable,
    166                  base::Owned(j_scoped_favicon_callback));
    167   favicon_service->GetLargestRawFaviconForPageURL(
    168       profile,
    169       GURL(ConvertJavaStringToUTF16(env, j_page_url)),
    170       icon_types,
    171       static_cast<int>(j_min_size_threshold_px),
    172       callback_runner,
    173       cancelable_task_tracker_.get());
    174 }
    175 
    176 ScopedJavaLocalRef<jobject> FaviconHelper::GetSyncedFaviconImageForURL(
    177     JNIEnv* env,
    178     jobject obj,
    179     jobject jprofile,
    180     jstring j_page_url) {
    181   Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
    182   DCHECK(profile);
    183 
    184   std::string page_url = ConvertJavaStringToUTF8(env, j_page_url);
    185 
    186   ProfileSyncService* sync_service =
    187       ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
    188   DCHECK(sync_service);
    189 
    190   scoped_refptr<base::RefCountedMemory> favicon_png;
    191   browser_sync::OpenTabsUIDelegate* open_tabs =
    192       sync_service->GetOpenTabsUIDelegate();
    193   DCHECK(open_tabs);
    194 
    195   if (!open_tabs->GetSyncedFaviconForPageURL(page_url, &favicon_png))
    196     return ScopedJavaLocalRef<jobject>();
    197 
    198   // Convert favicon_image_result to java objects.
    199   gfx::Image favicon_image = gfx::Image::CreateFrom1xPNGBytes(favicon_png);
    200   SkBitmap favicon_bitmap = favicon_image.AsBitmap();
    201 
    202   ScopedJavaLocalRef<jobject> j_favicon_bitmap;
    203   if (favicon_bitmap.isNull())
    204     return ScopedJavaLocalRef<jobject>();
    205 
    206   return gfx::ConvertToJavaBitmap(&favicon_bitmap);
    207 }
    208 
    209 FaviconHelper::~FaviconHelper() {}
    210 
    211 static jint GetDominantColorForBitmap(JNIEnv* env,
    212                                       jclass clazz,
    213                                       jobject bitmap) {
    214   if (!bitmap)
    215     return 0;
    216 
    217     gfx::JavaBitmap bitmap_lock(bitmap);
    218     SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(bitmap_lock);
    219     return color_utils::CalculateKMeanColorOfBitmap(skbitmap);
    220 }
    221 
    222 // static
    223 bool FaviconHelper::RegisterFaviconHelper(JNIEnv* env) {
    224   return RegisterNativesImpl(env);
    225 }
    226