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