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.
5 #include "components/bookmarks/browser/bookmark_node_data.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "components/bookmarks/browser/bookmark_model.h"
13 #include "components/bookmarks/test/bookmark_test_helpers.h"
14 #include "components/bookmarks/test/test_bookmark_client.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "ui/base/clipboard/clipboard.h"
17 #include "ui/base/dragdrop/os_exchange_data.h"
18 #include "ui/events/platform/platform_event_source.h"
21 using base::ASCIIToUTF16
;
25 class BookmarkNodeDataTest
: public testing::Test
{
27 BookmarkNodeDataTest() {}
29 void SetUp() override
{
30 event_source_
= ui::PlatformEventSource::CreateDefault();
31 model_
= client_
.CreateModel();
32 test::WaitForBookmarkModelToLoad(model_
.get());
33 bool success
= profile_dir_
.CreateUniqueTempDir();
37 void TearDown() override
{
39 event_source_
.reset();
40 bool success
= profile_dir_
.Delete();
42 ui::Clipboard::DestroyClipboardForCurrentThread();
45 const base::FilePath
& GetProfilePath() const { return profile_dir_
.path(); }
47 BookmarkModel
* model() { return model_
.get(); }
50 ui::Clipboard
& clipboard() { return *ui::Clipboard::GetForCurrentThread(); }
53 base::ScopedTempDir profile_dir_
;
54 TestBookmarkClient client_
;
55 scoped_ptr
<BookmarkModel
> model_
;
56 scoped_ptr
<ui::PlatformEventSource
> event_source_
;
57 base::MessageLoopForUI loop_
;
59 DISALLOW_COPY_AND_ASSIGN(BookmarkNodeDataTest
);
64 ui::OSExchangeData::Provider
* CloneProvider(const ui::OSExchangeData
& data
) {
65 return data
.provider().Clone();
70 // Makes sure BookmarkNodeData is initially invalid.
71 TEST_F(BookmarkNodeDataTest
, InitialState
) {
72 BookmarkNodeData data
;
73 EXPECT_FALSE(data
.is_valid());
76 // Makes sure reading bogus data leaves the BookmarkNodeData invalid.
77 TEST_F(BookmarkNodeDataTest
, BogusRead
) {
78 ui::OSExchangeData data
;
79 BookmarkNodeData drag_data
;
80 EXPECT_FALSE(drag_data
.Read(ui::OSExchangeData(CloneProvider(data
))));
81 EXPECT_FALSE(drag_data
.is_valid());
84 // Writes a URL to the clipboard and make sure BookmarkNodeData can correctly
86 TEST_F(BookmarkNodeDataTest
, JustURL
) {
87 const GURL
url("http://google.com");
88 const base::string16
title(ASCIIToUTF16("google.com"));
90 ui::OSExchangeData data
;
91 data
.SetURL(url
, title
);
93 BookmarkNodeData drag_data
;
94 EXPECT_TRUE(drag_data
.Read(ui::OSExchangeData(CloneProvider(data
))));
95 EXPECT_TRUE(drag_data
.is_valid());
96 ASSERT_EQ(1u, drag_data
.size());
97 EXPECT_TRUE(drag_data
.elements
[0].is_url
);
98 EXPECT_EQ(url
, drag_data
.elements
[0].url
);
99 EXPECT_EQ(title
, drag_data
.elements
[0].title
);
100 EXPECT_TRUE(drag_data
.elements
[0].date_added
.is_null());
101 EXPECT_TRUE(drag_data
.elements
[0].date_folder_modified
.is_null());
102 EXPECT_EQ(0u, drag_data
.elements
[0].children
.size());
105 TEST_F(BookmarkNodeDataTest
, URL
) {
106 // Write a single node representing a URL to the clipboard.
107 const BookmarkNode
* root
= model()->bookmark_bar_node();
108 GURL
url(GURL("http://foo.com"));
109 const base::string16
title(ASCIIToUTF16("foo.com"));
110 const BookmarkNode
* node
= model()->AddURL(root
, 0, title
, url
);
111 BookmarkNodeData
drag_data(node
);
112 EXPECT_TRUE(drag_data
.is_valid());
113 ASSERT_EQ(1u, drag_data
.size());
114 EXPECT_TRUE(drag_data
.elements
[0].is_url
);
115 EXPECT_EQ(url
, drag_data
.elements
[0].url
);
116 EXPECT_EQ(title
, drag_data
.elements
[0].title
);
117 EXPECT_EQ(node
->date_added(), drag_data
.elements
[0].date_added
);
118 EXPECT_EQ(node
->date_folder_modified(),
119 drag_data
.elements
[0].date_folder_modified
);
120 ui::OSExchangeData data
;
121 drag_data
.Write(GetProfilePath(), &data
);
123 // Now read the data back in.
124 ui::OSExchangeData
data2(CloneProvider(data
));
125 BookmarkNodeData read_data
;
126 EXPECT_TRUE(read_data
.Read(data2
));
127 EXPECT_TRUE(read_data
.is_valid());
128 ASSERT_EQ(1u, read_data
.size());
129 EXPECT_TRUE(read_data
.elements
[0].is_url
);
130 EXPECT_EQ(url
, read_data
.elements
[0].url
);
131 EXPECT_EQ(title
, read_data
.elements
[0].title
);
132 EXPECT_TRUE(read_data
.elements
[0].date_added
.is_null());
133 EXPECT_TRUE(read_data
.elements
[0].date_folder_modified
.is_null());
134 EXPECT_TRUE(read_data
.GetFirstNode(model(), GetProfilePath()) == node
);
136 // Make sure asking for the node with a different profile returns NULL.
137 base::ScopedTempDir other_profile_dir
;
138 EXPECT_TRUE(other_profile_dir
.CreateUniqueTempDir());
139 EXPECT_TRUE(read_data
.GetFirstNode(model(), other_profile_dir
.path()) ==
142 // Writing should also put the URL and title on the clipboard.
144 base::string16 read_title
;
145 EXPECT_TRUE(data2
.GetURLAndTitle(
146 ui::OSExchangeData::CONVERT_FILENAMES
, &read_url
, &read_title
));
147 EXPECT_EQ(url
, read_url
);
148 EXPECT_EQ(title
, read_title
);
151 // Tests writing a folder to the clipboard.
152 TEST_F(BookmarkNodeDataTest
, Folder
) {
153 const BookmarkNode
* root
= model()->bookmark_bar_node();
154 const BookmarkNode
* g1
= model()->AddFolder(root
, 0, ASCIIToUTF16("g1"));
155 model()->AddFolder(g1
, 0, ASCIIToUTF16("g11"));
156 const BookmarkNode
* g12
= model()->AddFolder(g1
, 0, ASCIIToUTF16("g12"));
158 BookmarkNodeData
drag_data(g12
);
159 EXPECT_TRUE(drag_data
.is_valid());
160 ASSERT_EQ(1u, drag_data
.size());
161 EXPECT_EQ(g12
->GetTitle(), drag_data
.elements
[0].title
);
162 EXPECT_FALSE(drag_data
.elements
[0].is_url
);
163 EXPECT_EQ(g12
->date_added(), drag_data
.elements
[0].date_added
);
164 EXPECT_EQ(g12
->date_folder_modified(),
165 drag_data
.elements
[0].date_folder_modified
);
167 ui::OSExchangeData data
;
168 drag_data
.Write(GetProfilePath(), &data
);
170 // Now read the data back in.
171 ui::OSExchangeData
data2(CloneProvider(data
));
172 BookmarkNodeData read_data
;
173 EXPECT_TRUE(read_data
.Read(data2
));
174 EXPECT_TRUE(read_data
.is_valid());
175 ASSERT_EQ(1u, read_data
.size());
176 EXPECT_EQ(g12
->GetTitle(), read_data
.elements
[0].title
);
177 EXPECT_FALSE(read_data
.elements
[0].is_url
);
178 EXPECT_TRUE(read_data
.elements
[0].date_added
.is_null());
179 EXPECT_TRUE(read_data
.elements
[0].date_folder_modified
.is_null());
181 // We should get back the same node when asking for the same profile.
182 const BookmarkNode
* r_g12
= read_data
.GetFirstNode(model(), GetProfilePath());
183 EXPECT_TRUE(g12
== r_g12
);
185 // A different profile should return NULL for the node.
186 base::ScopedTempDir other_profile_dir
;
187 EXPECT_TRUE(other_profile_dir
.CreateUniqueTempDir());
188 EXPECT_TRUE(read_data
.GetFirstNode(model(), other_profile_dir
.path()) ==
192 // Tests reading/writing a folder with children.
193 TEST_F(BookmarkNodeDataTest
, FolderWithChild
) {
194 const BookmarkNode
* root
= model()->bookmark_bar_node();
195 const BookmarkNode
* folder
= model()->AddFolder(root
, 0, ASCIIToUTF16("g1"));
197 GURL
url(GURL("http://foo.com"));
198 const base::string16
title(ASCIIToUTF16("blah2"));
200 model()->AddURL(folder
, 0, title
, url
);
202 BookmarkNodeData
drag_data(folder
);
204 ui::OSExchangeData data
;
205 drag_data
.Write(GetProfilePath(), &data
);
207 // Now read the data back in.
208 ui::OSExchangeData
data2(CloneProvider(data
));
209 BookmarkNodeData read_data
;
210 EXPECT_TRUE(read_data
.Read(data2
));
211 ASSERT_EQ(1u, read_data
.size());
212 ASSERT_EQ(1u, read_data
.elements
[0].children
.size());
213 const BookmarkNodeData::Element
& read_child
=
214 read_data
.elements
[0].children
[0];
216 EXPECT_TRUE(read_child
.is_url
);
217 EXPECT_EQ(title
, read_child
.title
);
218 EXPECT_EQ(url
, read_child
.url
);
219 EXPECT_TRUE(read_data
.elements
[0].date_added
.is_null());
220 EXPECT_TRUE(read_data
.elements
[0].date_folder_modified
.is_null());
221 EXPECT_TRUE(read_child
.is_url
);
223 // And make sure we get the node back.
224 const BookmarkNode
* r_folder
=
225 read_data
.GetFirstNode(model(), GetProfilePath());
226 EXPECT_TRUE(folder
== r_folder
);
229 // Tests reading/writing of multiple nodes.
230 TEST_F(BookmarkNodeDataTest
, MultipleNodes
) {
231 const BookmarkNode
* root
= model()->bookmark_bar_node();
232 const BookmarkNode
* folder
= model()->AddFolder(root
, 0, ASCIIToUTF16("g1"));
234 GURL
url(GURL("http://foo.com"));
235 const base::string16
title(ASCIIToUTF16("blah2"));
237 const BookmarkNode
* url_node
= model()->AddURL(folder
, 0, title
, url
);
239 // Write the nodes to the clipboard.
240 std::vector
<const BookmarkNode
*> nodes
;
241 nodes
.push_back(folder
);
242 nodes
.push_back(url_node
);
243 BookmarkNodeData
drag_data(nodes
);
244 ui::OSExchangeData data
;
245 drag_data
.Write(GetProfilePath(), &data
);
247 // Read the data back in.
248 ui::OSExchangeData
data2(CloneProvider(data
));
249 BookmarkNodeData read_data
;
250 EXPECT_TRUE(read_data
.Read(data2
));
251 EXPECT_TRUE(read_data
.is_valid());
252 ASSERT_EQ(2u, read_data
.size());
253 ASSERT_EQ(1u, read_data
.elements
[0].children
.size());
254 EXPECT_TRUE(read_data
.elements
[0].date_added
.is_null());
255 EXPECT_TRUE(read_data
.elements
[0].date_folder_modified
.is_null());
257 const BookmarkNodeData::Element
& read_folder
= read_data
.elements
[0];
258 EXPECT_FALSE(read_folder
.is_url
);
259 EXPECT_EQ(ASCIIToUTF16("g1"), read_folder
.title
);
260 EXPECT_EQ(1u, read_folder
.children
.size());
262 const BookmarkNodeData::Element
& read_url
= read_data
.elements
[1];
263 EXPECT_TRUE(read_url
.is_url
);
264 EXPECT_EQ(title
, read_url
.title
);
265 EXPECT_EQ(0u, read_url
.children
.size());
267 // And make sure we get the node back.
268 std::vector
<const BookmarkNode
*> read_nodes
=
269 read_data
.GetNodes(model(), GetProfilePath());
270 ASSERT_EQ(2u, read_nodes
.size());
271 EXPECT_TRUE(read_nodes
[0] == folder
);
272 EXPECT_TRUE(read_nodes
[1] == url_node
);
274 // Asking for the first node should return NULL with more than one element
276 EXPECT_TRUE(read_data
.GetFirstNode(model(), GetProfilePath()) == NULL
);
279 TEST_F(BookmarkNodeDataTest
, WriteToClipboardURL
) {
280 BookmarkNodeData data
;
281 GURL
url(GURL("http://foo.com"));
282 const base::string16
title(ASCIIToUTF16("blah"));
284 data
.ReadFromTuple(url
, title
);
285 data
.WriteToClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE
);
287 // Now read the data back in.
288 base::string16 clipboard_result
;
289 clipboard().ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE
, &clipboard_result
);
290 EXPECT_EQ(base::UTF8ToUTF16(url
.spec()), clipboard_result
);
293 TEST_F(BookmarkNodeDataTest
, WriteToClipboardMultipleURLs
) {
294 BookmarkNodeData data
;
295 const BookmarkNode
* root
= model()->bookmark_bar_node();
296 GURL
url(GURL("http://foo.com"));
297 const base::string16
title(ASCIIToUTF16("blah"));
298 GURL
url2(GURL("http://bar.com"));
299 const base::string16
title2(ASCIIToUTF16("blah2"));
300 const BookmarkNode
* url_node
= model()->AddURL(root
, 0, title
, url
);
301 const BookmarkNode
* url_node2
= model()->AddURL(root
, 1, title2
, url2
);
302 std::vector
<const BookmarkNode
*> nodes
;
303 nodes
.push_back(url_node
);
304 nodes
.push_back(url_node2
);
306 data
.ReadFromVector(nodes
);
307 data
.WriteToClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE
);
309 // Now read the data back in.
310 base::string16 combined_text
;
311 base::string16 new_line
= base::ASCIIToUTF16("\n");
312 combined_text
= base::UTF8ToUTF16(url
.spec()) + new_line
313 + base::UTF8ToUTF16(url2
.spec());
314 base::string16 clipboard_result
;
315 clipboard().ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE
, &clipboard_result
);
316 EXPECT_EQ(combined_text
, clipboard_result
);
319 TEST_F(BookmarkNodeDataTest
, WriteToClipboardEmptyFolder
) {
320 BookmarkNodeData data
;
321 const BookmarkNode
* root
= model()->bookmark_bar_node();
322 const BookmarkNode
* folder
= model()->AddFolder(root
, 0, ASCIIToUTF16("g1"));
323 std::vector
<const BookmarkNode
*> nodes
;
324 nodes
.push_back(folder
);
326 data
.ReadFromVector(nodes
);
327 data
.WriteToClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE
);
329 // Now read the data back in.
330 base::string16 clipboard_result
;
331 clipboard().ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE
, &clipboard_result
);
332 EXPECT_EQ(base::ASCIIToUTF16("g1"), clipboard_result
);
335 TEST_F(BookmarkNodeDataTest
, WriteToClipboardFolderWithChildren
) {
336 BookmarkNodeData data
;
337 const BookmarkNode
* root
= model()->bookmark_bar_node();
338 const BookmarkNode
* folder
= model()->AddFolder(root
, 0, ASCIIToUTF16("g1"));
339 GURL
url(GURL("http://foo.com"));
340 const base::string16
title(ASCIIToUTF16("blah"));
341 model()->AddURL(folder
, 0, title
, url
);
342 std::vector
<const BookmarkNode
*> nodes
;
343 nodes
.push_back(folder
);
345 data
.ReadFromVector(nodes
);
346 data
.WriteToClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE
);
348 // Now read the data back in.
349 base::string16 clipboard_result
;
350 clipboard().ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE
, &clipboard_result
);
351 EXPECT_EQ(base::ASCIIToUTF16("g1"), clipboard_result
);
354 TEST_F(BookmarkNodeDataTest
, WriteToClipboardFolderAndURL
) {
355 BookmarkNodeData data
;
356 GURL
url(GURL("http://foo.com"));
357 const base::string16
title(ASCIIToUTF16("blah"));
358 const BookmarkNode
* root
= model()->bookmark_bar_node();
359 const BookmarkNode
* url_node
= model()->AddURL(root
, 0, title
, url
);
360 const BookmarkNode
* folder
= model()->AddFolder(root
, 0, ASCIIToUTF16("g1"));
361 std::vector
<const BookmarkNode
*> nodes
;
362 nodes
.push_back(url_node
);
363 nodes
.push_back(folder
);
365 data
.ReadFromVector(nodes
);
366 data
.WriteToClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE
);
368 // Now read the data back in.
369 base::string16 combined_text
;
370 base::string16 new_line
= base::ASCIIToUTF16("\n");
371 base::string16 folder_title
= ASCIIToUTF16("g1");
372 combined_text
= base::ASCIIToUTF16(url
.spec()) + new_line
+ folder_title
;
373 base::string16 clipboard_result
;
374 clipboard().ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE
, &clipboard_result
);
375 EXPECT_EQ(combined_text
, clipboard_result
);
378 // Tests reading/writing of meta info.
379 TEST_F(BookmarkNodeDataTest
, MetaInfo
) {
380 // Create a node containing meta info.
381 const BookmarkNode
* node
= model()->AddURL(model()->other_node(),
383 ASCIIToUTF16("foo bar"),
384 GURL("http://www.google.com"));
385 model()->SetNodeMetaInfo(node
, "somekey", "somevalue");
386 model()->SetNodeMetaInfo(node
, "someotherkey", "someothervalue");
388 BookmarkNodeData
node_data(node
);
389 ui::OSExchangeData data
;
390 node_data
.Write(GetProfilePath(), &data
);
392 // Read the data back in.
393 ui::OSExchangeData
data2(CloneProvider(data
));
394 BookmarkNodeData read_data
;
395 EXPECT_TRUE(read_data
.Read(data2
));
396 EXPECT_TRUE(read_data
.is_valid());
397 ASSERT_EQ(1u, read_data
.size());
399 // Verify that the read data contains the same meta info.
400 BookmarkNode::MetaInfoMap meta_info_map
= read_data
.elements
[0].meta_info_map
;
401 EXPECT_EQ(2u, meta_info_map
.size());
402 EXPECT_EQ("somevalue", meta_info_map
["somekey"]);
403 EXPECT_EQ("someothervalue", meta_info_map
["someotherkey"]);
406 } // namespace bookmarks