OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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/bookmarks/partner_bookmarks_reader.h" | |
6 | |
7 #include "base/android/jni_android.h" | |
8 #include "base/android/jni_string.h" | |
9 #include "base/logging.h" | |
10 #include "chrome/browser/android/bookmarks/partner_bookmarks_shim.h" | |
11 #include "chrome/browser/browser_process.h" | |
12 #include "chrome/browser/favicon/favicon_service.h" | |
13 #include "chrome/browser/favicon/favicon_service_factory.h" | |
14 #include "chrome/browser/profiles/profile.h" | |
15 #include "chrome/browser/profiles/profile_manager.h" | |
16 #include "components/bookmarks/browser/bookmark_model.h" | |
17 #include "components/favicon_base/favicon_types.h" | |
18 #include "content/public/browser/browser_thread.h" | |
19 #include "jni/PartnerBookmarksReader_jni.h" | |
20 #include "third_party/skia/include/core/SkBitmap.h" | |
21 #include "ui/gfx/codec/png_codec.h" | |
22 #include "ui/gfx/favicon_size.h" | |
23 | |
24 using base::android::AttachCurrentThread; | |
25 using base::android::CheckException; | |
26 using base::android::ConvertJavaStringToUTF16; | |
27 using content::BrowserThread; | |
28 | |
29 namespace { | |
30 | |
31 void SetFaviconTask(Profile* profile, | |
32 const GURL& page_url, const GURL& icon_url, | |
33 const std::vector<unsigned char>& image_data, | |
34 favicon_base::IconType icon_type) { | |
35 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
36 scoped_refptr<base::RefCountedMemory> bitmap_data( | |
37 new base::RefCountedBytes(image_data)); | |
38 gfx::Size pixel_size(gfx::kFaviconSize, gfx::kFaviconSize); | |
39 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( | |
40 ProfileManager::GetActiveUserProfile(), | |
41 Profile::EXPLICIT_ACCESS); | |
42 if (!favicon_service) | |
43 return; | |
44 | |
45 favicon_service->MergeFavicon( | |
46 page_url, page_url, icon_type, bitmap_data, pixel_size); | |
47 } | |
48 | |
49 void SetFaviconCallback(Profile* profile, | |
50 const GURL& page_url, const GURL& icon_url, | |
51 const std::vector<unsigned char>& image_data, | |
52 favicon_base::IconType icon_type, | |
53 base::WaitableEvent* bookmark_added_event) { | |
54 SetFaviconTask(profile, page_url, icon_url, image_data, icon_type); | |
55 if (bookmark_added_event) | |
56 bookmark_added_event->Signal(); | |
57 } | |
58 | |
59 void PrepareAndSetFavicon(JNIEnv* env, jbyte* icon_bytes, int icon_len, | |
60 BookmarkNode* node, Profile* profile, | |
61 favicon_base::IconType icon_type) { | |
62 SkBitmap icon_bitmap; | |
63 if (!gfx::PNGCodec::Decode( | |
64 reinterpret_cast<const unsigned char*>(icon_bytes), | |
65 icon_len, &icon_bitmap)) | |
66 return; | |
67 std::vector<unsigned char> image_data; | |
68 if (!gfx::PNGCodec::EncodeBGRASkBitmap(icon_bitmap, false, &image_data)) | |
69 return; | |
70 // TODO(aruslan): TODO(tedchoc): Follow up on how to avoid this through js. | |
71 // Since the favicon URL is used as a key in the history's thumbnail DB, | |
72 // this gives us a value which does not collide with others. | |
73 GURL fake_icon_url = node->url(); | |
74 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
75 SetFaviconTask(profile, | |
76 node->url(), fake_icon_url, | |
77 image_data, icon_type); | |
78 } else { | |
79 base::WaitableEvent event(false, false); | |
80 BrowserThread::PostTask( | |
81 BrowserThread::UI, | |
82 FROM_HERE, | |
83 base::Bind(&SetFaviconCallback, | |
84 profile, node->url(), fake_icon_url, | |
85 image_data, icon_type, &event)); | |
86 // TODO(aruslan): http://b/6397072 If possible - avoid using favicon service | |
87 event.Wait(); | |
88 } | |
89 } | |
90 | |
91 const BookmarkNode* GetNodeByID(const BookmarkNode* parent, int64 id) { | |
92 if (parent->id() == id) | |
93 return parent; | |
94 for (int i= 0, child_count = parent->child_count(); i < child_count; ++i) { | |
95 const BookmarkNode* result = GetNodeByID(parent->GetChild(i), id); | |
96 if (result) | |
97 return result; | |
98 } | |
99 return NULL; | |
100 } | |
101 | |
102 } // namespace | |
103 | |
104 PartnerBookmarksReader::PartnerBookmarksReader( | |
105 PartnerBookmarksShim* partner_bookmarks_shim, | |
106 Profile* profile) | |
107 : partner_bookmarks_shim_(partner_bookmarks_shim), | |
108 profile_(profile), | |
109 wip_next_available_id_(0) { | |
110 } | |
111 | |
112 PartnerBookmarksReader::~PartnerBookmarksReader() {} | |
113 | |
114 void PartnerBookmarksReader::PartnerBookmarksCreationComplete(JNIEnv*, | |
115 jobject) { | |
116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
117 partner_bookmarks_shim_->SetPartnerBookmarksRoot( | |
118 wip_partner_bookmarks_root_.release()); | |
119 wip_next_available_id_ = 0; | |
120 } | |
121 | |
122 void PartnerBookmarksReader::Destroy(JNIEnv* env, jobject obj) { | |
123 delete this; | |
124 } | |
125 | |
126 void PartnerBookmarksReader::Reset(JNIEnv* env, jobject obj) { | |
127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
128 wip_partner_bookmarks_root_.reset(); | |
129 wip_next_available_id_ = 0; | |
130 } | |
131 | |
132 jlong PartnerBookmarksReader::AddPartnerBookmark(JNIEnv* env, | |
133 jobject obj, | |
134 jstring jurl, | |
135 jstring jtitle, | |
136 jboolean is_folder, | |
137 jlong parent_id, | |
138 jbyteArray favicon, | |
139 jbyteArray touchicon) { | |
140 base::string16 url; | |
141 base::string16 title; | |
142 if (jurl) | |
143 url = ConvertJavaStringToUTF16(env, jurl); | |
144 if (jtitle) | |
145 title = ConvertJavaStringToUTF16(env, jtitle); | |
146 | |
147 BookmarkNode* node = NULL; | |
148 if (wip_partner_bookmarks_root_.get()) { | |
149 node = new BookmarkNode(wip_next_available_id_++, GURL(url)); | |
150 node->set_type(is_folder ? BookmarkNode::FOLDER : BookmarkNode::URL); | |
151 node->SetTitle(title); | |
152 | |
153 // Handle favicon and touchicon | |
154 if (profile_ != NULL && (favicon != NULL || touchicon != NULL)) { | |
155 jbyteArray icon = (touchicon != NULL) ? touchicon : favicon; | |
156 const favicon_base::IconType icon_type = | |
157 touchicon ? favicon_base::TOUCH_ICON : favicon_base::FAVICON; | |
158 const int icon_len = env->GetArrayLength(icon); | |
159 jbyte* icon_bytes = env->GetByteArrayElements(icon, NULL); | |
160 if (icon_bytes) | |
161 PrepareAndSetFavicon(env, icon_bytes, icon_len, | |
162 node, profile_, icon_type); | |
163 env->ReleaseByteArrayElements(icon, icon_bytes, JNI_ABORT); | |
164 } | |
165 | |
166 const BookmarkNode* parent = | |
167 GetNodeByID(wip_partner_bookmarks_root_.get(), parent_id); | |
168 if (!parent) { | |
169 LOG(WARNING) << "partner_bookmarks_shim: invalid/unknown parent_id=" << | |
aruslan
2015/01/07 18:56:50
nit: split before << and align as appropriate e.g.
newt (away)
2015/01/07 20:53:55
Done
| |
170 parent_id << ": adding to the root"; | |
171 parent = wip_partner_bookmarks_root_.get(); | |
172 } | |
173 const_cast<BookmarkNode*>(parent)->Add(node, parent->child_count()); | |
174 } else { | |
175 node = new BookmarkPermanentNode(wip_next_available_id_++); | |
176 node->SetTitle(title); | |
177 wip_partner_bookmarks_root_.reset(node); | |
178 } | |
179 return node->id(); | |
180 } | |
181 | |
182 // static | |
183 static void DisablePartnerBookmarksEditing(JNIEnv* env, jclass clazz) { | |
184 PartnerBookmarksShim::DisablePartnerBookmarksEditing(); | |
185 } | |
186 | |
187 // static | |
188 bool PartnerBookmarksReader::RegisterPartnerBookmarksReader(JNIEnv* env) { | |
189 return RegisterNativesImpl(env); | |
190 } | |
191 | |
192 // ---------------------------------------------------------------- | |
193 | |
194 static jlong Init(JNIEnv* env, jobject obj) { | |
195 Profile* profile = ProfileManager::GetActiveUserProfile(); | |
196 PartnerBookmarksShim* partner_bookmarks_shim = | |
197 PartnerBookmarksShim::BuildForBrowserContext(profile); | |
198 PartnerBookmarksReader* reader = new PartnerBookmarksReader( | |
199 partner_bookmarks_shim, profile); | |
200 return reinterpret_cast<intptr_t>(reader); | |
201 } | |
OLD | NEW |