1 // Copyright (c) 2012 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/extensions/api/bookmarks/bookmark_api_helpers.h" 6 7 #include <math.h> // For floor() 8 #include <vector> 9 10 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "chrome/browser/bookmarks/chrome_bookmark_client.h" 13 #include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h" 14 #include "chrome/common/extensions/api/bookmarks.h" 15 #include "components/bookmarks/browser/bookmark_model.h" 16 #include "components/bookmarks/browser/bookmark_utils.h" 17 18 namespace extensions { 19 20 namespace keys = bookmark_api_constants; 21 using api::bookmarks::BookmarkTreeNode; 22 23 namespace bookmark_api_helpers { 24 25 namespace { 26 27 void AddNodeHelper(ChromeBookmarkClient* client, 28 const BookmarkNode* node, 29 std::vector<linked_ptr<BookmarkTreeNode> >* nodes, 30 bool recurse, 31 bool only_folders) { 32 if (node->IsVisible()) { 33 linked_ptr<BookmarkTreeNode> new_node(GetBookmarkTreeNode(client, 34 node, 35 recurse, 36 only_folders)); 37 nodes->push_back(new_node); 38 } 39 } 40 41 } // namespace 42 43 BookmarkTreeNode* GetBookmarkTreeNode(ChromeBookmarkClient* client, 44 const BookmarkNode* node, 45 bool recurse, 46 bool only_folders) { 47 BookmarkTreeNode* bookmark_tree_node = new BookmarkTreeNode; 48 49 bookmark_tree_node->id = base::Int64ToString(node->id()); 50 51 const BookmarkNode* parent = node->parent(); 52 if (parent) { 53 bookmark_tree_node->parent_id.reset(new std::string( 54 base::Int64ToString(parent->id()))); 55 bookmark_tree_node->index.reset(new int(parent->GetIndexOf(node))); 56 } 57 58 if (!node->is_folder()) { 59 bookmark_tree_node->url.reset(new std::string(node->url().spec())); 60 } else { 61 // Javascript Date wants milliseconds since the epoch, ToDoubleT is seconds. 62 base::Time t = node->date_folder_modified(); 63 if (!t.is_null()) { 64 bookmark_tree_node->date_group_modified.reset( 65 new double(floor(t.ToDoubleT() * 1000))); 66 } 67 } 68 69 bookmark_tree_node->title = base::UTF16ToUTF8(node->GetTitle()); 70 if (!node->date_added().is_null()) { 71 // Javascript Date wants milliseconds since the epoch, ToDoubleT is seconds. 72 bookmark_tree_node->date_added.reset( 73 new double(floor(node->date_added().ToDoubleT() * 1000))); 74 } 75 76 if (client->IsDescendantOfManagedNode(node)) 77 bookmark_tree_node->unmodifiable = BookmarkTreeNode::UNMODIFIABLE_MANAGED; 78 79 if (recurse && node->is_folder()) { 80 std::vector<linked_ptr<BookmarkTreeNode> > children; 81 for (int i = 0; i < node->child_count(); ++i) { 82 const BookmarkNode* child = node->GetChild(i); 83 if (child->IsVisible() && (!only_folders || child->is_folder())) { 84 linked_ptr<BookmarkTreeNode> child_node( 85 GetBookmarkTreeNode(client, child, true, only_folders)); 86 children.push_back(child_node); 87 } 88 } 89 bookmark_tree_node->children.reset( 90 new std::vector<linked_ptr<BookmarkTreeNode> >(children)); 91 } 92 return bookmark_tree_node; 93 } 94 95 void AddNode(ChromeBookmarkClient* client, 96 const BookmarkNode* node, 97 std::vector<linked_ptr<BookmarkTreeNode> >* nodes, 98 bool recurse) { 99 return AddNodeHelper(client, node, nodes, recurse, false); 100 } 101 102 void AddNodeFoldersOnly(ChromeBookmarkClient* client, 103 const BookmarkNode* node, 104 std::vector<linked_ptr<BookmarkTreeNode> >* nodes, 105 bool recurse) { 106 return AddNodeHelper(client, node, nodes, recurse, true); 107 } 108 109 bool RemoveNode(BookmarkModel* model, 110 ChromeBookmarkClient* client, 111 int64 id, 112 bool recursive, 113 std::string* error) { 114 const BookmarkNode* node = GetBookmarkNodeByID(model, id); 115 if (!node) { 116 *error = keys::kNoNodeError; 117 return false; 118 } 119 if (model->is_permanent_node(node)) { 120 *error = keys::kModifySpecialError; 121 return false; 122 } 123 if (client->IsDescendantOfManagedNode(node)) { 124 *error = keys::kModifyManagedError; 125 return false; 126 } 127 if (node->is_folder() && !node->empty() && !recursive) { 128 *error = keys::kFolderNotEmptyError; 129 return false; 130 } 131 132 const BookmarkNode* parent = node->parent(); 133 model->Remove(parent, parent->GetIndexOf(node)); 134 return true; 135 } 136 137 void GetMetaInfo(const BookmarkNode& node, 138 base::DictionaryValue* id_to_meta_info_map) { 139 if (!node.IsVisible()) 140 return; 141 142 const BookmarkNode::MetaInfoMap* meta_info = node.GetMetaInfoMap(); 143 base::DictionaryValue* value = new base::DictionaryValue(); 144 if (meta_info) { 145 BookmarkNode::MetaInfoMap::const_iterator itr; 146 for (itr = meta_info->begin(); itr != meta_info->end(); ++itr) { 147 value->SetStringWithoutPathExpansion(itr->first, itr->second); 148 } 149 } 150 id_to_meta_info_map->Set(base::Int64ToString(node.id()), value); 151 152 if (node.is_folder()) { 153 for (int i = 0; i < node.child_count(); ++i) { 154 GetMetaInfo(*(node.GetChild(i)), id_to_meta_info_map); 155 } 156 } 157 } 158 159 } // namespace bookmark_api_helpers 160 } // namespace extensions 161