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 "chrome/browser/bookmarks/chrome_bookmark_client.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/chrome_bookmark_client_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
;
33 class ChromeBookmarkClientTest
: public testing::Test
{
35 ChromeBookmarkClientTest() : client_(NULL
), model_(NULL
) {}
36 ~ChromeBookmarkClientTest() override
{}
38 void SetUp() override
{
39 prefs_
= profile_
.GetTestingPrefService();
40 ASSERT_FALSE(prefs_
->HasPrefPath(bookmarks::prefs::kManagedBookmarks
));
42 prefs_
->SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
46 // The managed node always exists.
47 ASSERT_TRUE(client_
->managed_node());
48 ASSERT_TRUE(client_
->managed_node()->parent() == model_
->root_node());
49 EXPECT_NE(-1, model_
->root_node()->GetIndexOf(client_
->managed_node()));
52 void TearDown() override
{ model_
->RemoveObserver(&observer_
); }
55 profile_
.CreateBookmarkModel(false);
56 model_
= BookmarkModelFactory::GetForProfile(&profile_
);
57 bookmarks::test::WaitForBookmarkModelToLoad(model_
);
58 model_
->AddObserver(&observer_
);
59 client_
= ChromeBookmarkClientFactory::GetForProfile(&profile_
);
63 static base::DictionaryValue
* CreateBookmark(const std::string
& title
,
64 const std::string
& url
) {
65 EXPECT_TRUE(GURL(url
).is_valid());
66 base::DictionaryValue
* dict
= new base::DictionaryValue();
67 dict
->SetString("name", title
);
68 dict
->SetString("url", GURL(url
).spec());
72 static base::DictionaryValue
* CreateFolder(const std::string
& title
,
73 base::ListValue
* children
) {
74 base::DictionaryValue
* dict
= new base::DictionaryValue();
75 dict
->SetString("name", title
);
76 dict
->Set("children", children
);
80 static base::ListValue
* CreateTestTree() {
81 base::ListValue
* folder
= new base::ListValue();
82 base::ListValue
* empty
= new base::ListValue();
83 folder
->Append(CreateFolder("Empty", empty
));
84 folder
->Append(CreateBookmark("Youtube", "http://youtube.com/"));
86 base::ListValue
* list
= new base::ListValue();
87 list
->Append(CreateBookmark("Google", "http://google.com/"));
88 list
->Append(CreateFolder("Folder", folder
));
93 static base::DictionaryValue
* CreateExpectedTree() {
94 return CreateFolder(GetManagedFolderTitle(), CreateTestTree());
97 static std::string
GetManagedFolderTitle() {
98 return l10n_util::GetStringUTF8(
99 IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME
);
102 static bool NodeMatchesValue(const BookmarkNode
* node
,
103 const base::DictionaryValue
* dict
) {
104 base::string16 title
;
105 if (!dict
->GetString("name", &title
) || node
->GetTitle() != title
)
108 if (node
->is_folder()) {
109 const base::ListValue
* children
= NULL
;
110 if (!dict
->GetList("children", &children
) ||
111 node
->child_count() != static_cast<int>(children
->GetSize())) {
114 for (int i
= 0; i
< node
->child_count(); ++i
) {
115 const base::DictionaryValue
* child
= NULL
;
116 if (!children
->GetDictionary(i
, &child
) ||
117 !NodeMatchesValue(node
->GetChild(i
), child
)) {
121 } else if (node
->is_url()) {
123 if (!dict
->GetString("url", &url
) || node
->url() != GURL(url
))
131 content::TestBrowserThreadBundle thread_bundle_
;
132 TestingProfile profile_
;
133 TestingPrefServiceSyncable
* prefs_
;
134 bookmarks::MockBookmarkModelObserver observer_
;
135 ChromeBookmarkClient
* client_
;
136 BookmarkModel
* model_
;
138 DISALLOW_COPY_AND_ASSIGN(ChromeBookmarkClientTest
);
141 TEST_F(ChromeBookmarkClientTest
, EmptyManagedNode
) {
142 // Verifies that the managed node is empty and invisible when the policy is
144 model_
->RemoveObserver(&observer_
);
145 prefs_
->RemoveManagedPref(bookmarks::prefs::kManagedBookmarks
);
148 ASSERT_TRUE(client_
->managed_node());
149 EXPECT_TRUE(client_
->managed_node()->empty());
150 EXPECT_FALSE(client_
->managed_node()->IsVisible());
153 TEST_F(ChromeBookmarkClientTest
, LoadInitial
) {
154 // Verifies that the initial load picks up the initial policy too.
155 EXPECT_TRUE(model_
->bookmark_bar_node()->empty());
156 EXPECT_TRUE(model_
->other_node()->empty());
157 EXPECT_FALSE(client_
->managed_node()->empty());
158 EXPECT_TRUE(client_
->managed_node()->IsVisible());
160 scoped_ptr
<base::DictionaryValue
> expected(CreateExpectedTree());
161 EXPECT_TRUE(NodeMatchesValue(client_
->managed_node(), expected
.get()));
164 TEST_F(ChromeBookmarkClientTest
, SwapNodes
) {
165 // Swap the Google bookmark with the Folder.
166 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
167 scoped_ptr
<base::Value
> removed
;
168 ASSERT_TRUE(updated
->Remove(0, &removed
));
169 updated
->Append(removed
.release());
171 // These two nodes should just be swapped.
172 const BookmarkNode
* parent
= client_
->managed_node();
173 EXPECT_CALL(observer_
, BookmarkNodeMoved(model_
, parent
, 1, parent
, 0));
174 prefs_
->SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
175 updated
->DeepCopy());
176 Mock::VerifyAndClearExpectations(&observer_
);
178 // Verify the final tree.
179 scoped_ptr
<base::DictionaryValue
> expected(
180 CreateFolder(GetManagedFolderTitle(), updated
.release()));
181 EXPECT_TRUE(NodeMatchesValue(client_
->managed_node(), expected
.get()));
184 TEST_F(ChromeBookmarkClientTest
, RemoveNode
) {
185 // Remove the Folder.
186 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
187 ASSERT_TRUE(updated
->Remove(1, NULL
));
189 const BookmarkNode
* parent
= client_
->managed_node();
190 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
, parent
, 1, _
, _
));
191 prefs_
->SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
192 updated
->DeepCopy());
193 Mock::VerifyAndClearExpectations(&observer_
);
195 // Verify the final tree.
196 scoped_ptr
<base::DictionaryValue
> expected(
197 CreateFolder(GetManagedFolderTitle(), updated
.release()));
198 EXPECT_TRUE(NodeMatchesValue(client_
->managed_node(), expected
.get()));
201 TEST_F(ChromeBookmarkClientTest
, CreateNewNodes
) {
202 // Put all the nodes inside another folder.
203 scoped_ptr
<base::ListValue
> updated(new base::ListValue
);
204 updated
->Append(CreateFolder("Container", CreateTestTree()));
206 EXPECT_CALL(observer_
, BookmarkNodeAdded(model_
, _
, _
)).Times(5);
207 // The remaining nodes have been pushed to positions 1 and 2; they'll both be
208 // removed when at position 1.
209 const BookmarkNode
* parent
= client_
->managed_node();
210 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
, parent
, 1, _
, _
))
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(client_
->managed_node(), expected
.get()));
222 TEST_F(ChromeBookmarkClientTest
, RemoveAllUserBookmarks
) {
223 // Remove the policy.
224 const BookmarkNode
* parent
= client_
->managed_node();
225 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
, parent
, 0, _
, _
))
227 prefs_
->RemoveManagedPref(bookmarks::prefs::kManagedBookmarks
);
228 Mock::VerifyAndClearExpectations(&observer_
);
230 EXPECT_TRUE(client_
->managed_node()->empty());
231 EXPECT_FALSE(client_
->managed_node()->IsVisible());
234 TEST_F(ChromeBookmarkClientTest
, IsDescendantOfManagedNode
) {
235 EXPECT_FALSE(bookmarks::IsDescendantOf(model_
->root_node(),
236 client_
->managed_node()));
237 EXPECT_FALSE(bookmarks::IsDescendantOf(model_
->bookmark_bar_node(),
238 client_
->managed_node()));
239 EXPECT_FALSE(bookmarks::IsDescendantOf(model_
->other_node(),
240 client_
->managed_node()));
241 EXPECT_FALSE(bookmarks::IsDescendantOf(model_
->mobile_node(),
242 client_
->managed_node()));
243 EXPECT_TRUE(bookmarks::IsDescendantOf(client_
->managed_node(),
244 client_
->managed_node()));
246 const BookmarkNode
* parent
= client_
->managed_node();
247 ASSERT_EQ(2, parent
->child_count());
248 EXPECT_TRUE(bookmarks::IsDescendantOf(parent
->GetChild(0),
249 client_
->managed_node()));
250 EXPECT_TRUE(bookmarks::IsDescendantOf(parent
->GetChild(1),
251 client_
->managed_node()));
253 parent
= parent
->GetChild(1);
254 ASSERT_EQ(2, parent
->child_count());
255 EXPECT_TRUE(bookmarks::IsDescendantOf(parent
->GetChild(0),
256 client_
->managed_node()));
257 EXPECT_TRUE(bookmarks::IsDescendantOf(parent
->GetChild(1),
258 client_
->managed_node()));
261 TEST_F(ChromeBookmarkClientTest
, RemoveAllDoesntRemoveManaged
) {
262 EXPECT_EQ(2, client_
->managed_node()->child_count());
264 EXPECT_CALL(observer_
,
265 BookmarkNodeAdded(model_
, model_
->bookmark_bar_node(), 0));
266 EXPECT_CALL(observer_
,
267 BookmarkNodeAdded(model_
, model_
->bookmark_bar_node(), 1));
268 model_
->AddURL(model_
->bookmark_bar_node(),
270 base::ASCIIToUTF16("Test"),
271 GURL("http://google.com/"));
273 model_
->bookmark_bar_node(), 1, base::ASCIIToUTF16("Test Folder"));
274 EXPECT_EQ(2, model_
->bookmark_bar_node()->child_count());
275 Mock::VerifyAndClearExpectations(&observer_
);
277 EXPECT_CALL(observer_
, BookmarkAllUserNodesRemoved(model_
, _
));
278 model_
->RemoveAllUserBookmarks();
279 EXPECT_EQ(2, client_
->managed_node()->child_count());
280 EXPECT_EQ(0, model_
->bookmark_bar_node()->child_count());
281 Mock::VerifyAndClearExpectations(&observer_
);
284 TEST_F(ChromeBookmarkClientTest
, HasDescendantsOfManagedNode
) {
285 const BookmarkNode
* user_node
= model_
->AddURL(model_
->other_node(),
287 base::ASCIIToUTF16("foo bar"),
288 GURL("http://www.google.com"));
289 const BookmarkNode
* managed_node
= client_
->managed_node()->GetChild(0);
290 ASSERT_TRUE(managed_node
);
292 std::vector
<const BookmarkNode
*> nodes
;
293 EXPECT_FALSE(bookmarks::HasDescendantsOf(nodes
, client_
->managed_node()));
294 nodes
.push_back(user_node
);
295 EXPECT_FALSE(bookmarks::HasDescendantsOf(nodes
, client_
->managed_node()));
296 nodes
.push_back(managed_node
);
297 EXPECT_TRUE(bookmarks::HasDescendantsOf(nodes
, client_
->managed_node()));