1 // Copyright (c) 2014 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.
6 #include "web/ExternalPopupMenu.h"
8 #include "core/HTMLNames.h"
9 #include "core/frame/FrameHost.h"
10 #include "core/frame/PinchViewport.h"
11 #include "core/html/HTMLSelectElement.h"
12 #include "core/page/Page.h"
13 #include "core/rendering/RenderMenuList.h"
14 #include "core/testing/URLTestHelpers.h"
15 #include "platform/PopupMenu.h"
16 #include "platform/PopupMenuClient.h"
17 #include "public/platform/Platform.h"
18 #include "public/platform/WebUnitTestSupport.h"
19 #include "public/web/WebExternalPopupMenu.h"
20 #include "public/web/WebPopupMenuInfo.h"
21 #include "public/web/WebSettings.h"
22 #include "web/WebLocalFrameImpl.h"
23 #include "web/tests/FrameTestHelpers.h"
24 #include <gtest/gtest.h>
26 using namespace blink;
30 const size_t kListSize = 7;
32 class TestPopupMenuClient : public PopupMenuClient {
34 TestPopupMenuClient() : m_listSize(0) { }
35 virtual ~TestPopupMenuClient() { }
37 virtual void valueChanged(unsigned listIndex, bool fireEvents = true) override { }
38 virtual void selectionChanged(unsigned listIndex, bool fireEvents = true) override { }
39 virtual void selectionCleared() override { }
41 virtual String itemText(unsigned listIndex) const override { return emptyString(); }
42 virtual String itemToolTip(unsigned listIndex) const override { return emptyString(); }
43 virtual String itemAccessibilityText(unsigned listIndex) const override { return emptyString(); }
44 virtual bool itemIsEnabled(unsigned listIndex) const override { return true; }
45 virtual PopupMenuStyle itemStyle(unsigned listIndex) const override
47 FontDescription fontDescription;
48 fontDescription.setComputedSize(12.0);
49 Font font(fontDescription);
51 bool displayNone = m_displayNoneIndexSet.find(listIndex) != m_displayNoneIndexSet.end();
52 return PopupMenuStyle(Color::black, Color::white, font, true, displayNone, Length(), TextDirection(), false);
54 virtual PopupMenuStyle menuStyle() const override { return itemStyle(0); }
55 virtual LayoutUnit clientPaddingLeft() const override { return 0; }
56 virtual LayoutUnit clientPaddingRight() const override { return 0; }
57 virtual int listSize() const override { return m_listSize; }
58 virtual int selectedIndex() const override { return 0; }
59 virtual void popupDidHide() override { }
60 virtual bool itemIsSeparator(unsigned listIndex) const override { return false;}
61 virtual bool itemIsLabel(unsigned listIndex) const override { return false; }
62 virtual bool itemIsSelected(unsigned listIndex) const override { return listIndex == 0;}
63 virtual void setTextFromItem(unsigned listIndex) override { }
64 virtual bool multiple() const override { return false; }
66 void setListSize(size_t size) { m_listSize = size; }
67 void setDisplayNoneIndex(unsigned index) { m_displayNoneIndexSet.insert(index); }
70 std::set<unsigned> m_displayNoneIndexSet;
73 class ExternalPopupMenuDisplayNoneItemsTest : public testing::Test {
75 ExternalPopupMenuDisplayNoneItemsTest() { }
78 virtual void SetUp() override
80 m_popupMenuClient.setListSize(kListSize);
82 // Set the 4th an 5th items to have "display: none" property
83 m_popupMenuClient.setDisplayNoneIndex(3);
84 m_popupMenuClient.setDisplayNoneIndex(4);
87 TestPopupMenuClient m_popupMenuClient;
90 TEST_F(ExternalPopupMenuDisplayNoneItemsTest, PopupMenuInfoSizeTest)
92 WebPopupMenuInfo info;
93 ExternalPopupMenu::getPopupMenuInfo(info, m_popupMenuClient);
94 EXPECT_EQ(5U, info.items.size());
97 TEST_F(ExternalPopupMenuDisplayNoneItemsTest, IndexMappingTest)
99 // 6th indexed item in popupmenu would be the 4th item in ExternalPopupMenu,
101 EXPECT_EQ(4, ExternalPopupMenu::toExternalPopupMenuItemIndex(6, m_popupMenuClient));
102 EXPECT_EQ(6, ExternalPopupMenu::toPopupMenuItemIndex(4, m_popupMenuClient));
104 // Invalid index, methods should return -1.
105 EXPECT_EQ(-1, ExternalPopupMenu::toExternalPopupMenuItemIndex(8, m_popupMenuClient));
106 EXPECT_EQ(-1, ExternalPopupMenu::toPopupMenuItemIndex(8, m_popupMenuClient));
109 class ExternalPopupMenuWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
111 virtual WebExternalPopupMenu* createExternalPopupMenu(const WebPopupMenuInfo&, WebExternalPopupMenuClient*) override
113 return &m_mockWebExternalPopupMenu;
115 WebRect shownBounds() const
117 return m_mockWebExternalPopupMenu.shownBounds();
120 class MockWebExternalPopupMenu : public WebExternalPopupMenu {
121 virtual void show(const WebRect& bounds) override
123 m_shownBounds = bounds;
125 virtual void close() override { }
128 WebRect shownBounds() const
130 return m_shownBounds;
134 WebRect m_shownBounds;
136 WebRect m_shownBounds;
137 MockWebExternalPopupMenu m_mockWebExternalPopupMenu;
140 class ExternalPopupMenuTest : public testing::Test {
142 ExternalPopupMenuTest() : m_baseURL("http://www.test.com") { }
145 virtual void SetUp() override
147 m_helper.initialize(false, &m_webFrameClient, &m_webViewClient, &configureSettings);
148 webView()->setUseExternalPopupMenus(true);
150 virtual void TearDown() override
152 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
155 void registerMockedURLLoad(const std::string& fileName)
157 URLTestHelpers::registerMockedURLLoad(URLTestHelpers::toKURL(m_baseURL + fileName), WebString::fromUTF8(fileName.c_str()), WebString::fromUTF8("popup/"), WebString::fromUTF8("text/html"));
160 void loadFrame(const std::string& fileName)
162 FrameTestHelpers::loadFrame(mainFrame(), m_baseURL + fileName);
165 WebViewImpl* webView() const { return m_helper.webViewImpl(); }
166 const ExternalPopupMenuWebFrameClient& client() const { return m_webFrameClient; }
167 WebLocalFrameImpl* mainFrame() const { return m_helper.webViewImpl()->mainFrameImpl(); }
170 static void configureSettings(WebSettings* settings)
172 settings->setPinchVirtualViewportEnabled(true);
175 std::string m_baseURL;
176 FrameTestHelpers::TestWebViewClient m_webViewClient;
177 ExternalPopupMenuWebFrameClient m_webFrameClient;
178 FrameTestHelpers::WebViewHelper m_helper;
181 TEST_F(ExternalPopupMenuTest, PopupAccountsForPinchViewportOffset)
183 registerMockedURLLoad("select_mid_screen.html");
184 loadFrame("select_mid_screen.html");
186 webView()->resize(WebSize(100, 100));
189 HTMLSelectElement* select = toHTMLSelectElement(mainFrame()->frame()->document()->getElementById("select"));
190 RenderMenuList* menuList = toRenderMenuList(select->renderer());
191 ASSERT_TRUE(menuList);
193 PinchViewport& pinchViewport = webView()->page()->frameHost().pinchViewport();
195 IntRect rectInDocument = menuList->absoluteBoundingBoxRect();
197 webView()->setPageScaleFactor(2);
198 IntPoint scrollDelta(20, 30);
199 pinchViewport.move(scrollDelta);
201 menuList->showPopup();
203 EXPECT_EQ(rectInDocument.x() - scrollDelta.x(), client().shownBounds().x);
204 EXPECT_EQ(rectInDocument.y() - scrollDelta.y(), client().shownBounds().y);
207 TEST_F(ExternalPopupMenuTest, DidAcceptIndex)
209 registerMockedURLLoad("select.html");
210 loadFrame("select.html");
212 HTMLSelectElement* select = toHTMLSelectElement(mainFrame()->frame()->document()->getElementById("select"));
213 RenderMenuList* menuList = toRenderMenuList(select->renderer());
214 ASSERT_TRUE(menuList);
216 menuList->showPopup();
217 ASSERT_TRUE(menuList->popupIsVisible());
219 WebExternalPopupMenuClient* client = static_cast<ExternalPopupMenu*>(menuList->popup());
220 client->didAcceptIndex(2);
221 EXPECT_FALSE(menuList->popupIsVisible());
222 ASSERT_STREQ("2", menuList->text().utf8().data());
223 EXPECT_EQ(2, select->selectedIndex());
226 TEST_F(ExternalPopupMenuTest, DidAcceptIndices)
228 registerMockedURLLoad("select.html");
229 loadFrame("select.html");
231 HTMLSelectElement* select = toHTMLSelectElement(mainFrame()->frame()->document()->getElementById("select"));
232 RenderMenuList* menuList = toRenderMenuList(select->renderer());
233 ASSERT_TRUE(menuList);
235 menuList->showPopup();
236 ASSERT_TRUE(menuList->popupIsVisible());
238 WebExternalPopupMenuClient* client = static_cast<ExternalPopupMenu*>(menuList->popup());
239 int indices[] = { 2 };
240 WebVector<int> indicesVector(indices, 1);
241 client->didAcceptIndices(indicesVector);
242 EXPECT_FALSE(menuList->popupIsVisible());
243 EXPECT_STREQ("2", menuList->text().utf8().data());
244 EXPECT_EQ(2, select->selectedIndex());
247 TEST_F(ExternalPopupMenuTest, DidAcceptIndicesClearSelect)
249 registerMockedURLLoad("select.html");
250 loadFrame("select.html");
252 HTMLSelectElement* select = toHTMLSelectElement(mainFrame()->frame()->document()->getElementById("select"));
253 RenderMenuList* menuList = toRenderMenuList(select->renderer());
254 ASSERT_TRUE(menuList);
256 menuList->showPopup();
257 ASSERT_TRUE(menuList->popupIsVisible());
259 WebExternalPopupMenuClient* client = static_cast<ExternalPopupMenu*>(menuList->popup());
260 WebVector<int> indices;
261 client->didAcceptIndices(indices);
262 EXPECT_FALSE(menuList->popupIsVisible());
263 EXPECT_EQ(-1, select->selectedIndex());