• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #include "include/base/cef_bind.h"
6 #include "include/views/cef_button.h"
7 #include "include/views/cef_button_delegate.h"
8 #include "include/views/cef_label_button.h"
9 #include "include/views/cef_menu_button.h"
10 #include "include/views/cef_menu_button_delegate.h"
11 #include "include/wrapper/cef_closure_task.h"
12 #include "tests/ceftests/image_util.h"
13 #include "tests/ceftests/test_handler.h"
14 #include "tests/ceftests/thread_helper.h"
15 #include "tests/ceftests/views/test_window_delegate.h"
16 #include "tests/gtest/include/gtest/gtest.h"
17 
18 #define BUTTON_TEST(name) UI_THREAD_TEST(ViewsButtonTest, name)
19 #define BUTTON_TEST_ASYNC(name) UI_THREAD_TEST_ASYNC(ViewsButtonTest, name)
20 
21 namespace {
22 
CreateIconImage()23 CefRefPtr<CefImage> CreateIconImage() {
24   CefRefPtr<CefImage> image = CefImage::CreateImage();
25   image_util::LoadIconImage(image, 1.0);
26   image_util::LoadIconImage(image, 2.0);
27   return image;
28 }
29 
30 const char kButtonText[] = "My Button";
31 
VerifyButtonStyle(CefRefPtr<CefButton> button)32 void VerifyButtonStyle(CefRefPtr<CefButton> button) {
33   // Test state.
34   EXPECT_EQ(CEF_BUTTON_STATE_NORMAL, button->GetState());
35   button->SetState(CEF_BUTTON_STATE_HOVERED);
36   EXPECT_EQ(CEF_BUTTON_STATE_HOVERED, button->GetState());
37   button->SetState(CEF_BUTTON_STATE_PRESSED);
38   EXPECT_EQ(CEF_BUTTON_STATE_PRESSED, button->GetState());
39   button->SetState(CEF_BUTTON_STATE_DISABLED);
40   EXPECT_EQ(CEF_BUTTON_STATE_DISABLED, button->GetState());
41   button->SetState(CEF_BUTTON_STATE_NORMAL);
42 
43   button->SetTooltipText("Some tooltip text");
44   button->SetAccessibleName("MyButton");
45 }
46 
VerifyLabelButtonImage(CefRefPtr<CefLabelButton> button,cef_button_state_t state,CefRefPtr<CefImage> image)47 void VerifyLabelButtonImage(CefRefPtr<CefLabelButton> button,
48                             cef_button_state_t state,
49                             CefRefPtr<CefImage> image) {
50   EXPECT_FALSE(button->GetImage(state).get()) << "state = " << state;
51   button->SetImage(state, image);
52   EXPECT_TRUE(image->IsSame(button->GetImage(state))) << "state = " << state;
53   button->SetImage(state, nullptr);
54   EXPECT_FALSE(button->GetImage(state).get()) << "state = " << state;
55 }
56 
VerifyLabelButtonStyle(CefRefPtr<CefLabelButton> button)57 void VerifyLabelButtonStyle(CefRefPtr<CefLabelButton> button) {
58   VerifyButtonStyle(button);
59 
60   // Test set/get text.
61   EXPECT_STREQ(kButtonText, button->GetText().ToString().c_str());
62   const char kText[] = "My text";
63   button->SetText(kText);
64   EXPECT_STREQ(kText, button->GetText().ToString().c_str());
65 
66   // Test images.
67   CefRefPtr<CefImage> image = CreateIconImage();
68   VerifyLabelButtonImage(button, CEF_BUTTON_STATE_NORMAL, image);
69   VerifyLabelButtonImage(button, CEF_BUTTON_STATE_HOVERED, image);
70   VerifyLabelButtonImage(button, CEF_BUTTON_STATE_PRESSED, image);
71   VerifyLabelButtonImage(button, CEF_BUTTON_STATE_DISABLED, image);
72 
73   // Test colors.
74   const cef_color_t color = CefColorSetARGB(255, 255, 0, 255);
75   button->SetTextColor(CEF_BUTTON_STATE_NORMAL, color);
76   button->SetTextColor(CEF_BUTTON_STATE_HOVERED, color);
77   button->SetTextColor(CEF_BUTTON_STATE_PRESSED, color);
78   button->SetTextColor(CEF_BUTTON_STATE_DISABLED, color);
79   button->SetEnabledTextColors(color);
80 
81   // Test alignment.
82   button->SetHorizontalAlignment(CEF_HORIZONTAL_ALIGNMENT_LEFT);
83   button->SetHorizontalAlignment(CEF_HORIZONTAL_ALIGNMENT_CENTER);
84   button->SetHorizontalAlignment(CEF_HORIZONTAL_ALIGNMENT_RIGHT);
85 
86   // Test fonts.
87   button->SetFontList("Arial, 14px");
88 
89   // Test sizes.
90   button->SetMinimumSize(CefSize(100, 100));
91   button->SetMaximumSize(CefSize(100, 100));
92 }
93 
VerifyMenuButtonStyle(CefRefPtr<CefMenuButton> button)94 void VerifyMenuButtonStyle(CefRefPtr<CefMenuButton> button) {
95   VerifyLabelButtonStyle(button);
96 }
97 
98 class EmptyMenuButtonDelegate : public CefMenuButtonDelegate {
99  public:
EmptyMenuButtonDelegate()100   EmptyMenuButtonDelegate() {}
101 
OnMenuButtonPressed(CefRefPtr<CefMenuButton> menu_button,const CefPoint & screen_point,CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock)102   void OnMenuButtonPressed(
103       CefRefPtr<CefMenuButton> menu_button,
104       const CefPoint& screen_point,
105       CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) override {
106     EXPECT_TRUE(false);  // Not reached.
107   }
108 
OnButtonPressed(CefRefPtr<CefButton> button)109   void OnButtonPressed(CefRefPtr<CefButton> button) override {
110     EXPECT_TRUE(false);  // Not reached.
111   }
112 
113  private:
114   IMPLEMENT_REFCOUNTING(EmptyMenuButtonDelegate);
115   DISALLOW_COPY_AND_ASSIGN(EmptyMenuButtonDelegate);
116 };
117 
LabelButtonStyle()118 void LabelButtonStyle() {
119   CefRefPtr<CefLabelButton> button = CefLabelButton::CreateLabelButton(
120       new EmptyMenuButtonDelegate(), kButtonText);
121   VerifyLabelButtonStyle(button);
122 }
123 
LabelButtonStyleFramelessImpl()124 void LabelButtonStyleFramelessImpl() {
125   LabelButtonStyle();
126 }
127 
MenuButtonStyle()128 void MenuButtonStyle() {
129   CefRefPtr<CefMenuButton> button = CefMenuButton::CreateMenuButton(
130       new EmptyMenuButtonDelegate(), kButtonText);
131   VerifyMenuButtonStyle(button);
132 }
133 
MenuButtonStyleFramelessImpl()134 void MenuButtonStyleFramelessImpl() {
135   MenuButtonStyle();
136 }
137 
138 }  // namespace
139 
140 // Test Button getters/setters.
141 BUTTON_TEST(LabelButtonStyleFrameless)
142 BUTTON_TEST(MenuButtonStyleFrameless)
143 
144 namespace {
145 
146 // Mouse click delay in MS.
147 const int kClickDelayMS = 100;
148 
149 const int kButtonID = 1;
150 
151 class TestButtonDelegate : public CefButtonDelegate {
152  public:
TestButtonDelegate()153   TestButtonDelegate() {}
154 
OnButtonPressed(CefRefPtr<CefButton> button)155   void OnButtonPressed(CefRefPtr<CefButton> button) override {
156     EXPECT_TRUE(button.get());
157     EXPECT_EQ(button->GetID(), kButtonID);
158 
159     // Complete the test by closing the window.
160     button->GetWindow()->Close();
161   }
162 
163  private:
164   IMPLEMENT_REFCOUNTING(TestButtonDelegate);
165   DISALLOW_COPY_AND_ASSIGN(TestButtonDelegate);
166 };
167 
ClickButton(CefRefPtr<CefWindow> window,int button_id)168 void ClickButton(CefRefPtr<CefWindow> window, int button_id) {
169   CefRefPtr<CefView> button = window->GetViewForID(button_id);
170   EXPECT_TRUE(button->AsButton());
171 
172   // Determine the middle of the button in screen coordinates.
173   const CefRect& bounds = button->GetBoundsInScreen();
174   const CefPoint& click_point =
175       CefPoint(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
176 
177   // Click the button.
178   window->SendMouseMove(click_point.x, click_point.y);
179   window->SendMouseEvents(MBT_LEFT, true, true);
180 }
181 
AddImage(CefRefPtr<CefLabelButton> button)182 void AddImage(CefRefPtr<CefLabelButton> button) {
183   CefRefPtr<CefImage> image = CreateIconImage();
184   button->SetImage(CEF_BUTTON_STATE_NORMAL, image);
185 }
186 
RunLabelButtonClick(bool with_text,bool with_image,CefRefPtr<CefWindow> window)187 void RunLabelButtonClick(bool with_text,
188                          bool with_image,
189                          CefRefPtr<CefWindow> window) {
190   CefRefPtr<CefLabelButton> button = CefLabelButton::CreateLabelButton(
191       new TestButtonDelegate(), with_text ? kButtonText : "");
192   button->SetID(kButtonID);
193 
194   EXPECT_TRUE(button->AsButton());
195   EXPECT_TRUE(button->AsButton()->AsLabelButton());
196   EXPECT_EQ(kButtonID, button->GetID());
197   EXPECT_TRUE(button->IsVisible());
198   EXPECT_FALSE(button->IsDrawn());
199 
200   if (with_text)
201     EXPECT_STREQ(kButtonText, button->GetText().ToString().c_str());
202   else
203     EXPECT_TRUE(button->GetText().empty());
204 
205   if (with_image)
206     AddImage(button);
207 
208   window->AddChildView(button);
209   window->Layout();
210 
211   EXPECT_TRUE(window->IsSame(button->GetWindow()));
212   EXPECT_TRUE(window->IsSame(button->GetParentView()));
213   EXPECT_TRUE(button->IsSame(window->GetViewForID(kButtonID)));
214   EXPECT_TRUE(button->IsVisible());
215   EXPECT_TRUE(button->IsDrawn());
216 
217   window->Show();
218 
219   // Wait a bit before trying to click the button.
220   CefPostDelayedTask(TID_UI, base::Bind(ClickButton, window, kButtonID),
221                      kClickDelayMS);
222 }
223 
LabelButtonClick(CefRefPtr<CefWaitableEvent> event,bool with_button_frame,bool with_button_text,bool with_button_image)224 void LabelButtonClick(CefRefPtr<CefWaitableEvent> event,
225                       bool with_button_frame,
226                       bool with_button_text,
227                       bool with_button_image) {
228   TestWindowDelegate::Config config;
229   config.on_window_created =
230       base::Bind(RunLabelButtonClick, with_button_text, with_button_image);
231   config.frameless = false;
232   config.close_window = false;
233   TestWindowDelegate::RunTest(event, config);
234 }
235 
LabelButtonClickFramedWithTextWithImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)236 void LabelButtonClickFramedWithTextWithImageFramelessWindowImpl(
237     CefRefPtr<CefWaitableEvent> event) {
238   LabelButtonClick(event, true, true, true);
239 }
240 
LabelButtonClickFramedWithTextNoImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)241 void LabelButtonClickFramedWithTextNoImageFramelessWindowImpl(
242     CefRefPtr<CefWaitableEvent> event) {
243   LabelButtonClick(event, true, true, false);
244 }
245 
LabelButtonClickFramedNoTextWithImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)246 void LabelButtonClickFramedNoTextWithImageFramelessWindowImpl(
247     CefRefPtr<CefWaitableEvent> event) {
248   LabelButtonClick(event, true, false, true);
249 }
250 
LabelButtonClickFramedNoTextNoImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)251 void LabelButtonClickFramedNoTextNoImageFramelessWindowImpl(
252     CefRefPtr<CefWaitableEvent> event) {
253   LabelButtonClick(event, true, false, false);
254 }
255 
LabelButtonClickFramelessWithTextWithImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)256 void LabelButtonClickFramelessWithTextWithImageFramelessWindowImpl(
257     CefRefPtr<CefWaitableEvent> event) {
258   LabelButtonClick(event, false, true, true);
259 }
260 
LabelButtonClickFramelessWithTextNoImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)261 void LabelButtonClickFramelessWithTextNoImageFramelessWindowImpl(
262     CefRefPtr<CefWaitableEvent> event) {
263   LabelButtonClick(event, false, true, false);
264 }
265 
LabelButtonClickFramelessNoTextWithImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)266 void LabelButtonClickFramelessNoTextWithImageFramelessWindowImpl(
267     CefRefPtr<CefWaitableEvent> event) {
268   LabelButtonClick(event, false, false, true);
269 }
270 
LabelButtonClickFramelessNoTextNoImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)271 void LabelButtonClickFramelessNoTextNoImageFramelessWindowImpl(
272     CefRefPtr<CefWaitableEvent> event) {
273   LabelButtonClick(event, false, false, false);
274 }
275 
276 }  // namespace
277 
278 // Test LabelButton functionality. This is primarily to exercise exposed CEF
279 // APIs and is not intended to comprehensively test button-related behavior
280 // (which we presume that Chromium is testing).
281 BUTTON_TEST_ASYNC(LabelButtonClickFramedWithTextWithImageFramelessWindow)
282 BUTTON_TEST_ASYNC(LabelButtonClickFramedWithTextNoImageFramelessWindow)
283 BUTTON_TEST_ASYNC(LabelButtonClickFramedNoTextWithImageFramelessWindow)
284 BUTTON_TEST_ASYNC(LabelButtonClickFramedNoTextNoImageFramelessWindow)
285 BUTTON_TEST_ASYNC(LabelButtonClickFramelessWithTextWithImageFramelessWindow)
286 BUTTON_TEST_ASYNC(LabelButtonClickFramelessWithTextNoImageFramelessWindow)
287 BUTTON_TEST_ASYNC(LabelButtonClickFramelessNoTextWithImageFramelessWindow)
288 BUTTON_TEST_ASYNC(LabelButtonClickFramelessNoTextNoImageFramelessWindow)
289 
290 namespace {
291 
292 const int kMenuItemID = 2;
293 const char kMenuItemLabel[] = "My Menu Item";
294 
ClickMenuItem(CefRefPtr<CefMenuButton> menu_button)295 void ClickMenuItem(CefRefPtr<CefMenuButton> menu_button) {
296   // Determine the lower-right corner of the menu button, then offset a bit to
297   // hit the first menu item.
298   const CefRect& bounds = menu_button->GetBoundsInScreen();
299   const CefPoint& click_point =
300       CefPoint(bounds.x + bounds.width + 10, bounds.y + bounds.height + 10);
301 
302   // Click the menu item.
303   CefRefPtr<CefWindow> window = menu_button->GetWindow();
304   window->SendMouseMove(click_point.x, click_point.y);
305   window->SendMouseEvents(MBT_LEFT, true, true);
306 }
307 
308 class TestMenuButtonDelegate : public CefMenuButtonDelegate,
309                                public CefMenuModelDelegate {
310  public:
TestMenuButtonDelegate()311   TestMenuButtonDelegate() {}
312 
OnMenuButtonPressed(CefRefPtr<CefMenuButton> menu_button,const CefPoint & screen_point,CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock)313   void OnMenuButtonPressed(
314       CefRefPtr<CefMenuButton> menu_button,
315       const CefPoint& screen_point,
316       CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) override {
317     window_ = menu_button->GetWindow();
318 
319     CefRefPtr<CefMenuModel> model = CefMenuModel::CreateMenuModel(this);
320     model->AddItem(kMenuItemID, kMenuItemLabel);
321 
322     // Verify color accessors.
323     for (int i = 0; i < CEF_MENU_COLOR_COUNT; ++i) {
324       cef_menu_color_type_t color_type = static_cast<cef_menu_color_type_t>(i);
325       cef_color_t color_out;
326       cef_color_t color = CefColorSetARGB(255, 255, 255, i);
327 
328       // No color set yet.
329       color_out = 1;
330       EXPECT_TRUE(model->GetColor(kMenuItemID, color_type, color_out));
331       EXPECT_EQ(0U, color_out);
332       color_out = 1;
333       EXPECT_TRUE(model->GetColorAt(0, color_type, color_out));
334       EXPECT_EQ(0U, color_out);
335       color_out = 1;
336       EXPECT_TRUE(model->GetColorAt(-1, color_type, color_out));
337       EXPECT_EQ(0U, color_out);
338 
339       // Set the default color.
340       EXPECT_TRUE(model->SetColorAt(-1, color_type, color));
341       color_out = 1;
342       EXPECT_TRUE(model->GetColorAt(-1, color_type, color_out));
343       EXPECT_EQ(color, color_out);
344 
345       // Clear the default color.
346       EXPECT_TRUE(model->SetColorAt(-1, color_type, 0));
347       color_out = 1;
348       EXPECT_TRUE(model->GetColorAt(-1, color_type, color_out));
349       EXPECT_EQ(0U, color_out);
350 
351       // Set the index color.
352       EXPECT_TRUE(model->SetColorAt(0, color_type, color));
353       color_out = 1;
354       EXPECT_TRUE(model->GetColorAt(0, color_type, color_out));
355       EXPECT_EQ(color, color_out);
356 
357       // Clear the index color.
358       EXPECT_TRUE(model->SetColorAt(0, color_type, 0));
359       color_out = 1;
360       EXPECT_TRUE(model->GetColorAt(0, color_type, color_out));
361       EXPECT_EQ(0U, color_out);
362 
363       // Set the ID color.
364       EXPECT_TRUE(model->SetColor(kMenuItemID, color_type, color));
365       color_out = 1;
366       EXPECT_TRUE(model->GetColor(kMenuItemID, color_type, color_out));
367       EXPECT_EQ(color, color_out);
368 
369       // Clear the ID color.
370       EXPECT_TRUE(model->SetColor(kMenuItemID, color_type, 0));
371       color_out = 1;
372       EXPECT_TRUE(model->GetColor(kMenuItemID, color_type, color_out));
373       EXPECT_EQ(0U, color_out);
374 
375       // Index/ID doesn't exist.
376       EXPECT_FALSE(model->SetColorAt(4, color_type, color));
377       EXPECT_FALSE(model->SetColor(4, color_type, color));
378       color_out = 1;
379       EXPECT_FALSE(model->GetColorAt(4, color_type, color_out));
380       EXPECT_FALSE(model->GetColor(4, color_type, color_out));
381       EXPECT_EQ(1U, color_out);
382     }
383 
384     // Verify font accessors.
385     const std::string& font = "Tahoma, 12px";
386     EXPECT_TRUE(model->SetFontListAt(0, font));
387     EXPECT_TRUE(model->SetFontListAt(0, CefString()));
388     EXPECT_TRUE(model->SetFontList(kMenuItemID, font));
389     EXPECT_TRUE(model->SetFontList(kMenuItemID, CefString()));
390 
391     // Index/ID doesn't exist.
392     EXPECT_FALSE(model->SetFontListAt(4, font));
393     EXPECT_FALSE(model->SetFontList(4, font));
394 
395     // Wait a bit before trying to click the menu item.
396     CefPostDelayedTask(TID_UI, base::Bind(ClickMenuItem, menu_button),
397                        kClickDelayMS);
398 
399     menu_button->ShowMenu(model, screen_point, CEF_MENU_ANCHOR_TOPLEFT);
400   }
401 
OnButtonPressed(CefRefPtr<CefButton> button)402   void OnButtonPressed(CefRefPtr<CefButton> button) override {}
403 
ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,int command_id,cef_event_flags_t event_flags)404   void ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
405                       int command_id,
406                       cef_event_flags_t event_flags) override {
407     EXPECT_TRUE(menu_model.get());
408     EXPECT_EQ(command_id, kMenuItemID);
409 
410     // Complete the test by closing the window.
411     window_->GetWindow()->Close();
412     window_ = nullptr;
413   }
414 
415  private:
416   CefRefPtr<CefWindow> window_;
417 
418   IMPLEMENT_REFCOUNTING(TestMenuButtonDelegate);
419   DISALLOW_COPY_AND_ASSIGN(TestMenuButtonDelegate);
420 };
421 
RunMenuButtonClick(bool with_text,bool with_image,CefRefPtr<CefWindow> window)422 void RunMenuButtonClick(bool with_text,
423                         bool with_image,
424                         CefRefPtr<CefWindow> window) {
425   CefRefPtr<CefMenuButton> button = CefMenuButton::CreateMenuButton(
426       new TestMenuButtonDelegate(), with_text ? kButtonText : "");
427   button->SetID(kButtonID);
428 
429   EXPECT_TRUE(button->AsButton());
430   EXPECT_TRUE(button->AsButton()->AsLabelButton());
431   EXPECT_TRUE(button->AsButton()->AsLabelButton()->AsMenuButton());
432   EXPECT_EQ(kButtonID, button->GetID());
433   EXPECT_TRUE(button->IsVisible());
434   EXPECT_FALSE(button->IsDrawn());
435 
436   if (with_text)
437     EXPECT_STREQ(kButtonText, button->GetText().ToString().c_str());
438   else
439     EXPECT_TRUE(button->GetText().empty());
440 
441   if (with_image)
442     AddImage(button);
443 
444   window->AddChildView(button);
445   window->Layout();
446 
447   EXPECT_TRUE(window->IsSame(button->GetWindow()));
448   EXPECT_TRUE(window->IsSame(button->GetParentView()));
449   EXPECT_TRUE(button->IsSame(window->GetViewForID(kButtonID)));
450   EXPECT_TRUE(button->IsVisible());
451   EXPECT_TRUE(button->IsDrawn());
452 
453   window->Show();
454 
455   // Wait a bit before trying to click the button.
456   CefPostDelayedTask(TID_UI, base::Bind(ClickButton, window, kButtonID),
457                      kClickDelayMS);
458 }
459 
MenuButtonClick(CefRefPtr<CefWaitableEvent> event,bool with_button_frame,bool with_button_text,bool with_button_image)460 void MenuButtonClick(CefRefPtr<CefWaitableEvent> event,
461                      bool with_button_frame,
462                      bool with_button_text,
463                      bool with_button_image) {
464   TestWindowDelegate::Config config;
465   config.on_window_created =
466       base::Bind(RunMenuButtonClick, with_button_text, with_button_image);
467   config.frameless = false;
468   config.close_window = false;
469   TestWindowDelegate::RunTest(event, config);
470 }
471 
MenuButtonClickFramedWithTextWithImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)472 void MenuButtonClickFramedWithTextWithImageFramelessWindowImpl(
473     CefRefPtr<CefWaitableEvent> event) {
474   MenuButtonClick(event, true, true, true);
475 }
476 
MenuButtonClickFramedWithTextNoImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)477 void MenuButtonClickFramedWithTextNoImageFramelessWindowImpl(
478     CefRefPtr<CefWaitableEvent> event) {
479   MenuButtonClick(event, true, true, false);
480 }
481 
MenuButtonClickFramedNoTextWithImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)482 void MenuButtonClickFramedNoTextWithImageFramelessWindowImpl(
483     CefRefPtr<CefWaitableEvent> event) {
484   MenuButtonClick(event, true, false, true);
485 }
486 
MenuButtonClickFramedNoTextNoImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)487 void MenuButtonClickFramedNoTextNoImageFramelessWindowImpl(
488     CefRefPtr<CefWaitableEvent> event) {
489   MenuButtonClick(event, true, false, false);
490 }
491 
MenuButtonClickFramelessWithTextWithImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)492 void MenuButtonClickFramelessWithTextWithImageFramelessWindowImpl(
493     CefRefPtr<CefWaitableEvent> event) {
494   MenuButtonClick(event, false, true, true);
495 }
496 
MenuButtonClickFramelessWithTextNoImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)497 void MenuButtonClickFramelessWithTextNoImageFramelessWindowImpl(
498     CefRefPtr<CefWaitableEvent> event) {
499   MenuButtonClick(event, false, true, false);
500 }
501 
MenuButtonClickFramelessNoTextWithImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)502 void MenuButtonClickFramelessNoTextWithImageFramelessWindowImpl(
503     CefRefPtr<CefWaitableEvent> event) {
504   MenuButtonClick(event, false, false, true);
505 }
506 
MenuButtonClickFramelessNoTextNoImageFramelessWindowImpl(CefRefPtr<CefWaitableEvent> event)507 void MenuButtonClickFramelessNoTextNoImageFramelessWindowImpl(
508     CefRefPtr<CefWaitableEvent> event) {
509   MenuButtonClick(event, false, false, false);
510 }
511 
512 }  // namespace
513 
514 // Test MenuButton functionality. This is primarily to exercise exposed CEF
515 // APIs and is not intended to comprehensively test button-related behavior
516 // (which we presume that Chromium is testing).
517 BUTTON_TEST_ASYNC(MenuButtonClickFramedWithTextWithImageFramelessWindow)
518 BUTTON_TEST_ASYNC(MenuButtonClickFramedWithTextNoImageFramelessWindow)
519 BUTTON_TEST_ASYNC(MenuButtonClickFramedNoTextWithImageFramelessWindow)
520 BUTTON_TEST_ASYNC(MenuButtonClickFramedNoTextNoImageFramelessWindow)
521 BUTTON_TEST_ASYNC(MenuButtonClickFramelessWithTextWithImageFramelessWindow)
522 BUTTON_TEST_ASYNC(MenuButtonClickFramelessWithTextNoImageFramelessWindow)
523 BUTTON_TEST_ASYNC(MenuButtonClickFramelessNoTextWithImageFramelessWindow)
524 BUTTON_TEST_ASYNC(MenuButtonClickFramelessNoTextNoImageFramelessWindow)
525 
526 namespace {
527 
528 class TestMenuButtonCustomPopupDelegate : public CefMenuButtonDelegate,
529                                           public CefWindowDelegate {
530  public:
TestMenuButtonCustomPopupDelegate(bool can_activate)531   explicit TestMenuButtonCustomPopupDelegate(bool can_activate)
532       : can_activate_(can_activate) {}
533 
OnMenuButtonPressed(CefRefPtr<CefMenuButton> menu_button,const CefPoint & screen_point,CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock)534   void OnMenuButtonPressed(
535       CefRefPtr<CefMenuButton> menu_button,
536       const CefPoint& screen_point,
537       CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) override {
538     parent_window_ = menu_button->GetWindow();
539     button_pressed_lock_ = button_pressed_lock;
540 
541     popup_window_ = CefWindow::CreateTopLevelWindow(this);
542     popup_window_->SetBounds(CefRect(screen_point.x, screen_point.y, 100, 100));
543 
544     CefRefPtr<CefLabelButton> button =
545         CefLabelButton::CreateLabelButton(this, "Button");
546     button->SetFocusable(can_activate_);
547     popup_window_->AddChildView(button);
548 
549     popup_window_->Show();
550 
551     // Wait a bit before trying to click the popup button.
552     CefPostDelayedTask(TID_UI, base::Bind(ClickMenuItem, menu_button),
553                        kClickDelayMS);
554   }
555 
OnButtonPressed(CefRefPtr<CefButton> button)556   void OnButtonPressed(CefRefPtr<CefButton> button) override {
557     EXPECT_TRUE(button->GetWindow()->IsSame(popup_window_));
558     popup_window_->Close();
559     popup_window_ = nullptr;
560     button_pressed_lock_ = nullptr;
561   }
562 
GetParentWindow(CefRefPtr<CefWindow> window,bool * is_menu,bool * can_activate_menu)563   CefRefPtr<CefWindow> GetParentWindow(CefRefPtr<CefWindow> window,
564                                        bool* is_menu,
565                                        bool* can_activate_menu) override {
566     EXPECT_TRUE(parent_window_);
567     *is_menu = true;
568     *can_activate_menu = can_activate_;
569     return parent_window_;
570   }
571 
IsFrameless(CefRefPtr<CefWindow> window)572   bool IsFrameless(CefRefPtr<CefWindow> window) override { return true; }
573 
OnFocus(CefRefPtr<CefView> view)574   void OnFocus(CefRefPtr<CefView> view) override {
575     if (popup_window_ && view->GetWindow()->IsSame(popup_window_)) {
576       EXPECT_TRUE(can_activate_);
577       got_focus_.yes();
578     }
579   }
580 
OnWindowDestroyed(CefRefPtr<CefWindow> window)581   void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
582     if (can_activate_)
583       EXPECT_TRUE(got_focus_);
584     else
585       EXPECT_FALSE(got_focus_);
586 
587     // Complete the test by closing the parent window.
588     parent_window_->Close();
589     parent_window_ = nullptr;
590   }
591 
592  private:
593   const bool can_activate_;
594 
595   CefRefPtr<CefWindow> parent_window_;
596   CefRefPtr<CefWindow> popup_window_;
597   CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock_;
598 
599   TrackCallback got_focus_;
600 
601   IMPLEMENT_REFCOUNTING(TestMenuButtonCustomPopupDelegate);
602   DISALLOW_COPY_AND_ASSIGN(TestMenuButtonCustomPopupDelegate);
603 };
604 
RunMenuButtonCustomPopupClick(bool can_activate,CefRefPtr<CefWindow> window)605 void RunMenuButtonCustomPopupClick(bool can_activate,
606                                    CefRefPtr<CefWindow> window) {
607   CefRefPtr<CefMenuButton> button = CefMenuButton::CreateMenuButton(
608       new TestMenuButtonCustomPopupDelegate(can_activate), "Custom");
609   button->SetID(kButtonID);
610 
611   window->AddChildView(button);
612   window->Layout();
613 
614   window->Show();
615 
616   // Wait a bit before trying to click the button.
617   CefPostDelayedTask(TID_UI, base::Bind(ClickButton, window, kButtonID),
618                      kClickDelayMS);
619 }
620 
MenuButtonCustomPopupClick(CefRefPtr<CefWaitableEvent> event,bool can_activate)621 void MenuButtonCustomPopupClick(CefRefPtr<CefWaitableEvent> event,
622                                 bool can_activate) {
623   TestWindowDelegate::Config config;
624   config.on_window_created =
625       base::Bind(RunMenuButtonCustomPopupClick, can_activate);
626   config.close_window = false;
627   TestWindowDelegate::RunTest(event, config);
628 }
629 
MenuButtonCustomPopupActivateImpl(CefRefPtr<CefWaitableEvent> event)630 void MenuButtonCustomPopupActivateImpl(CefRefPtr<CefWaitableEvent> event) {
631   MenuButtonCustomPopupClick(event, true);
632 }
633 
MenuButtonCustomPopupNoActivateImpl(CefRefPtr<CefWaitableEvent> event)634 void MenuButtonCustomPopupNoActivateImpl(CefRefPtr<CefWaitableEvent> event) {
635   MenuButtonCustomPopupClick(event, false);
636 }
637 
638 }  // namespace
639 
640 BUTTON_TEST_ASYNC(MenuButtonCustomPopupActivate)
641 BUTTON_TEST_ASYNC(MenuButtonCustomPopupNoActivate)
642