Home | History | Annotate | Download | only in bookmarks
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "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 
     50 using base::ASCIIToUTF16;
     51 using content::BrowserThread;
     52 using content::OpenURLParams;
     53 using content::PageNavigator;
     54 using content::WebContents;
     55 
     56 namespace {
     57 
     58 // Waits for a views::Widget dialog to show up.
     59 class 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.
    115 class 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.
    152 class 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 
    192 void 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.
    201 class 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.
    251 class 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.
    399 class 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 
    447 VIEW_TEST(BookmarkBarViewTest1, Basic)
    448 
    449 // Brings up menu, clicks on empty space and make sure menu hides.
    450 class 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 
    507 VIEW_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.
    511 class 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 
    579 VIEW_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.
    584 class 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).
    613 class 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 
    668 VIEW_TEST(BookmarkBarViewTest4, ContextMenus)
    669 
    670 // Tests drag and drop within the same menu.
    671 class 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 
    738 VIEW_TEST(BookmarkBarViewTest5, MAYBE(DND))
    739 
    740 // Tests holding mouse down on overflow button, dragging such that menu pops up
    741 // then selecting an item.
    742 class 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 
    776 VIEW_TEST(BookmarkBarViewTest6, OpenMenuOnClickAndHold)
    777 
    778 // Tests drag and drop to different menu.
    779 class 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
    874 VIEW_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.
    879 class 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
    983 VIEW_TEST(BookmarkBarViewTest8, MAYBE(DNDBackToOriginatingMenu))
    984 #endif
    985 
    986 // Moves the mouse over the scroll button and makes sure we get scrolling.
    987 class 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 
   1055 VIEW_TEST(BookmarkBarViewTest9, ScrollButtonScrolls)
   1056 
   1057 // Tests up/down/left/enter key messages.
   1058 class 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 
   1161 VIEW_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.
   1167 class 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 
   1245 VIEW_TEST(BookmarkBarViewTest11, MAYBE_CloseMenuAfterClosingContextMenu)
   1246 
   1247 // Tests showing a modal dialog from a context menu.
   1248 class 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 
   1341 VIEW_TEST(BookmarkBarViewTest12, MAYBE_CloseWithModalDialog)
   1342 
   1343 // Tests clicking on the separator of a context menu (this is for coverage of
   1344 // bug 17862).
   1345 class 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 
   1425 VIEW_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.
   1429 class 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 
   1465 VIEW_TEST(BookmarkBarViewTest14, ContextMenus2)
   1466 
   1467 // Makes sure deleting from the context menu keeps the bookmark menu showing.
   1468 class 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 
   1542 VIEW_TEST(BookmarkBarViewTest15, MenuStaysVisibleAfterDelete)
   1543 
   1544 // Tests that we don't crash or get stuck if the parent of a menu is closed.
   1545 class 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 
   1583 VIEW_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.
   1587 class 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 
   1671 VIEW_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.
   1676 class 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 
   1729 VIEW_TEST(BookmarkBarViewTest18, MAYBE_BookmarkBarViewTest18_SiblingMenu)
   1730 
   1731 // Verifies mousing over an already open sibling menu doesn't prematurely cancel
   1732 // the menu.
   1733 class 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 
   1803 VIEW_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).
   1808 class 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 
   1910 VIEW_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.
   1914 class 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 
   1983 VIEW_TEST(BookmarkBarViewTest21, ContextMenusForEmptyFolder)
   1984