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(bookmarks::prefs::kManagedBookmarks));
     38 
     39     prefs_->SetManagedPref(bookmarks::prefs::kManagedBookmarks,
     40                            CreateTestTree());
     41     ResetModel();
     42 
     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()));
     47   }
     48 
     49   virtual void TearDown() OVERRIDE {
     50     model_->RemoveObserver(&observer_);
     51   }
     52 
     53   void ResetModel() {
     54     profile_.CreateBookmarkModel(false);
     55     model_ = BookmarkModelFactory::GetForProfile(&profile_);
     56     test::WaitForBookmarkModelToLoad(model_);
     57     model_->AddObserver(&observer_);
     58     client_ = ChromeBookmarkClientFactory::GetForProfile(&profile_);
     59     DCHECK(client_);
     60   }
     61 
     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());
     68     return dict;
     69   }
     70 
     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);
     76     return dict;
     77   }
     78 
     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/"));
     84 
     85     base::ListValue* list = new base::ListValue();
     86     list->Append(CreateBookmark("Google", "http://google.com/"));
     87     list->Append(CreateFolder("Folder", folder));
     88 
     89     return list;
     90   }
     91 
     92   static base::DictionaryValue* CreateExpectedTree() {
     93     return CreateFolder(GetManagedFolderTitle(), CreateTestTree());
     94   }
     95 
     96   static std::string GetManagedFolderTitle() {
     97     return l10n_util::GetStringUTF8(
     98         IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME);
     99   }
    100 
    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)
    105       return false;
    106 
    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())) {
    111         return false;
    112       }
    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)) {
    117           return false;
    118         }
    119       }
    120     } else if (node->is_url()) {
    121       std::string url;
    122       if (!dict->GetString("url", &url) || node->url() != GURL(url))
    123         return false;
    124     } else {
    125       return false;
    126     }
    127     return true;
    128   }
    129 
    130   content::TestBrowserThreadBundle thread_bundle_;
    131   TestingProfile profile_;
    132   TestingPrefServiceSyncable* prefs_;
    133   bookmarks::MockBookmarkModelObserver observer_;
    134   ChromeBookmarkClient* client_;
    135   BookmarkModel* model_;
    136 
    137   DISALLOW_COPY_AND_ASSIGN(ChromeBookmarkClientTest);
    138 };
    139 
    140 TEST_F(ChromeBookmarkClientTest, EmptyManagedNode) {
    141   // Verifies that the managed node is empty and invisible when the policy is
    142   // not set.
    143   model_->RemoveObserver(&observer_);
    144   prefs_->RemoveManagedPref(bookmarks::prefs::kManagedBookmarks);
    145   ResetModel();
    146 
    147   ASSERT_TRUE(client_->managed_node());
    148   EXPECT_TRUE(client_->managed_node()->empty());
    149   EXPECT_FALSE(client_->managed_node()->IsVisible());
    150 }
    151 
    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());
    158 
    159   scoped_ptr<base::DictionaryValue> expected(CreateExpectedTree());
    160   EXPECT_TRUE(NodeMatchesValue(client_->managed_node(), expected.get()));
    161 }
    162 
    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());
    169 
    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_);
    176 
    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()));
    181 }
    182 
    183 TEST_F(ChromeBookmarkClientTest, RemoveNode) {
    184   // Remove the Folder.
    185   scoped_ptr<base::ListValue> updated(CreateTestTree());
    186   ASSERT_TRUE(updated->Remove(1, NULL));
    187 
    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_);
    193 
    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()));
    198 }
    199 
    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()));
    204 
    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, _, _))
    210       .Times(2);
    211   prefs_->SetManagedPref(bookmarks::prefs::kManagedBookmarks,
    212                          updated->DeepCopy());
    213   Mock::VerifyAndClearExpectations(&observer_);
    214 
    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()));
    219 }
    220 
    221 TEST_F(ChromeBookmarkClientTest, RemoveAllUserBookmarks) {
    222   // Remove the policy.
    223   const BookmarkNode* parent = client_->managed_node();
    224   EXPECT_CALL(observer_, BookmarkNodeRemoved(model_, parent, 0, _, _))
    225       .Times(2);
    226   prefs_->RemoveManagedPref(bookmarks::prefs::kManagedBookmarks);
    227   Mock::VerifyAndClearExpectations(&observer_);
    228 
    229   EXPECT_TRUE(client_->managed_node()->empty());
    230   EXPECT_FALSE(client_->managed_node()->IsVisible());
    231 }
    232 
    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()));
    239 
    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)));
    244 
    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)));
    249 }
    250 
    251 TEST_F(ChromeBookmarkClientTest, RemoveAllDoesntRemoveManaged) {
    252   EXPECT_EQ(2, client_->managed_node()->child_count());
    253 
    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(),
    259                  0,
    260                  base::ASCIIToUTF16("Test"),
    261                  GURL("http://google.com/"));
    262   model_->AddFolder(
    263       model_->bookmark_bar_node(), 1, base::ASCIIToUTF16("Test Folder"));
    264   EXPECT_EQ(2, model_->bookmark_bar_node()->child_count());
    265   Mock::VerifyAndClearExpectations(&observer_);
    266 
    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_);
    272 }
    273 
    274 TEST_F(ChromeBookmarkClientTest, HasDescendantsOfManagedNode) {
    275   const BookmarkNode* user_node = model_->AddURL(model_->other_node(),
    276                                                  0,
    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);
    281 
    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));
    288 }
    289