Add more checks to investigate SupervisedUserPrefStore crash at startup.
[chromium-blink-merge.git] / chrome / browser / android / bookmarks / partner_bookmarks_reader.cc
blob4be9c0ea4dd5929dc649805c45a2d2c6b606bcbb
1 // Copyright 2015 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/bookmarks/partner_bookmarks_reader.h"
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"
24 using base::android::AttachCurrentThread;
25 using base::android::CheckException;
26 using base::android::ConvertJavaStringToUTF16;
27 using bookmarks::BookmarkNode;
28 using bookmarks::BookmarkPermanentNode;
29 using content::BrowserThread;
31 namespace {
33 void SetFaviconTask(Profile* profile,
34 const GURL& page_url, const GURL& icon_url,
35 const std::vector<unsigned char>& image_data,
36 favicon_base::IconType icon_type) {
37 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
38 scoped_refptr<base::RefCountedMemory> bitmap_data(
39 new base::RefCountedBytes(image_data));
40 gfx::Size pixel_size(gfx::kFaviconSize, gfx::kFaviconSize);
41 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(
42 ProfileManager::GetActiveUserProfile(),
43 ServiceAccessType::EXPLICIT_ACCESS);
44 if (!favicon_service)
45 return;
47 favicon_service->MergeFavicon(
48 page_url, page_url, icon_type, bitmap_data, pixel_size);
51 void SetFaviconCallback(Profile* profile,
52 const GURL& page_url, const GURL& icon_url,
53 const std::vector<unsigned char>& image_data,
54 favicon_base::IconType icon_type,
55 base::WaitableEvent* bookmark_added_event) {
56 SetFaviconTask(profile, page_url, icon_url, image_data, icon_type);
57 if (bookmark_added_event)
58 bookmark_added_event->Signal();
61 void PrepareAndSetFavicon(JNIEnv* env, jbyte* icon_bytes, int icon_len,
62 BookmarkNode* node, Profile* profile,
63 favicon_base::IconType icon_type) {
64 SkBitmap icon_bitmap;
65 if (!gfx::PNGCodec::Decode(
66 reinterpret_cast<const unsigned char*>(icon_bytes),
67 icon_len, &icon_bitmap))
68 return;
69 std::vector<unsigned char> image_data;
70 if (!gfx::PNGCodec::EncodeBGRASkBitmap(icon_bitmap, false, &image_data))
71 return;
72 // TODO(aruslan): TODO(tedchoc): Follow up on how to avoid this through js.
73 // Since the favicon URL is used as a key in the history's thumbnail DB,
74 // this gives us a value which does not collide with others.
75 GURL fake_icon_url = node->url();
76 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
77 SetFaviconTask(profile,
78 node->url(), fake_icon_url,
79 image_data, icon_type);
80 } else {
81 base::WaitableEvent event(false, false);
82 BrowserThread::PostTask(
83 BrowserThread::UI,
84 FROM_HERE,
85 base::Bind(&SetFaviconCallback,
86 profile, node->url(), fake_icon_url,
87 image_data, icon_type, &event));
88 // TODO(aruslan): http://b/6397072 If possible - avoid using favicon service
89 event.Wait();
93 const BookmarkNode* GetNodeByID(const BookmarkNode* parent, int64 id) {
94 if (parent->id() == id)
95 return parent;
96 for (int i= 0, child_count = parent->child_count(); i < child_count; ++i) {
97 const BookmarkNode* result = GetNodeByID(parent->GetChild(i), id);
98 if (result)
99 return result;
101 return NULL;
104 } // namespace
106 PartnerBookmarksReader::PartnerBookmarksReader(
107 PartnerBookmarksShim* partner_bookmarks_shim,
108 Profile* profile)
109 : partner_bookmarks_shim_(partner_bookmarks_shim),
110 profile_(profile),
111 wip_next_available_id_(0) {
114 PartnerBookmarksReader::~PartnerBookmarksReader() {}
116 void PartnerBookmarksReader::PartnerBookmarksCreationComplete(JNIEnv*,
117 jobject) {
118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
119 partner_bookmarks_shim_->SetPartnerBookmarksRoot(
120 wip_partner_bookmarks_root_.release());
121 wip_next_available_id_ = 0;
124 void PartnerBookmarksReader::Destroy(JNIEnv* env, jobject obj) {
125 delete this;
128 void PartnerBookmarksReader::Reset(JNIEnv* env, jobject obj) {
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
130 wip_partner_bookmarks_root_.reset();
131 wip_next_available_id_ = 0;
134 jlong PartnerBookmarksReader::AddPartnerBookmark(JNIEnv* env,
135 jobject obj,
136 jstring jurl,
137 jstring jtitle,
138 jboolean is_folder,
139 jlong parent_id,
140 jbyteArray favicon,
141 jbyteArray touchicon) {
142 base::string16 url;
143 base::string16 title;
144 if (jurl)
145 url = ConvertJavaStringToUTF16(env, jurl);
146 if (jtitle)
147 title = ConvertJavaStringToUTF16(env, jtitle);
149 BookmarkNode* node = NULL;
150 if (wip_partner_bookmarks_root_.get()) {
151 node = new BookmarkNode(wip_next_available_id_++, GURL(url));
152 node->set_type(is_folder ? BookmarkNode::FOLDER : BookmarkNode::URL);
153 node->SetTitle(title);
155 // Handle favicon and touchicon
156 if (profile_ != NULL && (favicon != NULL || touchicon != NULL)) {
157 jbyteArray icon = (touchicon != NULL) ? touchicon : favicon;
158 const favicon_base::IconType icon_type =
159 touchicon ? favicon_base::TOUCH_ICON : favicon_base::FAVICON;
160 const int icon_len = env->GetArrayLength(icon);
161 jbyte* icon_bytes = env->GetByteArrayElements(icon, NULL);
162 if (icon_bytes)
163 PrepareAndSetFavicon(env, icon_bytes, icon_len,
164 node, profile_, icon_type);
165 env->ReleaseByteArrayElements(icon, icon_bytes, JNI_ABORT);
168 const BookmarkNode* parent =
169 GetNodeByID(wip_partner_bookmarks_root_.get(), parent_id);
170 if (!parent) {
171 LOG(WARNING) << "partner_bookmarks_shim: invalid/unknown parent_id="
172 << parent_id << ": adding to the root";
173 parent = wip_partner_bookmarks_root_.get();
175 const_cast<BookmarkNode*>(parent)->Add(node, parent->child_count());
176 } else {
177 node = new BookmarkPermanentNode(wip_next_available_id_++);
178 node->SetTitle(title);
179 wip_partner_bookmarks_root_.reset(node);
181 return node->id();
184 // static
185 static void DisablePartnerBookmarksEditing(JNIEnv* env, jclass clazz) {
186 PartnerBookmarksShim::DisablePartnerBookmarksEditing();
189 // static
190 bool PartnerBookmarksReader::RegisterPartnerBookmarksReader(JNIEnv* env) {
191 return RegisterNativesImpl(env);
194 // ----------------------------------------------------------------
196 static jlong Init(JNIEnv* env, jobject obj) {
197 Profile* profile = ProfileManager::GetActiveUserProfile();
198 PartnerBookmarksShim* partner_bookmarks_shim =
199 PartnerBookmarksShim::BuildForBrowserContext(profile);
200 PartnerBookmarksReader* reader = new PartnerBookmarksReader(
201 partner_bookmarks_shim, profile);
202 return reinterpret_cast<intptr_t>(reader);