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.
5 #include "chrome/browser/android/most_visited_sites.h"
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/chrome_notification_types.h"
12 #include "chrome/browser/history/history_types.h"
13 #include "chrome/browser/history/top_sites.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/profiles/profile_android.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/notification_source.h"
18 #include "jni/MostVisitedSites_jni.h"
19 #include "third_party/skia/include/core/SkBitmap.h"
20 #include "ui/gfx/android/java_bitmap.h"
21 #include "ui/gfx/codec/jpeg_codec.h"
23 using base::android::AttachCurrentThread
;
24 using base::android::ConvertUTF8ToJavaString
;
25 using base::android::ConvertJavaStringToUTF8
;
26 using base::android::ScopedJavaGlobalRef
;
27 using base::android::ToJavaArrayOfStrings
;
28 using base::android::CheckException
;
29 using content::BrowserThread
;
30 using history::TopSites
;
34 void ExtractMostVisitedTitlesAndURLs(
35 const history::MostVisitedURLList
& visited_list
,
36 std::vector
<base::string16
>* titles
,
37 std::vector
<std::string
>* urls
,
39 size_t max
= static_cast<size_t>(num_sites
);
40 for (size_t i
= 0; i
< visited_list
.size() && i
< max
; ++i
) {
41 const history::MostVisitedURL
& visited
= visited_list
[i
];
43 if (visited
.url
.is_empty())
44 break; // This is the signal that there are no more real visited sites.
46 titles
->push_back(visited
.title
);
47 urls
->push_back(visited
.url
.spec());
51 void OnMostVisitedURLsAvailable(
52 ScopedJavaGlobalRef
<jobject
>* j_observer
,
54 const history::MostVisitedURLList
& visited_list
) {
55 std::vector
<base::string16
> titles
;
56 std::vector
<std::string
> urls
;
57 ExtractMostVisitedTitlesAndURLs(visited_list
, &titles
, &urls
, num_sites
);
59 JNIEnv
* env
= AttachCurrentThread();
60 Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable(
63 ToJavaArrayOfStrings(env
, titles
).obj(),
64 ToJavaArrayOfStrings(env
, urls
).obj());
67 SkBitmap
ExtractThumbnail(const base::RefCountedMemory
& image_data
) {
68 scoped_ptr
<SkBitmap
> image(gfx::JPEGCodec::Decode(
71 return image
.get() ? *image
: SkBitmap();
74 void OnObtainedThumbnail(
75 ScopedJavaGlobalRef
<jobject
>* bitmap
,
76 ScopedJavaGlobalRef
<jobject
>* j_callback
) {
77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
78 JNIEnv
* env
= AttachCurrentThread();
79 Java_ThumbnailCallback_onMostVisitedURLsThumbnailAvailable(
80 env
, j_callback
->obj(), bitmap
->obj());
83 void GetUrlThumbnailTask(
84 std::string url_string
,
85 scoped_refptr
<TopSites
> top_sites
,
86 ScopedJavaGlobalRef
<jobject
>* j_callback
) {
87 JNIEnv
* env
= AttachCurrentThread();
89 ScopedJavaGlobalRef
<jobject
>* j_bitmap_ref
=
90 new ScopedJavaGlobalRef
<jobject
>();
92 GURL
gurl(url_string
);
94 scoped_refptr
<base::RefCountedMemory
> data
;
95 if (top_sites
->GetPageThumbnail(gurl
, false, &data
)) {
96 SkBitmap thumbnail_bitmap
= ExtractThumbnail(*data
.get());
97 if (!thumbnail_bitmap
.empty()) {
100 gfx::ConvertToJavaBitmap(&thumbnail_bitmap
).obj());
104 // Since j_callback is owned by this callback, when the callback falls out of
105 // scope it will be deleted. We need to pass ownership to the next callback.
106 ScopedJavaGlobalRef
<jobject
>* j_callback_pass
=
107 new ScopedJavaGlobalRef
<jobject
>(*j_callback
);
108 BrowserThread::PostTask(
109 BrowserThread::UI
, FROM_HERE
,
111 &OnObtainedThumbnail
,
112 base::Owned(j_bitmap_ref
), base::Owned(j_callback_pass
)));
117 MostVisitedSites::MostVisitedSites(Profile
* profile
)
118 : profile_(profile
), num_sites_(0) {
121 MostVisitedSites::~MostVisitedSites() {
124 void MostVisitedSites::Destroy(JNIEnv
* env
, jobject obj
) {
128 void MostVisitedSites::SetMostVisitedURLsObserver(JNIEnv
* env
,
132 observer_
.Reset(env
, j_observer
);
133 num_sites_
= num_sites
;
135 QueryMostVisitedURLs();
137 history::TopSites
* top_sites
= profile_
->GetTopSites();
139 // TopSites updates itself after a delay. To ensure up-to-date results,
140 // force an update now.
141 top_sites
->SyncWithHistory();
143 // Register for notification when TopSites changes so that we can update
145 registrar_
.Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED
,
146 content::Source
<history::TopSites
>(top_sites
));
150 // May be called from any thread
151 void MostVisitedSites::GetURLThumbnail(JNIEnv
* env
,
154 jobject j_callback_obj
) {
155 ScopedJavaGlobalRef
<jobject
>* j_callback
=
156 new ScopedJavaGlobalRef
<jobject
>();
157 j_callback
->Reset(env
, j_callback_obj
);
159 std::string url_string
= ConvertJavaStringToUTF8(env
, url
);
160 scoped_refptr
<TopSites
> top_sites(profile_
->GetTopSites());
161 BrowserThread::PostTask(
162 BrowserThread::DB
, FROM_HERE
, base::Bind(
163 &GetUrlThumbnailTask
,
165 top_sites
, base::Owned(j_callback
)));
168 void MostVisitedSites::BlacklistUrl(JNIEnv
* env
,
171 TopSites
* top_sites
= profile_
->GetTopSites();
175 std::string url_string
= ConvertJavaStringToUTF8(env
, j_url
);
176 top_sites
->AddBlacklistedURL(GURL(url_string
));
179 void MostVisitedSites::Observe(int type
,
180 const content::NotificationSource
& source
,
181 const content::NotificationDetails
& details
) {
182 DCHECK_EQ(type
, chrome::NOTIFICATION_TOP_SITES_CHANGED
);
184 // Most visited urls changed, query again.
185 QueryMostVisitedURLs();
189 bool MostVisitedSites::Register(JNIEnv
* env
) {
190 return RegisterNativesImpl(env
);
193 void MostVisitedSites::QueryMostVisitedURLs() {
194 TopSites
* top_sites
= profile_
->GetTopSites();
198 top_sites
->GetMostVisitedURLs(
200 &OnMostVisitedURLsAvailable
,
201 base::Owned(new ScopedJavaGlobalRef
<jobject
>(observer_
)),
206 static jlong
Init(JNIEnv
* env
, jobject obj
, jobject jprofile
) {
207 MostVisitedSites
* most_visited_sites
=
208 new MostVisitedSites(ProfileAndroid::FromProfileAndroid(jprofile
));
209 return reinterpret_cast<intptr_t>(most_visited_sites
);