1 // Copyright 2014 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 "base/basictypes.h" 6 #include "base/files/scoped_temp_dir.h" 7 #include "base/memory/scoped_ptr.h" 8 #include "base/strings/string16.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "components/bookmarks/browser/bookmark_model.h" 11 #include "components/bookmarks/browser/bookmark_node_data.h" 12 #include "components/bookmarks/test/bookmark_test_helpers.h" 13 #include "components/bookmarks/test/test_bookmark_client.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 #include "ui/base/dragdrop/os_exchange_data.h" 16 #include "ui/events/platform/platform_event_source.h" 17 #include "url/gurl.h" 18 19 using base::ASCIIToUTF16; 20 21 class BookmarkNodeDataTest : public testing::Test { 22 public: 23 BookmarkNodeDataTest() {} 24 25 virtual void SetUp() OVERRIDE { 26 event_source_ = ui::PlatformEventSource::CreateDefault(); 27 model_ = client_.CreateModel(false); 28 test::WaitForBookmarkModelToLoad(model_.get()); 29 bool success = profile_dir_.CreateUniqueTempDir(); 30 ASSERT_TRUE(success); 31 } 32 33 virtual void TearDown() OVERRIDE { 34 model_.reset(); 35 event_source_.reset(); 36 bool success = profile_dir_.Delete(); 37 ASSERT_TRUE(success); 38 } 39 40 const base::FilePath& GetProfilePath() const { return profile_dir_.path(); } 41 42 BookmarkModel* model() { return model_.get(); } 43 44 private: 45 base::ScopedTempDir profile_dir_; 46 test::TestBookmarkClient client_; 47 scoped_ptr<BookmarkModel> model_; 48 scoped_ptr<ui::PlatformEventSource> event_source_; 49 50 DISALLOW_COPY_AND_ASSIGN(BookmarkNodeDataTest); 51 }; 52 53 namespace { 54 55 ui::OSExchangeData::Provider* CloneProvider(const ui::OSExchangeData& data) { 56 return data.provider().Clone(); 57 } 58 59 } // namespace 60 61 // Makes sure BookmarkNodeData is initially invalid. 62 TEST_F(BookmarkNodeDataTest, InitialState) { 63 BookmarkNodeData data; 64 EXPECT_FALSE(data.is_valid()); 65 } 66 67 // Makes sure reading bogus data leaves the BookmarkNodeData invalid. 68 TEST_F(BookmarkNodeDataTest, BogusRead) { 69 ui::OSExchangeData data; 70 BookmarkNodeData drag_data; 71 EXPECT_FALSE(drag_data.Read(ui::OSExchangeData(CloneProvider(data)))); 72 EXPECT_FALSE(drag_data.is_valid()); 73 } 74 75 // Writes a URL to the clipboard and make sure BookmarkNodeData can correctly 76 // read it. 77 TEST_F(BookmarkNodeDataTest, JustURL) { 78 const GURL url("http://google.com"); 79 const base::string16 title(ASCIIToUTF16("google.com")); 80 81 ui::OSExchangeData data; 82 data.SetURL(url, title); 83 84 BookmarkNodeData drag_data; 85 EXPECT_TRUE(drag_data.Read(ui::OSExchangeData(CloneProvider(data)))); 86 EXPECT_TRUE(drag_data.is_valid()); 87 ASSERT_EQ(1u, drag_data.elements.size()); 88 EXPECT_TRUE(drag_data.elements[0].is_url); 89 EXPECT_EQ(url, drag_data.elements[0].url); 90 EXPECT_EQ(title, drag_data.elements[0].title); 91 EXPECT_TRUE(drag_data.elements[0].date_added.is_null()); 92 EXPECT_TRUE(drag_data.elements[0].date_folder_modified.is_null()); 93 EXPECT_EQ(0u, drag_data.elements[0].children.size()); 94 } 95 96 TEST_F(BookmarkNodeDataTest, URL) { 97 // Write a single node representing a URL to the clipboard. 98 const BookmarkNode* root = model()->bookmark_bar_node(); 99 GURL url(GURL("http://foo.com")); 100 const base::string16 title(ASCIIToUTF16("foo.com")); 101 const BookmarkNode* node = model()->AddURL(root, 0, title, url); 102 BookmarkNodeData drag_data(node); 103 EXPECT_TRUE(drag_data.is_valid()); 104 ASSERT_EQ(1u, drag_data.elements.size()); 105 EXPECT_TRUE(drag_data.elements[0].is_url); 106 EXPECT_EQ(url, drag_data.elements[0].url); 107 EXPECT_EQ(title, drag_data.elements[0].title); 108 EXPECT_EQ(node->date_added(), drag_data.elements[0].date_added); 109 EXPECT_EQ(node->date_folder_modified(), 110 drag_data.elements[0].date_folder_modified); 111 ui::OSExchangeData data; 112 drag_data.Write(GetProfilePath(), &data); 113 114 // Now read the data back in. 115 ui::OSExchangeData data2(CloneProvider(data)); 116 BookmarkNodeData read_data; 117 EXPECT_TRUE(read_data.Read(data2)); 118 EXPECT_TRUE(read_data.is_valid()); 119 ASSERT_EQ(1u, read_data.elements.size()); 120 EXPECT_TRUE(read_data.elements[0].is_url); 121 EXPECT_EQ(url, read_data.elements[0].url); 122 EXPECT_EQ(title, read_data.elements[0].title); 123 EXPECT_TRUE(read_data.elements[0].date_added.is_null()); 124 EXPECT_TRUE(read_data.elements[0].date_folder_modified.is_null()); 125 EXPECT_TRUE(read_data.GetFirstNode(model(), GetProfilePath()) == node); 126 127 // Make sure asking for the node with a different profile returns NULL. 128 base::ScopedTempDir other_profile_dir; 129 EXPECT_TRUE(other_profile_dir.CreateUniqueTempDir()); 130 EXPECT_TRUE(read_data.GetFirstNode(model(), other_profile_dir.path()) == 131 NULL); 132 133 // Writing should also put the URL and title on the clipboard. 134 GURL read_url; 135 base::string16 read_title; 136 EXPECT_TRUE(data2.GetURLAndTitle( 137 ui::OSExchangeData::CONVERT_FILENAMES, &read_url, &read_title)); 138 EXPECT_EQ(url, read_url); 139 EXPECT_EQ(title, read_title); 140 } 141 142 // Tests writing a folder to the clipboard. 143 TEST_F(BookmarkNodeDataTest, Folder) { 144 const BookmarkNode* root = model()->bookmark_bar_node(); 145 const BookmarkNode* g1 = model()->AddFolder(root, 0, ASCIIToUTF16("g1")); 146 model()->AddFolder(g1, 0, ASCIIToUTF16("g11")); 147 const BookmarkNode* g12 = model()->AddFolder(g1, 0, ASCIIToUTF16("g12")); 148 149 BookmarkNodeData drag_data(g12); 150 EXPECT_TRUE(drag_data.is_valid()); 151 ASSERT_EQ(1u, drag_data.elements.size()); 152 EXPECT_EQ(g12->GetTitle(), drag_data.elements[0].title); 153 EXPECT_FALSE(drag_data.elements[0].is_url); 154 EXPECT_EQ(g12->date_added(), drag_data.elements[0].date_added); 155 EXPECT_EQ(g12->date_folder_modified(), 156 drag_data.elements[0].date_folder_modified); 157 158 ui::OSExchangeData data; 159 drag_data.Write(GetProfilePath(), &data); 160 161 // Now read the data back in. 162 ui::OSExchangeData data2(CloneProvider(data)); 163 BookmarkNodeData read_data; 164 EXPECT_TRUE(read_data.Read(data2)); 165 EXPECT_TRUE(read_data.is_valid()); 166 ASSERT_EQ(1u, read_data.elements.size()); 167 EXPECT_EQ(g12->GetTitle(), read_data.elements[0].title); 168 EXPECT_FALSE(read_data.elements[0].is_url); 169 EXPECT_TRUE(read_data.elements[0].date_added.is_null()); 170 EXPECT_TRUE(read_data.elements[0].date_folder_modified.is_null()); 171 172 // We should get back the same node when asking for the same profile. 173 const BookmarkNode* r_g12 = read_data.GetFirstNode(model(), GetProfilePath()); 174 EXPECT_TRUE(g12 == r_g12); 175 176 // A different profile should return NULL for the node. 177 base::ScopedTempDir other_profile_dir; 178 EXPECT_TRUE(other_profile_dir.CreateUniqueTempDir()); 179 EXPECT_TRUE(read_data.GetFirstNode(model(), other_profile_dir.path()) == 180 NULL); 181 } 182 183 // Tests reading/writing a folder with children. 184 TEST_F(BookmarkNodeDataTest, FolderWithChild) { 185 const BookmarkNode* root = model()->bookmark_bar_node(); 186 const BookmarkNode* folder = model()->AddFolder(root, 0, ASCIIToUTF16("g1")); 187 188 GURL url(GURL("http://foo.com")); 189 const base::string16 title(ASCIIToUTF16("blah2")); 190 191 model()->AddURL(folder, 0, title, url); 192 193 BookmarkNodeData drag_data(folder); 194 195 ui::OSExchangeData data; 196 drag_data.Write(GetProfilePath(), &data); 197 198 // Now read the data back in. 199 ui::OSExchangeData data2(CloneProvider(data)); 200 BookmarkNodeData read_data; 201 EXPECT_TRUE(read_data.Read(data2)); 202 ASSERT_EQ(1u, read_data.elements.size()); 203 ASSERT_EQ(1u, read_data.elements[0].children.size()); 204 const BookmarkNodeData::Element& read_child = 205 read_data.elements[0].children[0]; 206 207 EXPECT_TRUE(read_child.is_url); 208 EXPECT_EQ(title, read_child.title); 209 EXPECT_EQ(url, read_child.url); 210 EXPECT_TRUE(read_data.elements[0].date_added.is_null()); 211 EXPECT_TRUE(read_data.elements[0].date_folder_modified.is_null()); 212 EXPECT_TRUE(read_child.is_url); 213 214 // And make sure we get the node back. 215 const BookmarkNode* r_folder = 216 read_data.GetFirstNode(model(), GetProfilePath()); 217 EXPECT_TRUE(folder == r_folder); 218 } 219 220 // Tests reading/writing of multiple nodes. 221 TEST_F(BookmarkNodeDataTest, MultipleNodes) { 222 const BookmarkNode* root = model()->bookmark_bar_node(); 223 const BookmarkNode* folder = model()->AddFolder(root, 0, ASCIIToUTF16("g1")); 224 225 GURL url(GURL("http://foo.com")); 226 const base::string16 title(ASCIIToUTF16("blah2")); 227 228 const BookmarkNode* url_node = model()->AddURL(folder, 0, title, url); 229 230 // Write the nodes to the clipboard. 231 std::vector<const BookmarkNode*> nodes; 232 nodes.push_back(folder); 233 nodes.push_back(url_node); 234 BookmarkNodeData drag_data(nodes); 235 ui::OSExchangeData data; 236 drag_data.Write(GetProfilePath(), &data); 237 238 // Read the data back in. 239 ui::OSExchangeData data2(CloneProvider(data)); 240 BookmarkNodeData read_data; 241 EXPECT_TRUE(read_data.Read(data2)); 242 EXPECT_TRUE(read_data.is_valid()); 243 ASSERT_EQ(2u, read_data.elements.size()); 244 ASSERT_EQ(1u, read_data.elements[0].children.size()); 245 EXPECT_TRUE(read_data.elements[0].date_added.is_null()); 246 EXPECT_TRUE(read_data.elements[0].date_folder_modified.is_null()); 247 248 const BookmarkNodeData::Element& read_folder = read_data.elements[0]; 249 EXPECT_FALSE(read_folder.is_url); 250 EXPECT_EQ(ASCIIToUTF16("g1"), read_folder.title); 251 EXPECT_EQ(1u, read_folder.children.size()); 252 253 const BookmarkNodeData::Element& read_url = read_data.elements[1]; 254 EXPECT_TRUE(read_url.is_url); 255 EXPECT_EQ(title, read_url.title); 256 EXPECT_EQ(0u, read_url.children.size()); 257 258 // And make sure we get the node back. 259 std::vector<const BookmarkNode*> read_nodes = 260 read_data.GetNodes(model(), GetProfilePath()); 261 ASSERT_EQ(2u, read_nodes.size()); 262 EXPECT_TRUE(read_nodes[0] == folder); 263 EXPECT_TRUE(read_nodes[1] == url_node); 264 265 // Asking for the first node should return NULL with more than one element 266 // present. 267 EXPECT_TRUE(read_data.GetFirstNode(model(), GetProfilePath()) == NULL); 268 } 269 270 // Tests reading/writing of meta info. 271 TEST_F(BookmarkNodeDataTest, MetaInfo) { 272 // Create a node containing meta info. 273 const BookmarkNode* node = model()->AddURL(model()->other_node(), 274 0, 275 ASCIIToUTF16("foo bar"), 276 GURL("http://www.google.com")); 277 model()->SetNodeMetaInfo(node, "somekey", "somevalue"); 278 model()->SetNodeMetaInfo(node, "someotherkey", "someothervalue"); 279 280 BookmarkNodeData node_data(node); 281 ui::OSExchangeData data; 282 node_data.Write(GetProfilePath(), &data); 283 284 // Read the data back in. 285 ui::OSExchangeData data2(CloneProvider(data)); 286 BookmarkNodeData read_data; 287 EXPECT_TRUE(read_data.Read(data2)); 288 EXPECT_TRUE(read_data.is_valid()); 289 ASSERT_EQ(1u, read_data.elements.size()); 290 291 // Verify that the read data contains the same meta info. 292 BookmarkNode::MetaInfoMap meta_info_map = read_data.elements[0].meta_info_map; 293 EXPECT_EQ(2u, meta_info_map.size()); 294 EXPECT_EQ("somevalue", meta_info_map["somekey"]); 295 EXPECT_EQ("someothervalue", meta_info_map["someotherkey"]); 296 } 297