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/prefs/pref_service.h"
9 #include "chrome/browser/bookmarks/bookmark_model.h"
10 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/profiles/profile_android.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/common/pref_names.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "jni/BookmarksBridge_jni.h"
18 using base::android::AttachCurrentThread;
19 using base::android::ConvertUTF8ToJavaString;
20 using base::android::ConvertUTF16ToJavaString;
21 using base::android::ScopedJavaLocalRef;
22 using base::android::ScopedJavaGlobalRef;
23 using content::BrowserThread;
25 // Should mirror constants in BookmarkBridge.java
26 static const int kBookmarkTypeNormal = 0;
27 static const int kBookmarkTypeManaged = 1;
29 BookmarksBridge::BookmarksBridge(JNIEnv* env,
32 : weak_java_ref_(env, obj) {
33 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
34 Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
35 bookmark_model_ = BookmarkModelFactory::GetForProfile(profile);
37 // Registers the notifications we are interested.
38 bookmark_model_->AddObserver(this);
39 if (bookmark_model_->loaded())
40 Java_BookmarksBridge_bookmarkModelLoaded(env, obj);
42 managed_bookmarks_shim_.reset(new ManagedBookmarksShim(profile->GetPrefs()));
43 managed_bookmarks_shim_->AddObserver(this);
45 // Since a sync or import could have started before this class is
46 // initialized, we need to make sure that our initial state is
48 if (bookmark_model_->IsDoingExtensiveChanges())
49 ExtensiveBookmarkChangesBeginning(bookmark_model_);
52 BookmarksBridge::~BookmarksBridge() {
53 bookmark_model_->RemoveObserver(this);
54 if (managed_bookmarks_shim_)
55 managed_bookmarks_shim_->RemoveObserver(this);
58 void BookmarksBridge::Destroy(JNIEnv*, jobject) {
63 bool BookmarksBridge::RegisterBookmarksBridge(JNIEnv* env) {
64 return RegisterNativesImpl(env);
67 static jint Init(JNIEnv* env, jobject obj, jobject j_profile) {
68 BookmarksBridge* delegate = new BookmarksBridge(env, obj, j_profile);
69 return reinterpret_cast<jint>(delegate);
72 static bool IsEditBookmarksEnabled() {
73 return ProfileManager::GetLastUsedProfile()->GetPrefs()->GetBoolean(
74 prefs::kEditBookmarksEnabled);
77 static jboolean IsEditBookmarksEnabled(JNIEnv* env, jclass clazz) {
78 return IsEditBookmarksEnabled();
81 void BookmarksBridge::GetBookmarksForFolder(JNIEnv* env,
83 jobject j_folder_id_obj,
84 jobject j_callback_obj,
85 jobject j_result_obj) {
86 DCHECK(bookmark_model_->loaded());
87 long folder_id = Java_BookmarkId_getId(env, j_folder_id_obj);
88 int type = Java_BookmarkId_getType(env, j_folder_id_obj);
89 const BookmarkNode* folder = GetFolderWithFallback(folder_id, type);
90 // If this is the Mobile bookmarks folder then add the "Managed bookmarks"
91 // folder first, so that it's the first entry.
92 if (folder == bookmark_model_->mobile_node() &&
93 managed_bookmarks_shim_->HasManagedBookmarks()) {
94 ExtractBookmarkNodeInformation(
95 managed_bookmarks_shim_->GetManagedBookmarksRoot(),
98 // Get the folder contents
99 for (int i = 0; i < folder->child_count(); ++i) {
100 const BookmarkNode* node = folder->GetChild(i);
101 ExtractBookmarkNodeInformation(node, j_result_obj);
104 Java_BookmarksCallback_onBookmarksAvailable(
105 env, j_callback_obj, j_folder_id_obj, j_result_obj);
108 void BookmarksBridge::GetCurrentFolderHierarchy(JNIEnv* env,
110 jobject j_folder_id_obj,
111 jobject j_callback_obj,
112 jobject j_result_obj) {
113 DCHECK(bookmark_model_->loaded());
114 long folder_id = Java_BookmarkId_getId(env, j_folder_id_obj);
115 int type = Java_BookmarkId_getType(env, j_folder_id_obj);
116 const BookmarkNode* folder = GetFolderWithFallback(folder_id, type);
117 // Get the folder heirarchy
118 const BookmarkNode* node = folder;
120 ExtractBookmarkNodeInformation(node, j_result_obj);
121 node = GetParentNode(node);
124 Java_BookmarksCallback_onBookmarksFolderHierarchyAvailable(
125 env, j_callback_obj, j_folder_id_obj, j_result_obj);
128 void BookmarksBridge::DeleteBookmark(JNIEnv* env,
130 jobject j_bookmark_id_obj) {
131 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
132 DCHECK(bookmark_model_->loaded());
134 long bookmark_id = Java_BookmarkId_getId(env, j_bookmark_id_obj);
135 int type = Java_BookmarkId_getType(env, j_bookmark_id_obj);
136 const BookmarkNode* node = GetNodeByID(bookmark_id, type);
137 if (!IsEditable(node)) {
142 const BookmarkNode* parent_node = GetParentNode(node);
143 bookmark_model_->Remove(parent_node, parent_node->GetIndexOf(node));
146 ScopedJavaLocalRef<jobject> BookmarksBridge::CreateJavaBookmark(
147 const BookmarkNode* node) {
148 JNIEnv* env = AttachCurrentThread();
150 const BookmarkNode* parent = GetParentNode(node);
151 int64 parent_id = parent ? parent->id() : -1;
155 url = node->url().spec();
157 return Java_BookmarksBridge_createBookmarkItem(
160 GetBookmarkType(node),
161 ConvertUTF16ToJavaString(env, node->GetTitle()).obj(),
162 ConvertUTF8ToJavaString(env, url).obj(),
165 GetBookmarkType(parent),
169 void BookmarksBridge::ExtractBookmarkNodeInformation(
170 const BookmarkNode* node,
171 jobject j_result_obj) {
172 JNIEnv* env = AttachCurrentThread();
173 Java_BookmarksBridge_addToList(
176 CreateJavaBookmark(node).obj());
179 const BookmarkNode* BookmarksBridge::GetNodeByID(long node_id,
181 const BookmarkNode* node;
182 if (type == kBookmarkTypeManaged) {
183 node = managed_bookmarks_shim_->GetNodeByID(
184 static_cast<int64>(node_id));
186 node = bookmark_model_->GetNodeByID(static_cast<int64>(node_id));
191 const BookmarkNode* BookmarksBridge::GetFolderWithFallback(
192 long folder_id, int type) {
193 const BookmarkNode* folder = GetNodeByID(folder_id, type);
194 if (!folder || folder->type() == BookmarkNode::URL)
195 folder = bookmark_model_->mobile_node();
199 bool BookmarksBridge::IsEditable(const BookmarkNode* node) const {
201 (node->type() == BookmarkNode::FOLDER ||
202 node->type() == BookmarkNode::URL) &&
203 !managed_bookmarks_shim_->IsManagedBookmark(node) &&
204 IsEditBookmarksEnabled();
207 const BookmarkNode* BookmarksBridge::GetParentNode(const BookmarkNode* node) {
208 DCHECK(bookmark_model_->loaded());
209 if (node == managed_bookmarks_shim_->GetManagedBookmarksRoot())
210 return bookmark_model_->mobile_node();
212 return node->parent();
215 int BookmarksBridge::GetBookmarkType(const BookmarkNode* node) {
216 if (managed_bookmarks_shim_->IsManagedBookmark(node))
217 return kBookmarkTypeManaged;
219 return kBookmarkTypeNormal;
222 // ------------- Observer-related methods ------------- //
224 void BookmarksBridge::BookmarkModelChanged() {
225 // Called when there are changes to the bookmark model. It is most
226 // likely changes to either managed or partner bookmarks.
227 JNIEnv* env = AttachCurrentThread();
228 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
231 Java_BookmarksBridge_bookmarkModelChanged(env, obj.obj());
234 void BookmarksBridge::Loaded(BookmarkModel* model, bool ids_reassigned) {
235 JNIEnv* env = AttachCurrentThread();
236 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
239 Java_BookmarksBridge_bookmarkModelLoaded(env, obj.obj());
242 void BookmarksBridge::BookmarkModelBeingDeleted(BookmarkModel* model) {
243 JNIEnv* env = AttachCurrentThread();
244 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
247 Java_BookmarksBridge_bookmarkModelDeleted(env, obj.obj());
250 void BookmarksBridge::BookmarkNodeMoved(BookmarkModel* model,
251 const BookmarkNode* old_parent,
253 const BookmarkNode* new_parent,
255 JNIEnv* env = AttachCurrentThread();
256 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
259 Java_BookmarksBridge_bookmarkNodeMoved(
262 CreateJavaBookmark(old_parent).obj(),
264 CreateJavaBookmark(new_parent).obj(),
268 void BookmarksBridge::BookmarkNodeAdded(BookmarkModel* model,
269 const BookmarkNode* parent,
271 JNIEnv* env = AttachCurrentThread();
272 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
275 Java_BookmarksBridge_bookmarkNodeAdded(
278 CreateJavaBookmark(parent).obj(),
282 void BookmarksBridge::BookmarkNodeRemoved(BookmarkModel* model,
283 const BookmarkNode* parent,
285 const BookmarkNode* node) {
286 JNIEnv* env = AttachCurrentThread();
287 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
290 Java_BookmarksBridge_bookmarkNodeRemoved(
293 CreateJavaBookmark(parent).obj(),
295 CreateJavaBookmark(node).obj());
298 void BookmarksBridge::BookmarkNodeChanged(BookmarkModel* model,
299 const BookmarkNode* node) {
300 JNIEnv* env = AttachCurrentThread();
301 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
304 Java_BookmarksBridge_bookmarkNodeChanged(
307 CreateJavaBookmark(node).obj());
310 void BookmarksBridge::BookmarkNodeChildrenReordered(BookmarkModel* model,
311 const BookmarkNode* node) {
312 JNIEnv* env = AttachCurrentThread();
313 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
316 Java_BookmarksBridge_bookmarkNodeChildrenReordered(
319 CreateJavaBookmark(node).obj());
322 void BookmarksBridge::ExtensiveBookmarkChangesBeginning(BookmarkModel* model) {
323 JNIEnv* env = AttachCurrentThread();
324 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
327 Java_BookmarksBridge_extensiveBookmarkChangesBeginning(env, obj.obj());
330 void BookmarksBridge::ExtensiveBookmarkChangesEnded(BookmarkModel* model) {
331 JNIEnv* env = AttachCurrentThread();
332 ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
335 Java_BookmarksBridge_extensiveBookmarkChangesEnded(env, obj.obj());
338 void BookmarksBridge::OnManagedBookmarksChanged() {
339 BookmarkModelChanged();