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/managed/managed_bookmarks_tracker.h"
8 #include "base/files/file_path.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/prefs/pref_registry_simple.h"
12 #include "base/prefs/testing_pref_service.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "components/bookmarks/browser/bookmark_model.h"
16 #include "components/bookmarks/browser/bookmark_model_observer.h"
17 #include "components/bookmarks/browser/bookmark_node.h"
18 #include "components/bookmarks/common/bookmark_pref_names.h"
19 #include "components/bookmarks/test/bookmark_test_helpers.h"
20 #include "components/bookmarks/test/mock_bookmark_model_observer.h"
21 #include "components/bookmarks/test/test_bookmark_client.h"
22 #include "grit/components_strings.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/base/l10n/l10n_util.h"
33 class ManagedBookmarksTrackerTest
: public testing::Test
{
35 ManagedBookmarksTrackerTest() : managed_node_(NULL
) {}
36 ~ManagedBookmarksTrackerTest() override
{}
38 void SetUp() override
{
39 prefs_
.registry()->RegisterListPref(bookmarks::prefs::kManagedBookmarks
);
40 prefs_
.registry()->RegisterListPref(bookmarks::prefs::kSupervisedBookmarks
);
41 prefs_
.registry()->RegisterListPref(
42 bookmarks::prefs::kBookmarkEditorExpandedNodes
);
45 void TearDown() override
{
47 model_
->RemoveObserver(&observer_
);
51 void CreateModel(bool is_supervised
) {
52 // Simulate the creation of the managed node by the BookmarkClient.
53 BookmarkPermanentNode
* managed_node
= new BookmarkPermanentNode(100);
54 ManagedBookmarksTracker::LoadInitial(
56 prefs_
.GetList(ManagedBookmarksTracker::GetPrefName(is_supervised
)),
58 managed_node
->set_visible(!managed_node
->empty());
59 managed_node
->SetTitle(l10n_util::GetStringUTF16(
60 is_supervised
? IDS_BOOKMARK_BAR_SUPERVISED_FOLDER_DEFAULT_NAME
61 : IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME
));
63 bookmarks::BookmarkPermanentNodeList extra_nodes
;
64 extra_nodes
.push_back(managed_node
);
65 client_
.SetExtraNodesToLoad(extra_nodes
.Pass());
67 model_
.reset(new BookmarkModel(&client_
));
68 model_
->AddObserver(&observer_
);
69 EXPECT_CALL(observer_
, BookmarkModelLoaded(model_
.get(), _
));
70 model_
->Load(&prefs_
, std::string(), base::FilePath(),
71 base::ThreadTaskRunnerHandle::Get(),
72 base::ThreadTaskRunnerHandle::Get());
73 bookmarks::test::WaitForBookmarkModelToLoad(model_
.get());
74 Mock::VerifyAndClearExpectations(&observer_
);
76 ASSERT_EQ(1u, client_
.extra_nodes().size());
77 managed_node_
= client_
.extra_nodes()[0];
78 ASSERT_EQ(managed_node
, managed_node_
);
80 managed_bookmarks_tracker_
.reset(new ManagedBookmarksTracker(
84 base::Bind(&ManagedBookmarksTrackerTest::GetManagementDomain
)));
85 managed_bookmarks_tracker_
->Init(managed_node_
);
88 const BookmarkNode
* managed_node() {
92 bool IsManaged(const BookmarkNode
* node
) {
93 return node
&& node
->HasAncestor(managed_node_
);
96 static base::DictionaryValue
* CreateBookmark(const std::string
& title
,
97 const std::string
& url
) {
98 EXPECT_TRUE(GURL(url
).is_valid());
99 base::DictionaryValue
* dict
= new base::DictionaryValue();
100 dict
->SetString("name", title
);
101 dict
->SetString("url", GURL(url
).spec());
105 static base::DictionaryValue
* CreateFolder(const std::string
& title
,
106 base::ListValue
* children
) {
107 base::DictionaryValue
* dict
= new base::DictionaryValue();
108 dict
->SetString("name", title
);
109 dict
->Set("children", children
);
113 static base::ListValue
* CreateTestTree() {
114 base::ListValue
* folder
= new base::ListValue();
115 base::ListValue
* empty
= new base::ListValue();
116 folder
->Append(CreateFolder("Empty", empty
));
117 folder
->Append(CreateBookmark("Youtube", "http://youtube.com/"));
119 base::ListValue
* list
= new base::ListValue();
120 list
->Append(CreateBookmark("Google", "http://google.com/"));
121 list
->Append(CreateFolder("Folder", folder
));
126 static std::string
GetManagementDomain() {
127 return std::string();
130 static std::string
GetManagedFolderTitle() {
131 return l10n_util::GetStringUTF8(
132 IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME
);
135 static base::DictionaryValue
* CreateExpectedTree() {
136 return CreateFolder(GetManagedFolderTitle(), CreateTestTree());
139 static bool NodeMatchesValue(const BookmarkNode
* node
,
140 const base::DictionaryValue
* dict
) {
141 base::string16 title
;
142 if (!dict
->GetString("name", &title
) || node
->GetTitle() != title
)
145 if (node
->is_folder()) {
146 const base::ListValue
* children
= NULL
;
147 if (!dict
->GetList("children", &children
) ||
148 node
->child_count() != static_cast<int>(children
->GetSize())) {
151 for (int i
= 0; i
< node
->child_count(); ++i
) {
152 const base::DictionaryValue
* child
= NULL
;
153 if (!children
->GetDictionary(i
, &child
) ||
154 !NodeMatchesValue(node
->GetChild(i
), child
)) {
158 } else if (node
->is_url()) {
160 if (!dict
->GetString("url", &url
) || node
->url() != GURL(url
))
168 base::MessageLoop loop_
;
169 TestingPrefServiceSimple prefs_
;
170 bookmarks::TestBookmarkClient client_
;
171 scoped_ptr
<BookmarkModel
> model_
;
172 bookmarks::MockBookmarkModelObserver observer_
;
173 BookmarkPermanentNode
* managed_node_
;
174 scoped_ptr
<ManagedBookmarksTracker
> managed_bookmarks_tracker_
;
177 TEST_F(ManagedBookmarksTrackerTest
, Empty
) {
178 CreateModel(false /* is_supervised */);
179 EXPECT_TRUE(model_
->bookmark_bar_node()->empty());
180 EXPECT_TRUE(model_
->other_node()->empty());
181 EXPECT_TRUE(managed_node()->empty());
182 EXPECT_FALSE(managed_node()->IsVisible());
185 TEST_F(ManagedBookmarksTrackerTest
, LoadInitial
) {
186 // Set a policy before loading the model.
187 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
188 CreateModel(false /* is_supervised */);
189 EXPECT_TRUE(model_
->bookmark_bar_node()->empty());
190 EXPECT_TRUE(model_
->other_node()->empty());
191 EXPECT_FALSE(managed_node()->empty());
192 EXPECT_TRUE(managed_node()->IsVisible());
194 scoped_ptr
<base::DictionaryValue
> expected(CreateExpectedTree());
195 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
198 TEST_F(ManagedBookmarksTrackerTest
, SupervisedTrackerIgnoresManagedPref
) {
199 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
200 CreateModel(true /* is_supervised */);
201 EXPECT_TRUE(managed_node()->empty());
202 EXPECT_FALSE(managed_node()->IsVisible());
205 TEST_F(ManagedBookmarksTrackerTest
, SupervisedTrackerHandlesSupervisedPref
) {
206 prefs_
.SetManagedPref(bookmarks::prefs::kSupervisedBookmarks
,
208 CreateModel(true /* is_supervised */);
209 EXPECT_FALSE(managed_node()->empty());
210 EXPECT_TRUE(managed_node()->IsVisible());
211 // Don't bother checking the actual contents, the non-supervised tests cover
215 TEST_F(ManagedBookmarksTrackerTest
, SwapNodes
) {
216 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
217 CreateModel(false /* is_supervised */);
219 // Swap the Google bookmark with the Folder.
220 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
221 scoped_ptr
<base::Value
> removed
;
222 ASSERT_TRUE(updated
->Remove(0, &removed
));
223 updated
->Append(removed
.release());
225 // These two nodes should just be swapped.
226 const BookmarkNode
* parent
= managed_node();
227 EXPECT_CALL(observer_
, BookmarkNodeMoved(model_
.get(), parent
, 1, parent
, 0));
228 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
229 updated
->DeepCopy());
230 Mock::VerifyAndClearExpectations(&observer_
);
232 // Verify the final tree.
233 scoped_ptr
<base::DictionaryValue
> expected(
234 CreateFolder(GetManagedFolderTitle(), updated
.release()));
235 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
238 TEST_F(ManagedBookmarksTrackerTest
, RemoveNode
) {
239 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
240 CreateModel(false /* is_supervised */);
242 // Remove the Folder.
243 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
244 ASSERT_TRUE(updated
->Remove(1, NULL
));
246 const BookmarkNode
* parent
= managed_node();
247 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
.get(), parent
, 1, _
, _
));
248 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
249 updated
->DeepCopy());
250 Mock::VerifyAndClearExpectations(&observer_
);
252 // Verify the final tree.
253 scoped_ptr
<base::DictionaryValue
> expected(
254 CreateFolder(GetManagedFolderTitle(), updated
.release()));
255 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
258 TEST_F(ManagedBookmarksTrackerTest
, CreateNewNodes
) {
259 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
260 CreateModel(false /* is_supervised */);
262 // Put all the nodes inside another folder.
263 scoped_ptr
<base::ListValue
> updated(new base::ListValue
);
264 updated
->Append(CreateFolder("Container", CreateTestTree()));
266 EXPECT_CALL(observer_
, BookmarkNodeAdded(model_
.get(), _
, _
)).Times(5);
267 // The remaining nodes have been pushed to positions 1 and 2; they'll both be
268 // removed when at position 1.
269 const BookmarkNode
* parent
= managed_node();
270 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
.get(), parent
, 1, _
, _
))
272 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
273 updated
->DeepCopy());
274 Mock::VerifyAndClearExpectations(&observer_
);
276 // Verify the final tree.
277 scoped_ptr
<base::DictionaryValue
> expected(
278 CreateFolder(GetManagedFolderTitle(), updated
.release()));
279 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
282 TEST_F(ManagedBookmarksTrackerTest
, RemoveAll
) {
283 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
284 CreateModel(false /* is_supervised */);
285 EXPECT_TRUE(managed_node()->IsVisible());
287 // Remove the policy.
288 const BookmarkNode
* parent
= managed_node();
289 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
.get(), parent
, 0, _
, _
))
291 prefs_
.RemoveManagedPref(bookmarks::prefs::kManagedBookmarks
);
292 Mock::VerifyAndClearExpectations(&observer_
);
294 EXPECT_TRUE(managed_node()->empty());
295 EXPECT_FALSE(managed_node()->IsVisible());
298 TEST_F(ManagedBookmarksTrackerTest
, IsManaged
) {
299 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
300 CreateModel(false /* is_supervised */);
302 EXPECT_FALSE(IsManaged(model_
->root_node()));
303 EXPECT_FALSE(IsManaged(model_
->bookmark_bar_node()));
304 EXPECT_FALSE(IsManaged(model_
->other_node()));
305 EXPECT_FALSE(IsManaged(model_
->mobile_node()));
306 EXPECT_TRUE(IsManaged(managed_node()));
308 const BookmarkNode
* parent
= managed_node();
309 ASSERT_EQ(2, parent
->child_count());
310 EXPECT_TRUE(IsManaged(parent
->GetChild(0)));
311 EXPECT_TRUE(IsManaged(parent
->GetChild(1)));
313 parent
= parent
->GetChild(1);
314 ASSERT_EQ(2, parent
->child_count());
315 EXPECT_TRUE(IsManaged(parent
->GetChild(0)));
316 EXPECT_TRUE(IsManaged(parent
->GetChild(1)));
319 TEST_F(ManagedBookmarksTrackerTest
, RemoveAllUserBookmarksDoesntRemoveManaged
) {
320 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
321 CreateModel(false /* is_supervised */);
322 EXPECT_EQ(2, managed_node()->child_count());
324 EXPECT_CALL(observer_
,
325 BookmarkNodeAdded(model_
.get(), model_
->bookmark_bar_node(), 0));
326 EXPECT_CALL(observer_
,
327 BookmarkNodeAdded(model_
.get(), model_
->bookmark_bar_node(), 1));
328 model_
->AddURL(model_
->bookmark_bar_node(),
330 base::ASCIIToUTF16("Test"),
331 GURL("http://google.com/"));
333 model_
->bookmark_bar_node(), 1, base::ASCIIToUTF16("Test Folder"));
334 EXPECT_EQ(2, model_
->bookmark_bar_node()->child_count());
335 Mock::VerifyAndClearExpectations(&observer_
);
337 EXPECT_CALL(observer_
, BookmarkAllUserNodesRemoved(model_
.get(), _
));
338 model_
->RemoveAllUserBookmarks();
339 EXPECT_EQ(2, managed_node()->child_count());
340 EXPECT_EQ(0, model_
->bookmark_bar_node()->child_count());
341 Mock::VerifyAndClearExpectations(&observer_
);
344 } // namespace bookmarks