[Datalist][iOS] Display suggestions for input[type=color]
[WebKit-https.git] / Source / WebCore / html / HTMLInputElement.h
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2000 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004-2018 Apple Inc. All rights reserved.
6  * Copyright (C) 2012 Samsung Electronics. All rights reserved.
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 #pragma once
26
27 #include "FileChooser.h"
28 #include "HTMLTextFormControlElement.h"
29 #include "StepRange.h"
30 #include <memory>
31 #include <wtf/WeakPtr.h>
32
33 #if PLATFORM(IOS)
34 #include "DateComponents.h"
35 #endif
36
37 namespace WebCore {
38
39 class DragData;
40 class FileList;
41 class HTMLDataListElement;
42 class HTMLImageLoader;
43 class Icon;
44 class InputType;
45 class ListAttributeTargetObserver;
46 class RadioButtonGroups;
47 class URL;
48
49 struct DateTimeChooserParameters;
50
51 struct InputElementClickState {
52     bool stateful { false };
53     bool checked { false };
54     bool indeterminate { false };
55     RefPtr<HTMLInputElement> checkedRadioButton;
56 };
57
58 class HTMLInputElement : public HTMLTextFormControlElement, public CanMakeWeakPtr<HTMLInputElement> {
59     WTF_MAKE_ISO_ALLOCATED(HTMLInputElement);
60 public:
61     static Ref<HTMLInputElement> create(const QualifiedName&, Document&, HTMLFormElement*, bool createdByParser);
62     virtual ~HTMLInputElement();
63
64     WEBCORE_EXPORT bool shouldAutocomplete() const final;
65
66     // For ValidityState
67     bool hasBadInput() const final;
68     bool patternMismatch() const final;
69     bool rangeUnderflow() const final;
70     bool rangeOverflow() const final;
71     bool stepMismatch() const final;
72     bool tooShort() const final;
73     bool tooLong() const final;
74     bool typeMismatch() const final;
75     bool valueMissing() const final;
76     bool isValid() const final;
77     WEBCORE_EXPORT String validationMessage() const final;
78
79     // Returns the minimum value for type=date, number, or range.  Don't call this for other types.
80     double minimum() const;
81     // Returns the maximum value for type=date, number, or range.  Don't call this for other types.
82     // This always returns a value which is >= minimum().
83     double maximum() const;
84     // Sets the "allowed value step" defined in the HTML spec to the specified double pointer.
85     // Returns false if there is no "allowed value step."
86     bool getAllowedValueStep(Decimal*) const;
87     StepRange createStepRange(AnyStepHandling) const;
88
89 #if ENABLE(DATALIST_ELEMENT)
90     std::optional<Decimal> findClosestTickMarkValue(const Decimal&);
91 #endif
92
93     WEBCORE_EXPORT ExceptionOr<void> stepUp(int = 1);
94     WEBCORE_EXPORT ExceptionOr<void> stepDown(int = 1);
95
96     bool isPresentingAttachedView() const;
97
98     // stepUp()/stepDown() for user-interaction.
99     bool isSteppable() const;
100
101     bool isTextButton() const;
102
103     bool isRadioButton() const;
104     WEBCORE_EXPORT bool isTextField() const final;
105     WEBCORE_EXPORT bool isSearchField() const;
106     bool isInputTypeHidden() const;
107     WEBCORE_EXPORT bool isPasswordField() const;
108     bool isCheckbox() const;
109     bool isRangeControl() const;
110
111 #if ENABLE(INPUT_TYPE_COLOR)
112     WEBCORE_EXPORT bool isColorControl() const;
113 #endif
114
115     // FIXME: It's highly likely that any call site calling this function should instead
116     // be using a different one. Many input elements behave like text fields, and in addition
117     // any unknown input type is treated as text. Consider, for example, isTextField or
118     // isTextField && !isPasswordField.
119     WEBCORE_EXPORT bool isText() const;
120
121     WEBCORE_EXPORT bool isEmailField() const;
122     bool isFileUpload() const;
123     bool isImageButton() const;
124     WEBCORE_EXPORT bool isNumberField() const;
125     bool isSubmitButton() const;
126     WEBCORE_EXPORT bool isTelephoneField() const;
127     WEBCORE_EXPORT bool isURLField() const;
128     WEBCORE_EXPORT bool isDateField() const;
129     WEBCORE_EXPORT bool isDateTimeField() const;
130     WEBCORE_EXPORT bool isDateTimeLocalField() const;
131     WEBCORE_EXPORT bool isMonthField() const;
132     WEBCORE_EXPORT bool isTimeField() const;
133     WEBCORE_EXPORT bool isWeekField() const;
134
135 #if PLATFORM(IOS)
136     DateComponents::Type dateType() const;
137 #endif
138
139     HTMLElement* containerElement() const;
140     
141     RefPtr<TextControlInnerTextElement> innerTextElement() const final;
142     RenderStyle createInnerTextStyle(const RenderStyle&) override;
143
144     HTMLElement* innerBlockElement() const;
145     HTMLElement* innerSpinButtonElement() const;
146     HTMLElement* capsLockIndicatorElement() const;
147     HTMLElement* resultsButtonElement() const;
148     HTMLElement* cancelButtonElement() const;
149     HTMLElement* sliderThumbElement() const;
150     HTMLElement* sliderTrackElement() const;
151     HTMLElement* placeholderElement() const final;
152     WEBCORE_EXPORT HTMLElement* autoFillButtonElement() const;
153 #if ENABLE(DATALIST_ELEMENT)
154     HTMLElement* dataListButtonElement() const;
155 #endif
156
157     bool checked() const { return m_isChecked; }
158     WEBCORE_EXPORT void setChecked(bool, TextFieldEventBehavior = DispatchNoEvent);
159
160     // 'indeterminate' is a state independent of the checked state that causes the control to draw in a way that hides the actual state.
161     bool indeterminate() const { return m_isIndeterminate; }
162     WEBCORE_EXPORT void setIndeterminate(bool);
163     // shouldAppearChecked is used by the rendering tree/CSS while checked() is used by JS to determine checked state
164     bool shouldAppearChecked() const;
165     bool matchesIndeterminatePseudoClass() const final;
166     bool shouldAppearIndeterminate() const final;
167
168     WEBCORE_EXPORT unsigned size() const;
169     bool sizeShouldIncludeDecoration(int& preferredSize) const;
170     float decorationWidth() const;
171
172     WEBCORE_EXPORT void setType(const AtomicString&);
173
174     WEBCORE_EXPORT String value() const final;
175     WEBCORE_EXPORT ExceptionOr<void> setValue(const String&, TextFieldEventBehavior = DispatchNoEvent);
176     WEBCORE_EXPORT void setValueForUser(const String&);
177     // Checks if the specified string would be a valid value.
178     // We should not call this for types with no string value such as CHECKBOX and RADIO.
179     bool isValidValue(const String&) const;
180     bool hasDirtyValue() const { return !m_valueIfDirty.isNull(); };
181
182     String sanitizeValue(const String&) const;
183
184     String localizeValue(const String&) const;
185
186     // The value which is drawn by a renderer.
187     String visibleValue() const;
188
189     WEBCORE_EXPORT void setEditingValue(const String&);
190
191     WEBCORE_EXPORT double valueAsDate() const;
192     WEBCORE_EXPORT ExceptionOr<void> setValueAsDate(double);
193
194     WEBCORE_EXPORT double valueAsNumber() const;
195     WEBCORE_EXPORT ExceptionOr<void> setValueAsNumber(double, TextFieldEventBehavior = DispatchNoEvent);
196
197     String valueWithDefault() const;
198
199     // This function dispatches 'input' event for non-textfield types. Callers
200     // need to handle any DOM structure changes by event handlers, or need to
201     // delay the 'input' event with EventQueueScope.
202     void setValueFromRenderer(const String&);
203
204     bool canHaveSelection() const;
205
206     bool rendererIsNeeded(const RenderStyle&) final;
207     RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final;
208     void willAttachRenderers() final;
209     void didAttachRenderers() final;
210     void didDetachRenderers() final;
211
212     // FIXME: For isActivatedSubmit and setActivatedSubmit, we should use the NVI-idiom here by making
213     // it private virtual in all classes and expose a public method in HTMLFormControlElement to call
214     // the private virtual method.
215     bool isActivatedSubmit() const final;
216     void setActivatedSubmit(bool flag) final;
217
218     String altText() const;
219
220     void willDispatchEvent(Event&, InputElementClickState&);
221     void didDispatchClickEvent(Event&, const InputElementClickState&);
222
223     void didBlur();
224
225     int maxResults() const { return m_maxResults; }
226
227     WEBCORE_EXPORT String defaultValue() const;
228     WEBCORE_EXPORT void setDefaultValue(const String&);
229
230     Vector<String> acceptMIMETypes();
231     Vector<String> acceptFileExtensions();
232     String accept() const;
233     WEBCORE_EXPORT String alt() const;
234
235     WEBCORE_EXPORT ExceptionOr<void> setSize(unsigned);
236
237     URL src() const;
238
239     unsigned effectiveMaxLength() const;
240
241     bool multiple() const;
242
243     bool isAutoFilled() const { return m_isAutoFilled; }
244     WEBCORE_EXPORT void setAutoFilled(bool = true);
245
246     AutoFillButtonType lastAutoFillButtonType() const { return static_cast<AutoFillButtonType>(m_lastAutoFillButtonType); }
247     AutoFillButtonType autoFillButtonType() const { return static_cast<AutoFillButtonType>(m_autoFillButtonType); }
248     WEBCORE_EXPORT void setShowAutoFillButton(AutoFillButtonType);
249
250     bool hasAutoFillStrongPasswordButton() const  { return autoFillButtonType() == AutoFillButtonType::StrongPassword; }
251
252     bool isAutoFillAvailable() const { return m_isAutoFillAvailable; }
253     void setAutoFillAvailable(bool autoFillAvailable) { m_isAutoFillAvailable = autoFillAvailable; }
254
255     WEBCORE_EXPORT FileList* files();
256     WEBCORE_EXPORT void setFiles(RefPtr<FileList>&&);
257
258 #if ENABLE(DRAG_SUPPORT)
259     // Returns true if the given DragData has more than one dropped files.
260     bool receiveDroppedFiles(const DragData&);
261 #endif
262
263     Icon* icon() const;
264     String displayString() const;
265
266     // These functions are used for rendering the input active during a
267     // drag-and-drop operation.
268     bool canReceiveDroppedFiles() const;
269     void setCanReceiveDroppedFiles(bool);
270
271     void addSearchResult();
272     void onSearch();
273
274     bool willRespondToMouseClickEvents() override;
275
276 #if ENABLE(DATALIST_ELEMENT)
277     WEBCORE_EXPORT RefPtr<HTMLElement> list() const;
278     RefPtr<HTMLDataListElement> dataList() const;
279     void listAttributeTargetChanged();
280 #endif
281
282     Vector<HTMLInputElement*> radioButtonGroup() const;
283     HTMLInputElement* checkedRadioButtonForGroup() const;
284     bool isInRequiredRadioButtonGroup();
285     // Returns null if this isn't associated with any radio button group.
286     RadioButtonGroups* radioButtonGroups() const;
287
288     // Functions for InputType classes.
289     void setValueInternal(const String&, TextFieldEventBehavior);
290     bool isTextFormControlFocusable() const;
291     bool isTextFormControlKeyboardFocusable(KeyboardEvent*) const;
292     bool isTextFormControlMouseFocusable() const;
293     bool valueAttributeWasUpdatedAfterParsing() const { return m_valueAttributeWasUpdatedAfterParsing; }
294
295     void cacheSelectionInResponseToSetValue(int caretOffset) { cacheSelection(caretOffset, caretOffset, SelectionHasNoDirection); }
296
297     Color valueAsColor() const; // Returns transparent color if not type=color.
298     WEBCORE_EXPORT void selectColor(StringView); // Does nothing if not type=color. Simulates user selection of color; intended for testing.
299     WEBCORE_EXPORT Vector<Color> suggestedColors() const;
300
301     String defaultToolTip() const;
302
303 #if ENABLE(MEDIA_CAPTURE)
304     MediaCaptureType mediaCaptureType() const;
305 #endif
306
307     static const unsigned maxEffectiveLength;
308
309     WEBCORE_EXPORT unsigned height() const;
310     WEBCORE_EXPORT unsigned width() const;
311     WEBCORE_EXPORT void setHeight(unsigned);
312     WEBCORE_EXPORT void setWidth(unsigned);
313
314     void blur() final;
315     void defaultBlur();
316
317     const AtomicString& name() const final;
318
319     void endEditing();
320
321     void setSpellcheckDisabledExceptTextReplacement(bool disabled) { m_isSpellcheckDisabledExceptTextReplacement = disabled; }
322     bool isSpellcheckDisabledExceptTextReplacement() const { return m_isSpellcheckDisabledExceptTextReplacement; }
323
324     static Vector<FileChooserFileInfo> filesFromFileInputFormControlState(const FormControlState&);
325
326     bool matchesReadWritePseudoClass() const final;
327     WEBCORE_EXPORT ExceptionOr<void> setRangeText(const String& replacement) final;
328     WEBCORE_EXPORT ExceptionOr<void> setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode) final;
329
330     HTMLImageLoader* imageLoader() { return m_imageLoader.get(); }
331     HTMLImageLoader& ensureImageLoader();
332
333 #if ENABLE(DATE_AND_TIME_INPUT_TYPES)
334     bool setupDateTimeChooserParameters(DateTimeChooserParameters&);
335 #endif
336
337     void capsLockStateMayHaveChanged();
338
339     bool shouldTruncateText(const RenderStyle&) const;
340
341     ExceptionOr<int> selectionStartForBindings() const;
342     ExceptionOr<void> setSelectionStartForBindings(int);
343
344     ExceptionOr<int> selectionEndForBindings() const;
345     ExceptionOr<void> setSelectionEndForBindings(int);
346
347     ExceptionOr<String> selectionDirectionForBindings() const;
348     ExceptionOr<void> setSelectionDirectionForBindings(const String&);
349
350     ExceptionOr<void> setSelectionRangeForBindings(int start, int end, const String& direction);
351
352 protected:
353     HTMLInputElement(const QualifiedName&, Document&, HTMLFormElement*, bool createdByParser);
354
355     void defaultEventHandler(Event&) override;
356
357 private:
358     enum AutoCompleteSetting { Uninitialized, On, Off };
359
360     void didAddUserAgentShadowRoot(ShadowRoot&) final;
361
362     void willChangeForm() final;
363     void didChangeForm() final;
364     InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) final;
365     void didFinishInsertingNode() final;
366     void removedFromAncestor(RemovalType, ContainerNode&) final;
367     void didMoveToNewDocument(Document& oldDocument, Document& newDocument) final;
368
369     bool hasCustomFocusLogic() const final;
370     bool isKeyboardFocusable(KeyboardEvent*) const final;
371     bool isMouseFocusable() const final;
372     bool isEnumeratable() const final;
373     bool supportLabels() const final;
374     void updateFocusAppearance(SelectionRestorationMode, SelectionRevealMode) final;
375     bool shouldUseInputMethod() final;
376
377     bool isInnerTextElementEditable() const final { return !hasAutoFillStrongPasswordButton() && HTMLTextFormControlElement::isInnerTextElementEditable(); }
378
379     bool canTriggerImplicitSubmission() const final { return isTextField(); }
380
381     const AtomicString& formControlType() const final;
382
383     bool shouldSaveAndRestoreFormControlState() const final;
384     FormControlState saveFormControlState() const final;
385     void restoreFormControlState(const FormControlState&) final;
386
387     void resignStrongPasswordAppearance();
388
389     bool canStartSelection() const final;
390
391     void accessKeyAction(bool sendMouseEvents) final;
392
393     void parseAttribute(const QualifiedName&, const AtomicString&) final;
394     bool isPresentationAttribute(const QualifiedName&) const final;
395     void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStyleProperties&) final;
396     void finishParsingChildren() final;
397     void parserDidSetAttributes() final;
398
399     void copyNonAttributePropertiesFromElement(const Element&) final;
400
401     bool appendFormData(DOMFormData&, bool) final;
402
403     bool isSuccessfulSubmitButton() const final;
404     bool matchesDefaultPseudoClass() const final;
405
406     void reset() final;
407
408     bool isURLAttribute(const Attribute&) const final;
409     bool isInRange() const final;
410     bool isOutOfRange() const final;
411
412     void resumeFromDocumentSuspension() final;
413 #if ENABLE(INPUT_TYPE_COLOR)
414     void prepareForDocumentSuspension() final;
415 #endif
416
417     void addSubresourceAttributeURLs(ListHashSet<URL>&) const final;
418
419     bool needsSuspensionCallback();
420     void registerForSuspensionCallbackIfNeeded();
421     void unregisterForSuspensionCallbackIfNeeded();
422
423     bool supportsMinLength() const { return isTextType(); }
424     bool supportsMaxLength() const { return isTextType(); }
425     bool isTextType() const;
426     bool tooShort(StringView, NeedsToCheckDirtyFlag) const;
427     bool tooLong(StringView, NeedsToCheckDirtyFlag) const;
428
429     bool supportsPlaceholder() const final;
430     void updatePlaceholderText() final;
431     bool isEmptyValue() const final;
432     void handleFocusEvent(Node* oldFocusedNode, FocusDirection) final;
433     void handleBlurEvent() final;
434
435     bool isOptionalFormControl() const final { return !isRequiredFormControl(); }
436     bool isRequiredFormControl() const final;
437     bool computeWillValidate() const final;
438     void requiredStateChanged() final;
439
440     void initializeInputType();
441     void updateType();
442     void runPostTypeUpdateTasks();
443
444     void subtreeHasChanged() final;
445     void disabledStateChanged() final;
446     void readOnlyStateChanged() final;
447
448 #if ENABLE(DATALIST_ELEMENT)
449     void resetListAttributeTargetObserver();
450 #endif
451     void maxLengthAttributeChanged(const AtomicString& newValue);
452     void minLengthAttributeChanged(const AtomicString& newValue);
453     void updateValueIfNeeded();
454
455     void addToRadioButtonGroup();
456     void removeFromRadioButtonGroup();
457
458     AtomicString m_name;
459     String m_valueIfDirty;
460     unsigned m_size;
461     short m_maxResults { -1 };
462     bool m_isChecked : 1;
463     bool m_reflectsCheckedAttribute : 1;
464     bool m_isIndeterminate : 1;
465     bool m_hasType : 1;
466     bool m_isActivatedSubmit : 1;
467     unsigned m_autocomplete : 2; // AutoCompleteSetting
468     bool m_isAutoFilled : 1;
469     unsigned m_autoFillButtonType : 3; // AutoFillButtonType
470     unsigned m_lastAutoFillButtonType : 3; // AutoFillButtonType
471     bool m_isAutoFillAvailable : 1;
472 #if ENABLE(DATALIST_ELEMENT)
473     bool m_hasNonEmptyList : 1;
474 #endif
475     bool m_stateRestored : 1;
476     bool m_parsingInProgress : 1;
477     bool m_valueAttributeWasUpdatedAfterParsing : 1;
478     bool m_wasModifiedByUser : 1;
479     bool m_canReceiveDroppedFiles : 1;
480 #if ENABLE(TOUCH_EVENTS)
481     bool m_hasTouchEventHandler : 1;
482 #endif
483     bool m_isSpellcheckDisabledExceptTextReplacement : 1;
484     RefPtr<InputType> m_inputType;
485     // The ImageLoader must be owned by this element because the loader code assumes
486     // that it lives as long as its owning element lives. If we move the loader into
487     // the ImageInput object we may delete the loader while this element lives on.
488     std::unique_ptr<HTMLImageLoader> m_imageLoader;
489 #if ENABLE(DATALIST_ELEMENT)
490     std::unique_ptr<ListAttributeTargetObserver> m_listAttributeTargetObserver;
491 #endif
492 };
493
494 }