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/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 "content/public/test/test_browser_thread_bundle.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"
30 class ChromeBookmarkClientTest
: public testing::Test
{
32 ChromeBookmarkClientTest() : client_(NULL
), model_(NULL
) {}
33 virtual ~ChromeBookmarkClientTest() {}
35 virtual void SetUp() OVERRIDE
{
36 prefs_
= profile_
.GetTestingPrefService();
37 ASSERT_FALSE(prefs_
->HasPrefPath(bookmarks::prefs::kManagedBookmarks
));
39 prefs_
->SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
43 // The managed node always exists.
44 ASSERT_TRUE(client_
->managed_node());
45 ASSERT_TRUE(client_
->managed_node()->parent() == model_
->root_node());
46 EXPECT_NE(-1, model_
->root_node()->GetIndexOf(client_
->managed_node()));
49 virtual void TearDown() OVERRIDE
{
50 model_
->RemoveObserver(&observer_
);
54 profile_
.CreateBookmarkModel(false);
55 model_
= BookmarkModelFactory::GetForProfile(&profile_
);
56 test::WaitForBookmarkModelToLoad(model_
);
57 model_
->AddObserver(&observer_
);
58 client_
= ChromeBookmarkClientFactory::GetForProfile(&profile_
);
62 static base::DictionaryValue
* CreateBookmark(const std::string
& title
,
63 const std::string
& url
) {
64 EXPECT_TRUE(GURL(url
).is_valid());
65 base::DictionaryValue
* dict
= new base::DictionaryValue();
66 dict
->SetString("name", title
);
67 dict
->SetString("url", GURL(url
).spec());
71 static base::DictionaryValue
* CreateFolder(const std::string
& title
,
72 base::ListValue
* children
) {
73 base::DictionaryValue
* dict
= new base::DictionaryValue();
74 dict
->SetString("name", title
);
75 dict
->Set("children", children
);
79 static base::ListValue
* CreateTestTree() {
80 base::ListValue
* folder
= new base::ListValue();
81 base::ListValue
* empty
= new base::ListValue();
82 folder
->Append(CreateFolder("Empty", empty
));
83 folder
->Append(CreateBookmark("Youtube", "http://youtube.com/"));
85 base::ListValue
* list
= new base::ListValue();
86 list
->Append(CreateBookmark("Google", "http://google.com/"));
87 list
->Append(CreateFolder("Folder", folder
));
92 static base::DictionaryValue
* CreateExpectedTree() {
93 return CreateFolder(GetManagedFolderTitle(), CreateTestTree());
96 static std::string
GetManagedFolderTitle() {
97 return l10n_util::GetStringUTF8(
98 IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME
);
101 static bool NodeMatchesValue(const BookmarkNode
* node
,
102 const base::DictionaryValue
* dict
) {
103 base::string16 title
;
104 if (!dict
->GetString("name", &title
) || node
->GetTitle() != title
)
107 if (node
->is_folder()) {
108 const base::ListValue
* children
= NULL
;
109 if (!dict
->GetList("children", &children
) ||
110 node
->child_count() != static_cast<int>(children
->GetSize())) {
113 for (int i
= 0; i
< node
->child_count(); ++i
) {
114 const base::DictionaryValue
* child
= NULL
;
115 if (!children
->GetDictionary(i
, &child
) ||
116 !NodeMatchesValue(node
->GetChild(i
), child
)) {
120 } else if (node
->is_url()) {
122 if (!dict
->GetString("url", &url
) || node
->url() != GURL(url
))
130 content::TestBrowserThreadBundle thread_bundle_
;
131 TestingProfile profile_
;
132 TestingPrefServiceSyncable
* prefs_
;
133 MockBookmarkModelObserver observer_
;
134 ChromeBookmarkClient
* client_
;
135 BookmarkModel
* model_
;
137 DISALLOW_COPY_AND_ASSIGN(ChromeBookmarkClientTest
);
140 TEST_F(ChromeBookmarkClientTest
, EmptyManagedNode
) {
141 // Verifies that the managed node is empty and invisible when the policy is
143 model_
->RemoveObserver(&observer_
);
144 prefs_
->RemoveManagedPref(bookmarks::prefs::kManagedBookmarks
);
147 ASSERT_TRUE(client_
->managed_node());
148 EXPECT_TRUE(client_
->managed_node()->empty());
149 EXPECT_FALSE(client_
->managed_node()->IsVisible());
152 TEST_F(ChromeBookmarkClientTest
, LoadInitial
) {
153 // Verifies that the initial load picks up the initial policy too.
154 EXPECT_TRUE(model_
->bookmark_bar_node()->empty());
155 EXPECT_TRUE(model_
->other_node()->empty());
156 EXPECT_FALSE(client_
->managed_node()->empty());
157 EXPECT_TRUE(client_
->managed_node()->IsVisible());
159 scoped_ptr
<base::DictionaryValue
> expected(CreateExpectedTree());
160 EXPECT_TRUE(NodeMatchesValue(client_
->managed_node(), expected
.get()));
163 TEST_F(ChromeBookmarkClientTest
, SwapNodes
) {
164 // Swap the Google bookmark with the Folder.
165 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
166 scoped_ptr
<base::Value
> removed
;
167 ASSERT_TRUE(updated
->Remove(0, &removed
));
168 updated
->Append(removed
.release());
170 // These two nodes should just be swapped.
171 const BookmarkNode
* parent
= client_
->managed_node();
172 EXPECT_CALL(observer_
, BookmarkNodeMoved(model_
, parent
, 1, parent
, 0));
173 prefs_
->SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
174 updated
->DeepCopy());
175 Mock::VerifyAndClearExpectations(&observer_
);
177 // Verify the final tree.
178 scoped_ptr
<base::DictionaryValue
> expected(
179 CreateFolder(GetManagedFolderTitle(), updated
.release()));
180 EXPECT_TRUE(NodeMatchesValue(client_
->managed_node(), expected
.get()));
183 TEST_F(ChromeBookmarkClientTest
, RemoveNode
) {
184 // Remove the Folder.
185 scoped_ptr
<base::ListValue
> updated(CreateTestTree());
186 ASSERT_TRUE(updated
->Remove(1, NULL
));
188 const BookmarkNode
* parent
= client_
->managed_node();
189 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
, parent
, 1, _
, _
));
190 prefs_
->SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
191 updated
->DeepCopy());
192 Mock::VerifyAndClearExpectations(&observer_
);
194 // Verify the final tree.
195 scoped_ptr
<base::DictionaryValue
> expected(
196 CreateFolder(GetManagedFolderTitle(), updated
.release()));
197 EXPECT_TRUE(NodeMatchesValue(client_
->managed_node(), expected
.get()));
200 TEST_F(ChromeBookmarkClientTest
, CreateNewNodes
) {
201 // Put all the nodes inside another folder.
202 scoped_ptr
<base::ListValue
> updated(new base::ListValue
);
203 updated
->Append(CreateFolder("Container", CreateTestTree()));
205 EXPECT_CALL(observer_
, BookmarkNodeAdded(model_
, _
, _
)).Times(5);
206 // The remaining nodes have been pushed to positions 1 and 2; they'll both be
207 // removed when at position 1.
208 const BookmarkNode
* parent
= client_
->managed_node();
209 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
, parent
, 1, _
, _
))
211 prefs_
->SetManagedPref(bookmarks::prefs::kManagedBookmarks
,
212 updated
->DeepCopy());
213 Mock::VerifyAndClearExpectations(&observer_
);
215 // Verify the final tree.
216 scoped_ptr
<base::DictionaryValue
> expected(
217 CreateFolder(GetManagedFolderTitle(), updated
.release()));
218 EXPECT_TRUE(NodeMatchesValue(client_
->managed_node(), expected
.get()));
221 TEST_F(ChromeBookmarkClientTest
, RemoveAllUserBookmarks
) {
222 // Remove the policy.
223 const BookmarkNode
* parent
= client_
->managed_node();
224 EXPECT_CALL(observer_
, BookmarkNodeRemoved(model_
, parent
, 0, _
, _
))
226 prefs_
->RemoveManagedPref(bookmarks::prefs::kManagedBookmarks
);
227 Mock::VerifyAndClearExpectations(&observer_
);
229 EXPECT_TRUE(client_
->managed_node()->empty());
230 EXPECT_FALSE(client_
->managed_node()->IsVisible());
233 TEST_F(ChromeBookmarkClientTest
, IsDescendantOfManagedNode
) {
234 EXPECT_FALSE(client_
->IsDescendantOfManagedNode(model_
->root_node()));
235 EXPECT_FALSE(client_
->IsDescendantOfManagedNode(model_
->bookmark_bar_node()));
236 EXPECT_FALSE(client_
->IsDescendantOfManagedNode(model_
->other_node()));
237 EXPECT_FALSE(client_
->IsDescendantOfManagedNode(model_
->mobile_node()));
238 EXPECT_TRUE(client_
->IsDescendantOfManagedNode(client_
->managed_node()));
240 const BookmarkNode
* parent
= client_
->managed_node();
241 ASSERT_EQ(2, parent
->child_count());
242 EXPECT_TRUE(client_
->IsDescendantOfManagedNode(parent
->GetChild(0)));
243 EXPECT_TRUE(client_
->IsDescendantOfManagedNode(parent
->GetChild(1)));
245 parent
= parent
->GetChild(1);
246 ASSERT_EQ(2, parent
->child_count());
247 EXPECT_TRUE(client_
->IsDescendantOfManagedNode(parent
->GetChild(0)));
248 EXPECT_TRUE(client_
->IsDescendantOfManagedNode(parent
->GetChild(1)));
251 TEST_F(ChromeBookmarkClientTest
, RemoveAllDoesntRemoveManaged
) {
252 EXPECT_EQ(2, client_
->managed_node()->child_count());
254 EXPECT_CALL(observer_
,
255 BookmarkNodeAdded(model_
, model_
->bookmark_bar_node(), 0));
256 EXPECT_CALL(observer_
,
257 BookmarkNodeAdded(model_
, model_
->bookmark_bar_node(), 1));
258 model_
->AddURL(model_
->bookmark_bar_node(),
260 base::ASCIIToUTF16("Test"),
261 GURL("http://google.com/"));
263 model_
->bookmark_bar_node(), 1, base::ASCIIToUTF16("Test Folder"));
264 EXPECT_EQ(2, model_
->bookmark_bar_node()->child_count());
265 Mock::VerifyAndClearExpectations(&observer_
);
267 EXPECT_CALL(observer_
, BookmarkAllUserNodesRemoved(model_
, _
));
268 model_
->RemoveAllUserBookmarks();
269 EXPECT_EQ(2, client_
->managed_node()->child_count());
270 EXPECT_EQ(0, model_
->bookmark_bar_node()->child_count());
271 Mock::VerifyAndClearExpectations(&observer_
);
274 TEST_F(ChromeBookmarkClientTest
, HasDescendantsOfManagedNode
) {
275 const BookmarkNode
* user_node
= model_
->AddURL(model_
->other_node(),
277 base::ASCIIToUTF16("foo bar"),
278 GURL("http://www.google.com"));
279 const BookmarkNode
* managed_node
= client_
->managed_node()->GetChild(0);
280 ASSERT_TRUE(managed_node
);
282 std::vector
<const BookmarkNode
*> nodes
;
283 EXPECT_FALSE(client_
->HasDescendantsOfManagedNode(nodes
));
284 nodes
.push_back(user_node
);
285 EXPECT_FALSE(client_
->HasDescendantsOfManagedNode(nodes
));
286 nodes
.push_back(managed_node
);
287 EXPECT_TRUE(client_
->HasDescendantsOfManagedNode(nodes
));