bookmark_utils_unittest.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  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. #include "components/bookmarks/browser/bookmark_utils.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/strings/utf_string_conversions.h"
  10. #include "base/test/task_environment.h"
  11. #include "build/build_config.h"
  12. #include "build/chromeos_buildflags.h"
  13. #include "components/bookmarks/browser/base_bookmark_model_observer.h"
  14. #include "components/bookmarks/browser/bookmark_model.h"
  15. #include "components/bookmarks/browser/bookmark_node_data.h"
  16. #include "components/bookmarks/test/test_bookmark_client.h"
  17. #include "testing/gtest/include/gtest/gtest.h"
  18. #include "ui/base/clipboard/clipboard.h"
  19. #include "ui/base/clipboard/scoped_clipboard_writer.h"
  20. using base::ASCIIToUTF16;
  21. using std::string;
  22. namespace bookmarks {
  23. namespace {
  24. class BookmarkUtilsTest : public testing::Test,
  25. public BaseBookmarkModelObserver {
  26. public:
  27. BookmarkUtilsTest()
  28. : task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
  29. grouped_changes_beginning_count_(0),
  30. grouped_changes_ended_count_(0) {}
  31. BookmarkUtilsTest(const BookmarkUtilsTest&) = delete;
  32. BookmarkUtilsTest& operator=(const BookmarkUtilsTest&) = delete;
  33. ~BookmarkUtilsTest() override {}
  34. // Copy and paste is not yet supported on iOS. http://crbug.com/228147
  35. #if !BUILDFLAG(IS_IOS)
  36. void TearDown() override {
  37. ui::Clipboard::DestroyClipboardForCurrentThread();
  38. }
  39. #endif // !BUILDFLAG(IS_IOS)
  40. // Certain user actions require multiple changes to the bookmark model,
  41. // however these modifications need to be atomic for the undo framework. The
  42. // BaseBookmarkModelObserver is used to inform the boundaries of the user
  43. // action. For example, when multiple bookmarks are cut to the clipboard we
  44. // expect one call each to GroupedBookmarkChangesBeginning/Ended.
  45. void ExpectGroupedChangeCount(int expected_beginning_count,
  46. int expected_ended_count) {
  47. // The undo framework is not used under Android. Thus the group change
  48. // events will not be fired and so should not be tested for Android.
  49. #if !BUILDFLAG(IS_ANDROID)
  50. EXPECT_EQ(grouped_changes_beginning_count_, expected_beginning_count);
  51. EXPECT_EQ(grouped_changes_ended_count_, expected_ended_count);
  52. #endif
  53. }
  54. private:
  55. // BaseBookmarkModelObserver:
  56. void BookmarkModelChanged() override {}
  57. void GroupedBookmarkChangesBeginning(BookmarkModel* model) override {
  58. ++grouped_changes_beginning_count_;
  59. }
  60. void GroupedBookmarkChangesEnded(BookmarkModel* model) override {
  61. ++grouped_changes_ended_count_;
  62. }
  63. // Clipboard requires a full TaskEnvironment.
  64. base::test::TaskEnvironment task_environment_;
  65. int grouped_changes_beginning_count_;
  66. int grouped_changes_ended_count_;
  67. };
  68. TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesWordPhraseQuery) {
  69. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  70. const BookmarkNode* node1 = model->AddURL(model->other_node(), 0, u"foo bar",
  71. GURL("http://www.google.com"));
  72. const BookmarkNode* node2 = model->AddURL(model->other_node(), 0, u"baz buz",
  73. GURL("http://www.cnn.com"));
  74. const BookmarkNode* folder1 =
  75. model->AddFolder(model->other_node(), 0, u"foo");
  76. std::vector<const BookmarkNode*> nodes;
  77. QueryFields query;
  78. query.word_phrase_query = std::make_unique<std::u16string>();
  79. // No nodes are returned for empty string.
  80. *query.word_phrase_query = u"";
  81. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  82. EXPECT_TRUE(nodes.empty());
  83. nodes.clear();
  84. // No nodes are returned for space-only string.
  85. *query.word_phrase_query = u" ";
  86. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  87. EXPECT_TRUE(nodes.empty());
  88. nodes.clear();
  89. // Node "foo bar" and folder "foo" are returned in search results.
  90. *query.word_phrase_query = u"foo";
  91. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  92. ASSERT_EQ(2U, nodes.size());
  93. EXPECT_TRUE(nodes[0] == folder1);
  94. EXPECT_TRUE(nodes[1] == node1);
  95. nodes.clear();
  96. // Ensure url matches return in search results.
  97. *query.word_phrase_query = u"cnn";
  98. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  99. ASSERT_EQ(1U, nodes.size());
  100. EXPECT_TRUE(nodes[0] == node2);
  101. nodes.clear();
  102. // Ensure folder "foo" is not returned in more specific search.
  103. *query.word_phrase_query = u"foo bar";
  104. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  105. ASSERT_EQ(1U, nodes.size());
  106. EXPECT_TRUE(nodes[0] == node1);
  107. nodes.clear();
  108. // Bookmark Bar and Other Bookmarks are not returned in search results.
  109. *query.word_phrase_query = u"Bookmark";
  110. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  111. ASSERT_EQ(0U, nodes.size());
  112. nodes.clear();
  113. }
  114. // Check exact matching against a URL query.
  115. TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesUrl) {
  116. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  117. const BookmarkNode* node1 = model->AddURL(model->other_node(), 0, u"Google",
  118. GURL("https://www.google.com/"));
  119. model->AddURL(model->other_node(), 0, u"Google Calendar",
  120. GURL("https://www.google.com/calendar"));
  121. model->AddFolder(model->other_node(), 0, u"Folder");
  122. std::vector<const BookmarkNode*> nodes;
  123. QueryFields query;
  124. query.url = std::make_unique<std::u16string>();
  125. *query.url = u"https://www.google.com/";
  126. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  127. ASSERT_EQ(1U, nodes.size());
  128. EXPECT_TRUE(nodes[0] == node1);
  129. nodes.clear();
  130. *query.url = u"calendar";
  131. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  132. ASSERT_EQ(0U, nodes.size());
  133. nodes.clear();
  134. // Empty URL should not match folders.
  135. *query.url = u"";
  136. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  137. ASSERT_EQ(0U, nodes.size());
  138. nodes.clear();
  139. }
  140. // Check exact matching against a title query.
  141. TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesTitle) {
  142. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  143. const BookmarkNode* node1 = model->AddURL(model->other_node(), 0, u"Google",
  144. GURL("https://www.google.com/"));
  145. model->AddURL(model->other_node(), 0, u"Google Calendar",
  146. GURL("https://www.google.com/calendar"));
  147. const BookmarkNode* folder1 =
  148. model->AddFolder(model->other_node(), 0, u"Folder");
  149. std::vector<const BookmarkNode*> nodes;
  150. QueryFields query;
  151. query.title = std::make_unique<std::u16string>();
  152. *query.title = u"Google";
  153. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  154. ASSERT_EQ(1U, nodes.size());
  155. EXPECT_TRUE(nodes[0] == node1);
  156. nodes.clear();
  157. *query.title = u"Calendar";
  158. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  159. ASSERT_EQ(0U, nodes.size());
  160. nodes.clear();
  161. // Title should match folders.
  162. *query.title = u"Folder";
  163. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  164. ASSERT_EQ(1U, nodes.size());
  165. EXPECT_TRUE(nodes[0] == folder1);
  166. nodes.clear();
  167. }
  168. // Check matching against a query with multiple predicates.
  169. TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesConjunction) {
  170. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  171. const BookmarkNode* node1 = model->AddURL(model->other_node(), 0, u"Google",
  172. GURL("https://www.google.com/"));
  173. model->AddURL(model->other_node(), 0, u"Google Calendar",
  174. GURL("https://www.google.com/calendar"));
  175. model->AddFolder(model->other_node(), 0, u"Folder");
  176. std::vector<const BookmarkNode*> nodes;
  177. QueryFields query;
  178. // Test all fields matching.
  179. query.word_phrase_query = std::make_unique<std::u16string>(u"www");
  180. query.url = std::make_unique<std::u16string>(u"https://www.google.com/");
  181. query.title = std::make_unique<std::u16string>(u"Google");
  182. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  183. ASSERT_EQ(1U, nodes.size());
  184. EXPECT_TRUE(nodes[0] == node1);
  185. nodes.clear();
  186. std::unique_ptr<std::u16string>* fields[] = {&query.word_phrase_query,
  187. &query.url, &query.title};
  188. // Test two fields matching.
  189. for (size_t i = 0; i < std::size(fields); i++) {
  190. std::unique_ptr<std::u16string> original_value(fields[i]->release());
  191. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  192. ASSERT_EQ(1U, nodes.size());
  193. EXPECT_TRUE(nodes[0] == node1);
  194. nodes.clear();
  195. *fields[i] = std::move(original_value);
  196. }
  197. // Test two fields matching with one non-matching field.
  198. for (size_t i = 0; i < std::size(fields); i++) {
  199. std::unique_ptr<std::u16string> original_value(fields[i]->release());
  200. *fields[i] = std::make_unique<std::u16string>(u"fjdkslafjkldsa");
  201. GetBookmarksMatchingProperties(model.get(), query, 100, &nodes);
  202. ASSERT_EQ(0U, nodes.size());
  203. nodes.clear();
  204. *fields[i] = std::move(original_value);
  205. }
  206. }
  207. // Copy and paste is not yet supported on iOS. http://crbug.com/228147
  208. #if !BUILDFLAG(IS_IOS)
  209. TEST_F(BookmarkUtilsTest, DISABLED_PasteBookmarkFromURL) {
  210. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  211. const std::u16string url_text = u"http://www.google.com/";
  212. const BookmarkNode* new_folder =
  213. model->AddFolder(model->bookmark_bar_node(), 0, u"New_Folder");
  214. // Write blank text to clipboard.
  215. {
  216. ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
  217. clipboard_writer.WriteText(std::u16string());
  218. }
  219. // Now we shouldn't be able to paste from the clipboard.
  220. EXPECT_FALSE(CanPasteFromClipboard(model.get(), new_folder));
  221. // Write some valid url to the clipboard.
  222. {
  223. ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
  224. clipboard_writer.WriteText(url_text);
  225. }
  226. // Now we should be able to paste from the clipboard.
  227. EXPECT_TRUE(CanPasteFromClipboard(model.get(), new_folder));
  228. PasteFromClipboard(model.get(), new_folder, 0);
  229. ASSERT_EQ(1u, new_folder->children().size());
  230. // Url for added node should be same as url_text.
  231. EXPECT_EQ(url_text,
  232. ASCIIToUTF16(new_folder->children().front()->url().spec()));
  233. }
  234. // TODO(https://crbug.com/1010182): Fix flakes and re-enable this test.
  235. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
  236. #define MAYBE_CopyPaste DISABLED_CopyPaste
  237. #else
  238. #define MAYBE_CopyPaste CopyPaste
  239. #endif
  240. TEST_F(BookmarkUtilsTest, MAYBE_CopyPaste) {
  241. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  242. const BookmarkNode* node = model->AddURL(model->other_node(), 0, u"foo bar",
  243. GURL("http://www.google.com"));
  244. // Copy a node to the clipboard.
  245. std::vector<const BookmarkNode*> nodes;
  246. nodes.push_back(node);
  247. CopyToClipboard(model.get(), nodes, false);
  248. // And make sure we can paste a bookmark from the clipboard.
  249. EXPECT_TRUE(CanPasteFromClipboard(model.get(), model->bookmark_bar_node()));
  250. // Write some text to the clipboard.
  251. {
  252. ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
  253. clipboard_writer.WriteText(u"foo");
  254. }
  255. // Now we shouldn't be able to paste from the clipboard.
  256. EXPECT_FALSE(CanPasteFromClipboard(model.get(), model->bookmark_bar_node()));
  257. }
  258. // Test for updating title such that url and title pair are unique among the
  259. // children of parent.
  260. TEST_F(BookmarkUtilsTest, DISABLED_MakeTitleUnique) {
  261. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  262. const std::u16string url_text = u"http://www.google.com/";
  263. const std::u16string title_text = u"foobar";
  264. const BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
  265. const BookmarkNode* node =
  266. model->AddURL(bookmark_bar_node, 0, title_text, GURL(url_text));
  267. EXPECT_EQ(url_text,
  268. ASCIIToUTF16(bookmark_bar_node->children()[0]->url().spec()));
  269. EXPECT_EQ(title_text, bookmark_bar_node->children()[0]->GetTitle());
  270. // Copy a node to the clipboard.
  271. std::vector<const BookmarkNode*> nodes;
  272. nodes.push_back(node);
  273. CopyToClipboard(model.get(), nodes, false);
  274. // Now we should be able to paste from the clipboard.
  275. EXPECT_TRUE(CanPasteFromClipboard(model.get(), bookmark_bar_node));
  276. PasteFromClipboard(model.get(), bookmark_bar_node, 1);
  277. ASSERT_EQ(2u, bookmark_bar_node->children().size());
  278. // Url for added node should be same as url_text.
  279. EXPECT_EQ(url_text,
  280. ASCIIToUTF16(bookmark_bar_node->children()[1]->url().spec()));
  281. // Title for added node should be numeric subscript suffix with copied node
  282. // title.
  283. EXPECT_EQ(u"foobar (1)", bookmark_bar_node->children()[1]->GetTitle());
  284. }
  285. TEST_F(BookmarkUtilsTest, DISABLED_CopyPasteMetaInfo) {
  286. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  287. const BookmarkNode* node = model->AddURL(model->other_node(), 0, u"foo bar",
  288. GURL("http://www.google.com"));
  289. model->SetNodeMetaInfo(node, "somekey", "somevalue");
  290. model->SetNodeMetaInfo(node, "someotherkey", "someothervalue");
  291. // Copy a node to the clipboard.
  292. std::vector<const BookmarkNode*> nodes;
  293. nodes.push_back(node);
  294. CopyToClipboard(model.get(), nodes, false);
  295. // Paste node to a different folder.
  296. const BookmarkNode* folder =
  297. model->AddFolder(model->bookmark_bar_node(), 0, u"Folder");
  298. EXPECT_EQ(0u, folder->children().size());
  299. // And make sure we can paste a bookmark from the clipboard.
  300. EXPECT_TRUE(CanPasteFromClipboard(model.get(), folder));
  301. PasteFromClipboard(model.get(), folder, 0);
  302. ASSERT_EQ(1u, folder->children().size());
  303. // Verify that the pasted node contains the same meta info.
  304. const BookmarkNode* pasted = folder->children().front().get();
  305. ASSERT_TRUE(pasted->GetMetaInfoMap());
  306. EXPECT_EQ(2u, pasted->GetMetaInfoMap()->size());
  307. std::string value;
  308. EXPECT_TRUE(pasted->GetMetaInfo("somekey", &value));
  309. EXPECT_EQ("somevalue", value);
  310. EXPECT_TRUE(pasted->GetMetaInfo("someotherkey", &value));
  311. EXPECT_EQ("someothervalue", value);
  312. }
  313. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC)
  314. // http://crbug.com/396472
  315. #define MAYBE_CutToClipboard DISABLED_CutToClipboard
  316. #else
  317. #define MAYBE_CutToClipboard CutToClipboard
  318. #endif
  319. TEST_F(BookmarkUtilsTest, MAYBE_CutToClipboard) {
  320. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  321. model->AddObserver(this);
  322. std::u16string title(u"foo");
  323. GURL url("http://foo.com");
  324. const BookmarkNode* n1 = model->AddURL(model->other_node(), 0, title, url);
  325. const BookmarkNode* n2 = model->AddURL(model->other_node(), 1, title, url);
  326. // Cut the nodes to the clipboard.
  327. std::vector<const BookmarkNode*> nodes;
  328. nodes.push_back(n1);
  329. nodes.push_back(n2);
  330. CopyToClipboard(model.get(), nodes, true);
  331. // Make sure the nodes were removed.
  332. EXPECT_EQ(0u, model->other_node()->children().size());
  333. // Make sure observers were notified the set of changes should be grouped.
  334. ExpectGroupedChangeCount(1, 1);
  335. // And make sure we can paste from the clipboard.
  336. EXPECT_TRUE(CanPasteFromClipboard(model.get(), model->other_node()));
  337. }
  338. // Test is flaky on Mac and LaCros: crbug.com/1236362
  339. #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_LACROS)
  340. #define MAYBE_PasteNonEditableNodes DISABLED_PasteNonEditableNodes
  341. #else
  342. #define MAYBE_PasteNonEditableNodes PasteNonEditableNodes
  343. #endif
  344. TEST_F(BookmarkUtilsTest, MAYBE_PasteNonEditableNodes) {
  345. // Load a model with an managed node that is not editable.
  346. auto client = std::make_unique<TestBookmarkClient>();
  347. BookmarkNode* managed_node = client->EnableManagedNode();
  348. std::unique_ptr<BookmarkModel> model(
  349. TestBookmarkClient::CreateModelWithClient(std::move(client)));
  350. const BookmarkNode* node = model->AddURL(model->other_node(), 0, u"foo bar",
  351. GURL("http://www.google.com"));
  352. // Copy a node to the clipboard.
  353. std::vector<const BookmarkNode*> nodes;
  354. nodes.push_back(node);
  355. CopyToClipboard(model.get(), nodes, false);
  356. // And make sure we can paste a bookmark from the clipboard.
  357. EXPECT_TRUE(CanPasteFromClipboard(model.get(), model->bookmark_bar_node()));
  358. // But it can't be pasted into a non-editable folder.
  359. BookmarkClient* upcast = model->client();
  360. EXPECT_FALSE(upcast->CanBeEditedByUser(managed_node));
  361. EXPECT_FALSE(CanPasteFromClipboard(model.get(), managed_node));
  362. }
  363. #endif // !BUILDFLAG(IS_IOS)
  364. TEST_F(BookmarkUtilsTest, GetParentForNewNodes) {
  365. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  366. // This tests the case where selection contains one item and that item is a
  367. // folder.
  368. std::vector<const BookmarkNode*> nodes;
  369. nodes.push_back(model->bookmark_bar_node());
  370. size_t index = static_cast<size_t>(-1);
  371. const BookmarkNode* real_parent =
  372. GetParentForNewNodes(model->bookmark_bar_node(), nodes, &index);
  373. EXPECT_EQ(real_parent, model->bookmark_bar_node());
  374. EXPECT_EQ(0u, index);
  375. nodes.clear();
  376. // This tests the case where selection contains one item and that item is an
  377. // url.
  378. const BookmarkNode* page1 = model->AddURL(
  379. model->bookmark_bar_node(), 0, u"Google", GURL("http://google.com"));
  380. nodes.push_back(page1);
  381. real_parent = GetParentForNewNodes(model->bookmark_bar_node(), nodes, &index);
  382. EXPECT_EQ(real_parent, model->bookmark_bar_node());
  383. EXPECT_EQ(1u, index);
  384. // This tests the case where selection has more than one item.
  385. const BookmarkNode* folder1 =
  386. model->AddFolder(model->bookmark_bar_node(), 1, u"Folder 1");
  387. nodes.push_back(folder1);
  388. real_parent = GetParentForNewNodes(model->bookmark_bar_node(), nodes, &index);
  389. EXPECT_EQ(real_parent, model->bookmark_bar_node());
  390. EXPECT_EQ(2u, index);
  391. // This tests the case where selection doesn't contain any items.
  392. nodes.clear();
  393. real_parent = GetParentForNewNodes(model->bookmark_bar_node(), nodes, &index);
  394. EXPECT_EQ(real_parent, model->bookmark_bar_node());
  395. EXPECT_EQ(2u, index);
  396. }
  397. // Verifies that meta info is copied when nodes are cloned.
  398. TEST_F(BookmarkUtilsTest, CloneMetaInfo) {
  399. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  400. // Add a node containing meta info.
  401. const BookmarkNode* node = model->AddURL(model->other_node(), 0, u"foo bar",
  402. GURL("http://www.google.com"));
  403. model->SetNodeMetaInfo(node, "somekey", "somevalue");
  404. model->SetNodeMetaInfo(node, "someotherkey", "someothervalue");
  405. // Clone node to a different folder.
  406. const BookmarkNode* folder =
  407. model->AddFolder(model->bookmark_bar_node(), 0, u"Folder");
  408. std::vector<BookmarkNodeData::Element> elements;
  409. BookmarkNodeData::Element node_data(node);
  410. elements.push_back(node_data);
  411. EXPECT_EQ(0u, folder->children().size());
  412. CloneBookmarkNode(model.get(), elements, folder, 0, false);
  413. ASSERT_EQ(1u, folder->children().size());
  414. // Verify that the cloned node contains the same meta info.
  415. const BookmarkNode* clone = folder->children().front().get();
  416. ASSERT_TRUE(clone->GetMetaInfoMap());
  417. EXPECT_EQ(2u, clone->GetMetaInfoMap()->size());
  418. std::string value;
  419. EXPECT_TRUE(clone->GetMetaInfo("somekey", &value));
  420. EXPECT_EQ("somevalue", value);
  421. EXPECT_TRUE(clone->GetMetaInfo("someotherkey", &value));
  422. EXPECT_EQ("someothervalue", value);
  423. }
  424. // Verifies that meta info fields in the non cloned set are not copied when
  425. // cloning a bookmark.
  426. TEST_F(BookmarkUtilsTest, CloneBookmarkResetsNonClonedKey) {
  427. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  428. model->AddNonClonedKey("foo");
  429. const BookmarkNode* parent = model->other_node();
  430. const BookmarkNode* node =
  431. model->AddURL(parent, 0, u"title", GURL("http://www.google.com"));
  432. model->SetNodeMetaInfo(node, "foo", "ignored value");
  433. model->SetNodeMetaInfo(node, "bar", "kept value");
  434. std::vector<BookmarkNodeData::Element> elements;
  435. BookmarkNodeData::Element node_data(node);
  436. elements.push_back(node_data);
  437. // Cloning a bookmark should clear the non cloned key.
  438. CloneBookmarkNode(model.get(), elements, parent, 0, true);
  439. ASSERT_EQ(2u, parent->children().size());
  440. std::string value;
  441. EXPECT_FALSE(parent->children().front()->GetMetaInfo("foo", &value));
  442. // Other keys should still be cloned.
  443. EXPECT_TRUE(parent->children().front()->GetMetaInfo("bar", &value));
  444. EXPECT_EQ("kept value", value);
  445. }
  446. // Verifies that meta info fields in the non cloned set are not copied when
  447. // cloning a folder.
  448. TEST_F(BookmarkUtilsTest, CloneFolderResetsNonClonedKey) {
  449. std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
  450. model->AddNonClonedKey("foo");
  451. const BookmarkNode* parent = model->other_node();
  452. const BookmarkNode* node = model->AddFolder(parent, 0, u"title");
  453. model->SetNodeMetaInfo(node, "foo", "ignored value");
  454. model->SetNodeMetaInfo(node, "bar", "kept value");
  455. std::vector<BookmarkNodeData::Element> elements;
  456. BookmarkNodeData::Element node_data(node);
  457. elements.push_back(node_data);
  458. // Cloning a folder should clear the non cloned key.
  459. CloneBookmarkNode(model.get(), elements, parent, 0, true);
  460. ASSERT_EQ(2u, parent->children().size());
  461. std::string value;
  462. EXPECT_FALSE(parent->children().front()->GetMetaInfo("foo", &value));
  463. // Other keys should still be cloned.
  464. EXPECT_TRUE(parent->children().front()->GetMetaInfo("bar", &value));
  465. EXPECT_EQ("kept value", value);
  466. }
  467. TEST_F(BookmarkUtilsTest, RemoveAllBookmarks) {
  468. // Load a model with an managed node that is not editable.
  469. auto client = std::make_unique<TestBookmarkClient>();
  470. BookmarkNode* managed_node = client->EnableManagedNode();
  471. std::unique_ptr<BookmarkModel> model(
  472. TestBookmarkClient::CreateModelWithClient(std::move(client)));
  473. EXPECT_TRUE(model->bookmark_bar_node()->children().empty());
  474. EXPECT_TRUE(model->other_node()->children().empty());
  475. EXPECT_TRUE(model->mobile_node()->children().empty());
  476. EXPECT_TRUE(managed_node->children().empty());
  477. const std::u16string title = u"Title";
  478. const GURL url("http://google.com");
  479. model->AddURL(model->bookmark_bar_node(), 0, title, url);
  480. model->AddURL(model->other_node(), 0, title, url);
  481. model->AddURL(model->mobile_node(), 0, title, url);
  482. model->AddURL(managed_node, 0, title, url);
  483. std::vector<const BookmarkNode*> nodes;
  484. model->GetNodesByURL(url, &nodes);
  485. ASSERT_EQ(4u, nodes.size());
  486. RemoveAllBookmarks(model.get(), url);
  487. nodes.clear();
  488. model->GetNodesByURL(url, &nodes);
  489. ASSERT_EQ(1u, nodes.size());
  490. EXPECT_TRUE(model->bookmark_bar_node()->children().empty());
  491. EXPECT_TRUE(model->other_node()->children().empty());
  492. EXPECT_TRUE(model->mobile_node()->children().empty());
  493. EXPECT_EQ(1u, managed_node->children().size());
  494. }
  495. } // namespace
  496. } // namespace bookmarks