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 "base/string_number_conversions.h"
6#include "base/utf_string_conversions.h"
7#include "chrome/app/chrome_command_ids.h"
8#include "chrome/browser/automation/ui_controls.h"
9#include "chrome/browser/bookmarks/bookmark_model.h"
10#include "chrome/browser/bookmarks/bookmark_utils.h"
11#include "chrome/browser/prefs/pref_service.h"
12#include "chrome/browser/profiles/profile.h"
13#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
14#include "chrome/common/pref_names.h"
15#include "chrome/test/interactive_ui/view_event_test_base.h"
16#include "chrome/test/testing_profile.h"
17#include "chrome/test/ui_test_utils.h"
18#include "content/browser/tab_contents/page_navigator.h"
19#include "content/common/notification_service.h"
20#include "grit/generated_resources.h"
21#include "ui/base/accessibility/accessibility_types.h"
22#include "ui/base/clipboard/clipboard.h"
23#include "ui/base/keycodes/keyboard_codes.h"
24#include "views/controls/button/menu_button.h"
25#include "views/controls/button/text_button.h"
26#include "views/controls/menu/menu_controller.h"
27#include "views/controls/menu/menu_item_view.h"
28#include "views/controls/menu/submenu_view.h"
29#include "views/views_delegate.h"
30#include "views/window/window.h"
31
32#if defined(OS_LINUX)
33// See http://crbug.com/40040 for details.
34#define MAYBE_DND DISABLED_DND
35#define MAYBE_DNDToDifferentMenu DISABLED_DNDToDifferentMenu
36#define MAYBE_DNDBackToOriginatingMenu DISABLED_DNDBackToOriginatingMenu
37
38// See http://crbug.com/40039 for details.
39#define MAYBE_KeyEvents DISABLED_KeyEvents
40
41// Two bugs here. http://crbug.com/47089 for general Linux Views, and
42// http://crbug.com/47452 for ChromiumOS.
43#define MAYBE_CloseWithModalDialog DISABLED_CloseWithModalDialog
44// See http://crbug.com/47089 for details.
45#define MAYBE_CloseMenuAfterClosingContextMenu \
46        DISABLED_CloseMenuAfterClosingContextMenu
47
48// See bug http://crbug.com/60444 for details.
49#define MAYBE_ScrollButtonScrolls DISABLED_ScrollButtonScrolls
50#else
51
52#define MAYBE_DND DND
53#define MAYBE_DNDToDifferentMenu DNDToDifferentMenu
54#define MAYBE_DNDBackToOriginatingMenu DNDBackToOriginatingMenu
55#define MAYBE_DNDBackToOriginatingMenu DNDBackToOriginatingMenu
56#define MAYBE_KeyEvents KeyEvents
57#define MAYBE_CloseWithModalDialog CloseWithModalDialog
58#define MAYBE_CloseMenuAfterClosingContextMenu CloseMenuAfterClosingContextMenu
59#define MAYBE_ScrollButtonScrolls ScrollButtonScrolls
60
61#endif
62
63namespace {
64
65class ViewsDelegateImpl : public views::ViewsDelegate {
66 public:
67  ViewsDelegateImpl() {}
68  virtual ui::Clipboard* GetClipboard() const { return NULL; }
69  virtual void SaveWindowPlacement(views::Window* window,
70                                   const std::wstring& window_name,
71                                   const gfx::Rect& bounds,
72                                   bool maximized) {}
73  virtual bool GetSavedWindowBounds(views::Window* window,
74                                    const std::wstring& window_name,
75                                    gfx::Rect* bounds) const {
76    return false;
77  }
78  virtual bool GetSavedMaximizedState(views::Window* window,
79                                      const std::wstring& window_name,
80                                      bool* maximized) const {
81    return false;
82  }
83
84  virtual void NotifyAccessibilityEvent(
85      views::View* view, ui::AccessibilityTypes::Event event_type) {}
86  virtual void NotifyMenuItemFocused(
87      const std::wstring& menu_name,
88      const std::wstring& menu_item_name,
89      int item_index,
90      int item_count,
91      bool has_submenu) {}
92
93#if defined(OS_WIN)
94  virtual HICON GetDefaultWindowIcon() const { return 0; }
95#endif
96
97  virtual void AddRef() {
98  }
99
100  virtual void ReleaseRef() {
101    MessageLoopForUI::current()->Quit();
102  }
103
104 private:
105  DISALLOW_COPY_AND_ASSIGN(ViewsDelegateImpl);
106};
107
108// PageNavigator implementation that records the URL.
109class TestingPageNavigator : public PageNavigator {
110 public:
111  virtual void OpenURL(const GURL& url, const GURL& referrer,
112                       WindowOpenDisposition disposition,
113                       PageTransition::Type transition) {
114    url_ = url;
115  }
116
117  GURL url_;
118};
119
120}  // namespace
121
122// Base class for event generating bookmark view tests. These test are intended
123// to exercise View's menus, but that's easier done with BookmarkBarView rather
124// than View's menu itself.
125//
126// SetUp creates a bookmark model with the following structure.
127// All folders are in upper case, all URLs in lower case.
128// F1
129//   f1a
130//   F11
131//     f11a
132//   *
133// a
134// b
135// c
136// d
137// OTHER
138//   oa
139//   OF
140//     ofa
141//     ofb
142//   OF2
143//     of2a
144//     of2b
145//
146// * if CreateBigMenu returns return true, 100 menu items are created here with
147//   the names f1-f100.
148//
149// Subclasses should be sure and invoke super's implementation of SetUp and
150// TearDown.
151class BookmarkBarViewEventTestBase : public ViewEventTestBase {
152 public:
153  BookmarkBarViewEventTestBase()
154      : ViewEventTestBase(),
155        model_(NULL),
156        bb_view_(NULL),
157        ui_thread_(BrowserThread::UI, MessageLoop::current()),
158        file_thread_(BrowserThread::FILE, MessageLoop::current()) {
159  }
160
161  virtual void SetUp() {
162    BookmarkBarView::testing_ = true;
163
164    profile_.reset(new TestingProfile());
165    profile_->CreateBookmarkModel(true);
166    profile_->BlockUntilBookmarkModelLoaded();
167    profile_->GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, true);
168
169    model_ = profile_->GetBookmarkModel();
170    model_->ClearStore();
171
172    bb_view_ = new BookmarkBarView(profile_.get(), NULL);
173    bb_view_->SetPageNavigator(&navigator_);
174
175    AddTestData(CreateBigMenu());
176
177    // Calculate the preferred size so that one button doesn't fit, which
178    // triggers the overflow button to appear.
179    //
180    // BookmarkBarView::Layout does nothing if the parent is NULL and
181    // GetPreferredSize hard codes a width of 1. For that reason we add the
182    // BookmarkBarView to a dumby view as the parent.
183    //
184    // This code looks a bit hacky, but I've written it so that it shouldn't
185    // be dependant upon any of the layout code in BookmarkBarView. Instead
186    // we brute force search for a size that triggers the overflow button.
187    views::View tmp_parent;
188
189    tmp_parent.AddChildView(bb_view_);
190
191    bb_view_pref_ = bb_view_->GetPreferredSize();
192    bb_view_pref_.set_width(1000);
193    views::TextButton* button = bb_view_->GetBookmarkButton(4);
194    while (button->IsVisible()) {
195      bb_view_pref_.set_width(bb_view_pref_.width() - 25);
196      bb_view_->SetBounds(0, 0, bb_view_pref_.width(), bb_view_pref_.height());
197      bb_view_->Layout();
198    }
199
200    tmp_parent.RemoveChildView(bb_view_);
201
202    ViewEventTestBase::SetUp();
203  }
204
205  virtual void TearDown() {
206    ViewEventTestBase::TearDown();
207    BookmarkBarView::testing_ = false;
208    views::ViewsDelegate::views_delegate = NULL;
209  }
210
211 protected:
212  void InstallViewsDelegate() {
213    views::ViewsDelegate::views_delegate = &views_delegate_;
214  }
215
216  virtual views::View* CreateContentsView() {
217    return bb_view_;
218  }
219
220  virtual gfx::Size GetPreferredSize() { return bb_view_pref_; }
221
222  // See comment above class description for what this does.
223  virtual bool CreateBigMenu() { return false; }
224
225  BookmarkModel* model_;
226  BookmarkBarView* bb_view_;
227  TestingPageNavigator navigator_;
228
229 private:
230  void AddTestData(bool big_menu) {
231    std::string test_base = "file:///c:/tmp/";
232
233    const BookmarkNode* f1 = model_->AddFolder(
234        model_->GetBookmarkBarNode(), 0, ASCIIToUTF16("F1"));
235    model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
236    const BookmarkNode* f11 = model_->AddFolder(f1, 1, ASCIIToUTF16("F11"));
237    model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
238    if (big_menu) {
239      for (int i = 1; i <= 100; ++i) {
240        model_->AddURL(f1, i + 1, ASCIIToUTF16("f") + base::IntToString16(i),
241                       GURL(test_base + "f" + base::IntToString(i)));
242      }
243    }
244    model_->AddURL(model_->GetBookmarkBarNode(), 1, ASCIIToUTF16("a"),
245                   GURL(test_base + "a"));
246    model_->AddURL(model_->GetBookmarkBarNode(), 2, ASCIIToUTF16("b"),
247                   GURL(test_base + "b"));
248    model_->AddURL(model_->GetBookmarkBarNode(), 3, ASCIIToUTF16("c"),
249                   GURL(test_base + "c"));
250    model_->AddURL(model_->GetBookmarkBarNode(), 4, ASCIIToUTF16("d"),
251                   GURL(test_base + "d"));
252    model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("oa"),
253                   GURL(test_base + "oa"));
254    const BookmarkNode* of = model_->AddFolder(model_->other_node(), 1,
255                                               ASCIIToUTF16("OF"));
256    model_->AddURL(of, 0, ASCIIToUTF16("ofa"), GURL(test_base + "ofa"));
257    model_->AddURL(of, 1, ASCIIToUTF16("ofb"), GURL(test_base + "ofb"));
258    const BookmarkNode* of2 = model_->AddFolder(model_->other_node(), 2,
259                                                ASCIIToUTF16("OF2"));
260    model_->AddURL(of2, 0, ASCIIToUTF16("of2a"), GURL(test_base + "of2a"));
261    model_->AddURL(of2, 1, ASCIIToUTF16("of2b"), GURL(test_base + "of2b"));
262  }
263
264  gfx::Size bb_view_pref_;
265  scoped_ptr<TestingProfile> profile_;
266  BrowserThread ui_thread_;
267  BrowserThread file_thread_;
268  ViewsDelegateImpl views_delegate_;
269};
270
271// Clicks on first menu, makes sure button is depressed. Moves mouse to first
272// child, clicks it and makes sure a navigation occurs.
273class BookmarkBarViewTest1 : public BookmarkBarViewEventTestBase {
274 protected:
275  virtual void DoTestOnMessageLoop() {
276    // Move the mouse to the first folder on the bookmark bar and press the
277    // mouse.
278    views::TextButton* button = bb_view_->GetBookmarkButton(0);
279    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
280        ui_controls::DOWN | ui_controls::UP,
281        CreateEventTask(this, &BookmarkBarViewTest1::Step2));
282  }
283
284 private:
285  void Step2() {
286    // Menu should be showing.
287    views::MenuItemView* menu = bb_view_->GetMenu();
288    ASSERT_TRUE(menu != NULL);
289    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
290
291    // Button should be depressed.
292    views::TextButton* button = bb_view_->GetBookmarkButton(0);
293    ASSERT_TRUE(button->state() == views::CustomButton::BS_PUSHED);
294
295    // Click on the 2nd menu item (A URL).
296    ASSERT_TRUE(menu->GetSubmenu());
297
298    views::MenuItemView* menu_to_select =
299        menu->GetSubmenu()->GetMenuItemAt(0);
300    ui_controls::MoveMouseToCenterAndPress(menu_to_select, ui_controls::LEFT,
301        ui_controls::DOWN | ui_controls::UP,
302        CreateEventTask(this, &BookmarkBarViewTest1::Step3));
303  }
304
305  void Step3() {
306    // We should have navigated to URL f1a.
307    ASSERT_TRUE(navigator_.url_ ==
308                model_->GetBookmarkBarNode()->GetChild(0)->GetChild(0)->
309                GetURL());
310
311    // Make sure button is no longer pushed.
312    views::TextButton* button = bb_view_->GetBookmarkButton(0);
313    ASSERT_TRUE(button->state() == views::CustomButton::BS_NORMAL);
314
315    views::MenuItemView* menu = bb_view_->GetMenu();
316    ASSERT_TRUE(menu == NULL || !menu->GetSubmenu()->IsShowing());
317
318    Done();
319  }
320};
321
322// TODO(jcampan): http://crbug.com/26996 temporarily disabled because failing
323//                since we move to running the process
324VIEW_TEST(BookmarkBarViewTest1, DISABLED_Basic)
325
326// Brings up menu, clicks on empty space and make sure menu hides.
327class BookmarkBarViewTest2 : public BookmarkBarViewEventTestBase {
328 protected:
329  virtual void DoTestOnMessageLoop() {
330    // Move the mouse to the first folder on the bookmark bar and press the
331    // mouse.
332    views::TextButton* button = bb_view_->GetBookmarkButton(0);
333    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
334        ui_controls::DOWN | ui_controls::UP,
335        CreateEventTask(this, &BookmarkBarViewTest2::Step2));
336  }
337
338 private:
339  void Step2() {
340    // Menu should be showing.
341    views::MenuItemView* menu = bb_view_->GetMenu();
342    ASSERT_TRUE(menu != NULL && menu->GetSubmenu()->IsShowing());
343
344    // Click on 0x0, which should trigger closing menu.
345    // NOTE: this code assume there is a left margin, which is currently
346    // true. If that changes, this code will need to find another empty space
347    // to press the mouse on.
348    gfx::Point mouse_loc;
349    views::View::ConvertPointToScreen(bb_view_, &mouse_loc);
350    ui_controls::SendMouseMove(0, 0);
351    ui_controls::SendMouseEventsNotifyWhenDone(
352        ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
353        CreateEventTask(this, &BookmarkBarViewTest2::Step3));
354  }
355
356  void Step3() {
357    // The menu shouldn't be showing.
358    views::MenuItemView* menu = bb_view_->GetMenu();
359    ASSERT_TRUE(menu == NULL || !menu->GetSubmenu()->IsShowing());
360
361    // Make sure button is no longer pushed.
362    views::TextButton* button = bb_view_->GetBookmarkButton(0);
363    ASSERT_TRUE(button->state() == views::CustomButton::BS_NORMAL);
364
365    window_->Activate();
366
367    Done();
368  }
369};
370
371// TODO(jcampan): http://crbug.com/26996 temporarily disabled because failing
372//                since we move to running the process
373VIEW_TEST(BookmarkBarViewTest2, DISABLED_HideOnDesktopClick)
374
375// Brings up menu. Moves over child to make sure submenu appears, moves over
376// another child and make sure next menu appears.
377class BookmarkBarViewTest3 : public BookmarkBarViewEventTestBase {
378 protected:
379  virtual void DoTestOnMessageLoop() {
380    // Move the mouse to the first folder on the bookmark bar and press the
381    // mouse.
382    views::MenuButton* button = bb_view_->other_bookmarked_button();
383    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
384        ui_controls::DOWN | ui_controls::UP,
385        CreateEventTask(this, &BookmarkBarViewTest3::Step2));
386  }
387
388 private:
389  void Step2() {
390    // Menu should be showing.
391    views::MenuItemView* menu = bb_view_->GetMenu();
392    ASSERT_TRUE(menu != NULL);
393    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
394
395    views::MenuItemView* child_menu =
396        menu->GetSubmenu()->GetMenuItemAt(1);
397    ASSERT_TRUE(child_menu != NULL);
398
399    // Click on second child, which has a submenu.
400    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
401        ui_controls::DOWN | ui_controls::UP,
402        CreateEventTask(this, &BookmarkBarViewTest3::Step3));
403  }
404
405  void Step3() {
406    // Make sure sub menu is showing.
407    views::MenuItemView* menu = bb_view_->GetMenu();
408    views::MenuItemView* child_menu =
409        menu->GetSubmenu()->GetMenuItemAt(1);
410    ASSERT_TRUE(child_menu->GetSubmenu() != NULL);
411    ASSERT_TRUE(child_menu->GetSubmenu()->IsShowing());
412
413    // Click on third child, which has a submenu too.
414    child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
415    ASSERT_TRUE(child_menu != NULL);
416    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
417        ui_controls::DOWN | ui_controls::UP,
418        CreateEventTask(this, &BookmarkBarViewTest3::Step4));
419  }
420
421  void Step4() {
422    // Make sure sub menu we first clicked isn't showing.
423    views::MenuItemView* menu = bb_view_->GetMenu();
424    views::MenuItemView* child_menu =
425        menu->GetSubmenu()->GetMenuItemAt(1);
426    ASSERT_TRUE(child_menu->GetSubmenu() != NULL);
427    ASSERT_FALSE(child_menu->GetSubmenu()->IsShowing());
428
429    // And submenu we last clicked is showing.
430    child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
431    ASSERT_TRUE(child_menu != NULL);
432    ASSERT_TRUE(child_menu->GetSubmenu()->IsShowing());
433
434    // Nothing should have been selected.
435    EXPECT_EQ(GURL(), navigator_.url_);
436
437    // Hide menu.
438    menu->GetMenuController()->CancelAll();
439
440    Done();
441  }
442};
443
444VIEW_TEST(BookmarkBarViewTest3, Submenus)
445
446// Observer that posts task upon the context menu creation.
447// This is necessary for Linux as the context menu has to check
448// the clipboard, which invokes the event loop.
449class ContextMenuNotificationObserver : public NotificationObserver {
450 public:
451  explicit ContextMenuNotificationObserver(Task* task) : task_(task) {
452    registrar_.Add(this,
453                   NotificationType::BOOKMARK_CONTEXT_MENU_SHOWN,
454                   NotificationService::AllSources());
455  }
456
457  virtual void Observe(NotificationType type,
458                       const NotificationSource& source,
459                       const NotificationDetails& details) {
460    MessageLoop::current()->PostTask(FROM_HERE, task_);
461  }
462
463  // Sets the task that is posted when the context menu is shown.
464  void set_task(Task* task) { task_ = task; }
465
466 private:
467  NotificationRegistrar registrar_;
468  Task* task_;
469
470  DISALLOW_COPY_AND_ASSIGN(ContextMenuNotificationObserver);
471};
472
473// Tests context menus by way of opening a context menu for a bookmark,
474// then right clicking to get context menu and selecting the first menu item
475// (open).
476class BookmarkBarViewTest4 : public BookmarkBarViewEventTestBase {
477 public:
478  BookmarkBarViewTest4()
479      : ALLOW_THIS_IN_INITIALIZER_LIST(
480          observer_(CreateEventTask(this, &BookmarkBarViewTest4::Step3))) {
481  }
482
483 protected:
484  virtual void DoTestOnMessageLoop() {
485    // Move the mouse to the first folder on the bookmark bar and press the
486    // mouse.
487    views::TextButton* button = bb_view_->other_bookmarked_button();
488    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
489        ui_controls::DOWN | ui_controls::UP,
490        CreateEventTask(this, &BookmarkBarViewTest4::Step2));
491  }
492
493 private:
494  void Step2() {
495    // Menu should be showing.
496    views::MenuItemView* menu = bb_view_->GetMenu();
497    ASSERT_TRUE(menu != NULL);
498    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
499
500    views::MenuItemView* child_menu =
501        menu->GetSubmenu()->GetMenuItemAt(0);
502    ASSERT_TRUE(child_menu != NULL);
503
504    // Right click on the first child to get its context menu.
505    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
506        ui_controls::DOWN | ui_controls::UP, NULL);
507    // Step3 will be invoked by ContextMenuNotificationObserver.
508  }
509
510  void Step3() {
511    // Make sure the context menu is showing.
512    views::MenuItemView* menu = bb_view_->GetContextMenu();
513    ASSERT_TRUE(menu != NULL);
514    ASSERT_TRUE(menu->GetSubmenu());
515    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
516
517    // Select the first menu item (open).
518    ui_controls::MoveMouseToCenterAndPress(menu->GetSubmenu()->GetMenuItemAt(0),
519        ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
520        CreateEventTask(this, &BookmarkBarViewTest4::Step4));
521  }
522
523  void Step4() {
524    EXPECT_EQ(navigator_.url_,
525              model_->other_node()->GetChild(0)->GetURL());
526
527    Done();
528  }
529
530  ContextMenuNotificationObserver observer_;
531};
532
533VIEW_TEST(BookmarkBarViewTest4, ContextMenus)
534
535// Tests drag and drop within the same menu.
536class BookmarkBarViewTest5 : public BookmarkBarViewEventTestBase {
537 protected:
538  virtual void DoTestOnMessageLoop() {
539    url_dragging_ =
540        model_->GetBookmarkBarNode()->GetChild(0)->GetChild(0)->GetURL();
541
542    // Move the mouse to the first folder on the bookmark bar and press the
543    // mouse.
544    views::TextButton* button = bb_view_->GetBookmarkButton(0);
545    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
546        ui_controls::DOWN | ui_controls::UP,
547        CreateEventTask(this, &BookmarkBarViewTest5::Step2));
548  }
549
550 private:
551  void Step2() {
552    // Menu should be showing.
553    views::MenuItemView* menu = bb_view_->GetMenu();
554    ASSERT_TRUE(menu != NULL);
555    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
556
557    views::MenuItemView* child_menu =
558        menu->GetSubmenu()->GetMenuItemAt(0);
559    ASSERT_TRUE(child_menu != NULL);
560
561    // Move mouse to center of menu and press button.
562    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
563        ui_controls::DOWN,
564        CreateEventTask(this, &BookmarkBarViewTest5::Step3));
565  }
566
567  void Step3() {
568    views::MenuItemView* target_menu =
569        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
570    gfx::Point loc(1, target_menu->height() - 1);
571    views::View::ConvertPointToScreen(target_menu, &loc);
572
573    // Start a drag.
574    ui_controls::SendMouseMoveNotifyWhenDone(loc.x() + 10, loc.y(),
575        CreateEventTask(this, &BookmarkBarViewTest5::Step4));
576
577    // See comment above this method as to why we do this.
578    ScheduleMouseMoveInBackground(loc.x(), loc.y());
579  }
580
581  void Step4() {
582    // Drop the item so that it's now the second item.
583    views::MenuItemView* target_menu =
584        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
585    gfx::Point loc(1, target_menu->height() - 1);
586    views::View::ConvertPointToScreen(target_menu, &loc);
587    ui_controls::SendMouseMove(loc.x(), loc.y());
588
589    ui_controls::SendMouseEventsNotifyWhenDone(ui_controls::LEFT,
590        ui_controls::UP,
591        CreateEventTask(this, &BookmarkBarViewTest5::Step5));
592  }
593
594  void Step5() {
595    GURL url = model_->GetBookmarkBarNode()->GetChild(0)->GetChild(1)->GetURL();
596    EXPECT_EQ(url_dragging_, url);
597    Done();
598  }
599
600  GURL url_dragging_;
601};
602
603VIEW_TEST(BookmarkBarViewTest5, MAYBE_DND)
604
605// Tests holding mouse down on overflow button, dragging such that menu pops up
606// then selecting an item.
607class BookmarkBarViewTest6 : public BookmarkBarViewEventTestBase {
608 protected:
609  virtual void DoTestOnMessageLoop() {
610    // Press the mouse button on the overflow button. Don't release it though.
611    views::TextButton* button = bb_view_->overflow_button();
612    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
613        ui_controls::DOWN, CreateEventTask(this, &BookmarkBarViewTest6::Step2));
614  }
615
616 private:
617  void Step2() {
618    // Menu should be showing.
619    views::MenuItemView* menu = bb_view_->GetMenu();
620    ASSERT_TRUE(menu != NULL);
621    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
622
623    views::MenuItemView* child_menu =
624        menu->GetSubmenu()->GetMenuItemAt(0);
625    ASSERT_TRUE(child_menu != NULL);
626
627    // Move mouse to center of menu and release mouse.
628    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
629        ui_controls::UP, CreateEventTask(this, &BookmarkBarViewTest6::Step3));
630  }
631
632  void Step3() {
633    ASSERT_TRUE(navigator_.url_ ==
634                model_->GetBookmarkBarNode()->GetChild(4)->GetURL());
635    Done();
636  }
637
638  GURL url_dragging_;
639};
640
641VIEW_TEST(BookmarkBarViewTest6, OpenMenuOnClickAndHold)
642
643// Tests drag and drop to different menu.
644class BookmarkBarViewTest7 : public BookmarkBarViewEventTestBase {
645 protected:
646  virtual void DoTestOnMessageLoop() {
647    url_dragging_ =
648        model_->GetBookmarkBarNode()->GetChild(0)->GetChild(0)->GetURL();
649
650    // Move the mouse to the first folder on the bookmark bar and press the
651    // mouse.
652    views::TextButton* button = bb_view_->GetBookmarkButton(0);
653    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
654        ui_controls::DOWN | ui_controls::UP,
655        CreateEventTask(this, &BookmarkBarViewTest7::Step2));
656  }
657
658 private:
659  void Step2() {
660    // Menu should be showing.
661    views::MenuItemView* menu = bb_view_->GetMenu();
662    ASSERT_TRUE(menu != NULL);
663    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
664
665    views::MenuItemView* child_menu =
666        menu->GetSubmenu()->GetMenuItemAt(0);
667    ASSERT_TRUE(child_menu != NULL);
668
669    // Move mouse to center of menu and press button.
670    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
671        ui_controls::DOWN,
672        CreateEventTask(this, &BookmarkBarViewTest7::Step3));
673  }
674
675  void Step3() {
676    // Drag over other button.
677    views::TextButton* other_button =
678        bb_view_->other_bookmarked_button();
679    gfx::Point loc(other_button->width() / 2, other_button->height() / 2);
680    views::View::ConvertPointToScreen(other_button, &loc);
681
682    // Start a drag.
683    ui_controls::SendMouseMoveNotifyWhenDone(loc.x() + 10, loc.y(),
684        NewRunnableMethod(this, &BookmarkBarViewTest7::Step4));
685
686    // See comment above this method as to why we do this.
687    ScheduleMouseMoveInBackground(loc.x(), loc.y());
688  }
689
690  void Step4() {
691    views::MenuItemView* drop_menu = bb_view_->GetDropMenu();
692    ASSERT_TRUE(drop_menu != NULL);
693    ASSERT_TRUE(drop_menu->GetSubmenu()->IsShowing());
694
695    views::MenuItemView* target_menu =
696        drop_menu->GetSubmenu()->GetMenuItemAt(0);
697    gfx::Point loc(1, 1);
698    views::View::ConvertPointToScreen(target_menu, &loc);
699    ui_controls::SendMouseMove(loc.x(), loc.y());
700    ui_controls::SendMouseEventsNotifyWhenDone(
701        ui_controls::LEFT, ui_controls::UP,
702        CreateEventTask(this, &BookmarkBarViewTest7::Step5));
703  }
704
705  void Step5() {
706    ASSERT_TRUE(model_->other_node()->GetChild(0)->GetURL() == url_dragging_);
707    Done();
708  }
709
710  GURL url_dragging_;
711};
712
713VIEW_TEST(BookmarkBarViewTest7, MAYBE_DNDToDifferentMenu)
714
715// Drags from one menu to next so that original menu closes, then back to
716// original menu.
717class BookmarkBarViewTest8 : public BookmarkBarViewEventTestBase {
718 protected:
719  virtual void DoTestOnMessageLoop() {
720    url_dragging_ =
721        model_->GetBookmarkBarNode()->GetChild(0)->GetChild(0)->GetURL();
722
723    // Move the mouse to the first folder on the bookmark bar and press the
724    // mouse.
725    views::TextButton* button = bb_view_->GetBookmarkButton(0);
726    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
727        ui_controls::DOWN | ui_controls::UP,
728        CreateEventTask(this, &BookmarkBarViewTest8::Step2));
729  }
730
731 private:
732  void Step2() {
733    // Menu should be showing.
734    views::MenuItemView* menu = bb_view_->GetMenu();
735    ASSERT_TRUE(menu != NULL);
736    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
737
738    views::MenuItemView* child_menu =
739        menu->GetSubmenu()->GetMenuItemAt(0);
740    ASSERT_TRUE(child_menu != NULL);
741
742    // Move mouse to center of menu and press button.
743    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
744        ui_controls::DOWN,
745        CreateEventTask(this, &BookmarkBarViewTest8::Step3));
746  }
747
748  void Step3() {
749    // Drag over other button.
750    views::TextButton* other_button =
751        bb_view_->other_bookmarked_button();
752    gfx::Point loc(other_button->width() / 2, other_button->height() / 2);
753    views::View::ConvertPointToScreen(other_button, &loc);
754
755    // Start a drag.
756    ui_controls::SendMouseMoveNotifyWhenDone(loc.x() + 10, loc.y(),
757        NewRunnableMethod(this, &BookmarkBarViewTest8::Step4));
758
759    // See comment above this method as to why we do this.
760    ScheduleMouseMoveInBackground(loc.x(), loc.y());
761  }
762
763  void Step4() {
764    views::MenuItemView* drop_menu = bb_view_->GetDropMenu();
765    ASSERT_TRUE(drop_menu != NULL);
766    ASSERT_TRUE(drop_menu->GetSubmenu()->IsShowing());
767
768    // Now drag back over first menu.
769    views::TextButton* button = bb_view_->GetBookmarkButton(0);
770    gfx::Point loc(button->width() / 2, button->height() / 2);
771    views::View::ConvertPointToScreen(button, &loc);
772    ui_controls::SendMouseMoveNotifyWhenDone(loc.x(), loc.y(),
773        NewRunnableMethod(this, &BookmarkBarViewTest8::Step5));
774  }
775
776  void Step5() {
777    // Drop on folder F11.
778    views::MenuItemView* drop_menu = bb_view_->GetDropMenu();
779    ASSERT_TRUE(drop_menu != NULL);
780    ASSERT_TRUE(drop_menu->GetSubmenu()->IsShowing());
781
782    views::MenuItemView* target_menu =
783        drop_menu->GetSubmenu()->GetMenuItemAt(1);
784    ui_controls::MoveMouseToCenterAndPress(
785        target_menu, ui_controls::LEFT, ui_controls::UP,
786        CreateEventTask(this, &BookmarkBarViewTest8::Step6));
787  }
788
789  void Step6() {
790    // Make sure drop was processed.
791    GURL final_url = model_->GetBookmarkBarNode()->GetChild(0)->GetChild(0)->
792        GetChild(1)->GetURL();
793    ASSERT_TRUE(final_url == url_dragging_);
794    Done();
795  }
796
797  GURL url_dragging_;
798};
799
800VIEW_TEST(BookmarkBarViewTest8, MAYBE_DNDBackToOriginatingMenu)
801
802// Moves the mouse over the scroll button and makes sure we get scrolling.
803class BookmarkBarViewTest9 : public BookmarkBarViewEventTestBase {
804 protected:
805  virtual bool CreateBigMenu() { return true; }
806
807  virtual void DoTestOnMessageLoop() {
808    // Move the mouse to the first folder on the bookmark bar and press the
809    // mouse.
810    views::TextButton* button = bb_view_->GetBookmarkButton(0);
811    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
812        ui_controls::DOWN | ui_controls::UP,
813        CreateEventTask(this, &BookmarkBarViewTest9::Step2));
814  }
815
816 private:
817  void Step2() {
818    // Menu should be showing.
819    views::MenuItemView* menu = bb_view_->GetMenu();
820    ASSERT_TRUE(menu != NULL);
821    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
822
823    first_menu_ = menu->GetSubmenu()->GetMenuItemAt(0);
824    gfx::Point menu_loc;
825    views::View::ConvertPointToScreen(first_menu_, &menu_loc);
826    start_y_ = menu_loc.y();
827
828    // Move the mouse over the scroll button.
829    views::View* scroll_container = menu->GetSubmenu()->parent();
830    ASSERT_TRUE(scroll_container != NULL);
831    scroll_container = scroll_container->parent();
832    ASSERT_TRUE(scroll_container != NULL);
833    views::View* scroll_down_button = scroll_container->GetChildViewAt(1);
834    ASSERT_TRUE(scroll_down_button);
835    gfx::Point loc(scroll_down_button->width() / 2,
836                   scroll_down_button->height() / 2);
837    views::View::ConvertPointToScreen(scroll_down_button, &loc);
838
839    // On linux, the sending one location isn't enough.
840    ui_controls::SendMouseMove(loc.x() - 1 , loc.y() - 1);
841    ui_controls::SendMouseMoveNotifyWhenDone(
842        loc.x(), loc.y(), CreateEventTask(this, &BookmarkBarViewTest9::Step3));
843  }
844
845  void Step3() {
846    MessageLoop::current()->PostDelayedTask(FROM_HERE,
847        NewRunnableMethod(this, &BookmarkBarViewTest9::Step4), 200);
848  }
849
850  void Step4() {
851    gfx::Point menu_loc;
852    views::View::ConvertPointToScreen(first_menu_, &menu_loc);
853    ASSERT_NE(start_y_, menu_loc.y());
854
855    // Hide menu.
856    bb_view_->GetMenu()->GetMenuController()->CancelAll();
857
858    // On linux, Cancelling menu will call Quit on the message loop,
859    // which can interfere with Done. We need to run Done in the
860    // next execution loop.
861    MessageLoop::current()->PostTask(
862        FROM_HERE,
863        NewRunnableMethod(this, &ViewEventTestBase::Done));
864  }
865
866  int start_y_;
867  views::MenuItemView* first_menu_;
868};
869
870VIEW_TEST(BookmarkBarViewTest9, MAYBE_ScrollButtonScrolls)
871
872// Tests up/down/left/enter key messages.
873class BookmarkBarViewTest10 : public BookmarkBarViewEventTestBase {
874 protected:
875  virtual void DoTestOnMessageLoop() {
876    // Move the mouse to the first folder on the bookmark bar and press the
877    // mouse.
878    views::TextButton* button = bb_view_->GetBookmarkButton(0);
879    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
880        ui_controls::DOWN | ui_controls::UP,
881        CreateEventTask(this, &BookmarkBarViewTest10::Step2));
882    MessageLoop::current()->RunAllPending();
883  }
884
885 private:
886  void Step2() {
887    // Menu should be showing.
888    views::MenuItemView* menu = bb_view_->GetMenu();
889    ASSERT_TRUE(menu != NULL);
890    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
891
892    // Send a down event, which should select the first item.
893    ui_controls::SendKeyPressNotifyWhenDone(
894        NULL, ui::VKEY_DOWN, false, false, false, false,
895        CreateEventTask(this, &BookmarkBarViewTest10::Step3));
896  }
897
898  void Step3() {
899    // Make sure menu is showing and item is selected.
900    views::MenuItemView* menu = bb_view_->GetMenu();
901    ASSERT_TRUE(menu != NULL);
902    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
903    ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
904
905    // Send a key down event, which should select the next item.
906    ui_controls::SendKeyPressNotifyWhenDone(
907        NULL, ui::VKEY_DOWN, false, false, false, false,
908        CreateEventTask(this, &BookmarkBarViewTest10::Step4));
909  }
910
911  void Step4() {
912    views::MenuItemView* menu = bb_view_->GetMenu();
913    ASSERT_TRUE(menu != NULL);
914    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
915    ASSERT_FALSE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
916    ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(1)->IsSelected());
917
918    // Send a right arrow to force the menu to open.
919    ui_controls::SendKeyPressNotifyWhenDone(
920        NULL, ui::VKEY_RIGHT, false, false, false, false,
921        CreateEventTask(this, &BookmarkBarViewTest10::Step5));
922  }
923
924  void Step5() {
925    // Make sure the submenu is showing.
926    views::MenuItemView* menu = bb_view_->GetMenu();
927    ASSERT_TRUE(menu != NULL);
928    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
929    views::MenuItemView* submenu = menu->GetSubmenu()->GetMenuItemAt(1);
930    ASSERT_TRUE(submenu->IsSelected());
931    ASSERT_TRUE(submenu->GetSubmenu());
932    ASSERT_TRUE(submenu->GetSubmenu()->IsShowing());
933
934    // Send a left arrow to close the submenu.
935    ui_controls::SendKeyPressNotifyWhenDone(
936        NULL, ui::VKEY_LEFT, false, false, false, false,
937        CreateEventTask(this, &BookmarkBarViewTest10::Step6));
938  }
939
940  void Step6() {
941    // Make sure the submenu is showing.
942    views::MenuItemView* menu = bb_view_->GetMenu();
943    ASSERT_TRUE(menu != NULL);
944    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
945    views::MenuItemView* submenu = menu->GetSubmenu()->GetMenuItemAt(1);
946    ASSERT_TRUE(submenu->IsSelected());
947    ASSERT_TRUE(!submenu->GetSubmenu() || !submenu->GetSubmenu()->IsShowing());
948
949    // Send a down arrow to wrap back to f1a
950    ui_controls::SendKeyPressNotifyWhenDone(
951        NULL, ui::VKEY_DOWN, false, false, false, false,
952        CreateEventTask(this, &BookmarkBarViewTest10::Step7));
953  }
954
955  void Step7() {
956    // Make sure menu is showing and item is selected.
957    views::MenuItemView* menu = bb_view_->GetMenu();
958    ASSERT_TRUE(menu != NULL);
959    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
960    ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
961
962    // Send enter, which should select the item.
963    ui_controls::SendKeyPressNotifyWhenDone(
964        NULL, ui::VKEY_RETURN, false, false, false, false,
965        CreateEventTask(this, &BookmarkBarViewTest10::Step8));
966  }
967
968  void Step8() {
969    ASSERT_TRUE(
970        model_->GetBookmarkBarNode()->GetChild(0)->GetChild(0)->GetURL() ==
971        navigator_.url_);
972    Done();
973  }
974};
975
976VIEW_TEST(BookmarkBarViewTest10, MAYBE_KeyEvents)
977
978// Make sure the menu closes with the following sequence: show menu, show
979// context menu, close context menu (via escape), then click else where. This
980// effectively verifies we maintain mouse capture after the context menu is
981// hidden.
982class BookmarkBarViewTest11 : public BookmarkBarViewEventTestBase {
983 public:
984  BookmarkBarViewTest11()
985      : ALLOW_THIS_IN_INITIALIZER_LIST(
986          observer_(CreateEventTask(this, &BookmarkBarViewTest11::Step3))) {
987  }
988
989 protected:
990  virtual void DoTestOnMessageLoop() {
991    // Move the mouse to the first folder on the bookmark bar and press the
992    // mouse.
993    views::TextButton* button = bb_view_->other_bookmarked_button();
994    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
995        ui_controls::DOWN | ui_controls::UP,
996        CreateEventTask(this, &BookmarkBarViewTest11::Step2));
997  }
998
999 private:
1000  void Step2() {
1001    // Menu should be showing.
1002    views::MenuItemView* menu = bb_view_->GetMenu();
1003    ASSERT_TRUE(menu != NULL);
1004    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1005
1006    views::MenuItemView* child_menu =
1007        menu->GetSubmenu()->GetMenuItemAt(0);
1008    ASSERT_TRUE(child_menu != NULL);
1009
1010    // Right click on the first child to get its context menu.
1011    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1012        ui_controls::DOWN | ui_controls::UP, NULL);
1013    // Step3 will be invoked by ContextMenuNotificationObserver.
1014  }
1015
1016  void Step3() {
1017    // Send escape so that the context menu hides.
1018    ui_controls::SendKeyPressNotifyWhenDone(
1019        NULL, ui::VKEY_ESCAPE, false, false, false, false,
1020        CreateEventTask(this, &BookmarkBarViewTest11::Step4));
1021  }
1022
1023  void Step4() {
1024    // Make sure the context menu is no longer showing.
1025    views::MenuItemView* menu = bb_view_->GetContextMenu();
1026    ASSERT_TRUE(!menu || !menu->GetSubmenu() ||
1027                !menu->GetSubmenu()->IsShowing());
1028
1029    // But the menu should be showing.
1030    menu = bb_view_->GetMenu();
1031    ASSERT_TRUE(menu && menu->GetSubmenu() && menu->GetSubmenu()->IsShowing());
1032
1033    // Now click on empty space.
1034    gfx::Point mouse_loc;
1035    views::View::ConvertPointToScreen(bb_view_, &mouse_loc);
1036    ui_controls::SendMouseMove(mouse_loc.x(), mouse_loc.y());
1037    ui_controls::SendMouseEventsNotifyWhenDone(
1038        ui_controls::LEFT, ui_controls::UP | ui_controls::DOWN,
1039        CreateEventTask(this, &BookmarkBarViewTest11::Step5));
1040  }
1041
1042  void Step5() {
1043    // Make sure the menu is not showing.
1044    views::MenuItemView* menu = bb_view_->GetMenu();
1045    ASSERT_TRUE(!menu || !menu->GetSubmenu() ||
1046                !menu->GetSubmenu()->IsShowing());
1047    Done();
1048  }
1049
1050  ContextMenuNotificationObserver observer_;
1051};
1052
1053VIEW_TEST(BookmarkBarViewTest11, MAYBE_CloseMenuAfterClosingContextMenu)
1054
1055// Tests showing a modal dialog from a context menu.
1056class BookmarkBarViewTest12 : public BookmarkBarViewEventTestBase {
1057 protected:
1058  virtual void DoTestOnMessageLoop() {
1059    // Open up the other folder.
1060    views::TextButton* button = bb_view_->other_bookmarked_button();
1061    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1062        ui_controls::DOWN | ui_controls::UP,
1063        CreateEventTask(this, &BookmarkBarViewTest12::Step2));
1064    bookmark_utils::num_urls_before_prompting = 1;
1065  }
1066
1067  ~BookmarkBarViewTest12() {
1068    bookmark_utils::num_urls_before_prompting = 15;
1069  }
1070
1071 private:
1072  void Step2() {
1073    // Menu should be showing.
1074    views::MenuItemView* menu = bb_view_->GetMenu();
1075    ASSERT_TRUE(menu != NULL);
1076    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1077
1078    views::MenuItemView* child_menu =
1079        menu->GetSubmenu()->GetMenuItemAt(1);
1080    ASSERT_TRUE(child_menu != NULL);
1081
1082    // Right click on the second child (a folder) to get its context menu.
1083    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1084        ui_controls::DOWN | ui_controls::UP,
1085        CreateEventTask(this, &BookmarkBarViewTest12::Step3));
1086  }
1087
1088  void Step3() {
1089    // Make sure the context menu is showing.
1090    views::MenuItemView* menu = bb_view_->GetContextMenu();
1091    ASSERT_TRUE(menu && menu->GetSubmenu() && menu->GetSubmenu()->IsShowing());
1092
1093    // Select the first item in the context menu (open all).
1094    views::MenuItemView* child_menu =
1095        menu->GetSubmenu()->GetMenuItemAt(0);
1096    ASSERT_TRUE(child_menu != NULL);
1097    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
1098        ui_controls::DOWN | ui_controls::UP, NULL);
1099
1100    // Delay until we send tab, otherwise the message box doesn't appear
1101    // correctly.
1102    MessageLoop::current()->PostDelayedTask(FROM_HERE,
1103        CreateEventTask(this, &BookmarkBarViewTest12::Step4), 1000);
1104  }
1105
1106  void Step4() {
1107    // Press tab to give focus to the cancel button.
1108    ui_controls::SendKeyPress(NULL, ui::VKEY_TAB, false, false, false, false);
1109
1110    // For some reason return isn't processed correctly unless we delay.
1111    MessageLoop::current()->PostDelayedTask(FROM_HERE,
1112        CreateEventTask(this, &BookmarkBarViewTest12::Step5), 1000);
1113  }
1114
1115  void Step5() {
1116    // And press enter so that the cancel button is selected.
1117    ui_controls::SendKeyPressNotifyWhenDone(
1118        NULL, ui::VKEY_RETURN, false, false, false, false,
1119        CreateEventTask(this, &BookmarkBarViewTest12::Step6));
1120  }
1121
1122  void Step6() {
1123    // Do a delayed task to give the dialog time to exit.
1124    MessageLoop::current()->PostTask(
1125        FROM_HERE, CreateEventTask(this, &BookmarkBarViewTest12::Step7));
1126  }
1127
1128  void Step7() {
1129    Done();
1130  }
1131};
1132
1133VIEW_TEST(BookmarkBarViewTest12, MAYBE_CloseWithModalDialog)
1134
1135// Tests clicking on the separator of a context menu (this is for coverage of
1136// bug 17862).
1137class BookmarkBarViewTest13 : public BookmarkBarViewEventTestBase {
1138 public:
1139  BookmarkBarViewTest13()
1140      : ALLOW_THIS_IN_INITIALIZER_LIST(
1141          observer_(CreateEventTask(this, &BookmarkBarViewTest13::Step3))) {
1142  }
1143
1144 protected:
1145  virtual void DoTestOnMessageLoop() {
1146    // Move the mouse to the first folder on the bookmark bar and press the
1147    // mouse.
1148    views::TextButton* button = bb_view_->other_bookmarked_button();
1149    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1150        ui_controls::DOWN | ui_controls::UP,
1151        CreateEventTask(this, &BookmarkBarViewTest13::Step2));
1152  }
1153
1154 private:
1155  void Step2() {
1156    // Menu should be showing.
1157    views::MenuItemView* menu = bb_view_->GetMenu();
1158    ASSERT_TRUE(menu != NULL);
1159    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1160
1161    views::MenuItemView* child_menu =
1162        menu->GetSubmenu()->GetMenuItemAt(0);
1163    ASSERT_TRUE(child_menu != NULL);
1164
1165    // Right click on the first child to get its context menu.
1166    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1167        ui_controls::DOWN | ui_controls::UP, NULL);
1168    // Step3 will be invoked by ContextMenuNotificationObserver.
1169  }
1170
1171  void Step3() {
1172    // Make sure the context menu is showing.
1173    views::MenuItemView* menu = bb_view_->GetContextMenu();
1174    ASSERT_TRUE(menu != NULL);
1175    ASSERT_TRUE(menu->GetSubmenu());
1176    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1177
1178    // Find the first separator.
1179    views::SubmenuView* submenu = menu->GetSubmenu();
1180    views::View* separator_view = NULL;
1181    for (int i = 0; i < submenu->child_count(); ++i) {
1182      if (submenu->GetChildViewAt(i)->GetID() !=
1183          views::MenuItemView::kMenuItemViewID) {
1184        separator_view = submenu->GetChildViewAt(i);
1185        break;
1186      }
1187    }
1188    ASSERT_TRUE(separator_view);
1189
1190    // Click on the separator. Clicking on the separator shouldn't visually
1191    // change anything.
1192    ui_controls::MoveMouseToCenterAndPress(separator_view,
1193        ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1194        CreateEventTask(this, &BookmarkBarViewTest13::Step4));
1195  }
1196
1197  void Step4() {
1198    // The context menu should still be showing.
1199    views::MenuItemView* menu = bb_view_->GetContextMenu();
1200    ASSERT_TRUE(menu != NULL);
1201    ASSERT_TRUE(menu->GetSubmenu());
1202    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1203
1204    // Select the first context menu item.
1205    ui_controls::MoveMouseToCenterAndPress(menu->GetSubmenu()->GetMenuItemAt(0),
1206        ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1207        CreateEventTask(this, &BookmarkBarViewTest13::Step5));
1208  }
1209
1210  void Step5() {
1211    Done();
1212  }
1213
1214  ContextMenuNotificationObserver observer_;
1215};
1216
1217VIEW_TEST(BookmarkBarViewTest13, ClickOnContextMenuSeparator)
1218
1219// Makes sure right clicking on a folder on the bookmark bar doesn't result in
1220// both a context menu and showing the menu.
1221class BookmarkBarViewTest14 : public BookmarkBarViewEventTestBase {
1222 public:
1223  BookmarkBarViewTest14()
1224      : ALLOW_THIS_IN_INITIALIZER_LIST(
1225          observer_(CreateEventTask(this, &BookmarkBarViewTest14::Step2))) {
1226  }
1227
1228 protected:
1229  virtual void DoTestOnMessageLoop() {
1230    // Move the mouse to the first folder on the bookmark bar and press the
1231    // right mouse button.
1232    views::TextButton* button = bb_view_->GetBookmarkButton(0);
1233    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::RIGHT,
1234        ui_controls::DOWN | ui_controls::UP, NULL);
1235    // Step2 will be invoked by ContextMenuNotificationObserver.
1236  }
1237
1238 private:
1239
1240  void Step2() {
1241    // Menu should NOT be showing.
1242    views::MenuItemView* menu = bb_view_->GetMenu();
1243    ASSERT_TRUE(menu == NULL);
1244
1245    // Send escape so that the context menu hides.
1246    ui_controls::SendKeyPressNotifyWhenDone(
1247        NULL, ui::VKEY_ESCAPE, false, false, false, false,
1248        CreateEventTask(this, &BookmarkBarViewTest14::Step3));
1249  }
1250
1251  void Step3() {
1252    Done();
1253  }
1254
1255  ContextMenuNotificationObserver observer_;
1256};
1257
1258VIEW_TEST(BookmarkBarViewTest14, ContextMenus2)
1259
1260// Makes sure deleting from the context menu keeps the bookmark menu showing.
1261class BookmarkBarViewTest15 : public BookmarkBarViewEventTestBase {
1262 public:
1263  BookmarkBarViewTest15()
1264      : deleted_menu_id_(0),
1265        ALLOW_THIS_IN_INITIALIZER_LIST(
1266            observer_(CreateEventTask(this, &BookmarkBarViewTest15::Step3))) {
1267  }
1268
1269 protected:
1270  virtual void DoTestOnMessageLoop() {
1271    // Show the other bookmarks.
1272    views::TextButton* button = bb_view_->other_bookmarked_button();
1273    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1274        ui_controls::DOWN | ui_controls::UP,
1275        CreateEventTask(this, &BookmarkBarViewTest15::Step2));
1276  }
1277
1278 private:
1279  void Step2() {
1280    // Menu should be showing.
1281    views::MenuItemView* menu = bb_view_->GetMenu();
1282    ASSERT_TRUE(menu != NULL);
1283    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1284
1285    views::MenuItemView* child_menu =
1286        menu->GetSubmenu()->GetMenuItemAt(1);
1287    ASSERT_TRUE(child_menu != NULL);
1288
1289    deleted_menu_id_ = child_menu->GetCommand();
1290
1291    // Right click on the second child to get its context menu.
1292    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1293        ui_controls::DOWN | ui_controls::UP, NULL);
1294    // Step3 will be invoked by ContextMenuNotificationObserver.
1295  }
1296
1297  void Step3() {
1298    // Make sure the context menu is showing.
1299    views::MenuItemView* menu = bb_view_->GetContextMenu();
1300    ASSERT_TRUE(menu != NULL);
1301    ASSERT_TRUE(menu->GetSubmenu());
1302    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1303
1304    views::MenuItemView* delete_menu =
1305        menu->GetMenuItemByID(IDC_BOOKMARK_BAR_REMOVE);
1306    ASSERT_TRUE(delete_menu);
1307
1308    // Click on the delete button.
1309    ui_controls::MoveMouseToCenterAndPress(delete_menu,
1310        ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1311        CreateEventTask(this, &BookmarkBarViewTest15::Step4));
1312  }
1313
1314  void Step4() {
1315    // The context menu should not be showing.
1316    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
1317    ASSERT_TRUE(context_menu == NULL);
1318
1319    // But the menu should be showing.
1320    views::MenuItemView* menu = bb_view_->GetMenu();
1321    ASSERT_TRUE(menu != NULL);
1322    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1323
1324    // And the deleted_menu_id_ should have been removed.
1325    ASSERT_TRUE(menu->GetMenuItemByID(deleted_menu_id_) == NULL);
1326
1327    bb_view_->GetMenu()->GetMenuController()->CancelAll();
1328
1329    Done();
1330  }
1331
1332  int deleted_menu_id_;
1333  ContextMenuNotificationObserver observer_;
1334};
1335
1336VIEW_TEST(BookmarkBarViewTest15, MenuStaysVisibleAfterDelete)
1337
1338// Tests that we don't crash or get stuck if the parent of a menu is closed.
1339class BookmarkBarViewTest16 : public BookmarkBarViewEventTestBase {
1340 protected:
1341  virtual void DoTestOnMessageLoop() {
1342    InstallViewsDelegate();
1343
1344    // Move the mouse to the first folder on the bookmark bar and press the
1345    // mouse.
1346    views::TextButton* button = bb_view_->GetBookmarkButton(0);
1347    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1348        ui_controls::DOWN | ui_controls::UP,
1349        CreateEventTask(this, &BookmarkBarViewTest16::Step2));
1350  }
1351
1352 private:
1353  void Step2() {
1354    // Menu should be showing.
1355    views::MenuItemView* menu = bb_view_->GetMenu();
1356    ASSERT_TRUE(menu != NULL);
1357    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1358
1359    // Button should be depressed.
1360    views::TextButton* button = bb_view_->GetBookmarkButton(0);
1361    ASSERT_TRUE(button->state() == views::CustomButton::BS_PUSHED);
1362
1363    // Close the window.
1364    window_->CloseWindow();
1365    window_ = NULL;
1366  }
1367};
1368
1369// Disabled, http://crbug.com/64303.
1370VIEW_TEST(BookmarkBarViewTest16, DISABLED_DeleteMenu)
1371
1372// Makes sure right clicking on an item while a context menu is already showing
1373// doesn't crash and works.
1374class BookmarkBarViewTest17 : public BookmarkBarViewEventTestBase {
1375 public:
1376  BookmarkBarViewTest17()
1377      : ALLOW_THIS_IN_INITIALIZER_LIST(
1378          observer_(CreateEventTask(this, &BookmarkBarViewTest17::Step3))) {
1379  }
1380
1381 protected:
1382  virtual void DoTestOnMessageLoop() {
1383    // Move the mouse to the other folder on the bookmark bar and press the
1384    // left mouse button.
1385    views::TextButton* button = bb_view_->other_bookmarked_button();
1386    ui_controls::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1387        ui_controls::DOWN | ui_controls::UP,
1388        CreateEventTask(this, &BookmarkBarViewTest17::Step2));
1389  }
1390
1391 private:
1392  void Step2() {
1393    // Menu should be showing.
1394    views::MenuItemView* menu = bb_view_->GetMenu();
1395    ASSERT_TRUE(menu != NULL);
1396    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1397
1398    // Right click on the second item to show its context menu.
1399    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
1400    ASSERT_TRUE(child_menu != NULL);
1401    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1402        ui_controls::DOWN | ui_controls::UP, NULL);
1403    // Step3 will be invoked by ContextMenuNotificationObserver.
1404  }
1405
1406  void Step3() {
1407    // Make sure the context menu is showing.
1408    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
1409    ASSERT_TRUE(context_menu != NULL);
1410    ASSERT_TRUE(context_menu->GetSubmenu());
1411    ASSERT_TRUE(context_menu->GetSubmenu()->IsShowing());
1412
1413    // Right click on the first menu item to trigger its context menu.
1414    views::MenuItemView* menu = bb_view_->GetMenu();
1415    ASSERT_TRUE(menu != NULL);
1416    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1417    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(1);
1418    ASSERT_TRUE(child_menu != NULL);
1419
1420    observer_.set_task(CreateEventTask(this, &BookmarkBarViewTest17::Step4));
1421    ui_controls::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1422        ui_controls::DOWN | ui_controls::UP, NULL);
1423    // Step4 will be invoked by ContextMenuNotificationObserver.
1424  }
1425
1426  void Step4() {
1427    // The context menu should still be showing.
1428    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
1429    ASSERT_TRUE(context_menu != NULL);
1430
1431    // And the menu should be showing.
1432    views::MenuItemView* menu = bb_view_->GetMenu();
1433    ASSERT_TRUE(menu != NULL);
1434    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1435
1436    bb_view_->GetMenu()->GetMenuController()->CancelAll();
1437
1438    Done();
1439  }
1440
1441  ContextMenuNotificationObserver observer_;
1442};
1443
1444VIEW_TEST(BookmarkBarViewTest17, ContextMenus3)
1445