Diff
Modified: trunk/LayoutTests/ChangeLog (93655 => 93656)
--- trunk/LayoutTests/ChangeLog 2011-08-23 23:24:44 UTC (rev 93655)
+++ trunk/LayoutTests/ChangeLog 2011-08-23 23:31:44 UTC (rev 93656)
@@ -1,3 +1,16 @@
+2011-08-23 Chang Shu <[email protected]>
+
+ Added support for momentarily revealing last typed character in password input.
+ Code change was partially based on Apple's iOS code and Samuel Nevala's work.
+ https://bugs.webkit.org/show_bug.cgi?id=32509
+
+ Reviewed by Alexey Proskuryakov.
+
+ Updated failed expected files.
+
+ * editing/input/password-echo-passnode-expected.txt:
+ * editing/input/password-echo-passnode2-expected.txt:
+
2011-08-23 Ben Wells <[email protected]>
Rebaselines for bug 66442 (skia webkit-transform breaks webkit-mask)
Modified: trunk/LayoutTests/editing/input/password-echo-passnode-expected.txt (93655 => 93656)
--- trunk/LayoutTests/editing/input/password-echo-passnode-expected.txt 2011-08-23 23:24:44 UTC (rev 93655)
+++ trunk/LayoutTests/editing/input/password-echo-passnode-expected.txt 2011-08-23 23:31:44 UTC (rev 93656)
@@ -1,6 +1,6 @@
Tests if input chars are secured correctly
-Error: secured right after. expected=false, actual=true
+Success: secured right after. expected=false, actual=false
Success: secured after delay. expected=true, actual=true
-Error: secured right after. expected=false, actual=true
+Success: secured right after. expected=false, actual=false
Success: secured after delay. expected=true, actual=true
Modified: trunk/LayoutTests/editing/input/password-echo-passnode2-expected.txt (93655 => 93656)
--- trunk/LayoutTests/editing/input/password-echo-passnode2-expected.txt 2011-08-23 23:24:44 UTC (rev 93655)
+++ trunk/LayoutTests/editing/input/password-echo-passnode2-expected.txt 2011-08-23 23:31:44 UTC (rev 93656)
@@ -1,6 +1,6 @@
Tests if input chars are secured correctly
-Error: secured right after. expected=false, actual=true
+Success: secured right after. expected=false, actual=false
Success: secured after delay. expected=true, actual=true
-Error: secured right after. expected=false, actual=true
+Success: secured right after. expected=false, actual=false
Success: secured after delay. expected=true, actual=true
Modified: trunk/Source/WebCore/ChangeLog (93655 => 93656)
--- trunk/Source/WebCore/ChangeLog 2011-08-23 23:24:44 UTC (rev 93655)
+++ trunk/Source/WebCore/ChangeLog 2011-08-23 23:31:44 UTC (rev 93656)
@@ -1,3 +1,30 @@
+2011-08-23 Chang Shu <[email protected]>
+
+ Added support for momentarily revealing last typed character in password input.
+ Code change was partially based on Apple's iOS code and Samuel Nevala's work.
+ https://bugs.webkit.org/show_bug.cgi?id=32509
+
+ Reviewed by Alexey Proskuryakov.
+
+ * editing/InsertIntoTextNodeCommand.cpp:
+ (WebCore::InsertIntoTextNodeCommand::doApply):
+ * rendering/RenderText.cpp:
+ (WebCore::SecureTextTimer::SecureTextTimer):
+ (WebCore::SecureTextTimer::restartWithNewText):
+ (WebCore::SecureTextTimer::invalidate):
+ (WebCore::SecureTextTimer::lastTypedCharacterOffset):
+ (WebCore::SecureTextTimer::fired):
+ (WebCore::RenderText::willBeDestroyed):
+ (WebCore::RenderText::setTextInternal):
+ (WebCore::RenderText::secureText):
+ (WebCore::RenderText::momentarilyRevealLastTypedCharacter):
+ * rendering/RenderText.h:
+ (WebCore::RenderText::isSecure):
+ * testing/Internals.cpp:
+ (WebCore::Internals::setPasswordEchoEnabled): Fixed some silly coding in Internals.
+ (WebCore::Internals::setPasswordEchoDurationInSeconds):
+ (WebCore::Internals::reset):
+
2011-08-23 Dmitry Lomov <Dmitry Lomov ([email protected])>
https://bugs.webkit.org/show_bug.cgi?id=66751
Modified: trunk/Source/WebCore/editing/InsertIntoTextNodeCommand.cpp (93655 => 93656)
--- trunk/Source/WebCore/editing/InsertIntoTextNodeCommand.cpp 2011-08-23 23:24:44 UTC (rev 93655)
+++ trunk/Source/WebCore/editing/InsertIntoTextNodeCommand.cpp 2011-08-23 23:31:44 UTC (rev 93656)
@@ -28,6 +28,8 @@
#include "AXObjectCache.h"
#include "Document.h"
+#include "RenderText.h"
+#include "Settings.h"
#include "Text.h"
namespace WebCore {
@@ -47,7 +49,13 @@
{
if (!m_node->rendererIsEditable())
return;
-
+
+ if (document()->settings() && document()->settings()->passwordEchoEnabled()) {
+ RenderText* renderText = toRenderText(m_node->renderer());
+ if (renderText && renderText->isSecure())
+ renderText->momentarilyRevealLastTypedCharacter(m_offset + m_text.length() - 1);
+ }
+
ExceptionCode ec;
m_node->insertData(m_offset, m_text, ec);
Modified: trunk/Source/WebCore/rendering/RenderText.cpp (93655 => 93656)
--- trunk/Source/WebCore/rendering/RenderText.cpp 2011-08-23 23:24:44 UTC (rev 93655)
+++ trunk/Source/WebCore/rendering/RenderText.cpp 2011-08-23 23:31:44 UTC (rev 93656)
@@ -37,6 +37,7 @@
#include "RenderCombineText.h"
#include "RenderLayer.h"
#include "RenderView.h"
+#include "Settings.h"
#include "Text.h"
#include "TextBreakIterator.h"
#include "TextResourceDecoder.h"
@@ -52,6 +53,37 @@
namespace WebCore {
+class SecureTextTimer;
+typedef HashMap<RenderText*, SecureTextTimer*> SecureTextTimerMap;
+static SecureTextTimerMap* gSecureTextTimers = 0;
+
+class SecureTextTimer : public TimerBase {
+public:
+ SecureTextTimer(RenderText* renderText)
+ : m_renderText(renderText)
+ , m_lastTypedCharacterOffset(-1)
+ {
+ }
+
+ void restartWithNewText(unsigned lastTypedCharacterOffset)
+ {
+ m_lastTypedCharacterOffset = lastTypedCharacterOffset;
+ startOneShot(m_renderText->document()->settings()->passwordEchoDurationInSeconds());
+ }
+ void invalidate() { m_lastTypedCharacterOffset = -1; }
+ unsigned lastTypedCharacterOffset() { return m_lastTypedCharacterOffset; }
+
+private:
+ virtual void fired()
+ {
+ ASSERT(gSecureTextTimers->contains(m_renderText));
+ m_renderText->setText(m_renderText->text(), true /* forcing setting text as it may be masked later */);
+ }
+
+ RenderText* m_renderText;
+ int m_lastTypedCharacterOffset;
+};
+
static void makeCapitalized(String* string, UChar previous)
{
if (string->isNull())
@@ -192,6 +224,9 @@
void RenderText::willBeDestroyed()
{
+ if (SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->take(this) : 0)
+ delete secureTextTimer;
+
removeAndDestroyTextBoxes();
RenderObject::willBeDestroyed();
}
@@ -1258,13 +1293,13 @@
case TSNONE:
break;
case TSCIRCLE:
- m_text.fill(whiteBullet);
+ secureText(whiteBullet);
break;
case TSDISC:
- m_text.fill(bullet);
+ secureText(bullet);
break;
case TSSQUARE:
- m_text.fill(blackSquare);
+ secureText(blackSquare);
}
}
@@ -1274,6 +1309,28 @@
m_isAllASCII = m_text.containsOnlyASCII();
}
+void RenderText::secureText(UChar mask)
+{
+ if (!m_text.length())
+ return;
+
+ int lastTypedCharacterOffsetToReveal = -1;
+ String revealedText;
+ SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->get(this) : 0;
+ if (secureTextTimer && secureTextTimer->isActive()) {
+ lastTypedCharacterOffsetToReveal = secureTextTimer->lastTypedCharacterOffset();
+ if (lastTypedCharacterOffsetToReveal >= 0)
+ revealedText.append(m_text[lastTypedCharacterOffsetToReveal]);
+ }
+
+ m_text.fill(mask);
+ if (lastTypedCharacterOffsetToReveal >= 0) {
+ m_text.replace(lastTypedCharacterOffsetToReveal, 1, revealedText);
+ // m_text may be updated later before timer fires. We invalidate the lastTypedCharacterOffset to avoid inconsistency.
+ secureTextTimer->invalidate();
+ }
+}
+
void RenderText::setText(PassRefPtr<StringImpl> text, bool force)
{
ASSERT(text);
@@ -1726,4 +1783,17 @@
#endif
+void RenderText::momentarilyRevealLastTypedCharacter(unsigned lastTypedCharacterOffset)
+{
+ if (!gSecureTextTimers)
+ gSecureTextTimers = new SecureTextTimerMap;
+
+ SecureTextTimer* secureTextTimer = gSecureTextTimers->get(this);
+ if (!secureTextTimer) {
+ secureTextTimer = new SecureTextTimer(this);
+ gSecureTextTimers->add(this, secureTextTimer);
+ }
+ secureTextTimer->restartWithNewText(lastTypedCharacterOffset);
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/rendering/RenderText.h (93655 => 93656)
--- trunk/Source/WebCore/rendering/RenderText.h 2011-08-23 23:24:44 UTC (rev 93655)
+++ trunk/Source/WebCore/rendering/RenderText.h 2011-08-23 23:31:44 UTC (rev 93656)
@@ -115,6 +115,9 @@
bool containsReversedText() const { return m_containsReversedText; }
+ bool isSecure() const { return style()->textSecurity() != TSNONE; }
+ void momentarilyRevealLastTypedCharacter(unsigned lastTypedCharacterOffset);
+
InlineTextBox* findNextInlineTextBox(int offset, int& pos) const;
bool allowTabs() const { return !style()->collapseWhiteSpace(); }
@@ -158,6 +161,7 @@
void updateNeedsTranscoding();
inline void transformText(String&) const;
+ void secureText(UChar mask);
float m_minWidth; // here to minimize padding in 64-bit.
Modified: trunk/Source/WebCore/testing/Internals.cpp (93655 => 93656)
--- trunk/Source/WebCore/testing/Internals.cpp 2011-08-23 23:24:44 UTC (rev 93655)
+++ trunk/Source/WebCore/testing/Internals.cpp 2011-08-23 23:31:44 UTC (rev 93656)
@@ -226,7 +226,7 @@
}
if (!passwordEchoEnabledBackedUp) {
- passwordEchoEnabledBackup = enabled;
+ passwordEchoEnabledBackup = document->settings()->passwordEchoEnabled();
passwordEchoEnabledBackedUp = true;
}
document->settings()->setPasswordEchoEnabled(enabled);
@@ -240,7 +240,7 @@
}
if (!passwordEchoDurationInSecondsBackedUp) {
- passwordEchoDurationInSecondsBackup = durationInSeconds;
+ passwordEchoDurationInSecondsBackup = document->settings()->passwordEchoDurationInSeconds();
passwordEchoDurationInSecondsBackedUp = true;
}
document->settings()->setPasswordEchoDurationInSeconds(durationInSeconds);
@@ -251,12 +251,16 @@
if (!document || !document->settings())
return;
- if (passwordEchoDurationInSecondsBackedUp)
+ if (passwordEchoDurationInSecondsBackedUp) {
document->settings()->setPasswordEchoDurationInSeconds(passwordEchoDurationInSecondsBackup);
+ passwordEchoDurationInSecondsBackedUp = false;
+ }
- if (passwordEchoEnabledBackedUp)
- document->settings()->setPasswordEchoDurationInSeconds(passwordEchoEnabledBackup);
+ if (passwordEchoEnabledBackedUp) {
+ document->settings()->setPasswordEchoEnabled(passwordEchoEnabledBackup);
+ passwordEchoEnabledBackedUp = false;
+ }
}
+}
-}