Home | History | Annotate | Download | only in bookmarks
      1 // Copyright (c) 2012 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/ui/views/bookmarks/bookmark_context_menu.h"
      6 
      7 #include <string>
      8 #include <vector>
      9 
     10 #include "base/compiler_specific.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "base/threading/sequenced_worker_pool.h"
     14 #include "chrome/app/chrome_command_ids.h"
     15 #include "chrome/browser/bookmarks/bookmark_model.h"
     16 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
     19 #include "chrome/test/base/testing_profile.h"
     20 #include "chrome/test/base/ui_test_utils.h"
     21 #include "content/public/browser/page_navigator.h"
     22 #include "content/public/test/test_browser_thread.h"
     23 #include "grit/generated_resources.h"
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 #include "ui/base/clipboard/clipboard.h"
     26 
     27 #if defined(OS_WIN)
     28 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
     29 #endif
     30 
     31 using content::BrowserThread;
     32 using content::OpenURLParams;
     33 using content::PageNavigator;
     34 using content::WebContents;
     35 
     36 namespace {
     37 
     38 // PageNavigator implementation that records the URL.
     39 class TestingPageNavigator : public PageNavigator {
     40  public:
     41   virtual WebContents* OpenURL(const OpenURLParams& params) OVERRIDE {
     42     urls_.push_back(params.url);
     43     return NULL;
     44   }
     45 
     46   std::vector<GURL> urls_;
     47 };
     48 
     49 }  // namespace
     50 
     51 class BookmarkContextMenuTest : public testing::Test {
     52  public:
     53   BookmarkContextMenuTest()
     54       : ui_thread_(BrowserThread::UI, &message_loop_),
     55         file_thread_(BrowserThread::FILE, &message_loop_),
     56         model_(NULL) {
     57   }
     58 
     59   virtual void SetUp() OVERRIDE {
     60     profile_.reset(new TestingProfile());
     61     profile_->CreateBookmarkModel(true);
     62 
     63     model_ = BookmarkModelFactory::GetForProfile(profile_.get());
     64     ui_test_utils::WaitForBookmarkModelToLoad(model_);
     65 
     66     AddTestData();
     67   }
     68 
     69   virtual void TearDown() OVERRIDE {
     70     ui::Clipboard::DestroyClipboardForCurrentThread();
     71 
     72     BrowserThread::GetBlockingPool()->FlushForTesting();
     73     // Flush the message loop to make application verifiers happy.
     74     message_loop_.RunUntilIdle();
     75   }
     76 
     77  protected:
     78   base::MessageLoopForUI message_loop_;
     79   content::TestBrowserThread ui_thread_;
     80   content::TestBrowserThread file_thread_;
     81   scoped_ptr<TestingProfile> profile_;
     82   BookmarkModel* model_;
     83   TestingPageNavigator navigator_;
     84 
     85  private:
     86   // Creates the following structure:
     87   // a
     88   // F1
     89   //  f1a
     90   // -f1b as "chrome://settings"
     91   //  F11
     92   //   f11a
     93   // F2
     94   // F3
     95   // F4
     96   //   f4a
     97   void AddTestData() {
     98     const BookmarkNode* bb_node = model_->bookmark_bar_node();
     99     std::string test_base = "file:///c:/tmp/";
    100     model_->AddURL(bb_node, 0, ASCIIToUTF16("a"), GURL(test_base + "a"));
    101     const BookmarkNode* f1 = model_->AddFolder(bb_node, 1, ASCIIToUTF16("F1"));
    102     model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
    103     model_->AddURL(f1, 1, ASCIIToUTF16("f1b"), GURL("chrome://settings"));
    104     const BookmarkNode* f11 = model_->AddFolder(f1, 2, ASCIIToUTF16("F11"));
    105     model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
    106     model_->AddFolder(bb_node, 2, ASCIIToUTF16("F2"));
    107     model_->AddFolder(bb_node, 3, ASCIIToUTF16("F3"));
    108     const BookmarkNode* f4 = model_->AddFolder(bb_node, 4, ASCIIToUTF16("F4"));
    109     model_->AddURL(f4, 0, ASCIIToUTF16("f4a"), GURL(test_base + "f4a"));
    110   }
    111 };
    112 
    113 // Tests Deleting from the menu.
    114 TEST_F(BookmarkContextMenuTest, DeleteURL) {
    115   std::vector<const BookmarkNode*> nodes;
    116   nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
    117   BookmarkContextMenu controller(
    118       NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes, false);
    119   GURL url = model_->bookmark_bar_node()->GetChild(0)->url();
    120   ASSERT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_REMOVE));
    121   // Delete the URL.
    122   controller.ExecuteCommand(IDC_BOOKMARK_BAR_REMOVE, 0);
    123   // Model shouldn't have URL anymore.
    124   ASSERT_FALSE(model_->IsBookmarked(url));
    125 }
    126 
    127 // Tests open all on a folder with a couple of bookmarks.
    128 TEST_F(BookmarkContextMenuTest, OpenAll) {
    129   const BookmarkNode* folder = model_->bookmark_bar_node()->GetChild(1);
    130   chrome::OpenAll(NULL, &navigator_, folder, NEW_FOREGROUND_TAB, NULL);
    131 
    132   // Should have navigated to F1's child but not F11's child.
    133   ASSERT_EQ(static_cast<size_t>(2), navigator_.urls_.size());
    134   ASSERT_TRUE(folder->GetChild(0)->url() == navigator_.urls_[0]);
    135 }
    136 
    137 // Tests open all on a folder with a couple of bookmarks in incognito window.
    138 TEST_F(BookmarkContextMenuTest, OpenAllIngonito) {
    139   const BookmarkNode* folder = model_->bookmark_bar_node()->GetChild(1);
    140   chrome::OpenAll(NULL, &navigator_, folder, OFF_THE_RECORD, NULL);
    141 
    142   // Should have navigated to only f1a but not f2a.
    143   ASSERT_EQ(static_cast<size_t>(1), navigator_.urls_.size());
    144   ASSERT_TRUE(folder->GetChild(0)->url() == navigator_.urls_[0]);
    145 }
    146 
    147 // Tests the enabled state of the menus when supplied an empty vector.
    148 TEST_F(BookmarkContextMenuTest, EmptyNodes) {
    149   BookmarkContextMenu controller(
    150       NULL, NULL, profile_.get(), NULL, model_->other_node(),
    151       std::vector<const BookmarkNode*>(), false);
    152   EXPECT_FALSE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
    153   EXPECT_FALSE(
    154       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
    155   EXPECT_FALSE(
    156       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
    157   EXPECT_FALSE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_REMOVE));
    158   EXPECT_TRUE(
    159       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
    160   EXPECT_TRUE(
    161       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
    162 }
    163 
    164 // Tests the enabled state of the menus when supplied a vector with a single
    165 // url.
    166 TEST_F(BookmarkContextMenuTest, SingleURL) {
    167   std::vector<const BookmarkNode*> nodes;
    168   nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
    169   BookmarkContextMenu controller(
    170       NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes, false);
    171   EXPECT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
    172   EXPECT_TRUE(
    173       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
    174   EXPECT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
    175   EXPECT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_REMOVE));
    176   EXPECT_TRUE(
    177       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
    178   EXPECT_TRUE(
    179       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
    180 }
    181 
    182 // Tests the enabled state of the menus when supplied a vector with multiple
    183 // urls.
    184 TEST_F(BookmarkContextMenuTest, MultipleURLs) {
    185   std::vector<const BookmarkNode*> nodes;
    186   nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
    187   nodes.push_back(model_->bookmark_bar_node()->GetChild(1)->GetChild(0));
    188   BookmarkContextMenu controller(
    189       NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes, false);
    190   EXPECT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
    191   EXPECT_TRUE(
    192       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
    193   EXPECT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
    194   EXPECT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_REMOVE));
    195   EXPECT_TRUE(
    196       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
    197   EXPECT_TRUE(
    198       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
    199 }
    200 
    201 // Tests the enabled state of the menus when supplied an vector with a single
    202 // folder.
    203 TEST_F(BookmarkContextMenuTest, SingleFolder) {
    204   std::vector<const BookmarkNode*> nodes;
    205   nodes.push_back(model_->bookmark_bar_node()->GetChild(2));
    206   BookmarkContextMenu controller(
    207       NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes, false);
    208   EXPECT_FALSE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
    209   EXPECT_FALSE(
    210       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
    211   EXPECT_FALSE(
    212       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
    213   EXPECT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_REMOVE));
    214   EXPECT_TRUE(
    215       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
    216   EXPECT_TRUE(
    217       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
    218 }
    219 
    220 // Tests the enabled state of the menus when supplied a vector with multiple
    221 // folders, all of which are empty.
    222 TEST_F(BookmarkContextMenuTest, MultipleEmptyFolders) {
    223   std::vector<const BookmarkNode*> nodes;
    224   nodes.push_back(model_->bookmark_bar_node()->GetChild(2));
    225   nodes.push_back(model_->bookmark_bar_node()->GetChild(3));
    226   BookmarkContextMenu controller(
    227       NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes, false);
    228   EXPECT_FALSE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
    229   EXPECT_FALSE(
    230       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
    231   EXPECT_FALSE(
    232       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
    233   EXPECT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_REMOVE));
    234   EXPECT_TRUE(
    235       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
    236   EXPECT_TRUE(
    237       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
    238 }
    239 
    240 // Tests the enabled state of the menus when supplied a vector with multiple
    241 // folders, some of which contain URLs.
    242 TEST_F(BookmarkContextMenuTest, MultipleFoldersWithURLs) {
    243   std::vector<const BookmarkNode*> nodes;
    244   nodes.push_back(model_->bookmark_bar_node()->GetChild(3));
    245   nodes.push_back(model_->bookmark_bar_node()->GetChild(4));
    246   BookmarkContextMenu controller(
    247       NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes, false);
    248   EXPECT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
    249   EXPECT_TRUE(
    250       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
    251   EXPECT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
    252   EXPECT_TRUE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_REMOVE));
    253   EXPECT_TRUE(
    254       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
    255   EXPECT_TRUE(
    256       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
    257 }
    258 
    259 // Tests the enabled state of open incognito.
    260 TEST_F(BookmarkContextMenuTest, DisableIncognito) {
    261   std::vector<const BookmarkNode*> nodes;
    262   nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
    263   BookmarkContextMenu controller(
    264       NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes, false);
    265   profile_->set_incognito(true);
    266   EXPECT_FALSE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_INCOGNITO));
    267   EXPECT_FALSE(
    268       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
    269 }
    270 
    271 // Tests that you can't remove/edit when showing the other node.
    272 TEST_F(BookmarkContextMenuTest, DisabledItemsWithOtherNode) {
    273   std::vector<const BookmarkNode*> nodes;
    274   nodes.push_back(model_->other_node());
    275   BookmarkContextMenu controller(
    276       NULL, NULL, profile_.get(), NULL, nodes[0], nodes, false);
    277   EXPECT_FALSE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_EDIT));
    278   EXPECT_FALSE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_REMOVE));
    279 }
    280 
    281 // Tests the enabled state of the menus when supplied an empty vector and null
    282 // parent.
    283 TEST_F(BookmarkContextMenuTest, EmptyNodesNullParent) {
    284   BookmarkContextMenu controller(
    285       NULL, NULL, profile_.get(), NULL, NULL,
    286       std::vector<const BookmarkNode*>(), false);
    287   EXPECT_FALSE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
    288   EXPECT_FALSE(
    289       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
    290   EXPECT_FALSE(
    291       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
    292   EXPECT_FALSE(controller.IsCommandEnabled(IDC_BOOKMARK_BAR_REMOVE));
    293   EXPECT_FALSE(
    294       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
    295   EXPECT_FALSE(
    296       controller.IsCommandEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
    297 }
    298 
    299 TEST_F(BookmarkContextMenuTest, CutCopyPasteNode) {
    300   const BookmarkNode* bb_node = model_->bookmark_bar_node();
    301   std::vector<const BookmarkNode*> nodes;
    302   nodes.push_back(bb_node->GetChild(0));
    303   scoped_ptr<BookmarkContextMenu> controller(new BookmarkContextMenu(
    304       NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes, false));
    305   EXPECT_TRUE(controller->IsCommandEnabled(IDC_COPY));
    306   EXPECT_TRUE(controller->IsCommandEnabled(IDC_CUT));
    307 
    308   // Copy the URL.
    309   controller->ExecuteCommand(IDC_COPY, 0);
    310 
    311   controller.reset(new BookmarkContextMenu(
    312       NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes, false));
    313   int old_count = bb_node->child_count();
    314   controller->ExecuteCommand(IDC_PASTE, 0);
    315 
    316   ASSERT_TRUE(bb_node->GetChild(1)->is_url());
    317   ASSERT_EQ(old_count + 1, bb_node->child_count());
    318   ASSERT_EQ(bb_node->GetChild(0)->url(), bb_node->GetChild(1)->url());
    319 
    320   controller.reset(new BookmarkContextMenu(
    321       NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes, false));
    322   // Cut the URL.
    323   controller->ExecuteCommand(IDC_CUT, 0);
    324   ASSERT_TRUE(bb_node->GetChild(0)->is_url());
    325   ASSERT_TRUE(bb_node->GetChild(1)->is_folder());
    326   ASSERT_EQ(old_count, bb_node->child_count());
    327 }
    328