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/bookmarks/bookmarks_bridge.h"
7 #include "base/android/jni_string.h"
8 #include "base/containers/stack_container.h"
9 #include "base/i18n/string_compare.h"
10 #include "base/prefs/pref_service.h"
11 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
12 #include "chrome/browser/bookmarks/chrome_bookmark_client_factory.h"
13 #include "chrome/browser/bookmarks/enhanced_bookmarks_features.h"
14 #include "chrome/browser/profiles/incognito_helpers.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/profiles/profile_android.h"
17 #include "chrome/browser/profiles/profile_manager.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/browser/undo/bookmark_undo_service.h"
20 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
21 #include "chrome/browser/undo/undo_manager.h"
22 #include "chrome/common/pref_names.h"
23 #include "components/bookmarks/browser/bookmark_match.h"
24 #include "components/bookmarks/browser/bookmark_model.h"
25 #include "components/bookmarks/browser/bookmark_utils.h"
26 #include "components/bookmarks/browser/scoped_group_bookmark_actions.h"
27 #include "components/bookmarks/common/android/bookmark_type.h"
28 #include "components/query_parser/query_parser.h"
29 #include "components/signin/core/browser/signin_manager.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "jni/BookmarksBridge_jni.h"
33 using base::android::AttachCurrentThread
;
34 using base::android::ConvertUTF8ToJavaString
;
35 using base::android::ConvertUTF16ToJavaString
;
36 using base::android::ScopedJavaLocalRef
;
37 using base::android::ScopedJavaGlobalRef
;
38 using bookmarks::android::JavaBookmarkIdCreateBookmarkId
;
39 using bookmarks::android::JavaBookmarkIdGetId
;
40 using bookmarks::android::JavaBookmarkIdGetType
;
41 using bookmarks::BookmarkType
;
42 using content::BrowserThread
;
46 class BookmarkNodeCreationTimeCompareFunctor
{
48 bool operator()(const BookmarkNode
* lhs
, const BookmarkNode
* rhs
) {
49 return lhs
->date_added().ToJavaTime() > rhs
->date_added().ToJavaTime();
53 class BookmarkTitleComparer
{
55 explicit BookmarkTitleComparer(const icu::Collator
* collator
)
56 : collator_(collator
) {}
58 bool operator()(const BookmarkNode
* lhs
, const BookmarkNode
* rhs
) {
60 return base::i18n::CompareString16WithCollator(
61 collator_
, lhs
->GetTitle(), rhs
->GetTitle()) == UCOL_LESS
;
63 return lhs
->GetTitle() < rhs
->GetTitle();
68 const icu::Collator
* collator_
;
71 scoped_ptr
<icu::Collator
> GetICUCollator() {
72 UErrorCode error
= U_ZERO_ERROR
;
73 scoped_ptr
<icu::Collator
> collator_
;
74 collator_
.reset(icu::Collator::createInstance(error
));
76 collator_
.reset(NULL
);
78 return collator_
.Pass();
83 BookmarksBridge::BookmarksBridge(JNIEnv
* env
,
86 : weak_java_ref_(env
, obj
),
87 bookmark_model_(NULL
),
89 partner_bookmarks_shim_(NULL
) {
90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
91 profile_
= ProfileAndroid::FromProfileAndroid(j_profile
);
92 bookmark_model_
= BookmarkModelFactory::GetForProfile(profile_
);
93 client_
= ChromeBookmarkClientFactory::GetForProfile(profile_
);
95 // Registers the notifications we are interested.
96 bookmark_model_
->AddObserver(this);
98 // Create the partner Bookmarks shim as early as possible (but don't attach).
99 partner_bookmarks_shim_
= PartnerBookmarksShim::BuildForBrowserContext(
100 chrome::GetBrowserContextRedirectedInIncognito(profile_
));
101 partner_bookmarks_shim_
->AddObserver(this);
103 NotifyIfDoneLoading();
105 // Since a sync or import could have started before this class is
106 // initialized, we need to make sure that our initial state is
108 if (bookmark_model_
->IsDoingExtensiveChanges())
109 ExtensiveBookmarkChangesBeginning(bookmark_model_
);
112 BookmarksBridge::~BookmarksBridge() {
113 bookmark_model_
->RemoveObserver(this);
114 if (partner_bookmarks_shim_
)
115 partner_bookmarks_shim_
->RemoveObserver(this);
118 void BookmarksBridge::Destroy(JNIEnv
*, jobject
) {
123 bool BookmarksBridge::RegisterBookmarksBridge(JNIEnv
* env
) {
124 return RegisterNativesImpl(env
);
127 static jlong
Init(JNIEnv
* env
, jobject obj
, jobject j_profile
) {
128 BookmarksBridge
* delegate
= new BookmarksBridge(env
, obj
, j_profile
);
129 return reinterpret_cast<intptr_t>(delegate
);
132 static jboolean
IsEnhancedBookmarksFeatureEnabled(JNIEnv
* env
,
135 Profile
* profile
= ProfileAndroid::FromProfileAndroid(j_profile
);
136 return IsEnhancedBookmarksEnabled(profile
->GetPrefs());
139 static bool IsEditBookmarksEnabled() {
140 return ProfileManager::GetLastUsedProfile()->GetPrefs()->GetBoolean(
141 bookmarks::prefs::kEditBookmarksEnabled
);
144 static jboolean
IsEditBookmarksEnabled(JNIEnv
* env
, jclass clazz
) {
145 return IsEditBookmarksEnabled();
148 void BookmarksBridge::LoadEmptyPartnerBookmarkShimForTesting(JNIEnv
* env
,
150 if (partner_bookmarks_shim_
->IsLoaded())
152 partner_bookmarks_shim_
->SetPartnerBookmarksRoot(
153 new BookmarkPermanentNode(0));
154 DCHECK(partner_bookmarks_shim_
->IsLoaded());
157 ScopedJavaLocalRef
<jobject
> BookmarksBridge::GetBookmarkByID(JNIEnv
* env
,
162 return CreateJavaBookmark(GetNodeByID(id
, type
));
165 bool BookmarksBridge::IsDoingExtensiveChanges(JNIEnv
* env
, jobject obj
) {
166 return bookmark_model_
->IsDoingExtensiveChanges();
169 void BookmarksBridge::GetPermanentNodeIDs(JNIEnv
* env
,
171 jobject j_result_obj
) {
172 // TODO(kkimlabs): Remove this function.
175 base::StackVector
<const BookmarkNode
*, 8> permanent_nodes
;
177 // Save all the permanent nodes.
178 const BookmarkNode
* root_node
= bookmark_model_
->root_node();
179 permanent_nodes
->push_back(root_node
);
180 for (int i
= 0; i
< root_node
->child_count(); ++i
) {
181 permanent_nodes
->push_back(root_node
->GetChild(i
));
183 permanent_nodes
->push_back(
184 partner_bookmarks_shim_
->GetPartnerBookmarksRoot());
186 // Write the permanent nodes to |j_result_obj|.
187 for (base::StackVector
<const BookmarkNode
*, 8>::ContainerType::const_iterator
188 it
= permanent_nodes
->begin();
189 it
!= permanent_nodes
->end();
192 Java_BookmarksBridge_addToBookmarkIdList(
193 env
, j_result_obj
, (*it
)->id(), GetBookmarkType(*it
));
198 void BookmarksBridge::GetTopLevelFolderParentIDs(JNIEnv
* env
,
200 jobject j_result_obj
) {
201 Java_BookmarksBridge_addToBookmarkIdList(
202 env
, j_result_obj
, bookmark_model_
->root_node()->id(),
203 GetBookmarkType(bookmark_model_
->root_node()));
204 Java_BookmarksBridge_addToBookmarkIdList(
205 env
, j_result_obj
, bookmark_model_
->mobile_node()->id(),
206 GetBookmarkType(bookmark_model_
->mobile_node()));
207 Java_BookmarksBridge_addToBookmarkIdList(
208 env
, j_result_obj
, bookmark_model_
->other_node()->id(),
209 GetBookmarkType(bookmark_model_
->other_node()));
212 void BookmarksBridge::GetTopLevelFolderIDs(JNIEnv
* env
,
214 jboolean get_special
,
216 jobject j_result_obj
) {
218 std::vector
<const BookmarkNode
*> top_level_folders
;
221 if (client_
->managed_node() &&
222 client_
->managed_node()->child_count() > 0) {
223 top_level_folders
.push_back(client_
->managed_node());
225 if (partner_bookmarks_shim_
->HasPartnerBookmarks()) {
226 top_level_folders
.push_back(
227 partner_bookmarks_shim_
->GetPartnerBookmarksRoot());
230 std::size_t special_count
= top_level_folders
.size();
233 DCHECK_EQ(bookmark_model_
->root_node()->child_count(), 4);
235 top_level_folders
.push_back(bookmark_model_
->bookmark_bar_node());
237 const BookmarkNode
* mobile_node
= bookmark_model_
->mobile_node();
238 for (int i
= 0; i
< mobile_node
->child_count(); ++i
) {
239 const BookmarkNode
* node
= mobile_node
->GetChild(i
);
240 if (node
->is_folder()) {
241 top_level_folders
.push_back(node
);
245 const BookmarkNode
* other_node
= bookmark_model_
->other_node();
246 for (int i
= 0; i
< other_node
->child_count(); ++i
) {
247 const BookmarkNode
* node
= other_node
->GetChild(i
);
248 if (node
->is_folder()) {
249 top_level_folders
.push_back(node
);
253 scoped_ptr
<icu::Collator
> collator
= GetICUCollator();
254 std::stable_sort(top_level_folders
.begin() + special_count
,
255 top_level_folders
.end(),
256 BookmarkTitleComparer(collator
.get()));
259 for (std::vector
<const BookmarkNode
*>::const_iterator it
=
260 top_level_folders
.begin(); it
!= top_level_folders
.end(); ++it
) {
261 Java_BookmarksBridge_addToBookmarkIdList(env
,
264 GetBookmarkType(*it
));
268 void BookmarksBridge::GetUncategorizedBookmarkIDs(JNIEnv
* env
,
270 jobject j_result_obj
) {
271 const BookmarkNode
* mobile_node
= bookmark_model_
->mobile_node();
272 for (int i
= 0; i
< mobile_node
->child_count(); ++i
) {
273 const BookmarkNode
* node
= mobile_node
->GetChild(i
);
274 if (!node
->is_folder()) {
275 Java_BookmarksBridge_addToBookmarkIdList(env
,
278 GetBookmarkType(node
));
282 const BookmarkNode
* other_node
= bookmark_model_
->other_node();
283 for (int i
= 0; i
< other_node
->child_count(); ++i
) {
284 const BookmarkNode
* node
= other_node
->GetChild(i
);
285 if (!node
->is_folder()) {
286 Java_BookmarksBridge_addToBookmarkIdList(env
,
289 GetBookmarkType(node
));
294 void BookmarksBridge::GetAllFoldersWithDepths(JNIEnv
* env
,
296 jobject j_folders_obj
,
297 jobject j_depths_obj
) {
300 const BookmarkNode
* desktop
= bookmark_model_
->bookmark_bar_node();
301 const BookmarkNode
* mobile
= bookmark_model_
->mobile_node();
302 const BookmarkNode
* other
= bookmark_model_
->other_node();
304 scoped_ptr
<icu::Collator
> collator
= GetICUCollator();
306 // Vector to temporarily contain all child bookmarks at same level for sorting
307 std::vector
<const BookmarkNode
*> bookmarkList
;
308 // Stack for Depth-First Search of bookmark model. It stores nodes and their
310 std::stack
<std::pair
<const BookmarkNode
*, int> > stk
;
312 for (int i
= 0; i
< mobile
->child_count(); ++i
) {
313 const BookmarkNode
* child
= mobile
->GetChild(i
);
314 if (child
->is_folder() && client_
->CanBeEditedByUser(child
))
315 bookmarkList
.push_back(child
);
317 for (int i
= 0; i
< other
->child_count(); ++i
) {
318 const BookmarkNode
* child
= other
->GetChild(i
);
319 if (child
->is_folder() && client_
->CanBeEditedByUser(child
))
320 bookmarkList
.push_back(child
);
322 bookmarkList
.push_back(desktop
);
323 std::stable_sort(bookmarkList
.begin(),
325 BookmarkTitleComparer(collator
.get()));
327 // Push all sorted top folders in stack and give them depth of 0.
328 // Note the order to push folders to stack should be opposite to the order in
330 for (std::vector
<const BookmarkNode
*>::reverse_iterator it
=
331 bookmarkList
.rbegin();
332 it
!= bookmarkList
.rend();
334 stk
.push(std::make_pair(*it
, 0));
337 while (!stk
.empty()) {
338 const BookmarkNode
* node
= stk
.top().first
;
339 int depth
= stk
.top().second
;
341 Java_BookmarksBridge_addToBookmarkIdListWithDepth(env
,
344 GetBookmarkType(node
),
347 bookmarkList
.clear();
348 for (int i
= 0; i
< node
->child_count(); ++i
) {
349 const BookmarkNode
* child
= node
->GetChild(i
);
350 if (child
->is_folder() && client_
->CanBeEditedByUser(child
))
351 bookmarkList
.push_back(node
->GetChild(i
));
353 std::stable_sort(bookmarkList
.begin(),
355 BookmarkTitleComparer(collator
.get()));
356 for (std::vector
<const BookmarkNode
*>::reverse_iterator it
=
357 bookmarkList
.rbegin();
358 it
!= bookmarkList
.rend();
360 stk
.push(std::make_pair(*it
, depth
+ 1));
365 ScopedJavaLocalRef
<jobject
> BookmarksBridge::GetMobileFolderId(JNIEnv
* env
,
367 const BookmarkNode
* mobile_node
= bookmark_model_
->mobile_node();
368 ScopedJavaLocalRef
<jobject
> folder_id_obj
=
369 JavaBookmarkIdCreateBookmarkId(
370 env
, mobile_node
->id(), GetBookmarkType(mobile_node
));
371 return folder_id_obj
;
374 ScopedJavaLocalRef
<jobject
> BookmarksBridge::GetOtherFolderId(JNIEnv
* env
,
376 const BookmarkNode
* other_node
= bookmark_model_
->other_node();
377 ScopedJavaLocalRef
<jobject
> folder_id_obj
=
378 JavaBookmarkIdCreateBookmarkId(
379 env
, other_node
->id(), GetBookmarkType(other_node
));
380 return folder_id_obj
;
383 ScopedJavaLocalRef
<jobject
> BookmarksBridge::GetDesktopFolderId(JNIEnv
* env
,
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
;
392 void BookmarksBridge::GetChildIDs(JNIEnv
* env
,
396 jboolean get_folders
,
397 jboolean get_bookmarks
,
398 jobject j_result_obj
) {
401 const BookmarkNode
* parent
= GetNodeByID(id
, type
);
402 if (!parent
->is_folder() || !IsReachable(parent
))
405 // Get the folder contents
406 for (int i
= 0; i
< parent
->child_count(); ++i
) {
407 const BookmarkNode
* child
= parent
->GetChild(i
);
408 if (!IsFolderAvailable(child
) || !IsReachable(child
))
411 if ((child
->is_folder() && get_folders
) ||
412 (!child
->is_folder() && get_bookmarks
)) {
413 Java_BookmarksBridge_addToBookmarkIdList(
414 env
, j_result_obj
, child
->id(), GetBookmarkType(child
));
418 // Partner bookmark root node is under mobile node.
419 if (parent
== bookmark_model_
->mobile_node() && get_folders
&&
420 partner_bookmarks_shim_
->HasPartnerBookmarks() &&
421 IsReachable(partner_bookmarks_shim_
->GetPartnerBookmarksRoot())) {
422 Java_BookmarksBridge_addToBookmarkIdList(
425 partner_bookmarks_shim_
->GetPartnerBookmarksRoot()->id(),
426 BookmarkType::BOOKMARK_TYPE_PARTNER
);
430 ScopedJavaLocalRef
<jobject
> BookmarksBridge::GetChildAt(JNIEnv
* env
,
437 const BookmarkNode
* parent
= GetNodeByID(id
, type
);
439 const BookmarkNode
* child
= parent
->GetChild(index
);
440 return JavaBookmarkIdCreateBookmarkId(
441 env
, child
->id(), GetBookmarkType(child
));
444 void BookmarksBridge::GetAllBookmarkIDsOrderedByCreationDate(
447 jobject j_result_obj
) {
449 std::list
<const BookmarkNode
*> folders
;
450 std::vector
<const BookmarkNode
*> result
;
451 folders
.push_back(bookmark_model_
->root_node());
453 for (std::list
<const BookmarkNode
*>::iterator folder_iter
= folders
.begin();
454 folder_iter
!= folders
.end(); ++folder_iter
) {
455 if (*folder_iter
== NULL
)
458 std::list
<const BookmarkNode
*>::iterator insert_iter
= folder_iter
;
461 for (int i
= 0; i
< (*folder_iter
)->child_count(); ++i
) {
462 const BookmarkNode
* child
= (*folder_iter
)->GetChild(i
);
463 if (!IsFolderAvailable(child
) || !IsReachable(child
) ||
464 client_
->IsDescendantOfManagedNode(child
))
467 if (child
->is_folder()) {
468 insert_iter
= folders
.insert(insert_iter
, child
);
470 result
.push_back(child
);
476 result
.begin(), result
.end(), BookmarkNodeCreationTimeCompareFunctor());
478 for (std::vector
<const BookmarkNode
*>::const_iterator iter
= result
.begin();
479 iter
!= result
.end();
481 const BookmarkNode
* bookmark
= *iter
;
482 Java_BookmarksBridge_addToBookmarkIdList(
483 env
, j_result_obj
, bookmark
->id(), GetBookmarkType(bookmark
));
487 void BookmarksBridge::SetBookmarkTitle(JNIEnv
* env
,
493 const BookmarkNode
* bookmark
= GetNodeByID(id
, type
);
494 const base::string16 title
=
495 base::android::ConvertJavaStringToUTF16(env
, j_title
);
497 if (partner_bookmarks_shim_
->IsPartnerBookmark(bookmark
)) {
498 partner_bookmarks_shim_
->RenameBookmark(bookmark
, title
);
500 bookmark_model_
->SetTitle(bookmark
, title
);
504 void BookmarksBridge::SetBookmarkUrl(JNIEnv
* env
,
510 bookmark_model_
->SetURL(
511 GetNodeByID(id
, type
),
512 GURL(base::android::ConvertJavaStringToUTF16(env
, url
)));
515 bool BookmarksBridge::DoesBookmarkExist(JNIEnv
* env
,
520 return GetNodeByID(id
, type
);
523 void BookmarksBridge::GetBookmarksForFolder(JNIEnv
* env
,
525 jobject j_folder_id_obj
,
526 jobject j_callback_obj
,
527 jobject j_result_obj
) {
529 long folder_id
= JavaBookmarkIdGetId(env
, j_folder_id_obj
);
530 int type
= JavaBookmarkIdGetType(env
, j_folder_id_obj
);
531 const BookmarkNode
* folder
= GetFolderWithFallback(folder_id
, type
);
533 if (!folder
->is_folder() || !IsReachable(folder
))
536 // Recreate the java bookmarkId object due to fallback.
537 ScopedJavaLocalRef
<jobject
> folder_id_obj
=
538 JavaBookmarkIdCreateBookmarkId(
539 env
, folder
->id(), GetBookmarkType(folder
));
540 j_folder_id_obj
= folder_id_obj
.obj();
542 // Get the folder contents.
543 for (int i
= 0; i
< folder
->child_count(); ++i
) {
544 const BookmarkNode
* node
= folder
->GetChild(i
);
545 if (!IsFolderAvailable(node
))
547 ExtractBookmarkNodeInformation(node
, j_result_obj
);
550 if (folder
== bookmark_model_
->mobile_node() &&
551 partner_bookmarks_shim_
->HasPartnerBookmarks()) {
552 ExtractBookmarkNodeInformation(
553 partner_bookmarks_shim_
->GetPartnerBookmarksRoot(),
557 if (j_callback_obj
) {
558 Java_BookmarksCallback_onBookmarksAvailable(
559 env
, j_callback_obj
, j_folder_id_obj
, j_result_obj
);
563 void BookmarksBridge::GetCurrentFolderHierarchy(JNIEnv
* env
,
565 jobject j_folder_id_obj
,
566 jobject j_callback_obj
,
567 jobject j_result_obj
) {
569 long folder_id
= JavaBookmarkIdGetId(env
, j_folder_id_obj
);
570 int type
= JavaBookmarkIdGetType(env
, j_folder_id_obj
);
571 const BookmarkNode
* folder
= GetFolderWithFallback(folder_id
, type
);
573 if (!folder
->is_folder() || !IsReachable(folder
))
576 // Recreate the java bookmarkId object due to fallback.
577 ScopedJavaLocalRef
<jobject
> folder_id_obj
=
578 JavaBookmarkIdCreateBookmarkId(
579 env
, folder
->id(), GetBookmarkType(folder
));
580 j_folder_id_obj
= folder_id_obj
.obj();
582 // Get the folder hierarchy.
583 const BookmarkNode
* node
= folder
;
585 ExtractBookmarkNodeInformation(node
, j_result_obj
);
586 node
= GetParentNode(node
);
589 Java_BookmarksCallback_onBookmarksFolderHierarchyAvailable(
590 env
, j_callback_obj
, j_folder_id_obj
, j_result_obj
);
593 ScopedJavaLocalRef
<jobject
> BookmarksBridge::AddFolder(JNIEnv
* env
,
595 jobject j_parent_id_obj
,
599 long bookmark_id
= JavaBookmarkIdGetId(env
, j_parent_id_obj
);
600 int type
= JavaBookmarkIdGetType(env
, j_parent_id_obj
);
601 const BookmarkNode
* parent
= GetNodeByID(bookmark_id
, type
);
603 const BookmarkNode
* new_node
= bookmark_model_
->AddFolder(
604 parent
, index
, base::android::ConvertJavaStringToUTF16(env
, j_title
));
607 return ScopedJavaLocalRef
<jobject
>();
609 ScopedJavaLocalRef
<jobject
> new_java_obj
=
610 JavaBookmarkIdCreateBookmarkId(
611 env
, new_node
->id(), GetBookmarkType(new_node
));
615 void BookmarksBridge::DeleteBookmark(JNIEnv
* env
,
617 jobject j_bookmark_id_obj
) {
618 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
621 long bookmark_id
= JavaBookmarkIdGetId(env
, j_bookmark_id_obj
);
622 int type
= JavaBookmarkIdGetType(env
, j_bookmark_id_obj
);
623 const BookmarkNode
* node
= GetNodeByID(bookmark_id
, type
);
624 if (!IsEditable(node
)) {
629 if (partner_bookmarks_shim_
->IsPartnerBookmark(node
)) {
630 partner_bookmarks_shim_
->RemoveBookmark(node
);
632 const BookmarkNode
* parent_node
= GetParentNode(node
);
633 bookmark_model_
->Remove(parent_node
, parent_node
->GetIndexOf(node
));
637 void BookmarksBridge::MoveBookmark(JNIEnv
* env
,
639 jobject j_bookmark_id_obj
,
640 jobject j_parent_id_obj
,
642 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
645 long bookmark_id
= JavaBookmarkIdGetId(env
, j_bookmark_id_obj
);
646 int type
= JavaBookmarkIdGetType(env
, j_bookmark_id_obj
);
647 const BookmarkNode
* node
= GetNodeByID(bookmark_id
, type
);
648 if (!IsEditable(node
)) {
652 bookmark_id
= JavaBookmarkIdGetId(env
, j_parent_id_obj
);
653 type
= JavaBookmarkIdGetType(env
, j_parent_id_obj
);
654 const BookmarkNode
* new_parent_node
= GetNodeByID(bookmark_id
, type
);
655 bookmark_model_
->Move(node
, new_parent_node
, index
);
658 void BookmarksBridge::SearchBookmarks(JNIEnv
* env
,
663 DCHECK(bookmark_model_
->loaded());
665 std::vector
<bookmarks::BookmarkMatch
> results
;
666 bookmark_model_
->GetBookmarksMatching(
667 base::android::ConvertJavaStringToUTF16(env
, j_query
),
669 query_parser::MatchingAlgorithm::ALWAYS_PREFIX_SEARCH
,
671 for (const bookmarks::BookmarkMatch
& match
: results
) {
672 const BookmarkNode
* node
= match
.node
;
673 Java_BookmarksBridge_addToBookmarkIdList(
674 env
, j_list
, node
->id(), node
->type());
678 ScopedJavaLocalRef
<jobject
> BookmarksBridge::AddBookmark(
681 jobject j_parent_id_obj
,
686 long bookmark_id
= JavaBookmarkIdGetId(env
, j_parent_id_obj
);
687 int type
= JavaBookmarkIdGetType(env
, j_parent_id_obj
);
688 const BookmarkNode
* parent
= GetNodeByID(bookmark_id
, type
);
690 const BookmarkNode
* new_node
= bookmark_model_
->AddURL(
693 base::android::ConvertJavaStringToUTF16(env
, j_title
),
694 GURL(base::android::ConvertJavaStringToUTF16(env
, j_url
)));
697 return ScopedJavaLocalRef
<jobject
>();
699 ScopedJavaLocalRef
<jobject
> new_java_obj
=
700 JavaBookmarkIdCreateBookmarkId(
701 env
, new_node
->id(), GetBookmarkType(new_node
));
705 void BookmarksBridge::Undo(JNIEnv
* env
, jobject obj
) {
706 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
708 BookmarkUndoService
* undo_service
=
709 BookmarkUndoServiceFactory::GetForProfile(profile_
);
710 UndoManager
* undo_manager
= undo_service
->undo_manager();
711 undo_manager
->Undo();
714 void BookmarksBridge::StartGroupingUndos(JNIEnv
* env
, jobject obj
) {
715 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
717 DCHECK(!grouped_bookmark_actions_
.get()); // shouldn't have started already
718 grouped_bookmark_actions_
.reset(
719 new bookmarks::ScopedGroupBookmarkActions(bookmark_model_
));
722 void BookmarksBridge::EndGroupingUndos(JNIEnv
* env
, jobject obj
) {
723 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
725 DCHECK(grouped_bookmark_actions_
.get()); // should only call after start
726 grouped_bookmark_actions_
.reset();
729 ScopedJavaLocalRef
<jobject
> BookmarksBridge::CreateJavaBookmark(
730 const BookmarkNode
* node
) {
731 JNIEnv
* env
= AttachCurrentThread();
733 const BookmarkNode
* parent
= GetParentNode(node
);
734 int64 parent_id
= parent
? parent
->id() : -1;
738 url
= node
->url().spec();
740 return Java_BookmarksBridge_createBookmarkItem(
743 GetBookmarkType(node
),
744 ConvertUTF16ToJavaString(env
, GetTitle(node
)).obj(),
745 ConvertUTF8ToJavaString(env
, url
).obj(),
748 GetBookmarkType(parent
),
753 void BookmarksBridge::ExtractBookmarkNodeInformation(const BookmarkNode
* node
,
754 jobject j_result_obj
) {
755 JNIEnv
* env
= AttachCurrentThread();
756 if (!IsReachable(node
))
758 Java_BookmarksBridge_addToList(
759 env
, j_result_obj
, CreateJavaBookmark(node
).obj());
762 const BookmarkNode
* BookmarksBridge::GetNodeByID(long node_id
, int type
) {
763 const BookmarkNode
* node
;
764 if (type
== BookmarkType::BOOKMARK_TYPE_PARTNER
) {
765 node
= partner_bookmarks_shim_
->GetNodeByID(
766 static_cast<int64
>(node_id
));
768 node
= bookmarks::GetBookmarkNodeByID(bookmark_model_
,
769 static_cast<int64
>(node_id
));
774 const BookmarkNode
* BookmarksBridge::GetFolderWithFallback(long folder_id
,
776 const BookmarkNode
* folder
= GetNodeByID(folder_id
, type
);
777 if (!folder
|| folder
->type() == BookmarkNode::URL
||
778 !IsFolderAvailable(folder
)) {
779 if (!client_
->managed_node()->empty())
780 folder
= client_
->managed_node();
782 folder
= bookmark_model_
->mobile_node();
787 bool BookmarksBridge::IsEditable(const BookmarkNode
* node
) const {
788 if (!node
|| (node
->type() != BookmarkNode::FOLDER
&&
789 node
->type() != BookmarkNode::URL
)) {
792 if (!IsEditBookmarksEnabled())
794 if (partner_bookmarks_shim_
->IsPartnerBookmark(node
))
795 return partner_bookmarks_shim_
->IsEditable(node
);
796 return client_
->CanBeEditedByUser(node
);
799 bool BookmarksBridge::IsManaged(const BookmarkNode
* node
) const {
800 return client_
->IsDescendantOfManagedNode(node
);
803 const BookmarkNode
* BookmarksBridge::GetParentNode(const BookmarkNode
* node
) {
805 if (node
== partner_bookmarks_shim_
->GetPartnerBookmarksRoot()) {
806 return bookmark_model_
->mobile_node();
808 return node
->parent();
812 int BookmarksBridge::GetBookmarkType(const BookmarkNode
* node
) {
813 if (partner_bookmarks_shim_
->IsPartnerBookmark(node
))
814 return BookmarkType::BOOKMARK_TYPE_PARTNER
;
816 return BookmarkType::BOOKMARK_TYPE_NORMAL
;
819 base::string16
BookmarksBridge::GetTitle(const BookmarkNode
* node
) const {
820 if (partner_bookmarks_shim_
->IsPartnerBookmark(node
))
821 return partner_bookmarks_shim_
->GetTitle(node
);
822 return node
->GetTitle();
825 bool BookmarksBridge::IsReachable(const BookmarkNode
* node
) const {
826 if (!partner_bookmarks_shim_
->IsPartnerBookmark(node
))
828 return partner_bookmarks_shim_
->IsReachable(node
);
831 bool BookmarksBridge::IsLoaded() const {
832 return (bookmark_model_
->loaded() && partner_bookmarks_shim_
->IsLoaded());
835 bool BookmarksBridge::IsFolderAvailable(
836 const BookmarkNode
* folder
) const {
837 // The managed bookmarks folder is not shown if there are no bookmarks
838 // configured via policy.
839 if (folder
== client_
->managed_node() && folder
->empty())
842 SigninManager
* signin
= SigninManagerFactory::GetForProfile(
843 profile_
->GetOriginalProfile());
844 return (folder
->type() != BookmarkNode::BOOKMARK_BAR
&&
845 folder
->type() != BookmarkNode::OTHER_NODE
) ||
846 (signin
&& signin
->IsAuthenticated());
849 void BookmarksBridge::NotifyIfDoneLoading() {
852 JNIEnv
* env
= AttachCurrentThread();
853 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
856 Java_BookmarksBridge_bookmarkModelLoaded(env
, obj
.obj());
859 // ------------- Observer-related methods ------------- //
861 void BookmarksBridge::BookmarkModelChanged() {
865 // Called when there are changes to the bookmark model. It is most
866 // likely changes to the partner bookmarks.
867 JNIEnv
* env
= AttachCurrentThread();
868 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
871 Java_BookmarksBridge_bookmarkModelChanged(env
, obj
.obj());
874 void BookmarksBridge::BookmarkModelLoaded(BookmarkModel
* model
,
875 bool ids_reassigned
) {
876 NotifyIfDoneLoading();
879 void BookmarksBridge::BookmarkModelBeingDeleted(BookmarkModel
* model
) {
883 JNIEnv
* env
= AttachCurrentThread();
884 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
887 Java_BookmarksBridge_bookmarkModelDeleted(env
, obj
.obj());
890 void BookmarksBridge::BookmarkNodeMoved(BookmarkModel
* model
,
891 const BookmarkNode
* old_parent
,
893 const BookmarkNode
* new_parent
,
898 JNIEnv
* env
= AttachCurrentThread();
899 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
902 Java_BookmarksBridge_bookmarkNodeMoved(
905 CreateJavaBookmark(old_parent
).obj(),
907 CreateJavaBookmark(new_parent
).obj(),
911 void BookmarksBridge::BookmarkNodeAdded(BookmarkModel
* model
,
912 const BookmarkNode
* parent
,
917 JNIEnv
* env
= AttachCurrentThread();
918 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
921 Java_BookmarksBridge_bookmarkNodeAdded(
924 CreateJavaBookmark(parent
).obj(),
928 void BookmarksBridge::BookmarkNodeRemoved(BookmarkModel
* model
,
929 const BookmarkNode
* parent
,
931 const BookmarkNode
* node
,
932 const std::set
<GURL
>& removed_urls
) {
936 JNIEnv
* env
= AttachCurrentThread();
937 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
940 Java_BookmarksBridge_bookmarkNodeRemoved(
943 CreateJavaBookmark(parent
).obj(),
945 CreateJavaBookmark(node
).obj());
948 void BookmarksBridge::BookmarkNodeChanged(BookmarkModel
* model
,
949 const BookmarkNode
* node
) {
953 JNIEnv
* env
= AttachCurrentThread();
954 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
957 Java_BookmarksBridge_bookmarkNodeChanged(
960 CreateJavaBookmark(node
).obj());
963 void BookmarksBridge::BookmarkNodeChildrenReordered(BookmarkModel
* model
,
964 const BookmarkNode
* node
) {
968 JNIEnv
* env
= AttachCurrentThread();
969 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
972 Java_BookmarksBridge_bookmarkNodeChildrenReordered(
975 CreateJavaBookmark(node
).obj());
978 void BookmarksBridge::ExtensiveBookmarkChangesBeginning(BookmarkModel
* model
) {
982 JNIEnv
* env
= AttachCurrentThread();
983 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
986 Java_BookmarksBridge_extensiveBookmarkChangesBeginning(env
, obj
.obj());
989 void BookmarksBridge::ExtensiveBookmarkChangesEnded(BookmarkModel
* model
) {
993 JNIEnv
* env
= AttachCurrentThread();
994 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
997 Java_BookmarksBridge_extensiveBookmarkChangesEnded(env
, obj
.obj());
1000 void BookmarksBridge::PartnerShimChanged(PartnerBookmarksShim
* shim
) {
1004 BookmarkModelChanged();
1007 void BookmarksBridge::PartnerShimLoaded(PartnerBookmarksShim
* shim
) {
1008 NotifyIfDoneLoading();
1011 void BookmarksBridge::ShimBeingDeleted(PartnerBookmarksShim
* shim
) {
1012 partner_bookmarks_shim_
= NULL
;