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_
);
50 void CreateModel(bool is_supervised
) {
51 // Simulate the creation of the managed node by the BookmarkClient.
52 BookmarkPermanentNode
* managed_node
= new BookmarkPermanentNode(100);
53 ManagedBookmarksTracker::LoadInitial(
55 prefs_
.GetList(ManagedBookmarksTracker::GetPrefName(is_supervised
)),
57 managed_node
->set_visible(!managed_node
->empty());
58 managed_node
->SetTitle(l10n_util::GetStringUTF16(
59 is_supervised
? IDS_BOOKMARK_BAR_SUPERVISED_FOLDER_DEFAULT_NAME
60 : IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME
));
62 bookmarks::BookmarkPermanentNodeList extra_nodes
;
63 extra_nodes
.push_back(managed_node
);
64 client_
.SetExtraNodesToLoad(extra_nodes
.Pass());
66 model_
.reset(new BookmarkModel(&client_
));
67 model_
->AddObserver(&observer_
);
68 EXPECT_CALL(observer_
, BookmarkModelLoaded(model_
.get(), _
));
69 model_
->Load(&prefs_
, std::string(), base::FilePath(),
70 base::ThreadTaskRunnerHandle::Get(),
71 base::ThreadTaskRunnerHandle::Get());
72 bookmarks::test::WaitForBookmarkModelToLoad(model_
.get());
73 Mock::VerifyAndClearExpectations(&observer_
);
75 ASSERT_EQ(1u, client_
.extra_nodes().size());
76 managed_node_
= client_
.extra_nodes()[0];
77 ASSERT_EQ(managed_node
, managed_node_
);
79 managed_bookmarks_tracker_
.reset(new ManagedBookmarksTracker(
83 base::Bind(&ManagedBookmarksTrackerTest::GetManagementDomain
)));
84 managed_bookmarks_tracker_
->Init(managed_node_
);
87 const BookmarkNode
* managed_node() {
91 bool IsManaged(const BookmarkNode
* node
) {
92 return node
&& node
->HasAncestor(managed_node_
);
95 static base::DictionaryValue
* CreateBookmark(const std::string
& title
,
96 const std::string
& url
) {
97 EXPECT_TRUE(GURL(url
).is_valid());
98 base::DictionaryValue
* dict
= new base::DictionaryValue();
99 dict
->SetString("name", title
);
100 dict
->SetString("url", GURL(url
).spec());
104 static base::DictionaryValue
* CreateFolder(const std::string
& title
,
105 base::ListValue
* children
) {
106 base::DictionaryValue
* dict
= new base::DictionaryValue();
107 dict
->SetString("name", title
);
108 dict
->Set("children", children
);
112 static base::ListValue
* CreateTestTree() {
113 base::ListValue
* folder
= new base::ListValue();
114 base::ListValue
* empty
= new base::ListValue();
115 folder
->Append(CreateFolder("Empty", empty
));
116 folder
->Append(CreateBookmark("Youtube", "http://youtube.com/"));
118 base::ListValue
* list
= new base::ListValue();
119 list
->Append(CreateBookmark("Google", "http://google.com/"));
120 list
->Append(CreateFolder("Folder", folder
));
125 static std::string
GetManagementDomain() {
126 return std::string();
129 static std::string
GetManagedFolderTitle() {
130 return l10n_util::GetStringUTF8(
131 IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME
);
134 static base::DictionaryValue
* CreateExpectedTree() {
135 return CreateFolder(GetManagedFolderTitle(), CreateTestTree());
138 static bool NodeMatchesValue(const BookmarkNode
* node
,
139 const base::DictionaryValue
* dict
) {
140 base::string16 title
;
141 if (!dict
->GetString("name", &title
) || node
->GetTitle() != title
)
144 if (node
->is_folder()) {
145 const base::ListValue
* children
= NULL
;
146 if (!dict
->GetList("children", &children
) ||
147 node
->child_count() != static_cast<int>(children
->GetSize())) {
150 for (int i
= 0; i
< node
->child_count(); ++i
) {
151 const base::DictionaryValue
* child
= NULL
;
152 if (!children
->GetDictionary(i
, &child
) ||
153 !NodeMatchesValue(node
->GetChild(i
), child
)) {
157 } else if (node
->is_url()) {
159 if (!dict
->GetString("url", &url
) || node
->url() != GURL(url
))
167 base::MessageLoop loop_
;
168 TestingPrefServiceSimple prefs_
;
169 bookmarks::TestBookmarkClient client_
;
170 scoped_ptr
<BookmarkModel
> model_
;
171 bookmarks::MockBookmarkModelObserver observer_
;
172 BookmarkPermanentNode
* managed_node_
;
173 scoped_ptr
<ManagedBookmarksTracker
> managed_bookmarks_tracker_
;
176 TEST_F(ManagedBookmarksTrackerTest
, Empty
) {
177 CreateModel(false /* is_supervised */);
178 EXPECT_TRUE(model_
->bookmark_bar_node()->empty());
179 EXPECT_TRUE(model_
->other_node()->empty());
180 EXPECT_TRUE(managed_node()->empty());
181 EXPECT_FALSE(managed_node()->IsVisible());
184 TEST_F(ManagedBookmarksTrackerTest
, LoadInitial
) {
185 // Set a policy before loading the model.
186 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
187 CreateModel(false /* is_supervised */);
188 EXPECT_TRUE(model_
->bookmark_bar_node()->empty());
189 EXPECT_TRUE(model_
->other_node()->empty());
190 EXPECT_FALSE(managed_node()->empty());
191 EXPECT_TRUE(managed_node()->IsVisible());
193 scoped_ptr
<base::DictionaryValue
> expected(CreateExpectedTree());
194 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
197 TEST_F(ManagedBookmarksTrackerTest
, SupervisedTrackerIgnoresManagedPref
) {
198 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
199 CreateModel(true /* is_supervised */);
200 EXPECT_TRUE(managed_node()->empty());
201 EXPECT_FALSE(managed_node()->IsVisible());
204 TEST_F(ManagedBookmarksTrackerTest
, SupervisedTrackerHandlesSupervisedPref
) {
205 prefs_
.SetManagedPref(bookmarks::prefs::kSupervisedBookmarks
,
207 CreateModel(true /* is_supervised */);
208 EXPECT_FALSE(managed_node()->empty());
209 EXPECT_TRUE(managed_node()->IsVisible());
210 // Don't bother checking the actual contents, the non-supervised tests cover
214 TEST_F(ManagedBookmarksTrackerTest
, SwapNodes
) {
215 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
216 CreateModel(false /* is_supervised */);
218 // Swap the Google bookmark with the Folder.
219 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
220 scoped_ptr
<base::Value
> removed
;
221 ASSERT_TRUE(updated
->Remove(0, &removed
));
222 updated
->Append(removed
.release());
224 // These two nodes should just be swapped.
225 const BookmarkNode
* parent
= managed_node();
226 EXPECT_CALL(observer_
, BookmarkNodeMoved(model_
.get(), parent
, 1, parent
, 0));
227 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
228 updated
->DeepCopy());
229 Mock::VerifyAndClearExpectations(&observer_
);
231 // Verify the final tree.
232 scoped_ptr
<base::DictionaryValue
> expected(
233 CreateFolder(GetManagedFolderTitle(), updated
.release()));
234 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
237 TEST_F(ManagedBookmarksTrackerTest
, RemoveNode
) {
238 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
239 CreateModel(false /* is_supervised */);
241 // Remove the Folder.
242 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
243 ASSERT_TRUE(updated
->Remove(1, NULL
));
245 const BookmarkNode
* parent
= managed_node();
246 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
.get(), parent
, 1, _
, _
));
247 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
248 updated
->DeepCopy());
249 Mock::VerifyAndClearExpectations(&observer_
);
251 // Verify the final tree.
252 scoped_ptr
<base::DictionaryValue
> expected(
253 CreateFolder(GetManagedFolderTitle(), updated
.release()));
254 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
257 TEST_F(ManagedBookmarksTrackerTest
, CreateNewNodes
) {
258 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
259 CreateModel(false /* is_supervised */);
261 // Put all the nodes inside another folder.
262 scoped_ptr
<base::ListValue
> updated(new base::ListValue
);
263 updated
->Append(CreateFolder("Container", CreateTestTree()));
265 EXPECT_CALL(observer_
, BookmarkNodeAdded(model_
.get(), _
, _
)).Times(5);
266 // The remaining nodes have been pushed to positions 1 and 2; they'll both be
267 // removed when at position 1.
268 const BookmarkNode
* parent
= managed_node();
269 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
.get(), parent
, 1, _
, _
))
271 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
272 updated
->DeepCopy());
273 Mock::VerifyAndClearExpectations(&observer_
);
275 // Verify the final tree.
276 scoped_ptr
<base::DictionaryValue
> expected(
277 CreateFolder(GetManagedFolderTitle(), updated
.release()));
278 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected
.get()));
281 TEST_F(ManagedBookmarksTrackerTest
, RemoveAll
) {
282 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
283 CreateModel(false /* is_supervised */);
284 EXPECT_TRUE(managed_node()->IsVisible());
286 // Remove the policy.
287 const BookmarkNode
* parent
= managed_node();
288 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
.get(), parent
, 0, _
, _
))
290 prefs_
.RemoveManagedPref(bookmarks::prefs::kManagedBookmarks
);
291 Mock::VerifyAndClearExpectations(&observer_
);
293 EXPECT_TRUE(managed_node()->empty());
294 EXPECT_FALSE(managed_node()->IsVisible());
297 TEST_F(ManagedBookmarksTrackerTest
, IsManaged
) {
298 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
299 CreateModel(false /* is_supervised */);
301 EXPECT_FALSE(IsManaged(model_
->root_node()));
302 EXPECT_FALSE(IsManaged(model_
->bookmark_bar_node()));
303 EXPECT_FALSE(IsManaged(model_
->other_node()));
304 EXPECT_FALSE(IsManaged(model_
->mobile_node()));
305 EXPECT_TRUE(IsManaged(managed_node()));
307 const BookmarkNode
* parent
= managed_node();
308 ASSERT_EQ(2, parent
->child_count());
309 EXPECT_TRUE(IsManaged(parent
->GetChild(0)));
310 EXPECT_TRUE(IsManaged(parent
->GetChild(1)));
312 parent
= parent
->GetChild(1);
313 ASSERT_EQ(2, parent
->child_count());
314 EXPECT_TRUE(IsManaged(parent
->GetChild(0)));
315 EXPECT_TRUE(IsManaged(parent
->GetChild(1)));
318 TEST_F(ManagedBookmarksTrackerTest
, RemoveAllUserBookmarksDoesntRemoveManaged
) {
319 prefs_
.SetManagedPref(bookmarks::prefs::kManagedBookmarks
, CreateTestTree());
320 CreateModel(false /* is_supervised */);
321 EXPECT_EQ(2, managed_node()->child_count());
323 EXPECT_CALL(observer_
,
324 BookmarkNodeAdded(model_
.get(), model_
->bookmark_bar_node(), 0));
325 EXPECT_CALL(observer_
,
326 BookmarkNodeAdded(model_
.get(), model_
->bookmark_bar_node(), 1));
327 model_
->AddURL(model_
->bookmark_bar_node(),
329 base::ASCIIToUTF16("Test"),
330 GURL("http://google.com/"));
332 model_
->bookmark_bar_node(), 1, base::ASCIIToUTF16("Test Folder"));
333 EXPECT_EQ(2, model_
->bookmark_bar_node()->child_count());
334 Mock::VerifyAndClearExpectations(&observer_
);
336 EXPECT_CALL(observer_
, BookmarkAllUserNodesRemoved(model_
.get(), _
));
337 model_
->RemoveAllUserBookmarks();
338 EXPECT_EQ(2, managed_node()->child_count());
339 EXPECT_EQ(0, model_
->bookmark_bar_node()->child_count());
340 Mock::VerifyAndClearExpectations(&observer_
);
343 } // namespace bookmarks