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