Home | History | Annotate | Download | only in bookmarks
      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 "chrome/browser/bookmarks/chrome_bookmark_client.h"
      6 
      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"
     26 
     27 using testing::Mock;
     28 using testing::_;
     29 
     30 class ChromeBookmarkClientTest : public testing::Test {
     31  public:
     32   ChromeBookmarkClientTest() : client_(NULL), model_(NULL) {}
     33   virtual ~ChromeBookmarkClientTest() {}
     34 
     35   virtual void SetUp() OVERRIDE {
     36     prefs_ = profile_.GetTestingPrefService();
     37     ASSERT_FALSE(prefs_->HasPrefPath(prefs::kManagedBookmarks));
     38 
     39     prefs_->SetManagedPref(prefs::kManagedBookmarks, CreateTestTree());
     40     ResetModel();
     41 
     42     // The managed node always exists.
     43     ASSERT_TRUE(client_->managed_node());
     44     ASSERT_TRUE(client_->managed_node()->parent() == model_->root_node());
     45     EXPECT_NE(-1, model_->root_node()->GetIndexOf(client_->managed_node()));
     46   }
     47 
     48   virtual void TearDown() OVERRIDE {
     49     model_->RemoveObserver(&observer_);
     50   }
     51 
     52   void ResetModel() {
     53     profile_.CreateBookmarkModel(false);
     54     model_ = BookmarkModelFactory::GetForProfile(&profile_);
     55     test::WaitForBookmarkModelToLoad(model_);
     56     model_->AddObserver(&observer_);
     57     client_ = ChromeBookmarkClientFactory::GetForProfile(&profile_);
     58     DCHECK(client_);
     59   }
     60 
     61   static base::DictionaryValue* CreateBookmark(const std::string& title,
     62                                                const std::string& url) {
     63     EXPECT_TRUE(GURL(url).is_valid());
     64     base::DictionaryValue* dict = new base::DictionaryValue();
     65     dict->SetString("name", title);
     66     dict->SetString("url", GURL(url).spec());
     67     return dict;
     68   }
     69 
     70   static base::DictionaryValue* CreateFolder(const std::string& title,
     71                                              base::ListValue* children) {
     72     base::DictionaryValue* dict = new base::DictionaryValue();
     73     dict->SetString("name", title);
     74     dict->Set("children", children);
     75     return dict;
     76   }
     77 
     78   static base::ListValue* CreateTestTree() {
     79     base::ListValue* folder = new base::ListValue();
     80     base::ListValue* empty = new base::ListValue();
     81     folder->Append(CreateFolder("Empty", empty));
     82     folder->Append(CreateBookmark("Youtube", "http://youtube.com/"));
     83 
     84     base::ListValue* list = new base::ListValue();
     85     list->Append(CreateBookmark("Google", "http://google.com/"));
     86     list->Append(CreateFolder("Folder", folder));
     87 
     88     return list;
     89   }
     90 
     91   static base::DictionaryValue* CreateExpectedTree() {
     92     return CreateFolder(GetManagedFolderTitle(), CreateTestTree());
     93   }
     94 
     95   static std::string GetManagedFolderTitle() {
     96     return l10n_util::GetStringUTF8(
     97         IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME);
     98   }
     99 
    100   static bool NodeMatchesValue(const BookmarkNode* node,
    101                                const base::DictionaryValue* dict) {
    102     base::string16 title;
    103     if (!dict->GetString("name", &title) || node->GetTitle() != title)
    104       return false;
    105 
    106     if (node->is_folder()) {
    107       const base::ListValue* children = NULL;
    108       if (!dict->GetList("children", &children) ||
    109           node->child_count() != static_cast<int>(children->GetSize())) {
    110         return false;
    111       }
    112       for (int i = 0; i < node->child_count(); ++i) {
    113         const base::DictionaryValue* child = NULL;
    114         if (!children->GetDictionary(i, &child) ||
    115             !NodeMatchesValue(node->GetChild(i), child)) {
    116           return false;
    117         }
    118       }
    119     } else if (node->is_url()) {
    120       std::string url;
    121       if (!dict->GetString("url", &url) || node->url() != GURL(url))
    122         return false;
    123     } else {
    124       return false;
    125     }
    126     return true;
    127   }
    128 
    129   content::TestBrowserThreadBundle thread_bundle_;
    130   TestingProfile profile_;
    131   TestingPrefServiceSyncable* prefs_;
    132   MockBookmarkModelObserver observer_;
    133   ChromeBookmarkClient* client_;
    134   BookmarkModel* model_;
    135 
    136   DISALLOW_COPY_AND_ASSIGN(ChromeBookmarkClientTest);
    137 };
    138 
    139 TEST_F(ChromeBookmarkClientTest, EmptyManagedNode) {
    140   // Verifies that the managed node is empty and invisible when the policy is
    141   // not set.
    142   model_->RemoveObserver(&observer_);
    143   prefs_->RemoveManagedPref(prefs::kManagedBookmarks);
    144   ResetModel();
    145 
    146   ASSERT_TRUE(client_->managed_node());
    147   EXPECT_TRUE(client_->managed_node()->empty());
    148   EXPECT_FALSE(client_->managed_node()->IsVisible());
    149 }
    150 
    151 TEST_F(ChromeBookmarkClientTest, LoadInitial) {
    152   // Verifies that the initial load picks up the initial policy too.
    153   EXPECT_TRUE(model_->bookmark_bar_node()->empty());
    154   EXPECT_TRUE(model_->other_node()->empty());
    155   EXPECT_FALSE(client_->managed_node()->empty());
    156   EXPECT_TRUE(client_->managed_node()->IsVisible());
    157 
    158   scoped_ptr<base::DictionaryValue> expected(CreateExpectedTree());
    159   EXPECT_TRUE(NodeMatchesValue(client_->managed_node(), expected.get()));
    160 }
    161 
    162 TEST_F(ChromeBookmarkClientTest, SwapNodes) {
    163   // Swap the Google bookmark with the Folder.
    164   scoped_ptr<base::ListValue> updated(CreateTestTree());
    165   scoped_ptr<base::Value> removed;
    166   ASSERT_TRUE(updated->Remove(0, &removed));
    167   updated->Append(removed.release());
    168 
    169   // These two nodes should just be swapped.
    170   const BookmarkNode* parent = client_->managed_node();
    171   EXPECT_CALL(observer_, BookmarkNodeMoved(model_, parent, 1, parent, 0));
    172   prefs_->SetManagedPref(prefs::kManagedBookmarks, updated->DeepCopy());
    173   Mock::VerifyAndClearExpectations(&observer_);
    174 
    175   // Verify the final tree.
    176   scoped_ptr<base::DictionaryValue> expected(
    177       CreateFolder(GetManagedFolderTitle(), updated.release()));
    178   EXPECT_TRUE(NodeMatchesValue(client_->managed_node(), expected.get()));
    179 }
    180 
    181 TEST_F(ChromeBookmarkClientTest, RemoveNode) {
    182   // Remove the Folder.
    183   scoped_ptr<base::ListValue> updated(CreateTestTree());
    184   ASSERT_TRUE(updated->Remove(1, NULL));
    185 
    186   const BookmarkNode* parent = client_->managed_node();
    187   EXPECT_CALL(observer_, BookmarkNodeRemoved(model_, parent, 1, _, _));
    188   prefs_->SetManagedPref(prefs::kManagedBookmarks, updated->DeepCopy());
    189   Mock::VerifyAndClearExpectations(&observer_);
    190 
    191   // Verify the final tree.
    192   scoped_ptr<base::DictionaryValue> expected(
    193       CreateFolder(GetManagedFolderTitle(), updated.release()));
    194   EXPECT_TRUE(NodeMatchesValue(client_->managed_node(), expected.get()));
    195 }
    196 
    197 TEST_F(ChromeBookmarkClientTest, CreateNewNodes) {
    198   // Put all the nodes inside another folder.
    199   scoped_ptr<base::ListValue> updated(new base::ListValue);
    200   updated->Append(CreateFolder("Container", CreateTestTree()));
    201 
    202   EXPECT_CALL(observer_, BookmarkNodeAdded(model_, _, _)).Times(5);
    203   // The remaining nodes have been pushed to positions 1 and 2; they'll both be
    204   // removed when at position 1.
    205   const BookmarkNode* parent = client_->managed_node();
    206   EXPECT_CALL(observer_, BookmarkNodeRemoved(model_, parent, 1, _, _))
    207       .Times(2);
    208   prefs_->SetManagedPref(prefs::kManagedBookmarks, updated->DeepCopy());
    209   Mock::VerifyAndClearExpectations(&observer_);
    210 
    211   // Verify the final tree.
    212   scoped_ptr<base::DictionaryValue> expected(
    213       CreateFolder(GetManagedFolderTitle(), updated.release()));
    214   EXPECT_TRUE(NodeMatchesValue(client_->managed_node(), expected.get()));
    215 }
    216 
    217 TEST_F(ChromeBookmarkClientTest, RemoveAllUserBookmarks) {
    218   // Remove the policy.
    219   const BookmarkNode* parent = client_->managed_node();
    220   EXPECT_CALL(observer_, BookmarkNodeRemoved(model_, parent, 0, _, _))
    221       .Times(2);
    222   prefs_->RemoveManagedPref(prefs::kManagedBookmarks);
    223   Mock::VerifyAndClearExpectations(&observer_);
    224 
    225   EXPECT_TRUE(client_->managed_node()->empty());
    226   EXPECT_FALSE(client_->managed_node()->IsVisible());
    227 }
    228 
    229 TEST_F(ChromeBookmarkClientTest, IsDescendantOfManagedNode) {
    230   EXPECT_FALSE(client_->IsDescendantOfManagedNode(model_->root_node()));
    231   EXPECT_FALSE(client_->IsDescendantOfManagedNode(model_->bookmark_bar_node()));
    232   EXPECT_FALSE(client_->IsDescendantOfManagedNode(model_->other_node()));
    233   EXPECT_FALSE(client_->IsDescendantOfManagedNode(model_->mobile_node()));
    234   EXPECT_TRUE(client_->IsDescendantOfManagedNode(client_->managed_node()));
    235 
    236   const BookmarkNode* parent = client_->managed_node();
    237   ASSERT_EQ(2, parent->child_count());
    238   EXPECT_TRUE(client_->IsDescendantOfManagedNode(parent->GetChild(0)));
    239   EXPECT_TRUE(client_->IsDescendantOfManagedNode(parent->GetChild(1)));
    240 
    241   parent = parent->GetChild(1);
    242   ASSERT_EQ(2, parent->child_count());
    243   EXPECT_TRUE(client_->IsDescendantOfManagedNode(parent->GetChild(0)));
    244   EXPECT_TRUE(client_->IsDescendantOfManagedNode(parent->GetChild(1)));
    245 }
    246 
    247 TEST_F(ChromeBookmarkClientTest, RemoveAllDoesntRemoveManaged) {
    248   EXPECT_EQ(2, client_->managed_node()->child_count());
    249 
    250   EXPECT_CALL(observer_,
    251               BookmarkNodeAdded(model_, model_->bookmark_bar_node(), 0));
    252   EXPECT_CALL(observer_,
    253               BookmarkNodeAdded(model_, model_->bookmark_bar_node(), 1));
    254   model_->AddURL(model_->bookmark_bar_node(),
    255                  0,
    256                  base::ASCIIToUTF16("Test"),
    257                  GURL("http://google.com/"));
    258   model_->AddFolder(
    259       model_->bookmark_bar_node(), 1, base::ASCIIToUTF16("Test Folder"));
    260   EXPECT_EQ(2, model_->bookmark_bar_node()->child_count());
    261   Mock::VerifyAndClearExpectations(&observer_);
    262 
    263   EXPECT_CALL(observer_, BookmarkAllUserNodesRemoved(model_, _));
    264   model_->RemoveAllUserBookmarks();
    265   EXPECT_EQ(2, client_->managed_node()->child_count());
    266   EXPECT_EQ(0, model_->bookmark_bar_node()->child_count());
    267   Mock::VerifyAndClearExpectations(&observer_);
    268 }
    269 
    270 TEST_F(ChromeBookmarkClientTest, HasDescendantsOfManagedNode) {
    271   const BookmarkNode* user_node = model_->AddURL(model_->other_node(),
    272                                                  0,
    273                                                  base::ASCIIToUTF16("foo bar"),
    274                                                  GURL("http://www.google.com"));
    275   const BookmarkNode* managed_node = client_->managed_node()->GetChild(0);
    276   ASSERT_TRUE(managed_node);
    277 
    278   std::vector<const BookmarkNode*> nodes;
    279   EXPECT_FALSE(client_->HasDescendantsOfManagedNode(nodes));
    280   nodes.push_back(user_node);
    281   EXPECT_FALSE(client_->HasDescendantsOfManagedNode(nodes));
    282   nodes.push_back(managed_node);
    283   EXPECT_TRUE(client_->HasDescendantsOfManagedNode(nodes));
    284 }
    285