Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      5  * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
      6  *           (C) 2006 Alexey Proskuryakov (ap (at) nypop.com)
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Library General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Library General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Library General Public License
     19  * along with this library; see the file COPYING.LIB.  If not, write to
     20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     21  * Boston, MA 02110-1301, USA.
     22  *
     23  */
     24 
     25 #include "config.h"
     26 #include "core/html/HTMLTextFormControlElement.h"
     27 
     28 #include "bindings/core/v8/ExceptionState.h"
     29 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
     30 #include "core/HTMLNames.h"
     31 #include "core/accessibility/AXObjectCache.h"
     32 #include "core/dom/Document.h"
     33 #include "core/dom/NodeList.h"
     34 #include "core/dom/NodeTraversal.h"
     35 #include "core/dom/Text.h"
     36 #include "core/dom/shadow/ShadowRoot.h"
     37 #include "core/editing/Editor.h"
     38 #include "core/editing/FrameSelection.h"
     39 #include "core/editing/TextIterator.h"
     40 #include "core/editing/htmlediting.h"
     41 #include "core/events/Event.h"
     42 #include "core/frame/LocalFrame.h"
     43 #include "core/frame/UseCounter.h"
     44 #include "core/html/HTMLBRElement.h"
     45 #include "core/html/shadow/ShadowElementNames.h"
     46 #include "core/page/FocusController.h"
     47 #include "core/page/Page.h"
     48 #include "core/rendering/RenderBlock.h"
     49 #include "core/rendering/RenderBlockFlow.h"
     50 #include "core/rendering/RenderTheme.h"
     51 #include "platform/heap/Handle.h"
     52 #include "platform/text/TextBoundaries.h"
     53 #include "wtf/text/StringBuilder.h"
     54 
     55 namespace blink {
     56 
     57 using namespace HTMLNames;
     58 
     59 HTMLTextFormControlElement::HTMLTextFormControlElement(const QualifiedName& tagName, Document& doc, HTMLFormElement* form)
     60     : HTMLFormControlElementWithState(tagName, doc, form)
     61     , m_lastChangeWasUserEdit(false)
     62     , m_cachedSelectionStart(0)
     63     , m_cachedSelectionEnd(0)
     64     , m_cachedSelectionDirection(SelectionHasNoDirection)
     65 {
     66 }
     67 
     68 HTMLTextFormControlElement::~HTMLTextFormControlElement()
     69 {
     70 }
     71 
     72 Node::InsertionNotificationRequest HTMLTextFormControlElement::insertedInto(ContainerNode* insertionPoint)
     73 {
     74     HTMLFormControlElementWithState::insertedInto(insertionPoint);
     75     if (!insertionPoint->inDocument())
     76         return InsertionDone;
     77     String initialValue = value();
     78     setTextAsOfLastFormControlChangeEvent(initialValue.isNull() ? emptyString() : initialValue);
     79     return InsertionDone;
     80 }
     81 
     82 void HTMLTextFormControlElement::dispatchFocusEvent(Element* oldFocusedElement, FocusType type)
     83 {
     84     if (supportsPlaceholder())
     85         updatePlaceholderVisibility(false);
     86     handleFocusEvent(oldFocusedElement, type);
     87     HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedElement, type);
     88 }
     89 
     90 void HTMLTextFormControlElement::dispatchBlurEvent(Element* newFocusedElement)
     91 {
     92     if (supportsPlaceholder())
     93         updatePlaceholderVisibility(false);
     94     handleBlurEvent();
     95     HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement);
     96 }
     97 
     98 void HTMLTextFormControlElement::defaultEventHandler(Event* event)
     99 {
    100     if (event->type() == EventTypeNames::webkitEditableContentChanged && renderer() && renderer()->isTextControl()) {
    101         m_lastChangeWasUserEdit = true;
    102         subtreeHasChanged();
    103         return;
    104     }
    105 
    106     HTMLFormControlElementWithState::defaultEventHandler(event);
    107 }
    108 
    109 void HTMLTextFormControlElement::forwardEvent(Event* event)
    110 {
    111     if (event->type() == EventTypeNames::blur || event->type() == EventTypeNames::focus)
    112         return;
    113     innerEditorElement()->defaultEventHandler(event);
    114 }
    115 
    116 String HTMLTextFormControlElement::strippedPlaceholder() const
    117 {
    118     // According to the HTML5 specification, we need to remove CR and LF from
    119     // the attribute value.
    120     const AtomicString& attributeValue = fastGetAttribute(placeholderAttr);
    121     if (!attributeValue.contains(newlineCharacter) && !attributeValue.contains(carriageReturn))
    122         return attributeValue;
    123 
    124     StringBuilder stripped;
    125     unsigned length = attributeValue.length();
    126     stripped.reserveCapacity(length);
    127     for (unsigned i = 0; i < length; ++i) {
    128         UChar character = attributeValue[i];
    129         if (character == newlineCharacter || character == carriageReturn)
    130             continue;
    131         stripped.append(character);
    132     }
    133     return stripped.toString();
    134 }
    135 
    136 static bool isNotLineBreak(UChar ch) { return ch != newlineCharacter && ch != carriageReturn; }
    137 
    138 bool HTMLTextFormControlElement::isPlaceholderEmpty() const
    139 {
    140     const AtomicString& attributeValue = fastGetAttribute(placeholderAttr);
    141     return attributeValue.string().find(isNotLineBreak) == kNotFound;
    142 }
    143 
    144 bool HTMLTextFormControlElement::placeholderShouldBeVisible() const
    145 {
    146     return supportsPlaceholder()
    147         && isEmptyValue()
    148         && isEmptySuggestedValue()
    149         && !isPlaceholderEmpty()
    150         && (document().focusedElement() != this || (RenderTheme::theme().shouldShowPlaceholderWhenFocused()))
    151         && (!renderer() || renderer()->style()->visibility() == VISIBLE);
    152 }
    153 
    154 HTMLElement* HTMLTextFormControlElement::placeholderElement() const
    155 {
    156     return toHTMLElement(userAgentShadowRoot()->getElementById(ShadowElementNames::placeholder()));
    157 }
    158 
    159 void HTMLTextFormControlElement::updatePlaceholderVisibility(bool placeholderValueChanged)
    160 {
    161     if (!supportsPlaceholder())
    162         return;
    163     if (!placeholderElement() || placeholderValueChanged)
    164         updatePlaceholderText();
    165     HTMLElement* placeholder = placeholderElement();
    166     if (!placeholder)
    167         return;
    168     placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShouldBeVisible() ? CSSValueVisible : CSSValueHidden);
    169 }
    170 
    171 void HTMLTextFormControlElement::setSelectionStart(int start)
    172 {
    173     setSelectionRange(start, std::max(start, selectionEnd()), selectionDirection());
    174 }
    175 
    176 void HTMLTextFormControlElement::setSelectionEnd(int end)
    177 {
    178     setSelectionRange(std::min(end, selectionStart()), end, selectionDirection());
    179 }
    180 
    181 void HTMLTextFormControlElement::setSelectionDirection(const String& direction)
    182 {
    183     setSelectionRange(selectionStart(), selectionEnd(), direction);
    184 }
    185 
    186 void HTMLTextFormControlElement::select()
    187 {
    188     document().updateLayoutIgnorePendingStylesheets();
    189     setSelectionRange(0, std::numeric_limits<int>::max(), SelectionHasNoDirection, isFocusable() ? ChangeSelectionAndFocus : NotChangeSelection);
    190 }
    191 
    192 bool HTMLTextFormControlElement::shouldDispatchFormControlChangeEvent(String& oldValue, String& newValue)
    193 {
    194     return !equalIgnoringNullity(oldValue, newValue);
    195 }
    196 
    197 void HTMLTextFormControlElement::dispatchFormControlChangeEvent()
    198 {
    199     String newValue = value();
    200     if (shouldDispatchFormControlChangeEvent(m_textAsOfLastFormControlChangeEvent, newValue)) {
    201         setTextAsOfLastFormControlChangeEvent(newValue);
    202         dispatchChangeEvent();
    203     }
    204     setChangedSinceLastFormControlChangeEvent(false);
    205 }
    206 
    207 void HTMLTextFormControlElement::setRangeText(const String& replacement, ExceptionState& exceptionState)
    208 {
    209     setRangeText(replacement, selectionStart(), selectionEnd(), String(), exceptionState);
    210 }
    211 
    212 void HTMLTextFormControlElement::setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState& exceptionState)
    213 {
    214     if (start > end) {
    215         exceptionState.throwDOMException(IndexSizeError, "The provided start value (" + String::number(start) + ") is larger than the provided end value (" + String::number(end) + ").");
    216         return;
    217     }
    218     if (hasAuthorShadowRoot())
    219         return;
    220 
    221     String text = innerEditorValue();
    222     unsigned textLength = text.length();
    223     unsigned replacementLength = replacement.length();
    224     unsigned newSelectionStart = selectionStart();
    225     unsigned newSelectionEnd = selectionEnd();
    226 
    227     start = std::min(start, textLength);
    228     end = std::min(end, textLength);
    229 
    230     if (start < end)
    231         text.replace(start, end - start, replacement);
    232     else
    233         text.insert(replacement, start);
    234 
    235     setInnerEditorValue(text);
    236 
    237     // FIXME: What should happen to the value (as in value()) if there's no renderer?
    238     if (!renderer())
    239         return;
    240 
    241     subtreeHasChanged();
    242 
    243     if (equalIgnoringCase(selectionMode, "select")) {
    244         newSelectionStart = start;
    245         newSelectionEnd = start + replacementLength;
    246     } else if (equalIgnoringCase(selectionMode, "start"))
    247         newSelectionStart = newSelectionEnd = start;
    248     else if (equalIgnoringCase(selectionMode, "end"))
    249         newSelectionStart = newSelectionEnd = start + replacementLength;
    250     else {
    251         // Default is "preserve".
    252         long delta = replacementLength - (end - start);
    253 
    254         if (newSelectionStart > end)
    255             newSelectionStart += delta;
    256         else if (newSelectionStart > start)
    257             newSelectionStart = start;
    258 
    259         if (newSelectionEnd > end)
    260             newSelectionEnd += delta;
    261         else if (newSelectionEnd > start)
    262             newSelectionEnd = start + replacementLength;
    263     }
    264 
    265     setSelectionRange(newSelectionStart, newSelectionEnd, SelectionHasNoDirection);
    266 }
    267 
    268 void HTMLTextFormControlElement::setSelectionRange(int start, int end, const String& directionString)
    269 {
    270     TextFieldSelectionDirection direction = SelectionHasNoDirection;
    271     if (directionString == "forward")
    272         direction = SelectionHasForwardDirection;
    273     else if (directionString == "backward")
    274         direction = SelectionHasBackwardDirection;
    275 
    276     if (direction == SelectionHasNoDirection && document().frame() && document().frame()->editor().behavior().shouldConsiderSelectionAsDirectional())
    277         direction = SelectionHasForwardDirection;
    278 
    279     return setSelectionRange(start, end, direction);
    280 }
    281 
    282 static Position positionForIndex(HTMLElement* innerEditor, int index)
    283 {
    284     ASSERT(index >= 0);
    285     if (index == 0) {
    286         Node* node = NodeTraversal::next(*innerEditor, innerEditor);
    287         if (node && node->isTextNode())
    288             return Position(node, 0, Position::PositionIsOffsetInAnchor);
    289         return Position(innerEditor, 0, Position::PositionIsOffsetInAnchor);
    290     }
    291     int remainingCharactersToMoveForward = index;
    292     Node* lastBrOrText = innerEditor;
    293     for (Node* node = NodeTraversal::next(*innerEditor, innerEditor); node; node = NodeTraversal::next(*node, innerEditor)) {
    294         ASSERT(remainingCharactersToMoveForward >= 0);
    295         if (node->hasTagName(brTag)) {
    296             if (remainingCharactersToMoveForward == 0)
    297                 return positionBeforeNode(node);
    298             --remainingCharactersToMoveForward;
    299             lastBrOrText = node;
    300             continue;
    301         }
    302 
    303         if (node->isTextNode()) {
    304             Text& text = toText(*node);
    305             if (remainingCharactersToMoveForward < static_cast<int>(text.length()))
    306                 return Position(&text, remainingCharactersToMoveForward);
    307             remainingCharactersToMoveForward -= text.length();
    308             lastBrOrText = node;
    309             continue;
    310         }
    311 
    312         ASSERT_NOT_REACHED();
    313     }
    314     return lastPositionInOrAfterNode(lastBrOrText);
    315 }
    316 
    317 static int indexForPosition(HTMLElement* innerEditor, const Position& passedPosition)
    318 {
    319     if (!innerEditor || !innerEditor->contains(passedPosition.anchorNode()) || passedPosition.isNull())
    320         return 0;
    321 
    322     if (positionBeforeNode(innerEditor) == passedPosition)
    323         return 0;
    324 
    325     int index = 0;
    326     Node* startNode = passedPosition.computeNodeBeforePosition();
    327     if (!startNode)
    328         startNode = passedPosition.containerNode();
    329     ASSERT(startNode);
    330     ASSERT(innerEditor->contains(startNode));
    331 
    332     for (Node* node = startNode; node; node = NodeTraversal::previous(*node, innerEditor)) {
    333         if (node->isTextNode()) {
    334             int length = toText(*node).length();
    335             if (node == passedPosition.containerNode())
    336                 index += std::min(length, passedPosition.offsetInContainerNode());
    337             else
    338                 index += length;
    339         } else if (node->hasTagName(brTag)) {
    340             ++index;
    341         }
    342     }
    343 
    344     ASSERT(index >= 0);
    345     return index;
    346 }
    347 
    348 void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextFieldSelectionDirection direction, SelectionOption selectionOption)
    349 {
    350     if (hasAuthorShadowRoot() || !isTextFormControl())
    351         return;
    352 
    353     const int editorValueLength = static_cast<int>(innerEditorValue().length());
    354     ASSERT(editorValueLength >= 0);
    355     end = std::max(std::min(end, editorValueLength), 0);
    356     start = std::min(std::max(start, 0), end);
    357     cacheSelection(start, end, direction);
    358 
    359     if (selectionOption == NotChangeSelection || (selectionOption == ChangeSelectionIfFocused && document().focusedElement() != this))
    360         return;
    361 
    362     LocalFrame* frame = document().frame();
    363     HTMLElement* innerEditor = innerEditorElement();
    364     if (!frame || !innerEditor)
    365         return;
    366 
    367     Position startPosition = positionForIndex(innerEditor, start);
    368     Position endPosition = start == end ? startPosition : positionForIndex(innerEditor, end);
    369 
    370     ASSERT(start == indexForPosition(innerEditor, startPosition));
    371     ASSERT(end == indexForPosition(innerEditor, endPosition));
    372 
    373     // startPosition and endPosition can be null position for example when
    374     // "-webkit-user-select: none" style attribute is specified.
    375     if (startPosition.isNotNull() && endPosition.isNotNull()) {
    376         ASSERT(startPosition.anchorNode()->shadowHost() == this
    377             && endPosition.anchorNode()->shadowHost() == this);
    378     }
    379     VisibleSelection newSelection;
    380     if (direction == SelectionHasBackwardDirection)
    381         newSelection.setWithoutValidation(endPosition, startPosition);
    382     else
    383         newSelection.setWithoutValidation(startPosition, endPosition);
    384     newSelection.setIsDirectional(direction != SelectionHasNoDirection);
    385 
    386     frame->selection().setSelection(newSelection, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle | (selectionOption == ChangeSelectionAndFocus ? 0 : FrameSelection::DoNotSetFocus));
    387 }
    388 
    389 VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) const
    390 {
    391     if (index <= 0)
    392         return VisiblePosition(firstPositionInNode(innerEditorElement()), DOWNSTREAM);
    393     Position start, end;
    394     bool selected = Range::selectNodeContents(innerEditorElement(), start, end);
    395     if (!selected)
    396         return VisiblePosition();
    397     CharacterIterator it(start, end);
    398     it.advance(index - 1);
    399     return VisiblePosition(it.endPosition(), UPSTREAM);
    400 }
    401 
    402 int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& pos) const
    403 {
    404     Position indexPosition = pos.deepEquivalent().parentAnchoredEquivalent();
    405     if (enclosingTextFormControl(indexPosition) != this)
    406         return 0;
    407     ASSERT(indexPosition.document());
    408     RefPtrWillBeRawPtr<Range> range = Range::create(*indexPosition.document());
    409     range->setStart(innerEditorElement(), 0, ASSERT_NO_EXCEPTION);
    410     range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainerNode(), ASSERT_NO_EXCEPTION);
    411     return TextIterator::rangeLength(range.get());
    412 }
    413 
    414 int HTMLTextFormControlElement::selectionStart() const
    415 {
    416     if (!isTextFormControl())
    417         return 0;
    418     if (document().focusedElement() != this)
    419         return m_cachedSelectionStart;
    420 
    421     return computeSelectionStart();
    422 }
    423 
    424 int HTMLTextFormControlElement::computeSelectionStart() const
    425 {
    426     ASSERT(isTextFormControl());
    427     LocalFrame* frame = document().frame();
    428     if (!frame)
    429         return 0;
    430 
    431     return indexForPosition(innerEditorElement(), frame->selection().start());
    432 }
    433 
    434 int HTMLTextFormControlElement::selectionEnd() const
    435 {
    436     if (!isTextFormControl())
    437         return 0;
    438     if (document().focusedElement() != this)
    439         return m_cachedSelectionEnd;
    440     return computeSelectionEnd();
    441 }
    442 
    443 int HTMLTextFormControlElement::computeSelectionEnd() const
    444 {
    445     ASSERT(isTextFormControl());
    446     LocalFrame* frame = document().frame();
    447     if (!frame)
    448         return 0;
    449 
    450     return indexForPosition(innerEditorElement(), frame->selection().end());
    451 }
    452 
    453 static const AtomicString& directionString(TextFieldSelectionDirection direction)
    454 {
    455     DEFINE_STATIC_LOCAL(const AtomicString, none, ("none", AtomicString::ConstructFromLiteral));
    456     DEFINE_STATIC_LOCAL(const AtomicString, forward, ("forward", AtomicString::ConstructFromLiteral));
    457     DEFINE_STATIC_LOCAL(const AtomicString, backward, ("backward", AtomicString::ConstructFromLiteral));
    458 
    459     switch (direction) {
    460     case SelectionHasNoDirection:
    461         return none;
    462     case SelectionHasForwardDirection:
    463         return forward;
    464     case SelectionHasBackwardDirection:
    465         return backward;
    466     }
    467 
    468     ASSERT_NOT_REACHED();
    469     return none;
    470 }
    471 
    472 const AtomicString& HTMLTextFormControlElement::selectionDirection() const
    473 {
    474     if (!isTextFormControl())
    475         return directionString(SelectionHasNoDirection);
    476     if (document().focusedElement() != this)
    477         return directionString(m_cachedSelectionDirection);
    478 
    479     return directionString(computeSelectionDirection());
    480 }
    481 
    482 TextFieldSelectionDirection HTMLTextFormControlElement::computeSelectionDirection() const
    483 {
    484     ASSERT(isTextFormControl());
    485     LocalFrame* frame = document().frame();
    486     if (!frame)
    487         return SelectionHasNoDirection;
    488 
    489     const VisibleSelection& selection = frame->selection().selection();
    490     return selection.isDirectional() ? (selection.isBaseFirst() ? SelectionHasForwardDirection : SelectionHasBackwardDirection) : SelectionHasNoDirection;
    491 }
    492 
    493 static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*& containerNode, int& offsetInContainer)
    494 {
    495     if (node->isTextNode()) {
    496         containerNode = node;
    497         offsetInContainer = offset;
    498     } else {
    499         containerNode = node->parentNode();
    500         offsetInContainer = node->nodeIndex() + offset;
    501     }
    502 }
    503 
    504 PassRefPtrWillBeRawPtr<Range> HTMLTextFormControlElement::selection() const
    505 {
    506     if (!renderer() || !isTextFormControl())
    507         return nullptr;
    508 
    509     int start = m_cachedSelectionStart;
    510     int end = m_cachedSelectionEnd;
    511 
    512     ASSERT(start <= end);
    513     HTMLElement* innerText = innerEditorElement();
    514     if (!innerText)
    515         return nullptr;
    516 
    517     if (!innerText->hasChildren())
    518         return Range::create(document(), innerText, 0, innerText, 0);
    519 
    520     int offset = 0;
    521     Node* startNode = 0;
    522     Node* endNode = 0;
    523     for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(*node, innerText)) {
    524         ASSERT(!node->hasChildren());
    525         ASSERT(node->isTextNode() || isHTMLBRElement(*node));
    526         int length = node->isTextNode() ? lastOffsetInNode(node) : 1;
    527 
    528         if (offset <= start && start <= offset + length)
    529             setContainerAndOffsetForRange(node, start - offset, startNode, start);
    530 
    531         if (offset <= end && end <= offset + length) {
    532             setContainerAndOffsetForRange(node, end - offset, endNode, end);
    533             break;
    534         }
    535 
    536         offset += length;
    537     }
    538 
    539     if (!startNode || !endNode)
    540         return nullptr;
    541 
    542     return Range::create(document(), startNode, start, endNode, end);
    543 }
    544 
    545 void HTMLTextFormControlElement::restoreCachedSelection()
    546 {
    547     setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSelectionDirection);
    548 }
    549 
    550 void HTMLTextFormControlElement::selectionChanged(bool userTriggered)
    551 {
    552     if (!renderer() || !isTextFormControl())
    553         return;
    554 
    555     // selectionStart() or selectionEnd() will return cached selection when this node doesn't have focus
    556     cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSelectionDirection());
    557 
    558     if (LocalFrame* frame = document().frame()) {
    559         if (frame->selection().isRange() && userTriggered)
    560             dispatchEvent(Event::createBubble(EventTypeNames::select));
    561     }
    562 }
    563 
    564 void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
    565 {
    566     if (name == placeholderAttr) {
    567         updatePlaceholderVisibility(true);
    568         UseCounter::count(document(), UseCounter::PlaceholderAttribute);
    569     } else
    570         HTMLFormControlElementWithState::parseAttribute(name, value);
    571 }
    572 
    573 bool HTMLTextFormControlElement::lastChangeWasUserEdit() const
    574 {
    575     if (!isTextFormControl())
    576         return false;
    577     return m_lastChangeWasUserEdit;
    578 }
    579 
    580 void HTMLTextFormControlElement::setInnerEditorValue(const String& value)
    581 {
    582     ASSERT(!hasAuthorShadowRoot());
    583     if (!isTextFormControl() || hasAuthorShadowRoot())
    584         return;
    585 
    586     bool textIsChanged = value != innerEditorValue();
    587     if (textIsChanged || !innerEditorElement()->hasChildren()) {
    588         if (textIsChanged && renderer()) {
    589             if (AXObjectCache* cache = document().existingAXObjectCache())
    590                 cache->postNotification(this, AXObjectCache::AXValueChanged, false);
    591         }
    592         innerEditorElement()->setInnerText(value, ASSERT_NO_EXCEPTION);
    593 
    594         if (value.endsWith('\n') || value.endsWith('\r'))
    595             innerEditorElement()->appendChild(HTMLBRElement::create(document()));
    596     }
    597 }
    598 
    599 static String finishText(StringBuilder& result)
    600 {
    601     // Remove one trailing newline; there's always one that's collapsed out by rendering.
    602     size_t size = result.length();
    603     if (size && result[size - 1] == '\n')
    604         result.resize(--size);
    605     return result.toString();
    606 }
    607 
    608 String HTMLTextFormControlElement::innerEditorValue() const
    609 {
    610     ASSERT(!hasAuthorShadowRoot());
    611     HTMLElement* innerEditor = innerEditorElement();
    612     if (!innerEditor || !isTextFormControl())
    613         return emptyString();
    614 
    615     StringBuilder result;
    616     for (Node* node = innerEditor; node; node = NodeTraversal::next(*node, innerEditor)) {
    617         if (isHTMLBRElement(*node))
    618             result.append(newlineCharacter);
    619         else if (node->isTextNode())
    620             result.append(toText(node)->data());
    621     }
    622     return finishText(result);
    623 }
    624 
    625 static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& breakOffset)
    626 {
    627     RootInlineBox* next;
    628     for (; line; line = next) {
    629         next = line->nextRootBox();
    630         if (next && !line->endsWithBreak()) {
    631             ASSERT(line->lineBreakObj());
    632             breakNode = line->lineBreakObj()->node();
    633             breakOffset = line->lineBreakPos();
    634             line = next;
    635             return;
    636         }
    637     }
    638     breakNode = 0;
    639     breakOffset = 0;
    640 }
    641 
    642 String HTMLTextFormControlElement::valueWithHardLineBreaks() const
    643 {
    644     // FIXME: It's not acceptable to ignore the HardWrap setting when there is no renderer.
    645     // While we have no evidence this has ever been a practical problem, it would be best to fix it some day.
    646     HTMLElement* innerText = innerEditorElement();
    647     if (!innerText || !isTextFormControl())
    648         return value();
    649 
    650     RenderBlockFlow* renderer = toRenderBlockFlow(innerText->renderer());
    651     if (!renderer)
    652         return value();
    653 
    654     Node* breakNode;
    655     unsigned breakOffset;
    656     RootInlineBox* line = renderer->firstRootBox();
    657     if (!line)
    658         return value();
    659 
    660     getNextSoftBreak(line, breakNode, breakOffset);
    661 
    662     StringBuilder result;
    663     for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(*node, innerText)) {
    664         if (isHTMLBRElement(*node))
    665             result.append(newlineCharacter);
    666         else if (node->isTextNode()) {
    667             String data = toText(node)->data();
    668             unsigned length = data.length();
    669             unsigned position = 0;
    670             while (breakNode == node && breakOffset <= length) {
    671                 if (breakOffset > position) {
    672                     result.append(data, position, breakOffset - position);
    673                     position = breakOffset;
    674                     result.append(newlineCharacter);
    675                 }
    676                 getNextSoftBreak(line, breakNode, breakOffset);
    677             }
    678             result.append(data, position, length - position);
    679         }
    680         while (breakNode == node)
    681             getNextSoftBreak(line, breakNode, breakOffset);
    682     }
    683     return finishText(result);
    684 }
    685 
    686 HTMLTextFormControlElement* enclosingTextFormControl(const Position& position)
    687 {
    688     ASSERT(position.isNull() || position.anchorType() == Position::PositionIsOffsetInAnchor
    689         || position.containerNode() || !position.anchorNode()->shadowHost()
    690         || (position.anchorNode()->parentNode() && position.anchorNode()->parentNode()->isShadowRoot()));
    691     return enclosingTextFormControl(position.containerNode());
    692 }
    693 
    694 HTMLTextFormControlElement* enclosingTextFormControl(Node* container)
    695 {
    696     if (!container)
    697         return 0;
    698     Element* ancestor = container->shadowHost();
    699     return ancestor && isHTMLTextFormControlElement(*ancestor) && container->containingShadowRoot()->type() == ShadowRoot::UserAgentShadowRoot ? toHTMLTextFormControlElement(ancestor) : 0;
    700 }
    701 
    702 String HTMLTextFormControlElement::directionForFormData() const
    703 {
    704     for (const HTMLElement* element = this; element; element = Traversal<HTMLElement>::firstAncestor(*element)) {
    705         const AtomicString& dirAttributeValue = element->fastGetAttribute(dirAttr);
    706         if (dirAttributeValue.isNull())
    707             continue;
    708 
    709         if (equalIgnoringCase(dirAttributeValue, "rtl") || equalIgnoringCase(dirAttributeValue, "ltr"))
    710             return dirAttributeValue;
    711 
    712         if (equalIgnoringCase(dirAttributeValue, "auto")) {
    713             bool isAuto;
    714             TextDirection textDirection = element->directionalityIfhasDirAutoAttribute(isAuto);
    715             return textDirection == RTL ? "rtl" : "ltr";
    716         }
    717     }
    718 
    719     return "ltr";
    720 }
    721 
    722 HTMLElement* HTMLTextFormControlElement::innerEditorElement() const
    723 {
    724     return toHTMLElement(userAgentShadowRoot()->getElementById(ShadowElementNames::innerEditor()));
    725 }
    726 
    727 static Position innerNodePosition(const Position& innerPosition)
    728 {
    729     ASSERT(innerPosition.anchorType() != Position::PositionIsBeforeAnchor);
    730     ASSERT(innerPosition.anchorType() != Position::PositionIsAfterAnchor);
    731     HTMLElement* element = toHTMLElement(innerPosition.anchorNode());
    732     ASSERT(element);
    733     RefPtrWillBeRawPtr<NodeList> childNodes = element->childNodes();
    734     if (!childNodes->length())
    735         return Position(element, 0, Position::PositionIsOffsetInAnchor);
    736 
    737     unsigned offset = 0;
    738 
    739     switch (innerPosition.anchorType()) {
    740     case Position::PositionIsOffsetInAnchor:
    741         offset = std::max(0, std::min(innerPosition.offsetInContainerNode(), static_cast<int>(childNodes->length())));
    742         break;
    743     case Position::PositionIsAfterChildren:
    744         offset = childNodes->length();
    745         break;
    746     default:
    747         break;
    748     }
    749 
    750     if (offset == childNodes->length())
    751         return Position(element->lastChild(), Position::PositionIsAfterAnchor);
    752 
    753     Node* node = childNodes->item(offset);
    754     if (node->isTextNode())
    755         return Position(toText(node), 0);
    756 
    757     return Position(node, Position::PositionIsBeforeAnchor);
    758 }
    759 
    760 enum FindOption {
    761     FindStart,
    762     FindEnd
    763 };
    764 
    765 static Position findWordBoundary(const HTMLElement* innerEditor, const Position& startPosition, const Position& endPosition, FindOption findOption)
    766 {
    767     StringBuilder concatTexts;
    768     Vector<unsigned> lengthList;
    769     Vector<Text*> textList;
    770 
    771     if (startPosition.anchorNode()->isTextNode())
    772         ASSERT(startPosition.anchorType() == Position::PositionIsOffsetInAnchor);
    773     if (endPosition.anchorNode()->isTextNode())
    774         ASSERT(endPosition.anchorType() == Position::PositionIsOffsetInAnchor);
    775 
    776     // Traverse text nodes.
    777     for (Node* node = startPosition.anchorNode(); node; node = NodeTraversal::next(*node, innerEditor)) {
    778         bool isStartNode = node == startPosition.anchorNode();
    779         bool isEndNode = node == endPosition.anchorNode();
    780         if (node->isTextNode()) {
    781             Text* text = toText(node);
    782             const unsigned start = isStartNode ? startPosition.offsetInContainerNode() : 0;
    783             const unsigned end = isEndNode ? endPosition.offsetInContainerNode() : text->data().length();
    784             const unsigned length = end - start;
    785 
    786             concatTexts.append(text->data(), start, length);
    787             lengthList.append(length);
    788             textList.append(text);
    789         }
    790 
    791         if (isEndNode)
    792             break;
    793     }
    794 
    795     if (concatTexts.length() == 0)
    796         return startPosition;
    797 
    798     int start, end;
    799     if (findOption == FindEnd && concatTexts[0] == '\n') {
    800         // findWordBoundary("\ntext", 0, &start, &end) assigns 1 to |end| but
    801         // we expect 0 at the case.
    802         start = 0;
    803         end = 0;
    804     } else {
    805         Vector<UChar> characters;
    806         concatTexts.toString().appendTo(characters);
    807         findWordBoundary(characters.data(), characters.size(), findOption == FindStart ? characters.size() : 0, &start, &end);
    808     }
    809     ASSERT(start >= 0);
    810     ASSERT(end >= 0);
    811     unsigned remainingOffset = findOption == FindStart ? start : end;
    812     // Find position.
    813     for (unsigned i = 0; i < lengthList.size(); ++i) {
    814         if (remainingOffset <= lengthList[i])
    815             return Position(textList[i], (textList[i] == startPosition.anchorNode()) ? remainingOffset + startPosition.offsetInContainerNode() : remainingOffset);
    816         remainingOffset -= lengthList[i];
    817     }
    818 
    819     ASSERT_NOT_REACHED();
    820     return Position();
    821 }
    822 
    823 Position HTMLTextFormControlElement::startOfWord(const Position& position)
    824 {
    825     const HTMLTextFormControlElement* textFormControl = enclosingTextFormControl(position);
    826     ASSERT(textFormControl);
    827     HTMLElement* innerEditor = textFormControl->innerEditorElement();
    828 
    829     const Position startPosition = startOfSentence(position);
    830     if (startPosition == position)
    831         return position;
    832     const Position endPosition = (position.anchorNode() == innerEditor) ? innerNodePosition(position) : position;
    833 
    834     return findWordBoundary(innerEditor, startPosition, endPosition, FindStart);
    835 }
    836 
    837 Position HTMLTextFormControlElement::endOfWord(const Position& position)
    838 {
    839     const HTMLTextFormControlElement* textFormControl = enclosingTextFormControl(position);
    840     ASSERT(textFormControl);
    841     HTMLElement* innerEditor = textFormControl->innerEditorElement();
    842 
    843     const Position endPosition = endOfSentence(position);
    844     if (endPosition == position)
    845         return position;
    846     const Position startPosition = (position.anchorNode() == innerEditor) ? innerNodePosition(position) : position;
    847 
    848     return findWordBoundary(innerEditor, startPosition, endPosition, FindEnd);
    849 }
    850 
    851 static Position endOfPrevious(const Node& node, HTMLElement* innerEditor)
    852 {
    853     Node* previousNode = NodeTraversal::previous(node, innerEditor);
    854     if (!previousNode)
    855         return Position();
    856 
    857     if (isHTMLBRElement(previousNode))
    858         return Position(previousNode, Position::PositionIsAfterAnchor);
    859 
    860     if (previousNode->isTextNode())
    861         return Position(toText(previousNode), toText(previousNode)->length());
    862 
    863     return Position();
    864 }
    865 
    866 static Position previousIfPositionIsAfterLineBreak(const Position& position, HTMLElement* innerEditor)
    867 {
    868     if (position.isNull())
    869         return Position();
    870 
    871     // Move back if position is just after line break.
    872     if (isHTMLBRElement(*position.anchorNode())) {
    873         switch (position.anchorType()) {
    874         case Position::PositionIsAfterAnchor:
    875             return Position(position.anchorNode(), Position::PositionIsBeforeAnchor);
    876         case Position::PositionIsBeforeAnchor:
    877             return previousIfPositionIsAfterLineBreak(endOfPrevious(*position.anchorNode(), innerEditor), innerEditor);
    878         default:
    879             ASSERT_NOT_REACHED();
    880         }
    881     } else if (position.anchorNode()->isTextNode()) {
    882         Text* textNode = toText(position.anchorNode());
    883         unsigned offset = position.offsetInContainerNode();
    884         if (textNode->length() == 0 || offset == 0) {
    885             return previousIfPositionIsAfterLineBreak(endOfPrevious(*position.anchorNode(), innerEditor), innerEditor);
    886         }
    887 
    888         if (offset <= textNode->length() && textNode->data()[offset - 1] == '\n') {
    889             return Position(textNode, offset - 1);
    890         }
    891     }
    892 
    893     return position;
    894 }
    895 
    896 static inline Position startOfInnerText(const HTMLTextFormControlElement* textFormControl)
    897 {
    898     return Position(textFormControl->innerEditorElement(), 0, Position::PositionIsOffsetInAnchor);
    899 }
    900 
    901 Position HTMLTextFormControlElement::startOfSentence(const Position& position)
    902 {
    903     HTMLTextFormControlElement* textFormControl = enclosingTextFormControl(position);
    904     ASSERT(textFormControl);
    905 
    906     HTMLElement* innerEditor = textFormControl->innerEditorElement();
    907     if (!innerEditor->childNodes()->length())
    908         return startOfInnerText(textFormControl);
    909 
    910     const Position innerPosition = position.anchorNode() == innerEditor ? innerNodePosition(position) : position;
    911     const Position pivotPosition = previousIfPositionIsAfterLineBreak(innerPosition, innerEditor);
    912     if (pivotPosition.isNull())
    913         return startOfInnerText(textFormControl);
    914 
    915     for (Node* node = pivotPosition.anchorNode(); node; node = NodeTraversal::previous(*node, innerEditor)) {
    916         bool isPivotNode = (node == pivotPosition.anchorNode());
    917 
    918         if (isHTMLBRElement(node) && (!isPivotNode || pivotPosition.anchorType() == Position::PositionIsAfterAnchor))
    919             return Position(node, Position::PositionIsAfterAnchor);
    920 
    921         if (node->isTextNode()) {
    922             Text* textNode = toText(node);
    923             size_t lastLineBreak = textNode->data().substring(0, isPivotNode ? pivotPosition.offsetInContainerNode() : textNode->length()).reverseFind('\n');
    924             if (lastLineBreak != kNotFound)
    925                 return Position(textNode, lastLineBreak + 1);
    926         }
    927     }
    928     return startOfInnerText(textFormControl);
    929 }
    930 
    931 static Position endOfInnerText(const HTMLTextFormControlElement* textFormControl)
    932 {
    933     HTMLElement* innerEditor = textFormControl->innerEditorElement();
    934     return Position(innerEditor, innerEditor->childNodes()->length(), Position::PositionIsOffsetInAnchor);
    935 }
    936 
    937 Position HTMLTextFormControlElement::endOfSentence(const Position& position)
    938 {
    939     HTMLTextFormControlElement* textFormControl = enclosingTextFormControl(position);
    940     ASSERT(textFormControl);
    941 
    942     HTMLElement* innerEditor = textFormControl->innerEditorElement();
    943     if (innerEditor->childNodes()->length() == 0)
    944         return startOfInnerText(textFormControl);
    945 
    946     const Position pivotPosition = position.anchorNode() == innerEditor ? innerNodePosition(position) : position;
    947     if (pivotPosition.isNull())
    948         return startOfInnerText(textFormControl);
    949 
    950     for (Node* node = pivotPosition.anchorNode(); node; node = NodeTraversal::next(*node, innerEditor)) {
    951         bool isPivotNode = node == pivotPosition.anchorNode();
    952 
    953         if (isHTMLBRElement(node))
    954             return Position(node, Position::PositionIsAfterAnchor);
    955 
    956         if (node->isTextNode()) {
    957             Text* textNode = toText(node);
    958             size_t firstLineBreak = textNode->data().find('\n', isPivotNode ? pivotPosition.offsetInContainerNode() : 0);
    959             if (firstLineBreak != kNotFound)
    960                 return Position(textNode, firstLineBreak + 1);
    961         }
    962     }
    963     return endOfInnerText(textFormControl);
    964 }
    965 
    966 } // namespace blink
    967