15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> // For floor() 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/bookmarks/chrome_bookmark_client.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/api/bookmarks.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_model.h" 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_utils.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace keys = bookmark_api_constants; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using api::bookmarks::BookmarkTreeNode; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace bookmark_api_helpers { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AddNodeHelper(ChromeBookmarkClient* client, 2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const BookmarkNode* node, 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<linked_ptr<BookmarkTreeNode> >* nodes, 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool recurse, 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool only_folders) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->IsVisible()) { 3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) linked_ptr<BookmarkTreeNode> new_node(GetBookmarkTreeNode(client, 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node, 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recurse, 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) only_folders)); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes->push_back(new_node); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)BookmarkTreeNode* GetBookmarkTreeNode(ChromeBookmarkClient* client, 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const BookmarkNode* node, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool recurse, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool only_folders) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkTreeNode* bookmark_tree_node = new BookmarkTreeNode; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_tree_node->id = base::Int64ToString(node->id()); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent = node->parent(); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_tree_node->parent_id.reset(new std::string( 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Int64ToString(parent->id()))); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_tree_node->index.reset(new int(parent->GetIndexOf(node))); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node->is_folder()) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_tree_node->url.reset(new std::string(node->url().spec())); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Javascript Date wants milliseconds since the epoch, ToDoubleT is seconds. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time t = node->date_folder_modified(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!t.is_null()) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_tree_node->date_group_modified.reset( 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new double(floor(t.ToDoubleT() * 1000))); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bookmark_tree_node->title = base::UTF16ToUTF8(node->GetTitle()); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node->date_added().is_null()) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Javascript Date wants milliseconds since the epoch, ToDoubleT is seconds. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_tree_node->date_added.reset( 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new double(floor(node->date_added().ToDoubleT() * 1000))); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (client->IsDescendantOfManagedNode(node)) 7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bookmark_tree_node->unmodifiable = BookmarkTreeNode::UNMODIFIABLE_MANAGED; 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (recurse && node->is_folder()) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<linked_ptr<BookmarkTreeNode> > children; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < node->child_count(); ++i) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* child = node->GetChild(i); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child->IsVisible() && (!only_folders || child->is_folder())) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) linked_ptr<BookmarkTreeNode> child_node( 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) GetBookmarkTreeNode(client, child, true, only_folders)); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) children.push_back(child_node); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_tree_node->children.reset( 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new std::vector<linked_ptr<BookmarkTreeNode> >(children)); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bookmark_tree_node; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AddNode(ChromeBookmarkClient* client, 9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const BookmarkNode* node, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<linked_ptr<BookmarkTreeNode> >* nodes, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool recurse) { 9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return AddNodeHelper(client, node, nodes, recurse, false); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AddNodeFoldersOnly(ChromeBookmarkClient* client, 10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const BookmarkNode* node, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<linked_ptr<BookmarkTreeNode> >* nodes, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool recurse) { 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return AddNodeHelper(client, node, nodes, recurse, true); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool RemoveNode(BookmarkModel* model, 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ChromeBookmarkClient* client, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool recursive, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error) { 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const BookmarkNode* node = bookmarks::GetBookmarkNodeByID(model, id); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error = keys::kNoNodeError; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model->is_permanent_node(node)) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error = keys::kModifySpecialError; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (client->IsDescendantOfManagedNode(node)) { 12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) *error = keys::kModifyManagedError; 12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->is_folder() && !node->empty() && !recursive) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error = keys::kFolderNotEmptyError; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent = node->parent(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->Remove(parent, parent->GetIndexOf(node)); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void GetMetaInfo(const BookmarkNode& node, 1386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) base::DictionaryValue* id_to_meta_info_map) { 1396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!node.IsVisible()) 1406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 1416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const BookmarkNode::MetaInfoMap* meta_info = node.GetMetaInfoMap(); 1436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) base::DictionaryValue* value = new base::DictionaryValue(); 1446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (meta_info) { 1456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) BookmarkNode::MetaInfoMap::const_iterator itr; 1466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (itr = meta_info->begin(); itr != meta_info->end(); ++itr) { 1476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) value->SetStringWithoutPathExpansion(itr->first, itr->second); 1486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) id_to_meta_info_map->Set(base::Int64ToString(node.id()), value); 1516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (node.is_folder()) { 1536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (int i = 0; i < node.child_count(); ++i) { 1546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) GetMetaInfo(*(node.GetChild(i)), id_to_meta_info_map); 1556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 1586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace bookmark_api_helpers 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace extensions 161