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/common/pref_names.h"
20 #include "components/bookmarks/browser/bookmark_model.h"
21 #include "components/bookmarks/browser/bookmark_utils.h"
22 #include "components/bookmarks/common/android/bookmark_type.h"
23 #include "components/signin/core/browser/signin_manager.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "jni/BookmarksBridge_jni.h"
27 using base::android::AttachCurrentThread
;
28 using base::android::ConvertUTF8ToJavaString
;
29 using base::android::ConvertUTF16ToJavaString
;
30 using base::android::ScopedJavaLocalRef
;
31 using base::android::ScopedJavaGlobalRef
;
32 using bookmarks::android::JavaBookmarkIdGetId
;
33 using bookmarks::android::JavaBookmarkIdGetType
;
34 using bookmarks::BookmarkType
;
35 using content::BrowserThread
;
39 class BookmarkNodeCreationTimeCompareFunctor
{
41 bool operator()(const BookmarkNode
* lhs
, const BookmarkNode
* rhs
) {
42 return lhs
->date_added().ToJavaTime() > rhs
->date_added().ToJavaTime();
46 class BookmarkTitleComparer
{
48 explicit BookmarkTitleComparer(const icu::Collator
* collator
)
49 : collator_(collator
) {}
51 bool operator()(const BookmarkNode
* lhs
, const BookmarkNode
* rhs
) {
53 return base::i18n::CompareString16WithCollator(
54 collator_
, lhs
->GetTitle(), rhs
->GetTitle()) == UCOL_LESS
;
56 return lhs
->GetTitle() < rhs
->GetTitle();
61 const icu::Collator
* collator_
;
64 scoped_ptr
<icu::Collator
> GetICUCollator() {
65 UErrorCode error
= U_ZERO_ERROR
;
66 scoped_ptr
<icu::Collator
> collator_
;
67 collator_
.reset(icu::Collator::createInstance(error
));
69 collator_
.reset(NULL
);
71 return collator_
.Pass();
76 BookmarksBridge::BookmarksBridge(JNIEnv
* env
,
79 : weak_java_ref_(env
, obj
),
80 bookmark_model_(NULL
),
82 partner_bookmarks_shim_(NULL
) {
83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
84 profile_
= ProfileAndroid::FromProfileAndroid(j_profile
);
85 bookmark_model_
= BookmarkModelFactory::GetForProfile(profile_
);
86 client_
= ChromeBookmarkClientFactory::GetForProfile(profile_
);
88 // Registers the notifications we are interested.
89 bookmark_model_
->AddObserver(this);
91 // Create the partner Bookmarks shim as early as possible (but don't attach).
92 partner_bookmarks_shim_
= PartnerBookmarksShim::BuildForBrowserContext(
93 chrome::GetBrowserContextRedirectedInIncognito(profile_
));
94 partner_bookmarks_shim_
->AddObserver(this);
96 NotifyIfDoneLoading();
98 // Since a sync or import could have started before this class is
99 // initialized, we need to make sure that our initial state is
101 if (bookmark_model_
->IsDoingExtensiveChanges())
102 ExtensiveBookmarkChangesBeginning(bookmark_model_
);
105 BookmarksBridge::~BookmarksBridge() {
106 bookmark_model_
->RemoveObserver(this);
107 if (partner_bookmarks_shim_
)
108 partner_bookmarks_shim_
->RemoveObserver(this);
111 void BookmarksBridge::Destroy(JNIEnv
*, jobject
) {
116 bool BookmarksBridge::RegisterBookmarksBridge(JNIEnv
* env
) {
117 return RegisterNativesImpl(env
);
120 static jlong
Init(JNIEnv
* env
, jobject obj
, jobject j_profile
) {
121 BookmarksBridge
* delegate
= new BookmarksBridge(env
, obj
, j_profile
);
122 return reinterpret_cast<intptr_t>(delegate
);
125 static jlong
GetNativeBookmarkModel(JNIEnv
* env
,
128 Profile
* profile
= ProfileAndroid::FromProfileAndroid(j_profile
);
129 BookmarkModel
*bookmark_model_
= BookmarkModelFactory::GetForProfile(profile
);
130 return reinterpret_cast<jlong
>(bookmark_model_
);
133 static jboolean
IsEnhancedBookmarksFeatureEnabled(JNIEnv
* env
,
136 Profile
* profile
= ProfileAndroid::FromProfileAndroid(j_profile
);
137 return IsEnhancedBookmarksEnabled(profile
->GetPrefs());
140 static bool IsEditBookmarksEnabled() {
141 return ProfileManager::GetLastUsedProfile()->GetPrefs()->GetBoolean(
142 bookmarks::prefs::kEditBookmarksEnabled
);
145 static jboolean
IsEditBookmarksEnabled(JNIEnv
* env
, jclass clazz
) {
146 return IsEditBookmarksEnabled();
149 void BookmarksBridge::LoadEmptyPartnerBookmarkShimForTesting(JNIEnv
* env
,
151 if (partner_bookmarks_shim_
->IsLoaded())
153 partner_bookmarks_shim_
->SetPartnerBookmarksRoot(
154 new BookmarkPermanentNode(0));
155 DCHECK(partner_bookmarks_shim_
->IsLoaded());
158 ScopedJavaLocalRef
<jobject
> BookmarksBridge::GetBookmarkByID(JNIEnv
* env
,
163 return CreateJavaBookmark(GetNodeByID(id
, type
));
166 bool BookmarksBridge::IsDoingExtensiveChanges(JNIEnv
* env
, jobject obj
) {
167 return bookmark_model_
->IsDoingExtensiveChanges();
170 void BookmarksBridge::GetPermanentNodeIDs(JNIEnv
* env
,
172 jobject j_result_obj
) {
173 // TODO(kkimlabs): Remove this function.
176 base::StackVector
<const BookmarkNode
*, 8> permanent_nodes
;
178 // Save all the permanent nodes.
179 const BookmarkNode
* root_node
= bookmark_model_
->root_node();
180 permanent_nodes
->push_back(root_node
);
181 for (int i
= 0; i
< root_node
->child_count(); ++i
) {
182 permanent_nodes
->push_back(root_node
->GetChild(i
));
184 permanent_nodes
->push_back(
185 partner_bookmarks_shim_
->GetPartnerBookmarksRoot());
187 // Write the permanent nodes to |j_result_obj|.
188 for (base::StackVector
<const BookmarkNode
*, 8>::ContainerType::const_iterator
189 it
= permanent_nodes
->begin();
190 it
!= permanent_nodes
->end();
193 Java_BookmarksBridge_addToBookmarkIdList(
194 env
, j_result_obj
, (*it
)->id(), GetBookmarkType(*it
));
199 void BookmarksBridge::GetTopLevelFolderParentIDs(JNIEnv
* env
,
201 jobject j_result_obj
) {
202 Java_BookmarksBridge_addToBookmarkIdList(
203 env
, j_result_obj
, bookmark_model_
->root_node()->id(),
204 GetBookmarkType(bookmark_model_
->root_node()));
205 Java_BookmarksBridge_addToBookmarkIdList(
206 env
, j_result_obj
, bookmark_model_
->mobile_node()->id(),
207 GetBookmarkType(bookmark_model_
->mobile_node()));
208 Java_BookmarksBridge_addToBookmarkIdList(
209 env
, j_result_obj
, bookmark_model_
->other_node()->id(),
210 GetBookmarkType(bookmark_model_
->other_node()));
213 void BookmarksBridge::GetTopLevelFolderIDs(JNIEnv
* env
,
215 jboolean get_special
,
217 jobject j_result_obj
) {
219 std::vector
<const BookmarkNode
*> top_level_folders
;
222 if (client_
->managed_node() &&
223 client_
->managed_node()->child_count() > 0) {
224 top_level_folders
.push_back(client_
->managed_node());
226 if (partner_bookmarks_shim_
->HasPartnerBookmarks()) {
227 top_level_folders
.push_back(
228 partner_bookmarks_shim_
->GetPartnerBookmarksRoot());
231 std::size_t special_count
= top_level_folders
.size();
234 DCHECK_EQ(bookmark_model_
->root_node()->child_count(), 4);
236 top_level_folders
.push_back(bookmark_model_
->bookmark_bar_node());
238 const BookmarkNode
* mobile_node
= bookmark_model_
->mobile_node();
239 for (int i
= 0; i
< mobile_node
->child_count(); ++i
) {
240 const BookmarkNode
* node
= mobile_node
->GetChild(i
);
241 if (node
->is_folder()) {
242 top_level_folders
.push_back(node
);
246 const BookmarkNode
* other_node
= bookmark_model_
->other_node();
247 for (int i
= 0; i
< other_node
->child_count(); ++i
) {
248 const BookmarkNode
* node
= other_node
->GetChild(i
);
249 if (node
->is_folder()) {
250 top_level_folders
.push_back(node
);
254 scoped_ptr
<icu::Collator
> collator
= GetICUCollator();
255 std::stable_sort(top_level_folders
.begin() + special_count
,
256 top_level_folders
.end(),
257 BookmarkTitleComparer(collator
.get()));
260 for (std::vector
<const BookmarkNode
*>::const_iterator it
=
261 top_level_folders
.begin(); it
!= top_level_folders
.end(); ++it
) {
262 Java_BookmarksBridge_addToBookmarkIdList(env
,
265 GetBookmarkType(*it
));
269 void BookmarksBridge::GetUncategorizedBookmarkIDs(JNIEnv
* env
,
271 jobject j_result_obj
) {
272 const BookmarkNode
* mobile_node
= bookmark_model_
->mobile_node();
273 for (int i
= 0; i
< mobile_node
->child_count(); ++i
) {
274 const BookmarkNode
* node
= mobile_node
->GetChild(i
);
275 if (!node
->is_folder()) {
276 Java_BookmarksBridge_addToBookmarkIdList(env
,
279 GetBookmarkType(node
));
283 const BookmarkNode
* other_node
= bookmark_model_
->other_node();
284 for (int i
= 0; i
< other_node
->child_count(); ++i
) {
285 const BookmarkNode
* node
= other_node
->GetChild(i
);
286 if (!node
->is_folder()) {
287 Java_BookmarksBridge_addToBookmarkIdList(env
,
290 GetBookmarkType(node
));
295 void BookmarksBridge::GetAllFoldersWithDepths(JNIEnv
* env
,
297 jobject j_folders_obj
,
298 jobject j_depths_obj
) {
301 const BookmarkNode
* desktop
= bookmark_model_
->bookmark_bar_node();
302 const BookmarkNode
* mobile
= bookmark_model_
->mobile_node();
303 const BookmarkNode
* other
= bookmark_model_
->other_node();
305 scoped_ptr
<icu::Collator
> collator
= GetICUCollator();
307 // Vector to temporarily contain all child bookmarks at same level for sorting
308 std::vector
<const BookmarkNode
*> bookmarkList
;
309 // Stack for Depth-First Search of bookmark model. It stores nodes and their
311 std::stack
<std::pair
<const BookmarkNode
*, int> > stk
;
313 for (int i
= 0; i
< mobile
->child_count(); ++i
) {
314 const BookmarkNode
* child
= mobile
->GetChild(i
);
315 if (child
->is_folder() && client_
->CanBeEditedByUser(child
))
316 bookmarkList
.push_back(child
);
318 for (int i
= 0; i
< other
->child_count(); ++i
) {
319 const BookmarkNode
* child
= other
->GetChild(i
);
320 if (child
->is_folder() && client_
->CanBeEditedByUser(child
))
321 bookmarkList
.push_back(child
);
323 bookmarkList
.push_back(desktop
);
324 std::stable_sort(bookmarkList
.begin(),
326 BookmarkTitleComparer(collator
.get()));
328 // Push all sorted top folders in stack and give them depth of 0.
329 // Note the order to push folders to stack should be opposite to the order in
331 for (std::vector
<const BookmarkNode
*>::reverse_iterator it
=
332 bookmarkList
.rbegin();
333 it
!= bookmarkList
.rend();
335 stk
.push(std::make_pair(*it
, 0));
338 while (!stk
.empty()) {
339 const BookmarkNode
* node
= stk
.top().first
;
340 int depth
= stk
.top().second
;
342 Java_BookmarksBridge_addToBookmarkIdListWithDepth(env
,
345 GetBookmarkType(node
),
348 bookmarkList
.clear();
349 for (int i
= 0; i
< node
->child_count(); ++i
) {
350 const BookmarkNode
* child
= node
->GetChild(i
);
351 if (child
->is_folder() && client_
->CanBeEditedByUser(child
))
352 bookmarkList
.push_back(node
->GetChild(i
));
354 std::stable_sort(bookmarkList
.begin(),
356 BookmarkTitleComparer(collator
.get()));
357 for (std::vector
<const BookmarkNode
*>::reverse_iterator it
=
358 bookmarkList
.rbegin();
359 it
!= bookmarkList
.rend();
361 stk
.push(std::make_pair(*it
, depth
+ 1));
366 ScopedJavaLocalRef
<jobject
> BookmarksBridge::GetMobileFolderId(JNIEnv
* env
,
368 const BookmarkNode
* mobile_node
= bookmark_model_
->mobile_node();
369 ScopedJavaLocalRef
<jobject
> folder_id_obj
=
370 Java_BookmarksBridge_createBookmarkId(
371 env
, mobile_node
->id(), GetBookmarkType(mobile_node
));
372 return folder_id_obj
;
375 ScopedJavaLocalRef
<jobject
> BookmarksBridge::GetOtherFolderId(JNIEnv
* env
,
377 const BookmarkNode
* other_node
= bookmark_model_
->other_node();
378 ScopedJavaLocalRef
<jobject
> folder_id_obj
=
379 Java_BookmarksBridge_createBookmarkId(
380 env
, other_node
->id(), GetBookmarkType(other_node
));
381 return folder_id_obj
;
384 ScopedJavaLocalRef
<jobject
> BookmarksBridge::GetDesktopFolderId(JNIEnv
* env
,
386 const BookmarkNode
* desktop_node
= bookmark_model_
->bookmark_bar_node();
387 ScopedJavaLocalRef
<jobject
> folder_id_obj
=
388 Java_BookmarksBridge_createBookmarkId(
389 env
, desktop_node
->id(), GetBookmarkType(desktop_node
));
390 return folder_id_obj
;
393 void BookmarksBridge::GetChildIDs(JNIEnv
* env
,
397 jboolean get_folders
,
398 jboolean get_bookmarks
,
399 jobject j_result_obj
) {
402 const BookmarkNode
* parent
= GetNodeByID(id
, type
);
403 if (!parent
->is_folder() || !IsReachable(parent
))
406 // Get the folder contents
407 for (int i
= 0; i
< parent
->child_count(); ++i
) {
408 const BookmarkNode
* child
= parent
->GetChild(i
);
409 if (!IsFolderAvailable(child
) || !IsReachable(child
))
412 if ((child
->is_folder() && get_folders
) ||
413 (!child
->is_folder() && get_bookmarks
)) {
414 Java_BookmarksBridge_addToBookmarkIdList(
415 env
, j_result_obj
, child
->id(), GetBookmarkType(child
));
419 // Partner bookmark root node is under mobile node.
420 if (parent
== bookmark_model_
->mobile_node() && get_folders
&&
421 partner_bookmarks_shim_
->HasPartnerBookmarks() &&
422 IsReachable(partner_bookmarks_shim_
->GetPartnerBookmarksRoot())) {
423 Java_BookmarksBridge_addToBookmarkIdList(
426 partner_bookmarks_shim_
->GetPartnerBookmarksRoot()->id(),
427 BookmarkType::PARTNER
);
431 void BookmarksBridge::GetAllBookmarkIDsOrderedByCreationDate(
434 jobject j_result_obj
) {
436 std::list
<const BookmarkNode
*> folders
;
437 std::vector
<const BookmarkNode
*> result
;
438 folders
.push_back(bookmark_model_
->root_node());
439 folders
.push_back(partner_bookmarks_shim_
->GetPartnerBookmarksRoot());
441 for (std::list
<const BookmarkNode
*>::iterator folder_iter
= folders
.begin();
442 folder_iter
!= folders
.end(); ++folder_iter
) {
443 if (*folder_iter
== NULL
)
446 std::list
<const BookmarkNode
*>::iterator insert_iter
= folder_iter
;
449 for (int i
= 0; i
< (*folder_iter
)->child_count(); ++i
) {
450 const BookmarkNode
* child
= (*folder_iter
)->GetChild(i
);
451 if (!IsFolderAvailable(child
) || !IsReachable(child
))
454 if (child
->is_folder()) {
455 insert_iter
= folders
.insert(insert_iter
, child
);
457 result
.push_back(child
);
463 result
.begin(), result
.end(), BookmarkNodeCreationTimeCompareFunctor());
465 for (std::vector
<const BookmarkNode
*>::const_iterator iter
= result
.begin();
466 iter
!= result
.end();
468 const BookmarkNode
* bookmark
= *iter
;
469 Java_BookmarksBridge_addToBookmarkIdList(
470 env
, j_result_obj
, bookmark
->id(), GetBookmarkType(bookmark
));
474 void BookmarksBridge::SetBookmarkTitle(JNIEnv
* env
,
480 const BookmarkNode
* bookmark
= GetNodeByID(id
, type
);
481 const base::string16 title
=
482 base::android::ConvertJavaStringToUTF16(env
, j_title
);
484 if (partner_bookmarks_shim_
->IsPartnerBookmark(bookmark
)) {
485 partner_bookmarks_shim_
->RenameBookmark(bookmark
, title
);
487 bookmark_model_
->SetTitle(bookmark
, title
);
491 void BookmarksBridge::SetBookmarkUrl(JNIEnv
* env
,
497 bookmark_model_
->SetURL(
498 GetNodeByID(id
, type
),
499 GURL(base::android::ConvertJavaStringToUTF16(env
, url
)));
502 bool BookmarksBridge::DoesBookmarkExist(JNIEnv
* env
,
507 return GetNodeByID(id
, type
);
510 void BookmarksBridge::GetBookmarksForFolder(JNIEnv
* env
,
512 jobject j_folder_id_obj
,
513 jobject j_callback_obj
,
514 jobject j_result_obj
) {
516 long folder_id
= JavaBookmarkIdGetId(env
, j_folder_id_obj
);
517 int type
= JavaBookmarkIdGetType(env
, j_folder_id_obj
);
518 const BookmarkNode
* folder
= GetFolderWithFallback(folder_id
, type
);
520 if (!folder
->is_folder() || !IsReachable(folder
))
523 // Recreate the java bookmarkId object due to fallback.
524 ScopedJavaLocalRef
<jobject
> folder_id_obj
=
525 Java_BookmarksBridge_createBookmarkId(
526 env
, folder
->id(), GetBookmarkType(folder
));
527 j_folder_id_obj
= folder_id_obj
.obj();
529 // Get the folder contents.
530 for (int i
= 0; i
< folder
->child_count(); ++i
) {
531 const BookmarkNode
* node
= folder
->GetChild(i
);
532 if (!IsFolderAvailable(node
))
534 ExtractBookmarkNodeInformation(node
, j_result_obj
);
537 if (folder
== bookmark_model_
->mobile_node() &&
538 partner_bookmarks_shim_
->HasPartnerBookmarks()) {
539 ExtractBookmarkNodeInformation(
540 partner_bookmarks_shim_
->GetPartnerBookmarksRoot(),
544 if (j_callback_obj
) {
545 Java_BookmarksCallback_onBookmarksAvailable(
546 env
, j_callback_obj
, j_folder_id_obj
, j_result_obj
);
550 void BookmarksBridge::GetCurrentFolderHierarchy(JNIEnv
* env
,
552 jobject j_folder_id_obj
,
553 jobject j_callback_obj
,
554 jobject j_result_obj
) {
556 long folder_id
= JavaBookmarkIdGetId(env
, j_folder_id_obj
);
557 int type
= JavaBookmarkIdGetType(env
, j_folder_id_obj
);
558 const BookmarkNode
* folder
= GetFolderWithFallback(folder_id
, type
);
560 if (!folder
->is_folder() || !IsReachable(folder
))
563 // Recreate the java bookmarkId object due to fallback.
564 ScopedJavaLocalRef
<jobject
> folder_id_obj
=
565 Java_BookmarksBridge_createBookmarkId(
566 env
, folder
->id(), GetBookmarkType(folder
));
567 j_folder_id_obj
= folder_id_obj
.obj();
569 // Get the folder hierarchy.
570 const BookmarkNode
* node
= folder
;
572 ExtractBookmarkNodeInformation(node
, j_result_obj
);
573 node
= GetParentNode(node
);
576 Java_BookmarksCallback_onBookmarksFolderHierarchyAvailable(
577 env
, j_callback_obj
, j_folder_id_obj
, j_result_obj
);
580 ScopedJavaLocalRef
<jobject
> BookmarksBridge::AddFolder(JNIEnv
* env
,
582 jobject j_parent_id_obj
,
586 long bookmark_id
= JavaBookmarkIdGetId(env
, j_parent_id_obj
);
587 int type
= JavaBookmarkIdGetType(env
, j_parent_id_obj
);
588 const BookmarkNode
* parent
= GetNodeByID(bookmark_id
, type
);
590 const BookmarkNode
* new_node
= bookmark_model_
->AddFolder(
591 parent
, index
, base::android::ConvertJavaStringToUTF16(env
, j_title
));
594 return ScopedJavaLocalRef
<jobject
>();
596 ScopedJavaLocalRef
<jobject
> new_java_obj
=
597 Java_BookmarksBridge_createBookmarkId(
598 env
, new_node
->id(), GetBookmarkType(new_node
));
602 void BookmarksBridge::DeleteBookmark(JNIEnv
* env
,
604 jobject j_bookmark_id_obj
) {
605 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
608 long bookmark_id
= JavaBookmarkIdGetId(env
, j_bookmark_id_obj
);
609 int type
= JavaBookmarkIdGetType(env
, j_bookmark_id_obj
);
610 const BookmarkNode
* node
= GetNodeByID(bookmark_id
, type
);
611 if (!IsEditable(node
)) {
616 if (partner_bookmarks_shim_
->IsPartnerBookmark(node
)) {
617 partner_bookmarks_shim_
->RemoveBookmark(node
);
619 const BookmarkNode
* parent_node
= GetParentNode(node
);
620 bookmark_model_
->Remove(parent_node
, parent_node
->GetIndexOf(node
));
624 void BookmarksBridge::MoveBookmark(JNIEnv
* env
,
626 jobject j_bookmark_id_obj
,
627 jobject j_parent_id_obj
,
629 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
632 long bookmark_id
= JavaBookmarkIdGetId(env
, j_bookmark_id_obj
);
633 int type
= JavaBookmarkIdGetType(env
, j_bookmark_id_obj
);
634 const BookmarkNode
* node
= GetNodeByID(bookmark_id
, type
);
635 if (!IsEditable(node
)) {
639 bookmark_id
= JavaBookmarkIdGetId(env
, j_parent_id_obj
);
640 type
= JavaBookmarkIdGetType(env
, j_parent_id_obj
);
641 const BookmarkNode
* new_parent_node
= GetNodeByID(bookmark_id
, type
);
642 bookmark_model_
->Move(node
, new_parent_node
, index
);
645 ScopedJavaLocalRef
<jobject
> BookmarksBridge::AddBookmark(
648 jobject j_parent_id_obj
,
653 long bookmark_id
= JavaBookmarkIdGetId(env
, j_parent_id_obj
);
654 int type
= JavaBookmarkIdGetType(env
, j_parent_id_obj
);
655 const BookmarkNode
* parent
= GetNodeByID(bookmark_id
, type
);
657 const BookmarkNode
* new_node
= bookmark_model_
->AddURL(
660 base::android::ConvertJavaStringToUTF16(env
, j_title
),
661 GURL(base::android::ConvertJavaStringToUTF16(env
, j_url
)));
664 return ScopedJavaLocalRef
<jobject
>();
666 ScopedJavaLocalRef
<jobject
> new_java_obj
=
667 Java_BookmarksBridge_createBookmarkId(
668 env
, new_node
->id(), GetBookmarkType(new_node
));
672 ScopedJavaLocalRef
<jobject
> BookmarksBridge::CreateJavaBookmark(
673 const BookmarkNode
* node
) {
674 JNIEnv
* env
= AttachCurrentThread();
676 const BookmarkNode
* parent
= GetParentNode(node
);
677 int64 parent_id
= parent
? parent
->id() : -1;
681 url
= node
->url().spec();
683 return Java_BookmarksBridge_createBookmarkItem(
686 GetBookmarkType(node
),
687 ConvertUTF16ToJavaString(env
, GetTitle(node
)).obj(),
688 ConvertUTF8ToJavaString(env
, url
).obj(),
691 GetBookmarkType(parent
),
696 void BookmarksBridge::ExtractBookmarkNodeInformation(const BookmarkNode
* node
,
697 jobject j_result_obj
) {
698 JNIEnv
* env
= AttachCurrentThread();
699 if (!IsReachable(node
))
701 Java_BookmarksBridge_addToList(
702 env
, j_result_obj
, CreateJavaBookmark(node
).obj());
705 const BookmarkNode
* BookmarksBridge::GetNodeByID(long node_id
, int type
) {
706 const BookmarkNode
* node
;
707 if (type
== BookmarkType::PARTNER
) {
708 node
= partner_bookmarks_shim_
->GetNodeByID(
709 static_cast<int64
>(node_id
));
711 node
= bookmarks::GetBookmarkNodeByID(bookmark_model_
,
712 static_cast<int64
>(node_id
));
717 const BookmarkNode
* BookmarksBridge::GetFolderWithFallback(long folder_id
,
719 const BookmarkNode
* folder
= GetNodeByID(folder_id
, type
);
720 if (!folder
|| folder
->type() == BookmarkNode::URL
||
721 !IsFolderAvailable(folder
)) {
722 if (!client_
->managed_node()->empty())
723 folder
= client_
->managed_node();
725 folder
= bookmark_model_
->mobile_node();
730 bool BookmarksBridge::IsEditable(const BookmarkNode
* node
) const {
731 if (!node
|| (node
->type() != BookmarkNode::FOLDER
&&
732 node
->type() != BookmarkNode::URL
)) {
735 if (!IsEditBookmarksEnabled())
737 if (partner_bookmarks_shim_
->IsPartnerBookmark(node
))
738 return partner_bookmarks_shim_
->IsEditable(node
);
739 return client_
->CanBeEditedByUser(node
);
742 bool BookmarksBridge::IsManaged(const BookmarkNode
* node
) const {
743 return client_
->IsDescendantOfManagedNode(node
);
746 const BookmarkNode
* BookmarksBridge::GetParentNode(const BookmarkNode
* node
) {
748 if (node
== partner_bookmarks_shim_
->GetPartnerBookmarksRoot()) {
749 return bookmark_model_
->mobile_node();
751 return node
->parent();
755 int BookmarksBridge::GetBookmarkType(const BookmarkNode
* node
) {
756 if (partner_bookmarks_shim_
->IsPartnerBookmark(node
))
757 return BookmarkType::PARTNER
;
759 return BookmarkType::NORMAL
;
762 base::string16
BookmarksBridge::GetTitle(const BookmarkNode
* node
) const {
763 if (partner_bookmarks_shim_
->IsPartnerBookmark(node
))
764 return partner_bookmarks_shim_
->GetTitle(node
);
765 return node
->GetTitle();
768 bool BookmarksBridge::IsReachable(const BookmarkNode
* node
) const {
769 if (!partner_bookmarks_shim_
->IsPartnerBookmark(node
))
771 return partner_bookmarks_shim_
->IsReachable(node
);
774 bool BookmarksBridge::IsLoaded() const {
775 return (bookmark_model_
->loaded() && partner_bookmarks_shim_
->IsLoaded());
778 bool BookmarksBridge::IsFolderAvailable(
779 const BookmarkNode
* folder
) const {
780 // The managed bookmarks folder is not shown if there are no bookmarks
781 // configured via policy.
782 if (folder
== client_
->managed_node() && folder
->empty())
785 SigninManager
* signin
= SigninManagerFactory::GetForProfile(
786 profile_
->GetOriginalProfile());
787 return (folder
->type() != BookmarkNode::BOOKMARK_BAR
&&
788 folder
->type() != BookmarkNode::OTHER_NODE
) ||
789 (signin
&& signin
->IsAuthenticated());
792 void BookmarksBridge::NotifyIfDoneLoading() {
795 JNIEnv
* env
= AttachCurrentThread();
796 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
799 Java_BookmarksBridge_bookmarkModelLoaded(env
, obj
.obj());
802 // ------------- Observer-related methods ------------- //
804 void BookmarksBridge::BookmarkModelChanged() {
808 // Called when there are changes to the bookmark model. It is most
809 // likely changes to the partner bookmarks.
810 JNIEnv
* env
= AttachCurrentThread();
811 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
814 Java_BookmarksBridge_bookmarkModelChanged(env
, obj
.obj());
817 void BookmarksBridge::BookmarkModelLoaded(BookmarkModel
* model
,
818 bool ids_reassigned
) {
819 NotifyIfDoneLoading();
822 void BookmarksBridge::BookmarkModelBeingDeleted(BookmarkModel
* model
) {
826 JNIEnv
* env
= AttachCurrentThread();
827 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
830 Java_BookmarksBridge_bookmarkModelDeleted(env
, obj
.obj());
833 void BookmarksBridge::BookmarkNodeMoved(BookmarkModel
* model
,
834 const BookmarkNode
* old_parent
,
836 const BookmarkNode
* new_parent
,
841 JNIEnv
* env
= AttachCurrentThread();
842 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
845 Java_BookmarksBridge_bookmarkNodeMoved(
848 CreateJavaBookmark(old_parent
).obj(),
850 CreateJavaBookmark(new_parent
).obj(),
854 void BookmarksBridge::BookmarkNodeAdded(BookmarkModel
* model
,
855 const BookmarkNode
* parent
,
860 JNIEnv
* env
= AttachCurrentThread();
861 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
864 Java_BookmarksBridge_bookmarkNodeAdded(
867 CreateJavaBookmark(parent
).obj(),
871 void BookmarksBridge::BookmarkNodeRemoved(BookmarkModel
* model
,
872 const BookmarkNode
* parent
,
874 const BookmarkNode
* node
,
875 const std::set
<GURL
>& removed_urls
) {
879 JNIEnv
* env
= AttachCurrentThread();
880 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
883 Java_BookmarksBridge_bookmarkNodeRemoved(
886 CreateJavaBookmark(parent
).obj(),
888 CreateJavaBookmark(node
).obj());
891 void BookmarksBridge::BookmarkNodeChanged(BookmarkModel
* model
,
892 const BookmarkNode
* node
) {
896 JNIEnv
* env
= AttachCurrentThread();
897 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
900 Java_BookmarksBridge_bookmarkNodeChanged(
903 CreateJavaBookmark(node
).obj());
906 void BookmarksBridge::BookmarkNodeChildrenReordered(BookmarkModel
* model
,
907 const BookmarkNode
* node
) {
911 JNIEnv
* env
= AttachCurrentThread();
912 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
915 Java_BookmarksBridge_bookmarkNodeChildrenReordered(
918 CreateJavaBookmark(node
).obj());
921 void BookmarksBridge::ExtensiveBookmarkChangesBeginning(BookmarkModel
* model
) {
925 JNIEnv
* env
= AttachCurrentThread();
926 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
929 Java_BookmarksBridge_extensiveBookmarkChangesBeginning(env
, obj
.obj());
932 void BookmarksBridge::ExtensiveBookmarkChangesEnded(BookmarkModel
* model
) {
936 JNIEnv
* env
= AttachCurrentThread();
937 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
940 Java_BookmarksBridge_extensiveBookmarkChangesEnded(env
, obj
.obj());
943 void BookmarksBridge::PartnerShimChanged(PartnerBookmarksShim
* shim
) {
947 BookmarkModelChanged();
950 void BookmarksBridge::PartnerShimLoaded(PartnerBookmarksShim
* shim
) {
951 NotifyIfDoneLoading();
954 void BookmarksBridge::ShimBeingDeleted(PartnerBookmarksShim
* shim
) {
955 partner_bookmarks_shim_
= NULL
;