Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / html / TextFieldInputType.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  * Copyright (C) 2011, 2014 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 "Editor.h"
39 #include "FormDataList.h"
40 #include "Frame.h"
41 #include "FrameSelection.h"
42 #include "HTMLInputElement.h"
43 #include "HTMLNames.h"
44 #include "KeyboardEvent.h"
45 #include "NodeRenderStyle.h"
46 #include "Page.h"
47 #include "PlatformKeyboardEvent.h"
48 #include "RenderLayer.h"
49 #include "RenderTextControlSingleLine.h"
50 #include "RenderTheme.h"
51 #include "ShadowRoot.h"
52 #include "TextBreakIterator.h"
53 #include "TextControlInnerElements.h"
54 #include "TextEvent.h"
55 #include "TextIterator.h"
56 #include "TextNodeTraversal.h"
57 #include "WheelEvent.h"
58
59 namespace WebCore {
60
61 using namespace HTMLNames;
62
63 TextFieldInputType::TextFieldInputType(HTMLInputElement& element)
64     : InputType(element)
65 {
66 }
67
68 TextFieldInputType::~TextFieldInputType()
69 {
70     if (m_innerSpinButton)
71         m_innerSpinButton->removeSpinButtonOwner();
72 }
73
74 bool TextFieldInputType::isKeyboardFocusable(KeyboardEvent*) const
75 {
76 #if PLATFORM(IOS)
77     if (element().isReadOnly())
78         return false;
79 #endif
80     return element().isTextFormControlFocusable();
81 }
82
83 bool TextFieldInputType::isMouseFocusable() const
84 {
85     return element().isTextFormControlFocusable();
86 }
87
88 bool TextFieldInputType::isTextField() const
89 {
90     return true;
91 }
92
93 bool TextFieldInputType::isEmptyValue() const
94 {
95     TextControlInnerTextElement* innerText = innerTextElement();
96     ASSERT(innerText);
97
98     for (Text* text = TextNodeTraversal::firstWithin(*innerText); text; text = TextNodeTraversal::next(*text, innerText)) {
99         if (text->length())
100             return false;
101     }
102     return true;
103 }
104
105 bool TextFieldInputType::valueMissing(const String& value) const
106 {
107     return element().isRequired() && value.isEmpty();
108 }
109
110 void TextFieldInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
111 {
112     // Grab this input element to keep reference even if JS event handler
113     // changes input type.
114     Ref<HTMLInputElement> input(element());
115
116     // We don't ask InputType::setValue to dispatch events because
117     // TextFieldInputType dispatches events different way from InputType.
118     InputType::setValue(sanitizedValue, valueChanged, DispatchNoEvent);
119
120     if (valueChanged)
121         updateInnerTextValue();
122
123     unsigned max = visibleValue().length();
124     if (input->focused())
125         input->setSelectionRange(max, max);
126     else
127         input->cacheSelectionInResponseToSetValue(max);
128
129     if (!valueChanged)
130         return;
131
132     switch (eventBehavior) {
133     case DispatchChangeEvent:
134         // If the user is still editing this field, dispatch an input event rather than a change event.
135         // The change event will be dispatched when editing finishes.
136         if (input->focused())
137             input->dispatchFormControlInputEvent();
138         else
139             input->dispatchFormControlChangeEvent();
140         break;
141
142     case DispatchInputAndChangeEvent: {
143         input->dispatchFormControlInputEvent();
144         input->dispatchFormControlChangeEvent();
145         break;
146     }
147
148     case DispatchNoEvent:
149         break;
150     }
151
152     // FIXME: Why do we do this when eventBehavior == DispatchNoEvent
153     if (!input->focused() || eventBehavior == DispatchNoEvent)
154         input->setTextAsOfLastFormControlChangeEvent(sanitizedValue);
155 }
156
157 void TextFieldInputType::handleKeydownEvent(KeyboardEvent* event)
158 {
159     if (!element().focused())
160         return;
161     Frame* frame = element().document().frame();
162     if (!frame || !frame->editor().doTextFieldCommandFromEvent(&element(), event))
163         return;
164     event->setDefaultHandled();
165 }
166
167 void TextFieldInputType::handleKeydownEventForSpinButton(KeyboardEvent* event)
168 {
169     if (element().isDisabledOrReadOnly())
170         return;
171     const String& key = event->keyIdentifier();
172     if (key == "Up")
173         spinButtonStepUp();
174     else if (key == "Down")
175         spinButtonStepDown();
176     else
177         return;
178     event->setDefaultHandled();
179 }
180
181 void TextFieldInputType::forwardEvent(Event* event)
182 {
183     if (m_innerSpinButton) {
184         m_innerSpinButton->forwardEvent(event);
185         if (event->defaultHandled())
186             return;
187     }
188
189     if (event->isMouseEvent()
190         || event->type() == eventNames().blurEvent
191         || event->type() == eventNames().focusEvent)
192     {
193         element().document().updateStyleIfNeeded();
194
195         if (element().renderer()) {
196             RenderTextControlSingleLine& renderTextControl = downcast<RenderTextControlSingleLine>(*element().renderer());
197             if (event->type() == eventNames().blurEvent) {
198                 if (RenderTextControlInnerBlock* innerTextRenderer = innerTextElement()->renderer()) {
199                     if (RenderLayer* innerLayer = innerTextRenderer->layer()) {
200                         ScrollOffset scrollOffset(!renderTextControl.style().isLeftToRightDirection() ? innerLayer->scrollWidth() : 0, 0);
201                         innerLayer->scrollToOffset(scrollOffset, RenderLayer::ScrollOffsetClamped);
202                     }
203                 }
204
205                 capsLockStateMayHaveChanged();
206             } else if (event->type() == eventNames().focusEvent)
207                 capsLockStateMayHaveChanged();
208
209             element().forwardEvent(event);
210         }
211     }
212 }
213
214 void TextFieldInputType::handleFocusEvent(Node* oldFocusedNode, FocusDirection)
215 {
216     ASSERT_UNUSED(oldFocusedNode, oldFocusedNode != &element());
217     if (Frame* frame = element().document().frame())
218         frame->editor().textFieldDidBeginEditing(&element());
219 }
220
221 void TextFieldInputType::handleBlurEvent()
222 {
223     InputType::handleBlurEvent();
224     element().endEditing();
225 }
226
227 bool TextFieldInputType::shouldSubmitImplicitly(Event* event)
228 {
229     return (event->type() == eventNames().textInputEvent && is<TextEvent>(*event) && downcast<TextEvent>(*event).data() == "\n")
230         || InputType::shouldSubmitImplicitly(event);
231 }
232
233 RenderPtr<RenderElement> TextFieldInputType::createInputRenderer(Ref<RenderStyle>&& style)
234 {
235     return createRenderer<RenderTextControlSingleLine>(element(), WTFMove(style));
236 }
237
238 bool TextFieldInputType::needsContainer() const
239 {
240     return false;
241 }
242
243 bool TextFieldInputType::shouldHaveSpinButton() const
244 {
245     Document& document = element().document();
246     RefPtr<RenderTheme> theme = document.page() ? &document.page()->theme() : RenderTheme::defaultTheme();
247     return theme->shouldHaveSpinButton(element());
248 }
249
250 bool TextFieldInputType::shouldHaveCapsLockIndicator() const
251 {
252     Document& document = element().document();
253     RefPtr<RenderTheme> theme = document.page() ? &document.page()->theme() : RenderTheme::defaultTheme();
254     return theme->shouldHaveCapsLockIndicator(element());
255 }
256
257 void TextFieldInputType::createShadowSubtree()
258 {
259     ASSERT(element().shadowRoot());
260
261     ASSERT(!m_innerText);
262     ASSERT(!m_innerBlock);
263     ASSERT(!m_innerSpinButton);
264     ASSERT(!m_capsLockIndicator);
265     ASSERT(!m_autoFillButton);
266
267     Document& document = element().document();
268     bool shouldHaveSpinButton = this->shouldHaveSpinButton();
269     bool shouldHaveCapsLockIndicator = this->shouldHaveCapsLockIndicator();
270     bool createsContainer = shouldHaveSpinButton || shouldHaveCapsLockIndicator || needsContainer();
271
272     m_innerText = TextControlInnerTextElement::create(document);
273
274     if (!createsContainer) {
275         element().userAgentShadowRoot()->appendChild(*m_innerText, IGNORE_EXCEPTION);
276         updatePlaceholderText();
277         return;
278     }
279
280     createContainer();
281     updatePlaceholderText();
282
283     if (shouldHaveSpinButton) {
284         m_innerSpinButton = SpinButtonElement::create(document, *this);
285         m_container->appendChild(*m_innerSpinButton, IGNORE_EXCEPTION);
286     }
287
288     if (shouldHaveCapsLockIndicator) {
289         m_capsLockIndicator = HTMLDivElement::create(document);
290         m_capsLockIndicator->setPseudo(AtomicString("-webkit-caps-lock-indicator", AtomicString::ConstructFromLiteral));
291
292         bool shouldDrawCapsLockIndicator = this->shouldDrawCapsLockIndicator();
293         m_capsLockIndicator->setInlineStyleProperty(CSSPropertyDisplay, shouldDrawCapsLockIndicator ? CSSValueBlock : CSSValueNone, true);
294
295         m_container->appendChild(*m_capsLockIndicator, IGNORE_EXCEPTION);
296     }
297
298     updateAutoFillButton();
299 }
300
301 HTMLElement* TextFieldInputType::containerElement() const
302 {
303     return m_container.get();
304 }
305
306 HTMLElement* TextFieldInputType::innerBlockElement() const
307 {
308     return m_innerBlock.get();
309 }
310
311 TextControlInnerTextElement* TextFieldInputType::innerTextElement() const
312 {
313     ASSERT(m_innerText);
314     return m_innerText.get();
315 }
316
317 HTMLElement* TextFieldInputType::innerSpinButtonElement() const
318 {
319     return m_innerSpinButton.get();
320 }
321
322 HTMLElement* TextFieldInputType::capsLockIndicatorElement() const
323 {
324     return m_capsLockIndicator.get();
325 }
326
327 HTMLElement* TextFieldInputType::autoFillButtonElement() const
328 {
329     return m_autoFillButton.get();
330 }
331
332 HTMLElement* TextFieldInputType::placeholderElement() const
333 {
334     return m_placeholder.get();
335 }
336
337 void TextFieldInputType::destroyShadowSubtree()
338 {
339     InputType::destroyShadowSubtree();
340     m_innerText = nullptr;
341     m_placeholder = nullptr;
342     m_innerBlock = nullptr;
343     if (m_innerSpinButton)
344         m_innerSpinButton->removeSpinButtonOwner();
345     m_innerSpinButton = nullptr;
346     m_capsLockIndicator = nullptr;
347     m_autoFillButton = nullptr;
348     m_container = nullptr;
349 }
350
351 void TextFieldInputType::attributeChanged()
352 {
353     // FIXME: Updating the inner text on any attribute update should
354     // be unnecessary. We should figure out what attributes affect.
355     updateInnerTextValue();
356 }
357
358 void TextFieldInputType::disabledAttributeChanged()
359 {
360     if (m_innerSpinButton)
361         m_innerSpinButton->releaseCapture();
362     capsLockStateMayHaveChanged();
363     updateAutoFillButton();
364 }
365
366 void TextFieldInputType::readonlyAttributeChanged()
367 {
368     if (m_innerSpinButton)
369         m_innerSpinButton->releaseCapture();
370     capsLockStateMayHaveChanged();
371     updateAutoFillButton();
372 }
373
374 bool TextFieldInputType::supportsReadOnly() const
375 {
376     return true;
377 }
378
379 bool TextFieldInputType::shouldUseInputMethod() const
380 {
381     return true;
382 }
383
384 static bool isASCIILineBreak(UChar c)
385 {
386     return c == '\r' || c == '\n';
387 }
388
389 static String limitLength(const String& string, int maxLength)
390 {
391     unsigned newLength = numCharactersInGraphemeClusters(string, maxLength);
392     for (unsigned i = 0; i < newLength; ++i) {
393         const UChar current = string[i];
394         if (current < ' ' && current != '\t') {
395             newLength = i;
396             break;
397         }
398     }
399     return string.left(newLength);
400 }
401
402 String TextFieldInputType::sanitizeValue(const String& proposedValue) const
403 {
404     return limitLength(proposedValue.removeCharacters(isASCIILineBreak), HTMLInputElement::maximumLength);
405 }
406
407 void TextFieldInputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* event)
408 {
409     // Make sure that the text to be inserted will not violate the maxLength.
410
411     // We use RenderTextControlSingleLine::text() instead of InputElement::value()
412     // because they can be mismatched by sanitizeValue() in
413     // HTMLInputElement::subtreeHasChanged() in some cases.
414     String innerText = element().innerTextValue();
415     unsigned oldLength = numGraphemeClusters(innerText);
416
417     // selectionLength represents the selection length of this text field to be
418     // removed by this insertion.
419     // If the text field has no focus, we don't need to take account of the
420     // selection length. The selection is the source of text drag-and-drop in
421     // that case, and nothing in the text field will be removed.
422     unsigned selectionLength = 0;
423     if (element().focused()) {
424         ASSERT(enclosingTextFormControl(element().document().frame()->selection().selection().start()) == &element());
425         int selectionStart = element().selectionStart();
426         ASSERT(selectionStart <= element().selectionEnd());
427         int selectionCodeUnitCount = element().selectionEnd() - selectionStart;
428         selectionLength = selectionCodeUnitCount ? numGraphemeClusters(innerText.substring(selectionStart, selectionCodeUnitCount)) : 0;
429     }
430     ASSERT(oldLength >= selectionLength);
431
432     // Selected characters will be removed by the next text event.
433     unsigned baseLength = oldLength - selectionLength;
434     unsigned maxLength = static_cast<unsigned>(isTextType() ? element().maxLength() : HTMLInputElement::maximumLength); // maxLength can never be negative.
435     unsigned appendableLength = maxLength > baseLength ? maxLength - baseLength : 0;
436
437     // Truncate the inserted text to avoid violating the maxLength and other constraints.
438     String eventText = event->text();
439     unsigned textLength = eventText.length();
440     while (textLength > 0 && isASCIILineBreak(eventText[textLength - 1]))
441         textLength--;
442     eventText.truncate(textLength);
443     eventText.replace("\r\n", " ");
444     eventText.replace('\r', ' ');
445     eventText.replace('\n', ' ');
446
447     event->setText(limitLength(eventText, appendableLength));
448 }
449
450 bool TextFieldInputType::shouldRespectListAttribute()
451 {
452     return InputType::themeSupportsDataListUI(this);
453 }
454
455 void TextFieldInputType::updatePlaceholderText()
456 {
457     if (!supportsPlaceholder())
458         return;
459     String placeholderText = element().strippedPlaceholder();
460     if (placeholderText.isEmpty()) {
461         if (m_placeholder) {
462             m_placeholder->parentNode()->removeChild(*m_placeholder, ASSERT_NO_EXCEPTION);
463             m_placeholder = nullptr;
464         }
465         return;
466     }
467     if (!m_placeholder) {
468         m_placeholder = HTMLDivElement::create(element().document());
469         m_placeholder->setPseudo(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral));
470         m_placeholder->setInlineStyleProperty(CSSPropertyDisplay, element().isPlaceholderVisible() ? CSSValueBlock : CSSValueNone, true);
471         element().userAgentShadowRoot()->insertBefore(*m_placeholder, m_container ? m_container.get() : innerTextElement(), ASSERT_NO_EXCEPTION);
472         
473     }
474     m_placeholder->setInnerText(placeholderText, ASSERT_NO_EXCEPTION);
475 }
476
477 bool TextFieldInputType::appendFormData(FormDataList& list, bool multipart) const
478 {
479     InputType::appendFormData(list, multipart);
480     const AtomicString& dirnameAttrValue = element().fastGetAttribute(dirnameAttr);
481     if (!dirnameAttrValue.isNull())
482         list.appendData(dirnameAttrValue, element().directionForFormData());
483     return true;
484 }
485
486 String TextFieldInputType::convertFromVisibleValue(const String& visibleValue) const
487 {
488     return visibleValue;
489 }
490
491 void TextFieldInputType::subtreeHasChanged()
492 {
493     element().setChangedSinceLastFormControlChangeEvent(true);
494
495     // We don't need to call sanitizeUserInputValue() function here because
496     // HTMLInputElement::handleBeforeTextInsertedEvent() has already called
497     // sanitizeUserInputValue().
498     // ---
499     // sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent.
500     // ---
501     // Input types that support the selection API do *not* sanitize their
502     // user input in order to retain parity between what's in the model and
503     // what's on the screen. Otherwise, we retain the sanitization process for
504     // backward compatibility. https://bugs.webkit.org/show_bug.cgi?id=150346
505     String innerText = convertFromVisibleValue(element().innerTextValue());
506     if (!supportsSelectionAPI())
507         innerText = sanitizeValue(innerText);
508     element().setValueFromRenderer(innerText);
509     element().updatePlaceholderVisibility();
510     // Recalc for :invalid change.
511     element().setNeedsStyleRecalc();
512
513     didSetValueByUserEdit();
514 }
515
516 void TextFieldInputType::didSetValueByUserEdit()
517 {
518     if (!element().focused())
519         return;
520     if (Frame* frame = element().document().frame())
521         frame->editor().textDidChangeInTextField(&element());
522 }
523
524 void TextFieldInputType::spinButtonStepDown()
525 {
526     stepUpFromRenderer(-1);
527 }
528
529 void TextFieldInputType::spinButtonStepUp()
530 {
531     stepUpFromRenderer(1);
532 }
533
534 void TextFieldInputType::updateInnerTextValue()
535 {
536     if (!element().formControlValueMatchesRenderer()) {
537         // Update the renderer value if the formControlValueMatchesRenderer() flag is false.
538         // It protects an unacceptable renderer value from being overwritten with the DOM value.
539         element().setInnerTextValue(visibleValue());
540         element().updatePlaceholderVisibility();
541     }
542 }
543
544 void TextFieldInputType::focusAndSelectSpinButtonOwner()
545 {
546     Ref<HTMLInputElement> input(element());
547     input->focus();
548     input->select();
549 }
550
551 bool TextFieldInputType::shouldSpinButtonRespondToMouseEvents()
552 {
553     return !element().isDisabledOrReadOnly();
554 }
555
556 bool TextFieldInputType::shouldSpinButtonRespondToWheelEvents()
557 {
558     return shouldSpinButtonRespondToMouseEvents() && element().focused();
559 }
560
561 bool TextFieldInputType::shouldDrawCapsLockIndicator() const
562 {
563     if (element().document().focusedElement() != &element())
564         return false;
565
566     if (element().isDisabledOrReadOnly())
567         return false;
568
569     Frame* frame = element().document().frame();
570     if (!frame)
571         return false;
572
573     if (!frame->selection().isFocusedAndActive())
574         return false;
575
576     return PlatformKeyboardEvent::currentCapsLockState();
577 }
578
579 void TextFieldInputType::capsLockStateMayHaveChanged()
580 {
581     if (!m_capsLockIndicator)
582         return;
583
584     bool shouldDrawCapsLockIndicator = this->shouldDrawCapsLockIndicator();
585     m_capsLockIndicator->setInlineStyleProperty(CSSPropertyDisplay, shouldDrawCapsLockIndicator ? CSSValueBlock : CSSValueNone, true);
586 }
587
588 bool TextFieldInputType::shouldDrawAutoFillButton() const
589 {
590     return !element().isDisabledOrReadOnly() && element().showAutoFillButton();
591 }
592
593 void TextFieldInputType::autoFillButtonElementWasClicked()
594 {
595     Page* page = element().document().page();
596     if (!page)
597         return;
598
599     page->chrome().client().handleAutoFillButtonClick(element());
600 }
601
602 void TextFieldInputType::createContainer()
603 {
604     ASSERT(!m_container);
605
606     m_container = TextControlInnerContainer::create(element().document());
607     m_container->setPseudo(AtomicString("-webkit-textfield-decoration-container", AtomicString::ConstructFromLiteral));
608
609     m_innerBlock = TextControlInnerElement::create(element().document());
610     m_innerBlock->appendChild(*m_innerText, IGNORE_EXCEPTION);
611     m_container->appendChild(*m_innerBlock, IGNORE_EXCEPTION);
612
613     element().userAgentShadowRoot()->appendChild(*m_container, IGNORE_EXCEPTION);
614 }
615
616 void TextFieldInputType::createAutoFillButton()
617 {
618     ASSERT(!m_autoFillButton);
619
620     m_autoFillButton = AutoFillButtonElement::create(element().document(), *this);
621     m_autoFillButton->setPseudo(AtomicString("-webkit-auto-fill-button", AtomicString::ConstructFromLiteral));
622     m_container->appendChild(*m_autoFillButton, IGNORE_EXCEPTION);
623 }
624
625 void TextFieldInputType::updateAutoFillButton()
626 {
627     if (shouldDrawAutoFillButton()) {
628         if (!m_container)
629             createContainer();
630
631         if (!m_autoFillButton)
632             createAutoFillButton();
633
634         m_autoFillButton->setInlineStyleProperty(CSSPropertyDisplay, CSSValueBlock, true);
635         return;
636     }
637     
638     if (m_autoFillButton)
639         m_autoFillButton->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone, true);        
640 }
641
642 } // namespace WebCore