Add support of setPasswordEchoEnabled and setPasswordEchoDuration for password echo feature
https://bugs.webkit.org/show_bug.cgi?id=66052
Patch by Chang Shu <cshu@webkit.org> on 2011-08-18
Reviewed by Alexey Proskuryakov.
Source/WebCore:
Added runtime settings in WebCore.
Added support in window.internals for testing.
Tests: editing/input/password-echo-passnode.html
editing/input/password-echo-passnode2.html
editing/input/password-echo-passnode3.html
editing/input/password-echo-textnode.html
* page/Settings.cpp:
(WebCore::Settings::Settings):
* page/Settings.h:
(WebCore::Settings::setPasswordEchoEnabled):
(WebCore::Settings::passwordEchoEnabled):
(WebCore::Settings::setPasswordEchoDurationInSeconds):
(WebCore::Settings::passwordEchoDurationInSeconds):
* testing/Internals.cpp:
(WebCore::Internals::Internals):
(WebCore::Internals::setPasswordEchoEnabled):
(WebCore::Internals::setPasswordEchoDurationInSeconds):
(WebCore::Internals::reset):
* testing/Internals.h:
* testing/Internals.idl:
Source/WebKit/qt:
Enable password echo under the build flag.
* Api/qwebsettings.cpp:
(QWebSettingsPrivate::apply):
LayoutTests:
Added tests.
* editing/input/password-echo-passnode-expected.txt: Added.
* editing/input/password-echo-passnode.html: Added.
* editing/input/password-echo-passnode2-expected.txt: Added.
* editing/input/password-echo-passnode2.html: Added.
* editing/input/password-echo-passnode3-expected.txt: Added.
* editing/input/password-echo-passnode3.html: Added.
* editing/input/password-echo-textnode-expected.txt: Added.
* editing/input/password-echo-textnode.html: Added.
* editing/input/resources: Added.
* editing/input/resources/password-echo.js: Added.
(secureChar):
(secureText):
(log):
(assert):
(run.else):
(run):
(init):
* platform/wk2/Skipped: No support yet.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@93291 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 302e54b..30dd7c3 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,31 @@
+2011-08-18 Chang Shu <cshu@webkit.org>
+
+ Add support of setPasswordEchoEnabled and setPasswordEchoDuration for password echo feature
+ https://bugs.webkit.org/show_bug.cgi?id=66052
+
+ Reviewed by Alexey Proskuryakov.
+
+ Added tests.
+
+ * editing/input/password-echo-passnode-expected.txt: Added.
+ * editing/input/password-echo-passnode.html: Added.
+ * editing/input/password-echo-passnode2-expected.txt: Added.
+ * editing/input/password-echo-passnode2.html: Added.
+ * editing/input/password-echo-passnode3-expected.txt: Added.
+ * editing/input/password-echo-passnode3.html: Added.
+ * editing/input/password-echo-textnode-expected.txt: Added.
+ * editing/input/password-echo-textnode.html: Added.
+ * editing/input/resources: Added.
+ * editing/input/resources/password-echo.js: Added.
+ (secureChar):
+ (secureText):
+ (log):
+ (assert):
+ (run.else):
+ (run):
+ (init):
+ * platform/wk2/Skipped: No support yet.
+
2011-08-18 Wyatt Carss <wcarss@chromium.org>
Selecting all and inserting text into a page with a frameset leads to a NULL ptr
diff --git a/LayoutTests/editing/input/password-echo-passnode-expected.txt b/LayoutTests/editing/input/password-echo-passnode-expected.txt
new file mode 100644
index 0000000..1b199f2
--- /dev/null
+++ b/LayoutTests/editing/input/password-echo-passnode-expected.txt
@@ -0,0 +1,6 @@
+Tests if input chars are secured correctly
+
+Error: secured right after. expected=false, actual=true
+Success: secured after delay. expected=true, actual=true
+Error: secured right after. expected=false, actual=true
+Success: secured after delay. expected=true, actual=true
diff --git a/LayoutTests/editing/input/password-echo-passnode.html b/LayoutTests/editing/input/password-echo-passnode.html
new file mode 100644
index 0000000..c9141f4
--- /dev/null
+++ b/LayoutTests/editing/input/password-echo-passnode.html
@@ -0,0 +1,16 @@
+<html>
+<script src="resources/password-echo.js" language="JavaScript" type="text/JavaScript" ></script>
+<script language="javascript" type="text/javascript">
+var mytests = [
+ //format: [preedit1, preedit2,...,commit_text], secured_right_after?, secured_after_delay? check?
+ [['a'], false, true, true], // test password (when only 1 char) is only secured after a delay(regular).
+ [['2','2','b'], false, true, true], // test password (when only 1 char) is only secured after a delay(ime).
+ ];
+</script>
+<body onload=init(mytests)>
+
+<p>Tests if input chars are secured correctly
+<input type='password' id='testnode' />
+<ul id="console"></ul>
+</body>
+</html>
diff --git a/LayoutTests/editing/input/password-echo-passnode2-expected.txt b/LayoutTests/editing/input/password-echo-passnode2-expected.txt
new file mode 100644
index 0000000..1b199f2
--- /dev/null
+++ b/LayoutTests/editing/input/password-echo-passnode2-expected.txt
@@ -0,0 +1,6 @@
+Tests if input chars are secured correctly
+
+Error: secured right after. expected=false, actual=true
+Success: secured after delay. expected=true, actual=true
+Error: secured right after. expected=false, actual=true
+Success: secured after delay. expected=true, actual=true
diff --git a/LayoutTests/editing/input/password-echo-passnode2.html b/LayoutTests/editing/input/password-echo-passnode2.html
new file mode 100644
index 0000000..fd1ebf8
--- /dev/null
+++ b/LayoutTests/editing/input/password-echo-passnode2.html
@@ -0,0 +1,18 @@
+<html>
+<script src="resources/password-echo.js" language="JavaScript" type="text/JavaScript" ></script>
+<script language="javascript" type="text/javascript">
+var mytests = [
+ //format: [preedit1, preedit2,...,commit_text], secured_right_after?, secured_after_delay? check?
+ [['a'], false, true, false],
+ [['f'], false, true, true], // test password (when more than 1 char) is only secured after a delay(regular).
+ [['3','3','3','f'], false, true, true], // test password (when more than 1 char) is only secured after a delay(ime).
+ ];
+</script>
+<body onload=init(mytests)>
+
+<p>Tests if input chars are secured correctly
+<input type='password' id='testnode' />
+<ul id="console"></ul>
+</body>
+</html>
+
diff --git a/LayoutTests/editing/input/password-echo-passnode3-expected.txt b/LayoutTests/editing/input/password-echo-passnode3-expected.txt
new file mode 100644
index 0000000..65b5e0b
--- /dev/null
+++ b/LayoutTests/editing/input/password-echo-passnode3-expected.txt
@@ -0,0 +1,4 @@
+Tests if input chars are secured correctly
+
+Success: secured right after. expected=true, actual=true
+Success: secured after delay. expected=true, actual=true
diff --git a/LayoutTests/editing/input/password-echo-passnode3.html b/LayoutTests/editing/input/password-echo-passnode3.html
new file mode 100644
index 0000000..16cae81
--- /dev/null
+++ b/LayoutTests/editing/input/password-echo-passnode3.html
@@ -0,0 +1,17 @@
+<html>
+<script src="resources/password-echo.js" language="JavaScript" type="text/JavaScript" ></script>
+<script language="javascript" type="text/javascript">
+var mytests = [
+ //format: [preedit1, preedit2,...,commit_text], secured_right_after?, secured_after_delay? check?
+ [['a'], false, true, false],
+ [['3','3','3','f'], false, true, false],
+ [['backspace'], true, true, true], // test password is secured all the time when deleting.
+ ];
+</script>
+<body onload=init(mytests)>
+
+<p>Tests if input chars are secured correctly
+<input type='password' id='testnode' />
+<ul id="console"></ul>
+</body>
+</html>
diff --git a/LayoutTests/editing/input/password-echo-textnode-expected.txt b/LayoutTests/editing/input/password-echo-textnode-expected.txt
new file mode 100644
index 0000000..5eb64f4
--- /dev/null
+++ b/LayoutTests/editing/input/password-echo-textnode-expected.txt
@@ -0,0 +1,6 @@
+Test text input is never secured.
+
+Success: secured right after. expected=false, actual=false
+Success: secured after delay. expected=false, actual=false
+Success: secured right after. expected=false, actual=false
+Success: secured after delay. expected=false, actual=false
diff --git a/LayoutTests/editing/input/password-echo-textnode.html b/LayoutTests/editing/input/password-echo-textnode.html
new file mode 100644
index 0000000..647a8ad
--- /dev/null
+++ b/LayoutTests/editing/input/password-echo-textnode.html
@@ -0,0 +1,17 @@
+<html>
+<script src="resources/password-echo.js" language="JavaScript" type="text/JavaScript" ></script>
+<script language="javascript" type="text/javascript">
+var mytests = [
+ //format: [preedit1, preedit2,...,commit_text], secured_right_after?, secured_after_delay? check?
+ [['a'], false, false, true], // test text input is never secured, (regular input).
+ [['2','2','b'], false, false, true], // test text input is never secured (ime input).
+ ];
+</script>
+<body onload=init(mytests)>
+
+<p>Test text input is never secured.
+<input type='text' id='testnode' />
+<ul id="console"></ul>
+</body>
+</html>
+
diff --git a/LayoutTests/editing/input/resources/password-echo.js b/LayoutTests/editing/input/resources/password-echo.js
new file mode 100644
index 0000000..afaf872
--- /dev/null
+++ b/LayoutTests/editing/input/resources/password-echo.js
@@ -0,0 +1,89 @@
+var testnode;
+
+function secureChar()
+{
+ var element = testnode;
+ var securechar = document.defaultView.getComputedStyle(element, "").getPropertyValue("-webkit-text-security");
+ switch(securechar) {
+ case "square":
+ return String.fromCharCode(0x25A0);
+ case "disc":
+ return String.fromCharCode(0x2022);
+ case "circle":
+ return String.fromCharCode(0x25E6);
+ }
+}
+
+function secureText(textLength)
+{
+ var text = "";
+ for (var counter = 0; counter < textLength; counter++)
+ text += secureChar();
+ return text;
+}
+
+function log(msg)
+{
+ var console = document.getElementById("console");
+ var li = document.createElement("li");
+ li.appendChild(document.createTextNode(msg));
+ console.appendChild(li);
+}
+
+function assert(expected, actual, msg)
+{
+ if (expected != actual)
+ log("Error: " + msg + " expected=" + expected + ", actual=" + actual);
+ else
+ log("Success: " + msg + " expected=" + expected + ", actual=" + actual);
+}
+
+function run(tests, testIdx)
+{
+ var expectedSecureTextLen;
+ if (testIdx >= 0) {
+ textInputController.doCommand("moveForward:");
+ if(tests[testIdx][3])
+ assert(tests[testIdx][2], window.find(secureText(testnode.value.length), false, true), "secured after delay.");
+ }
+ testIdx++;
+ if (testIdx >= tests.length) {
+ layoutTestController.notifyDone();
+ return;
+ }
+
+ testnode.focus();
+ textInputController.doCommand("moveForward:");
+
+ var charSequence = tests[testIdx][0];
+ for (var i = 0; i < charSequence.length - 1; i++) {
+ textInputController.setMarkedText(charSequence[i], testnode.value.length, testnode.value.length);
+ }
+ if (charSequence[charSequence.length - 1] == "backspace")
+ textInputController.doCommand("deleteBackward:");
+ else
+ textInputController.insertText(charSequence[charSequence.length - 1]);
+
+ if(tests[testIdx][3])
+ assert(tests[testIdx][1], window.find(secureText(testnode.value.length), false, true), "secured right after.");
+
+ if(tests[testIdx][3])
+ window.setTimeout(function(){ run(tests, testIdx); }, 600);
+ else
+ window.setTimeout(function(){ run(tests, testIdx); }, 0);
+}
+
+function init(tests)
+{
+ if (window.layoutTestController && window.textInputController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+ if (window.internals) {
+ window.internals.setPasswordEchoEnabled(document, true);
+ window.internals.setPasswordEchoDurationInSeconds(document, 0.1);
+ testnode = document.getElementById('testnode');
+ run(tests, -1);
+ }
+ }
+}
+
diff --git a/LayoutTests/platform/wk2/Skipped b/LayoutTests/platform/wk2/Skipped
index c9d51ea..2d49a52 100644
--- a/LayoutTests/platform/wk2/Skipped
+++ b/LayoutTests/platform/wk2/Skipped
@@ -1850,6 +1850,13 @@
# missing window.internals.createShadowContentElement
fast/dom/shadow/create-content-element.html
+# WebKitTestRunner needs layoutTestController.setPasswordEchoEnabled
+# WebKitTestRunner needs layoutTestController.setPasswordEchoDuration
+editing/input/password-echo-passnode.html
+editing/input/password-echo-passnode2.html
+editing/input/password-echo-passnode3.html
+editing/input/password-echo-textnode.html
+
### END OF (2) Classified failures without bug reports (yet)
########################################
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index c172c32..83f641b 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,33 @@
+2011-08-18 Chang Shu <cshu@webkit.org>
+
+ Add support of setPasswordEchoEnabled and setPasswordEchoDuration for password echo feature
+ https://bugs.webkit.org/show_bug.cgi?id=66052
+
+ Reviewed by Alexey Proskuryakov.
+
+ Added runtime settings in WebCore.
+ Added support in window.internals for testing.
+
+ Tests: editing/input/password-echo-passnode.html
+ editing/input/password-echo-passnode2.html
+ editing/input/password-echo-passnode3.html
+ editing/input/password-echo-textnode.html
+
+ * page/Settings.cpp:
+ (WebCore::Settings::Settings):
+ * page/Settings.h:
+ (WebCore::Settings::setPasswordEchoEnabled):
+ (WebCore::Settings::passwordEchoEnabled):
+ (WebCore::Settings::setPasswordEchoDurationInSeconds):
+ (WebCore::Settings::passwordEchoDurationInSeconds):
+ * testing/Internals.cpp:
+ (WebCore::Internals::Internals):
+ (WebCore::Internals::setPasswordEchoEnabled):
+ (WebCore::Internals::setPasswordEchoDurationInSeconds):
+ (WebCore::Internals::reset):
+ * testing/Internals.h:
+ * testing/Internals.idl:
+
2011-08-18 Wyatt Carss <wcarss@chromium.org>
Selecting all and inserting text into a page with a frameset leads to a NULL ptr
diff --git a/Source/WebCore/page/Settings.cpp b/Source/WebCore/page/Settings.cpp
index e3e02a4..45007c3 100644
--- a/Source/WebCore/page/Settings.cpp
+++ b/Source/WebCore/page/Settings.cpp
@@ -108,6 +108,7 @@
: m_page(page)
, m_editableLinkBehavior(EditableLinkDefaultBehavior)
, m_textDirectionSubmenuInclusionBehavior(TextDirectionSubmenuAutomaticallyIncluded)
+ , m_passwordEchoDurationInSeconds(1)
, m_minimumFontSize(0)
, m_minimumLogicalFontSize(0)
, m_defaultFontSize(0)
@@ -213,6 +214,7 @@
#endif
, m_mediaPlaybackRequiresUserGesture(false)
, m_mediaPlaybackAllowsInline(true)
+ , m_passwordEchoEnabled(false)
, m_loadsImagesAutomaticallyTimer(this, &Settings::loadsImagesAutomaticallyTimerFired)
{
// A Frame may not have been created yet, so we initialize the AtomicString
diff --git a/Source/WebCore/page/Settings.h b/Source/WebCore/page/Settings.h
index 5ce64f0..51519ad 100644
--- a/Source/WebCore/page/Settings.h
+++ b/Source/WebCore/page/Settings.h
@@ -461,6 +461,12 @@
void setMediaPlaybackAllowsInline(bool flag) { m_mediaPlaybackAllowsInline = flag; };
bool mediaPlaybackAllowsInline() const { return m_mediaPlaybackAllowsInline; }
+ void setPasswordEchoEnabled(bool flag) { m_passwordEchoEnabled = flag; }
+ bool passwordEchoEnabled() const { return m_passwordEchoEnabled; }
+
+ void setPasswordEchoDurationInSeconds(double durationInSeconds) { m_passwordEchoDurationInSeconds = durationInSeconds; }
+ double passwordEchoDurationInSeconds() const { return m_passwordEchoDurationInSeconds; }
+
private:
Page* m_page;
@@ -477,6 +483,7 @@
ScriptFontFamilyMap m_pictographFontFamilyMap;
EditableLinkBehavior m_editableLinkBehavior;
TextDirectionSubmenuInclusionBehavior m_textDirectionSubmenuInclusionBehavior;
+ double m_passwordEchoDurationInSeconds;
int m_minimumFontSize;
int m_minimumLogicalFontSize;
int m_defaultFontSize;
@@ -580,6 +587,7 @@
#endif
bool m_mediaPlaybackRequiresUserGesture : 1;
bool m_mediaPlaybackAllowsInline : 1;
+ bool m_passwordEchoEnabled : 1;
Timer<Settings> m_loadsImagesAutomaticallyTimer;
void loadsImagesAutomaticallyTimerFired(Timer<Settings>*);
diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp
index 261fefa..2695dac 100644
--- a/Source/WebCore/testing/Internals.cpp
+++ b/Source/WebCore/testing/Internals.cpp
@@ -55,6 +55,8 @@
}
Internals::Internals()
+ : passwordEchoDurationInSecondsBackedUp(false)
+ , passwordEchoEnabledBackedUp(false)
{
}
@@ -191,9 +193,44 @@
document->settings()->setForceCompositingMode(enabled);
}
-void Internals::reset(Document*)
+void Internals::setPasswordEchoEnabled(Document* document, bool enabled, ExceptionCode& ec)
{
-// FIXME: Implement
+ if (!document || !document->settings()) {
+ ec = INVALID_ACCESS_ERR;
+ return;
+ }
+
+ if (!passwordEchoEnabledBackedUp) {
+ passwordEchoEnabledBackup = enabled;
+ passwordEchoEnabledBackedUp = true;
+ }
+ document->settings()->setPasswordEchoEnabled(enabled);
+}
+
+void Internals::setPasswordEchoDurationInSeconds(Document* document, double durationInSeconds, ExceptionCode& ec)
+{
+ if (!document || !document->settings()) {
+ ec = INVALID_ACCESS_ERR;
+ return;
+ }
+
+ if (!passwordEchoDurationInSecondsBackedUp) {
+ passwordEchoDurationInSecondsBackup = durationInSeconds;
+ passwordEchoDurationInSecondsBackedUp = true;
+ }
+ document->settings()->setPasswordEchoDurationInSeconds(durationInSeconds);
+}
+
+void Internals::reset(Document* document)
+{
+ if (!document || !document->settings())
+ return;
+
+ if (passwordEchoDurationInSecondsBackedUp)
+ document->settings()->setPasswordEchoDurationInSeconds(passwordEchoDurationInSecondsBackup);
+
+ if (passwordEchoEnabledBackedUp)
+ document->settings()->setPasswordEchoDurationInSeconds(passwordEchoEnabledBackup);
}
}
diff --git a/Source/WebCore/testing/Internals.h b/Source/WebCore/testing/Internals.h
index 6afe9f5..6892554 100644
--- a/Source/WebCore/testing/Internals.h
+++ b/Source/WebCore/testing/Internals.h
@@ -69,9 +69,18 @@
void setForceCompositingMode(Document*, bool enabled, ExceptionCode&);
+ void setPasswordEchoEnabled(Document*, bool enabled, ExceptionCode&);
+ void setPasswordEchoDurationInSeconds(Document*, double durationInSeconds, ExceptionCode&);
+
static const char* internalsId;
+
private:
Internals();
+
+ double passwordEchoDurationInSecondsBackup;
+ bool passwordEchoEnabledBackup : 1;
+ bool passwordEchoDurationInSecondsBackedUp : 1;
+ bool passwordEchoEnabledBackedUp : 1;
};
} // namespace WebCore
diff --git a/Source/WebCore/testing/Internals.idl b/Source/WebCore/testing/Internals.idl
index 8da0b99..22023f6 100644
--- a/Source/WebCore/testing/Internals.idl
+++ b/Source/WebCore/testing/Internals.idl
@@ -44,6 +44,9 @@
ClientRect boundingBox(in Element element) raises(DOMException);
void setForceCompositingMode(in Document document, in boolean enabled) raises(DOMException);
+
+ void setPasswordEchoEnabled(in Document document, in boolean enabled) raises(DOMException);
+ void setPasswordEchoDurationInSeconds(in Document document, in double durationInSeconds) raises(DOMException);
};
}
diff --git a/Source/WebKit/qt/Api/qwebsettings.cpp b/Source/WebKit/qt/Api/qwebsettings.cpp
index 18d3d97..fa162c1 100644
--- a/Source/WebKit/qt/Api/qwebsettings.cpp
+++ b/Source/WebKit/qt/Api/qwebsettings.cpp
@@ -284,6 +284,11 @@
settings->setNeedsSiteSpecificQuirks(value);
settings->setUsesPageCache(WebCore::pageCache()->capacity());
+
+#if ENABLE(PASSWORD_ECHO)
+ settings->setPasswordEchoEnabled(true);
+ settings->setPasswordEchoDurationInSeconds(1);
+#endif
} else {
QList<QWebSettingsPrivate*> settings = *::allSettings();
for (int i = 0; i < settings.count(); ++i)
diff --git a/Source/WebKit/qt/ChangeLog b/Source/WebKit/qt/ChangeLog
index 2c0643e..c120883 100644
--- a/Source/WebKit/qt/ChangeLog
+++ b/Source/WebKit/qt/ChangeLog
@@ -1,3 +1,15 @@
+2011-08-18 Chang Shu <cshu@webkit.org>
+
+ Add support of setPasswordEchoEnabled and setPasswordEchoDuration for password echo feature
+ https://bugs.webkit.org/show_bug.cgi?id=66052
+
+ Reviewed by Alexey Proskuryakov.
+
+ Enable password echo under the build flag.
+
+ * Api/qwebsettings.cpp:
+ (QWebSettingsPrivate::apply):
+
2011-08-16 Chang Shu <cshu@webkit.org>
Support reset in WebCore::Internals