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 "base/memory/scoped_ptr.h" 8 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "base/values.h" 11 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 12 #include "chrome/browser/bookmarks/chrome_bookmark_client.h" 13 #include "chrome/browser/bookmarks/chrome_bookmark_client_factory.h" 14 #include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h" 15 #include "chrome/common/extensions/api/bookmarks.h" 16 #include "chrome/test/base/testing_profile.h" 17 #include "components/bookmarks/browser/bookmark_model.h" 18 #include "components/bookmarks/test/bookmark_test_helpers.h" 19 #include "content/public/test/test_browser_thread_bundle.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 22 namespace extensions { 23 24 namespace keys = bookmark_api_constants; 25 using api::bookmarks::BookmarkTreeNode; 26 27 namespace bookmark_api_helpers { 28 29 class ExtensionBookmarksTest : public testing::Test { 30 public: 31 ExtensionBookmarksTest() 32 : client_(NULL), model_(NULL), node_(NULL), node2_(NULL), folder_(NULL) {} 33 34 virtual void SetUp() OVERRIDE { 35 profile_.CreateBookmarkModel(false); 36 model_ = BookmarkModelFactory::GetForProfile(&profile_); 37 client_ = ChromeBookmarkClientFactory::GetForProfile(&profile_); 38 test::WaitForBookmarkModelToLoad(model_); 39 40 node_ = model_->AddURL(model_->other_node(), 0, base::ASCIIToUTF16("Digg"), 41 GURL("http://www.reddit.com")); 42 model_->SetNodeMetaInfo(node_, "some_key1", "some_value1"); 43 model_->SetNodeMetaInfo(node_, "some_key2", "some_value2"); 44 model_->AddURL(model_->other_node(), 0, base::ASCIIToUTF16("News"), 45 GURL("http://www.foxnews.com")); 46 folder_ = model_->AddFolder( 47 model_->other_node(), 0, base::ASCIIToUTF16("outer folder")); 48 model_->SetNodeMetaInfo(folder_, "some_key1", "some_value1"); 49 model_->AddFolder(folder_, 0, base::ASCIIToUTF16("inner folder 1")); 50 model_->AddFolder(folder_, 0, base::ASCIIToUTF16("inner folder 2")); 51 node2_ = model_->AddURL( 52 folder_, 0, base::ASCIIToUTF16("Digg"), GURL("http://reddit.com")); 53 model_->SetNodeMetaInfo(node2_, "some_key2", "some_value2"); 54 model_->AddURL( 55 folder_, 0, base::ASCIIToUTF16("CNet"), GURL("http://cnet.com")); 56 } 57 58 content::TestBrowserThreadBundle thread_bundle_; 59 TestingProfile profile_; 60 ChromeBookmarkClient* client_; 61 BookmarkModel* model_; 62 const BookmarkNode* node_; 63 const BookmarkNode* node2_; 64 const BookmarkNode* folder_; 65 }; 66 67 TEST_F(ExtensionBookmarksTest, GetFullTreeFromRoot) { 68 scoped_ptr<BookmarkTreeNode> tree( 69 GetBookmarkTreeNode(client_, 70 model_->other_node(), 71 true, // Recurse. 72 false)); // Not only folders. 73 ASSERT_EQ(3U, tree->children->size()); 74 } 75 76 TEST_F(ExtensionBookmarksTest, GetFoldersOnlyFromRoot) { 77 scoped_ptr<BookmarkTreeNode> tree( 78 GetBookmarkTreeNode(client_, 79 model_->other_node(), 80 true, // Recurse. 81 true)); // Only folders. 82 ASSERT_EQ(1U, tree->children->size()); 83 } 84 85 TEST_F(ExtensionBookmarksTest, GetSubtree) { 86 scoped_ptr<BookmarkTreeNode> tree( 87 GetBookmarkTreeNode(client_, 88 folder_, 89 true, // Recurse. 90 false)); // Not only folders. 91 ASSERT_EQ(4U, tree->children->size()); 92 linked_ptr<BookmarkTreeNode> digg = tree->children->at(1); 93 ASSERT_TRUE(digg.get()); 94 ASSERT_EQ("Digg", digg->title); 95 } 96 97 TEST_F(ExtensionBookmarksTest, GetSubtreeFoldersOnly) { 98 scoped_ptr<BookmarkTreeNode> tree( 99 GetBookmarkTreeNode(client_, 100 folder_, 101 true, // Recurse. 102 true)); // Only folders. 103 ASSERT_EQ(2U, tree->children->size()); 104 linked_ptr<BookmarkTreeNode> inner_folder = tree->children->at(1); 105 ASSERT_TRUE(inner_folder.get()); 106 ASSERT_EQ("inner folder 1", inner_folder->title); 107 } 108 109 TEST_F(ExtensionBookmarksTest, GetModifiableNode) { 110 scoped_ptr<BookmarkTreeNode> tree( 111 GetBookmarkTreeNode(client_, 112 node_, 113 false, // Recurse. 114 false)); // Only folders. 115 EXPECT_EQ("Digg", tree->title); 116 ASSERT_TRUE(tree->url); 117 EXPECT_EQ("http://www.reddit.com/", *tree->url); 118 EXPECT_EQ(BookmarkTreeNode::UNMODIFIABLE_NONE, tree->unmodifiable); 119 } 120 121 TEST_F(ExtensionBookmarksTest, GetManagedNode) { 122 const BookmarkNode* managed_bookmark = 123 model_->AddURL(client_->managed_node(), 124 0, 125 base::ASCIIToUTF16("Chromium"), 126 GURL("http://www.chromium.org/")); 127 scoped_ptr<BookmarkTreeNode> tree( 128 GetBookmarkTreeNode(client_, 129 managed_bookmark, 130 false, // Recurse. 131 false)); // Only folders. 132 EXPECT_EQ("Chromium", tree->title); 133 EXPECT_EQ("http://www.chromium.org/", *tree->url); 134 EXPECT_EQ(BookmarkTreeNode::UNMODIFIABLE_MANAGED, tree->unmodifiable); 135 } 136 137 TEST_F(ExtensionBookmarksTest, RemoveNodeInvalidId) { 138 int64 invalid_id = model_->next_node_id(); 139 std::string error; 140 EXPECT_FALSE(RemoveNode(model_, client_, invalid_id, true, &error)); 141 EXPECT_EQ(keys::kNoNodeError, error); 142 } 143 144 TEST_F(ExtensionBookmarksTest, RemoveNodePermanent) { 145 std::string error; 146 EXPECT_FALSE( 147 RemoveNode(model_, client_, model_->other_node()->id(), true, &error)); 148 EXPECT_EQ(keys::kModifySpecialError, error); 149 } 150 151 TEST_F(ExtensionBookmarksTest, RemoveNodeManaged) { 152 const BookmarkNode* managed_bookmark = 153 model_->AddURL(client_->managed_node(), 154 0, 155 base::ASCIIToUTF16("Chromium"), 156 GURL("http://www.chromium.org")); 157 std::string error; 158 EXPECT_FALSE( 159 RemoveNode(model_, client_, managed_bookmark->id(), true, &error)); 160 EXPECT_EQ(keys::kModifyManagedError, error); 161 } 162 163 TEST_F(ExtensionBookmarksTest, RemoveNodeNotRecursive) { 164 std::string error; 165 EXPECT_FALSE(RemoveNode(model_, client_, folder_->id(), false, &error)); 166 EXPECT_EQ(keys::kFolderNotEmptyError, error); 167 } 168 169 TEST_F(ExtensionBookmarksTest, RemoveNodeRecursive) { 170 EXPECT_EQ(3, model_->other_node()->child_count()); 171 std::string error; 172 EXPECT_TRUE(RemoveNode(model_, client_, folder_->id(), true, &error)); 173 EXPECT_EQ(2, model_->other_node()->child_count()); 174 } 175 176 TEST_F(ExtensionBookmarksTest, GetMetaInfo) { 177 base::DictionaryValue id_to_meta_info_map; 178 GetMetaInfo(*model_->other_node(), &id_to_meta_info_map); 179 EXPECT_EQ(8u, id_to_meta_info_map.size()); 180 181 // Verify top level node. 182 const base::Value* value = NULL; 183 EXPECT_TRUE(id_to_meta_info_map.Get( 184 base::Int64ToString(model_->other_node()->id()), &value)); 185 ASSERT_TRUE(NULL != value); 186 const base::DictionaryValue* dictionary_value = NULL; 187 EXPECT_TRUE(value->GetAsDictionary(&dictionary_value)); 188 ASSERT_TRUE(NULL != dictionary_value); 189 EXPECT_EQ(0u, dictionary_value->size()); 190 191 // Verify bookmark with two meta info key/value pairs. 192 value = NULL; 193 EXPECT_TRUE(id_to_meta_info_map.Get( 194 base::Int64ToString(node_->id()), &value)); 195 ASSERT_TRUE(NULL != value); 196 dictionary_value = NULL; 197 EXPECT_TRUE(value->GetAsDictionary(&dictionary_value)); 198 ASSERT_TRUE(NULL != dictionary_value); 199 EXPECT_EQ(2u, dictionary_value->size()); 200 std::string string_value; 201 EXPECT_TRUE(dictionary_value->GetString("some_key1", &string_value)); 202 EXPECT_EQ("some_value1", string_value); 203 EXPECT_TRUE(dictionary_value->GetString("some_key2", &string_value)); 204 EXPECT_EQ("some_value2", string_value); 205 206 // Verify folder with one meta info key/value pair. 207 value = NULL; 208 EXPECT_TRUE(id_to_meta_info_map.Get( 209 base::Int64ToString(folder_->id()), &value)); 210 ASSERT_TRUE(NULL != value); 211 dictionary_value = NULL; 212 EXPECT_TRUE(value->GetAsDictionary(&dictionary_value)); 213 ASSERT_TRUE(NULL != dictionary_value); 214 EXPECT_EQ(1u, dictionary_value->size()); 215 EXPECT_TRUE(dictionary_value->GetString("some_key1", &string_value)); 216 EXPECT_EQ("some_value1", string_value); 217 218 // Verify bookmark in a subfolder with one meta info key/value pairs. 219 value = NULL; 220 EXPECT_TRUE(id_to_meta_info_map.Get( 221 base::Int64ToString(node2_->id()), &value)); 222 ASSERT_TRUE(NULL != value); 223 dictionary_value = NULL; 224 EXPECT_TRUE(value->GetAsDictionary(&dictionary_value)); 225 ASSERT_TRUE(NULL != dictionary_value); 226 EXPECT_EQ(1u, dictionary_value->size()); 227 string_value.clear(); 228 EXPECT_FALSE(dictionary_value->GetString("some_key1", &string_value)); 229 EXPECT_EQ("", string_value); 230 EXPECT_TRUE(dictionary_value->GetString("some_key2", &string_value)); 231 EXPECT_EQ("some_value2", string_value); 232 233 } 234 235 } // namespace bookmark_api_helpers 236 } // namespace extensions 237