Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / android / bookmarks / bookmarks_bridge.cc
index 7cd704a..6dcb559 100644 (file)
@@ -6,17 +6,23 @@
 
 #include "base/android/jni_string.h"
 #include "base/containers/stack_container.h"
+#include "base/i18n/string_compare.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/chrome_bookmark_client_factory.h"
+#include "chrome/browser/bookmarks/enhanced_bookmarks_features.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/undo/bookmark_undo_service.h"
+#include "chrome/browser/undo/bookmark_undo_service_factory.h"
+#include "chrome/browser/undo/undo_manager.h"
 #include "chrome/common/pref_names.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/browser/bookmark_utils.h"
+#include "components/bookmarks/browser/scoped_group_bookmark_actions.h"
 #include "components/bookmarks/common/android/bookmark_type.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "content/public/browser/browser_thread.h"
@@ -40,6 +46,35 @@ class BookmarkNodeCreationTimeCompareFunctor {
     return lhs->date_added().ToJavaTime() > rhs->date_added().ToJavaTime();
   }
 };
+
+class BookmarkTitleComparer {
+ public:
+  explicit BookmarkTitleComparer(const icu::Collator* collator)
+      : collator_(collator) {}
+
+  bool operator()(const BookmarkNode* lhs, const BookmarkNode* rhs) {
+    if (collator_) {
+      return base::i18n::CompareString16WithCollator(
+          collator_, lhs->GetTitle(), rhs->GetTitle()) == UCOL_LESS;
+    } else {
+      return lhs->GetTitle() < rhs->GetTitle();
+    }
+  }
+
+private:
+  const icu::Collator* collator_;
+};
+
+scoped_ptr<icu::Collator> GetICUCollator() {
+  UErrorCode error = U_ZERO_ERROR;
+  scoped_ptr<icu::Collator> collator_;
+  collator_.reset(icu::Collator::createInstance(error));
+  if (U_FAILURE(error))
+    collator_.reset(NULL);
+
+  return collator_.Pass();
+}
+
 }  // namespace
 
 BookmarksBridge::BookmarksBridge(JNIEnv* env,
@@ -94,20 +129,36 @@ static jlong Init(JNIEnv* env, jobject obj, jobject j_profile) {
 static jlong GetNativeBookmarkModel(JNIEnv* env,
                                     jclass caller,
                                     jobject j_profile) {
-  Profile *profile = ProfileAndroid::FromProfileAndroid(j_profile);
+  Profileprofile = ProfileAndroid::FromProfileAndroid(j_profile);
   BookmarkModel *bookmark_model_ = BookmarkModelFactory::GetForProfile(profile);
   return reinterpret_cast<jlong>(bookmark_model_);
 }
 
+static jboolean IsEnhancedBookmarksFeatureEnabled(JNIEnv* env,
+                                                  jclass clazz,
+                                                  jobject j_profile) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
+  return IsEnhancedBookmarksEnabled(profile->GetPrefs());
+}
+
 static bool IsEditBookmarksEnabled() {
   return ProfileManager::GetLastUsedProfile()->GetPrefs()->GetBoolean(
-      prefs::kEditBookmarksEnabled);
+      bookmarks::prefs::kEditBookmarksEnabled);
 }
 
 static jboolean IsEditBookmarksEnabled(JNIEnv* env, jclass clazz) {
   return IsEditBookmarksEnabled();
 }
 
+void BookmarksBridge::LoadEmptyPartnerBookmarkShimForTesting(JNIEnv* env,
+                                                             jobject obj) {
+  if (partner_bookmarks_shim_->IsLoaded())
+      return;
+  partner_bookmarks_shim_->SetPartnerBookmarksRoot(
+      new BookmarkPermanentNode(0));
+  DCHECK(partner_bookmarks_shim_->IsLoaded());
+}
+
 ScopedJavaLocalRef<jobject> BookmarksBridge::GetBookmarkByID(JNIEnv* env,
                                                              jobject obj,
                                                              jlong id,
@@ -116,9 +167,14 @@ ScopedJavaLocalRef<jobject> BookmarksBridge::GetBookmarkByID(JNIEnv* env,
   return CreateJavaBookmark(GetNodeByID(id, type));
 }
 
+bool BookmarksBridge::IsDoingExtensiveChanges(JNIEnv* env, jobject obj) {
+  return bookmark_model_->IsDoingExtensiveChanges();
+}
+
 void BookmarksBridge::GetPermanentNodeIDs(JNIEnv* env,
                                           jobject obj,
                                           jobject j_result_obj) {
+  // TODO(kkimlabs): Remove this function.
   DCHECK(IsLoaded());
 
   base::StackVector<const BookmarkNode*, 8> permanent_nodes;
@@ -144,6 +200,200 @@ void BookmarksBridge::GetPermanentNodeIDs(JNIEnv* env,
   }
 }
 
+void BookmarksBridge::GetTopLevelFolderParentIDs(JNIEnv* env,
+                                                 jobject obj,
+                                                 jobject j_result_obj) {
+  Java_BookmarksBridge_addToBookmarkIdList(
+      env, j_result_obj, bookmark_model_->root_node()->id(),
+      GetBookmarkType(bookmark_model_->root_node()));
+  Java_BookmarksBridge_addToBookmarkIdList(
+      env, j_result_obj, bookmark_model_->mobile_node()->id(),
+      GetBookmarkType(bookmark_model_->mobile_node()));
+  Java_BookmarksBridge_addToBookmarkIdList(
+      env, j_result_obj, bookmark_model_->other_node()->id(),
+      GetBookmarkType(bookmark_model_->other_node()));
+}
+
+void BookmarksBridge::GetTopLevelFolderIDs(JNIEnv* env,
+                                           jobject obj,
+                                           jboolean get_special,
+                                           jboolean get_normal,
+                                           jobject j_result_obj) {
+  DCHECK(IsLoaded());
+  std::vector<const BookmarkNode*> top_level_folders;
+
+  if (get_special) {
+    if (client_->managed_node() &&
+        client_->managed_node()->child_count() > 0) {
+      top_level_folders.push_back(client_->managed_node());
+    }
+    if (partner_bookmarks_shim_->HasPartnerBookmarks()) {
+      top_level_folders.push_back(
+          partner_bookmarks_shim_->GetPartnerBookmarksRoot());
+    }
+  }
+  std::size_t special_count = top_level_folders.size();
+
+  if (get_normal) {
+    DCHECK_EQ(bookmark_model_->root_node()->child_count(), 4);
+
+    top_level_folders.push_back(bookmark_model_->bookmark_bar_node());
+
+    const BookmarkNode* mobile_node = bookmark_model_->mobile_node();
+    for (int i = 0; i < mobile_node->child_count(); ++i) {
+      const BookmarkNode* node = mobile_node->GetChild(i);
+      if (node->is_folder()) {
+        top_level_folders.push_back(node);
+      }
+    }
+
+    const BookmarkNode* other_node = bookmark_model_->other_node();
+    for (int i = 0; i < other_node->child_count(); ++i) {
+      const BookmarkNode* node = other_node->GetChild(i);
+      if (node->is_folder()) {
+        top_level_folders.push_back(node);
+      }
+    }
+
+    scoped_ptr<icu::Collator> collator = GetICUCollator();
+    std::stable_sort(top_level_folders.begin() + special_count,
+                     top_level_folders.end(),
+                     BookmarkTitleComparer(collator.get()));
+  }
+
+  for (std::vector<const BookmarkNode*>::const_iterator it =
+      top_level_folders.begin(); it != top_level_folders.end(); ++it) {
+    Java_BookmarksBridge_addToBookmarkIdList(env,
+                                             j_result_obj,
+                                             (*it)->id(),
+                                             GetBookmarkType(*it));
+  }
+}
+
+void BookmarksBridge::GetUncategorizedBookmarkIDs(JNIEnv* env,
+                                                  jobject obj,
+                                                  jobject j_result_obj) {
+  const BookmarkNode* mobile_node = bookmark_model_->mobile_node();
+  for (int i = 0; i < mobile_node->child_count(); ++i) {
+    const BookmarkNode* node = mobile_node->GetChild(i);
+    if (!node->is_folder()) {
+      Java_BookmarksBridge_addToBookmarkIdList(env,
+                                               j_result_obj,
+                                               node->id(),
+                                               GetBookmarkType(node));
+    }
+  }
+
+  const BookmarkNode* other_node = bookmark_model_->other_node();
+  for (int i = 0; i < other_node->child_count(); ++i) {
+    const BookmarkNode* node = other_node->GetChild(i);
+    if (!node->is_folder()) {
+      Java_BookmarksBridge_addToBookmarkIdList(env,
+                                               j_result_obj,
+                                               node->id(),
+                                               GetBookmarkType(node));
+    }
+  }
+}
+
+void BookmarksBridge::GetAllFoldersWithDepths(JNIEnv* env,
+                                              jobject obj,
+                                              jobject j_folders_obj,
+                                              jobject j_depths_obj) {
+  DCHECK(IsLoaded());
+
+  const BookmarkNode* desktop = bookmark_model_->bookmark_bar_node();
+  const BookmarkNode* mobile = bookmark_model_->mobile_node();
+  const BookmarkNode* other = bookmark_model_->other_node();
+
+  scoped_ptr<icu::Collator> collator = GetICUCollator();
+
+  // Vector to temporarily contain all child bookmarks at same level for sorting
+  std::vector<const BookmarkNode*> bookmarkList;
+  // Stack for Depth-First Search of bookmark model. It stores nodes and their
+  // heights.
+  std::stack<std::pair<const BookmarkNode*, int> > stk;
+
+  for (int i = 0; i < mobile->child_count(); ++i) {
+    const BookmarkNode* child = mobile->GetChild(i);
+    if (child->is_folder() && client_->CanBeEditedByUser(child))
+      bookmarkList.push_back(child);
+  }
+  for (int i = 0; i < other->child_count(); ++i) {
+    const BookmarkNode* child = other->GetChild(i);
+    if (child->is_folder() && client_->CanBeEditedByUser(child))
+      bookmarkList.push_back(child);
+  }
+  bookmarkList.push_back(desktop);
+  std::stable_sort(bookmarkList.begin(),
+                   bookmarkList.end(),
+                   BookmarkTitleComparer(collator.get()));
+
+  // Push all sorted top folders in stack and give them depth of 0.
+  // Note the order to push folders to stack should be opposite to the order in
+  // output.
+  for (std::vector<const BookmarkNode*>::reverse_iterator it =
+           bookmarkList.rbegin();
+       it != bookmarkList.rend();
+       ++it) {
+    stk.push(std::make_pair(*it, 0));
+  }
+
+  while (!stk.empty()) {
+    const BookmarkNode* node = stk.top().first;
+    int depth = stk.top().second;
+    stk.pop();
+    Java_BookmarksBridge_addToBookmarkIdListWithDepth(env,
+                                                      j_folders_obj,
+                                                      node->id(),
+                                                      GetBookmarkType(node),
+                                                      j_depths_obj,
+                                                      depth);
+    bookmarkList.clear();
+    for (int i = 0; i < node->child_count(); ++i) {
+      const BookmarkNode* child = node->GetChild(i);
+      if (child->is_folder() && client_->CanBeEditedByUser(child))
+        bookmarkList.push_back(node->GetChild(i));
+    }
+    std::stable_sort(bookmarkList.begin(),
+                     bookmarkList.end(),
+                     BookmarkTitleComparer(collator.get()));
+    for (std::vector<const BookmarkNode*>::reverse_iterator it =
+             bookmarkList.rbegin();
+         it != bookmarkList.rend();
+         ++it) {
+      stk.push(std::make_pair(*it, depth + 1));
+    }
+  }
+}
+
+ScopedJavaLocalRef<jobject> BookmarksBridge::GetMobileFolderId(JNIEnv* env,
+                                                               jobject obj) {
+  const BookmarkNode* mobile_node = bookmark_model_->mobile_node();
+  ScopedJavaLocalRef<jobject> folder_id_obj =
+      Java_BookmarksBridge_createBookmarkId(
+          env, mobile_node->id(), GetBookmarkType(mobile_node));
+  return folder_id_obj;
+}
+
+ScopedJavaLocalRef<jobject> BookmarksBridge::GetOtherFolderId(JNIEnv* env,
+                                                              jobject obj) {
+  const BookmarkNode* other_node = bookmark_model_->other_node();
+  ScopedJavaLocalRef<jobject> folder_id_obj =
+      Java_BookmarksBridge_createBookmarkId(
+          env, other_node->id(), GetBookmarkType(other_node));
+  return folder_id_obj;
+}
+
+ScopedJavaLocalRef<jobject> BookmarksBridge::GetDesktopFolderId(JNIEnv* env,
+                                                                jobject obj) {
+  const BookmarkNode* desktop_node = bookmark_model_->bookmark_bar_node();
+  ScopedJavaLocalRef<jobject> folder_id_obj =
+      Java_BookmarksBridge_createBookmarkId(
+          env, desktop_node->id(), GetBookmarkType(desktop_node));
+  return folder_id_obj;
+}
+
 void BookmarksBridge::GetChildIDs(JNIEnv* env,
                                   jobject obj,
                                   jlong id,
@@ -331,6 +581,28 @@ void BookmarksBridge::GetCurrentFolderHierarchy(JNIEnv* env,
       env, j_callback_obj, j_folder_id_obj, j_result_obj);
 }
 
+ScopedJavaLocalRef<jobject> BookmarksBridge::AddFolder(JNIEnv* env,
+                                                       jobject obj,
+                                                       jobject j_parent_id_obj,
+                                                       jint index,
+                                                       jstring j_title) {
+  DCHECK(IsLoaded());
+  long bookmark_id = JavaBookmarkIdGetId(env, j_parent_id_obj);
+  int type = JavaBookmarkIdGetType(env, j_parent_id_obj);
+  const BookmarkNode* parent = GetNodeByID(bookmark_id, type);
+
+  const BookmarkNode* new_node = bookmark_model_->AddFolder(
+      parent, index, base::android::ConvertJavaStringToUTF16(env, j_title));
+  if (!new_node) {
+    NOTREACHED();
+    return ScopedJavaLocalRef<jobject>();
+  }
+  ScopedJavaLocalRef<jobject> new_java_obj =
+      Java_BookmarksBridge_createBookmarkId(
+          env, new_node->id(), GetBookmarkType(new_node));
+  return new_java_obj;
+}
+
 void BookmarksBridge::DeleteBookmark(JNIEnv* env,
                                      jobject obj,
                                      jobject j_bookmark_id_obj) {
@@ -374,6 +646,57 @@ void BookmarksBridge::MoveBookmark(JNIEnv* env,
   bookmark_model_->Move(node, new_parent_node, index);
 }
 
+ScopedJavaLocalRef<jobject> BookmarksBridge::AddBookmark(
+    JNIEnv* env,
+    jobject obj,
+    jobject j_parent_id_obj,
+    jint index,
+    jstring j_title,
+    jstring j_url) {
+  DCHECK(IsLoaded());
+  long bookmark_id = JavaBookmarkIdGetId(env, j_parent_id_obj);
+  int type = JavaBookmarkIdGetType(env, j_parent_id_obj);
+  const BookmarkNode* parent = GetNodeByID(bookmark_id, type);
+
+  const BookmarkNode* new_node = bookmark_model_->AddURL(
+      parent,
+      index,
+      base::android::ConvertJavaStringToUTF16(env, j_title),
+      GURL(base::android::ConvertJavaStringToUTF16(env, j_url)));
+  if (!new_node) {
+    NOTREACHED();
+    return ScopedJavaLocalRef<jobject>();
+  }
+  ScopedJavaLocalRef<jobject> new_java_obj =
+      Java_BookmarksBridge_createBookmarkId(
+          env, new_node->id(), GetBookmarkType(new_node));
+  return new_java_obj;
+}
+
+void BookmarksBridge::Undo(JNIEnv* env, jobject obj) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(IsLoaded());
+  BookmarkUndoService* undo_service =
+      BookmarkUndoServiceFactory::GetForProfile(profile_);
+  UndoManager* undo_manager = undo_service->undo_manager();
+  undo_manager->Undo();
+}
+
+void BookmarksBridge::StartGroupingUndos(JNIEnv* env, jobject obj) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(IsLoaded());
+  DCHECK(!grouped_bookmark_actions_.get()); // shouldn't have started already
+  grouped_bookmark_actions_.reset(
+      new bookmarks::ScopedGroupBookmarkActions(bookmark_model_));
+}
+
+void BookmarksBridge::EndGroupingUndos(JNIEnv* env, jobject obj) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(IsLoaded());
+  DCHECK(grouped_bookmark_actions_.get()); // should only call after start
+  grouped_bookmark_actions_.reset();
+}
+
 ScopedJavaLocalRef<jobject> BookmarksBridge::CreateJavaBookmark(
     const BookmarkNode* node) {
   JNIEnv* env = AttachCurrentThread();
@@ -491,7 +814,7 @@ bool BookmarksBridge::IsFolderAvailable(
       profile_->GetOriginalProfile());
   return (folder->type() != BookmarkNode::BOOKMARK_BAR &&
       folder->type() != BookmarkNode::OTHER_NODE) ||
-      (signin && !signin->GetAuthenticatedUsername().empty());
+      (signin && signin->IsAuthenticated());
 }
 
 void BookmarksBridge::NotifyIfDoneLoading() {