#include "components/bookmarks/browser/bookmark_utils.h"
#include <stddef.h>
#include <array>
#include <memory>
#include <utility>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/bookmarks/browser/base_bookmark_model_observer.h"
#include "components/bookmarks/browser/bookmark_client.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_model_observer.h"
#include "components/bookmarks/browser/bookmark_node_data.h"
#include "components/bookmarks/common/bookmark_metrics.h"
#include "components/bookmarks/test/test_bookmark_client.h"
#include "components/signin/public/base/signin_switches.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
namespace bookmarks {
namespace {
using base::ASCIIToUTF16;
using std::string;
using testing::ElementsAre;
using testing::UnorderedElementsAre;
class BookmarkUtilsTest : public testing::Test,
public BaseBookmarkModelObserver {
public:
BookmarkUtilsTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
BookmarkUtilsTest(const BookmarkUtilsTest&) = delete;
BookmarkUtilsTest& operator=(const BookmarkUtilsTest&) = delete;
~BookmarkUtilsTest() override {}
#if !BUILDFLAG(IS_IOS)
void TearDown() override {
ui::Clipboard::DestroyClipboardForCurrentThread();
}
#endif
void ExpectGroupedChangeCount(int expected_beginning_count,
int expected_ended_count) {
#if !BUILDFLAG(IS_ANDROID)
EXPECT_EQ(grouped_changes_beginning_count_, expected_beginning_count);
EXPECT_EQ(grouped_changes_ended_count_, expected_ended_count);
#endif
}
base::HistogramTester* histogram() { return &histogram_; }
private:
void BookmarkModelChanged() override {}
void GroupedBookmarkChangesBeginning() override {
++grouped_changes_beginning_count_;
}
void GroupedBookmarkChangesEnded() override {
++grouped_changes_ended_count_;
}
base::test::ScopedFeatureList features_override_{
switches::kSyncEnableBookmarksInTransportMode};
base::test::TaskEnvironment task_environment_;
int grouped_changes_beginning_count_{0};
int grouped_changes_ended_count_{0};
base::HistogramTester histogram_;
};
class SuggestFolderClient : public TestBookmarkClient {
public:
SuggestFolderClient() = default;
SuggestFolderClient(const SuggestFolderClient&) = delete;
SuggestFolderClient& operator=(const SuggestFolderClient&) = delete;
~SuggestFolderClient() override = default;
const BookmarkNode* GetSuggestedSaveLocation(const GURL& url) override {
return suggested_save_location_.get();
}
void SetSuggestedSaveLocation(const BookmarkNode* node) {
suggested_save_location_ = node;
}
private:
raw_ptr<const BookmarkNode> suggested_save_location_;
};
TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesWordPhraseQuery) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* node1 = model->AddURL(model->other_node(), 0, u"foo bar",
GURL("http://www.google.com"));
const BookmarkNode* node2 = model->AddURL(model->other_node(), 0, u"baz buz",
GURL("http://www.cnn.com"));
const BookmarkNode* folder1 =
model->AddFolder(model->other_node(), 0, u"foo");
QueryFields query;
query.word_phrase_query = std::make_unique<std::u16string>();
*query.word_phrase_query = u"";
EXPECT_TRUE(GetBookmarksMatchingProperties(model.get(), query, 100).empty());
*query.word_phrase_query = u" ";
EXPECT_TRUE(GetBookmarksMatchingProperties(model.get(), query, 100).empty());
*query.word_phrase_query = u"foo";
EXPECT_THAT(GetBookmarksMatchingProperties(model.get(), query, 100),
UnorderedElementsAre(folder1, node1));
*query.word_phrase_query = u"cnn";
EXPECT_THAT(GetBookmarksMatchingProperties(model.get(), query, 100),
UnorderedElementsAre(node2));
*query.word_phrase_query = u"foo bar";
EXPECT_THAT(GetBookmarksMatchingProperties(model.get(), query, 100),
UnorderedElementsAre(node1));
*query.word_phrase_query = u"Bookmark";
EXPECT_TRUE(GetBookmarksMatchingProperties(model.get(), query, 100).empty());
}
TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesUrl) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* node1 = model->AddURL(model->other_node(), 0, u"Google",
GURL("https://www.google.com/"));
model->AddURL(model->other_node(), 0, u"Google Calendar",
GURL("https://www.google.com/calendar"));
model->AddFolder(model->other_node(), 0, u"Folder");
QueryFields query;
query.url = std::make_unique<std::u16string>();
*query.url = u"https://www.google.com/";
EXPECT_THAT(GetBookmarksMatchingProperties(model.get(), query, 100),
UnorderedElementsAre(node1));
*query.url = u"calendar";
EXPECT_TRUE(GetBookmarksMatchingProperties(model.get(), query, 100).empty());
*query.url = u"";
EXPECT_TRUE(GetBookmarksMatchingProperties(model.get(), query, 100).empty());
}
TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesTitle) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* node1 = model->AddURL(model->other_node(), 0, u"Google",
GURL("https://www.google.com/"));
model->AddURL(model->other_node(), 0, u"Google Calendar",
GURL("https://www.google.com/calendar"));
const BookmarkNode* folder1 =
model->AddFolder(model->other_node(), 0, u"Folder");
QueryFields query;
query.title = std::make_unique<std::u16string>();
*query.title = u"Google";
EXPECT_THAT(GetBookmarksMatchingProperties(model.get(), query, 100),
UnorderedElementsAre(node1));
*query.title = u"Calendar";
EXPECT_TRUE(GetBookmarksMatchingProperties(model.get(), query, 100).empty());
*query.title = u"Folder";
EXPECT_THAT(GetBookmarksMatchingProperties(model.get(), query, 100),
UnorderedElementsAre(folder1));
}
TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesConjunction) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* node1 = model->AddURL(model->other_node(), 0, u"Google",
GURL("https://www.google.com/"));
model->AddURL(model->other_node(), 0, u"Google Calendar",
GURL("https://www.google.com/calendar"));
model->AddFolder(model->other_node(), 0, u"Folder");
QueryFields query;
query.word_phrase_query = std::make_unique<std::u16string>(u"www");
query.url = std::make_unique<std::u16string>(u"https://www.google.com/");
query.title = std::make_unique<std::u16string>(u"Google");
EXPECT_THAT(GetBookmarksMatchingProperties(model.get(), query, 100),
UnorderedElementsAre(node1));
auto fields = std::to_array<std::unique_ptr<std::u16string>*>({
&query.word_phrase_query,
&query.url,
&query.title,
});
for (size_t i = 0; i < std::size(fields); i++) {
std::unique_ptr<std::u16string> original_value(fields[i]->release());
EXPECT_THAT(GetBookmarksMatchingProperties(model.get(), query, 100),
UnorderedElementsAre(node1));
*fields[i] = std::move(original_value);
}
for (size_t i = 0; i < std::size(fields); i++) {
std::unique_ptr<std::u16string> original_value(fields[i]->release());
*fields[i] = std::make_unique<std::u16string>(u"fjdkslafjkldsa");
EXPECT_TRUE(
GetBookmarksMatchingProperties(model.get(), query, 100).empty());
*fields[i] = std::move(original_value);
}
}
TEST_F(BookmarkUtilsTest, GetParentForNewNodes_ClientOverride) {
std::unique_ptr<SuggestFolderClient> client =
std::make_unique<SuggestFolderClient>();
SuggestFolderClient* client_ptr = client.get();
std::unique_ptr<BookmarkModel> model(
TestBookmarkClient::CreateModelWithClient(std::move(client)));
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
EXPECT_EQ(model->mobile_node(), GetParentForNewNodes(model.get(), GURL()));
#else
EXPECT_EQ(model->other_node(), GetParentForNewNodes(model.get(), GURL()));
model->CreateAccountPermanentFolders();
EXPECT_EQ(model->account_other_node(),
GetParentForNewNodes(model.get(), GURL()));
#endif
const BookmarkNode* folder_to_suggest =
model->AddFolder(model->bookmark_bar_node(), 0, u"Suggested");
const BookmarkNode* folder1 =
model->AddFolder(model->bookmark_bar_node(), 1, u"Folder 1");
EXPECT_EQ(folder1, GetParentForNewNodes(model.get(), GURL()));
client_ptr->SetSuggestedSaveLocation(folder_to_suggest);
EXPECT_EQ(folder_to_suggest, GetParentForNewNodes(model.get(), GURL()));
client_ptr = nullptr;
}
TEST_F(BookmarkUtilsTest, CloneMetaInfo) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* node = model->AddURL(model->other_node(), 0, u"foo bar",
GURL("http://www.google.com"));
model->SetNodeMetaInfo(node, "somekey", "somevalue");
model->SetNodeMetaInfo(node, "someotherkey", "someothervalue");
const BookmarkNode* folder =
model->AddFolder(model->bookmark_bar_node(), 0, u"Folder");
std::vector<BookmarkNodeData::Element> elements;
BookmarkNodeData::Element node_data(node);
elements.push_back(node_data);
ASSERT_EQ(0u, folder->children().size());
CloneBookmarkNode(model.get(), elements, folder, 0, false);
ASSERT_EQ(1u, folder->children().size());
const BookmarkNode* clone = folder->children().front().get();
ASSERT_TRUE(clone->GetMetaInfoMap());
EXPECT_EQ(2u, clone->GetMetaInfoMap()->size());
std::string value;
EXPECT_TRUE(clone->GetMetaInfo("somekey", &value));
EXPECT_EQ("somevalue", value);
EXPECT_TRUE(clone->GetMetaInfo("someotherkey", &value));
EXPECT_EQ("someothervalue", value);
histogram()->ExpectTotalCount("Bookmarks.Clone.NumCloned", 1);
histogram()->ExpectBucketCount("Bookmarks.Clone.NumCloned", 1, 1);
}
TEST_F(BookmarkUtilsTest, RemoveAllBookmarks) {
auto client = std::make_unique<TestBookmarkClient>();
BookmarkNode* managed_node = client->EnableManagedNode();
std::unique_ptr<BookmarkModel> model(
TestBookmarkClient::CreateModelWithClient(std::move(client)));
ASSERT_TRUE(model->bookmark_bar_node()->children().empty());
ASSERT_TRUE(model->other_node()->children().empty());
ASSERT_TRUE(model->mobile_node()->children().empty());
ASSERT_TRUE(managed_node->children().empty());
const std::u16string title = u"Title";
const GURL url("http://google.com");
model->AddURL(model->bookmark_bar_node(), 0, title, url);
model->AddURL(model->other_node(), 0, title, url);
model->AddURL(model->mobile_node(), 0, title, url);
model->AddURL(managed_node, 0, title, url);
std::vector<raw_ptr<const BookmarkNode, VectorExperimental>> nodes =
model->GetNodesByURL(url);
ASSERT_EQ(4u, nodes.size());
RemoveAllBookmarks(model.get(), url, FROM_HERE);
nodes = model->GetNodesByURL(url);
ASSERT_EQ(1u, nodes.size());
EXPECT_TRUE(model->bookmark_bar_node()->children().empty());
EXPECT_TRUE(model->other_node()->children().empty());
EXPECT_TRUE(model->mobile_node()->children().empty());
EXPECT_EQ(1u, managed_node->children().size());
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithOnlyLocalBookmarks_PermanentNodesOrderUnaffectedByDisplay) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* const local_other_bookmark = model->AddURL(
model->other_node(), 0, u"Title", GURL("http://google.com"));
model->SetDateFolderModified(model->other_node(),
base::Time::FromMillisecondsSinceUnixEpoch(1));
model->SetDateFolderModified(model->bookmark_bar_node(),
base::Time::FromMillisecondsSinceUnixEpoch(2));
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(model.get(),
local_other_bookmark);
EXPECT_TRUE(mru_bookmarks.account_nodes.empty());
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(model->bookmark_bar_node(), model->other_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithOnlyLocalBookmarks_NonPermanentNodesOrderAffectedByDisplay) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* const folder1 =
model->AddFolder(model->other_node(), 0, u"Folder1");
const BookmarkNode* const folder2 =
model->AddFolder(model->other_node(), 0, u"Folder2");
const BookmarkNode* const bookmark =
model->AddURL(folder1, 0, u"Title", GURL("http://google.com"));
model->SetDateFolderModified(folder1,
base::Time::FromMillisecondsSinceUnixEpoch(1));
model->SetDateFolderModified(folder2,
base::Time::FromMillisecondsSinceUnixEpoch(2));
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(model.get(), bookmark);
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(folder1, folder2, model->bookmark_bar_node(),
model->other_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithOnlyLocalBookmarks_DateFolderModifiedChangesOrder) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* const local_other_bookmark = model->AddURL(
model->other_node(), 0, u"Title", GURL("http://google.com"));
const BookmarkNode* const folder1 =
model->AddFolder(model->other_node(), 0, u"Folder1");
const BookmarkNode* const folder2 =
model->AddFolder(model->other_node(), 0, u"Folder2");
model->SetDateFolderModified(folder1,
base::Time::FromMillisecondsSinceUnixEpoch(1));
model->SetDateFolderModified(folder2,
base::Time::FromMillisecondsSinceUnixEpoch(2));
bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(model.get(),
local_other_bookmark);
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(folder2, folder1, model->bookmark_bar_node(),
model->other_node()));
model->SetDateFolderModified(folder1,
base::Time::FromMillisecondsSinceUnixEpoch(3));
mru_bookmarks = bookmarks::GetMostRecentlyUsedFoldersForDisplay(
model.get(), local_other_bookmark);
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(folder1, folder2, model->bookmark_bar_node(),
model->other_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithOnlyLocalBookmarks_PermanentFoldersAlwaysShownWithCustomFolders) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* const local_other_bookmark = model->AddURL(
model->other_node(), 0, u"Title", GURL("http://google.com"));
std::vector<const BookmarkNode*> custom_nodes;
for (int i = 0; i < 6; i++) {
custom_nodes.push_back(
model->AddFolder(model->other_node(), 0, u"CustomFolder"));
}
CHECK_EQ(6u, custom_nodes.size());
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(model.get(),
local_other_bookmark);
EXPECT_TRUE(mru_bookmarks.account_nodes.empty());
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(custom_nodes[5], custom_nodes[4], custom_nodes[3],
custom_nodes[2], custom_nodes[1],
model->bookmark_bar_node(), model->other_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithOnlyLocalBookmarks_CustomFolderShownWhenChildNodeDisplayed) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
std::vector<const BookmarkNode*> custom_nodes;
custom_nodes.push_back(
model->AddFolder(model->other_node(), 0, u"CustomFolder"));
const BookmarkNode* const bookmark =
model->AddURL(custom_nodes[0], 0, u"Title", GURL("http://google.com"));
for (int i = 0; i < 5; i++) {
custom_nodes.push_back(
model->AddFolder(model->other_node(), 0, u"CustomFolder"));
}
CHECK_EQ(6u, custom_nodes.size());
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(model.get(), bookmark);
EXPECT_TRUE(mru_bookmarks.account_nodes.empty());
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(custom_nodes[0], custom_nodes[5], custom_nodes[4],
custom_nodes[3], custom_nodes[2],
model->bookmark_bar_node(), model->other_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithOnlyLocalBookmarks_CustomFolderShownWhenRecentlyModified) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* const local_other_bookmark = model->AddURL(
model->other_node(), 0, u"Title", GURL("http://google.com"));
std::vector<const BookmarkNode*> custom_nodes;
for (int i = 0; i < 6; i++) {
custom_nodes.push_back(
model->AddFolder(model->other_node(), 0, u"CustomFolder"));
}
CHECK_EQ(6u, custom_nodes.size());
model->SetDateFolderModified(custom_nodes[0], base::Time::Now());
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(model.get(),
local_other_bookmark);
EXPECT_TRUE(mru_bookmarks.account_nodes.empty());
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(custom_nodes[0], custom_nodes[5], custom_nodes[4],
custom_nodes[3], custom_nodes[2],
model->bookmark_bar_node(), model->other_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithAccountBookmarks_PermanentNodesOrderUnaffectedByDisplay) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
const BookmarkNode* const bookmark_in_account_other_node = model->AddURL(
model->account_other_node(), 0, u"Title", GURL("http://google.com"));
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(
model.get(), bookmark_in_account_other_node);
EXPECT_TRUE(mru_bookmarks.local_nodes.empty());
EXPECT_THAT(mru_bookmarks.account_nodes,
ElementsAre(model->account_bookmark_bar_node(),
model->account_other_node()));
}
TEST_F(BookmarkUtilsTest,
GetRecentlyUsedFoldersWithAccountBookmarks_LocalPermanentNodesNotShown) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
const BookmarkNode* const bookmark_in_account_other_node = model->AddURL(
model->account_other_node(), 0, u"Title", GURL("http://google.com"));
const BookmarkNode* const account_folder =
model->AddFolder(model->account_other_node(), 0, u"Folder");
const BookmarkNode* const local_folder =
model->AddFolder(model->other_node(), 0, u"Folder2");
model->SetDateFolderModified(account_folder,
base::Time::FromMillisecondsSinceUnixEpoch(20));
model->SetDateFolderModified(local_folder,
base::Time::FromMillisecondsSinceUnixEpoch(10));
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(
model.get(), bookmark_in_account_other_node);
EXPECT_THAT(mru_bookmarks.account_nodes,
ElementsAre(account_folder, model->account_bookmark_bar_node(),
model->account_other_node()));
EXPECT_THAT(mru_bookmarks.local_nodes, ElementsAre(local_folder));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithAccountBookmarks_LocalPermanentNodeShownWhenChildDisplayed) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
const BookmarkNode* const local_other_bookmark = model->AddURL(
model->other_node(), 0, u"Title", GURL("http://google.com"));
model->SetDateFolderModified(model->other_node(),
base::Time::FromMillisecondsSinceUnixEpoch(1));
model->SetDateFolderModified(model->account_other_node(),
base::Time::FromMillisecondsSinceUnixEpoch(2));
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(model.get(),
local_other_bookmark);
EXPECT_THAT(mru_bookmarks.local_nodes, ElementsAre(model->other_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithAccountBookmarks_LocalPermanentNodeShownWhenRecentlyModified) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
const base::Time account_folders_created_time = base::Time::Now();
model->AddURL(model->bookmark_bar_node(), 0, u"Title",
GURL("http://google.com"));
const BookmarkNode* const bookmark_in_account_other_node = model->AddURL(
model->account_other_node(), 0, u"Title", GURL("http://google.com"));
model->SetDateFolderModified(model->account_other_node(),
account_folders_created_time + base::Seconds(1));
model->SetDateFolderModified(model->bookmark_bar_node(),
account_folders_created_time + base::Seconds(2));
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(
model.get(), bookmark_in_account_other_node);
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(model->bookmark_bar_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithAccountBookmarks_LocalPermanentNodeDisplayedOnlyOnce) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
const BookmarkNode* const local_bookmark = model->AddURL(
model->bookmark_bar_node(), 0, u"Title", GURL("http://google.com"));
model->SetDateFolderModified(model->account_other_node(),
base::Time::FromMillisecondsSinceUnixEpoch(1));
model->SetDateFolderModified(model->bookmark_bar_node(),
base::Time::FromMillisecondsSinceUnixEpoch(2));
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(model.get(),
local_bookmark);
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(model->bookmark_bar_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithAccountBookmarks_LocalPermanentNodesDisplayedLast) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
const base::Time account_folders_created_time = base::Time::Now();
const BookmarkNode* const bookmark_in_account_other_node = model->AddURL(
model->account_other_node(), 0, u"Title", GURL("http://google.com"));
const BookmarkNode* const local_bookmark = model->AddURL(
model->bookmark_bar_node(), 0, u"Title", GURL("http://google.com"));
const BookmarkNode* const folder1 =
model->AddFolder(model->bookmark_bar_node(), 0, u"Folder");
const BookmarkNode* const folder2 =
model->AddFolder(model->bookmark_bar_node(), 0, u"Folder2");
model->SetDateFolderModified(folder1, account_folders_created_time);
model->SetDateFolderModified(model->bookmark_bar_node(),
account_folders_created_time + base::Seconds(1));
model->SetDateFolderModified(folder2,
account_folders_created_time + base::Seconds(2));
model->SetDateFolderModified(model->account_other_node(),
account_folders_created_time + base::Seconds(3));
bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(
model.get(), bookmark_in_account_other_node);
EXPECT_THAT(mru_bookmarks.local_nodes, ElementsAre(folder2, folder1));
mru_bookmarks = bookmarks::GetMostRecentlyUsedFoldersForDisplay(
model.get(), local_bookmark);
mru_bookmarks = bookmarks::GetMostRecentlyUsedFoldersForDisplay(
model.get(), local_bookmark);
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(folder2, folder1, model->bookmark_bar_node()));
model->SetDateFolderModified(
model->bookmark_bar_node(),
account_folders_created_time + base::Seconds(10));
mru_bookmarks = bookmarks::GetMostRecentlyUsedFoldersForDisplay(
model.get(), bookmark_in_account_other_node);
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(folder2, folder1, model->bookmark_bar_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithAccountBookmarks_MultipleLocalPermanentNodesDisplayed) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
const base::Time account_folders_created_time = base::Time::Now();
const BookmarkNode* const local_bookmark = model->AddURL(
model->bookmark_bar_node(), 0, u"Title", GURL("http://google.com"));
model->SetDateFolderModified(model->bookmark_bar_node(),
account_folders_created_time + base::Seconds(1));
model->SetDateFolderModified(model->account_bookmark_bar_node(),
account_folders_created_time + base::Seconds(1));
model->SetDateFolderModified(model->account_other_node(),
account_folders_created_time + base::Seconds(1));
model->SetDateFolderModified(model->other_node(),
account_folders_created_time + base::Seconds(2));
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(model.get(),
local_bookmark);
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(model->other_node(), model->bookmark_bar_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithAccountBookmarks_AccountPermanentFoldersAlwaysShownWithCustomFolders) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
const BookmarkNode* const bookmark_in_account_other_node = model->AddURL(
model->account_other_node(), 0, u"Title", GURL("http://google.com"));
std::vector<const BookmarkNode*> custom_nodes;
for (int i = 0; i < 6; i++) {
custom_nodes.push_back(model->AddFolder(model->account_other_node(), 0,
u"CustomAccountFolder"));
}
CHECK_EQ(6u, custom_nodes.size());
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(
model.get(), bookmark_in_account_other_node);
EXPECT_TRUE(mru_bookmarks.local_nodes.empty());
EXPECT_THAT(mru_bookmarks.account_nodes,
ElementsAre(custom_nodes[5], custom_nodes[4], custom_nodes[3],
custom_nodes[2], custom_nodes[1],
model->account_bookmark_bar_node(),
model->account_other_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithAccountBookmarks_CustomFolderShownWhenChildNodeDisplayed) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
std::vector<const BookmarkNode*> custom_nodes;
custom_nodes.push_back(
model->AddFolder(model->account_other_node(), 0, u"CustomAccountFolder"));
const BookmarkNode* const bookmark =
model->AddURL(custom_nodes[0], 0, u"Title", GURL("http://google.com"));
for (int i = 0; i < 5; i++) {
custom_nodes.push_back(model->AddFolder(model->account_other_node(), 0,
u"CustomAccountFolder"));
}
CHECK_EQ(6u, custom_nodes.size());
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(model.get(), bookmark);
EXPECT_TRUE(mru_bookmarks.local_nodes.empty());
EXPECT_THAT(mru_bookmarks.account_nodes,
ElementsAre(custom_nodes[0], custom_nodes[5], custom_nodes[4],
custom_nodes[3], custom_nodes[2],
model->account_bookmark_bar_node(),
model->account_other_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithAccountBookmarks_CustomFolderShownWhenRecentlyModified) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
const BookmarkNode* const bookmark_in_account_other_node = model->AddURL(
model->account_other_node(), 0, u"Title", GURL("http://google.com"));
std::vector<const BookmarkNode*> custom_nodes;
for (int i = 0; i < 6; i++) {
custom_nodes.push_back(model->AddFolder(model->account_other_node(), 0,
u"CustomAccountFolder"));
}
CHECK_EQ(6u, custom_nodes.size());
model->SetDateFolderModified(custom_nodes[0], base::Time::Now());
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(
model.get(), bookmark_in_account_other_node);
EXPECT_TRUE(mru_bookmarks.local_nodes.empty());
EXPECT_THAT(mru_bookmarks.account_nodes,
ElementsAre(custom_nodes[0], custom_nodes[5], custom_nodes[4],
custom_nodes[3], custom_nodes[2],
model->account_bookmark_bar_node(),
model->account_other_node()));
}
TEST_F(
BookmarkUtilsTest,
GetRecentlyUsedFoldersWithAccountBookmarks_CustomFolderMaximumDisplayedIndependentOfStorage) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
const BookmarkNode* const bookmark_in_account_other_node = model->AddURL(
model->account_other_node(), 0, u"Title", GURL("http://google.com"));
std::vector<const BookmarkNode*> custom_nodes;
for (int i = 0; i < 3; i++) {
custom_nodes.push_back(
model->AddFolder(model->other_node(), 0, u"CustomLocalFolder"));
custom_nodes.push_back(model->AddFolder(model->account_other_node(), 0,
u"CustomAccountFolder"));
}
CHECK_EQ(6u, custom_nodes.size());
const bookmarks::BookmarkNodesSplitByAccountAndLocal mru_bookmarks =
bookmarks::GetMostRecentlyUsedFoldersForDisplay(
model.get(), bookmark_in_account_other_node);
EXPECT_THAT(mru_bookmarks.account_nodes,
ElementsAre(custom_nodes[5], custom_nodes[3], custom_nodes[1],
model->account_bookmark_bar_node(),
model->account_other_node()));
EXPECT_THAT(mru_bookmarks.local_nodes,
ElementsAre(custom_nodes[4], custom_nodes[2]));
}
TEST_F(BookmarkUtilsTest, GetPermanentNodesForDisplayWithOnlyLocalBookmarks) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNodesSplitByAccountAndLocal permanent_display_nodes =
GetPermanentNodesForDisplay(model.get());
EXPECT_TRUE(permanent_display_nodes.account_nodes.empty());
EXPECT_THAT(permanent_display_nodes.local_nodes,
ElementsAre(model->bookmark_bar_node(), model->other_node()));
}
TEST_F(BookmarkUtilsTest, GetPermanentNodesForDisplayWithAccountBookmarks) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
BookmarkNodesSplitByAccountAndLocal permanent_display_nodes =
GetPermanentNodesForDisplay(model.get());
ASSERT_FALSE(HasLocalOrSyncableBookmarks(model.get()));
ASSERT_TRUE(permanent_display_nodes.local_nodes.empty());
ASSERT_THAT(permanent_display_nodes.account_nodes,
ElementsAre(model->account_bookmark_bar_node(),
model->account_other_node()));
model->AddURL(model->other_node(), 0, u"Title", GURL("http://google.com"));
ASSERT_TRUE(HasLocalOrSyncableBookmarks(model.get()));
permanent_display_nodes = GetPermanentNodesForDisplay(model.get());
EXPECT_THAT(permanent_display_nodes.account_nodes,
ElementsAre(model->account_bookmark_bar_node(),
model->account_other_node()));
EXPECT_THAT(permanent_display_nodes.local_nodes,
ElementsAre(model->bookmark_bar_node(), model->other_node()));
}
TEST_F(BookmarkUtilsTest, GetPermanentNodesForDisplayWithSyncEnabled) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
static_cast<TestBookmarkClient*>(model->client())
->SetIsSyncFeatureEnabledIncludingBookmarks(true);
const BookmarkNodesSplitByAccountAndLocal permanent_display_nodes =
GetPermanentNodesForDisplay(model.get());
EXPECT_TRUE(permanent_display_nodes.account_nodes.empty());
EXPECT_THAT(permanent_display_nodes.local_nodes,
ElementsAre(model->bookmark_bar_node(), model->other_node()));
}
#endif
TEST_F(BookmarkUtilsTest,
GetMostRecentlyModifiedUserFolders_DefaultOrderWithoutAccountBookmarks) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
ASSERT_FALSE(model->account_other_node());
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
EXPECT_THAT(GetMostRecentlyModifiedUserFolders(model.get()),
ElementsAre(model->mobile_node()));
#else
EXPECT_THAT(GetMostRecentlyModifiedUserFolders(model.get()),
ElementsAre(model->other_node(), model->bookmark_bar_node()));
#endif
}
TEST_F(BookmarkUtilsTest,
GetMostRecentlyModifiedUserFolders_DefaultOrderWithAccountBookmarks) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
EXPECT_THAT(GetMostRecentlyModifiedUserFolders(model.get()),
ElementsAre(model->account_mobile_node(), model->mobile_node()));
#else
EXPECT_THAT(GetMostRecentlyModifiedUserFolders(model.get()),
ElementsAre(model->account_other_node(),
model->account_bookmark_bar_node()));
#endif
}
TEST_F(
BookmarkUtilsTest,
GetMostRecentlyModifiedUserFolders_LocalFolderModifiedBeforeAccountFoldersAdded) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->AddURL(model->bookmark_bar_node(), 0, u"Title",
GURL("http://google.com"));
std::vector<const BookmarkNode*> recently_modified =
GetMostRecentlyModifiedUserFolders(model.get());
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
ASSERT_THAT(recently_modified,
ElementsAre(model->bookmark_bar_node(), model->mobile_node()));
#else
ASSERT_THAT(recently_modified,
ElementsAre(model->bookmark_bar_node(), model->other_node()));
#endif
model->CreateAccountPermanentFolders();
recently_modified = GetMostRecentlyModifiedUserFolders(model.get());
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
EXPECT_THAT(recently_modified,
ElementsAre(model->account_mobile_node(),
model->bookmark_bar_node(), model->mobile_node()));
#else
EXPECT_THAT(recently_modified,
ElementsAre(model->account_other_node(),
model->account_bookmark_bar_node(),
model->bookmark_bar_node(), model->other_node()));
#endif
}
TEST_F(
BookmarkUtilsTest,
GetMostRecentlyModifiedUserFolders_LocalFolderModifiedAfterAccountFoldersAdded) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
model->AddURL(model->bookmark_bar_node(), 0, u"Title",
GURL("http://google.com"));
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
EXPECT_THAT(GetMostRecentlyModifiedUserFolders(model.get()),
ElementsAre(model->bookmark_bar_node(),
model->account_mobile_node(), model->mobile_node()));
#else
EXPECT_THAT(
GetMostRecentlyModifiedUserFolders(model.get()),
ElementsAre(model->bookmark_bar_node(), model->account_other_node(),
model->account_bookmark_bar_node(), model->other_node()));
#endif
}
TEST_F(
BookmarkUtilsTest,
GetMostRecentlyModifiedUserFolders_AccountFolderModifiedAfterAccountFoldersAdded) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
model->AddURL(model->account_bookmark_bar_node(), 0, u"Title",
GURL("http://google.com"));
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
EXPECT_THAT(GetMostRecentlyModifiedUserFolders(model.get()),
ElementsAre(model->account_bookmark_bar_node(),
model->account_mobile_node(), model->mobile_node()));
#else
EXPECT_THAT(GetMostRecentlyModifiedUserFolders(model.get()),
ElementsAre(model->account_bookmark_bar_node(),
model->account_other_node()));
#endif
}
TEST_F(
BookmarkUtilsTest,
GetMostRecentlyModifiedUserFolders_DefinedModifiedOrderWithCustomLocalFolders) {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
model->CreateAccountPermanentFolders();
const BookmarkNode* const local_folder1 =
model->AddFolder(model->other_node(), 0, u"Folder");
const BookmarkNode* const local_folder2 =
model->AddFolder(model->bookmark_bar_node(), 0, u"Folder2");
model->SetDateFolderModified(model->account_other_node(),
base::Time::FromMillisecondsSinceUnixEpoch(0));
model->SetDateFolderModified(model->account_bookmark_bar_node(),
base::Time::FromMillisecondsSinceUnixEpoch(1));
model->SetDateFolderModified(model->bookmark_bar_node(),
base::Time::FromMillisecondsSinceUnixEpoch(2));
model->SetDateFolderModified(local_folder2,
base::Time::FromMillisecondsSinceUnixEpoch(3));
model->SetDateFolderModified(model->other_node(),
base::Time::FromMillisecondsSinceUnixEpoch(4));
model->SetDateFolderModified(local_folder1,
base::Time::FromMillisecondsSinceUnixEpoch(5));
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
model->SetDateFolderModified(model->mobile_node(),
base::Time::FromMillisecondsSinceUnixEpoch(6));
#endif
model->RemoveAccountPermanentFolders();
model->CreateAccountPermanentFolders();
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
EXPECT_THAT(GetMostRecentlyModifiedUserFolders(model.get()),
ElementsAre(model->account_mobile_node(), model->mobile_node(),
local_folder1, model->other_node(), local_folder2,
model->bookmark_bar_node()));
#else
EXPECT_THAT(GetMostRecentlyModifiedUserFolders(model.get()),
ElementsAre(model->account_other_node(),
model->account_bookmark_bar_node(), local_folder1,
model->other_node(), local_folder2,
model->bookmark_bar_node()));
#endif
}
}
}