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