Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: chrome/browser/android/bookmarks/bookmarks_bridge.cc

Issue 1708433002: Move BookmarksBridge into package with other bookmarks classes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebased Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/bookmarks/bookmarks_bridge.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include "base/android/jni_array.h"
11 #include "base/android/jni_string.h"
12 #include "base/containers/stack_container.h"
13 #include "base/i18n/string_compare.h"
14 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
15 #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h"
16 #include "chrome/browser/profiles/incognito_helpers.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/profiles/profile_android.h"
19 #include "chrome/browser/signin/signin_manager_factory.h"
20 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
21 #include "components/bookmarks/browser/bookmark_match.h"
22 #include "components/bookmarks/browser/bookmark_model.h"
23 #include "components/bookmarks/browser/bookmark_utils.h"
24 #include "components/bookmarks/browser/scoped_group_bookmark_actions.h"
25 #include "components/bookmarks/common/android/bookmark_type.h"
26 #include "components/bookmarks/common/bookmark_pref_names.h"
27 #include "components/bookmarks/managed/managed_bookmark_service.h"
28 #include "components/prefs/pref_service.h"
29 #include "components/query_parser/query_parser.h"
30 #include "components/signin/core/browser/signin_manager.h"
31 #include "components/undo/bookmark_undo_service.h"
32 #include "components/undo/undo_manager.h"
33 #include "content/public/browser/browser_thread.h"
34 #include "grit/components_strings.h"
35 #include "jni/BookmarksBridge_jni.h"
36 #include "ui/base/l10n/l10n_util.h"
37
38 using base::android::AttachCurrentThread;
39 using base::android::ConvertUTF8ToJavaString;
40 using base::android::ConvertUTF16ToJavaString;
41 using base::android::ScopedJavaLocalRef;
42 using base::android::ScopedJavaGlobalRef;
43 using base::android::ToJavaIntArray;
44 using bookmarks::android::JavaBookmarkIdCreateBookmarkId;
45 using bookmarks::android::JavaBookmarkIdGetId;
46 using bookmarks::android::JavaBookmarkIdGetType;
47 using bookmarks::BookmarkModel;
48 using bookmarks::BookmarkNode;
49 using bookmarks::BookmarkPermanentNode;
50 using bookmarks::BookmarkType;
51 using content::BrowserThread;
52
53 namespace {
54
55 class BookmarkNodeCreationTimeCompareFunctor {
56 public:
57 bool operator()(const BookmarkNode* lhs, const BookmarkNode* rhs) {
58 return lhs->date_added().ToJavaTime() > rhs->date_added().ToJavaTime();
59 }
60 };
61
62 class BookmarkTitleComparer {
63 public:
64 explicit BookmarkTitleComparer(BookmarksBridge* bookmarks_bridge,
65 const icu::Collator* collator)
66 : bookmarks_bridge_(bookmarks_bridge),
67 collator_(collator) {}
68
69 bool operator()(const BookmarkNode* lhs, const BookmarkNode* rhs) {
70 if (collator_) {
71 return base::i18n::CompareString16WithCollator(
72 *collator_, bookmarks_bridge_->GetTitle(lhs),
73 bookmarks_bridge_->GetTitle(rhs)) == UCOL_LESS;
74 } else {
75 return lhs->GetTitle() < rhs->GetTitle();
76 }
77 }
78
79 private:
80 BookmarksBridge* bookmarks_bridge_; // weak
81 const icu::Collator* collator_;
82 };
83
84 scoped_ptr<icu::Collator> GetICUCollator() {
85 UErrorCode error = U_ZERO_ERROR;
86 scoped_ptr<icu::Collator> collator_;
87 collator_.reset(icu::Collator::createInstance(error));
88 if (U_FAILURE(error))
89 collator_.reset(NULL);
90
91 return collator_;
92 }
93
94 } // namespace
95
96 BookmarksBridge::BookmarksBridge(JNIEnv* env, jobject obj, jobject j_profile)
97 : weak_java_ref_(env, obj),
98 bookmark_model_(NULL),
99 managed_bookmark_service_(NULL),
100 partner_bookmarks_shim_(NULL) {
101 DCHECK_CURRENTLY_ON(BrowserThread::UI);
102 profile_ = ProfileAndroid::FromProfileAndroid(j_profile);
103 bookmark_model_ = BookmarkModelFactory::GetForProfile(profile_);
104 managed_bookmark_service_ =
105 ManagedBookmarkServiceFactory::GetForProfile(profile_);
106
107 // Registers the notifications we are interested.
108 bookmark_model_->AddObserver(this);
109
110 // Create the partner Bookmarks shim as early as possible (but don't attach).
111 partner_bookmarks_shim_ = PartnerBookmarksShim::BuildForBrowserContext(
112 chrome::GetBrowserContextRedirectedInIncognito(profile_));
113 partner_bookmarks_shim_->AddObserver(this);
114
115 pref_change_registrar_.Init(profile_->GetPrefs());
116 pref_change_registrar_.Add(
117 bookmarks::prefs::kEditBookmarksEnabled,
118 base::Bind(&BookmarksBridge::EditBookmarksEnabledChanged,
119 base::Unretained(this)));
120
121 NotifyIfDoneLoading();
122
123 // Since a sync or import could have started before this class is
124 // initialized, we need to make sure that our initial state is
125 // up to date.
126 if (bookmark_model_->IsDoingExtensiveChanges())
127 ExtensiveBookmarkChangesBeginning(bookmark_model_);
128 }
129
130 BookmarksBridge::~BookmarksBridge() {
131 bookmark_model_->RemoveObserver(this);
132 if (partner_bookmarks_shim_)
133 partner_bookmarks_shim_->RemoveObserver(this);
134 }
135
136 void BookmarksBridge::Destroy(JNIEnv*, const JavaParamRef<jobject>&) {
137 delete this;
138 }
139
140 // static
141 bool BookmarksBridge::RegisterBookmarksBridge(JNIEnv* env) {
142 return RegisterNativesImpl(env);
143 }
144
145 static jlong Init(JNIEnv* env,
146 const JavaParamRef<jobject>& obj,
147 const JavaParamRef<jobject>& j_profile) {
148 BookmarksBridge* delegate = new BookmarksBridge(env, obj, j_profile);
149 return reinterpret_cast<intptr_t>(delegate);
150 }
151
152 jboolean BookmarksBridge::IsEditBookmarksEnabled(
153 JNIEnv* env,
154 const JavaParamRef<jobject>& obj) {
155 return IsEditBookmarksEnabled();
156 }
157
158 void BookmarksBridge::LoadEmptyPartnerBookmarkShimForTesting(
159 JNIEnv* env,
160 const JavaParamRef<jobject>& obj) {
161 if (partner_bookmarks_shim_->IsLoaded())
162 return;
163 partner_bookmarks_shim_->SetPartnerBookmarksRoot(
164 new BookmarkPermanentNode(0));
165 DCHECK(partner_bookmarks_shim_->IsLoaded());
166 }
167
168 ScopedJavaLocalRef<jobject> BookmarksBridge::GetBookmarkByID(
169 JNIEnv* env,
170 const JavaParamRef<jobject>& obj,
171 jlong id,
172 jint type) {
173 DCHECK(IsLoaded());
174 const BookmarkNode* node = GetNodeByID(id, type);
175 return node ? CreateJavaBookmark(node) : ScopedJavaLocalRef<jobject>();
176 }
177
178 bool BookmarksBridge::IsDoingExtensiveChanges(
179 JNIEnv* env,
180 const JavaParamRef<jobject>& obj) {
181 return bookmark_model_->IsDoingExtensiveChanges();
182 }
183
184 void BookmarksBridge::GetPermanentNodeIDs(
185 JNIEnv* env,
186 const JavaParamRef<jobject>& obj,
187 const JavaParamRef<jobject>& j_result_obj) {
188 // TODO(kkimlabs): Remove this function.
189 DCHECK(IsLoaded());
190
191 base::StackVector<const BookmarkNode*, 8> permanent_nodes;
192
193 // Save all the permanent nodes.
194 const BookmarkNode* root_node = bookmark_model_->root_node();
195 permanent_nodes->push_back(root_node);
196 for (int i = 0; i < root_node->child_count(); ++i) {
197 permanent_nodes->push_back(root_node->GetChild(i));
198 }
199 permanent_nodes->push_back(
200 partner_bookmarks_shim_->GetPartnerBookmarksRoot());
201
202 // Write the permanent nodes to |j_result_obj|.
203 for (base::StackVector<const BookmarkNode*, 8>::ContainerType::const_iterator
204 it = permanent_nodes->begin();
205 it != permanent_nodes->end();
206 ++it) {
207 if (*it != NULL) {
208 Java_BookmarksBridge_addToBookmarkIdList(
209 env, j_result_obj, (*it)->id(), GetBookmarkType(*it));
210 }
211 }
212 }
213
214 void BookmarksBridge::GetTopLevelFolderParentIDs(
215 JNIEnv* env,
216 const JavaParamRef<jobject>& obj,
217 const JavaParamRef<jobject>& j_result_obj) {
218 Java_BookmarksBridge_addToBookmarkIdList(
219 env, j_result_obj, bookmark_model_->root_node()->id(),
220 GetBookmarkType(bookmark_model_->root_node()));
221 }
222
223 void BookmarksBridge::GetTopLevelFolderIDs(
224 JNIEnv* env,
225 const JavaParamRef<jobject>& obj,
226 jboolean get_special,
227 jboolean get_normal,
228 const JavaParamRef<jobject>& j_result_obj) {
229 DCHECK(IsLoaded());
230 std::vector<const BookmarkNode*> top_level_folders;
231
232 if (get_special) {
233 if (managed_bookmark_service_->managed_node() &&
234 managed_bookmark_service_->managed_node()->child_count() > 0) {
235 top_level_folders.push_back(managed_bookmark_service_->managed_node());
236 }
237 if (managed_bookmark_service_->supervised_node() &&
238 managed_bookmark_service_->supervised_node()->child_count() > 0) {
239 top_level_folders.push_back(managed_bookmark_service_->supervised_node());
240 }
241 if (partner_bookmarks_shim_->HasPartnerBookmarks()
242 && IsReachable(partner_bookmarks_shim_->GetPartnerBookmarksRoot())) {
243 top_level_folders.push_back(
244 partner_bookmarks_shim_->GetPartnerBookmarksRoot());
245 }
246 }
247 std::size_t special_count = top_level_folders.size();
248
249 if (get_normal) {
250 DCHECK_EQ(bookmark_model_->root_node()->child_count(), 5);
251
252 const BookmarkNode* mobile_node = bookmark_model_->mobile_node();
253 for (int i = 0; i < mobile_node->child_count(); ++i) {
254 const BookmarkNode* node = mobile_node->GetChild(i);
255 if (node->is_folder()) {
256 top_level_folders.push_back(node);
257 }
258 }
259
260 const BookmarkNode* bookmark_bar_node =
261 bookmark_model_->bookmark_bar_node();
262 for (int i = 0; i < bookmark_bar_node->child_count(); ++i) {
263 const BookmarkNode* node = bookmark_bar_node->GetChild(i);
264 if (node->is_folder()) {
265 top_level_folders.push_back(node);
266 }
267 }
268
269 const BookmarkNode* other_node = bookmark_model_->other_node();
270 for (int i = 0; i < other_node->child_count(); ++i) {
271 const BookmarkNode* node = other_node->GetChild(i);
272 if (node->is_folder()) {
273 top_level_folders.push_back(node);
274 }
275 }
276
277 scoped_ptr<icu::Collator> collator = GetICUCollator();
278 std::stable_sort(top_level_folders.begin() + special_count,
279 top_level_folders.end(),
280 BookmarkTitleComparer(this, collator.get()));
281 }
282
283 for (std::vector<const BookmarkNode*>::const_iterator it =
284 top_level_folders.begin(); it != top_level_folders.end(); ++it) {
285 Java_BookmarksBridge_addToBookmarkIdList(env,
286 j_result_obj,
287 (*it)->id(),
288 GetBookmarkType(*it));
289 }
290 }
291
292 void BookmarksBridge::GetAllFoldersWithDepths(
293 JNIEnv* env,
294 const JavaParamRef<jobject>& obj,
295 const JavaParamRef<jobject>& j_folders_obj,
296 const JavaParamRef<jobject>& j_depths_obj) {
297 DCHECK(IsLoaded());
298
299 scoped_ptr<icu::Collator> collator = GetICUCollator();
300
301 // Vector to temporarily contain all child bookmarks at same level for sorting
302 std::vector<const BookmarkNode*> bookmarkList;
303
304 // Stack for Depth-First Search of bookmark model. It stores nodes and their
305 // heights.
306 std::stack<std::pair<const BookmarkNode*, int> > stk;
307
308 bookmarkList.push_back(bookmark_model_->mobile_node());
309 bookmarkList.push_back(bookmark_model_->bookmark_bar_node());
310 bookmarkList.push_back(bookmark_model_->other_node());
311
312 // Push all sorted top folders in stack and give them depth of 0.
313 // Note the order to push folders to stack should be opposite to the order in
314 // output.
315 for (std::vector<const BookmarkNode*>::reverse_iterator it =
316 bookmarkList.rbegin();
317 it != bookmarkList.rend();
318 ++it) {
319 stk.push(std::make_pair(*it, 0));
320 }
321
322 while (!stk.empty()) {
323 const BookmarkNode* node = stk.top().first;
324 int depth = stk.top().second;
325 stk.pop();
326 Java_BookmarksBridge_addToBookmarkIdListWithDepth(env,
327 j_folders_obj,
328 node->id(),
329 GetBookmarkType(node),
330 j_depths_obj,
331 depth);
332 bookmarkList.clear();
333 for (int i = 0; i < node->child_count(); ++i) {
334 const BookmarkNode* child = node->GetChild(i);
335 if (child->is_folder() &&
336 managed_bookmark_service_->CanBeEditedByUser(child)) {
337 bookmarkList.push_back(node->GetChild(i));
338 }
339 }
340 std::stable_sort(bookmarkList.begin(),
341 bookmarkList.end(),
342 BookmarkTitleComparer(this, collator.get()));
343 for (std::vector<const BookmarkNode*>::reverse_iterator it =
344 bookmarkList.rbegin();
345 it != bookmarkList.rend();
346 ++it) {
347 stk.push(std::make_pair(*it, depth + 1));
348 }
349 }
350 }
351
352 ScopedJavaLocalRef<jobject> BookmarksBridge::GetRootFolderId(
353 JNIEnv* env,
354 const JavaParamRef<jobject>& obj) {
355 const BookmarkNode* root_node = bookmark_model_->root_node();
356 ScopedJavaLocalRef<jobject> folder_id_obj =
357 JavaBookmarkIdCreateBookmarkId(
358 env, root_node->id(), GetBookmarkType(root_node));
359 return folder_id_obj;
360 }
361
362 ScopedJavaLocalRef<jobject> BookmarksBridge::GetMobileFolderId(
363 JNIEnv* env,
364 const JavaParamRef<jobject>& obj) {
365 const BookmarkNode* mobile_node = bookmark_model_->mobile_node();
366 ScopedJavaLocalRef<jobject> folder_id_obj =
367 JavaBookmarkIdCreateBookmarkId(
368 env, mobile_node->id(), GetBookmarkType(mobile_node));
369 return folder_id_obj;
370 }
371
372 ScopedJavaLocalRef<jobject> BookmarksBridge::GetOtherFolderId(
373 JNIEnv* env,
374 const JavaParamRef<jobject>& obj) {
375 const BookmarkNode* other_node = bookmark_model_->other_node();
376 ScopedJavaLocalRef<jobject> folder_id_obj =
377 JavaBookmarkIdCreateBookmarkId(
378 env, other_node->id(), GetBookmarkType(other_node));
379 return folder_id_obj;
380 }
381
382 ScopedJavaLocalRef<jobject> BookmarksBridge::GetDesktopFolderId(
383 JNIEnv* env,
384 const JavaParamRef<jobject>& obj) {
385 const BookmarkNode* desktop_node = bookmark_model_->bookmark_bar_node();
386 ScopedJavaLocalRef<jobject> folder_id_obj =
387 JavaBookmarkIdCreateBookmarkId(
388 env, desktop_node->id(), GetBookmarkType(desktop_node));
389 return folder_id_obj;
390 }
391
392 jint BookmarksBridge::GetChildCount(JNIEnv* env,
393 const JavaParamRef<jobject>& obj,
394 jlong id,
395 jint type) {
396 DCHECK(IsLoaded());
397 const BookmarkNode* node = GetNodeByID(id, type);
398 return node->child_count();
399 }
400
401 void BookmarksBridge::GetChildIDs(JNIEnv* env,
402 const JavaParamRef<jobject>& obj,
403 jlong id,
404 jint type,
405 jboolean get_folders,
406 jboolean get_bookmarks,
407 const JavaParamRef<jobject>& j_result_obj) {
408 DCHECK(IsLoaded());
409
410 const BookmarkNode* parent = GetNodeByID(id, type);
411 if (!parent->is_folder() || !IsReachable(parent))
412 return;
413
414 // Get the folder contents
415 for (int i = 0; i < parent->child_count(); ++i) {
416 const BookmarkNode* child = parent->GetChild(i);
417 if (!IsFolderAvailable(child) || !IsReachable(child))
418 continue;
419
420 if ((child->is_folder() && get_folders) ||
421 (!child->is_folder() && get_bookmarks)) {
422 Java_BookmarksBridge_addToBookmarkIdList(
423 env, j_result_obj, child->id(), GetBookmarkType(child));
424 }
425 }
426
427 // Partner bookmark root node is under mobile node.
428 if (parent == bookmark_model_->mobile_node() && get_folders &&
429 partner_bookmarks_shim_->HasPartnerBookmarks() &&
430 IsReachable(partner_bookmarks_shim_->GetPartnerBookmarksRoot())) {
431 Java_BookmarksBridge_addToBookmarkIdList(
432 env,
433 j_result_obj,
434 partner_bookmarks_shim_->GetPartnerBookmarksRoot()->id(),
435 BookmarkType::BOOKMARK_TYPE_PARTNER);
436 }
437 }
438
439 ScopedJavaLocalRef<jobject> BookmarksBridge::GetChildAt(
440 JNIEnv* env,
441 const JavaParamRef<jobject>& obj,
442 jlong id,
443 jint type,
444 jint index) {
445 DCHECK(IsLoaded());
446
447 const BookmarkNode* parent = GetNodeByID(id, type);
448 DCHECK(parent);
449 const BookmarkNode* child = parent->GetChild(index);
450 return JavaBookmarkIdCreateBookmarkId(
451 env, child->id(), GetBookmarkType(child));
452 }
453
454 void BookmarksBridge::GetAllBookmarkIDsOrderedByCreationDate(
455 JNIEnv* env,
456 const JavaParamRef<jobject>& obj,
457 const JavaParamRef<jobject>& j_result_obj) {
458 DCHECK(IsLoaded());
459 std::list<const BookmarkNode*> folders;
460 std::vector<const BookmarkNode*> result;
461 folders.push_back(bookmark_model_->root_node());
462
463 for (std::list<const BookmarkNode*>::iterator folder_iter = folders.begin();
464 folder_iter != folders.end(); ++folder_iter) {
465 if (*folder_iter == NULL)
466 continue;
467
468 std::list<const BookmarkNode*>::iterator insert_iter = folder_iter;
469 ++insert_iter;
470
471 for (int i = 0; i < (*folder_iter)->child_count(); ++i) {
472 const BookmarkNode* child = (*folder_iter)->GetChild(i);
473 if (!IsReachable(child) ||
474 bookmarks::IsDescendantOf(
475 child, managed_bookmark_service_->managed_node()) ||
476 bookmarks::IsDescendantOf(
477 child, managed_bookmark_service_->supervised_node())) {
478 continue;
479 }
480
481 if (child->is_folder()) {
482 insert_iter = folders.insert(insert_iter, child);
483 } else {
484 result.push_back(child);
485 }
486 }
487 }
488
489 std::sort(
490 result.begin(), result.end(), BookmarkNodeCreationTimeCompareFunctor());
491
492 for (std::vector<const BookmarkNode*>::const_iterator iter = result.begin();
493 iter != result.end();
494 ++iter) {
495 const BookmarkNode* bookmark = *iter;
496 Java_BookmarksBridge_addToBookmarkIdList(
497 env, j_result_obj, bookmark->id(), GetBookmarkType(bookmark));
498 }
499 }
500
501 void BookmarksBridge::SetBookmarkTitle(JNIEnv* env,
502 const JavaParamRef<jobject>& obj,
503 jlong id,
504 jint type,
505 const JavaParamRef<jstring>& j_title) {
506 DCHECK(IsLoaded());
507 const BookmarkNode* bookmark = GetNodeByID(id, type);
508 const base::string16 title =
509 base::android::ConvertJavaStringToUTF16(env, j_title);
510
511 if (partner_bookmarks_shim_->IsPartnerBookmark(bookmark)) {
512 partner_bookmarks_shim_->RenameBookmark(bookmark, title);
513 } else {
514 bookmark_model_->SetTitle(bookmark, title);
515 }
516 }
517
518 void BookmarksBridge::SetBookmarkUrl(JNIEnv* env,
519 const JavaParamRef<jobject>& obj,
520 jlong id,
521 jint type,
522 const JavaParamRef<jstring>& url) {
523 DCHECK(IsLoaded());
524 bookmark_model_->SetURL(
525 GetNodeByID(id, type),
526 GURL(base::android::ConvertJavaStringToUTF16(env, url)));
527 }
528
529 bool BookmarksBridge::DoesBookmarkExist(JNIEnv* env,
530 const JavaParamRef<jobject>& obj,
531 jlong id,
532 jint type) {
533 DCHECK(IsLoaded());
534
535 const BookmarkNode* node = GetNodeByID(id, type);
536
537 if (!node)
538 return false;
539
540 if (type == BookmarkType::BOOKMARK_TYPE_NORMAL) {
541 return true;
542 } else {
543 DCHECK(type == BookmarkType::BOOKMARK_TYPE_PARTNER);
544 return partner_bookmarks_shim_->IsReachable(node);
545 }
546 }
547
548 void BookmarksBridge::GetBookmarksForFolder(
549 JNIEnv* env,
550 const JavaParamRef<jobject>& obj,
551 const JavaParamRef<jobject>& j_folder_id_obj,
552 const JavaParamRef<jobject>& j_callback_obj,
553 const JavaParamRef<jobject>& j_result_obj) {
554 DCHECK(IsLoaded());
555 long folder_id = JavaBookmarkIdGetId(env, j_folder_id_obj);
556 int type = JavaBookmarkIdGetType(env, j_folder_id_obj);
557 const BookmarkNode* folder = GetFolderWithFallback(folder_id, type);
558
559 if (!folder->is_folder() || !IsReachable(folder))
560 return;
561
562 // Recreate the java bookmarkId object due to fallback.
563 ScopedJavaLocalRef<jobject> folder_id_obj =
564 JavaBookmarkIdCreateBookmarkId(
565 env, folder->id(), GetBookmarkType(folder));
566
567 // Get the folder contents.
568 for (int i = 0; i < folder->child_count(); ++i) {
569 const BookmarkNode* node = folder->GetChild(i);
570 if (!IsFolderAvailable(node))
571 continue;
572 ExtractBookmarkNodeInformation(node, j_result_obj);
573 }
574
575 if (folder == bookmark_model_->mobile_node() &&
576 partner_bookmarks_shim_->HasPartnerBookmarks()) {
577 ExtractBookmarkNodeInformation(
578 partner_bookmarks_shim_->GetPartnerBookmarksRoot(),
579 j_result_obj);
580 }
581
582 if (j_callback_obj) {
583 Java_BookmarksCallback_onBookmarksAvailable(
584 env, j_callback_obj, folder_id_obj.obj(), j_result_obj);
585 }
586 }
587
588 jboolean BookmarksBridge::IsFolderVisible(JNIEnv* env,
589 const JavaParamRef<jobject>& obj,
590 jlong id,
591 jint type) {
592 if (type == BookmarkType::BOOKMARK_TYPE_NORMAL) {
593 const BookmarkNode* node = bookmarks::GetBookmarkNodeByID(
594 bookmark_model_, static_cast<int64_t>(id));
595 return node->IsVisible();
596 } else if (type == BookmarkType::BOOKMARK_TYPE_PARTNER) {
597 const BookmarkNode* node = partner_bookmarks_shim_->GetNodeByID(
598 static_cast<long>(id));
599 return partner_bookmarks_shim_->IsReachable(node);
600 }
601
602 NOTREACHED();
603 return false;
604 }
605
606 void BookmarksBridge::GetCurrentFolderHierarchy(
607 JNIEnv* env,
608 const JavaParamRef<jobject>& obj,
609 const JavaParamRef<jobject>& j_folder_id_obj,
610 const JavaParamRef<jobject>& j_callback_obj,
611 const JavaParamRef<jobject>& j_result_obj) {
612 DCHECK(IsLoaded());
613 long folder_id = JavaBookmarkIdGetId(env, j_folder_id_obj);
614 int type = JavaBookmarkIdGetType(env, j_folder_id_obj);
615 const BookmarkNode* folder = GetFolderWithFallback(folder_id, type);
616
617 if (!folder->is_folder() || !IsReachable(folder))
618 return;
619
620 // Recreate the java bookmarkId object due to fallback.
621 ScopedJavaLocalRef<jobject> folder_id_obj =
622 JavaBookmarkIdCreateBookmarkId(
623 env, folder->id(), GetBookmarkType(folder));
624
625 // Get the folder hierarchy.
626 const BookmarkNode* node = folder;
627 while (node) {
628 ExtractBookmarkNodeInformation(node, j_result_obj);
629 node = GetParentNode(node);
630 }
631
632 Java_BookmarksCallback_onBookmarksFolderHierarchyAvailable(
633 env, j_callback_obj, folder_id_obj.obj(), j_result_obj);
634 }
635
636 void BookmarksBridge::SearchBookmarks(JNIEnv* env,
637 const JavaParamRef<jobject>& obj,
638 const JavaParamRef<jobject>& j_list,
639 const JavaParamRef<jstring>& j_query,
640 jint max_results) {
641 DCHECK(bookmark_model_->loaded());
642
643 std::vector<bookmarks::BookmarkMatch> results;
644 bookmark_model_->GetBookmarksMatching(
645 base::android::ConvertJavaStringToUTF16(env, j_query),
646 max_results,
647 query_parser::MatchingAlgorithm::ALWAYS_PREFIX_SEARCH,
648 &results);
649 for (const bookmarks::BookmarkMatch& match : results) {
650 const BookmarkNode* node = match.node;
651
652 std::vector<int> title_match_start_positions;
653 std::vector<int> title_match_end_positions;
654 for (auto position : match.title_match_positions) {
655 title_match_start_positions.push_back(position.first);
656 title_match_end_positions.push_back(position.second);
657 }
658
659 std::vector<int> url_match_start_positions;
660 std::vector<int> url_match_end_positions;
661 for (auto position : match.url_match_positions) {
662 url_match_start_positions.push_back(position.first);
663 url_match_end_positions.push_back(position.second);
664 }
665
666 Java_BookmarksBridge_addToBookmarkMatchList(
667 env, j_list, node->id(), node->type(),
668 ToJavaIntArray(env, title_match_start_positions).obj(),
669 ToJavaIntArray(env, title_match_end_positions).obj(),
670 ToJavaIntArray(env, url_match_start_positions).obj(),
671 ToJavaIntArray(env, url_match_end_positions).obj());
672 }
673 }
674
675 ScopedJavaLocalRef<jobject> BookmarksBridge::AddFolder(
676 JNIEnv* env,
677 const JavaParamRef<jobject>& obj,
678 const JavaParamRef<jobject>& j_parent_id_obj,
679 jint index,
680 const JavaParamRef<jstring>& j_title) {
681 DCHECK(IsLoaded());
682 long bookmark_id = JavaBookmarkIdGetId(env, j_parent_id_obj);
683 int type = JavaBookmarkIdGetType(env, j_parent_id_obj);
684 const BookmarkNode* parent = GetNodeByID(bookmark_id, type);
685
686 const BookmarkNode* new_node = bookmark_model_->AddFolder(
687 parent, index, base::android::ConvertJavaStringToUTF16(env, j_title));
688 if (!new_node) {
689 NOTREACHED();
690 return ScopedJavaLocalRef<jobject>();
691 }
692 ScopedJavaLocalRef<jobject> new_java_obj =
693 JavaBookmarkIdCreateBookmarkId(
694 env, new_node->id(), GetBookmarkType(new_node));
695 return new_java_obj;
696 }
697
698 void BookmarksBridge::DeleteBookmark(
699 JNIEnv* env,
700 const JavaParamRef<jobject>& obj,
701 const JavaParamRef<jobject>& j_bookmark_id_obj) {
702 DCHECK_CURRENTLY_ON(BrowserThread::UI);
703 DCHECK(IsLoaded());
704
705 long bookmark_id = JavaBookmarkIdGetId(env, j_bookmark_id_obj);
706 int type = JavaBookmarkIdGetType(env, j_bookmark_id_obj);
707 const BookmarkNode* node = GetNodeByID(bookmark_id, type);
708 if (!IsEditable(node)) {
709 NOTREACHED();
710 return;
711 }
712
713 if (partner_bookmarks_shim_->IsPartnerBookmark(node))
714 partner_bookmarks_shim_->RemoveBookmark(node);
715 else
716 bookmark_model_->Remove(node);
717 }
718
719 void BookmarksBridge::MoveBookmark(
720 JNIEnv* env,
721 const JavaParamRef<jobject>& obj,
722 const JavaParamRef<jobject>& j_bookmark_id_obj,
723 const JavaParamRef<jobject>& j_parent_id_obj,
724 jint index) {
725 DCHECK_CURRENTLY_ON(BrowserThread::UI);
726 DCHECK(IsLoaded());
727
728 long bookmark_id = JavaBookmarkIdGetId(env, j_bookmark_id_obj);
729 int type = JavaBookmarkIdGetType(env, j_bookmark_id_obj);
730 const BookmarkNode* node = GetNodeByID(bookmark_id, type);
731 if (!IsEditable(node)) {
732 NOTREACHED();
733 return;
734 }
735 bookmark_id = JavaBookmarkIdGetId(env, j_parent_id_obj);
736 type = JavaBookmarkIdGetType(env, j_parent_id_obj);
737 const BookmarkNode* new_parent_node = GetNodeByID(bookmark_id, type);
738 bookmark_model_->Move(node, new_parent_node, index);
739 }
740
741 ScopedJavaLocalRef<jobject> BookmarksBridge::AddBookmark(
742 JNIEnv* env,
743 const JavaParamRef<jobject>& obj,
744 const JavaParamRef<jobject>& j_parent_id_obj,
745 jint index,
746 const JavaParamRef<jstring>& j_title,
747 const JavaParamRef<jstring>& j_url) {
748 DCHECK(IsLoaded());
749 long bookmark_id = JavaBookmarkIdGetId(env, j_parent_id_obj);
750 int type = JavaBookmarkIdGetType(env, j_parent_id_obj);
751 const BookmarkNode* parent = GetNodeByID(bookmark_id, type);
752
753 const BookmarkNode* new_node = bookmark_model_->AddURL(
754 parent,
755 index,
756 base::android::ConvertJavaStringToUTF16(env, j_title),
757 GURL(base::android::ConvertJavaStringToUTF16(env, j_url)));
758 if (!new_node) {
759 NOTREACHED();
760 return ScopedJavaLocalRef<jobject>();
761 }
762 ScopedJavaLocalRef<jobject> new_java_obj =
763 JavaBookmarkIdCreateBookmarkId(
764 env, new_node->id(), GetBookmarkType(new_node));
765 return new_java_obj;
766 }
767
768 void BookmarksBridge::Undo(JNIEnv* env, const JavaParamRef<jobject>& obj) {
769 DCHECK_CURRENTLY_ON(BrowserThread::UI);
770 DCHECK(IsLoaded());
771 BookmarkUndoService* undo_service =
772 BookmarkUndoServiceFactory::GetForProfile(profile_);
773 UndoManager* undo_manager = undo_service->undo_manager();
774 undo_manager->Undo();
775 }
776
777 void BookmarksBridge::StartGroupingUndos(JNIEnv* env,
778 const JavaParamRef<jobject>& obj) {
779 DCHECK_CURRENTLY_ON(BrowserThread::UI);
780 DCHECK(IsLoaded());
781 DCHECK(!grouped_bookmark_actions_.get()); // shouldn't have started already
782 grouped_bookmark_actions_.reset(
783 new bookmarks::ScopedGroupBookmarkActions(bookmark_model_));
784 }
785
786 void BookmarksBridge::EndGroupingUndos(JNIEnv* env,
787 const JavaParamRef<jobject>& obj) {
788 DCHECK_CURRENTLY_ON(BrowserThread::UI);
789 DCHECK(IsLoaded());
790 DCHECK(grouped_bookmark_actions_.get()); // should only call after start
791 grouped_bookmark_actions_.reset();
792 }
793
794 base::string16 BookmarksBridge::GetTitle(const BookmarkNode* node) const {
795 if (partner_bookmarks_shim_->IsPartnerBookmark(node))
796 return partner_bookmarks_shim_->GetTitle(node);
797
798 return node->GetTitle();
799 }
800
801 ScopedJavaLocalRef<jobject> BookmarksBridge::CreateJavaBookmark(
802 const BookmarkNode* node) {
803 JNIEnv* env = AttachCurrentThread();
804
805 const BookmarkNode* parent = GetParentNode(node);
806 int64_t parent_id = parent ? parent->id() : -1;
807
808 std::string url;
809 if (node->is_url())
810 url = node->url().spec();
811
812 return Java_BookmarksBridge_createBookmarkItem(
813 env,
814 node->id(),
815 GetBookmarkType(node),
816 ConvertUTF16ToJavaString(env, GetTitle(node)).obj(),
817 ConvertUTF8ToJavaString(env, url).obj(),
818 node->is_folder(),
819 parent_id,
820 GetBookmarkType(parent),
821 IsEditable(node),
822 IsManaged(node));
823 }
824
825 void BookmarksBridge::ExtractBookmarkNodeInformation(const BookmarkNode* node,
826 jobject j_result_obj) {
827 JNIEnv* env = AttachCurrentThread();
828 if (!IsReachable(node))
829 return;
830 Java_BookmarksBridge_addToList(
831 env, j_result_obj, CreateJavaBookmark(node).obj());
832 }
833
834 const BookmarkNode* BookmarksBridge::GetNodeByID(long node_id, int type) {
835 const BookmarkNode* node;
836 if (type == BookmarkType::BOOKMARK_TYPE_PARTNER) {
837 node = partner_bookmarks_shim_->GetNodeByID(static_cast<int64_t>(node_id));
838 } else {
839 node = bookmarks::GetBookmarkNodeByID(bookmark_model_,
840 static_cast<int64_t>(node_id));
841 }
842 return node;
843 }
844
845 const BookmarkNode* BookmarksBridge::GetFolderWithFallback(long folder_id,
846 int type) {
847 const BookmarkNode* folder = GetNodeByID(folder_id, type);
848 if (!folder || folder->type() == BookmarkNode::URL ||
849 !IsFolderAvailable(folder)) {
850 if (!managed_bookmark_service_->managed_node()->empty())
851 folder = managed_bookmark_service_->managed_node();
852 else
853 folder = bookmark_model_->mobile_node();
854 }
855 return folder;
856 }
857
858 bool BookmarksBridge::IsEditBookmarksEnabled() const {
859 return profile_->GetPrefs()->GetBoolean(
860 bookmarks::prefs::kEditBookmarksEnabled);
861 }
862
863 void BookmarksBridge::EditBookmarksEnabledChanged() {
864 JNIEnv* env = AttachCurrentThread();
865 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
866 if (obj.is_null())
867 return;
868 Java_BookmarksBridge_editBookmarksEnabledChanged(env, obj.obj());
869 }
870
871 bool BookmarksBridge::IsEditable(const BookmarkNode* node) const {
872 if (!node || (node->type() != BookmarkNode::FOLDER &&
873 node->type() != BookmarkNode::URL)) {
874 return false;
875 }
876 if (!IsEditBookmarksEnabled())
877 return false;
878 if (partner_bookmarks_shim_->IsPartnerBookmark(node))
879 return partner_bookmarks_shim_->IsEditable(node);
880 return managed_bookmark_service_->CanBeEditedByUser(node);
881 }
882
883 bool BookmarksBridge::IsManaged(const BookmarkNode* node) const {
884 return bookmarks::IsDescendantOf(node,
885 managed_bookmark_service_->managed_node());
886 }
887
888 const BookmarkNode* BookmarksBridge::GetParentNode(const BookmarkNode* node) {
889 DCHECK(IsLoaded());
890 if (node == partner_bookmarks_shim_->GetPartnerBookmarksRoot()) {
891 return bookmark_model_->mobile_node();
892 } else {
893 return node->parent();
894 }
895 }
896
897 int BookmarksBridge::GetBookmarkType(const BookmarkNode* node) {
898 if (partner_bookmarks_shim_->IsPartnerBookmark(node))
899 return BookmarkType::BOOKMARK_TYPE_PARTNER;
900 else
901 return BookmarkType::BOOKMARK_TYPE_NORMAL;
902 }
903
904 bool BookmarksBridge::IsReachable(const BookmarkNode* node) const {
905 if (!partner_bookmarks_shim_->IsPartnerBookmark(node))
906 return true;
907 return partner_bookmarks_shim_->IsReachable(node);
908 }
909
910 bool BookmarksBridge::IsLoaded() const {
911 return (bookmark_model_->loaded() && partner_bookmarks_shim_->IsLoaded());
912 }
913
914 bool BookmarksBridge::IsFolderAvailable(
915 const BookmarkNode* folder) const {
916 // The managed bookmarks folder is not shown if there are no bookmarks
917 // configured via policy.
918 if (folder == managed_bookmark_service_->managed_node() && folder->empty())
919 return false;
920 // Similarly, the supervised bookmarks folder is not shown if there are no
921 // bookmarks configured by the custodian.
922 if (folder == managed_bookmark_service_->supervised_node() && folder->empty())
923 return false;
924
925 SigninManager* signin = SigninManagerFactory::GetForProfile(
926 profile_->GetOriginalProfile());
927 return (folder->type() != BookmarkNode::BOOKMARK_BAR &&
928 folder->type() != BookmarkNode::OTHER_NODE) ||
929 (signin && signin->IsAuthenticated());
930 }
931
932 void BookmarksBridge::NotifyIfDoneLoading() {
933 if (!IsLoaded())
934 return;
935 JNIEnv* env = AttachCurrentThread();
936 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
937 if (obj.is_null())
938 return;
939 Java_BookmarksBridge_bookmarkModelLoaded(env, obj.obj());
940 }
941
942 // ------------- Observer-related methods ------------- //
943
944 void BookmarksBridge::BookmarkModelChanged() {
945 if (!IsLoaded())
946 return;
947
948 // Called when there are changes to the bookmark model. It is most
949 // likely changes to the partner bookmarks.
950 JNIEnv* env = AttachCurrentThread();
951 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
952 if (obj.is_null())
953 return;
954 Java_BookmarksBridge_bookmarkModelChanged(env, obj.obj());
955 }
956
957 void BookmarksBridge::BookmarkModelLoaded(BookmarkModel* model,
958 bool ids_reassigned) {
959 NotifyIfDoneLoading();
960 }
961
962 void BookmarksBridge::BookmarkModelBeingDeleted(BookmarkModel* model) {
963 if (!IsLoaded())
964 return;
965
966 JNIEnv* env = AttachCurrentThread();
967 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
968 if (obj.is_null())
969 return;
970 Java_BookmarksBridge_bookmarkModelDeleted(env, obj.obj());
971 }
972
973 void BookmarksBridge::BookmarkNodeMoved(BookmarkModel* model,
974 const BookmarkNode* old_parent,
975 int old_index,
976 const BookmarkNode* new_parent,
977 int new_index) {
978 if (!IsLoaded())
979 return;
980
981 JNIEnv* env = AttachCurrentThread();
982 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
983 if (obj.is_null())
984 return;
985 Java_BookmarksBridge_bookmarkNodeMoved(
986 env,
987 obj.obj(),
988 CreateJavaBookmark(old_parent).obj(),
989 old_index,
990 CreateJavaBookmark(new_parent).obj(),
991 new_index);
992 }
993
994 void BookmarksBridge::BookmarkNodeAdded(BookmarkModel* model,
995 const BookmarkNode* parent,
996 int index) {
997 if (!IsLoaded())
998 return;
999
1000 JNIEnv* env = AttachCurrentThread();
1001 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
1002 if (obj.is_null())
1003 return;
1004 Java_BookmarksBridge_bookmarkNodeAdded(
1005 env,
1006 obj.obj(),
1007 CreateJavaBookmark(parent).obj(),
1008 index);
1009 }
1010
1011 void BookmarksBridge::BookmarkNodeRemoved(BookmarkModel* model,
1012 const BookmarkNode* parent,
1013 int old_index,
1014 const BookmarkNode* node,
1015 const std::set<GURL>& removed_urls) {
1016 if (!IsLoaded())
1017 return;
1018
1019 JNIEnv* env = AttachCurrentThread();
1020 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
1021 if (obj.is_null())
1022 return;
1023 Java_BookmarksBridge_bookmarkNodeRemoved(
1024 env,
1025 obj.obj(),
1026 CreateJavaBookmark(parent).obj(),
1027 old_index,
1028 CreateJavaBookmark(node).obj());
1029 }
1030
1031 void BookmarksBridge::BookmarkAllUserNodesRemoved(
1032 BookmarkModel* model,
1033 const std::set<GURL>& removed_urls) {
1034 if (!IsLoaded())
1035 return;
1036
1037 JNIEnv* env = AttachCurrentThread();
1038 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
1039 if (obj.is_null())
1040 return;
1041 Java_BookmarksBridge_bookmarkAllUserNodesRemoved(env, obj.obj());
1042 }
1043
1044 void BookmarksBridge::BookmarkNodeChanged(BookmarkModel* model,
1045 const BookmarkNode* node) {
1046 if (!IsLoaded())
1047 return;
1048
1049 JNIEnv* env = AttachCurrentThread();
1050 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
1051 if (obj.is_null())
1052 return;
1053 Java_BookmarksBridge_bookmarkNodeChanged(
1054 env,
1055 obj.obj(),
1056 CreateJavaBookmark(node).obj());
1057 }
1058
1059 void BookmarksBridge::BookmarkNodeChildrenReordered(BookmarkModel* model,
1060 const BookmarkNode* node) {
1061 if (!IsLoaded())
1062 return;
1063
1064 JNIEnv* env = AttachCurrentThread();
1065 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
1066 if (obj.is_null())
1067 return;
1068 Java_BookmarksBridge_bookmarkNodeChildrenReordered(
1069 env,
1070 obj.obj(),
1071 CreateJavaBookmark(node).obj());
1072 }
1073
1074 void BookmarksBridge::ExtensiveBookmarkChangesBeginning(BookmarkModel* model) {
1075 if (!IsLoaded())
1076 return;
1077
1078 JNIEnv* env = AttachCurrentThread();
1079 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
1080 if (obj.is_null())
1081 return;
1082 Java_BookmarksBridge_extensiveBookmarkChangesBeginning(env, obj.obj());
1083 }
1084
1085 void BookmarksBridge::ExtensiveBookmarkChangesEnded(BookmarkModel* model) {
1086 if (!IsLoaded())
1087 return;
1088
1089 JNIEnv* env = AttachCurrentThread();
1090 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
1091 if (obj.is_null())
1092 return;
1093 Java_BookmarksBridge_extensiveBookmarkChangesEnded(env, obj.obj());
1094 }
1095
1096 void BookmarksBridge::PartnerShimChanged(PartnerBookmarksShim* shim) {
1097 if (!IsLoaded())
1098 return;
1099
1100 BookmarkModelChanged();
1101 }
1102
1103 void BookmarksBridge::PartnerShimLoaded(PartnerBookmarksShim* shim) {
1104 NotifyIfDoneLoading();
1105 }
1106
1107 void BookmarksBridge::ShimBeingDeleted(PartnerBookmarksShim* shim) {
1108 partner_bookmarks_shim_ = NULL;
1109 }
OLDNEW
« no previous file with comments | « chrome/browser/android/bookmarks/bookmarks_bridge.h ('k') | chrome/browser/android/chrome_jni_registrar.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698