REGRESSION(r231291): InputType should hold a WeakPtr to its HTMLInputElement
[WebKit-https.git] / Source / WebCore / html / TextFieldInputType.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33 #include "TextFieldInputType.h"
34
35 #include "BeforeTextInsertedEvent.h"
36 #include "Chrome.h"
37 #include "ChromeClient.h"
38 #include "DOMFormData.h"
39 #include "Editor.h"
40 #include "EventNames.h"
41 #include "Frame.h"
42 #include "FrameSelection.h"
43 #include "HTMLInputElement.h"
44 #include "HTMLNames.h"
45 #include "HTMLParserIdioms.h"
46 #include "KeyboardEvent.h"
47 #include "LocalizedStrings.h"
48 #include "NodeRenderStyle.h"
49 #include "Page.h"
50 #include "PlatformKeyboardEvent.h"
51 #include "RenderLayer.h"
52 #include "RenderTextControlSingleLine.h"
53 #include "RenderTheme.h"
54 #include "ShadowRoot.h"
55 #include "TextControlInnerElements.h"
56 #include "TextEvent.h"
57 #include "TextIterator.h"
58 #include "TextNodeTraversal.h"
59 #include "WheelEvent.h"
60
61 namespace WebCore {
62
63 using namespace HTMLNames;
64
65 TextFieldInputType::TextFieldInputType(HTMLInputElement& element)
66     : InputType(element)
67 {
68 }
69
70 TextFieldInputType::~TextFieldInputType()
71 {
72     if (m_innerSpinButton)
73         m_innerSpinButton->removeSpinButtonOwner();
74 }
75
76 bool TextFieldInputType::isKeyboardFocusable(KeyboardEvent*) const
77 {
78     ASSERT(element());
79 #if PLATFORM(IOS)
80     if (element()->isReadOnly())
81         return false;
82 #endif
83     return element()->isTextFormControlFocusable();
84 }
85
86 bool TextFieldInputType::isMouseFocusable() const
87 {
88     ASSERT(element());
89     return element()->isTextFormControlFocusable();
90 }
91
92 bool TextFieldInputType::isTextField() const
93 {
94     return true;
95 }
96
97 bool TextFieldInputType::isEmptyValue() const
98 {
99     auto innerText = innerTextElement();
100     ASSERT(innerText);
101
102     for (Text* text = TextNodeTraversal::firstWithin(*innerText); text; text = TextNodeTraversal::next(*text, innerText.get())) {
103         if (text->length())
104             return false;
105     }
106     return true;
107 }
108
109 bool TextFieldInputType::valueMissing(const String& value) const
110 {
111     ASSERT(element());
112     return element()->isRequired() && value.isEmpty();
113 }
114
115 void TextFieldInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
116 {
117     ASSERT(element());
118
119     // Grab this input element to keep reference even if JS event handler
120     // changes input type.
121     Ref<HTMLInputElement> input(*element());
122
123     // We don't ask InputType::setValue to dispatch events because
124     // TextFieldInputType dispatches events different way from InputType.
125     InputType::setValue(sanitizedValue, valueChanged, DispatchNoEvent);
126
127     if (valueChanged)
128         updateInnerTextValue();
129
130     unsigned max = visibleValue().length();
131     if (input->focused())
132         input->setSelectionRange(max, max);
133     else
134         input->cacheSelectionInResponseToSetValue(max);
135
136     if (!valueChanged)
137         return;
138
139     switch (eventBehavior) {
140     case DispatchChangeEvent:
141         // If the user is still editing this field, dispatch an input event rather than a change event.
142         // The change event will be dispatched when editing finishes.
143         if (input->focused())
144             input->dispatchFormControlInputEvent();
145         else
146             input->dispatchFormControlChangeEvent();
147         break;
148
149     case DispatchInputAndChangeEvent: {
150         input->dispatchFormControlInputEvent();
151         input->dispatchFormControlChangeEvent();
152         break;
153     }
154
155     case DispatchNoEvent:
156         break;
157     }
158
159     // FIXME: Why do we do this when eventBehavior == DispatchNoEvent
160     if (!input->focused() || eventBehavior == DispatchNoEvent)
161         input->setTextAsOfLastFormControlChangeEvent(sanitizedValue);
162 }
163
164 void TextFieldInputType::handleKeydownEvent(KeyboardEvent& event)
165 {
166     ASSERT(element());
167     if (!element()->focused())
168         return;
169     RefPtr<Frame> frame = element()->document().frame();
170     if (!frame || !frame->editor().doTextFieldCommandFromEvent(element(), &event))
171         return;
172     event.setDefaultHandled();
173 }
174
175 void TextFieldInputType::handleKeydownEventForSpinButton(KeyboardEvent& event)
176 {
177     ASSERT(element());
178     if (element()->isDisabledOrReadOnly())
179         return;
180     const String& key = event.keyIdentifier();
181     if (key == "Up")
182         spinButtonStepUp();
183     else if (key == "Down")
184         spinButtonStepDown();
185     else
186         return;
187     event.setDefaultHandled();
188 }
189
190 void TextFieldInputType::forwardEvent(Event& event)
191 {
192     if (m_innerSpinButton) {
193         m_innerSpinButton->forwardEvent(event);
194         if (event.defaultHandled())
195             return;
196     }
197
198     bool isFocusEvent = event.type() == eventNames().focusEvent;
199     bool isBlurEvent = event.type() == eventNames().blurEvent;
200     if (isFocusEvent || isBlurEvent)
201         capsLockStateMayHaveChanged();
202     if (event.isMouseEvent() || isFocusEvent || isBlurEvent) {
203         ASSERT(element());
204         element()->forwardEvent(event);
205     }
206 }
207
208 void TextFieldInputType::elementDidBlur()
209 {
210     ASSERT(element());
211     auto* renderer = element()->renderer();
212     if (!renderer)
213         return;
214
215     auto* innerTextRenderer = innerTextElement()->renderer();
216     if (!innerTextRenderer)
217         return;
218
219     auto* innerLayer = innerTextRenderer->layer();
220     if (!innerLayer)
221         return;
222
223     bool isLeftToRightDirection = downcast<RenderTextControlSingleLine>(*renderer).style().isLeftToRightDirection();
224     ScrollOffset scrollOffset(isLeftToRightDirection ? 0 : innerLayer->scrollWidth(), 0);
225     innerLayer->scrollToOffset(scrollOffset);
226 }
227
228 void TextFieldInputType::handleFocusEvent(Node* oldFocusedNode, FocusDirection)
229 {
230     ASSERT(element());
231     ASSERT_UNUSED(oldFocusedNode, oldFocusedNode != element());
232     if (RefPtr<Frame> frame = element()->document().frame())
233         frame->editor().textFieldDidBeginEditing(element());
234 }
235
236 void TextFieldInputType::handleBlurEvent()
237 {
238     InputType::handleBlurEvent();
239     ASSERT(element());
240     element()->endEditing();
241 }
242
243 bool TextFieldInputType::shouldSubmitImplicitly(Event& event)
244 {
245     return (event.type() == eventNames().textInputEvent && is<TextEvent>(event) && downcast<TextEvent>(event).data() == "\n")
246         || InputType::shouldSubmitImplicitly(event);
247 }
248
249 RenderPtr<RenderElement> TextFieldInputType::createInputRenderer(RenderStyle&& style)
250 {
251     ASSERT(element());
252     return createRenderer<RenderTextControlSingleLine>(*element(), WTFMove(style));
253 }
254
255 bool TextFieldInputType::needsContainer() const
256 {
257     return false;
258 }
259
260 bool TextFieldInputType::shouldHaveSpinButton() const
261 {
262     ASSERT(element());
263     return RenderTheme::singleton().shouldHaveSpinButton(*element());
264 }
265
266 bool TextFieldInputType::shouldHaveCapsLockIndicator() const
267 {
268     ASSERT(element());
269     return RenderTheme::singleton().shouldHaveCapsLockIndicator(*element());
270 }
271
272 void TextFieldInputType::createShadowSubtree()
273 {
274     ASSERT(element());
275     ASSERT(element()->shadowRoot());
276
277     ASSERT(!m_innerText);
278     ASSERT(!m_innerBlock);
279     ASSERT(!m_innerSpinButton);
280     ASSERT(!m_capsLockIndicator);
281     ASSERT(!m_autoFillButton);
282
283     Document& document = element()->document();
284     bool shouldHaveSpinButton = this->shouldHaveSpinButton();
285     bool shouldHaveCapsLockIndicator = this->shouldHaveCapsLockIndicator();
286     bool createsContainer = shouldHaveSpinButton || shouldHaveCapsLockIndicator || needsContainer();
287
288     m_innerText = TextControlInnerTextElement::create(document);
289
290     if (!createsContainer) {
291         element()->userAgentShadowRoot()->appendChild(*m_innerText);
292         updatePlaceholderText();
293         return;
294     }
295
296     createContainer();
297     updatePlaceholderText();
298
299     if (shouldHaveSpinButton) {
300         m_innerSpinButton = SpinButtonElement::create(document, *this);
301         m_container->appendChild(*m_innerSpinButton);
302     }
303
304     if (shouldHaveCapsLockIndicator) {
305         m_capsLockIndicator = HTMLDivElement::create(document);
306         m_capsLockIndicator->setPseudo(AtomicString("-webkit-caps-lock-indicator", AtomicString::ConstructFromLiteral));
307
308         bool shouldDrawCapsLockIndicator = this->shouldDrawCapsLockIndicator();
309         m_capsLockIndicator->setInlineStyleProperty(CSSPropertyDisplay, shouldDrawCapsLockIndicator ? CSSValueBlock : CSSValueNone, true);
310
311         m_container->appendChild(*m_capsLockIndicator);
312     }
313
314     updateAutoFillButton();
315 }
316
317 HTMLElement* TextFieldInputType::containerElement() const
318 {
319     return m_container.get();
320 }
321
322 HTMLElement* TextFieldInputType::innerBlockElement() const
323 {
324     return m_innerBlock.get();
325 }
326
327 RefPtr<TextControlInnerTextElement> TextFieldInputType::innerTextElement() const
328 {
329     ASSERT(m_innerText);
330     return m_innerText;
331 }
332
333 HTMLElement* TextFieldInputType::innerSpinButtonElement() const
334 {
335     return m_innerSpinButton.get();
336 }
337
338 HTMLElement* TextFieldInputType::capsLockIndicatorElement() const
339 {
340     return m_capsLockIndicator.get();
341 }
342
343 HTMLElement* TextFieldInputType::autoFillButtonElement() const
344 {
345     return m_autoFillButton.get();
346 }
347
348 HTMLElement* TextFieldInputType::placeholderElement() const
349 {
350     return m_placeholder.get();
351 }
352
353 void TextFieldInputType::destroyShadowSubtree()
354 {
355     InputType::destroyShadowSubtree();
356     m_innerText = nullptr;
357     m_placeholder = nullptr;
358     m_innerBlock = nullptr;
359     if (m_innerSpinButton)
360         m_innerSpinButton->removeSpinButtonOwner();
361     m_innerSpinButton = nullptr;
362     m_capsLockIndicator = nullptr;
363     m_autoFillButton = nullptr;
364     m_container = nullptr;
365 }
366
367 void TextFieldInputType::attributeChanged(const QualifiedName& name)
368 {
369     if (name == valueAttr || name == placeholderAttr) {
370         if (element())
371             updateInnerTextValue();
372     }
373     InputType::attributeChanged(name);
374 }
375
376 void TextFieldInputType::disabledStateChanged()
377 {
378     if (m_innerSpinButton)
379         m_innerSpinButton->releaseCapture();
380     capsLockStateMayHaveChanged();
381     updateAutoFillButton();
382 }
383
384 void TextFieldInputType::readOnlyStateChanged()
385 {
386     if (m_innerSpinButton)
387         m_innerSpinButton->releaseCapture();
388     capsLockStateMayHaveChanged();
389     updateAutoFillButton();
390 }
391
392 bool TextFieldInputType::supportsReadOnly() const
393 {
394     return true;
395 }
396
397 bool TextFieldInputType::shouldUseInputMethod() const
398 {
399     return true;
400 }
401
402 // FIXME: The name of this function doesn't make clear the two jobs it does:
403 // 1) Limits the string to a particular number of grapheme clusters.
404 // 2) Truncates the string at the first character which is a control character other than tab.
405 // FIXME: TextFieldInputType::sanitizeValue doesn't need a limit on grapheme clusters. A limit on code units would do.
406 // FIXME: Where does the "truncate at first control character" rule come from?
407 static String limitLength(const String& string, unsigned maxNumGraphemeClusters)
408 {
409     StringView stringView { string };
410     unsigned firstNonTabControlCharacterIndex = stringView.find([] (UChar character) {
411         return character < ' ' && character != '\t';
412     });
413     unsigned limitedLength;
414     if (stringView.is8Bit())
415         limitedLength = std::min(firstNonTabControlCharacterIndex, maxNumGraphemeClusters);
416     else
417         limitedLength = numCodeUnitsInGraphemeClusters(stringView.substring(0, firstNonTabControlCharacterIndex), maxNumGraphemeClusters);
418     return string.left(limitedLength);
419 }
420
421 static String autoFillButtonTypeToAccessibilityLabel(AutoFillButtonType autoFillButtonType)
422 {
423     switch (autoFillButtonType) {
424     case AutoFillButtonType::Contacts:
425         return AXAutoFillContactsLabel();
426     case AutoFillButtonType::Credentials:
427         return AXAutoFillCredentialsLabel();
428     case AutoFillButtonType::StrongConfirmationPassword:
429         return AXAutoFillStrongConfirmationPasswordLabel();
430     case AutoFillButtonType::StrongPassword:
431         return AXAutoFillStrongPasswordLabel();
432     case AutoFillButtonType::None:
433         ASSERT_NOT_REACHED();
434         return { };
435     }
436     ASSERT_NOT_REACHED();
437     return { };
438 }
439
440 static String autoFillButtonTypeToAutoFillButtonText(AutoFillButtonType autoFillButtonType)
441 {
442     switch (autoFillButtonType) {
443     case AutoFillButtonType::Contacts:
444     case AutoFillButtonType::Credentials:
445     case AutoFillButtonType::StrongConfirmationPassword:
446         return emptyString();
447     case AutoFillButtonType::StrongPassword:
448         return autoFillStrongPasswordLabel();
449     case AutoFillButtonType::None:
450         ASSERT_NOT_REACHED();
451         return { };
452     }
453     ASSERT_NOT_REACHED();
454     return { };
455 }
456
457 static AtomicString autoFillButtonTypeToAutoFillButtonPseudoClassName(AutoFillButtonType autoFillButtonType)
458 {
459     switch (autoFillButtonType) {
460     case AutoFillButtonType::Contacts:
461         return { "-webkit-contacts-auto-fill-button", AtomicString::ConstructFromLiteral };
462     case AutoFillButtonType::Credentials:
463         return { "-webkit-credentials-auto-fill-button", AtomicString::ConstructFromLiteral };
464     case AutoFillButtonType::StrongConfirmationPassword:
465         return { "-webkit-strong-confirmation-password-auto-fill-button", AtomicString::ConstructFromLiteral };
466     case AutoFillButtonType::StrongPassword:
467         return { "-webkit-strong-password-auto-fill-button", AtomicString::ConstructFromLiteral };
468     case AutoFillButtonType::None:
469         ASSERT_NOT_REACHED();
470         return emptyAtom();
471     }
472     ASSERT_NOT_REACHED();
473     return { };
474 }
475
476 static bool isAutoFillButtonTypeChanged(const AtomicString& attribute, AutoFillButtonType autoFillButtonType)
477 {
478     if (attribute == "-webkit-contacts-auto-fill-button" && autoFillButtonType != AutoFillButtonType::Contacts)
479         return true;
480     if (attribute == "-webkit-credentials-auto-fill-button" && autoFillButtonType != AutoFillButtonType::Credentials)
481         return true;
482     if (attribute == "-webkit-strong-confirmation-password-auto-fill-button" && autoFillButtonType != AutoFillButtonType::StrongConfirmationPassword)
483         return true;
484     if (attribute == "-webkit-strong-password-auto-fill-button" && autoFillButtonType != AutoFillButtonType::StrongPassword)
485         return true;
486     return false;
487 }
488
489 String TextFieldInputType::sanitizeValue(const String& proposedValue) const
490 {
491     return limitLength(proposedValue.removeCharacters(isHTMLLineBreak), HTMLInputElement::maxEffectiveLength);
492 }
493
494 void TextFieldInputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent& event)
495 {
496     ASSERT(element());
497     // Make sure that the text to be inserted will not violate the maxLength.
498
499     // We use RenderTextControlSingleLine::text() instead of InputElement::value()
500     // because they can be mismatched by sanitizeValue() in
501     // HTMLInputElement::subtreeHasChanged() in some cases.
502     String innerText = element()->innerTextValue();
503     unsigned oldLength = numGraphemeClusters(innerText);
504
505     // selectionLength represents the selection length of this text field to be
506     // removed by this insertion.
507     // If the text field has no focus, we don't need to take account of the
508     // selection length. The selection is the source of text drag-and-drop in
509     // that case, and nothing in the text field will be removed.
510     unsigned selectionLength = 0;
511     if (element()->focused()) {
512         ASSERT(enclosingTextFormControl(element()->document().frame()->selection().selection().start()) == element());
513         int selectionStart = element()->selectionStart();
514         ASSERT(selectionStart <= element()->selectionEnd());
515         int selectionCodeUnitCount = element()->selectionEnd() - selectionStart;
516         selectionLength = selectionCodeUnitCount ? numGraphemeClusters(StringView(innerText).substring(selectionStart, selectionCodeUnitCount)) : 0;
517     }
518     ASSERT(oldLength >= selectionLength);
519
520     // Selected characters will be removed by the next text event.
521     unsigned baseLength = oldLength - selectionLength;
522     unsigned maxLength = isTextType() ? element()->effectiveMaxLength() : HTMLInputElement::maxEffectiveLength;
523     unsigned appendableLength = maxLength > baseLength ? maxLength - baseLength : 0;
524
525     // Truncate the inserted text to avoid violating the maxLength and other constraints.
526     String eventText = event.text();
527     unsigned textLength = eventText.length();
528     while (textLength > 0 && isHTMLLineBreak(eventText[textLength - 1]))
529         textLength--;
530     eventText.truncate(textLength);
531     eventText.replace("\r\n", " ");
532     eventText.replace('\r', ' ');
533     eventText.replace('\n', ' ');
534     event.setText(limitLength(eventText, appendableLength));
535 }
536
537 bool TextFieldInputType::shouldRespectListAttribute()
538 {
539     return InputType::themeSupportsDataListUI(this);
540 }
541
542 void TextFieldInputType::updatePlaceholderText()
543 {
544     if (!supportsPlaceholder())
545         return;
546     ASSERT(element());
547     String placeholderText = element()->strippedPlaceholder();
548     if (placeholderText.isEmpty()) {
549         if (m_placeholder) {
550             m_placeholder->parentNode()->removeChild(*m_placeholder);
551             m_placeholder = nullptr;
552         }
553         return;
554     }
555     if (!m_placeholder) {
556         m_placeholder = TextControlPlaceholderElement::create(element()->document());
557         element()->userAgentShadowRoot()->insertBefore(*m_placeholder, m_container ? m_container.get() : innerTextElement().get());
558     }
559     m_placeholder->setInnerText(placeholderText);
560 }
561
562 bool TextFieldInputType::appendFormData(DOMFormData& formData, bool multipart) const
563 {
564     InputType::appendFormData(formData, multipart);
565     ASSERT(element());
566     auto& dirnameAttrValue = element()->attributeWithoutSynchronization(dirnameAttr);
567     if (!dirnameAttrValue.isNull())
568         formData.append(dirnameAttrValue, element()->directionForFormData());
569     return true;
570 }
571
572 String TextFieldInputType::convertFromVisibleValue(const String& visibleValue) const
573 {
574     return visibleValue;
575 }
576
577 void TextFieldInputType::subtreeHasChanged()
578 {
579     ASSERT(element());
580     element()->setChangedSinceLastFormControlChangeEvent(true);
581
582     // We don't need to call sanitizeUserInputValue() function here because
583     // HTMLInputElement::handleBeforeTextInsertedEvent() has already called
584     // sanitizeUserInputValue().
585     // ---
586     // sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent.
587     // ---
588     // Input types that support the selection API do *not* sanitize their
589     // user input in order to retain parity between what's in the model and
590     // what's on the screen. Otherwise, we retain the sanitization process for
591     // backward compatibility. https://bugs.webkit.org/show_bug.cgi?id=150346
592     String innerText = convertFromVisibleValue(element()->innerTextValue());
593     if (!supportsSelectionAPI())
594         innerText = sanitizeValue(innerText);
595     element()->setValueFromRenderer(innerText);
596     element()->updatePlaceholderVisibility();
597     // Recalc for :invalid change.
598     element()->invalidateStyleForSubtree();
599
600     didSetValueByUserEdit();
601 }
602
603 void TextFieldInputType::didSetValueByUserEdit()
604 {
605     ASSERT(element());
606     if (!element()->focused())
607         return;
608     if (RefPtr<Frame> frame = element()->document().frame())
609         frame->editor().textDidChangeInTextField(element());
610 }
611
612 void TextFieldInputType::spinButtonStepDown()
613 {
614     stepUpFromRenderer(-1);
615 }
616
617 void TextFieldInputType::spinButtonStepUp()
618 {
619     stepUpFromRenderer(1);
620 }
621
622 void TextFieldInputType::updateInnerTextValue()
623 {
624     ASSERT(element());
625     if (!element()->formControlValueMatchesRenderer()) {
626         // Update the renderer value if the formControlValueMatchesRenderer() flag is false.
627         // It protects an unacceptable renderer value from being overwritten with the DOM value.
628         element()->setInnerTextValue(visibleValue());
629         element()->updatePlaceholderVisibility();
630     }
631 }
632
633 void TextFieldInputType::focusAndSelectSpinButtonOwner()
634 {
635     ASSERT(element());
636     Ref<HTMLInputElement> input(*element());
637     input->focus();
638     input->select();
639 }
640
641 bool TextFieldInputType::shouldSpinButtonRespondToMouseEvents()
642 {
643     ASSERT(element());
644     return !element()->isDisabledOrReadOnly();
645 }
646
647 bool TextFieldInputType::shouldSpinButtonRespondToWheelEvents()
648 {
649     ASSERT(element());
650     return shouldSpinButtonRespondToMouseEvents() && element()->focused();
651 }
652
653 bool TextFieldInputType::shouldDrawCapsLockIndicator() const
654 {
655     ASSERT(element());
656     if (element()->document().focusedElement() != element())
657         return false;
658
659     if (element()->isDisabledOrReadOnly())
660         return false;
661
662     RefPtr<Frame> frame = element()->document().frame();
663     if (!frame)
664         return false;
665
666     if (!frame->selection().isFocusedAndActive())
667         return false;
668
669     return PlatformKeyboardEvent::currentCapsLockState();
670 }
671
672 void TextFieldInputType::capsLockStateMayHaveChanged()
673 {
674     if (!m_capsLockIndicator)
675         return;
676
677     bool shouldDrawCapsLockIndicator = this->shouldDrawCapsLockIndicator();
678     m_capsLockIndicator->setInlineStyleProperty(CSSPropertyDisplay, shouldDrawCapsLockIndicator ? CSSValueBlock : CSSValueNone, true);
679 }
680
681 bool TextFieldInputType::shouldDrawAutoFillButton() const
682 {
683     ASSERT(element());
684     return !element()->isDisabledOrReadOnly() && element()->autoFillButtonType() != AutoFillButtonType::None;
685 }
686
687 void TextFieldInputType::autoFillButtonElementWasClicked()
688 {
689     ASSERT(element());
690     Page* page = element()->document().page();
691     if (!page)
692         return;
693
694     page->chrome().client().handleAutoFillButtonClick(*element());
695 }
696
697 void TextFieldInputType::createContainer()
698 {
699     ASSERT(!m_container);
700     ASSERT(element());
701
702     m_container = TextControlInnerContainer::create(element()->document());
703     m_container->setPseudo(AtomicString("-webkit-textfield-decoration-container", AtomicString::ConstructFromLiteral));
704
705     m_innerBlock = TextControlInnerElement::create(element()->document());
706     m_innerBlock->appendChild(*m_innerText);
707     m_container->appendChild(*m_innerBlock);
708
709     element()->userAgentShadowRoot()->appendChild(*m_container);
710 }
711
712 void TextFieldInputType::createAutoFillButton(AutoFillButtonType autoFillButtonType)
713 {
714     ASSERT(!m_autoFillButton);
715
716     if (autoFillButtonType == AutoFillButtonType::None)
717         return;
718
719     ASSERT(element());
720     m_autoFillButton = AutoFillButtonElement::create(element()->document(), *this);
721     m_autoFillButton->setPseudo(autoFillButtonTypeToAutoFillButtonPseudoClassName(autoFillButtonType));
722     m_autoFillButton->setAttributeWithoutSynchronization(roleAttr, AtomicString("button", AtomicString::ConstructFromLiteral));
723     m_autoFillButton->setAttributeWithoutSynchronization(aria_labelAttr, autoFillButtonTypeToAccessibilityLabel(autoFillButtonType));
724     m_autoFillButton->setTextContent(autoFillButtonTypeToAutoFillButtonText(autoFillButtonType));
725     m_container->appendChild(*m_autoFillButton);
726 }
727
728 void TextFieldInputType::updateAutoFillButton()
729 {
730     if (shouldDrawAutoFillButton()) {
731         if (!m_container)
732             createContainer();
733
734         ASSERT(element());
735         AutoFillButtonType autoFillButtonType = element()->autoFillButtonType();
736         if (!m_autoFillButton)
737             createAutoFillButton(autoFillButtonType);
738
739         const AtomicString& attribute = m_autoFillButton->attributeWithoutSynchronization(pseudoAttr);
740         bool shouldUpdateAutoFillButtonType = isAutoFillButtonTypeChanged(attribute, autoFillButtonType);
741         if (shouldUpdateAutoFillButtonType) {
742             m_autoFillButton->setPseudo(autoFillButtonTypeToAutoFillButtonPseudoClassName(autoFillButtonType));
743             m_autoFillButton->setAttributeWithoutSynchronization(aria_labelAttr, autoFillButtonTypeToAccessibilityLabel(autoFillButtonType));
744             m_autoFillButton->setTextContent(autoFillButtonTypeToAutoFillButtonText(autoFillButtonType));
745         }
746         m_autoFillButton->setInlineStyleProperty(CSSPropertyDisplay, CSSValueBlock, true);
747         return;
748     }
749     
750     if (m_autoFillButton)
751         m_autoFillButton->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone, true);        
752 }
753
754 } // namespace WebCore