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 "base/bind.h"
6#include "base/callback.h"
7#include "base/compiler_specific.h"
8#include "base/prefs/pref_service.h"
9#include "base/strings/string_number_conversions.h"
10#include "base/strings/utf_string_conversions.h"
11#include "chrome/app/chrome_command_ids.h"
12#include "chrome/browser/bookmarks/bookmark_model_factory.h"
13#include "chrome/browser/chrome_content_browser_client.h"
14#include "chrome/browser/chrome_notification_types.h"
15#include "chrome/browser/profiles/profile.h"
16#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
17#include "chrome/browser/ui/browser.h"
18#include "chrome/browser/ui/browser_tabstrip.h"
19#include "chrome/browser/ui/browser_window.h"
20#include "chrome/browser/ui/tabs/tab_strip_model.h"
21#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
22#include "chrome/common/chrome_content_client.h"
23#include "chrome/common/pref_names.h"
24#include "chrome/test/base/interactive_test_utils.h"
25#include "chrome/test/base/scoped_testing_local_state.h"
26#include "chrome/test/base/test_browser_window.h"
27#include "chrome/test/base/testing_browser_process.h"
28#include "chrome/test/base/testing_profile.h"
29#include "chrome/test/base/ui_test_utils.h"
30#include "chrome/test/base/view_event_test_base.h"
31#include "components/bookmarks/browser/bookmark_model.h"
32#include "components/bookmarks/test/bookmark_test_helpers.h"
33#include "content/public/browser/notification_service.h"
34#include "content/public/browser/page_navigator.h"
35#include "content/public/test/test_browser_thread.h"
36#include "grit/generated_resources.h"
37#include "ui/aura/env.h"
38#include "ui/aura/env_observer.h"
39#include "ui/aura/window.h"
40#include "ui/base/clipboard/clipboard.h"
41#include "ui/base/test/ui_controls.h"
42#include "ui/events/keycodes/keyboard_codes.h"
43#include "ui/views/controls/button/menu_button.h"
44#include "ui/views/controls/button/text_button.h"
45#include "ui/views/controls/menu/menu_controller.h"
46#include "ui/views/controls/menu/menu_item_view.h"
47#include "ui/views/controls/menu/submenu_view.h"
48#include "ui/views/widget/widget.h"
49
50using base::ASCIIToUTF16;
51using content::BrowserThread;
52using content::OpenURLParams;
53using content::PageNavigator;
54using content::WebContents;
55
56namespace {
57
58// Waits for a views::Widget dialog to show up.
59class DialogWaiter : public aura::EnvObserver,
60                     public views::WidgetObserver {
61 public:
62  DialogWaiter()
63      : dialog_created_(false),
64        dialog_(NULL) {
65    aura::Env::GetInstance()->AddObserver(this);
66  }
67
68  virtual ~DialogWaiter() {
69    aura::Env::GetInstance()->RemoveObserver(this);
70  }
71
72  views::Widget* WaitForDialog() {
73    if (dialog_created_)
74      return dialog_;
75    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
76    base::MessageLoopForUI::ScopedNestableTaskAllower allow_nested(loop);
77    base::RunLoop run_loop;
78    quit_closure_ = run_loop.QuitClosure();
79    run_loop.Run();
80    return dialog_;
81  }
82
83 private:
84  // aura::EnvObserver:
85  virtual void OnWindowInitialized(aura::Window* window) OVERRIDE {
86    if (dialog_)
87      return;
88    views::Widget* widget = views::Widget::GetWidgetForNativeView(window);
89    if (!widget || !widget->IsDialogBox())
90      return;
91    dialog_ = widget;
92    dialog_->AddObserver(this);
93  }
94
95  // views::WidgetObserver:
96  virtual void OnWidgetVisibilityChanged(views::Widget* widget,
97                                         bool visible) OVERRIDE {
98    CHECK_EQ(dialog_, widget);
99    if (visible) {
100      dialog_created_ = true;
101      dialog_->RemoveObserver(this);
102      if (!quit_closure_.is_null())
103        quit_closure_.Run();
104    }
105  }
106
107  bool dialog_created_;
108  views::Widget* dialog_;
109  base::Closure quit_closure_;
110
111  DISALLOW_COPY_AND_ASSIGN(DialogWaiter);
112};
113
114// Waits for a dialog to terminate.
115class DialogCloseWaiter : public views::WidgetObserver {
116 public:
117  explicit DialogCloseWaiter(views::Widget* dialog)
118      : dialog_closed_(false) {
119    dialog->AddObserver(this);
120  }
121
122  virtual ~DialogCloseWaiter() {
123    // It is not necessary to remove |this| from the dialog's observer, since
124    // the dialog is destroyed before this waiter.
125  }
126
127  void WaitForDialogClose() {
128    if (dialog_closed_)
129      return;
130    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
131    base::MessageLoopForUI::ScopedNestableTaskAllower allow_nested(loop);
132    base::RunLoop run_loop;
133    quit_closure_ = run_loop.QuitClosure();
134    run_loop.Run();
135  }
136
137 private:
138  // views::WidgetObserver:
139  virtual void OnWidgetDestroyed(views::Widget* widget) OVERRIDE {
140    dialog_closed_ = true;
141    if (!quit_closure_.is_null())
142      quit_closure_.Run();
143  }
144
145  bool dialog_closed_;
146  base::Closure quit_closure_;
147
148  DISALLOW_COPY_AND_ASSIGN(DialogCloseWaiter);
149};
150
151// Waits for a views::Widget to receive a Tab key.
152class TabKeyWaiter : public ui::EventHandler {
153 public:
154  explicit TabKeyWaiter(views::Widget* widget)
155      : widget_(widget),
156        received_tab_(false) {
157    widget_->GetNativeView()->AddPreTargetHandler(this);
158  }
159
160  virtual ~TabKeyWaiter() {
161    widget_->GetNativeView()->RemovePreTargetHandler(this);
162  }
163
164  void WaitForTab() {
165    if (received_tab_)
166      return;
167    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
168    base::MessageLoopForUI::ScopedNestableTaskAllower allow_nested(loop);
169    base::RunLoop run_loop;
170    quit_closure_ = run_loop.QuitClosure();
171    run_loop.Run();
172  }
173
174 private:
175  // ui::EventHandler:
176  virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
177    if (event->type() == ui::ET_KEY_RELEASED &&
178        event->key_code() == ui::VKEY_TAB) {
179      received_tab_ = true;
180      if (!quit_closure_.is_null())
181        quit_closure_.Run();
182    }
183  }
184
185  views::Widget* widget_;
186  bool received_tab_;
187  base::Closure quit_closure_;
188
189  DISALLOW_COPY_AND_ASSIGN(TabKeyWaiter);
190};
191
192void MoveMouseAndPress(const gfx::Point& screen_pos,
193                       ui_controls::MouseButton button,
194                       int state,
195                       const base::Closure& closure) {
196  ui_controls::SendMouseMove(screen_pos.x(), screen_pos.y());
197  ui_controls::SendMouseEventsNotifyWhenDone(button, state, closure);
198}
199
200// PageNavigator implementation that records the URL.
201class TestingPageNavigator : public PageNavigator {
202 public:
203  virtual WebContents* OpenURL(const OpenURLParams& params) OVERRIDE {
204    url_ = params.url;
205    return NULL;
206  }
207
208  GURL url_;
209};
210
211// TODO(erg): Fix bookmark DBD tests on linux_aura. crbug.com/163931
212#if defined(OS_LINUX) && defined(USE_AURA)
213#define MAYBE(x) DISABLED_##x
214#else
215#define MAYBE(x) x
216#endif
217
218}  // namespace
219
220// Base class for event generating bookmark view tests. These test are intended
221// to exercise View's menus, but that's easier done with BookmarkBarView rather
222// than View's menu itself.
223//
224// SetUp creates a bookmark model with the following structure.
225// All folders are in upper case, all URLs in lower case.
226// F1
227//   f1a
228//   F11
229//     f11a
230//   *
231// a
232// b
233// c
234// d
235// F2
236// e
237// OTHER
238//   oa
239//   OF
240//     ofa
241//     ofb
242//   OF2
243//     of2a
244//     of2b
245//
246// * if CreateBigMenu returns return true, 100 menu items are created here with
247//   the names f1-f100.
248//
249// Subclasses should be sure and invoke super's implementation of SetUp and
250// TearDown.
251class BookmarkBarViewEventTestBase : public ViewEventTestBase {
252 public:
253  BookmarkBarViewEventTestBase()
254      : ViewEventTestBase(),
255        model_(NULL) {}
256
257  virtual void SetUp() OVERRIDE {
258    content_client_.reset(new ChromeContentClient);
259    content::SetContentClient(content_client_.get());
260    browser_content_client_.reset(new chrome::ChromeContentBrowserClient());
261    content::SetBrowserClientForTesting(browser_content_client_.get());
262
263    views::MenuController::TurnOffMenuSelectionHoldForTest();
264    BookmarkBarView::DisableAnimationsForTesting(true);
265
266    profile_.reset(new TestingProfile());
267    profile_->CreateBookmarkModel(true);
268    model_ = BookmarkModelFactory::GetForProfile(profile_.get());
269    test::WaitForBookmarkModelToLoad(model_);
270    profile_->GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, true);
271
272    Browser::CreateParams native_params(profile_.get(),
273                                        chrome::GetActiveDesktop());
274    browser_.reset(
275        chrome::CreateBrowserWithTestWindowForParams(&native_params));
276
277    local_state_.reset(new ScopedTestingLocalState(
278        TestingBrowserProcess::GetGlobal()));
279    model_->ClearStore();
280
281    bb_view_.reset(new BookmarkBarView(browser_.get(), NULL));
282    bb_view_->set_owned_by_client();
283    bb_view_->SetPageNavigator(&navigator_);
284
285    AddTestData(CreateBigMenu());
286
287    // Calculate the preferred size so that one button doesn't fit, which
288    // triggers the overflow button to appear.
289    //
290    // BookmarkBarView::Layout does nothing if the parent is NULL and
291    // GetPreferredSize hard codes a width of 1. For that reason we add the
292    // BookmarkBarView to a dumby view as the parent.
293    //
294    // This code looks a bit hacky, but I've written it so that it shouldn't
295    // be dependant upon any of the layout code in BookmarkBarView. Instead
296    // we brute force search for a size that triggers the overflow button.
297    views::View tmp_parent;
298
299    tmp_parent.AddChildView(bb_view_.get());
300
301    bb_view_pref_ = bb_view_->GetPreferredSize();
302    bb_view_pref_.set_width(1000);
303    views::LabelButton* button = GetBookmarkButton(6);
304    while (button->visible()) {
305      bb_view_pref_.set_width(bb_view_pref_.width() - 25);
306      bb_view_->SetBounds(0, 0, bb_view_pref_.width(), bb_view_pref_.height());
307      bb_view_->Layout();
308    }
309
310    tmp_parent.RemoveChildView(bb_view_.get());
311
312    ViewEventTestBase::SetUp();
313  }
314
315  virtual void TearDown() {
316    // Destroy everything, then run the message loop to ensure we delete all
317    // Tasks and fully shut down.
318    browser_->tab_strip_model()->CloseAllTabs();
319    bb_view_.reset();
320    browser_.reset();
321    profile_.reset();
322
323    // Run the message loop to ensure we delete allTasks and fully shut down.
324    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
325    base::MessageLoopForUI::ScopedNestableTaskAllower allow_nested(loop);
326    base::RunLoop run_loop;
327    loop->PostTask(FROM_HERE, run_loop.QuitClosure());
328    run_loop.Run();
329
330    ViewEventTestBase::TearDown();
331    BookmarkBarView::DisableAnimationsForTesting(false);
332
333    browser_content_client_.reset();
334    content_client_.reset();
335    content::SetContentClient(NULL);
336  }
337
338 protected:
339  virtual views::View* CreateContentsView() OVERRIDE {
340    return bb_view_.get();
341  }
342
343  virtual gfx::Size GetPreferredSize() const OVERRIDE { return bb_view_pref_; }
344
345  views::LabelButton* GetBookmarkButton(int view_index) {
346    return bb_view_->GetBookmarkButton(view_index);
347  }
348
349  // See comment above class description for what this does.
350  virtual bool CreateBigMenu() { return false; }
351
352  BookmarkModel* model_;
353  scoped_ptr<BookmarkBarView> bb_view_;
354  TestingPageNavigator navigator_;
355
356 private:
357  void AddTestData(bool big_menu) {
358    const BookmarkNode* bb_node = model_->bookmark_bar_node();
359    std::string test_base = "file:///c:/tmp/";
360    const BookmarkNode* f1 = model_->AddFolder(bb_node, 0, ASCIIToUTF16("F1"));
361    model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
362    const BookmarkNode* f11 = model_->AddFolder(f1, 1, ASCIIToUTF16("F11"));
363    model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
364    if (big_menu) {
365      for (int i = 1; i <= 100; ++i) {
366        model_->AddURL(f1, i + 1, ASCIIToUTF16("f") + base::IntToString16(i),
367                       GURL(test_base + "f" + base::IntToString(i)));
368      }
369    }
370    model_->AddURL(bb_node, 1, ASCIIToUTF16("a"), GURL(test_base + "a"));
371    model_->AddURL(bb_node, 2, ASCIIToUTF16("b"), GURL(test_base + "b"));
372    model_->AddURL(bb_node, 3, ASCIIToUTF16("c"), GURL(test_base + "c"));
373    model_->AddURL(bb_node, 4, ASCIIToUTF16("d"), GURL(test_base + "d"));
374    model_->AddFolder(bb_node, 5, ASCIIToUTF16("F2"));
375    model_->AddURL(bb_node, 6, ASCIIToUTF16("d"), GURL(test_base + "d"));
376
377    model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("oa"),
378                   GURL(test_base + "oa"));
379    const BookmarkNode* of = model_->AddFolder(model_->other_node(), 1,
380                                               ASCIIToUTF16("OF"));
381    model_->AddURL(of, 0, ASCIIToUTF16("ofa"), GURL(test_base + "ofa"));
382    model_->AddURL(of, 1, ASCIIToUTF16("ofb"), GURL(test_base + "ofb"));
383    const BookmarkNode* of2 = model_->AddFolder(model_->other_node(), 2,
384                                                ASCIIToUTF16("OF2"));
385    model_->AddURL(of2, 0, ASCIIToUTF16("of2a"), GURL(test_base + "of2a"));
386    model_->AddURL(of2, 1, ASCIIToUTF16("of2b"), GURL(test_base + "of2b"));
387  }
388
389  gfx::Size bb_view_pref_;
390  scoped_ptr<ChromeContentClient> content_client_;
391  scoped_ptr<chrome::ChromeContentBrowserClient> browser_content_client_;
392  scoped_ptr<TestingProfile> profile_;
393  scoped_ptr<Browser> browser_;
394  scoped_ptr<ScopedTestingLocalState> local_state_;
395};
396
397// Clicks on first menu, makes sure button is depressed. Moves mouse to first
398// child, clicks it and makes sure a navigation occurs.
399class BookmarkBarViewTest1 : public BookmarkBarViewEventTestBase {
400 protected:
401  virtual void DoTestOnMessageLoop() OVERRIDE {
402    // Move the mouse to the first folder on the bookmark bar and press the
403    // mouse.
404    views::LabelButton* button = GetBookmarkButton(0);
405    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
406        ui_controls::DOWN | ui_controls::UP,
407        CreateEventTask(this, &BookmarkBarViewTest1::Step2));
408  }
409
410 private:
411  void Step2() {
412    // Menu should be showing.
413    views::MenuItemView* menu = bb_view_->GetMenu();
414    ASSERT_TRUE(menu != NULL);
415    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
416
417    // Button should be depressed.
418    views::LabelButton* button = GetBookmarkButton(0);
419    ASSERT_TRUE(button->state() == views::CustomButton::STATE_PRESSED);
420
421    // Click on the 2nd menu item (A URL).
422    ASSERT_TRUE(menu->GetSubmenu());
423
424    views::MenuItemView* menu_to_select =
425        menu->GetSubmenu()->GetMenuItemAt(0);
426    ui_test_utils::MoveMouseToCenterAndPress(menu_to_select, ui_controls::LEFT,
427        ui_controls::DOWN | ui_controls::UP,
428        CreateEventTask(this, &BookmarkBarViewTest1::Step3));
429  }
430
431  void Step3() {
432    // We should have navigated to URL f1a.
433    ASSERT_TRUE(navigator_.url_ ==
434                model_->bookmark_bar_node()->GetChild(0)->GetChild(0)->url());
435
436    // Make sure button is no longer pushed.
437    views::LabelButton* button = GetBookmarkButton(0);
438    ASSERT_TRUE(button->state() == views::CustomButton::STATE_NORMAL);
439
440    views::MenuItemView* menu = bb_view_->GetMenu();
441    ASSERT_TRUE(menu == NULL || !menu->GetSubmenu()->IsShowing());
442
443    Done();
444  }
445};
446
447VIEW_TEST(BookmarkBarViewTest1, Basic)
448
449// Brings up menu, clicks on empty space and make sure menu hides.
450class BookmarkBarViewTest2 : public BookmarkBarViewEventTestBase {
451 protected:
452  virtual void DoTestOnMessageLoop() OVERRIDE {
453    // Move the mouse to the first folder on the bookmark bar and press the
454    // mouse.
455    views::LabelButton* button = GetBookmarkButton(0);
456    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
457        ui_controls::DOWN | ui_controls::UP,
458        CreateEventTask(this, &BookmarkBarViewTest2::Step2));
459  }
460
461 private:
462  void Step2() {
463    // Menu should be showing.
464    views::MenuItemView* menu = bb_view_->GetMenu();
465    ASSERT_TRUE(menu != NULL && menu->GetSubmenu()->IsShowing());
466
467    // Click on 0x0, which should trigger closing menu.
468    // NOTE: this code assume there is a left margin, which is currently
469    // true. If that changes, this code will need to find another empty space
470    // to press the mouse on.
471    gfx::Point mouse_loc;
472    views::View::ConvertPointToScreen(bb_view_.get(), &mouse_loc);
473    ui_controls::SendMouseMoveNotifyWhenDone(0, 0,
474        CreateEventTask(this, &BookmarkBarViewTest2::Step3));
475  }
476
477  void Step3() {
478    // As the click is on the desktop the hook never sees the up, so we only
479    // wait on the down. We still send the up though else the system thinks
480    // the mouse is still down.
481    ui_controls::SendMouseEventsNotifyWhenDone(
482        ui_controls::LEFT, ui_controls::DOWN,
483        CreateEventTask(this, &BookmarkBarViewTest2::Step4));
484    ui_controls::SendMouseEvents(ui_controls::LEFT, ui_controls::UP);
485  }
486
487  void Step4() {
488    // The menu shouldn't be showing.
489    views::MenuItemView* menu = bb_view_->GetMenu();
490    ASSERT_TRUE(menu == NULL || !menu->GetSubmenu()->IsShowing());
491
492    // Make sure button is no longer pushed.
493    views::LabelButton* button = GetBookmarkButton(0);
494    ASSERT_TRUE(button->state() == views::CustomButton::STATE_NORMAL);
495
496    Done();
497  }
498};
499
500#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
501// TODO(erg): linux_aura bringup: http://crbug.com/163931
502#define MAYBE_HideOnDesktopClick DISABLED_HideOnDesktopClick
503#else
504#define MAYBE_HideOnDesktopClick HideOnDesktopClick
505#endif
506
507VIEW_TEST(BookmarkBarViewTest2, MAYBE_HideOnDesktopClick)
508
509// Brings up menu. Moves over child to make sure submenu appears, moves over
510// another child and make sure next menu appears.
511class BookmarkBarViewTest3 : public BookmarkBarViewEventTestBase {
512 protected:
513  virtual void DoTestOnMessageLoop() OVERRIDE {
514    // Move the mouse to the first folder on the bookmark bar and press the
515    // mouse.
516    views::MenuButton* button = bb_view_->other_bookmarked_button();
517    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
518        ui_controls::DOWN | ui_controls::UP,
519        CreateEventTask(this, &BookmarkBarViewTest3::Step2));
520  }
521
522 private:
523  void Step2() {
524    // Menu should be showing.
525    views::MenuItemView* menu = bb_view_->GetMenu();
526    ASSERT_TRUE(menu != NULL);
527    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
528
529    views::MenuItemView* child_menu =
530        menu->GetSubmenu()->GetMenuItemAt(1);
531    ASSERT_TRUE(child_menu != NULL);
532
533    // Click on second child, which has a submenu.
534    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
535        ui_controls::DOWN | ui_controls::UP,
536        CreateEventTask(this, &BookmarkBarViewTest3::Step3));
537  }
538
539  void Step3() {
540    // Make sure sub menu is showing.
541    views::MenuItemView* menu = bb_view_->GetMenu();
542    ASSERT_TRUE(menu);
543    views::MenuItemView* child_menu =
544        menu->GetSubmenu()->GetMenuItemAt(1);
545    ASSERT_TRUE(child_menu->GetSubmenu() != NULL);
546    ASSERT_TRUE(child_menu->GetSubmenu()->IsShowing());
547
548    // Click on third child, which has a submenu too.
549    child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
550    ASSERT_TRUE(child_menu != NULL);
551    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
552        ui_controls::DOWN | ui_controls::UP,
553        CreateEventTask(this, &BookmarkBarViewTest3::Step4));
554  }
555
556  void Step4() {
557    // Make sure sub menu we first clicked isn't showing.
558    views::MenuItemView* menu = bb_view_->GetMenu();
559    views::MenuItemView* child_menu =
560        menu->GetSubmenu()->GetMenuItemAt(1);
561    ASSERT_TRUE(child_menu->GetSubmenu() != NULL);
562    ASSERT_FALSE(child_menu->GetSubmenu()->IsShowing());
563
564    // And submenu we last clicked is showing.
565    child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
566    ASSERT_TRUE(child_menu != NULL);
567    ASSERT_TRUE(child_menu->GetSubmenu()->IsShowing());
568
569    // Nothing should have been selected.
570    EXPECT_EQ(GURL(), navigator_.url_);
571
572    // Hide menu.
573    menu->GetMenuController()->CancelAll();
574
575    Done();
576  }
577};
578
579VIEW_TEST(BookmarkBarViewTest3, Submenus)
580
581// Observer that posts task upon the context menu creation.
582// This is necessary for Linux as the context menu has to check
583// the clipboard, which invokes the event loop.
584class BookmarkContextMenuNotificationObserver
585    : public content::NotificationObserver {
586 public:
587  explicit BookmarkContextMenuNotificationObserver(const base::Closure& task)
588      : task_(task) {
589    registrar_.Add(this,
590                   chrome::NOTIFICATION_BOOKMARK_CONTEXT_MENU_SHOWN,
591                   content::NotificationService::AllSources());
592  }
593
594  virtual void Observe(int type,
595                       const content::NotificationSource& source,
596                       const content::NotificationDetails& details) OVERRIDE {
597    base::MessageLoop::current()->PostTask(FROM_HERE, task_);
598  }
599
600  // Sets the task that is posted when the context menu is shown.
601  void set_task(const base::Closure& task) { task_ = task; }
602
603 private:
604  content::NotificationRegistrar registrar_;
605  base::Closure task_;
606
607  DISALLOW_COPY_AND_ASSIGN(BookmarkContextMenuNotificationObserver);
608};
609
610// Tests context menus by way of opening a context menu for a bookmark,
611// then right clicking to get context menu and selecting the first menu item
612// (open).
613class BookmarkBarViewTest4 : public BookmarkBarViewEventTestBase {
614 public:
615  BookmarkBarViewTest4()
616      : observer_(CreateEventTask(this, &BookmarkBarViewTest4::Step3)) {
617  }
618
619 protected:
620  virtual void DoTestOnMessageLoop() OVERRIDE {
621    // Move the mouse to the first folder on the bookmark bar and press the
622    // mouse.
623    views::LabelButton* button = bb_view_->other_bookmarked_button();
624    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
625        ui_controls::DOWN | ui_controls::UP,
626        CreateEventTask(this, &BookmarkBarViewTest4::Step2));
627  }
628
629 private:
630  void Step2() {
631    // Menu should be showing.
632    views::MenuItemView* menu = bb_view_->GetMenu();
633    ASSERT_TRUE(menu != NULL);
634    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
635
636    views::MenuItemView* child_menu =
637        menu->GetSubmenu()->GetMenuItemAt(0);
638    ASSERT_TRUE(child_menu != NULL);
639
640    // Right click on the first child to get its context menu.
641    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
642        ui_controls::DOWN | ui_controls::UP, base::Closure());
643    // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
644  }
645
646  void Step3() {
647    // Make sure the context menu is showing.
648    views::MenuItemView* menu = bb_view_->GetContextMenu();
649    ASSERT_TRUE(menu != NULL);
650    ASSERT_TRUE(menu->GetSubmenu());
651    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
652
653    // Select the first menu item (open).
654    ui_test_utils::MoveMouseToCenterAndPress(
655        menu->GetSubmenu()->GetMenuItemAt(0),
656        ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
657        CreateEventTask(this, &BookmarkBarViewTest4::Step4));
658  }
659
660  void Step4() {
661    EXPECT_EQ(navigator_.url_, model_->other_node()->GetChild(0)->url());
662    Done();
663  }
664
665  BookmarkContextMenuNotificationObserver observer_;
666};
667
668VIEW_TEST(BookmarkBarViewTest4, ContextMenus)
669
670// Tests drag and drop within the same menu.
671class BookmarkBarViewTest5 : public BookmarkBarViewEventTestBase {
672 protected:
673  virtual void DoTestOnMessageLoop() OVERRIDE {
674    url_dragging_ =
675        model_->bookmark_bar_node()->GetChild(0)->GetChild(0)->url();
676
677    // Move the mouse to the first folder on the bookmark bar and press the
678    // mouse.
679    views::LabelButton* button = GetBookmarkButton(0);
680    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
681        ui_controls::DOWN | ui_controls::UP,
682        CreateEventTask(this, &BookmarkBarViewTest5::Step2));
683  }
684
685 private:
686  void Step2() {
687    // Menu should be showing.
688    views::MenuItemView* menu = bb_view_->GetMenu();
689    ASSERT_TRUE(menu != NULL);
690    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
691
692    views::MenuItemView* child_menu =
693        menu->GetSubmenu()->GetMenuItemAt(0);
694    ASSERT_TRUE(child_menu != NULL);
695
696    // Move mouse to center of menu and press button.
697    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
698        ui_controls::DOWN,
699        CreateEventTask(this, &BookmarkBarViewTest5::Step3));
700  }
701
702  void Step3() {
703    views::MenuItemView* target_menu =
704        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
705    gfx::Point loc(1, target_menu->height() - 1);
706    views::View::ConvertPointToScreen(target_menu, &loc);
707
708    // Start a drag.
709    ui_controls::SendMouseMoveNotifyWhenDone(loc.x() + 10, loc.y(),
710        CreateEventTask(this, &BookmarkBarViewTest5::Step4));
711
712    // See comment above this method as to why we do this.
713    ScheduleMouseMoveInBackground(loc.x(), loc.y());
714  }
715
716  void Step4() {
717    // Drop the item so that it's now the second item.
718    views::MenuItemView* target_menu =
719        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
720    gfx::Point loc(1, target_menu->height() - 2);
721    views::View::ConvertPointToScreen(target_menu, &loc);
722    ui_controls::SendMouseMove(loc.x(), loc.y());
723
724    ui_controls::SendMouseEventsNotifyWhenDone(ui_controls::LEFT,
725        ui_controls::UP,
726        CreateEventTask(this, &BookmarkBarViewTest5::Step5));
727  }
728
729  void Step5() {
730    GURL url = model_->bookmark_bar_node()->GetChild(0)->GetChild(1)->url();
731    EXPECT_EQ(url_dragging_, url);
732    Done();
733  }
734
735  GURL url_dragging_;
736};
737
738VIEW_TEST(BookmarkBarViewTest5, MAYBE(DND))
739
740// Tests holding mouse down on overflow button, dragging such that menu pops up
741// then selecting an item.
742class BookmarkBarViewTest6 : public BookmarkBarViewEventTestBase {
743 protected:
744  virtual void DoTestOnMessageLoop() OVERRIDE {
745    // Press the mouse button on the overflow button. Don't release it though.
746    views::LabelButton* button = bb_view_->overflow_button();
747    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
748        ui_controls::DOWN, CreateEventTask(this, &BookmarkBarViewTest6::Step2));
749  }
750
751 private:
752  void Step2() {
753    // Menu should be showing.
754    views::MenuItemView* menu = bb_view_->GetMenu();
755    ASSERT_TRUE(menu != NULL);
756    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
757
758    views::MenuItemView* child_menu =
759        menu->GetSubmenu()->GetMenuItemAt(0);
760    ASSERT_TRUE(child_menu != NULL);
761
762    // Move mouse to center of menu and release mouse.
763    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
764        ui_controls::UP, CreateEventTask(this, &BookmarkBarViewTest6::Step3));
765  }
766
767  void Step3() {
768    ASSERT_TRUE(navigator_.url_ ==
769                model_->bookmark_bar_node()->GetChild(6)->url());
770    Done();
771  }
772
773  GURL url_dragging_;
774};
775
776VIEW_TEST(BookmarkBarViewTest6, OpenMenuOnClickAndHold)
777
778// Tests drag and drop to different menu.
779class BookmarkBarViewTest7 : public BookmarkBarViewEventTestBase {
780 protected:
781  virtual void DoTestOnMessageLoop() OVERRIDE {
782    url_dragging_ =
783        model_->bookmark_bar_node()->GetChild(0)->GetChild(0)->url();
784
785    // Move the mouse to the first folder on the bookmark bar and press the
786    // mouse.
787    views::LabelButton* button = GetBookmarkButton(0);
788    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
789        ui_controls::DOWN | ui_controls::UP,
790        CreateEventTask(this, &BookmarkBarViewTest7::Step2));
791  }
792
793 private:
794  void Step2() {
795    // Menu should be showing.
796    views::MenuItemView* menu = bb_view_->GetMenu();
797    ASSERT_TRUE(menu != NULL);
798    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
799
800    views::MenuItemView* child_menu =
801        menu->GetSubmenu()->GetMenuItemAt(0);
802    ASSERT_TRUE(child_menu != NULL);
803
804    // Move mouse to center of menu and press button.
805    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
806        ui_controls::DOWN,
807        CreateEventTask(this, &BookmarkBarViewTest7::Step3));
808  }
809
810  void Step3() {
811    // Drag over other button.
812    views::LabelButton* other_button =
813        bb_view_->other_bookmarked_button();
814    gfx::Point loc(other_button->width() / 2, other_button->height() / 2);
815    views::View::ConvertPointToScreen(other_button, &loc);
816
817#if defined(USE_AURA)
818    // TODO: fix this. Aura requires an additional mouse event to trigger drag
819    // and drop checking state.
820    ui_controls::SendMouseMoveNotifyWhenDone(loc.x() + 10, loc.y(),
821        base::Bind(&BookmarkBarViewTest7::Step3A, this));
822#else
823    // Start a drag.
824    ui_controls::SendMouseMoveNotifyWhenDone(loc.x() + 10, loc.y(),
825        base::Bind(&BookmarkBarViewTest7::Step4, this));
826
827    // See comment above this method as to why we do this.
828    ScheduleMouseMoveInBackground(loc.x(), loc.y());
829#endif
830  }
831
832  void Step3A() {
833    // Drag over other button.
834    views::LabelButton* other_button =
835        bb_view_->other_bookmarked_button();
836    gfx::Point loc(other_button->width() / 2, other_button->height() / 2);
837    views::View::ConvertPointToScreen(other_button, &loc);
838
839    ui_controls::SendMouseMoveNotifyWhenDone(loc.x(), loc.y(),
840        base::Bind(&BookmarkBarViewTest7::Step4, this));
841  }
842
843  void Step4() {
844    views::MenuItemView* drop_menu = bb_view_->GetDropMenu();
845    ASSERT_TRUE(drop_menu != NULL);
846    ASSERT_TRUE(drop_menu->GetSubmenu()->IsShowing());
847
848    views::MenuItemView* target_menu =
849        drop_menu->GetSubmenu()->GetMenuItemAt(0);
850    gfx::Point loc(1, 1);
851    views::View::ConvertPointToScreen(target_menu, &loc);
852    ui_controls::SendMouseMoveNotifyWhenDone(loc.x(), loc.y(),
853        CreateEventTask(this, &BookmarkBarViewTest7::Step5));
854  }
855
856  void Step5() {
857    ui_controls::SendMouseEventsNotifyWhenDone(
858        ui_controls::LEFT, ui_controls::UP,
859        CreateEventTask(this, &BookmarkBarViewTest7::Step6));
860  }
861
862  void Step6() {
863    ASSERT_TRUE(model_->other_node()->GetChild(0)->url() == url_dragging_);
864    Done();
865  }
866
867  GURL url_dragging_;
868};
869
870#if !defined(OS_WIN)
871// This test passes locally (on aero and non-aero) but fails on the trybots and
872// buildbot.
873// http://crbug.com/154081
874VIEW_TEST(BookmarkBarViewTest7, MAYBE(DNDToDifferentMenu))
875#endif
876
877// Drags from one menu to next so that original menu closes, then back to
878// original menu.
879class BookmarkBarViewTest8 : public BookmarkBarViewEventTestBase {
880 protected:
881  virtual void DoTestOnMessageLoop() OVERRIDE {
882    url_dragging_ =
883        model_->bookmark_bar_node()->GetChild(0)->GetChild(0)->url();
884
885    // Move the mouse to the first folder on the bookmark bar and press the
886    // mouse.
887    views::LabelButton* button = GetBookmarkButton(0);
888    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
889        ui_controls::DOWN | ui_controls::UP,
890        CreateEventTask(this, &BookmarkBarViewTest8::Step2));
891  }
892
893 private:
894  void Step2() {
895    // Menu should be showing.
896    views::MenuItemView* menu = bb_view_->GetMenu();
897    ASSERT_TRUE(menu != NULL);
898    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
899
900    views::MenuItemView* child_menu =
901        menu->GetSubmenu()->GetMenuItemAt(0);
902    ASSERT_TRUE(child_menu != NULL);
903
904    // Move mouse to center of menu and press button.
905    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
906        ui_controls::DOWN,
907        CreateEventTask(this, &BookmarkBarViewTest8::Step3));
908  }
909
910  void Step3() {
911    // Drag over other button.
912    views::LabelButton* other_button =
913        bb_view_->other_bookmarked_button();
914    gfx::Point loc(other_button->width() / 2, other_button->height() / 2);
915    views::View::ConvertPointToScreen(other_button, &loc);
916
917    // Start a drag.
918#if defined(USE_AURA)
919    // TODO: fix this. Aura requires an additional mouse event to trigger drag
920    // and drop checking state.
921    ui_controls::SendMouseMoveNotifyWhenDone(loc.x() + 10, loc.y(),
922        base::Bind(&BookmarkBarViewTest8::Step3A, this));
923#else
924    ui_controls::SendMouseMoveNotifyWhenDone(loc.x() + 10, loc.y(),
925        base::Bind(&BookmarkBarViewTest8::Step4, this));
926    // See comment above this method as to why we do this.
927    ScheduleMouseMoveInBackground(loc.x(), loc.y());
928#endif
929  }
930
931  void Step3A() {
932    // Drag over other button.
933    views::LabelButton* other_button =
934        bb_view_->other_bookmarked_button();
935    gfx::Point loc(other_button->width() / 2, other_button->height() / 2);
936    views::View::ConvertPointToScreen(other_button, &loc);
937
938    ui_controls::SendMouseMoveNotifyWhenDone(loc.x() + 10, loc.y(),
939        base::Bind(&BookmarkBarViewTest8::Step4, this));
940  }
941
942  void Step4() {
943    views::MenuItemView* drop_menu = bb_view_->GetDropMenu();
944    ASSERT_TRUE(drop_menu != NULL);
945    ASSERT_TRUE(drop_menu->GetSubmenu()->IsShowing());
946
947    // Now drag back over first menu.
948    views::LabelButton* button = GetBookmarkButton(0);
949    gfx::Point loc(button->width() / 2, button->height() / 2);
950    views::View::ConvertPointToScreen(button, &loc);
951    ui_controls::SendMouseMoveNotifyWhenDone(loc.x(), loc.y(),
952        base::Bind(&BookmarkBarViewTest8::Step5, this));
953  }
954
955  void Step5() {
956    // Drop on folder F11.
957    views::MenuItemView* drop_menu = bb_view_->GetDropMenu();
958    ASSERT_TRUE(drop_menu != NULL);
959    ASSERT_TRUE(drop_menu->GetSubmenu()->IsShowing());
960
961    views::MenuItemView* target_menu =
962        drop_menu->GetSubmenu()->GetMenuItemAt(1);
963    ui_test_utils::MoveMouseToCenterAndPress(
964        target_menu, ui_controls::LEFT, ui_controls::UP,
965        CreateEventTask(this, &BookmarkBarViewTest8::Step6));
966  }
967
968  void Step6() {
969    // Make sure drop was processed.
970    GURL final_url = model_->bookmark_bar_node()->GetChild(0)->GetChild(0)->
971        GetChild(1)->url();
972    ASSERT_TRUE(final_url == url_dragging_);
973    Done();
974  }
975
976  GURL url_dragging_;
977};
978
979#if !defined(OS_WIN)
980// This test passes locally (on aero and non-aero) but fails on the trybots and
981// buildbot.
982// http://crbug.com/154081
983VIEW_TEST(BookmarkBarViewTest8, MAYBE(DNDBackToOriginatingMenu))
984#endif
985
986// Moves the mouse over the scroll button and makes sure we get scrolling.
987class BookmarkBarViewTest9 : public BookmarkBarViewEventTestBase {
988 protected:
989  virtual bool CreateBigMenu() OVERRIDE { return true; }
990
991  virtual void DoTestOnMessageLoop() OVERRIDE {
992    // Move the mouse to the first folder on the bookmark bar and press the
993    // mouse.
994    views::LabelButton* button = GetBookmarkButton(0);
995    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
996        ui_controls::DOWN | ui_controls::UP,
997        CreateEventTask(this, &BookmarkBarViewTest9::Step2));
998  }
999
1000 private:
1001  void Step2() {
1002    // Menu should be showing.
1003    views::MenuItemView* menu = bb_view_->GetMenu();
1004    ASSERT_TRUE(menu != NULL);
1005    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1006
1007    first_menu_ = menu->GetSubmenu()->GetMenuItemAt(0);
1008    gfx::Point menu_loc;
1009    views::View::ConvertPointToScreen(first_menu_, &menu_loc);
1010    start_y_ = menu_loc.y();
1011
1012    // Move the mouse over the scroll button.
1013    views::View* scroll_container = menu->GetSubmenu()->parent();
1014    ASSERT_TRUE(scroll_container != NULL);
1015    scroll_container = scroll_container->parent();
1016    ASSERT_TRUE(scroll_container != NULL);
1017    views::View* scroll_down_button = scroll_container->child_at(1);
1018    ASSERT_TRUE(scroll_down_button);
1019    gfx::Point loc(scroll_down_button->width() / 2,
1020                   scroll_down_button->height() / 2);
1021    views::View::ConvertPointToScreen(scroll_down_button, &loc);
1022
1023    // On linux, the sending one location isn't enough.
1024    ui_controls::SendMouseMove(loc.x() - 1 , loc.y() - 1);
1025    ui_controls::SendMouseMoveNotifyWhenDone(
1026        loc.x(), loc.y(), CreateEventTask(this, &BookmarkBarViewTest9::Step3));
1027  }
1028
1029  void Step3() {
1030    base::MessageLoop::current()->PostDelayedTask(
1031        FROM_HERE,
1032        base::Bind(&BookmarkBarViewTest9::Step4, this),
1033        base::TimeDelta::FromMilliseconds(200));
1034  }
1035
1036  void Step4() {
1037    gfx::Point menu_loc;
1038    views::View::ConvertPointToScreen(first_menu_, &menu_loc);
1039    ASSERT_NE(start_y_, menu_loc.y());
1040
1041    // Hide menu.
1042    bb_view_->GetMenu()->GetMenuController()->CancelAll();
1043
1044    // On linux, Cancelling menu will call Quit on the message loop,
1045    // which can interfere with Done. We need to run Done in the
1046    // next execution loop.
1047    base::MessageLoop::current()->PostTask(
1048        FROM_HERE, base::Bind(&ViewEventTestBase::Done, this));
1049  }
1050
1051  int start_y_;
1052  views::MenuItemView* first_menu_;
1053};
1054
1055VIEW_TEST(BookmarkBarViewTest9, ScrollButtonScrolls)
1056
1057// Tests up/down/left/enter key messages.
1058class BookmarkBarViewTest10 : public BookmarkBarViewEventTestBase {
1059 protected:
1060  virtual void DoTestOnMessageLoop() OVERRIDE {
1061    // Move the mouse to the first folder on the bookmark bar and press the
1062    // mouse.
1063    views::LabelButton* button = GetBookmarkButton(0);
1064    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1065        ui_controls::DOWN | ui_controls::UP,
1066        CreateEventTask(this, &BookmarkBarViewTest10::Step2));
1067    base::MessageLoop::current()->RunUntilIdle();
1068  }
1069
1070 private:
1071  void Step2() {
1072    // Menu should be showing.
1073    views::MenuItemView* menu = bb_view_->GetMenu();
1074    ASSERT_TRUE(menu != NULL);
1075    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1076
1077    // Send a down event, which should select the first item.
1078    ui_controls::SendKeyPressNotifyWhenDone(
1079        window_->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
1080        CreateEventTask(this, &BookmarkBarViewTest10::Step3));
1081  }
1082
1083  void Step3() {
1084    // Make sure menu is showing and item is selected.
1085    views::MenuItemView* menu = bb_view_->GetMenu();
1086    ASSERT_TRUE(menu != NULL);
1087    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1088    ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
1089
1090    // Send a key down event, which should select the next item.
1091    ui_controls::SendKeyPressNotifyWhenDone(
1092        window_->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
1093        CreateEventTask(this, &BookmarkBarViewTest10::Step4));
1094  }
1095
1096  void Step4() {
1097    views::MenuItemView* menu = bb_view_->GetMenu();
1098    ASSERT_TRUE(menu != NULL);
1099    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1100    ASSERT_FALSE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
1101    ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(1)->IsSelected());
1102
1103    // Send a right arrow to force the menu to open.
1104    ui_controls::SendKeyPressNotifyWhenDone(
1105        window_->GetNativeWindow(), ui::VKEY_RIGHT, false, false, false, false,
1106        CreateEventTask(this, &BookmarkBarViewTest10::Step5));
1107  }
1108
1109  void Step5() {
1110    // Make sure the submenu is showing.
1111    views::MenuItemView* menu = bb_view_->GetMenu();
1112    ASSERT_TRUE(menu != NULL);
1113    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1114    views::MenuItemView* submenu = menu->GetSubmenu()->GetMenuItemAt(1);
1115    ASSERT_TRUE(submenu->IsSelected());
1116    ASSERT_TRUE(submenu->GetSubmenu());
1117    ASSERT_TRUE(submenu->GetSubmenu()->IsShowing());
1118
1119    // Send a left arrow to close the submenu.
1120    ui_controls::SendKeyPressNotifyWhenDone(
1121        window_->GetNativeWindow(), ui::VKEY_LEFT, false, false, false, false,
1122        CreateEventTask(this, &BookmarkBarViewTest10::Step6));
1123  }
1124
1125  void Step6() {
1126    // Make sure the submenu is showing.
1127    views::MenuItemView* menu = bb_view_->GetMenu();
1128    ASSERT_TRUE(menu != NULL);
1129    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1130    views::MenuItemView* submenu = menu->GetSubmenu()->GetMenuItemAt(1);
1131    ASSERT_TRUE(submenu->IsSelected());
1132    ASSERT_TRUE(!submenu->GetSubmenu() || !submenu->GetSubmenu()->IsShowing());
1133
1134    // Send a down arrow to wrap back to f1a
1135    ui_controls::SendKeyPressNotifyWhenDone(
1136        window_->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
1137        CreateEventTask(this, &BookmarkBarViewTest10::Step7));
1138  }
1139
1140  void Step7() {
1141    // Make sure menu is showing and item is selected.
1142    views::MenuItemView* menu = bb_view_->GetMenu();
1143    ASSERT_TRUE(menu != NULL);
1144    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1145    ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
1146
1147    // Send enter, which should select the item.
1148    ui_controls::SendKeyPressNotifyWhenDone(
1149        window_->GetNativeWindow(), ui::VKEY_RETURN, false, false, false, false,
1150        CreateEventTask(this, &BookmarkBarViewTest10::Step8));
1151  }
1152
1153  void Step8() {
1154    ASSERT_TRUE(
1155        model_->bookmark_bar_node()->GetChild(0)->GetChild(0)->url() ==
1156        navigator_.url_);
1157    Done();
1158  }
1159};
1160
1161VIEW_TEST(BookmarkBarViewTest10, KeyEvents)
1162
1163// Make sure the menu closes with the following sequence: show menu, show
1164// context menu, close context menu (via escape), then click else where. This
1165// effectively verifies we maintain mouse capture after the context menu is
1166// hidden.
1167class BookmarkBarViewTest11 : public BookmarkBarViewEventTestBase {
1168 public:
1169  BookmarkBarViewTest11()
1170      : observer_(CreateEventTask(this, &BookmarkBarViewTest11::Step3)) {
1171  }
1172
1173 protected:
1174  virtual void DoTestOnMessageLoop() OVERRIDE {
1175    // Move the mouse to the first folder on the bookmark bar and press the
1176    // mouse.
1177    views::LabelButton* button = bb_view_->other_bookmarked_button();
1178    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1179        ui_controls::DOWN | ui_controls::UP,
1180        CreateEventTask(this, &BookmarkBarViewTest11::Step2));
1181  }
1182
1183 private:
1184  void Step2() {
1185    // Menu should be showing.
1186    views::MenuItemView* menu = bb_view_->GetMenu();
1187    ASSERT_TRUE(menu != NULL);
1188    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1189
1190    views::MenuItemView* child_menu =
1191        menu->GetSubmenu()->GetMenuItemAt(0);
1192    ASSERT_TRUE(child_menu != NULL);
1193
1194    // Right click on the first child to get its context menu.
1195    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1196        ui_controls::DOWN | ui_controls::UP, base::Closure());
1197    // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
1198  }
1199
1200  void Step3() {
1201    // Send escape so that the context menu hides.
1202    ui_controls::SendKeyPressNotifyWhenDone(
1203        window_->GetNativeWindow(), ui::VKEY_ESCAPE, false, false, false, false,
1204        CreateEventTask(this, &BookmarkBarViewTest11::Step4));
1205  }
1206
1207  void Step4() {
1208    // Make sure the context menu is no longer showing.
1209    views::MenuItemView* menu = bb_view_->GetContextMenu();
1210    ASSERT_TRUE(!menu || !menu->GetSubmenu() ||
1211                !menu->GetSubmenu()->IsShowing());
1212
1213    // But the menu should be showing.
1214    menu = bb_view_->GetMenu();
1215    ASSERT_TRUE(menu && menu->GetSubmenu() && menu->GetSubmenu()->IsShowing());
1216
1217    // Now click on empty space.
1218    gfx::Point mouse_loc;
1219    views::View::ConvertPointToScreen(bb_view_.get(), &mouse_loc);
1220    ui_controls::SendMouseMove(mouse_loc.x(), mouse_loc.y());
1221    ui_controls::SendMouseEventsNotifyWhenDone(
1222        ui_controls::LEFT, ui_controls::UP | ui_controls::DOWN,
1223        CreateEventTask(this, &BookmarkBarViewTest11::Step5));
1224  }
1225
1226  void Step5() {
1227    // Make sure the menu is not showing.
1228    views::MenuItemView* menu = bb_view_->GetMenu();
1229    ASSERT_TRUE(!menu || !menu->GetSubmenu() ||
1230                !menu->GetSubmenu()->IsShowing());
1231    Done();
1232  }
1233
1234  BookmarkContextMenuNotificationObserver observer_;
1235};
1236
1237#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
1238// TODO(erg): linux_aura bringup: http://crbug.com/163931
1239#define MAYBE_CloseMenuAfterClosingContextMenu \
1240  DISABLED_CloseMenuAfterClosingContextMenu
1241#else
1242#define MAYBE_CloseMenuAfterClosingContextMenu CloseMenuAfterClosingContextMenu
1243#endif
1244
1245VIEW_TEST(BookmarkBarViewTest11, MAYBE_CloseMenuAfterClosingContextMenu)
1246
1247// Tests showing a modal dialog from a context menu.
1248class BookmarkBarViewTest12 : public BookmarkBarViewEventTestBase {
1249 protected:
1250  virtual void DoTestOnMessageLoop() OVERRIDE {
1251    // Open up the other folder.
1252    views::LabelButton* button = bb_view_->other_bookmarked_button();
1253    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1254        ui_controls::DOWN | ui_controls::UP,
1255        CreateEventTask(this, &BookmarkBarViewTest12::Step2));
1256    chrome::num_bookmark_urls_before_prompting = 1;
1257  }
1258
1259  virtual ~BookmarkBarViewTest12() {
1260    chrome::num_bookmark_urls_before_prompting = 15;
1261  }
1262
1263 private:
1264  void Step2() {
1265    // Menu should be showing.
1266    views::MenuItemView* menu = bb_view_->GetMenu();
1267    ASSERT_TRUE(menu != NULL);
1268    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1269
1270    views::MenuItemView* child_menu =
1271        menu->GetSubmenu()->GetMenuItemAt(1);
1272    ASSERT_TRUE(child_menu != NULL);
1273
1274    // Right click on the second child (a folder) to get its context menu.
1275    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1276        ui_controls::DOWN | ui_controls::UP,
1277        CreateEventTask(this, &BookmarkBarViewTest12::Step3));
1278  }
1279
1280  void Step3() {
1281    // Make sure the context menu is showing.
1282    views::MenuItemView* menu = bb_view_->GetContextMenu();
1283    ASSERT_TRUE(menu && menu->GetSubmenu() && menu->GetSubmenu()->IsShowing());
1284
1285    // Select the first item in the context menu (open all).
1286    views::MenuItemView* child_menu =
1287        menu->GetSubmenu()->GetMenuItemAt(0);
1288    ASSERT_TRUE(child_menu != NULL);
1289
1290    // Click and wait until the dialog box appears.
1291    scoped_ptr<DialogWaiter> dialog_waiter(new DialogWaiter());
1292    ui_test_utils::MoveMouseToCenterAndPress(
1293        child_menu,
1294        ui_controls::LEFT,
1295        ui_controls::DOWN | ui_controls::UP,
1296        base::Bind(
1297            &BookmarkBarViewTest12::Step4, this, base::Passed(&dialog_waiter)));
1298  }
1299
1300  void Step4(scoped_ptr<DialogWaiter> waiter) {
1301    views::Widget* dialog = waiter->WaitForDialog();
1302    waiter.reset();
1303
1304    // Press tab to give focus to the cancel button. Wait until the widget
1305    // receives the tab key.
1306    TabKeyWaiter tab_waiter(dialog);
1307    ui_controls::SendKeyPress(
1308        window_->GetNativeWindow(), ui::VKEY_TAB, false, false, false, false);
1309    tab_waiter.WaitForTab();
1310
1311    // For some reason return isn't processed correctly unless we delay.
1312    base::MessageLoop::current()->PostDelayedTask(
1313        FROM_HERE,
1314        base::Bind(
1315            &BookmarkBarViewTest12::Step5, this, base::Unretained(dialog)),
1316        base::TimeDelta::FromSeconds(1));
1317  }
1318
1319  void Step5(views::Widget* dialog) {
1320    DialogCloseWaiter waiter(dialog);
1321    // And press enter so that the cancel button is selected.
1322    ui_controls::SendKeyPressNotifyWhenDone(window_->GetNativeWindow(),
1323                                            ui::VKEY_RETURN,
1324                                            false,
1325                                            false,
1326                                            false,
1327                                            false,
1328                                            base::Closure());
1329    waiter.WaitForDialogClose();
1330    Done();
1331  }
1332};
1333
1334#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
1335// TODO(erg): linux_aura bringup: http://crbug.com/163931
1336#define MAYBE_CloseWithModalDialog DISABLED_CloseWithModalDialog
1337#else
1338#define MAYBE_CloseWithModalDialog CloseWithModalDialog
1339#endif
1340
1341VIEW_TEST(BookmarkBarViewTest12, MAYBE_CloseWithModalDialog)
1342
1343// Tests clicking on the separator of a context menu (this is for coverage of
1344// bug 17862).
1345class BookmarkBarViewTest13 : public BookmarkBarViewEventTestBase {
1346 public:
1347  BookmarkBarViewTest13()
1348      : observer_(CreateEventTask(this, &BookmarkBarViewTest13::Step3)) {
1349  }
1350
1351 protected:
1352  virtual void DoTestOnMessageLoop() OVERRIDE {
1353    // Move the mouse to the first folder on the bookmark bar and press the
1354    // mouse.
1355    views::LabelButton* button = bb_view_->other_bookmarked_button();
1356    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1357        ui_controls::DOWN | ui_controls::UP,
1358        CreateEventTask(this, &BookmarkBarViewTest13::Step2));
1359  }
1360
1361 private:
1362  void Step2() {
1363    // Menu should be showing.
1364    views::MenuItemView* menu = bb_view_->GetMenu();
1365    ASSERT_TRUE(menu != NULL);
1366    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1367
1368    views::MenuItemView* child_menu =
1369        menu->GetSubmenu()->GetMenuItemAt(0);
1370    ASSERT_TRUE(child_menu != NULL);
1371
1372    // Right click on the first child to get its context menu.
1373    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1374        ui_controls::DOWN | ui_controls::UP, base::Closure());
1375    // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
1376  }
1377
1378  void Step3() {
1379    // Make sure the context menu is showing.
1380    views::MenuItemView* menu = bb_view_->GetContextMenu();
1381    ASSERT_TRUE(menu != NULL);
1382    ASSERT_TRUE(menu->GetSubmenu());
1383    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1384
1385    // Find the first separator.
1386    views::SubmenuView* submenu = menu->GetSubmenu();
1387    views::View* separator_view = NULL;
1388    for (int i = 0; i < submenu->child_count(); ++i) {
1389      if (submenu->child_at(i)->id() != views::MenuItemView::kMenuItemViewID) {
1390        separator_view = submenu->child_at(i);
1391        break;
1392      }
1393    }
1394    ASSERT_TRUE(separator_view);
1395
1396    // Click on the separator. Clicking on the separator shouldn't visually
1397    // change anything.
1398    ui_test_utils::MoveMouseToCenterAndPress(separator_view,
1399        ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1400        CreateEventTask(this, &BookmarkBarViewTest13::Step4));
1401  }
1402
1403  void Step4() {
1404    // The context menu should still be showing.
1405    views::MenuItemView* menu = bb_view_->GetContextMenu();
1406    ASSERT_TRUE(menu != NULL);
1407    ASSERT_TRUE(menu->GetSubmenu());
1408    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1409
1410    // Select the first context menu item.
1411    ui_test_utils::MoveMouseToCenterAndPress(
1412        menu->GetSubmenu()->GetMenuItemAt(0),
1413        ui_controls::LEFT,
1414        ui_controls::DOWN | ui_controls::UP,
1415        CreateEventTask(this, &BookmarkBarViewTest13::Step5));
1416  }
1417
1418  void Step5() {
1419    Done();
1420  }
1421
1422  BookmarkContextMenuNotificationObserver observer_;
1423};
1424
1425VIEW_TEST(BookmarkBarViewTest13, ClickOnContextMenuSeparator)
1426
1427// Makes sure right clicking on a folder on the bookmark bar doesn't result in
1428// both a context menu and showing the menu.
1429class BookmarkBarViewTest14 : public BookmarkBarViewEventTestBase {
1430 public:
1431  BookmarkBarViewTest14()
1432      : observer_(CreateEventTask(this, &BookmarkBarViewTest14::Step2)) {
1433  }
1434
1435 protected:
1436  virtual void DoTestOnMessageLoop() OVERRIDE {
1437    // Move the mouse to the first folder on the bookmark bar and press the
1438    // right mouse button.
1439    views::LabelButton* button = GetBookmarkButton(0);
1440    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::RIGHT,
1441        ui_controls::DOWN | ui_controls::UP, base::Closure());
1442    // Step2 will be invoked by BookmarkContextMenuNotificationObserver.
1443  }
1444
1445 private:
1446
1447  void Step2() {
1448    // Menu should NOT be showing.
1449    views::MenuItemView* menu = bb_view_->GetMenu();
1450    ASSERT_TRUE(menu == NULL);
1451
1452    // Send escape so that the context menu hides.
1453    ui_controls::SendKeyPressNotifyWhenDone(
1454        window_->GetNativeWindow(), ui::VKEY_ESCAPE, false, false, false, false,
1455        CreateEventTask(this, &BookmarkBarViewTest14::Step3));
1456  }
1457
1458  void Step3() {
1459    Done();
1460  }
1461
1462  BookmarkContextMenuNotificationObserver observer_;
1463};
1464
1465VIEW_TEST(BookmarkBarViewTest14, ContextMenus2)
1466
1467// Makes sure deleting from the context menu keeps the bookmark menu showing.
1468class BookmarkBarViewTest15 : public BookmarkBarViewEventTestBase {
1469 public:
1470  BookmarkBarViewTest15()
1471      : deleted_menu_id_(0),
1472        observer_(CreateEventTask(this, &BookmarkBarViewTest15::Step3)) {
1473  }
1474
1475 protected:
1476  virtual void DoTestOnMessageLoop() OVERRIDE {
1477    // Show the other bookmarks.
1478    views::LabelButton* button = bb_view_->other_bookmarked_button();
1479    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1480        ui_controls::DOWN | ui_controls::UP,
1481        CreateEventTask(this, &BookmarkBarViewTest15::Step2));
1482  }
1483
1484 private:
1485  void Step2() {
1486    // Menu should be showing.
1487    views::MenuItemView* menu = bb_view_->GetMenu();
1488    ASSERT_TRUE(menu != NULL);
1489    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1490
1491    views::MenuItemView* child_menu =
1492        menu->GetSubmenu()->GetMenuItemAt(1);
1493    ASSERT_TRUE(child_menu != NULL);
1494
1495    deleted_menu_id_ = child_menu->GetCommand();
1496
1497    // Right click on the second child to get its context menu.
1498    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1499        ui_controls::DOWN | ui_controls::UP, base::Closure());
1500    // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
1501  }
1502
1503  void Step3() {
1504    // Make sure the context menu is showing.
1505    views::MenuItemView* menu = bb_view_->GetContextMenu();
1506    ASSERT_TRUE(menu != NULL);
1507    ASSERT_TRUE(menu->GetSubmenu());
1508    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1509
1510    views::MenuItemView* delete_menu =
1511        menu->GetMenuItemByID(IDC_BOOKMARK_BAR_REMOVE);
1512    ASSERT_TRUE(delete_menu);
1513
1514    // Click on the delete button.
1515    ui_test_utils::MoveMouseToCenterAndPress(delete_menu,
1516        ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1517        CreateEventTask(this, &BookmarkBarViewTest15::Step4));
1518  }
1519
1520  void Step4() {
1521    // The context menu should not be showing.
1522    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
1523    ASSERT_TRUE(context_menu == NULL);
1524
1525    // But the menu should be showing.
1526    views::MenuItemView* menu = bb_view_->GetMenu();
1527    ASSERT_TRUE(menu != NULL);
1528    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1529
1530    // And the deleted_menu_id_ should have been removed.
1531    ASSERT_TRUE(menu->GetMenuItemByID(deleted_menu_id_) == NULL);
1532
1533    bb_view_->GetMenu()->GetMenuController()->CancelAll();
1534
1535    Done();
1536  }
1537
1538  int deleted_menu_id_;
1539  BookmarkContextMenuNotificationObserver observer_;
1540};
1541
1542VIEW_TEST(BookmarkBarViewTest15, MenuStaysVisibleAfterDelete)
1543
1544// Tests that we don't crash or get stuck if the parent of a menu is closed.
1545class BookmarkBarViewTest16 : public BookmarkBarViewEventTestBase {
1546 protected:
1547  virtual void DoTestOnMessageLoop() OVERRIDE {
1548    // Move the mouse to the first folder on the bookmark bar and press the
1549    // mouse.
1550    views::LabelButton* button = GetBookmarkButton(0);
1551    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1552        ui_controls::DOWN | ui_controls::UP,
1553        CreateEventTask(this, &BookmarkBarViewTest16::Step2));
1554  }
1555
1556 private:
1557  void Step2() {
1558    // Menu should be showing.
1559    views::MenuItemView* menu = bb_view_->GetMenu();
1560    ASSERT_TRUE(menu != NULL);
1561    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1562
1563    // Button should be depressed.
1564    views::LabelButton* button = GetBookmarkButton(0);
1565    ASSERT_TRUE(button->state() == views::CustomButton::STATE_PRESSED);
1566
1567    // Close the window.
1568    window_->Close();
1569    window_ = NULL;
1570
1571    base::MessageLoop::current()->PostTask(
1572        FROM_HERE, CreateEventTask(this, &BookmarkBarViewTest16::Done));
1573  }
1574};
1575
1576#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1577// TODO(erg): linux_aura bringup: http://crbug.com/163931
1578#define MAYBE_DeleteMenu DISABLED_DeleteMenu
1579#else
1580#define MAYBE_DeleteMenu DeleteMenu
1581#endif
1582
1583VIEW_TEST(BookmarkBarViewTest16, MAYBE_DeleteMenu)
1584
1585// Makes sure right clicking on an item while a context menu is already showing
1586// doesn't crash and works.
1587class BookmarkBarViewTest17 : public BookmarkBarViewEventTestBase {
1588 public:
1589  BookmarkBarViewTest17()
1590      : observer_(CreateEventTask(this, &BookmarkBarViewTest17::Step3)) {
1591  }
1592
1593 protected:
1594  virtual void DoTestOnMessageLoop() OVERRIDE {
1595    // Move the mouse to the other folder on the bookmark bar and press the
1596    // left mouse button.
1597    views::LabelButton* button = bb_view_->other_bookmarked_button();
1598    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1599        ui_controls::DOWN | ui_controls::UP,
1600        CreateEventTask(this, &BookmarkBarViewTest17::Step2));
1601  }
1602
1603 private:
1604  void Step2() {
1605    // Menu should be showing.
1606    views::MenuItemView* menu = bb_view_->GetMenu();
1607    ASSERT_TRUE(menu != NULL);
1608    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1609
1610    // Right click on the second item to show its context menu.
1611    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
1612    ASSERT_TRUE(child_menu != NULL);
1613    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1614        ui_controls::DOWN | ui_controls::UP, base::Closure());
1615    // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
1616  }
1617
1618  void Step3() {
1619    // Make sure the context menu is showing.
1620    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
1621    ASSERT_TRUE(context_menu != NULL);
1622    ASSERT_TRUE(context_menu->GetSubmenu());
1623    ASSERT_TRUE(context_menu->GetSubmenu()->IsShowing());
1624
1625    // Right click on the first menu item to trigger its context menu.
1626    views::MenuItemView* menu = bb_view_->GetMenu();
1627    ASSERT_TRUE(menu != NULL);
1628    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1629    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(1);
1630    ASSERT_TRUE(child_menu != NULL);
1631
1632    // The context menu and child_menu can be overlapped, calculate the
1633    // non-intersected Rect of the child menu and click on its center to make
1634    // sure the click is always on the child menu.
1635    gfx::Rect context_rect = context_menu->GetSubmenu()->GetBoundsInScreen();
1636    gfx::Rect child_menu_rect = child_menu->GetBoundsInScreen();
1637    gfx::Rect clickable_rect =
1638        gfx::SubtractRects(child_menu_rect, context_rect);
1639    ASSERT_FALSE(clickable_rect.IsEmpty());
1640    observer_.set_task(CreateEventTask(this, &BookmarkBarViewTest17::Step4));
1641    MoveMouseAndPress(clickable_rect.CenterPoint(), ui_controls::RIGHT,
1642        ui_controls::DOWN | ui_controls::UP, base::Closure());
1643    // Step4 will be invoked by BookmarkContextMenuNotificationObserver.
1644  }
1645
1646  void Step4() {
1647    // The context menu should still be showing.
1648    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
1649    ASSERT_TRUE(context_menu != NULL);
1650
1651    // And the menu should be showing.
1652    views::MenuItemView* menu = bb_view_->GetMenu();
1653    ASSERT_TRUE(menu != NULL);
1654    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1655
1656    bb_view_->GetMenu()->GetMenuController()->CancelAll();
1657
1658    Done();
1659  }
1660
1661  BookmarkContextMenuNotificationObserver observer_;
1662};
1663
1664#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
1665// TODO(erg): linux_aura bringup: http://crbug.com/163931
1666#define MAYBE_ContextMenus3 DISABLED_ContextMenus3
1667#else
1668#define MAYBE_ContextMenus3 ContextMenus3
1669#endif
1670
1671VIEW_TEST(BookmarkBarViewTest17, MAYBE_ContextMenus3)
1672
1673// Verifies sibling menus works. Clicks on the 'other bookmarks' folder, then
1674// moves the mouse over the first item on the bookmark bar and makes sure the
1675// menu appears.
1676class BookmarkBarViewTest18 : public BookmarkBarViewEventTestBase {
1677 protected:
1678  virtual void DoTestOnMessageLoop() OVERRIDE {
1679    // Move the mouse to the other folder on the bookmark bar and press the
1680    // left mouse button.
1681    views::LabelButton* button = bb_view_->other_bookmarked_button();
1682    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1683        ui_controls::DOWN | ui_controls::UP,
1684        CreateEventTask(this, &BookmarkBarViewTest18::Step2));
1685  }
1686
1687 private:
1688  void Step2() {
1689    // Menu should be showing.
1690    views::MenuItemView* menu = bb_view_->GetMenu();
1691    ASSERT_TRUE(menu != NULL);
1692    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1693
1694    // Move the mouse to the first folder on the bookmark bar
1695    views::LabelButton* button = GetBookmarkButton(0);
1696    gfx::Point button_center(button->width() / 2, button->height() / 2);
1697    views::View::ConvertPointToScreen(button, &button_center);
1698    ui_controls::SendMouseMoveNotifyWhenDone(
1699        button_center.x(), button_center.y(),
1700        CreateEventTask(this, &BookmarkBarViewTest18::Step3));
1701  }
1702
1703  void Step3() {
1704    // Make sure the menu is showing.
1705    views::MenuItemView* menu = bb_view_->GetMenu();
1706    ASSERT_TRUE(menu != NULL);
1707    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1708
1709    // The menu for the first folder should be in the pressed state (since the
1710    // menu is showing for it).
1711    EXPECT_EQ(views::CustomButton::STATE_PRESSED,
1712              GetBookmarkButton(0)->state());
1713
1714    menu->GetMenuController()->CancelAll();
1715
1716    Done();
1717  }
1718};
1719
1720#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1721// TODO(erg): linux_aura bringup: http://crbug.com/163931
1722#define MAYBE_BookmarkBarViewTest18_SiblingMenu \
1723  DISABLED_BookmarkBarViewTest18_SiblingMenu
1724#else
1725#define MAYBE_BookmarkBarViewTest18_SiblingMenu \
1726  BookmarkBarViewTest18_SiblingMenu
1727#endif
1728
1729VIEW_TEST(BookmarkBarViewTest18, MAYBE_BookmarkBarViewTest18_SiblingMenu)
1730
1731// Verifies mousing over an already open sibling menu doesn't prematurely cancel
1732// the menu.
1733class BookmarkBarViewTest19 : public BookmarkBarViewEventTestBase {
1734 protected:
1735  virtual void DoTestOnMessageLoop() OVERRIDE {
1736    // Move the mouse to the other folder on the bookmark bar and press the
1737    // left mouse button.
1738    views::LabelButton* button = bb_view_->other_bookmarked_button();
1739    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1740        ui_controls::DOWN | ui_controls::UP,
1741        CreateEventTask(this, &BookmarkBarViewTest19::Step2));
1742  }
1743
1744 private:
1745  void Step2() {
1746    // Menu should be showing.
1747    views::MenuItemView* menu = bb_view_->GetMenu();
1748    ASSERT_TRUE(menu != NULL);
1749    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1750
1751    // Click on the first folder.
1752    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(1);
1753    ASSERT_TRUE(child_menu != NULL);
1754    ui_test_utils::MoveMouseToCenterAndPress(
1755        child_menu, ui_controls::LEFT,
1756        ui_controls::DOWN | ui_controls::UP,
1757        CreateEventTask(this, &BookmarkBarViewTest19::Step3));
1758  }
1759
1760  void Step3() {
1761    // Make sure the menu is showing.
1762    views::MenuItemView* menu = bb_view_->GetMenu();
1763    ASSERT_TRUE(menu != NULL);
1764    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1765
1766    // Move the mouse back to the other bookmark button.
1767    views::LabelButton* button = bb_view_->other_bookmarked_button();
1768    gfx::Point button_center(button->width() / 2, button->height() / 2);
1769    views::View::ConvertPointToScreen(button, &button_center);
1770    ui_controls::SendMouseMoveNotifyWhenDone(
1771        button_center.x() + 1, button_center.y() + 1,
1772        CreateEventTask(this, &BookmarkBarViewTest19::Step4));
1773  }
1774
1775  void Step4() {
1776    // Menu should be showing.
1777    views::MenuItemView* menu = bb_view_->GetMenu();
1778    ASSERT_TRUE(menu != NULL);
1779    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1780
1781    // Click on the first folder.
1782    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(1);
1783    ASSERT_TRUE(child_menu != NULL);
1784    ui_test_utils::MoveMouseToCenterAndPress(
1785        child_menu,
1786        ui_controls::LEFT,
1787        ui_controls::DOWN | ui_controls::UP,
1788        CreateEventTask(this, &BookmarkBarViewTest19::Step5));
1789  }
1790
1791  void Step5() {
1792    // Make sure the menu is showing.
1793    views::MenuItemView* menu = bb_view_->GetMenu();
1794    ASSERT_TRUE(menu != NULL);
1795    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1796
1797    menu->GetMenuController()->CancelAll();
1798
1799    Done();
1800  }
1801};
1802
1803VIEW_TEST(BookmarkBarViewTest19, BookmarkBarViewTest19_SiblingMenu)
1804
1805// Verify that when clicking a mouse button outside a context menu,
1806// the context menu is dismissed *and* the underlying view receives
1807// the the mouse event (due to event reposting).
1808class BookmarkBarViewTest20 : public BookmarkBarViewEventTestBase {
1809 public:
1810  BookmarkBarViewTest20() : test_view_(new TestViewForMenuExit) {}
1811
1812 protected:
1813  virtual void DoTestOnMessageLoop() OVERRIDE {
1814    // Add |test_view_| next to |bb_view_|.
1815    views::View* parent = bb_view_->parent();
1816    views::View* container_view = new ContainerViewForMenuExit;
1817    container_view->AddChildView(bb_view_.get());
1818    container_view->AddChildView(test_view_);
1819    parent->AddChildView(container_view);
1820    parent->Layout();
1821
1822    ASSERT_EQ(test_view_->press_count(), 0);
1823
1824    // Move the mouse to the Test View and press the left mouse button.
1825    ui_test_utils::MoveMouseToCenterAndPress(
1826        test_view_, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1827        CreateEventTask(this, &BookmarkBarViewTest20::Step1));
1828  }
1829
1830 private:
1831  void Step1() {
1832    ASSERT_EQ(test_view_->press_count(), 1);
1833    ASSERT_TRUE(bb_view_->GetMenu() == NULL);
1834
1835    // Move the mouse to the first folder on the bookmark bar and press the
1836    // left mouse button.
1837    views::LabelButton* button = GetBookmarkButton(0);
1838    ui_test_utils::MoveMouseToCenterAndPress(
1839        button, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1840        CreateEventTask(this, &BookmarkBarViewTest20::Step2));
1841  }
1842
1843  void Step2() {
1844    ASSERT_EQ(test_view_->press_count(), 1);
1845    views::MenuItemView* menu = bb_view_->GetMenu();
1846    ASSERT_TRUE(menu != NULL);
1847    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1848
1849    // Move the mouse to the Test View and press the left mouse button.
1850    // The context menu will consume the event and exit. Thereafter,
1851    // the event is reposted and delivered to the Test View which
1852    // increases its press-count.
1853    ui_test_utils::MoveMouseToCenterAndPress(
1854        test_view_, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1855        CreateEventTask(this, &BookmarkBarViewTest20::Step3));
1856  }
1857
1858  void Step3() {
1859    ASSERT_EQ(test_view_->press_count(), 2);
1860    ASSERT_TRUE(bb_view_->GetMenu() == NULL);
1861    Done();
1862  }
1863
1864  class ContainerViewForMenuExit : public views::View {
1865   public:
1866    ContainerViewForMenuExit() {
1867    }
1868
1869    virtual void Layout() OVERRIDE {
1870      DCHECK_EQ(2, child_count());
1871      views::View* bb_view = child_at(0);
1872      views::View* test_view = child_at(1);
1873      const int width = bb_view->width();
1874      const int height = bb_view->height();
1875      bb_view->SetBounds(0,0, width - 22, height);
1876      test_view->SetBounds(width - 20, 0, 20, height);
1877    }
1878
1879   private:
1880
1881    DISALLOW_COPY_AND_ASSIGN(ContainerViewForMenuExit);
1882  };
1883
1884  class TestViewForMenuExit : public views::View {
1885   public:
1886    TestViewForMenuExit() : press_count_(0) {
1887    }
1888    virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
1889      ++press_count_;
1890      return true;
1891    }
1892    int press_count() const { return press_count_; }
1893
1894   private:
1895    int press_count_;
1896
1897    DISALLOW_COPY_AND_ASSIGN(TestViewForMenuExit);
1898  };
1899
1900  TestViewForMenuExit* test_view_;
1901};
1902
1903#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1904// TODO(erg): linux_aura bringup: http://crbug.com/163931
1905#define MAYBE_ContextMenuExitTest DISABLED_ContextMenuExitTest
1906#else
1907#define MAYBE_ContextMenuExitTest ContextMenuExitTest
1908#endif
1909
1910VIEW_TEST(BookmarkBarViewTest20, MAYBE_ContextMenuExitTest)
1911
1912// Tests context menu by way of opening a context menu for a empty folder menu.
1913// The opened context menu should behave as it is from the folder button.
1914class BookmarkBarViewTest21 : public BookmarkBarViewEventTestBase {
1915 public:
1916  BookmarkBarViewTest21()
1917      : observer_(CreateEventTask(this, &BookmarkBarViewTest21::Step3)) {
1918  }
1919
1920 protected:
1921  // Move the mouse to the empty folder on the bookmark bar and press the
1922  // left mouse button.
1923  virtual void DoTestOnMessageLoop() OVERRIDE {
1924    views::LabelButton* button = GetBookmarkButton(5);
1925    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1926        ui_controls::DOWN | ui_controls::UP,
1927        CreateEventTask(this, &BookmarkBarViewTest21::Step2));
1928  }
1929
1930 private:
1931  // Confirm that a menu for empty folder shows and right click the menu.
1932  void Step2() {
1933    // Menu should be showing.
1934    views::MenuItemView* menu = bb_view_->GetMenu();
1935    ASSERT_TRUE(menu != NULL);
1936
1937    views::SubmenuView* submenu = menu->GetSubmenu();
1938    ASSERT_TRUE(submenu->IsShowing());
1939    ASSERT_EQ(1, submenu->child_count());
1940
1941    views::View* view = submenu->child_at(0);
1942    ASSERT_TRUE(view != NULL);
1943    EXPECT_EQ(views::MenuItemView::kEmptyMenuItemViewID, view->id());
1944
1945    // Right click on the first child to get its context menu.
1946    ui_test_utils::MoveMouseToCenterAndPress(view, ui_controls::RIGHT,
1947        ui_controls::DOWN | ui_controls::UP, base::Closure());
1948    // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
1949  }
1950
1951  // Confirm that context menu shows and click REMOVE menu.
1952  void Step3() {
1953    // Make sure the context menu is showing.
1954    views::MenuItemView* menu = bb_view_->GetContextMenu();
1955    ASSERT_TRUE(menu != NULL);
1956    ASSERT_TRUE(menu->GetSubmenu());
1957    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1958
1959    views::MenuItemView* delete_menu =
1960        menu->GetMenuItemByID(IDC_BOOKMARK_BAR_REMOVE);
1961    ASSERT_TRUE(delete_menu);
1962
1963    // Click on the delete menu item.
1964    ui_test_utils::MoveMouseToCenterAndPress(delete_menu,
1965        ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1966        CreateEventTask(this, &BookmarkBarViewTest21::Step4));
1967  }
1968
1969  // Confirm that the empty folder gets removed and menu doesn't show.
1970  void Step4() {
1971    views::LabelButton* button = GetBookmarkButton(5);
1972    ASSERT_TRUE(button);
1973    EXPECT_EQ(ASCIIToUTF16("d"), button->GetText());
1974    EXPECT_TRUE(bb_view_->GetContextMenu() == NULL);
1975    EXPECT_TRUE(bb_view_->GetMenu() == NULL);
1976
1977    Done();
1978  }
1979
1980  BookmarkContextMenuNotificationObserver observer_;
1981};
1982
1983VIEW_TEST(BookmarkBarViewTest21, ContextMenusForEmptyFolder)
1984