- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / android / bookmarks / bookmarks_bridge.cc
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 "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"
17
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;
24
25 // Should mirror constants in BookmarkBridge.java
26 static const int kBookmarkTypeNormal = 0;
27 static const int kBookmarkTypeManaged = 1;
28
29 BookmarksBridge::BookmarksBridge(JNIEnv* env,
30                                  jobject obj,
31                                  jobject j_profile)
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);
36
37   // Registers the notifications we are interested.
38   bookmark_model_->AddObserver(this);
39   if (bookmark_model_->loaded())
40     Java_BookmarksBridge_bookmarkModelLoaded(env, obj);
41
42   managed_bookmarks_shim_.reset(new ManagedBookmarksShim(profile->GetPrefs()));
43   managed_bookmarks_shim_->AddObserver(this);
44
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
47   // up to date.
48   if (bookmark_model_->IsDoingExtensiveChanges())
49     ExtensiveBookmarkChangesBeginning(bookmark_model_);
50 }
51
52 BookmarksBridge::~BookmarksBridge() {
53   bookmark_model_->RemoveObserver(this);
54   if (managed_bookmarks_shim_)
55     managed_bookmarks_shim_->RemoveObserver(this);
56 }
57
58 void BookmarksBridge::Destroy(JNIEnv*, jobject) {
59   delete this;
60 }
61
62 // static
63 bool BookmarksBridge::RegisterBookmarksBridge(JNIEnv* env) {
64   return RegisterNativesImpl(env);
65 }
66
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);
70 }
71
72 static bool IsEditBookmarksEnabled() {
73   return ProfileManager::GetLastUsedProfile()->GetPrefs()->GetBoolean(
74       prefs::kEditBookmarksEnabled);
75 }
76
77 static jboolean IsEditBookmarksEnabled(JNIEnv* env, jclass clazz) {
78   return IsEditBookmarksEnabled();
79 }
80
81 void BookmarksBridge::GetBookmarksForFolder(JNIEnv* env,
82                                             jobject obj,
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(),
96         j_result_obj);
97   }
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);
102   }
103
104   Java_BookmarksCallback_onBookmarksAvailable(
105       env, j_callback_obj, j_folder_id_obj, j_result_obj);
106 }
107
108 void BookmarksBridge::GetCurrentFolderHierarchy(JNIEnv* env,
109                                                 jobject obj,
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;
119   while (node) {
120     ExtractBookmarkNodeInformation(node, j_result_obj);
121     node = GetParentNode(node);
122   }
123
124   Java_BookmarksCallback_onBookmarksFolderHierarchyAvailable(
125       env, j_callback_obj, j_folder_id_obj, j_result_obj);
126 }
127
128 void BookmarksBridge::DeleteBookmark(JNIEnv* env,
129                                      jobject obj,
130                                      jobject j_bookmark_id_obj) {
131   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
132   DCHECK(bookmark_model_->loaded());
133
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)) {
138     NOTREACHED();
139     return;
140   }
141
142   const BookmarkNode* parent_node = GetParentNode(node);
143   bookmark_model_->Remove(parent_node, parent_node->GetIndexOf(node));
144 }
145
146 ScopedJavaLocalRef<jobject> BookmarksBridge::CreateJavaBookmark(
147     const BookmarkNode* node) {
148   JNIEnv* env = AttachCurrentThread();
149
150   const BookmarkNode* parent = GetParentNode(node);
151   int64 parent_id = parent ? parent->id() : -1;
152
153   std::string url;
154   if (node->is_url())
155     url = node->url().spec();
156
157   return Java_BookmarksBridge_createBookmarkItem(
158       env,
159       node->id(),
160       GetBookmarkType(node),
161       ConvertUTF16ToJavaString(env, node->GetTitle()).obj(),
162       ConvertUTF8ToJavaString(env, url).obj(),
163       node->is_folder(),
164       parent_id,
165       GetBookmarkType(parent),
166       IsEditable(node));
167 }
168
169 void BookmarksBridge::ExtractBookmarkNodeInformation(
170     const BookmarkNode* node,
171     jobject j_result_obj) {
172   JNIEnv* env = AttachCurrentThread();
173   Java_BookmarksBridge_addToList(
174       env,
175       j_result_obj,
176       CreateJavaBookmark(node).obj());
177 }
178
179 const BookmarkNode* BookmarksBridge::GetNodeByID(long node_id,
180                                                  int type) {
181   const BookmarkNode* node;
182   if (type == kBookmarkTypeManaged) {
183     node = managed_bookmarks_shim_->GetNodeByID(
184         static_cast<int64>(node_id));
185   } else {
186     node = bookmark_model_->GetNodeByID(static_cast<int64>(node_id));
187   }
188   return node;
189 }
190
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();
196   return folder;
197 }
198
199 bool BookmarksBridge::IsEditable(const BookmarkNode* node) const {
200   return node &&
201       (node->type() == BookmarkNode::FOLDER ||
202           node->type() == BookmarkNode::URL) &&
203       !managed_bookmarks_shim_->IsManagedBookmark(node) &&
204       IsEditBookmarksEnabled();
205 }
206
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();
211   else
212     return node->parent();
213 }
214
215 int BookmarksBridge::GetBookmarkType(const BookmarkNode* node) {
216   if (managed_bookmarks_shim_->IsManagedBookmark(node))
217     return kBookmarkTypeManaged;
218   else
219     return kBookmarkTypeNormal;
220 }
221
222 // ------------- Observer-related methods ------------- //
223
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);
229   if (obj.is_null())
230     return;
231   Java_BookmarksBridge_bookmarkModelChanged(env, obj.obj());
232 }
233
234 void BookmarksBridge::Loaded(BookmarkModel* model, bool ids_reassigned) {
235   JNIEnv* env = AttachCurrentThread();
236   ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
237   if (obj.is_null())
238     return;
239   Java_BookmarksBridge_bookmarkModelLoaded(env, obj.obj());
240 }
241
242 void BookmarksBridge::BookmarkModelBeingDeleted(BookmarkModel* model) {
243   JNIEnv* env = AttachCurrentThread();
244   ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
245   if (obj.is_null())
246     return;
247   Java_BookmarksBridge_bookmarkModelDeleted(env, obj.obj());
248 }
249
250 void BookmarksBridge::BookmarkNodeMoved(BookmarkModel* model,
251                                         const BookmarkNode* old_parent,
252                                         int old_index,
253                                         const BookmarkNode* new_parent,
254                                         int new_index) {
255   JNIEnv* env = AttachCurrentThread();
256   ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
257   if (obj.is_null())
258     return;
259   Java_BookmarksBridge_bookmarkNodeMoved(
260       env,
261       obj.obj(),
262       CreateJavaBookmark(old_parent).obj(),
263       old_index,
264       CreateJavaBookmark(new_parent).obj(),
265       new_index);
266 }
267
268 void BookmarksBridge::BookmarkNodeAdded(BookmarkModel* model,
269                                         const BookmarkNode* parent,
270                                         int index) {
271   JNIEnv* env = AttachCurrentThread();
272   ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
273   if (obj.is_null())
274     return;
275   Java_BookmarksBridge_bookmarkNodeAdded(
276       env,
277       obj.obj(),
278       CreateJavaBookmark(parent).obj(),
279       index);
280 }
281
282 void BookmarksBridge::BookmarkNodeRemoved(BookmarkModel* model,
283                                           const BookmarkNode* parent,
284                                           int old_index,
285                                           const BookmarkNode* node) {
286   JNIEnv* env = AttachCurrentThread();
287   ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
288   if (obj.is_null())
289     return;
290   Java_BookmarksBridge_bookmarkNodeRemoved(
291       env,
292       obj.obj(),
293       CreateJavaBookmark(parent).obj(),
294       old_index,
295       CreateJavaBookmark(node).obj());
296 }
297
298 void BookmarksBridge::BookmarkNodeChanged(BookmarkModel* model,
299                                           const BookmarkNode* node) {
300   JNIEnv* env = AttachCurrentThread();
301   ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
302   if (obj.is_null())
303     return;
304   Java_BookmarksBridge_bookmarkNodeChanged(
305       env,
306       obj.obj(),
307       CreateJavaBookmark(node).obj());
308 }
309
310 void BookmarksBridge::BookmarkNodeChildrenReordered(BookmarkModel* model,
311                                                     const BookmarkNode* node) {
312   JNIEnv* env = AttachCurrentThread();
313   ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
314   if (obj.is_null())
315     return;
316   Java_BookmarksBridge_bookmarkNodeChildrenReordered(
317       env,
318       obj.obj(),
319       CreateJavaBookmark(node).obj());
320 }
321
322 void BookmarksBridge::ExtensiveBookmarkChangesBeginning(BookmarkModel* model) {
323   JNIEnv* env = AttachCurrentThread();
324   ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
325   if (obj.is_null())
326     return;
327   Java_BookmarksBridge_extensiveBookmarkChangesBeginning(env, obj.obj());
328 }
329
330 void BookmarksBridge::ExtensiveBookmarkChangesEnded(BookmarkModel* model) {
331   JNIEnv* env = AttachCurrentThread();
332   ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
333   if (obj.is_null())
334     return;
335   Java_BookmarksBridge_extensiveBookmarkChangesEnded(env, obj.obj());
336 }
337
338 void BookmarksBridge::OnManagedBookmarksChanged() {
339   BookmarkModelChanged();
340 }