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/most_visited_sites.h"
      6 
      7 #include "base/android/jni_android.h"
      8 #include "base/android/jni_array.h"
      9 #include "base/android/jni_string.h"
     10 #include "base/android/scoped_java_ref.h"
     11 #include "chrome/browser/history/history_types.h"
     12 #include "chrome/browser/history/top_sites.h"
     13 #include "chrome/browser/profiles/profile.h"
     14 #include "chrome/browser/profiles/profile_android.h"
     15 #include "content/public/browser/browser_thread.h"
     16 #include "jni/MostVisitedSites_jni.h"
     17 #include "third_party/skia/include/core/SkBitmap.h"
     18 #include "ui/gfx/android/java_bitmap.h"
     19 #include "ui/gfx/codec/jpeg_codec.h"
     20 
     21 using base::android::AttachCurrentThread;
     22 using base::android::ConvertUTF8ToJavaString;
     23 using base::android::ConvertJavaStringToUTF8;
     24 using base::android::ScopedJavaGlobalRef;
     25 using base::android::ToJavaArrayOfStrings;
     26 using base::android::CheckException;
     27 using content::BrowserThread;
     28 using history::TopSites;
     29 
     30 namespace chrome {
     31 namespace android {
     32 
     33 bool RegisterMostVisitedSites(JNIEnv* env) {
     34   return RegisterNativesImpl(env);
     35 }
     36 
     37 }  // namespace android
     38 }  // namespace chrome
     39 
     40 namespace {
     41 
     42 class NativeCallback : public base::RefCounted<NativeCallback> {
     43  public:
     44   NativeCallback(jobject j_callback_obj, int num_results)
     45       : num_results_(num_results) {
     46     JNIEnv* env = AttachCurrentThread();
     47     j_callback_obj_.Reset(env, j_callback_obj);
     48   }
     49 
     50   void OnMostVisitedURLsAvailable(
     51       const history::MostVisitedURLList& visited_list) {
     52     std::vector<string16> titles;
     53     std::vector<std::string> urls;
     54     ExtractMostVisitedTitlesAndURLs(visited_list, &titles, &urls);
     55 
     56     JNIEnv* env = AttachCurrentThread();
     57     Java_MostVisitedURLsCallback_onMostVisitedURLsAvailable(
     58         env,
     59         j_callback_obj_.obj(),
     60         ToJavaArrayOfStrings(env, titles).obj(),
     61         ToJavaArrayOfStrings(env, urls).obj());
     62   }
     63 
     64  private:
     65   friend class base::RefCounted<NativeCallback>;
     66   ~NativeCallback() {}
     67 
     68   void ExtractMostVisitedTitlesAndURLs(
     69       const history::MostVisitedURLList& visited_list,
     70       std::vector<string16>* titles,
     71       std::vector<std::string>* urls) {
     72     for (size_t i = 0; i < visited_list.size() && i < num_results_; ++i) {
     73       const history::MostVisitedURL& visited = visited_list[i];
     74 
     75       if (visited.url.is_empty())
     76         break;  // This is the signal that there are no more real visited sites.
     77 
     78       titles->push_back(visited.title);
     79       urls->push_back(visited.url.spec());
     80     }
     81   }
     82 
     83   ScopedJavaGlobalRef<jobject> j_callback_obj_;
     84   size_t num_results_;
     85 };
     86 
     87 SkBitmap ExtractThumbnail(const base::RefCountedMemory& image_data) {
     88   scoped_ptr<SkBitmap> image(gfx::JPEGCodec::Decode(
     89       image_data.front(),
     90       image_data.size()));
     91   return image.get() ? *image : SkBitmap();
     92 }
     93 
     94 void OnObtainedThumbnail(
     95     ScopedJavaGlobalRef<jobject>* bitmap,
     96     ScopedJavaGlobalRef<jobject>* j_callback_ref) {
     97   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     98   JNIEnv* env = AttachCurrentThread();
     99   Java_ThumbnailCallback_onMostVisitedURLsThumbnailAvailable(
    100       env, j_callback_ref->obj(), bitmap->obj());
    101 }
    102 
    103 void GetUrlThumbnailTask(
    104     std::string url_string,
    105     scoped_refptr<TopSites> top_sites,
    106     ScopedJavaGlobalRef<jobject>* j_callback_ref) {
    107   JNIEnv* env = AttachCurrentThread();
    108 
    109   ScopedJavaGlobalRef<jobject>* j_bitmap_ref =
    110       new ScopedJavaGlobalRef<jobject>();
    111 
    112   GURL gurl(url_string);
    113 
    114   scoped_refptr<base::RefCountedMemory> data;
    115   if (top_sites->GetPageThumbnail(gurl, &data)) {
    116     SkBitmap thumbnail_bitmap = ExtractThumbnail(*data.get());
    117     if (!thumbnail_bitmap.empty()) {
    118       j_bitmap_ref->Reset(
    119           env,
    120           gfx::ConvertToJavaBitmap(&thumbnail_bitmap).obj());
    121     }
    122   }
    123 
    124   // Since j_callback_ref is owned by this callback,
    125   // when the callback falls out of scope it will be deleted.
    126   // We need to pass ownership to the next callback.
    127   ScopedJavaGlobalRef<jobject>* j_callback_ref_pass =
    128       new ScopedJavaGlobalRef<jobject>(*j_callback_ref);
    129   BrowserThread::PostTask(
    130       BrowserThread::UI, FROM_HERE,
    131       base::Bind(
    132           &OnObtainedThumbnail,
    133           base::Owned(j_bitmap_ref),base::Owned(j_callback_ref_pass)));
    134 }
    135 
    136 }  // namespace
    137 
    138 void GetMostVisitedURLs(
    139     JNIEnv* env,
    140     jclass clazz,
    141     jobject j_profile,
    142     jobject j_callback_obj,
    143     jint num_results) {
    144   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
    145 
    146   DCHECK(profile);
    147   if (!profile)
    148     return;
    149 
    150   TopSites* top_sites = profile->GetTopSites();
    151   if (!top_sites)
    152     return;
    153 
    154   scoped_refptr<NativeCallback> native_callback =
    155       new NativeCallback(j_callback_obj, static_cast<int>(num_results));
    156   top_sites->GetMostVisitedURLs(
    157       base::Bind(&NativeCallback::OnMostVisitedURLsAvailable,
    158                  native_callback));
    159 }
    160 
    161 // May be called from any thread
    162 void GetURLThumbnail(
    163     JNIEnv* env,
    164     jclass clazz,
    165     jobject j_profile,
    166     jstring url,
    167     jobject j_callback_obj) {
    168   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
    169 
    170   DCHECK(profile);
    171   if (!profile)
    172     return;
    173 
    174   ScopedJavaGlobalRef<jobject>* j_callback_ref =
    175       new ScopedJavaGlobalRef<jobject>();
    176   j_callback_ref->Reset(env, j_callback_obj);
    177 
    178   std::string url_string = ConvertJavaStringToUTF8(env, url);
    179   scoped_refptr<TopSites> top_sites(profile->GetTopSites());
    180   BrowserThread::PostTask(
    181       BrowserThread::DB, FROM_HERE, base::Bind(
    182           &GetUrlThumbnailTask,
    183           url_string,
    184           top_sites, base::Owned(j_callback_ref)));
    185 }
    186 
    187 void BlacklistUrl(JNIEnv* env, jclass clazz, jobject j_profile, jstring j_url) {
    188   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
    189 
    190   DCHECK(profile);
    191   if (!profile)
    192     return;
    193 
    194   TopSites* top_sites = profile->GetTopSites();
    195   if (!top_sites)
    196     return;
    197 
    198   std::string url_string = ConvertJavaStringToUTF8(env, j_url);
    199   top_sites->AddBlacklistedURL(GURL(url_string));
    200 }
    201