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/policy/core/browser/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 "components/bookmarks/browser/bookmark_model.h"
15 #include "components/bookmarks/browser/bookmark_model_observer.h"
16 #include "components/bookmarks/browser/bookmark_node.h"
17 #include "components/bookmarks/common/bookmark_pref_names.h"
18 #include "components/bookmarks/test/bookmark_test_helpers.h"
19 #include "components/bookmarks/test/mock_bookmark_model_observer.h"
20 #include "components/bookmarks/test/test_bookmark_client.h"
21 #include "grit/components_strings.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "ui/base/l10n/l10n_util.h"
27 using bookmarks::BookmarkModel
;
28 using bookmarks::BookmarkNode
;
29 using bookmarks::BookmarkPermanentNode
;
35 class ManagedBookmarksTrackerTest
: public testing::Test
{
37 ManagedBookmarksTrackerTest() : managed_node_(NULL
) {}
38 ~ManagedBookmarksTrackerTest() override
{}
40 void SetUp() override
{
41 prefs_
.registry()->RegisterListPref(bookmarks::prefs::kManagedBookmarks
);
42 prefs_
.registry()->RegisterListPref(bookmarks::prefs::kSupervisedBookmarks
);
43 prefs_
.registry()->RegisterListPref(
44 bookmarks::prefs::kBookmarkEditorExpandedNodes
);
47 void TearDown() override
{
49 model_
->RemoveObserver(&observer_
);
52 void CreateModel(bool is_supervised
) {
53 // Simulate the creation of the managed node by the BookmarkClient.
54 BookmarkPermanentNode
* managed_node
= new BookmarkPermanentNode(100);
55 policy::ManagedBookmarksTracker::LoadInitial(
57 prefs_
.GetList(ManagedBookmarksTracker::GetPrefName(is_supervised
)),
59 managed_node
->set_visible(!managed_node
->empty());
60 managed_node
->SetTitle(l10n_util::GetStringUTF16(
61 is_supervised
? IDS_BOOKMARK_BAR_SUPERVISED_FOLDER_DEFAULT_NAME
62 : IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME
));
64 bookmarks::BookmarkPermanentNodeList extra_nodes
;
65 extra_nodes
.push_back(managed_node
);
66 client_
.SetExtraNodesToLoad(extra_nodes
.Pass());
68 model_
.reset(new BookmarkModel(&client_
));
69 model_
->AddObserver(&observer_
);
70 EXPECT_CALL(observer_
, BookmarkModelLoaded(model_
.get(), _
));
74 base::MessageLoopProxy::current(),
75 base::MessageLoopProxy::current());
76 bookmarks::test::WaitForBookmarkModelToLoad(model_
.get());
77 Mock::VerifyAndClearExpectations(&observer_
);
79 ASSERT_EQ(1u, client_
.extra_nodes().size());
80 managed_node_
= client_
.extra_nodes()[0];
81 ASSERT_EQ(managed_node
, managed_node_
);
83 managed_bookmarks_tracker_
.reset(new ManagedBookmarksTracker(
87 base::Bind(&ManagedBookmarksTrackerTest::GetManagementDomain
)));
88 managed_bookmarks_tracker_
->Init(managed_node_
);
91 const BookmarkNode
* managed_node() {
95 bool IsManaged(const BookmarkNode
* node
) {
96 return node
&& node
->HasAncestor(managed_node_
);
99 static base::DictionaryValue
* CreateBookmark(const std::string
& title
,
100 const std::string
& url
) {
101 EXPECT_TRUE(GURL(url
).is_valid());
102 base::DictionaryValue
* dict
= new base::DictionaryValue();
103 dict
->SetString("name", title
);
104 dict
->SetString("url", GURL(url
).spec());
108 static base::DictionaryValue
* CreateFolder(const std::string
& title
,
109 base::ListValue
* children
) {
110 base::DictionaryValue
* dict
= new base::DictionaryValue();
111 dict
->SetString("name", title
);
112 dict
->Set("children", children
);
116 static base::ListValue
* CreateTestTree() {
117 base::ListValue
* folder
= new base::ListValue();
118 base::ListValue
* empty
= new base::ListValue();
119 folder
->Append(CreateFolder("Empty", empty
));
120 folder
->Append(CreateBookmark("Youtube", "http://youtube.com/"));
122 base::ListValue
* list
= new base::ListValue();
123 list
->Append(CreateBookmark("Google", "http://google.com/"));
124 list
->Append(CreateFolder("Folder", folder
));
129 static std::string
GetManagementDomain() {
130 return std::string();
133 static std::string
GetManagedFolderTitle() {
134 return l10n_util::GetStringUTF8(
135 IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME
);
138 static base::DictionaryValue
* CreateExpectedTree() {
139 return CreateFolder(GetManagedFolderTitle(), CreateTestTree());
142 static bool NodeMatchesValue(const BookmarkNode
* node
,
143 const base::DictionaryValue
* dict
) {
144 base::string16 title
;
145 if (!dict
->GetString("name", &title
) || node
->GetTitle() != title
)
148 if (node
->is_folder()) {
149 const base::ListValue
* children
= NULL
;
150 if (!dict
->GetList("children", &children
) ||
151 node
->child_count() != static_cast<int>(children
->GetSize())) {
154 for (int i
= 0; i
< node
->child_count(); ++i
) {
155 const base::DictionaryValue
* child
= NULL
;
156 if (!children
->GetDictionary(i
, &child
) ||
157 !NodeMatchesValue(node
->GetChild(i
), child
)) {
161 } else if (node
->is_url()) {
163 if (!dict
->GetString("url", &url
) || node
->url() != GURL(url
))
171 base::MessageLoop loop_
;
172 TestingPrefServiceSimple prefs_
;
173 bookmarks::TestBookmarkClient client_
;
174 scoped_ptr
<BookmarkModel
> model_
;
175 bookmarks::MockBookmarkModelObserver observer_
;
176 BookmarkPermanentNode
* managed_node_
;
177 scoped_ptr
<ManagedBookmarksTracker
> managed_bookmarks_tracker_
;
180 TEST_F(ManagedBookmarksTrackerTest
, Empty
) {
181 CreateModel(false /* is_supervised */);
182 EXPECT_TRUE(model_
->bookmark_bar_node()->empty());
183 EXPECT_TRUE(model_
->other_node()->empty());
184 EXPECT_TRUE(managed_node()->empty());
185 EXPECT_FALSE(managed_node()->IsVisible());
188 TEST_F(ManagedBookmarksTrackerTest
, LoadInitial
) {
189 // Set a policy before loading the model.
190 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
191 CreateModel(false /* is_supervised */);
192 EXPECT_TRUE(model_
->bookmark_bar_node()->empty());
193 EXPECT_TRUE(model_
->other_node()->empty());
194 EXPECT_FALSE(managed_node()->empty());
195 EXPECT_TRUE(managed_node()->IsVisible());
197 scoped_ptr
<base::DictionaryValue
> expected(CreateExpectedTree());
198 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
201 TEST_F(ManagedBookmarksTrackerTest
, SupervisedTrackerIgnoresManagedPref
) {
202 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
203 CreateModel(true /* is_supervised */);
204 EXPECT_TRUE(managed_node()->empty());
205 EXPECT_FALSE(managed_node()->IsVisible());
208 TEST_F(ManagedBookmarksTrackerTest
, SupervisedTrackerHandlesSupervisedPref
) {
209 prefs_
.SetManagedPref(bookmarks::prefs::kSupervisedBookmarks
,
211 CreateModel(true /* is_supervised */);
212 EXPECT_FALSE(managed_node()->empty());
213 EXPECT_TRUE(managed_node()->IsVisible());
214 // Don't bother checking the actual contents, the non-supervised tests cover
218 TEST_F(ManagedBookmarksTrackerTest
, SwapNodes
) {
219 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
220 CreateModel(false /* is_supervised */);
222 // Swap the Google bookmark with the Folder.
223 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
224 scoped_ptr
<base::Value
> removed
;
225 ASSERT_TRUE(updated
->Remove(0, &removed
));
226 updated
->Append(removed
.release());
228 // These two nodes should just be swapped.
229 const BookmarkNode
* parent
= managed_node();
230 EXPECT_CALL(observer_
, BookmarkNodeMoved(model_
.get(), parent
, 1, parent
, 0));
231 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
232 updated
->DeepCopy());
233 Mock::VerifyAndClearExpectations(&observer_
);
235 // Verify the final tree.
236 scoped_ptr
<base::DictionaryValue
> expected(
237 CreateFolder(GetManagedFolderTitle(), updated
.release()));
238 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
241 TEST_F(ManagedBookmarksTrackerTest
, RemoveNode
) {
242 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
243 CreateModel(false /* is_supervised */);
245 // Remove the Folder.
246 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
247 ASSERT_TRUE(updated
->Remove(1, NULL
));
249 const BookmarkNode
* parent
= managed_node();
250 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
.get(), parent
, 1, _
, _
));
251 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
252 updated
->DeepCopy());
253 Mock::VerifyAndClearExpectations(&observer_
);
255 // Verify the final tree.
256 scoped_ptr
<base::DictionaryValue
> expected(
257 CreateFolder(GetManagedFolderTitle(), updated
.release()));
258 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
261 TEST_F(ManagedBookmarksTrackerTest
, CreateNewNodes
) {
262 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
263 CreateModel(false /* is_supervised */);
265 // Put all the nodes inside another folder.
266 scoped_ptr
<base::ListValue
> updated(new base::ListValue
);
267 updated
->Append(CreateFolder("Container", CreateTestTree()));
269 EXPECT_CALL(observer_
, BookmarkNodeAdded(model_
.get(), _
, _
)).Times(5);
270 // The remaining nodes have been pushed to positions 1 and 2; they'll both be
271 // removed when at position 1.
272 const BookmarkNode
* parent
= managed_node();
273 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
.get(), parent
, 1, _
, _
))
275 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
276 updated
->DeepCopy());
277 Mock::VerifyAndClearExpectations(&observer_
);
279 // Verify the final tree.
280 scoped_ptr
<base::DictionaryValue
> expected(
281 CreateFolder(GetManagedFolderTitle(), updated
.release()));
282 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
285 TEST_F(ManagedBookmarksTrackerTest
, RemoveAll
) {
286 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
287 CreateModel(false /* is_supervised */);
288 EXPECT_TRUE(managed_node()->IsVisible());
290 // Remove the policy.
291 const BookmarkNode
* parent
= managed_node();
292 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
.get(), parent
, 0, _
, _
))
294 prefs_
.RemoveManagedPref(bookmarks::prefs::kManagedBookmarks
);
295 Mock::VerifyAndClearExpectations(&observer_
);
297 EXPECT_TRUE(managed_node()->empty());
298 EXPECT_FALSE(managed_node()->IsVisible());
301 TEST_F(ManagedBookmarksTrackerTest
, IsManaged
) {
302 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
303 CreateModel(false /* is_supervised */);
305 EXPECT_FALSE(IsManaged(model_
->root_node()));
306 EXPECT_FALSE(IsManaged(model_
->bookmark_bar_node()));
307 EXPECT_FALSE(IsManaged(model_
->other_node()));
308 EXPECT_FALSE(IsManaged(model_
->mobile_node()));
309 EXPECT_TRUE(IsManaged(managed_node()));
311 const BookmarkNode
* parent
= managed_node();
312 ASSERT_EQ(2, parent
->child_count());
313 EXPECT_TRUE(IsManaged(parent
->GetChild(0)));
314 EXPECT_TRUE(IsManaged(parent
->GetChild(1)));
316 parent
= parent
->GetChild(1);
317 ASSERT_EQ(2, parent
->child_count());
318 EXPECT_TRUE(IsManaged(parent
->GetChild(0)));
319 EXPECT_TRUE(IsManaged(parent
->GetChild(1)));
322 TEST_F(ManagedBookmarksTrackerTest
, RemoveAllUserBookmarksDoesntRemoveManaged
) {
323 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
324 CreateModel(false /* is_supervised */);
325 EXPECT_EQ(2, managed_node()->child_count());
327 EXPECT_CALL(observer_
,
328 BookmarkNodeAdded(model_
.get(), model_
->bookmark_bar_node(), 0));
329 EXPECT_CALL(observer_
,
330 BookmarkNodeAdded(model_
.get(), model_
->bookmark_bar_node(), 1));
331 model_
->AddURL(model_
->bookmark_bar_node(),
333 base::ASCIIToUTF16("Test"),
334 GURL("http://google.com/"));
336 model_
->bookmark_bar_node(), 1, base::ASCIIToUTF16("Test Folder"));
337 EXPECT_EQ(2, model_
->bookmark_bar_node()->child_count());
338 Mock::VerifyAndClearExpectations(&observer_
);
340 EXPECT_CALL(observer_
, BookmarkAllUserNodesRemoved(model_
.get(), _
));
341 model_
->RemoveAllUserBookmarks();
342 EXPECT_EQ(2, managed_node()->child_count());
343 EXPECT_EQ(0, model_
->bookmark_bar_node()->child_count());
344 Mock::VerifyAndClearExpectations(&observer_
);
347 } // namespace policy