diff options
Diffstat (limited to 'WebCore/dom/InputElement.cpp')
-rw-r--r-- | WebCore/dom/InputElement.cpp | 115 |
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) |