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_bookmark_service.h"
7 #include "base/macros.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
12 #include "chrome/browser/bookmarks/chrome_bookmark_client.h"
13 #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h"
14 #include "chrome/test/base/testing_pref_service_syncable.h"
15 #include "chrome/test/base/testing_profile.h"
16 #include "components/bookmarks/browser/bookmark_model.h"
17 #include "components/bookmarks/browser/bookmark_node.h"
18 #include "components/bookmarks/browser/bookmark_utils.h"
19 #include "components/bookmarks/common/bookmark_pref_names.h"
20 #include "components/bookmarks/test/bookmark_test_helpers.h"
21 #include "components/bookmarks/test/mock_bookmark_model_observer.h"
22 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "grit/components_strings.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "ui/base/l10n/l10n_util.h"
28 using bookmarks::BookmarkModel
;
29 using bookmarks::BookmarkNode
;
30 using bookmarks::ManagedBookmarkService
;
34 class ManagedBookmarkServiceTest
: public testing::Test
{
36 ManagedBookmarkServiceTest() : managed_(NULL
), model_(NULL
) {}
37 ~ManagedBookmarkServiceTest() override
{}
39 void SetUp() override
{
40 prefs_
= profile_
.GetTestingPrefService();
41 ASSERT_FALSE(prefs_
->HasPrefPath(bookmarks::prefs::kManagedBookmarks
));
43 prefs_
->SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
47 // The managed node always exists.
48 ASSERT_TRUE(managed_
->managed_node());
49 ASSERT_TRUE(managed_
->managed_node()->parent() == model_
->root_node());
50 EXPECT_NE(-1, model_
->root_node()->GetIndexOf(managed_
->managed_node()));
53 void TearDown() override
{ model_
->RemoveObserver(&observer_
); }
56 profile_
.CreateBookmarkModel(false);
57 model_
= BookmarkModelFactory::GetForProfile(&profile_
);
58 bookmarks::test::WaitForBookmarkModelToLoad(model_
);
59 model_
->AddObserver(&observer_
);
60 managed_
= ManagedBookmarkServiceFactory::GetForProfile(&profile_
);
64 static base::DictionaryValue
* CreateBookmark(const std::string
& title
,
65 const std::string
& url
) {
66 EXPECT_TRUE(GURL(url
).is_valid());
67 base::DictionaryValue
* dict
= new base::DictionaryValue();
68 dict
->SetString("name", title
);
69 dict
->SetString("url", GURL(url
).spec());
73 static base::DictionaryValue
* CreateFolder(const std::string
& title
,
74 base::ListValue
* children
) {
75 base::DictionaryValue
* dict
= new base::DictionaryValue();
76 dict
->SetString("name", title
);
77 dict
->Set("children", children
);
81 static base::ListValue
* CreateTestTree() {
82 base::ListValue
* folder
= new base::ListValue();
83 base::ListValue
* empty
= new base::ListValue();
84 folder
->Append(CreateFolder("Empty", empty
));
85 folder
->Append(CreateBookmark("Youtube", "http://youtube.com/"));
87 base::ListValue
* list
= new base::ListValue();
88 list
->Append(CreateBookmark("Google", "http://google.com/"));
89 list
->Append(CreateFolder("Folder", folder
));
94 static base::DictionaryValue
* CreateExpectedTree() {
95 return CreateFolder(GetManagedFolderTitle(), CreateTestTree());
98 static std::string
GetManagedFolderTitle() {
99 return l10n_util::GetStringUTF8(
100 IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME
);
103 static bool NodeMatchesValue(const BookmarkNode
* node
,
104 const base::DictionaryValue
* dict
) {
105 base::string16 title
;
106 if (!dict
->GetString("name", &title
) || node
->GetTitle() != title
)
109 if (node
->is_folder()) {
110 const base::ListValue
* children
= NULL
;
111 if (!dict
->GetList("children", &children
) ||
112 node
->child_count() != static_cast<int>(children
->GetSize())) {
115 for (int i
= 0; i
< node
->child_count(); ++i
) {
116 const base::DictionaryValue
* child
= NULL
;
117 if (!children
->GetDictionary(i
, &child
) ||
118 !NodeMatchesValue(node
->GetChild(i
), child
)) {
122 } else if (node
->is_url()) {
124 if (!dict
->GetString("url", &url
) || node
->url() != GURL(url
))
132 content::TestBrowserThreadBundle thread_bundle_
;
133 TestingProfile profile_
;
134 TestingPrefServiceSyncable
* prefs_
;
135 bookmarks::MockBookmarkModelObserver observer_
;
136 ManagedBookmarkService
* managed_
;
137 BookmarkModel
* model_
;
139 DISALLOW_COPY_AND_ASSIGN(ManagedBookmarkServiceTest
);
142 TEST_F(ManagedBookmarkServiceTest
, EmptyManagedNode
) {
143 // Verifies that the managed node is empty and invisible when the policy is
145 model_
->RemoveObserver(&observer_
);
146 prefs_
->RemoveManagedPref(bookmarks::prefs::kManagedBookmarks
);
149 ASSERT_TRUE(managed_
->managed_node());
150 EXPECT_TRUE(managed_
->managed_node()->empty());
151 EXPECT_FALSE(managed_
->managed_node()->IsVisible());
154 TEST_F(ManagedBookmarkServiceTest
, LoadInitial
) {
155 // Verifies that the initial load picks up the initial policy too.
156 EXPECT_TRUE(model_
->bookmark_bar_node()->empty());
157 EXPECT_TRUE(model_
->other_node()->empty());
158 EXPECT_FALSE(managed_
->managed_node()->empty());
159 EXPECT_TRUE(managed_
->managed_node()->IsVisible());
161 scoped_ptr
<base::DictionaryValue
> expected(CreateExpectedTree());
162 EXPECT_TRUE(NodeMatchesValue(managed_
->managed_node(), expected
.get()));
165 TEST_F(ManagedBookmarkServiceTest
, SwapNodes
) {
166 // Swap the Google bookmark with the Folder.
167 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
168 scoped_ptr
<base::Value
> removed
;
169 ASSERT_TRUE(updated
->Remove(0, &removed
));
170 updated
->Append(removed
.release());
172 // These two nodes should just be swapped.
173 const BookmarkNode
* parent
= managed_
->managed_node();
174 EXPECT_CALL(observer_
, BookmarkNodeMoved(model_
, parent
, 1, parent
, 0));
175 prefs_
->SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
176 updated
->DeepCopy());
177 Mock::VerifyAndClearExpectations(&observer_
);
179 // Verify the final tree.
180 scoped_ptr
<base::DictionaryValue
> expected(
181 CreateFolder(GetManagedFolderTitle(), updated
.release()));
182 EXPECT_TRUE(NodeMatchesValue(managed_
->managed_node(), expected
.get()));
185 TEST_F(ManagedBookmarkServiceTest
, RemoveNode
) {
186 // Remove the Folder.
187 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
188 ASSERT_TRUE(updated
->Remove(1, NULL
));
190 const BookmarkNode
* parent
= managed_
->managed_node();
191 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
, parent
, 1, _
, _
));
192 prefs_
->SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
193 updated
->DeepCopy());
194 Mock::VerifyAndClearExpectations(&observer_
);
196 // Verify the final tree.
197 scoped_ptr
<base::DictionaryValue
> expected(
198 CreateFolder(GetManagedFolderTitle(), updated
.release()));
199 EXPECT_TRUE(NodeMatchesValue(managed_
->managed_node(), expected
.get()));
202 TEST_F(ManagedBookmarkServiceTest
, CreateNewNodes
) {
203 // Put all the nodes inside another folder.
204 scoped_ptr
<base::ListValue
> updated(new base::ListValue
);
205 updated
->Append(CreateFolder("Container", CreateTestTree()));
207 EXPECT_CALL(observer_
, BookmarkNodeAdded(model_
, _
, _
)).Times(5);
208 // The remaining nodes have been pushed to positions 1 and 2; they'll both be
209 // removed when at position 1.
210 const BookmarkNode
* parent
= managed_
->managed_node();
211 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
, parent
, 1, _
, _
)).Times(2);
212 prefs_
->SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
213 updated
->DeepCopy());
214 Mock::VerifyAndClearExpectations(&observer_
);
216 // Verify the final tree.
217 scoped_ptr
<base::DictionaryValue
> expected(
218 CreateFolder(GetManagedFolderTitle(), updated
.release()));
219 EXPECT_TRUE(NodeMatchesValue(managed_
->managed_node(), expected
.get()));
222 TEST_F(ManagedBookmarkServiceTest
, RemoveAllUserBookmarks
) {
223 // Remove the policy.
224 const BookmarkNode
* parent
= managed_
->managed_node();
225 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
, parent
, 0, _
, _
)).Times(2);
226 prefs_
->RemoveManagedPref(bookmarks::prefs::kManagedBookmarks
);
227 Mock::VerifyAndClearExpectations(&observer_
);
229 EXPECT_TRUE(managed_
->managed_node()->empty());
230 EXPECT_FALSE(managed_
->managed_node()->IsVisible());
233 TEST_F(ManagedBookmarkServiceTest
, IsDescendantOfManagedNode
) {
235 bookmarks::IsDescendantOf(model_
->root_node(), managed_
->managed_node()));
236 EXPECT_FALSE(bookmarks::IsDescendantOf(model_
->bookmark_bar_node(),
237 managed_
->managed_node()));
238 EXPECT_FALSE(bookmarks::IsDescendantOf(model_
->other_node(),
239 managed_
->managed_node()));
240 EXPECT_FALSE(bookmarks::IsDescendantOf(model_
->mobile_node(),
241 managed_
->managed_node()));
242 EXPECT_TRUE(bookmarks::IsDescendantOf(managed_
->managed_node(),
243 managed_
->managed_node()));
245 const BookmarkNode
* parent
= managed_
->managed_node();
246 ASSERT_EQ(2, parent
->child_count());
248 bookmarks::IsDescendantOf(parent
->GetChild(0), managed_
->managed_node()));
250 bookmarks::IsDescendantOf(parent
->GetChild(1), managed_
->managed_node()));
252 parent
= parent
->GetChild(1);
253 ASSERT_EQ(2, parent
->child_count());
255 bookmarks::IsDescendantOf(parent
->GetChild(0), managed_
->managed_node()));
257 bookmarks::IsDescendantOf(parent
->GetChild(1), managed_
->managed_node()));
260 TEST_F(ManagedBookmarkServiceTest
, RemoveAllDoesntRemoveManaged
) {
261 EXPECT_EQ(2, managed_
->managed_node()->child_count());
263 EXPECT_CALL(observer_
,
264 BookmarkNodeAdded(model_
, model_
->bookmark_bar_node(), 0));
265 EXPECT_CALL(observer_
,
266 BookmarkNodeAdded(model_
, model_
->bookmark_bar_node(), 1));
267 model_
->AddURL(model_
->bookmark_bar_node(), 0, base::ASCIIToUTF16("Test"),
268 GURL("http://google.com/"));
269 model_
->AddFolder(model_
->bookmark_bar_node(), 1,
270 base::ASCIIToUTF16("Test Folder"));
271 EXPECT_EQ(2, model_
->bookmark_bar_node()->child_count());
272 Mock::VerifyAndClearExpectations(&observer_
);
274 EXPECT_CALL(observer_
, BookmarkAllUserNodesRemoved(model_
, _
));
275 model_
->RemoveAllUserBookmarks();
276 EXPECT_EQ(2, managed_
->managed_node()->child_count());
277 EXPECT_EQ(0, model_
->bookmark_bar_node()->child_count());
278 Mock::VerifyAndClearExpectations(&observer_
);
281 TEST_F(ManagedBookmarkServiceTest
, HasDescendantsOfManagedNode
) {
282 const BookmarkNode
* user_node
=
283 model_
->AddURL(model_
->other_node(), 0, base::ASCIIToUTF16("foo bar"),
284 GURL("http://www.google.com"));
285 const BookmarkNode
* managed_node
= managed_
->managed_node()->GetChild(0);
286 ASSERT_TRUE(managed_node
);
288 std::vector
<const BookmarkNode
*> nodes
;
289 EXPECT_FALSE(bookmarks::HasDescendantsOf(nodes
, managed_
->managed_node()));
290 nodes
.push_back(user_node
);
291 EXPECT_FALSE(bookmarks::HasDescendantsOf(nodes
, managed_
->managed_node()));
292 nodes
.push_back(managed_node
);
293 EXPECT_TRUE(bookmarks::HasDescendantsOf(nodes
, managed_
->managed_node()));