summaryrefslogtreecommitdiffstats
path: root/WebCore/dom/InputElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/dom/InputElement.cpp')
-rw-r--r--WebCore/dom/InputElement.cpp115
1 files changed, 33 insertions, 82 deletions
diff --git a/WebCore/dom/InputElement.cpp b/WebCore/dom/InputElement.cpp
index 0e2456d..c29cb1c 100644
--- a/WebCore/dom/InputElement.cpp
+++ b/WebCore/dom/InputElement.cpp
@@ -34,7 +34,6 @@
#include "RenderTextControlSingleLine.h"
#include "SelectionController.h"
#include "TextIterator.h"
-#include "TextBreakIterator.h"
#if ENABLE(WML)
#include "WMLInputElement.h"
@@ -46,25 +45,23 @@ namespace WebCore {
using namespace HTMLNames;
// FIXME: According to HTML4, the length attribute's value can be arbitrarily
-// large. However, due to http://bugs.webkit.org/show_bugs.cgi?id=14536 things
+// large. However, due to https://bugs.webkit.org/show_bug.cgi?id=14536 things
// get rather sluggish when a text field has a larger number of characters than
// this, even when just clicking in the text field.
const int InputElement::s_maximumLength = 524288;
const int InputElement::s_defaultSize = 20;
-void InputElement::dispatchFocusEvent(InputElementData& data, InputElement* inputElement, Element* element)
+void InputElement::dispatchFocusEvent(InputElement* inputElement, Element* element)
{
if (!inputElement->isTextField())
return;
- updatePlaceholderVisibility(data, inputElement, element);
-
Document* document = element->document();
if (inputElement->isPasswordField() && document->frame())
document->setUseSecureKeyboardEntryWhenActive(true);
}
-void InputElement::dispatchBlurEvent(InputElementData& data, InputElement* inputElement, Element* element)
+void InputElement::dispatchBlurEvent(InputElement* inputElement, Element* element)
{
if (!inputElement->isTextField())
return;
@@ -74,28 +71,12 @@ void InputElement::dispatchBlurEvent(InputElementData& data, InputElement* input
if (!frame)
return;
- updatePlaceholderVisibility(data, inputElement, element);
-
if (inputElement->isPasswordField())
document->setUseSecureKeyboardEntryWhenActive(false);
frame->textFieldDidEndEditing(element);
}
-void InputElement::updatePlaceholderVisibility(InputElementData& data, InputElement* inputElement, Element* element, bool placeholderValueChanged)
-{
- ASSERT(inputElement->isTextField());
- Document* document = element->document();
-
- bool oldPlaceholderShouldBeVisible = data.placeholderShouldBeVisible();
- data.setPlaceholderShouldBeVisible(inputElement->value().isEmpty()
- && document->focusedNode() != element
- && !inputElement->placeholder().isEmpty());
-
- if ((oldPlaceholderShouldBeVisible != data.placeholderShouldBeVisible() || placeholderValueChanged) && element->renderer())
- toRenderTextControlSingleLine(element->renderer())->updatePlaceholderVisibility();
-}
-
void InputElement::updateFocusAppearance(InputElementData& data, InputElement* inputElement, Element* element, bool restorePreviousSelection)
{
ASSERT(inputElement->isTextField());
@@ -137,11 +118,8 @@ void InputElement::aboutToUnload(InputElement* inputElement, Element* element)
void InputElement::setValueFromRenderer(InputElementData& data, InputElement* inputElement, Element* element, const String& value)
{
- // Renderer and our event handler are responsible for constraining values.
- ASSERT(value == inputElement->constrainValue(value) || inputElement->constrainValue(value).isEmpty());
-
- if (inputElement->isTextField())
- updatePlaceholderVisibility(data, inputElement, element);
+ // Renderer and our event handler are responsible for sanitizing values.
+ ASSERT_UNUSED(inputElement, value == inputElement->sanitizeValue(value) || inputElement->sanitizeValue(value).isEmpty());
// Workaround for bug where trailing \n is included in the result of textContent.
// The assert macro above may also be simplified to: value == constrainValue(value)
@@ -153,84 +131,58 @@ void InputElement::setValueFromRenderer(InputElementData& data, InputElement* in
element->setFormControlValueMatchesRenderer(true);
- // Fire the "input" DOM event
- element->dispatchEvent(eventNames().inputEvent, true, false);
+ element->dispatchEvent(Event::create(eventNames().inputEvent, true, false));
notifyFormStateChanged(element);
}
-static int numCharactersInGraphemeClusters(StringImpl* s, int numGraphemeClusters)
+String InputElement::sanitizeValue(const InputElement* inputElement, const String& proposedValue)
{
- if (!s)
- return 0;
-
- TextBreakIterator* it = characterBreakIterator(s->characters(), s->length());
- if (!it)
- return 0;
-
- for (int i = 0; i < numGraphemeClusters; ++i) {
- if (textBreakNext(it) == TextBreakDone)
- return s->length();
- }
-
- return textBreakCurrent(it);
+ return InputElement::sanitizeUserInputValue(inputElement, proposedValue, s_maximumLength);
}
-String InputElement::constrainValue(const InputElement* inputElement, const String& proposedValue, int maxLength)
+String InputElement::sanitizeUserInputValue(const InputElement* inputElement, const String& proposedValue, int maxLength)
{
- String string = proposedValue;
if (!inputElement->isTextField())
- return string;
+ return proposedValue;
+ String string = proposedValue;
string.replace("\r\n", " ");
string.replace('\r', ' ');
string.replace('\n', ' ');
-
- StringImpl* s = string.impl();
- int newLength = numCharactersInGraphemeClusters(s, maxLength);
- for (int i = 0; i < newLength; ++i) {
- const UChar& current = (*s)[i];
+
+ unsigned newLength = string.numCharactersInGraphemeClusters(maxLength);
+ for (unsigned i = 0; i < newLength; ++i) {
+ const UChar current = string[i];
if (current < ' ' && current != '\t') {
newLength = i;
break;
}
}
-
- if (newLength < static_cast<int>(string.length()))
- return string.left(newLength);
-
- return string;
-}
-
-static int numGraphemeClusters(StringImpl* s)
-{
- if (!s)
- return 0;
-
- TextBreakIterator* it = characterBreakIterator(s->characters(), s->length());
- if (!it)
- return 0;
-
- int num = 0;
- while (textBreakNext(it) != TextBreakDone)
- ++num;
-
- return num;
+ return string.left(newLength);
}
-void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, InputElement* inputElement, Document* document, Event* event)
+void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, InputElement* inputElement, Element* element, Event* event)
{
ASSERT(event->isBeforeTextInsertedEvent());
-
// Make sure that the text to be inserted will not violate the maxLength.
- int oldLength = numGraphemeClusters(inputElement->value().impl());
- ASSERT(oldLength <= data.maxLength());
- int selectionLength = numGraphemeClusters(plainText(document->frame()->selection()->selection().toNormalizedRange().get()).impl());
+
+ // We use RenderTextControlSingleLine::text() instead of InputElement::value()
+ // because they can be mismatched by sanitizeValue() in
+ // RenderTextControlSingleLine::subtreeHasChanged() in some cases.
+ unsigned oldLength = toRenderTextControlSingleLine(element->renderer())->text().numGraphemeClusters();
+
+ // selection() may be a pre-edit text.
+ unsigned selectionLength = plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get()).numGraphemeClusters();
ASSERT(oldLength >= selectionLength);
- int maxNewLength = data.maxLength() - (oldLength - selectionLength);
+
+ // Selected characters will be removed by the next text event.
+ unsigned baseLength = oldLength - selectionLength;
+ unsigned maxLength = static_cast<unsigned>(data.maxLength()); // maxLength() can never be negative.
+ unsigned appendableLength = maxLength > baseLength ? maxLength - baseLength : 0;
// Truncate the inserted text to avoid violating the maxLength and other constraints.
BeforeTextInsertedEvent* textEvent = static_cast<BeforeTextInsertedEvent*>(event);
- textEvent->setText(constrainValue(inputElement, textEvent->text(), maxNewLength));
+ textEvent->setText(sanitizeUserInputValue(inputElement, textEvent->text(), appendableLength));
}
void InputElement::parseSizeAttribute(InputElementData& data, Element* element, MappedAttribute* attribute)
@@ -259,7 +211,7 @@ void InputElement::parseMaxLengthAttribute(InputElementData& data, InputElement*
void InputElement::updateValueIfNeeded(InputElementData& data, InputElement* inputElement)
{
String oldValue = data.value();
- String newValue = inputElement->constrainValue(oldValue);
+ String newValue = sanitizeValue(inputElement, oldValue);
if (newValue != oldValue)
inputElement->setValue(newValue);
}
@@ -277,8 +229,7 @@ void InputElement::notifyFormStateChanged(Element* element)
// InputElementData
InputElementData::InputElementData()
- : m_placeholderShouldBeVisible(false)
- , m_size(InputElement::s_defaultSize)
+ : m_size(InputElement::s_defaultSize)
, m_maxLength(InputElement::s_maximumLength)
, m_cachedSelectionStart(-1)
, m_cachedSelectionEnd(-1)