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