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/v8/ExceptionState.h"
     29 #include "bindings/v8/ExceptionStatePlaceholder.h"
     30 #include "core/HTMLNames.h"
     31 #include "core/accessibility/AXObjectCache.h"
     32 #include "core/dom/Document.h"
     33 #include "core/dom/NodeTraversal.h"
     34 #include "core/dom/Text.h"
     35 #include "core/dom/shadow/ShadowRoot.h"
     36 #include "core/editing/FrameSelection.h"
     37 #include "core/editing/TextIterator.h"
     38 #include "core/events/Event.h"
     39 #include "core/frame/LocalFrame.h"
     40 #include "core/frame/UseCounter.h"
     41 #include "core/html/HTMLBRElement.h"
     42 #include "core/html/shadow/ShadowElementNames.h"
     43 #include "core/rendering/RenderBlock.h"
     44 #include "core/rendering/RenderTheme.h"
     45 #include "platform/heap/Handle.h"
     46 #include "wtf/text/StringBuilder.h"
     47 
     48 namespace WebCore {
     49 
     50 using namespace HTMLNames;
     51 
     52 HTMLTextFormControlElement::HTMLTextFormControlElement(const QualifiedName& tagName, Document& doc, HTMLFormElement* form)
     53     : HTMLFormControlElementWithState(tagName, doc, form)
     54     , m_lastChangeWasUserEdit(false)
     55     , m_cachedSelectionStart(0)
     56     , m_cachedSelectionEnd(0)
     57     , m_cachedSelectionDirection(SelectionHasNoDirection)
     58 {
     59 }
     60 
     61 HTMLTextFormControlElement::~HTMLTextFormControlElement()
     62 {
     63 }
     64 
     65 Node::InsertionNotificationRequest HTMLTextFormControlElement::insertedInto(ContainerNode* insertionPoint)
     66 {
     67     HTMLFormControlElementWithState::insertedInto(insertionPoint);
     68     if (!insertionPoint->inDocument())
     69         return InsertionDone;
     70     String initialValue = value();
     71     setTextAsOfLastFormControlChangeEvent(initialValue.isNull() ? emptyString() : initialValue);
     72     return InsertionDone;
     73 }
     74 
     75 void HTMLTextFormControlElement::dispatchFocusEvent(Element* oldFocusedElement, FocusType type)
     76 {
     77     if (supportsPlaceholder())
     78         updatePlaceholderVisibility(false);
     79     handleFocusEvent(oldFocusedElement, type);
     80     HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedElement, type);
     81 }
     82 
     83 void HTMLTextFormControlElement::dispatchBlurEvent(Element* newFocusedElement)
     84 {
     85     if (supportsPlaceholder())
     86         updatePlaceholderVisibility(false);
     87     handleBlurEvent();
     88     HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement);
     89 }
     90 
     91 void HTMLTextFormControlElement::defaultEventHandler(Event* event)
     92 {
     93     if (event->type() == EventTypeNames::webkitEditableContentChanged && renderer() && renderer()->isTextControl()) {
     94         m_lastChangeWasUserEdit = true;
     95         subtreeHasChanged();
     96         return;
     97     }
     98 
     99     HTMLFormControlElementWithState::defaultEventHandler(event);
    100 }
    101 
    102 void HTMLTextFormControlElement::forwardEvent(Event* event)
    103 {
    104     if (event->type() == EventTypeNames::blur || event->type() == EventTypeNames::focus)
    105         return;
    106     innerEditorElement()->defaultEventHandler(event);
    107 }
    108 
    109 String HTMLTextFormControlElement::strippedPlaceholder() const
    110 {
    111     // According to the HTML5 specification, we need to remove CR and LF from
    112     // the attribute value.
    113     const AtomicString& attributeValue = fastGetAttribute(placeholderAttr);
    114     if (!attributeValue.contains(newlineCharacter) && !attributeValue.contains(carriageReturn))
    115         return attributeValue;
    116 
    117     StringBuilder stripped;
    118     unsigned length = attributeValue.length();
    119     stripped.reserveCapacity(length);
    120     for (unsigned i = 0; i < length; ++i) {
    121         UChar character = attributeValue[i];
    122         if (character == newlineCharacter || character == carriageReturn)
    123             continue;
    124         stripped.append(character);
    125     }
    126     return stripped.toString();
    127 }
    128 
    129 static bool isNotLineBreak(UChar ch) { return ch != newlineCharacter && ch != carriageReturn; }
    130 
    131 bool HTMLTextFormControlElement::isPlaceholderEmpty() const
    132 {
    133     const AtomicString& attributeValue = fastGetAttribute(placeholderAttr);
    134     return attributeValue.string().find(isNotLineBreak) == kNotFound;
    135 }
    136 
    137 bool HTMLTextFormControlElement::placeholderShouldBeVisible() const
    138 {
    139     return supportsPlaceholder()
    140         && isEmptyValue()
    141         && isEmptySuggestedValue()
    142         && !isPlaceholderEmpty()
    143         && (document().focusedElement() != this || (RenderTheme::theme().shouldShowPlaceholderWhenFocused()))
    144         && (!renderer() || renderer()->style()->visibility() == VISIBLE);
    145 }
    146 
    147 HTMLElement* HTMLTextFormControlElement::placeholderElement() const
    148 {
    149     return toHTMLElement(userAgentShadowRoot()->getElementById(ShadowElementNames::placeholder()));
    150 }
    151 
    152 void HTMLTextFormControlElement::updatePlaceholderVisibility(bool placeholderValueChanged)
    153 {
    154     if (!supportsPlaceholder())
    155         return;
    156     if (!placeholderElement() || placeholderValueChanged)
    157         updatePlaceholderText();
    158     HTMLElement* placeholder = placeholderElement();
    159     if (!placeholder)
    160         return;
    161     placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShouldBeVisible() ? CSSValueVisible : CSSValueHidden);
    162 }
    163 
    164 void HTMLTextFormControlElement::setSelectionStart(int start)
    165 {
    166     setSelectionRange(start, std::max(start, selectionEnd()), selectionDirection());
    167 }
    168 
    169 void HTMLTextFormControlElement::setSelectionEnd(int end)
    170 {
    171     setSelectionRange(std::min(end, selectionStart()), end, selectionDirection());
    172 }
    173 
    174 void HTMLTextFormControlElement::setSelectionDirection(const String& direction)
    175 {
    176     setSelectionRange(selectionStart(), selectionEnd(), direction);
    177 }
    178 
    179 void HTMLTextFormControlElement::select()
    180 {
    181     setSelectionRange(0, std::numeric_limits<int>::max(), SelectionHasNoDirection);
    182 }
    183 
    184 bool HTMLTextFormControlElement::shouldDispatchFormControlChangeEvent(String& oldValue, String& newValue)
    185 {
    186     return !equalIgnoringNullity(oldValue, newValue);
    187 }
    188 
    189 void HTMLTextFormControlElement::dispatchFormControlChangeEvent()
    190 {
    191     String newValue = value();
    192     if (shouldDispatchFormControlChangeEvent(m_textAsOfLastFormControlChangeEvent, newValue)) {
    193         setTextAsOfLastFormControlChangeEvent(newValue);
    194         dispatchChangeEvent();
    195     }
    196     setChangedSinceLastFormControlChangeEvent(false);
    197 }
    198 
    199 static inline bool hasVisibleTextArea(RenderObject* renderer, HTMLElement* innerText)
    200 {
    201     ASSERT(renderer);
    202     return renderer->style()->visibility() != HIDDEN && innerText && innerText->renderer() && innerText->renderBox()->height();
    203 }
    204 
    205 
    206 void HTMLTextFormControlElement::setRangeText(const String& replacement, ExceptionState& exceptionState)
    207 {
    208     setRangeText(replacement, selectionStart(), selectionEnd(), String(), exceptionState);
    209 }
    210 
    211 void HTMLTextFormControlElement::setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState& exceptionState)
    212 {
    213     if (start > end) {
    214         exceptionState.throwDOMException(IndexSizeError, "The provided start value (" + String::number(start) + ") is larger than the provided end value (" + String::number(end) + ").");
    215         return;
    216     }
    217     if (hasAuthorShadowRoot())
    218         return;
    219 
    220     String text = innerEditorValue();
    221     unsigned textLength = text.length();
    222     unsigned replacementLength = replacement.length();
    223     unsigned newSelectionStart = selectionStart();
    224     unsigned newSelectionEnd = selectionEnd();
    225 
    226     start = std::min(start, textLength);
    227     end = std::min(end, textLength);
    228 
    229     if (start < end)
    230         text.replace(start, end - start, replacement);
    231     else
    232         text.insert(replacement, start);
    233 
    234     setInnerEditorValue(text);
    235 
    236     // FIXME: What should happen to the value (as in value()) if there's no renderer?
    237     if (!renderer())
    238         return;
    239 
    240     subtreeHasChanged();
    241 
    242     if (equalIgnoringCase(selectionMode, "select")) {
    243         newSelectionStart = start;
    244         newSelectionEnd = start + replacementLength;
    245     } else if (equalIgnoringCase(selectionMode, "start"))
    246         newSelectionStart = newSelectionEnd = start;
    247     else if (equalIgnoringCase(selectionMode, "end"))
    248         newSelectionStart = newSelectionEnd = start + replacementLength;
    249     else {
    250         // Default is "preserve".
    251         long delta = replacementLength - (end - start);
    252 
    253         if (newSelectionStart > end)
    254             newSelectionStart += delta;
    255         else if (newSelectionStart > start)
    256             newSelectionStart = start;
    257 
    258         if (newSelectionEnd > end)
    259             newSelectionEnd += delta;
    260         else if (newSelectionEnd > start)
    261             newSelectionEnd = start + replacementLength;
    262     }
    263 
    264     setSelectionRange(newSelectionStart, newSelectionEnd, SelectionHasNoDirection);
    265 }
    266 
    267 void HTMLTextFormControlElement::setSelectionRange(int start, int end, const String& directionString)
    268 {
    269     TextFieldSelectionDirection direction = SelectionHasNoDirection;
    270     if (directionString == "forward")
    271         direction = SelectionHasForwardDirection;
    272     else if (directionString == "backward")
    273         direction = SelectionHasBackwardDirection;
    274 
    275     return setSelectionRange(start, end, direction);
    276 }
    277 
    278 void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextFieldSelectionDirection direction)
    279 {
    280     document().updateLayoutIgnorePendingStylesheets();
    281 
    282     if (!renderer() || !renderer()->isTextControl())
    283         return;
    284 
    285     end = std::max(end, 0);
    286     start = std::min(std::max(start, 0), end);
    287 
    288     if (!hasVisibleTextArea(renderer(), innerEditorElement())) {
    289         cacheSelection(start, end, direction);
    290         return;
    291     }
    292     VisiblePosition startPosition = visiblePositionForIndex(start);
    293     VisiblePosition endPosition;
    294     if (start == end)
    295         endPosition = startPosition;
    296     else
    297         endPosition = visiblePositionForIndex(end);
    298 
    299     // startPosition and endPosition can be null position for example when
    300     // "-webkit-user-select: none" style attribute is specified.
    301     if (startPosition.isNotNull() && endPosition.isNotNull()) {
    302         ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() == this
    303             && endPosition.deepEquivalent().deprecatedNode()->shadowHost() == this);
    304     }
    305     VisibleSelection newSelection;
    306     if (direction == SelectionHasBackwardDirection)
    307         newSelection = VisibleSelection(endPosition, startPosition);
    308     else
    309         newSelection = VisibleSelection(startPosition, endPosition);
    310     newSelection.setIsDirectional(direction != SelectionHasNoDirection);
    311 
    312     if (LocalFrame* frame = document().frame())
    313         frame->selection().setSelection(newSelection);
    314 }
    315 
    316 VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) const
    317 {
    318     if (index <= 0)
    319         return VisiblePosition(firstPositionInNode(innerEditorElement()), DOWNSTREAM);
    320     RefPtrWillBeRawPtr<Range> range = Range::create(document());
    321     range->selectNodeContents(innerEditorElement(), ASSERT_NO_EXCEPTION);
    322     CharacterIterator it(range.get());
    323     it.advance(index - 1);
    324     return VisiblePosition(it.range()->endPosition(), UPSTREAM);
    325 }
    326 
    327 int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& pos) const
    328 {
    329     Position indexPosition = pos.deepEquivalent().parentAnchoredEquivalent();
    330     if (enclosingTextFormControl(indexPosition) != this)
    331         return 0;
    332     ASSERT(indexPosition.document());
    333     RefPtrWillBeRawPtr<Range> range = Range::create(*indexPosition.document());
    334     range->setStart(innerEditorElement(), 0, ASSERT_NO_EXCEPTION);
    335     range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainerNode(), ASSERT_NO_EXCEPTION);
    336     return TextIterator::rangeLength(range.get());
    337 }
    338 
    339 int HTMLTextFormControlElement::selectionStart() const
    340 {
    341     if (!isTextFormControl())
    342         return 0;
    343     if (document().focusedElement() != this)
    344         return m_cachedSelectionStart;
    345 
    346     return computeSelectionStart();
    347 }
    348 
    349 int HTMLTextFormControlElement::computeSelectionStart() const
    350 {
    351     ASSERT(isTextFormControl());
    352     LocalFrame* frame = document().frame();
    353     if (!frame)
    354         return 0;
    355 
    356     return indexForVisiblePosition(VisiblePosition(frame->selection().start()));
    357 }
    358 
    359 int HTMLTextFormControlElement::selectionEnd() const
    360 {
    361     if (!isTextFormControl())
    362         return 0;
    363     if (document().focusedElement() != this)
    364         return m_cachedSelectionEnd;
    365     return computeSelectionEnd();
    366 }
    367 
    368 int HTMLTextFormControlElement::computeSelectionEnd() const
    369 {
    370     ASSERT(isTextFormControl());
    371     LocalFrame* frame = document().frame();
    372     if (!frame)
    373         return 0;
    374 
    375     return indexForVisiblePosition(VisiblePosition(frame->selection().end()));
    376 }
    377 
    378 static const AtomicString& directionString(TextFieldSelectionDirection direction)
    379 {
    380     DEFINE_STATIC_LOCAL(const AtomicString, none, ("none", AtomicString::ConstructFromLiteral));
    381     DEFINE_STATIC_LOCAL(const AtomicString, forward, ("forward", AtomicString::ConstructFromLiteral));
    382     DEFINE_STATIC_LOCAL(const AtomicString, backward, ("backward", AtomicString::ConstructFromLiteral));
    383 
    384     switch (direction) {
    385     case SelectionHasNoDirection:
    386         return none;
    387     case SelectionHasForwardDirection:
    388         return forward;
    389     case SelectionHasBackwardDirection:
    390         return backward;
    391     }
    392 
    393     ASSERT_NOT_REACHED();
    394     return none;
    395 }
    396 
    397 const AtomicString& HTMLTextFormControlElement::selectionDirection() const
    398 {
    399     if (!isTextFormControl())
    400         return directionString(SelectionHasNoDirection);
    401     if (document().focusedElement() != this)
    402         return directionString(m_cachedSelectionDirection);
    403 
    404     return directionString(computeSelectionDirection());
    405 }
    406 
    407 TextFieldSelectionDirection HTMLTextFormControlElement::computeSelectionDirection() const
    408 {
    409     ASSERT(isTextFormControl());
    410     LocalFrame* frame = document().frame();
    411     if (!frame)
    412         return SelectionHasNoDirection;
    413 
    414     const VisibleSelection& selection = frame->selection().selection();
    415     return selection.isDirectional() ? (selection.isBaseFirst() ? SelectionHasForwardDirection : SelectionHasBackwardDirection) : SelectionHasNoDirection;
    416 }
    417 
    418 static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*& containerNode, int& offsetInContainer)
    419 {
    420     if (node->isTextNode()) {
    421         containerNode = node;
    422         offsetInContainer = offset;
    423     } else {
    424         containerNode = node->parentNode();
    425         offsetInContainer = node->nodeIndex() + offset;
    426     }
    427 }
    428 
    429 PassRefPtrWillBeRawPtr<Range> HTMLTextFormControlElement::selection() const
    430 {
    431     if (!renderer() || !isTextFormControl())
    432         return nullptr;
    433 
    434     int start = m_cachedSelectionStart;
    435     int end = m_cachedSelectionEnd;
    436 
    437     ASSERT(start <= end);
    438     HTMLElement* innerText = innerEditorElement();
    439     if (!innerText)
    440         return nullptr;
    441 
    442     if (!innerText->firstChild())
    443         return Range::create(document(), innerText, 0, innerText, 0);
    444 
    445     int offset = 0;
    446     Node* startNode = 0;
    447     Node* endNode = 0;
    448     for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(*node, innerText)) {
    449         ASSERT(!node->firstChild());
    450         ASSERT(node->isTextNode() || isHTMLBRElement(*node));
    451         int length = node->isTextNode() ? lastOffsetInNode(node) : 1;
    452 
    453         if (offset <= start && start <= offset + length)
    454             setContainerAndOffsetForRange(node, start - offset, startNode, start);
    455 
    456         if (offset <= end && end <= offset + length) {
    457             setContainerAndOffsetForRange(node, end - offset, endNode, end);
    458             break;
    459         }
    460 
    461         offset += length;
    462     }
    463 
    464     if (!startNode || !endNode)
    465         return nullptr;
    466 
    467     return Range::create(document(), startNode, start, endNode, end);
    468 }
    469 
    470 void HTMLTextFormControlElement::restoreCachedSelection()
    471 {
    472     setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSelectionDirection);
    473 }
    474 
    475 void HTMLTextFormControlElement::selectionChanged(bool userTriggered)
    476 {
    477     if (!renderer() || !isTextFormControl())
    478         return;
    479 
    480     // selectionStart() or selectionEnd() will return cached selection when this node doesn't have focus
    481     cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSelectionDirection());
    482 
    483     if (LocalFrame* frame = document().frame()) {
    484         if (frame->selection().isRange() && userTriggered)
    485             dispatchEvent(Event::createBubble(EventTypeNames::select));
    486     }
    487 }
    488 
    489 void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
    490 {
    491     if (name == placeholderAttr) {
    492         updatePlaceholderVisibility(true);
    493         UseCounter::count(document(), UseCounter::PlaceholderAttribute);
    494     } else
    495         HTMLFormControlElementWithState::parseAttribute(name, value);
    496 }
    497 
    498 bool HTMLTextFormControlElement::lastChangeWasUserEdit() const
    499 {
    500     if (!isTextFormControl())
    501         return false;
    502     return m_lastChangeWasUserEdit;
    503 }
    504 
    505 void HTMLTextFormControlElement::setInnerEditorValue(const String& value)
    506 {
    507     ASSERT(!hasAuthorShadowRoot());
    508     if (!isTextFormControl() || hasAuthorShadowRoot())
    509         return;
    510 
    511     bool textIsChanged = value != innerEditorValue();
    512     if (textIsChanged || !innerEditorElement()->hasChildren()) {
    513         if (textIsChanged && renderer()) {
    514             if (AXObjectCache* cache = document().existingAXObjectCache())
    515                 cache->postNotification(this, AXObjectCache::AXValueChanged, false);
    516         }
    517         innerEditorElement()->setInnerText(value, ASSERT_NO_EXCEPTION);
    518 
    519         if (value.endsWith('\n') || value.endsWith('\r'))
    520             innerEditorElement()->appendChild(HTMLBRElement::create(document()));
    521     }
    522 }
    523 
    524 static String finishText(StringBuilder& result)
    525 {
    526     // Remove one trailing newline; there's always one that's collapsed out by rendering.
    527     size_t size = result.length();
    528     if (size && result[size - 1] == '\n')
    529         result.resize(--size);
    530     return result.toString();
    531 }
    532 
    533 String HTMLTextFormControlElement::innerEditorValue() const
    534 {
    535     ASSERT(!hasAuthorShadowRoot());
    536     HTMLElement* innerEditor = innerEditorElement();
    537     if (!innerEditor || !isTextFormControl())
    538         return emptyString();
    539 
    540     StringBuilder result;
    541     for (Node* node = innerEditor; node; node = NodeTraversal::next(*node, innerEditor)) {
    542         if (isHTMLBRElement(*node))
    543             result.append(newlineCharacter);
    544         else if (node->isTextNode())
    545             result.append(toText(node)->data());
    546     }
    547     return finishText(result);
    548 }
    549 
    550 static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& breakOffset)
    551 {
    552     RootInlineBox* next;
    553     for (; line; line = next) {
    554         next = line->nextRootBox();
    555         if (next && !line->endsWithBreak()) {
    556             ASSERT(line->lineBreakObj());
    557             breakNode = line->lineBreakObj()->node();
    558             breakOffset = line->lineBreakPos();
    559             line = next;
    560             return;
    561         }
    562     }
    563     breakNode = 0;
    564     breakOffset = 0;
    565 }
    566 
    567 String HTMLTextFormControlElement::valueWithHardLineBreaks() const
    568 {
    569     // FIXME: It's not acceptable to ignore the HardWrap setting when there is no renderer.
    570     // While we have no evidence this has ever been a practical problem, it would be best to fix it some day.
    571     HTMLElement* innerText = innerEditorElement();
    572     if (!innerText || !isTextFormControl())
    573         return value();
    574 
    575     RenderBlock* renderer = toRenderBlock(innerText->renderer());
    576     if (!renderer)
    577         return value();
    578 
    579     Node* breakNode;
    580     unsigned breakOffset;
    581     RootInlineBox* line = renderer->firstRootBox();
    582     if (!line)
    583         return value();
    584 
    585     getNextSoftBreak(line, breakNode, breakOffset);
    586 
    587     StringBuilder result;
    588     for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(*node, innerText)) {
    589         if (isHTMLBRElement(*node))
    590             result.append(newlineCharacter);
    591         else if (node->isTextNode()) {
    592             String data = toText(node)->data();
    593             unsigned length = data.length();
    594             unsigned position = 0;
    595             while (breakNode == node && breakOffset <= length) {
    596                 if (breakOffset > position) {
    597                     result.append(data, position, breakOffset - position);
    598                     position = breakOffset;
    599                     result.append(newlineCharacter);
    600                 }
    601                 getNextSoftBreak(line, breakNode, breakOffset);
    602             }
    603             result.append(data, position, length - position);
    604         }
    605         while (breakNode == node)
    606             getNextSoftBreak(line, breakNode, breakOffset);
    607     }
    608     return finishText(result);
    609 }
    610 
    611 HTMLTextFormControlElement* enclosingTextFormControl(const Position& position)
    612 {
    613     ASSERT(position.isNull() || position.anchorType() == Position::PositionIsOffsetInAnchor
    614         || position.containerNode() || !position.anchorNode()->shadowHost()
    615         || (position.anchorNode()->parentNode() && position.anchorNode()->parentNode()->isShadowRoot()));
    616     return enclosingTextFormControl(position.containerNode());
    617 }
    618 
    619 HTMLTextFormControlElement* enclosingTextFormControl(Node* container)
    620 {
    621     if (!container)
    622         return 0;
    623     Element* ancestor = container->shadowHost();
    624     return ancestor && isHTMLTextFormControlElement(*ancestor) && container->containingShadowRoot()->type() == ShadowRoot::UserAgentShadowRoot ? toHTMLTextFormControlElement(ancestor) : 0;
    625 }
    626 
    627 static const HTMLElement* parentHTMLElement(const Element* element)
    628 {
    629     while (element) {
    630         element = element->parentElement();
    631         if (element && element->isHTMLElement())
    632             return toHTMLElement(element);
    633     }
    634     return 0;
    635 }
    636 
    637 String HTMLTextFormControlElement::directionForFormData() const
    638 {
    639     for (const HTMLElement* element = this; element; element = parentHTMLElement(element)) {
    640         const AtomicString& dirAttributeValue = element->fastGetAttribute(dirAttr);
    641         if (dirAttributeValue.isNull())
    642             continue;
    643 
    644         if (equalIgnoringCase(dirAttributeValue, "rtl") || equalIgnoringCase(dirAttributeValue, "ltr"))
    645             return dirAttributeValue;
    646 
    647         if (equalIgnoringCase(dirAttributeValue, "auto")) {
    648             bool isAuto;
    649             TextDirection textDirection = element->directionalityIfhasDirAutoAttribute(isAuto);
    650             return textDirection == RTL ? "rtl" : "ltr";
    651         }
    652     }
    653 
    654     return "ltr";
    655 }
    656 
    657 HTMLElement* HTMLTextFormControlElement::innerEditorElement() const
    658 {
    659     return toHTMLElement(userAgentShadowRoot()->getElementById(ShadowElementNames::innerEditor()));
    660 }
    661 
    662 } // namespace Webcore
    663