OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2010 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 #include "config.h" | |
32 #include "platform/PopupMenu.h" | |
33 | |
34 #include "core/dom/Element.h" | |
35 #include "core/frame/FrameHost.h" | |
36 #include "core/frame/FrameView.h" | |
37 #include "core/frame/PinchViewport.h" | |
38 #include "core/frame/Settings.h" | |
39 #include "core/html/HTMLSelectElement.h" | |
40 #include "core/html/forms/PopupMenuClient.h" | |
41 #include "core/layout/LayoutMenuList.h" | |
42 #include "core/page/EventHandler.h" | |
43 #include "core/page/Page.h" | |
44 #include "platform/KeyboardCodes.h" | |
45 #include "platform/PlatformMouseEvent.h" | |
46 #include "platform/RuntimeEnabledFeatures.h" | |
47 #include "platform/graphics/Color.h" | |
48 #include "platform/scroll/ScrollbarTheme.h" | |
49 #include "platform/testing/URLTestHelpers.h" | |
50 #include "public/platform/Platform.h" | |
51 #include "public/platform/WebScreenInfo.h" | |
52 #include "public/platform/WebString.h" | |
53 #include "public/platform/WebURL.h" | |
54 #include "public/platform/WebURLRequest.h" | |
55 #include "public/platform/WebURLResponse.h" | |
56 #include "public/platform/WebUnitTestSupport.h" | |
57 #include "public/web/WebDocument.h" | |
58 #include "public/web/WebElement.h" | |
59 #include "public/web/WebFrame.h" | |
60 #include "public/web/WebFrameClient.h" | |
61 #include "public/web/WebInputEvent.h" | |
62 #include "public/web/WebSettings.h" | |
63 #include "public/web/WebView.h" | |
64 #include "public/web/WebViewClient.h" | |
65 #include "web/PopupContainer.h" | |
66 #include "web/PopupListBox.h" | |
67 #include "web/PopupMenuChromium.h" | |
68 #include "web/WebLocalFrameImpl.h" | |
69 #include "web/WebPopupMenuImpl.h" | |
70 #include "web/WebViewImpl.h" | |
71 #include "web/tests/FrameTestHelpers.h" | |
72 #include <gtest/gtest.h> | |
73 | |
74 using namespace blink; | |
75 using URLTestHelpers::toKURL; | |
76 | |
77 namespace { | |
78 | |
79 class TestPopupMenuClient : public PopupMenuClient { | |
80 public: | |
81 // Item at index 0 is selected by default. | |
82 TestPopupMenuClient() : m_selectIndex(0), m_node(0), m_listSize(10), m_index
ToSelectOnCancel(-1) { } | |
83 virtual ~TestPopupMenuClient() { } | |
84 virtual void valueChanged(unsigned listIndex, bool fireEvents = true) | |
85 { | |
86 m_selectIndex = listIndex; | |
87 if (m_node) { | |
88 HTMLSelectElement* select = toHTMLSelectElement(m_node); | |
89 select->optionSelectedByUser(select->listToOptionIndex(listIndex), f
ireEvents); | |
90 } | |
91 } | |
92 virtual void selectionChanged(unsigned, bool) { } | |
93 virtual void selectionCleared() { } | |
94 | |
95 virtual String itemText(unsigned listIndex) const | |
96 { | |
97 String str("Item "); | |
98 str.append(String::number(listIndex)); | |
99 return str; | |
100 } | |
101 virtual String itemLabel(unsigned) const { return String(); } | |
102 virtual String itemIcon(unsigned) const { return String(); } | |
103 virtual String itemToolTip(unsigned listIndex) const { return itemText(listI
ndex); } | |
104 virtual String itemAccessibilityText(unsigned listIndex) const { return item
Text(listIndex); } | |
105 virtual bool itemIsEnabled(unsigned listIndex) const { return m_disabledInde
xSet.find(listIndex) == m_disabledIndexSet.end(); } | |
106 virtual PopupMenuStyle itemStyle(unsigned listIndex) const | |
107 { | |
108 FontDescription fontDescription; | |
109 fontDescription.setComputedSize(12.0); | |
110 Font font(fontDescription); | |
111 font.update(nullptr); | |
112 return PopupMenuStyle(Color::black, Color::white, font, true, false, Len
gth(), TextDirection(), false /* has text direction override */); | |
113 } | |
114 virtual PopupMenuStyle menuStyle() const { return itemStyle(0); } | |
115 virtual LayoutUnit clientPaddingLeft() const { return 0; } | |
116 virtual LayoutUnit clientPaddingRight() const { return 0; } | |
117 virtual int listSize() const { return m_listSize; } | |
118 virtual int selectedIndex() const { return m_selectIndex; } | |
119 virtual void popupDidHide() { } | |
120 virtual void popupDidCancel() | |
121 { | |
122 if (m_indexToSelectOnCancel >= 0) | |
123 m_selectIndex = m_indexToSelectOnCancel; | |
124 } | |
125 virtual bool itemIsSeparator(unsigned listIndex) const { return false; } | |
126 virtual bool itemIsLabel(unsigned listIndex) const { return false; } | |
127 virtual bool itemIsSelected(unsigned listIndex) const { return listIndex ==
m_selectIndex; } | |
128 virtual void provisionalSelectionChanged(unsigned listIndex) { m_indexToSele
ctOnCancel = listIndex; } | |
129 virtual IntRect elementRectRelativeToViewport() const override { return IntR
ect(); } | |
130 virtual Element& ownerElement() const override { return *toElement(m_node);
} | |
131 virtual ComputedStyle* computedStyleForItem(Element& element) const override
{ return nullptr; } | |
132 | |
133 virtual FontSelector* fontSelector() const { return 0; } | |
134 virtual HostWindow* hostWindow() const { return 0; } | |
135 | |
136 virtual PassRefPtrWillBeRawPtr<Scrollbar> createScrollbar(ScrollableArea*, S
crollbarOrientation, ScrollbarControlSize) { return nullptr; } | |
137 | |
138 void setDisabledIndex(unsigned index) { m_disabledIndexSet.insert(index); } | |
139 void setFocusedNode(Node* node) { m_node = node; } | |
140 void setListSize(int listSize) { m_listSize = listSize; } | |
141 | |
142 private: | |
143 unsigned m_selectIndex; | |
144 std::set<unsigned> m_disabledIndexSet; | |
145 Node* m_node; | |
146 int m_listSize; | |
147 int m_indexToSelectOnCancel; | |
148 }; | |
149 | |
150 class TestWebWidgetClient : public WebWidgetClient { | |
151 public: | |
152 ~TestWebWidgetClient() { } | |
153 virtual WebRect windowRect() { return m_windowRect; } | |
154 virtual void setWindowRect(const WebRect& rect) { m_windowRect = rect; } | |
155 private: | |
156 WebRect m_windowRect; | |
157 }; | |
158 | |
159 class TestWebPopupMenuImpl : public WebPopupMenuImpl { | |
160 public: | |
161 static PassRefPtr<TestWebPopupMenuImpl> create(WebWidgetClient* client) | |
162 { | |
163 return adoptRef(new TestWebPopupMenuImpl(client)); | |
164 } | |
165 | |
166 ~TestWebPopupMenuImpl() { } | |
167 | |
168 private: | |
169 TestWebPopupMenuImpl(WebWidgetClient* client) : WebPopupMenuImpl(client) { } | |
170 }; | |
171 | |
172 class PopupTestWebViewClient : public FrameTestHelpers::TestWebViewClient { | |
173 public: | |
174 PopupTestWebViewClient() : m_webPopupMenu(TestWebPopupMenuImpl::create(&m_we
bWidgetClient)) { } | |
175 ~PopupTestWebViewClient() { } | |
176 | |
177 virtual WebWidget* createPopupMenu(WebPopupType) { return m_webPopupMenu.get
(); } | |
178 | |
179 // We need to override this so that the popup menu size is not 0 | |
180 // (the layout code checks to see if the popup fits on the screen). | |
181 virtual WebScreenInfo screenInfo() | |
182 { | |
183 WebScreenInfo screenInfo; | |
184 screenInfo.availableRect.height = 2000; | |
185 screenInfo.availableRect.width = 2000; | |
186 return screenInfo; | |
187 } | |
188 | |
189 WebWidgetClient* webWidgetClient() { return &m_webWidgetClient; } | |
190 | |
191 private: | |
192 TestWebWidgetClient m_webWidgetClient; | |
193 RefPtr<TestWebPopupMenuImpl> m_webPopupMenu; | |
194 }; | |
195 | |
196 class SelectPopupMenuTest : public testing::Test { | |
197 public: | |
198 SelectPopupMenuTest() | |
199 : baseURL("http://www.test.com/") | |
200 { | |
201 } | |
202 | |
203 protected: | |
204 virtual void SetUp() | |
205 { | |
206 m_helper.initialize(false, 0, &m_webviewClient); | |
207 m_popupMenu = adoptRefWillBeNoop(new PopupMenuChromium(*mainFrame()->fra
me(), &m_popupMenuClient)); | |
208 } | |
209 | |
210 virtual void TearDown() | |
211 { | |
212 m_popupMenu->disconnectClient(); | |
213 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); | |
214 } | |
215 | |
216 // Returns true if there currently is a select popup in the WebView. | |
217 bool popupOpen() const { return webView()->selectPopup(); } | |
218 | |
219 int selectedIndex() const { return m_popupMenuClient.selectedIndex(); } | |
220 | |
221 void showPopup() | |
222 { | |
223 m_popupMenu->show(FloatQuad(FloatRect(0, 0, 100, 100)), IntSize(100, 100
), 0); | |
224 ASSERT_TRUE(popupOpen()); | |
225 } | |
226 | |
227 void hidePopup() | |
228 { | |
229 m_popupMenu->hide(); | |
230 EXPECT_FALSE(popupOpen()); | |
231 } | |
232 | |
233 void simulateKeyDownEvent(int keyCode) | |
234 { | |
235 simulateKeyEvent(WebInputEvent::RawKeyDown, keyCode); | |
236 } | |
237 | |
238 void simulateKeyUpEvent(int keyCode) | |
239 { | |
240 simulateKeyEvent(WebInputEvent::KeyUp, keyCode); | |
241 } | |
242 | |
243 // Simulates a key event on the WebView. | |
244 // The WebView forwards the event to the select popup if one is open. | |
245 void simulateKeyEvent(WebInputEvent::Type eventType, int keyCode) | |
246 { | |
247 WebKeyboardEvent keyEvent; | |
248 keyEvent.windowsKeyCode = keyCode; | |
249 keyEvent.type = eventType; | |
250 webView()->handleInputEvent(keyEvent); | |
251 } | |
252 | |
253 // Simulates a mouse event on the select popup. | |
254 void simulateLeftMouseDownEvent(const IntPoint& point) | |
255 { | |
256 PlatformMouseEvent mouseEvent(point, point, LeftButton, PlatformEvent::M
ousePressed, | |
257 1, false, false, false, false, PlatformMouseEvent::RealOrIndistingui
shable, 0); | |
258 webView()->selectPopup()->handleMouseDownEvent(mouseEvent); | |
259 } | |
260 void simulateLeftMouseUpEvent(const IntPoint& point) | |
261 { | |
262 PlatformMouseEvent mouseEvent(point, point, LeftButton, PlatformEvent::M
ouseReleased, | |
263 1, false, false, false, false, PlatformMouseEvent::RealOrIndistingui
shable, 0); | |
264 webView()->selectPopup()->handleMouseReleaseEvent(mouseEvent); | |
265 } | |
266 | |
267 void registerMockedURLLoad(const std::string& fileName) | |
268 { | |
269 URLTestHelpers::registerMockedURLLoad(toKURL(baseURL + fileName), WebStr
ing::fromUTF8(fileName.c_str()), WebString::fromUTF8("popup/"), WebString::fromU
TF8("text/html")); | |
270 } | |
271 | |
272 void loadFrame(WebFrame* frame, const std::string& fileName) | |
273 { | |
274 FrameTestHelpers::loadFrame(frame, baseURL + fileName); | |
275 } | |
276 | |
277 WebViewImpl* webView() const { return m_helper.webViewImpl(); } | |
278 WebLocalFrameImpl* mainFrame() const { return m_helper.webViewImpl()->mainFr
ameImpl(); } | |
279 | |
280 protected: | |
281 PopupTestWebViewClient m_webviewClient; | |
282 TestPopupMenuClient m_popupMenuClient; | |
283 RefPtrWillBePersistent<PopupMenu> m_popupMenu; | |
284 std::string baseURL; | |
285 | |
286 private: | |
287 FrameTestHelpers::WebViewHelper m_helper; | |
288 }; | |
289 | |
290 // Tests that show/hide and repeats. Select popups are reused in web pages when | |
291 // they are reopened, that what this is testing. | |
292 TEST_F(SelectPopupMenuTest, ShowThenHide) | |
293 { | |
294 for (int i = 0; i < 3; i++) { | |
295 showPopup(); | |
296 hidePopup(); | |
297 } | |
298 } | |
299 | |
300 // Tests that showing a select popup and deleting it does not cause problem. | |
301 // This happens in real-life if a page navigates while a select popup is showing
. | |
302 TEST_F(SelectPopupMenuTest, ShowThenDelete) | |
303 { | |
304 showPopup(); | |
305 // Nothing else to do, TearDown() deletes the popup. | |
306 } | |
307 | |
308 // Tests that losing focus closes the select popup. | |
309 TEST_F(SelectPopupMenuTest, ShowThenLoseFocus) | |
310 { | |
311 showPopup(); | |
312 // Simulate losing focus. | |
313 webView()->setFocus(false); | |
314 | |
315 // Popup should have closed. | |
316 EXPECT_FALSE(popupOpen()); | |
317 } | |
318 | |
319 // Tests that pressing ESC closes the popup. | |
320 TEST_F(SelectPopupMenuTest, ShowThenPressESC) | |
321 { | |
322 showPopup(); | |
323 simulateKeyDownEvent(VKEY_ESCAPE); | |
324 // Popup should have closed. | |
325 EXPECT_FALSE(popupOpen()); | |
326 } | |
327 | |
328 // Tests selecting an item with the arrows and enter/esc/tab. | |
329 TEST_F(SelectPopupMenuTest, SelectWithKeys) | |
330 { | |
331 showPopup(); | |
332 // Simulate selecting the 2nd item by pressing Down, Down, enter. | |
333 simulateKeyDownEvent(VKEY_DOWN); | |
334 simulateKeyDownEvent(VKEY_DOWN); | |
335 simulateKeyDownEvent(VKEY_RETURN); | |
336 | |
337 // Popup should have closed. | |
338 EXPECT_TRUE(!popupOpen()); | |
339 EXPECT_EQ(2, selectedIndex()); | |
340 | |
341 // It should work as well with ESC. | |
342 showPopup(); | |
343 simulateKeyDownEvent(VKEY_DOWN); | |
344 simulateKeyDownEvent(VKEY_ESCAPE); | |
345 EXPECT_FALSE(popupOpen()); | |
346 EXPECT_EQ(3, selectedIndex()); | |
347 | |
348 // It should work as well with TAB. | |
349 showPopup(); | |
350 simulateKeyDownEvent(VKEY_DOWN); | |
351 simulateKeyDownEvent(VKEY_TAB); | |
352 EXPECT_FALSE(popupOpen()); | |
353 EXPECT_EQ(4, selectedIndex()); | |
354 } | |
355 | |
356 TEST_F(SelectPopupMenuTest, PinchZoomedIn) | |
357 { | |
358 FrameTestHelpers::loadFrame(webView()->mainFrame(), "about:blank"); | |
359 webView()->resize(WebSize(1000, 1000)); | |
360 webView()->layout(); | |
361 webView()->setPageScaleFactor(2); | |
362 webView()->page()->frameHost().pinchViewport().setLocation(IntPoint(30, 50))
; | |
363 | |
364 m_popupMenu->show(FloatQuad(FloatRect(80, 90, 100, 100)), IntSize(100, 100),
0); | |
365 | |
366 EXPECT_EQ(100, m_webviewClient.webWidgetClient()->windowRect().x); | |
367 EXPECT_EQ(280, m_webviewClient.webWidgetClient()->windowRect().y); | |
368 } | |
369 | |
370 // Tests that selecting an item with the mouse does select the item and close | |
371 // the popup. | |
372 TEST_F(SelectPopupMenuTest, ClickItem) | |
373 { | |
374 showPopup(); | |
375 | |
376 int menuItemHeight = webView()->selectPopup()->menuItemHeight(); | |
377 // menuItemHeight * 1.5 means the Y position on the item at index 1. | |
378 IntPoint row1Point(2, menuItemHeight * 1.5); | |
379 // Simulate a click down/up on the first item. | |
380 simulateLeftMouseDownEvent(row1Point); | |
381 simulateLeftMouseUpEvent(row1Point); | |
382 | |
383 // Popup should have closed and the item at index 1 selected. | |
384 EXPECT_FALSE(popupOpen()); | |
385 EXPECT_EQ(1, selectedIndex()); | |
386 } | |
387 | |
388 // Tests that moving the mouse over an item and then clicking outside the select
popup | |
389 // leaves the seleted item unchanged. | |
390 TEST_F(SelectPopupMenuTest, MouseOverItemClickOutside) | |
391 { | |
392 showPopup(); | |
393 | |
394 int menuItemHeight = webView()->selectPopup()->menuItemHeight(); | |
395 // menuItemHeight * 1.5 means the Y position on the item at index 1. | |
396 IntPoint row1Point(2, menuItemHeight * 1.5); | |
397 // Simulate the mouse moving over the first item. | |
398 PlatformMouseEvent mouseEvent(row1Point, row1Point, NoButton, PlatformEvent:
:MouseMoved, | |
399 1, false, false, false, false, PlatformMouseEvent::RealOrIndistinguishab
le, 0); | |
400 webView()->selectPopup()->handleMouseMoveEvent(mouseEvent); | |
401 | |
402 // Click outside the popup. | |
403 simulateLeftMouseDownEvent(IntPoint(1000, 1000)); | |
404 | |
405 // Popup should have closed and item 0 should still be selected. | |
406 EXPECT_FALSE(popupOpen()); | |
407 EXPECT_EQ(0, selectedIndex()); | |
408 } | |
409 | |
410 // Tests that selecting an item with the keyboard and then clicking outside the
select | |
411 // popup does select that item. | |
412 TEST_F(SelectPopupMenuTest, SelectItemWithKeyboardItemClickOutside) | |
413 { | |
414 showPopup(); | |
415 | |
416 // Simulate selecting the 2nd item by pressing Down, Down. | |
417 simulateKeyDownEvent(VKEY_DOWN); | |
418 simulateKeyDownEvent(VKEY_DOWN); | |
419 | |
420 // Click outside the popup. | |
421 simulateLeftMouseDownEvent(IntPoint(1000, 1000)); | |
422 | |
423 // Popup should have closed and the item should have been selected. | |
424 EXPECT_FALSE(popupOpen()); | |
425 EXPECT_EQ(2, selectedIndex()); | |
426 } | |
427 | |
428 TEST_F(SelectPopupMenuTest, DISABLED_SelectItemEventFire) | |
429 { | |
430 registerMockedURLLoad("select_event.html"); | |
431 webView()->settings()->setJavaScriptEnabled(true); | |
432 loadFrame(mainFrame(), "select_event.html"); | |
433 | |
434 m_popupMenuClient.setFocusedNode(mainFrame()->frame()->document()->focusedEl
ement()); | |
435 | |
436 showPopup(); | |
437 | |
438 int menuItemHeight = webView()->selectPopup()->menuItemHeight(); | |
439 // menuItemHeight * 0.5 means the Y position on the item at index 0. | |
440 IntPoint row1Point(2, menuItemHeight * 0.5); | |
441 simulateLeftMouseDownEvent(row1Point); | |
442 simulateLeftMouseUpEvent(row1Point); | |
443 | |
444 WebElement element = webView()->mainFrame()->document().getElementById("mess
age"); | |
445 | |
446 // mousedown event is held by select node, and we don't simulate the event f
or the node. | |
447 // So we can only see mouseup and click event. | |
448 EXPECT_STREQ("upclick", element.textContent().utf8().data()); | |
449 | |
450 // Disable the item at index 1. | |
451 m_popupMenuClient.setDisabledIndex(1); | |
452 | |
453 showPopup(); | |
454 // menuItemHeight * 1.5 means the Y position on the item at index 1. | |
455 row1Point.setY(menuItemHeight * 1.5); | |
456 simulateLeftMouseDownEvent(row1Point); | |
457 simulateLeftMouseUpEvent(row1Point); | |
458 | |
459 // The item at index 1 is disabled, so the text should not be changed. | |
460 EXPECT_STREQ("upclick", element.textContent().utf8().data()); | |
461 | |
462 showPopup(); | |
463 // menuItemHeight * 2.5 means the Y position on the item at index 2. | |
464 row1Point.setY(menuItemHeight * 2.5); | |
465 simulateLeftMouseDownEvent(row1Point); | |
466 simulateLeftMouseUpEvent(row1Point); | |
467 | |
468 // The item is changed to the item at index 2, from index 0, so change event
is fired. | |
469 EXPECT_STREQ("upclickchangeupclick", element.textContent().utf8().data()); | |
470 } | |
471 | |
472 TEST_F(SelectPopupMenuTest, FLAKY_SelectItemKeyEvent) | |
473 { | |
474 registerMockedURLLoad("select_event.html"); | |
475 webView()->settings()->setJavaScriptEnabled(true); | |
476 loadFrame(mainFrame(), "select_event.html"); | |
477 | |
478 m_popupMenuClient.setFocusedNode(mainFrame()->frame()->document()->focusedEl
ement()); | |
479 | |
480 showPopup(); | |
481 | |
482 // Siumulate to choose the item at index 1 with keyboard. | |
483 simulateKeyDownEvent(VKEY_DOWN); | |
484 simulateKeyDownEvent(VKEY_DOWN); | |
485 simulateKeyDownEvent(VKEY_RETURN); | |
486 | |
487 WebElement element = webView()->mainFrame()->document().getElementById("mess
age"); | |
488 // We only can see change event but no other mouse related events. | |
489 EXPECT_STREQ("change", element.textContent().utf8().data()); | |
490 } | |
491 | |
492 TEST_F(SelectPopupMenuTest, SelectItemRemoveSelectOnChange) | |
493 { | |
494 // Make sure no crash, even if select node is removed on 'change' event hand
ler. | |
495 registerMockedURLLoad("select_event_remove_on_change.html"); | |
496 webView()->settings()->setJavaScriptEnabled(true); | |
497 loadFrame(mainFrame(), "select_event_remove_on_change.html"); | |
498 | |
499 m_popupMenuClient.setFocusedNode(mainFrame()->frame()->document()->focusedEl
ement()); | |
500 | |
501 showPopup(); | |
502 | |
503 int menuItemHeight = webView()->selectPopup()->menuItemHeight(); | |
504 // menuItemHeight * 1.5 means the Y position on the item at index 1. | |
505 IntPoint row1Point(2, menuItemHeight * 1.5); | |
506 simulateLeftMouseDownEvent(row1Point); | |
507 simulateLeftMouseUpEvent(row1Point); | |
508 | |
509 WebElement element = webView()->mainFrame()->document().getElementById("mess
age"); | |
510 EXPECT_STREQ("change", element.textContent().utf8().data()); | |
511 } | |
512 | |
513 TEST_F(SelectPopupMenuTest, SelectItemRemoveSelectOnClick) | |
514 { | |
515 // Make sure no crash, even if select node is removed on 'click' event handl
er. | |
516 registerMockedURLLoad("select_event_remove_on_click.html"); | |
517 webView()->settings()->setJavaScriptEnabled(true); | |
518 loadFrame(mainFrame(), "select_event_remove_on_click.html"); | |
519 | |
520 m_popupMenuClient.setFocusedNode(mainFrame()->frame()->document()->focusedEl
ement()); | |
521 | |
522 showPopup(); | |
523 | |
524 int menuItemHeight = webView()->selectPopup()->menuItemHeight(); | |
525 // menuItemHeight * 1.5 means the Y position on the item at index 1. | |
526 IntPoint row1Point(2, menuItemHeight * 1.5); | |
527 simulateLeftMouseDownEvent(row1Point); | |
528 simulateLeftMouseUpEvent(row1Point); | |
529 | |
530 WebElement element = webView()->mainFrame()->document().getElementById("mess
age"); | |
531 EXPECT_STREQ("click", element.textContent().utf8().data()); | |
532 } | |
533 | |
534 #if OS(ANDROID) | |
535 TEST_F(SelectPopupMenuTest, DISABLED_PopupListBoxWithOverlayScrollbarEnabled) | |
536 #else | |
537 TEST_F(SelectPopupMenuTest, PopupListBoxWithOverlayScrollbarEnabled) | |
538 #endif | |
539 { | |
540 Settings::setMockScrollbarsEnabled(true); | |
541 RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true); | |
542 EXPECT_TRUE(ScrollbarTheme::theme()->usesOverlayScrollbars()); | |
543 registerMockedURLLoad("select_rtl.html"); | |
544 loadFrame(mainFrame(), "select_rtl.html"); | |
545 | |
546 m_popupMenuClient.setFocusedNode(mainFrame()->frame()->document()->focusedEl
ement()); | |
547 m_popupMenuClient.setListSize(30); | |
548 | |
549 showPopup(); | |
550 PopupContainer* container = webView()->selectPopup(); | |
551 PopupListBox* listBox = container->listBox(); | |
552 | |
553 EXPECT_EQ(container->width(), listBox->contentsSize().width() + 2); | |
554 Settings::setMockScrollbarsEnabled(false); | |
555 RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(false); | |
556 EXPECT_FALSE(ScrollbarTheme::theme()->usesOverlayScrollbars()); | |
557 } | |
558 | |
559 #if OS(ANDROID) | |
560 TEST_F(SelectPopupMenuTest, DISABLED_PopupListBoxWithOverlayScrollbarDisabled) | |
561 #else | |
562 TEST_F(SelectPopupMenuTest, PopupListBoxWithOverlayScrollbarDisabled) | |
563 #endif | |
564 { | |
565 EXPECT_FALSE(ScrollbarTheme::theme()->usesOverlayScrollbars()); | |
566 registerMockedURLLoad("select_rtl.html"); | |
567 loadFrame(mainFrame(), "select_rtl.html"); | |
568 | |
569 m_popupMenuClient.setFocusedNode(mainFrame()->frame()->document()->focusedEl
ement()); | |
570 m_popupMenuClient.setListSize(30); | |
571 | |
572 showPopup(); | |
573 PopupContainer* container = webView()->selectPopup(); | |
574 PopupListBox* listBox = container->listBox(); | |
575 | |
576 EXPECT_EQ(container->width(), listBox->contentsSize().width() + ScrollbarThe
me::theme()->scrollbarThickness() + 2); | |
577 } | |
578 | |
579 class SelectPopupMenuStyleTest : public testing::Test { | |
580 public: | |
581 SelectPopupMenuStyleTest() | |
582 : baseURL("http://www.test.com/") | |
583 { | |
584 } | |
585 | |
586 protected: | |
587 virtual void SetUp() override | |
588 { | |
589 m_helper.initialize(false, 0, &m_webviewClient); | |
590 } | |
591 | |
592 virtual void TearDown() override | |
593 { | |
594 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); | |
595 } | |
596 | |
597 // Returns true if there currently is a select popup in the WebView. | |
598 bool popupOpen() const { return webView()->selectPopup(); } | |
599 | |
600 void registerMockedURLLoad(const std::string& fileName) | |
601 { | |
602 URLTestHelpers::registerMockedURLLoad(toKURL(baseURL + fileName), WebStr
ing::fromUTF8(fileName.c_str()), WebString::fromUTF8("popup/"), WebString::fromU
TF8("text/html")); | |
603 } | |
604 | |
605 void loadFrame(WebFrame* frame, const std::string& fileName) | |
606 { | |
607 FrameTestHelpers::loadFrame(frame, baseURL + fileName); | |
608 } | |
609 | |
610 WebViewImpl* webView() const { return m_helper.webViewImpl(); } | |
611 WebLocalFrameImpl* mainFrame() const { return m_helper.webViewImpl()->mainFr
ameImpl(); } | |
612 | |
613 protected: | |
614 PopupTestWebViewClient m_webviewClient; | |
615 std::string baseURL; | |
616 | |
617 private: | |
618 FrameTestHelpers::WebViewHelper m_helper; | |
619 }; | |
620 | |
621 #if OS(MACOSX) || OS(ANDROID) | |
622 TEST_F(SelectPopupMenuStyleTest, DISABLED_PopupListBoxRTLRowWidth) | |
623 #else | |
624 TEST_F(SelectPopupMenuStyleTest, PopupListBoxRTLRowWidth) | |
625 #endif | |
626 { | |
627 RuntimeEnabledFeatures::setHTMLPopupMenuEnabled(false); | |
628 registerMockedURLLoad("select_rtl_width.html"); | |
629 loadFrame(mainFrame(), "select_rtl_width.html"); | |
630 HTMLSelectElement* select = toHTMLSelectElement(mainFrame()->frame()->docume
nt()->focusedElement()); | |
631 LayoutMenuList* menuList = toLayoutMenuList(select->layoutObject()); | |
632 ASSERT(menuList); | |
633 menuList->showPopup(); | |
634 ASSERT(popupOpen()); | |
635 PopupListBox* listBox = webView()->selectPopup()->listBox(); | |
636 int ltrWidth = listBox->getRowBaseWidth(0); | |
637 int rtlWidth = listBox->getRowBaseWidth(1); | |
638 EXPECT_LT(rtlWidth, ltrWidth); | |
639 } | |
640 | |
641 } // namespace | |
OLD | NEW |