NaCl docs: add sanitizers to GSoC ideas
[chromium-blink-merge.git] / chrome / browser / ui / views / menu_model_adapter_test.cc
blob3ecde40e25db3c6ebe7009e69b6a15ad28d6d92a
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.
5 #include "base/callback.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "chrome/test/base/interactive_test_utils.h"
8 #include "chrome/test/base/ui_test_utils.h"
9 #include "chrome/test/base/view_event_test_base.h"
10 #include "ui/base/models/menu_model.h"
11 #include "ui/base/test/ui_controls.h"
12 #include "ui/views/controls/button/menu_button.h"
13 #include "ui/views/controls/button/menu_button_listener.h"
14 #include "ui/views/controls/menu/menu_controller.h"
15 #include "ui/views/controls/menu/menu_item_view.h"
16 #include "ui/views/controls/menu/menu_model_adapter.h"
17 #include "ui/views/controls/menu/menu_runner.h"
18 #include "ui/views/controls/menu/submenu_view.h"
19 #include "ui/views/widget/root_view.h"
20 #include "ui/views/widget/widget.h"
22 namespace {
24 const int kTopMenuBaseId = 100;
25 const int kSubMenuBaseId = 200;
27 // Implement most of the ui::MenuModel pure virtual methods for subclasses
29 // Exceptions:
30 // virtual int GetItemCount() const = 0;
31 // virtual ItemType GetTypeAt(int index) const = 0;
32 // virtual int GetCommandIdAt(int index) const = 0;
33 // virtual base::string16 GetLabelAt(int index) const = 0;
34 class CommonMenuModel : public ui::MenuModel {
35 public:
36 CommonMenuModel() {
39 ~CommonMenuModel() override {}
41 protected:
42 // ui::MenuModel implementation.
43 bool HasIcons() const override { return false; }
45 bool IsItemDynamicAt(int index) const override { return false; }
47 bool GetAcceleratorAt(int index,
48 ui::Accelerator* accelerator) const override {
49 return false;
52 ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override {
53 return ui::NORMAL_SEPARATOR;
56 bool IsItemCheckedAt(int index) const override { return false; }
58 int GetGroupIdAt(int index) const override { return 0; }
60 bool GetIconAt(int index, gfx::Image* icon) override { return false; }
62 ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override {
63 return NULL;
66 bool IsEnabledAt(int index) const override { return true; }
68 ui::MenuModel* GetSubmenuModelAt(int index) const override { return NULL; }
70 void HighlightChangedTo(int index) override {}
72 void ActivatedAt(int index) override {}
74 void SetMenuModelDelegate(ui::MenuModelDelegate* delegate) override {}
76 ui::MenuModelDelegate* GetMenuModelDelegate() const override { return NULL; }
78 private:
79 DISALLOW_COPY_AND_ASSIGN(CommonMenuModel);
82 class SubMenuModel : public CommonMenuModel {
83 public:
84 SubMenuModel()
85 : showing_(false) {
88 ~SubMenuModel() override {}
90 bool showing() const {
91 return showing_;
94 private:
95 // ui::MenuModel implementation.
96 int GetItemCount() const override { return 1; }
98 ItemType GetTypeAt(int index) const override { return TYPE_COMMAND; }
100 int GetCommandIdAt(int index) const override {
101 return index + kSubMenuBaseId;
104 base::string16 GetLabelAt(int index) const override {
105 return base::ASCIIToUTF16("Item");
108 void MenuWillShow() override { showing_ = true; }
110 // Called when the menu has been closed.
111 void MenuClosed() override { showing_ = false; }
113 bool showing_;
115 DISALLOW_COPY_AND_ASSIGN(SubMenuModel);
118 class TopMenuModel : public CommonMenuModel {
119 public:
120 TopMenuModel() {
123 ~TopMenuModel() override {}
125 bool IsSubmenuShowing() {
126 return sub_menu_model_.showing();
129 private:
130 // ui::MenuModel implementation.
131 int GetItemCount() const override { return 1; }
133 ItemType GetTypeAt(int index) const override { return TYPE_SUBMENU; }
135 int GetCommandIdAt(int index) const override {
136 return index + kTopMenuBaseId;
139 base::string16 GetLabelAt(int index) const override {
140 return base::ASCIIToUTF16("submenu");
143 MenuModel* GetSubmenuModelAt(int index) const override {
144 return &sub_menu_model_;
147 mutable SubMenuModel sub_menu_model_;
149 DISALLOW_COPY_AND_ASSIGN(TopMenuModel);
152 } // namespace
154 class MenuModelAdapterTest : public ViewEventTestBase,
155 public views::MenuButtonListener {
156 public:
157 MenuModelAdapterTest()
158 : ViewEventTestBase(),
159 button_(NULL),
160 menu_model_adapter_(&top_menu_model_),
161 menu_(NULL) {
164 ~MenuModelAdapterTest() override {}
166 // ViewEventTestBase implementation.
168 void SetUp() override {
169 button_ = new views::MenuButton(
170 NULL, base::ASCIIToUTF16("Menu Adapter Test"), this, true);
172 menu_ = menu_model_adapter_.CreateMenu();
173 menu_runner_.reset(
174 new views::MenuRunner(menu_, views::MenuRunner::HAS_MNEMONICS));
176 ViewEventTestBase::SetUp();
179 void TearDown() override {
180 menu_runner_.reset(NULL);
181 menu_ = NULL;
182 ViewEventTestBase::TearDown();
185 views::View* CreateContentsView() override { return button_; }
187 gfx::Size GetPreferredSize() const override {
188 return button_->GetPreferredSize();
191 // views::MenuButtonListener implementation.
192 void OnMenuButtonClicked(views::View* source,
193 const gfx::Point& point) override {
194 gfx::Point screen_location;
195 views::View::ConvertPointToScreen(source, &screen_location);
196 gfx::Rect bounds(screen_location, source->size());
197 ignore_result(menu_runner_->RunMenuAt(source->GetWidget(),
198 button_,
199 bounds,
200 views::MENU_ANCHOR_TOPLEFT,
201 ui::MENU_SOURCE_NONE));
204 // ViewEventTestBase implementation
205 void DoTestOnMessageLoop() override {
206 Click(button_, CreateEventTask(this, &MenuModelAdapterTest::Step1));
209 // Open the submenu.
210 void Step1() {
211 views::SubmenuView* topmenu = menu_->GetSubmenu();
212 ASSERT_TRUE(topmenu);
213 ASSERT_TRUE(topmenu->IsShowing());
214 ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());
216 // Click the first item to open the submenu.
217 views::MenuItemView* item = topmenu->GetMenuItemAt(0);
218 ASSERT_TRUE(item);
219 Click(item, CreateEventTask(this, &MenuModelAdapterTest::Step2));
222 // Rebuild the menu which should close the submenu.
223 void Step2() {
224 views::SubmenuView* topmenu = menu_->GetSubmenu();
225 ASSERT_TRUE(topmenu);
226 ASSERT_TRUE(topmenu->IsShowing());
227 ASSERT_TRUE(top_menu_model_.IsSubmenuShowing());
229 menu_model_adapter_.BuildMenu(menu_);
231 base::MessageLoopForUI::current()->PostTask(
232 FROM_HERE, CreateEventTask(this, &MenuModelAdapterTest::Step3));
235 // Verify that the submenu MenuModel received the close callback
236 // and close the menu.
237 void Step3() {
238 views::SubmenuView* topmenu = menu_->GetSubmenu();
239 ASSERT_TRUE(topmenu);
240 ASSERT_TRUE(topmenu->IsShowing());
241 ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());
243 // Click the button to exit the menu.
244 Click(button_, CreateEventTask(this, &MenuModelAdapterTest::Step4));
247 // All done.
248 void Step4() {
249 views::SubmenuView* topmenu = menu_->GetSubmenu();
250 ASSERT_TRUE(topmenu);
251 ASSERT_FALSE(topmenu->IsShowing());
252 ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());
254 Done();
257 private:
258 // Generate a mouse click on the specified view and post a new task.
259 virtual void Click(views::View* view, const base::Closure& next) {
260 ui_test_utils::MoveMouseToCenterAndPress(
261 view,
262 ui_controls::LEFT,
263 ui_controls::DOWN | ui_controls::UP,
264 next);
267 views::MenuButton* button_;
268 TopMenuModel top_menu_model_;
269 views::MenuModelAdapter menu_model_adapter_;
270 views::MenuItemView* menu_;
271 scoped_ptr<views::MenuRunner> menu_runner_;
274 VIEW_TEST(MenuModelAdapterTest, RebuildMenu)