Index: third_party/WebKit/Source/core/html/HTMLInputElementTest.cpp |
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElementTest.cpp b/third_party/WebKit/Source/core/html/HTMLInputElementTest.cpp |
index 7ef7a1cc5d89de236a49987cc3d2bbe1bb7b8b59..1d74864c46b58a179b4463d9d89600f83d07b189 100644 |
--- a/third_party/WebKit/Source/core/html/HTMLInputElementTest.cpp |
+++ b/third_party/WebKit/Source/core/html/HTMLInputElementTest.cpp |
@@ -5,6 +5,7 @@ |
#include "core/html/HTMLInputElement.h" |
#include "core/dom/Document.h" |
+#include "core/dom/IntersectionObserverController.h" |
#include "core/frame/FrameHost.h" |
#include "core/frame/FrameView.h" |
#include "core/frame/VisualViewport.h" |
@@ -13,6 +14,7 @@ |
#include "core/html/HTMLHtmlElement.h" |
#include "core/html/HTMLOptionElement.h" |
#include "core/html/forms/DateTimeChooser.h" |
+#include "core/loader/EmptyClients.h" |
#include "core/testing/DummyPageHolder.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include <memory> |
@@ -165,4 +167,119 @@ TEST_F(HTMLInputElementTest, DateTimeChooserSizeParamRespectsScale) |
EXPECT_EQ(IntRect(16, 16, 400, 100), params.anchorRectInScreen); |
} |
+class TestPasswordChromeClient : public EmptyChromeClient { |
+public: |
+ static TestPasswordChromeClient* create() { return new TestPasswordChromeClient; } |
+ ~TestPasswordChromeClient() override {} |
+ void passwordFieldBecameVisible(HTMLInputElement&) override { m_passwordFieldVisibleCalled = true; } |
+ bool passwordFieldVisibleCalled() { return m_passwordFieldVisibleCalled; } |
+private: |
+ bool m_passwordFieldVisibleCalled = false; |
+}; |
+ |
+// Tests that ChromeClient::passwordFieldBecameVisible() is called when |
+// a visible password field appears on the page. |
+TEST_F(HTMLInputElementTest, PasswordVisibilityObserver) |
+{ |
+ Page::PageClients pageClients; |
+ fillWithEmptyClients(pageClients); |
+ TestPasswordChromeClient* chromeClientUnowned = TestPasswordChromeClient::create(); |
+ pageClients.chromeClient = chromeClientUnowned; |
+ |
+ std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(2000, 2000), &pageClients); |
+ pageHolder->document().body()->setInnerHTML("<input type='password'>", ASSERT_NO_EXCEPTION); |
+ pageHolder->document().view()->updateAllLifecyclePhases(); |
+ |
+ // Force the intersection observer callback to fire synchronously. |
+ ASSERT_TRUE(pageHolder->document().intersectionObserverController()); |
+ pageHolder->document().intersectionObserverController()->deliverIntersectionObservations(); |
+ |
+ EXPECT_TRUE(chromeClientUnowned->passwordFieldVisibleCalled()); |
+} |
+ |
+// Tests that ChromeClient::passwordFieldBecameVisible() is called when |
+// a previously invisible password field becomes visible. |
+TEST_F(HTMLInputElementTest, InvisiblePasswordFieldBecomesVisible) |
+{ |
+ Page::PageClients pageClients; |
+ fillWithEmptyClients(pageClients); |
+ TestPasswordChromeClient* chromeClientUnowned = TestPasswordChromeClient::create(); |
+ pageClients.chromeClient = chromeClientUnowned; |
+ |
+ std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(2000, 2000), &pageClients); |
+ pageHolder->document().body()->setInnerHTML("<input type='password' style='display:none;'>", ASSERT_NO_EXCEPTION); |
+ pageHolder->document().view()->updateAllLifecyclePhases(); |
+ |
+ // Force the intersection observer callback to fire synchronously. |
+ ASSERT_TRUE(pageHolder->document().intersectionObserverController()); |
+ pageHolder->document().intersectionObserverController()->deliverIntersectionObservations(); |
+ |
+ // The callback should not fire for a hidden password field. |
+ EXPECT_FALSE(chromeClientUnowned->passwordFieldVisibleCalled()); |
+ |
+ // Now make the previously invisible password field visible. |
+ HTMLInputElement* input = toHTMLInputElement(pageHolder->document().body()->firstChild()); |
+ input->setAttribute("style", "", ASSERT_NO_EXCEPTION); |
+ pageHolder->document().view()->updateAllLifecyclePhases(); |
+ pageHolder->document().intersectionObserverController()->deliverIntersectionObservations(); |
+ EXPECT_TRUE(chromeClientUnowned->passwordFieldVisibleCalled()); |
+} |
+ |
+// Tests that ChromeClient::passwordFieldBecameVisible() is called when |
+// a previously non-password field becomes a password field. |
+TEST_F(HTMLInputElementTest, NonPasswordFieldBecomesPassword) |
+{ |
+ Page::PageClients pageClients; |
+ fillWithEmptyClients(pageClients); |
+ TestPasswordChromeClient* chromeClientUnowned = TestPasswordChromeClient::create(); |
+ pageClients.chromeClient = chromeClientUnowned; |
+ |
+ std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(2000, 2000), &pageClients); |
+ pageHolder->document().body()->setInnerHTML("<input type='text'>", ASSERT_NO_EXCEPTION); |
+ pageHolder->document().view()->updateAllLifecyclePhases(); |
+ |
+ // With no password field on the page, an intersection observer has |
+ // not been created and the document does not have an |
+ // intersectionObserverController(). |
+ EXPECT_FALSE(pageHolder->document().intersectionObserverController()); |
+ EXPECT_FALSE(chromeClientUnowned->passwordFieldVisibleCalled()); |
+ |
+ // Now make the previously non-password field a password field. |
+ HTMLInputElement* input = toHTMLInputElement(pageHolder->document().body()->firstChild()); |
+ input->setType("password"); |
+ pageHolder->document().view()->updateAllLifecyclePhases(); |
+ ASSERT_TRUE(pageHolder->document().intersectionObserverController()); |
+ pageHolder->document().intersectionObserverController()->deliverIntersectionObservations(); |
+ EXPECT_TRUE(chromeClientUnowned->passwordFieldVisibleCalled()); |
+} |
+ |
+// Tests that ChromeClient::passwordFieldBecameVisible() is *not* called |
+// when a previously invisible password field becomes a visible |
+// non-password field. |
+TEST_F(HTMLInputElementTest, InvisiblePasswordFieldBecomesVisibleNonPasswordField) |
+{ |
+ Page::PageClients pageClients; |
+ fillWithEmptyClients(pageClients); |
+ TestPasswordChromeClient* chromeClientUnowned = TestPasswordChromeClient::create(); |
+ pageClients.chromeClient = chromeClientUnowned; |
+ |
+ std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(2000, 2000), &pageClients); |
+ pageHolder->document().body()->setInnerHTML("<input type='password' style='display:none;'>", ASSERT_NO_EXCEPTION); |
+ pageHolder->document().view()->updateAllLifecyclePhases(); |
+ |
+ ASSERT_TRUE(pageHolder->document().intersectionObserverController()); |
+ pageHolder->document().intersectionObserverController()->deliverIntersectionObservations(); |
+ EXPECT_FALSE(chromeClientUnowned->passwordFieldVisibleCalled()); |
+ |
+ // Now make the previously invisible password field a visible non-password field. |
+ HTMLInputElement* input = toHTMLInputElement(pageHolder->document().body()->firstChild()); |
+ input->setType("text"); |
+ input->setAttribute("style", "", ASSERT_NO_EXCEPTION); |
+ pageHolder->document().view()->updateAllLifecyclePhases(); |
+ |
+ ASSERT_TRUE(pageHolder->document().intersectionObserverController()); |
+ pageHolder->document().intersectionObserverController()->deliverIntersectionObservations(); |
+ EXPECT_FALSE(chromeClientUnowned->passwordFieldVisibleCalled()); |
+} |
+ |
} // namespace blink |