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. 4 5#include "components/policy/core/browser/managed_bookmarks_tracker.h" 6 7#include "base/bind.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" 25#include "url/gurl.h" 26 27using testing::Mock; 28using testing::_; 29 30namespace policy { 31 32class ManagedBookmarksTrackerTest : public testing::Test { 33 public: 34 ManagedBookmarksTrackerTest() : managed_node_(NULL) {} 35 virtual ~ManagedBookmarksTrackerTest() {} 36 37 virtual void SetUp() OVERRIDE { 38 prefs_.registry()->RegisterListPref(prefs::kManagedBookmarks); 39 prefs_.registry()->RegisterListPref(prefs::kBookmarkEditorExpandedNodes); 40 } 41 42 virtual void TearDown() OVERRIDE { 43 if (model_) 44 model_->RemoveObserver(&observer_); 45 } 46 47 void CreateModel() { 48 // Simulate the creation of the managed node by the BookmarkClient. 49 BookmarkPermanentNode* managed_node = new BookmarkPermanentNode(100); 50 policy::ManagedBookmarksTracker::LoadInitial( 51 managed_node, prefs_.GetList(prefs::kManagedBookmarks), 101); 52 managed_node->set_visible(!managed_node->empty()); 53 managed_node->SetTitle(l10n_util::GetStringUTF16( 54 IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME)); 55 56 bookmarks::BookmarkPermanentNodeList extra_nodes; 57 extra_nodes.push_back(managed_node); 58 client_.SetExtraNodesToLoad(extra_nodes.Pass()); 59 60 model_.reset(new BookmarkModel(&client_, false)); 61 model_->AddObserver(&observer_); 62 EXPECT_CALL(observer_, BookmarkModelLoaded(model_.get(), _)); 63 model_->Load(&prefs_, 64 std::string(), 65 base::FilePath(), 66 base::MessageLoopProxy::current(), 67 base::MessageLoopProxy::current()); 68 test::WaitForBookmarkModelToLoad(model_.get()); 69 Mock::VerifyAndClearExpectations(&observer_); 70 71 ASSERT_EQ(1u, client_.extra_nodes().size()); 72 managed_node_ = client_.extra_nodes()[0]; 73 ASSERT_EQ(managed_node, managed_node_); 74 75 managed_bookmarks_tracker_.reset(new ManagedBookmarksTracker( 76 model_.get(), 77 &prefs_, 78 base::Bind(&ManagedBookmarksTrackerTest::GetManagementDomain))); 79 managed_bookmarks_tracker_->Init(managed_node_); 80 } 81 82 const BookmarkNode* managed_node() { 83 return managed_node_; 84 } 85 86 bool IsManaged(const BookmarkNode* node) { 87 return node && node->HasAncestor(managed_node_); 88 } 89 90 static base::DictionaryValue* CreateBookmark(const std::string& title, 91 const std::string& url) { 92 EXPECT_TRUE(GURL(url).is_valid()); 93 base::DictionaryValue* dict = new base::DictionaryValue(); 94 dict->SetString("name", title); 95 dict->SetString("url", GURL(url).spec()); 96 return dict; 97 } 98 99 static base::DictionaryValue* CreateFolder(const std::string& title, 100 base::ListValue* children) { 101 base::DictionaryValue* dict = new base::DictionaryValue(); 102 dict->SetString("name", title); 103 dict->Set("children", children); 104 return dict; 105 } 106 107 static base::ListValue* CreateTestTree() { 108 base::ListValue* folder = new base::ListValue(); 109 base::ListValue* empty = new base::ListValue(); 110 folder->Append(CreateFolder("Empty", empty)); 111 folder->Append(CreateBookmark("Youtube", "http://youtube.com/")); 112 113 base::ListValue* list = new base::ListValue(); 114 list->Append(CreateBookmark("Google", "http://google.com/")); 115 list->Append(CreateFolder("Folder", folder)); 116 117 return list; 118 } 119 120 static std::string GetManagementDomain() { 121 return std::string(); 122 } 123 124 static std::string GetManagedFolderTitle() { 125 return l10n_util::GetStringUTF8( 126 IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME); 127 } 128 129 static base::DictionaryValue* CreateExpectedTree() { 130 return CreateFolder(GetManagedFolderTitle(), CreateTestTree()); 131 } 132 133 static bool NodeMatchesValue(const BookmarkNode* node, 134 const base::DictionaryValue* dict) { 135 base::string16 title; 136 if (!dict->GetString("name", &title) || node->GetTitle() != title) 137 return false; 138 139 if (node->is_folder()) { 140 const base::ListValue* children = NULL; 141 if (!dict->GetList("children", &children) || 142 node->child_count() != static_cast<int>(children->GetSize())) { 143 return false; 144 } 145 for (int i = 0; i < node->child_count(); ++i) { 146 const base::DictionaryValue* child = NULL; 147 if (!children->GetDictionary(i, &child) || 148 !NodeMatchesValue(node->GetChild(i), child)) { 149 return false; 150 } 151 } 152 } else if (node->is_url()) { 153 std::string url; 154 if (!dict->GetString("url", &url) || node->url() != GURL(url)) 155 return false; 156 } else { 157 return false; 158 } 159 return true; 160 } 161 162 base::MessageLoop loop_; 163 TestingPrefServiceSimple prefs_; 164 test::TestBookmarkClient client_; 165 scoped_ptr<BookmarkModel> model_; 166 MockBookmarkModelObserver observer_; 167 BookmarkPermanentNode* managed_node_; 168 scoped_ptr<ManagedBookmarksTracker> managed_bookmarks_tracker_; 169}; 170 171TEST_F(ManagedBookmarksTrackerTest, Empty) { 172 CreateModel(); 173 EXPECT_TRUE(model_->bookmark_bar_node()->empty()); 174 EXPECT_TRUE(model_->other_node()->empty()); 175 EXPECT_TRUE(managed_node()->empty()); 176 EXPECT_FALSE(managed_node()->IsVisible()); 177} 178 179TEST_F(ManagedBookmarksTrackerTest, LoadInitial) { 180 // Set a policy before loading the model. 181 prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); 182 CreateModel(); 183 EXPECT_TRUE(model_->bookmark_bar_node()->empty()); 184 EXPECT_TRUE(model_->other_node()->empty()); 185 EXPECT_FALSE(managed_node()->empty()); 186 EXPECT_TRUE(managed_node()->IsVisible()); 187 188 scoped_ptr<base::DictionaryValue> expected(CreateExpectedTree()); 189 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected.get())); 190} 191 192TEST_F(ManagedBookmarksTrackerTest, SwapNodes) { 193 prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); 194 CreateModel(); 195 196 // Swap the Google bookmark with the Folder. 197 scoped_ptr<base::ListValue> updated(CreateTestTree()); 198 scoped_ptr<base::Value> removed; 199 ASSERT_TRUE(updated->Remove(0, &removed)); 200 updated->Append(removed.release()); 201 202 // These two nodes should just be swapped. 203 const BookmarkNode* parent = managed_node(); 204 EXPECT_CALL(observer_, BookmarkNodeMoved(model_.get(), parent, 1, parent, 0)); 205 prefs_.SetManagedPref(prefs::kManagedBookmarks, updated->DeepCopy()); 206 Mock::VerifyAndClearExpectations(&observer_); 207 208 // Verify the final tree. 209 scoped_ptr<base::DictionaryValue> expected( 210 CreateFolder(GetManagedFolderTitle(), updated.release())); 211 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected.get())); 212} 213 214TEST_F(ManagedBookmarksTrackerTest, RemoveNode) { 215 prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); 216 CreateModel(); 217 218 // Remove the Folder. 219 scoped_ptr<base::ListValue> updated(CreateTestTree()); 220 ASSERT_TRUE(updated->Remove(1, NULL)); 221 222 const BookmarkNode* parent = managed_node(); 223 EXPECT_CALL(observer_, BookmarkNodeRemoved(model_.get(), parent, 1, _, _)); 224 prefs_.SetManagedPref(prefs::kManagedBookmarks, updated->DeepCopy()); 225 Mock::VerifyAndClearExpectations(&observer_); 226 227 // Verify the final tree. 228 scoped_ptr<base::DictionaryValue> expected( 229 CreateFolder(GetManagedFolderTitle(), updated.release())); 230 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected.get())); 231} 232 233TEST_F(ManagedBookmarksTrackerTest, CreateNewNodes) { 234 prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); 235 CreateModel(); 236 237 // Put all the nodes inside another folder. 238 scoped_ptr<base::ListValue> updated(new base::ListValue); 239 updated->Append(CreateFolder("Container", CreateTestTree())); 240 241 EXPECT_CALL(observer_, BookmarkNodeAdded(model_.get(), _, _)).Times(5); 242 // The remaining nodes have been pushed to positions 1 and 2; they'll both be 243 // removed when at position 1. 244 const BookmarkNode* parent = managed_node(); 245 EXPECT_CALL(observer_, BookmarkNodeRemoved(model_.get(), parent, 1, _, _)) 246 .Times(2); 247 prefs_.SetManagedPref(prefs::kManagedBookmarks, updated->DeepCopy()); 248 Mock::VerifyAndClearExpectations(&observer_); 249 250 // Verify the final tree. 251 scoped_ptr<base::DictionaryValue> expected( 252 CreateFolder(GetManagedFolderTitle(), updated.release())); 253 EXPECT_TRUE(NodeMatchesValue(managed_node(), expected.get())); 254} 255 256TEST_F(ManagedBookmarksTrackerTest, RemoveAll) { 257 prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); 258 CreateModel(); 259 EXPECT_TRUE(managed_node()->IsVisible()); 260 261 // Remove the policy. 262 const BookmarkNode* parent = managed_node(); 263 EXPECT_CALL(observer_, BookmarkNodeRemoved(model_.get(), parent, 0, _, _)) 264 .Times(2); 265 prefs_.RemoveManagedPref(prefs::kManagedBookmarks); 266 Mock::VerifyAndClearExpectations(&observer_); 267 268 EXPECT_TRUE(managed_node()->empty()); 269 EXPECT_FALSE(managed_node()->IsVisible()); 270} 271 272TEST_F(ManagedBookmarksTrackerTest, IsManaged) { 273 prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); 274 CreateModel(); 275 276 EXPECT_FALSE(IsManaged(model_->root_node())); 277 EXPECT_FALSE(IsManaged(model_->bookmark_bar_node())); 278 EXPECT_FALSE(IsManaged(model_->other_node())); 279 EXPECT_FALSE(IsManaged(model_->mobile_node())); 280 EXPECT_TRUE(IsManaged(managed_node())); 281 282 const BookmarkNode* parent = managed_node(); 283 ASSERT_EQ(2, parent->child_count()); 284 EXPECT_TRUE(IsManaged(parent->GetChild(0))); 285 EXPECT_TRUE(IsManaged(parent->GetChild(1))); 286 287 parent = parent->GetChild(1); 288 ASSERT_EQ(2, parent->child_count()); 289 EXPECT_TRUE(IsManaged(parent->GetChild(0))); 290 EXPECT_TRUE(IsManaged(parent->GetChild(1))); 291} 292 293TEST_F(ManagedBookmarksTrackerTest, RemoveAllUserBookmarksDoesntRemoveManaged) { 294 prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); 295 CreateModel(); 296 EXPECT_EQ(2, managed_node()->child_count()); 297 298 EXPECT_CALL(observer_, 299 BookmarkNodeAdded(model_.get(), model_->bookmark_bar_node(), 0)); 300 EXPECT_CALL(observer_, 301 BookmarkNodeAdded(model_.get(), model_->bookmark_bar_node(), 1)); 302 model_->AddURL(model_->bookmark_bar_node(), 303 0, 304 base::ASCIIToUTF16("Test"), 305 GURL("http://google.com/")); 306 model_->AddFolder( 307 model_->bookmark_bar_node(), 1, base::ASCIIToUTF16("Test Folder")); 308 EXPECT_EQ(2, model_->bookmark_bar_node()->child_count()); 309 Mock::VerifyAndClearExpectations(&observer_); 310 311 EXPECT_CALL(observer_, BookmarkAllUserNodesRemoved(model_.get(), _)); 312 model_->RemoveAllUserBookmarks(); 313 EXPECT_EQ(2, managed_node()->child_count()); 314 EXPECT_EQ(0, model_->bookmark_bar_node()->child_count()); 315 Mock::VerifyAndClearExpectations(&observer_); 316} 317 318} // namespace policy 319