blob: e0098012989f4cbe44de9662201057f1252c64ba [file] [log] [blame]
darina51de912007-04-29 20:32:51 +00001/*
darinb9481ed2006-03-20 02:57:59 +00002 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
weinig@apple.comfa4b1a12008-06-15 02:03:24 +00004 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
staikos@webkit.org159f11f2009-05-18 23:48:30 +00005 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
rniwa@webkit.orgd10f6702011-10-25 00:13:34 +00006 * Copyright (C) 2011 Motorola Mobility. All rights reserved.
darinb9481ed2006-03-20 02:57:59 +00007 *
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
ddkilzerc8eccec2007-09-26 02:29:57 +000020 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
darinb9481ed2006-03-20 02:57:59 +000022 *
23 */
24
25#include "config.h"
26#include "HTMLElement.h"
27
commit-queue@webkit.org5d3b4a72011-12-23 07:29:32 +000028#include "CSSParser.h"
weinig681a5172006-06-19 22:58:36 +000029#include "CSSPropertyNames.h"
30#include "CSSValueKeywords.h"
kling@webkit.orgc92997c2012-02-23 01:40:12 +000031#include "CSSValuePool.h"
cdumez@apple.com5863cc72016-02-04 16:57:44 +000032#include "DOMTokenList.h"
darin36d11362006-04-11 16:30:21 +000033#include "DocumentFragment.h"
darin@apple.comd8db0872013-10-11 15:07:12 +000034#include "ElementAncestorIterator.h"
darinf1bb0042006-12-01 22:46:21 +000035#include "Event.h"
darinb9481ed2006-03-20 02:57:59 +000036#include "EventListener.h"
37#include "EventNames.h"
38#include "ExceptionCode.h"
39#include "Frame.h"
abarth@webkit.org401a3792013-03-03 10:12:59 +000040#include "FrameLoader.h"
antti@apple.com4942ea52013-12-20 14:44:23 +000041#include "FrameView.h"
cdumez@apple.comcd131532014-09-27 01:32:34 +000042#include "HTMLBDIElement.h"
anderscac1c14c92006-07-07 01:00:32 +000043#include "HTMLBRElement.h"
akling@apple.com4d48f412016-08-26 21:46:07 +000044#include "HTMLButtonElement.h"
darin@apple.com9a925fa2009-05-04 18:00:34 +000045#include "HTMLCollection.h"
darinb9481ed2006-03-20 02:57:59 +000046#include "HTMLDocument.h"
47#include "HTMLElementFactory.h"
akling@apple.com4d48f412016-08-26 21:46:07 +000048#include "HTMLFieldSetElement.h"
darin9efc76e2007-05-29 17:41:17 +000049#include "HTMLFormElement.h"
akling@apple.com4d48f412016-08-26 21:46:07 +000050#include "HTMLInputElement.h"
darin98fa8b82006-03-20 08:03:57 +000051#include "HTMLNames.h"
akling@apple.com4d48f412016-08-26 21:46:07 +000052#include "HTMLOptGroupElement.h"
53#include "HTMLOptionElement.h"
abarth@webkit.org9f272bb2010-09-14 22:53:02 +000054#include "HTMLParserIdioms.h"
akling@apple.com4d48f412016-08-26 21:46:07 +000055#include "HTMLSelectElement.h"
56#include "HTMLTextAreaElement.h"
yael.aharon@nokia.com0a5d0e52011-08-05 14:36:33 +000057#include "HTMLTextFormControlElement.h"
antti@apple.com5d47b582012-12-11 00:13:29 +000058#include "NodeTraversal.h"
cdumez@apple.com43c01da2014-11-06 23:17:32 +000059#include "RenderElement.h"
weinig@apple.com123e4aa2013-04-14 00:54:27 +000060#include "ScriptController.h"
darin@apple.comab6c146e2016-09-06 03:33:50 +000061#include "SimulatedClick.h"
antti@apple.come5428c52013-11-28 20:53:22 +000062#include "StyleProperties.h"
akling@apple.com7f81b1e2013-09-06 17:23:03 +000063#include "SubframeLoader.h"
darin42563ac52007-01-22 17:28:57 +000064#include "Text.h"
commit-queue@webkit.org5d3b4a72011-12-23 07:29:32 +000065#include "XMLNames.h"
weinig681a5172006-06-19 22:58:36 +000066#include "markup.h"
darin@apple.com8ceb5ba2013-09-14 16:19:14 +000067#include <wtf/NeverDestroyed.h>
bolsinga@apple.com97e42c42008-11-15 04:47:20 +000068#include <wtf/StdLibExtras.h>
andreas.kling@nokia.com5fac4182010-09-16 15:17:46 +000069#include <wtf/text/CString.h>
darinb9481ed2006-03-20 02:57:59 +000070
71namespace WebCore {
72
darinb9481ed2006-03-20 02:57:59 +000073using namespace HTMLNames;
yael.aharon@nokia.com0a5d0e52011-08-05 14:36:33 +000074using namespace WTF;
darinb9481ed2006-03-20 02:57:59 +000075
weinig@apple.com02f433a2015-01-06 22:32:48 +000076Ref<HTMLElement> HTMLElement::create(const QualifiedName& tagName, Document& document)
darinb9481ed2006-03-20 02:57:59 +000077{
weinig@apple.com02f433a2015-01-06 22:32:48 +000078 return adoptRef(*new HTMLElement(tagName, document));
darinb9481ed2006-03-20 02:57:59 +000079}
80
81String HTMLElement::nodeName() const
82{
darin@apple.com048cc3a2016-01-22 17:17:04 +000083 // FIXME: Would be nice to have an AtomicString lookup based off uppercase
84 // ASCII characters that does not have to copy the string on a hit in the hash.
cdumez@apple.com892c7c22015-09-11 14:51:32 +000085 if (document().isHTMLDocument()) {
rniwa@webkit.orgcd6bdd42016-01-23 02:04:41 +000086 if (LIKELY(!tagQName().hasPrefix()))
cdumez@apple.com892c7c22015-09-11 14:51:32 +000087 return tagQName().localNameUpper();
rniwa@webkit.orgcd6bdd42016-01-23 02:04:41 +000088 return Element::nodeName().convertToASCIIUppercase();
cdumez@apple.com892c7c22015-09-11 14:51:32 +000089 }
darinb9481ed2006-03-20 02:57:59 +000090 return Element::nodeName();
91}
darinb9481ed2006-03-20 02:57:59 +000092
darin@apple.comd8db0872013-10-11 15:07:12 +000093static inline CSSValueID unicodeBidiAttributeForDirAuto(HTMLElement& element)
leviw@chromium.org7781b6a2011-06-27 22:01:38 +000094{
darin@apple.com15708b12014-03-16 16:38:58 +000095 if (element.hasTagName(preTag) || element.hasTagName(textareaTag))
leviw@chromium.org7781b6a2011-06-27 22:01:38 +000096 return CSSValueWebkitPlaintext;
rniwa@webkit.org01f7f672011-11-28 19:19:37 +000097 // FIXME: For bdo element, dir="auto" should result in "bidi-override isolate" but we don't support having multiple values in unicode-bidi yet.
98 // See https://bugs.webkit.org/show_bug.cgi?id=73164.
99 return CSSValueWebkitIsolate;
leviw@chromium.org7781b6a2011-06-27 22:01:38 +0000100}
101
akling@apple.comb75eeea2013-02-23 17:57:50 +0000102unsigned HTMLElement::parseBorderWidthAttribute(const AtomicString& value) const
commit-queue@webkit.org77f2f392011-08-01 11:18:15 +0000103{
cdumez@apple.com2702e9c2016-09-08 21:31:54 +0000104 if (Optional<unsigned> borderWidth = parseHTMLNonNegativeInteger(value))
cdumez@apple.com7a2e4052016-03-02 17:12:37 +0000105 return borderWidth.value();
106
107 return hasTagName(tableTag) ? 1 : 0;
commit-queue@webkit.org77f2f392011-08-01 11:18:15 +0000108}
109
antti@apple.come5428c52013-11-28 20:53:22 +0000110void HTMLElement::applyBorderAttributeToStyle(const AtomicString& value, MutableStyleProperties& style)
commit-queue@webkit.org2c5d5c62011-09-02 17:01:42 +0000111{
akling@apple.comb75eeea2013-02-23 17:57:50 +0000112 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderWidth, parseBorderWidthAttribute(value), CSSPrimitiveValue::CSS_PX);
kling@webkit.org569556d2012-11-12 23:52:12 +0000113 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderStyle, CSSValueSolid);
commit-queue@webkit.org2c5d5c62011-09-02 17:01:42 +0000114}
115
antti@apple.come5428c52013-11-28 20:53:22 +0000116void HTMLElement::mapLanguageAttributeToLocale(const AtomicString& value, MutableStyleProperties& style)
commit-queue@webkit.org5d3b4a72011-12-23 07:29:32 +0000117{
akling@apple.comb75eeea2013-02-23 17:57:50 +0000118 if (!value.isEmpty()) {
commit-queue@webkit.org5d3b4a72011-12-23 07:29:32 +0000119 // Have to quote so the locale id is treated as a string instead of as a CSS keyword.
akling@apple.comb75eeea2013-02-23 17:57:50 +0000120 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitLocale, quoteCSSString(value));
commit-queue@webkit.org5d3b4a72011-12-23 07:29:32 +0000121 } else {
122 // The empty string means the language is explicitly unknown.
kling@webkit.org569556d2012-11-12 23:52:12 +0000123 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitLocale, CSSValueAuto);
commit-queue@webkit.org5d3b4a72011-12-23 07:29:32 +0000124 }
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000125}
126
kling@webkit.org44bc0dd2012-02-28 22:21:02 +0000127bool HTMLElement::isPresentationAttribute(const QualifiedName& name) const
kling@webkit.org11f25562012-02-13 10:36:55 +0000128{
kling@webkit.org44bc0dd2012-02-28 22:21:02 +0000129 if (name == alignAttr || name == contenteditableAttr || name == hiddenAttr || name == langAttr || name.matches(XMLNames::langAttr) || name == draggableAttr || name == dirAttr)
kling@webkit.org11f25562012-02-13 10:36:55 +0000130 return true;
kling@webkit.org44bc0dd2012-02-28 22:21:02 +0000131 return StyledElement::isPresentationAttribute(name);
kling@webkit.org11f25562012-02-13 10:36:55 +0000132}
133
rniwa@webkit.org8b638ce2013-12-17 20:10:12 +0000134static bool isLTROrRTLIgnoringCase(const AtomicString& dirAttributeValue)
135{
darin@apple.com048cc3a2016-01-22 17:17:04 +0000136 return equalLettersIgnoringASCIICase(dirAttributeValue, "rtl") || equalLettersIgnoringASCIICase(dirAttributeValue, "ltr");
rniwa@webkit.org8b638ce2013-12-17 20:10:12 +0000137}
138
rniwa@webkit.org095ae4e2015-02-25 18:42:04 +0000139enum class ContentEditableType {
140 Inherit,
141 True,
142 False,
143 PlaintextOnly
144};
145
146static inline ContentEditableType contentEditableType(const AtomicString& value)
147{
148 if (value.isNull())
149 return ContentEditableType::Inherit;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000150 if (value.isEmpty() || equalLettersIgnoringASCIICase(value, "true"))
rniwa@webkit.org095ae4e2015-02-25 18:42:04 +0000151 return ContentEditableType::True;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000152 if (equalLettersIgnoringASCIICase(value, "false"))
rniwa@webkit.org095ae4e2015-02-25 18:42:04 +0000153 return ContentEditableType::False;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000154 if (equalLettersIgnoringASCIICase(value, "plaintext-only"))
rniwa@webkit.org095ae4e2015-02-25 18:42:04 +0000155 return ContentEditableType::PlaintextOnly;
156
157 return ContentEditableType::Inherit;
158}
159
160static ContentEditableType contentEditableType(const HTMLElement& element)
161{
rniwa@webkit.orge999a052016-07-16 15:21:55 +0000162 return contentEditableType(element.attributeWithoutSynchronization(contenteditableAttr));
rniwa@webkit.org095ae4e2015-02-25 18:42:04 +0000163}
164
antti@apple.come5428c52013-11-28 20:53:22 +0000165void HTMLElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStyleProperties& style)
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000166{
akling@apple.comb75eeea2013-02-23 17:57:50 +0000167 if (name == alignAttr) {
darin@apple.com048cc3a2016-01-22 17:17:04 +0000168 if (equalLettersIgnoringASCIICase(value, "middle"))
kling@webkit.org569556d2012-11-12 23:52:12 +0000169 addPropertyToPresentationAttributeStyle(style, CSSPropertyTextAlign, CSSValueCenter);
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000170 else
akling@apple.comb75eeea2013-02-23 17:57:50 +0000171 addPropertyToPresentationAttributeStyle(style, CSSPropertyTextAlign, value);
172 } else if (name == contenteditableAttr) {
rniwa@webkit.org095ae4e2015-02-25 18:42:04 +0000173 CSSValueID userModifyValue = CSSValueReadWrite;
174 switch (contentEditableType(value)) {
175 case ContentEditableType::Inherit:
176 return;
177 case ContentEditableType::False:
178 userModifyValue = CSSValueReadOnly;
179 break;
180 case ContentEditableType::PlaintextOnly:
181 userModifyValue = CSSValueReadWritePlaintextOnly;
182 FALLTHROUGH;
183 case ContentEditableType::True:
kling@webkit.org569556d2012-11-12 23:52:12 +0000184 addPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap, CSSValueBreakWord);
185 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitNbspMode, CSSValueSpace);
186 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace);
dbates@webkit.org1edd81d2013-12-18 00:15:02 +0000187#if PLATFORM(IOS)
188 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitTextSizeAdjust, CSSValueNone);
189#endif
rniwa@webkit.org095ae4e2015-02-25 18:42:04 +0000190 break;
191 }
192 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserModify, userModifyValue);
akling@apple.comb75eeea2013-02-23 17:57:50 +0000193 } else if (name == hiddenAttr) {
kling@webkit.org569556d2012-11-12 23:52:12 +0000194 addPropertyToPresentationAttributeStyle(style, CSSPropertyDisplay, CSSValueNone);
akling@apple.comb75eeea2013-02-23 17:57:50 +0000195 } else if (name == draggableAttr) {
darin@apple.com048cc3a2016-01-22 17:17:04 +0000196 if (equalLettersIgnoringASCIICase(value, "true")) {
kling@webkit.org569556d2012-11-12 23:52:12 +0000197 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserDrag, CSSValueElement);
198 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserSelect, CSSValueNone);
darin@apple.com048cc3a2016-01-22 17:17:04 +0000199 } else if (equalLettersIgnoringASCIICase(value, "false"))
kling@webkit.org569556d2012-11-12 23:52:12 +0000200 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserDrag, CSSValueNone);
akling@apple.comb75eeea2013-02-23 17:57:50 +0000201 } else if (name == dirAttr) {
darin@apple.com048cc3a2016-01-22 17:17:04 +0000202 if (equalLettersIgnoringASCIICase(value, "auto"))
darin@apple.comd8db0872013-10-11 15:07:12 +0000203 addPropertyToPresentationAttributeStyle(style, CSSPropertyUnicodeBidi, unicodeBidiAttributeForDirAuto(*this));
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000204 else {
rniwa@webkit.org8b638ce2013-12-17 20:10:12 +0000205 if (isLTROrRTLIgnoringCase(value))
206 addPropertyToPresentationAttributeStyle(style, CSSPropertyDirection, value);
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000207 if (!hasTagName(bdiTag) && !hasTagName(bdoTag) && !hasTagName(outputTag))
kling@webkit.org569556d2012-11-12 23:52:12 +0000208 addPropertyToPresentationAttributeStyle(style, CSSPropertyUnicodeBidi, CSSValueEmbed);
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000209 }
akling@apple.comb75eeea2013-02-23 17:57:50 +0000210 } else if (name.matches(XMLNames::langAttr))
211 mapLanguageAttributeToLocale(value, style);
212 else if (name == langAttr) {
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000213 // xml:lang has a higher priority than lang.
rniwa@webkit.orgbda54a02016-07-18 00:39:37 +0000214 if (!hasAttributeWithoutSynchronization(XMLNames::langAttr))
akling@apple.comb75eeea2013-02-23 17:57:50 +0000215 mapLanguageAttributeToLocale(value, style);
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000216 } else
akling@apple.comb75eeea2013-02-23 17:57:50 +0000217 StyledElement::collectStyleForPresentationAttribute(name, value, style);
commit-queue@webkit.org5d3b4a72011-12-23 07:29:32 +0000218}
219
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000220HTMLElement::EventHandlerNameMap HTMLElement::createEventHandlerNameMap()
keishi@webkit.orgb61c3832013-03-29 09:59:09 +0000221{
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000222 EventHandlerNameMap map;
223
224 static const QualifiedName* const table[] = {
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000225 &onabortAttr,
darin@apple.com25da4122015-03-11 02:21:20 +0000226 &onanimationendAttr,
227 &onanimationiterationAttr,
228 &onanimationstartAttr,
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000229 &onautocompleteAttr,
230 &onautocompleteerrorAttr,
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000231 &onbeforecopyAttr,
232 &onbeforecutAttr,
wenson_hsieh@apple.com2bebcde2016-10-07 23:47:18 +0000233 &onbeforeinputAttr,
darin@apple.com25da4122015-03-11 02:21:20 +0000234 &onbeforeloadAttr,
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000235 &onbeforepasteAttr,
236 &onblurAttr,
237 &oncanplayAttr,
238 &oncanplaythroughAttr,
239 &onchangeAttr,
240 &onclickAttr,
241 &oncontextmenuAttr,
242 &oncopyAttr,
243 &oncutAttr,
244 &ondblclickAttr,
245 &ondragAttr,
246 &ondragendAttr,
247 &ondragenterAttr,
248 &ondragleaveAttr,
249 &ondragoverAttr,
250 &ondragstartAttr,
251 &ondropAttr,
252 &ondurationchangeAttr,
253 &onemptiedAttr,
254 &onendedAttr,
255 &onerrorAttr,
256 &onfocusAttr,
257 &onfocusinAttr,
258 &onfocusoutAttr,
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000259 &ongesturechangeAttr,
260 &ongestureendAttr,
261 &ongesturestartAttr,
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000262 &oninputAttr,
263 &oninvalidAttr,
264 &onkeydownAttr,
265 &onkeypressAttr,
266 &onkeyupAttr,
267 &onloadAttr,
268 &onloadeddataAttr,
269 &onloadedmetadataAttr,
270 &onloadstartAttr,
271 &onmousedownAttr,
272 &onmouseenterAttr,
273 &onmouseleaveAttr,
274 &onmousemoveAttr,
275 &onmouseoutAttr,
276 &onmouseoverAttr,
277 &onmouseupAttr,
278 &onmousewheelAttr,
279 &onpasteAttr,
280 &onpauseAttr,
281 &onplayAttr,
282 &onplayingAttr,
283 &onprogressAttr,
284 &onratechangeAttr,
285 &onresetAttr,
commit-queue@webkit.orgaeaaa2d2016-02-01 06:34:07 +0000286 &onresizeAttr,
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000287 &onscrollAttr,
darin@apple.com25da4122015-03-11 02:21:20 +0000288 &onsearchAttr,
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000289 &onseekedAttr,
290 &onseekingAttr,
291 &onselectAttr,
292 &onselectstartAttr,
293 &onstalledAttr,
294 &onsubmitAttr,
295 &onsuspendAttr,
296 &ontimeupdateAttr,
cdumez@apple.com40261112016-10-19 02:03:07 +0000297 &ontoggleAttr,
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000298 &ontouchcancelAttr,
299 &ontouchendAttr,
bdakin@apple.com4e191ed2016-03-08 20:18:51 +0000300 &ontouchforcechangeAttr,
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000301 &ontouchmoveAttr,
302 &ontouchstartAttr,
darin@apple.com25da4122015-03-11 02:21:20 +0000303 &ontransitionendAttr,
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000304 &onvolumechangeAttr,
305 &onwaitingAttr,
darin@apple.com25da4122015-03-11 02:21:20 +0000306 &onwebkitbeginfullscreenAttr,
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000307 &onwebkitcurrentplaybacktargetiswirelesschangedAttr,
darin@apple.com25da4122015-03-11 02:21:20 +0000308 &onwebkitendfullscreenAttr,
darin@apple.com25da4122015-03-11 02:21:20 +0000309 &onwebkitfullscreenchangeAttr,
310 &onwebkitfullscreenerrorAttr,
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000311 &onwebkitkeyaddedAttr,
312 &onwebkitkeyerrorAttr,
313 &onwebkitkeymessageAttr,
bdakin@apple.comfe249052015-03-24 21:31:28 +0000314 &onwebkitmouseforcechangedAttr,
bdakin@apple.comfe249052015-03-24 21:31:28 +0000315 &onwebkitmouseforcedownAttr,
316 &onwebkitmouseforcewillbeginAttr,
317 &onwebkitmouseforceupAttr,
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000318 &onwebkitneedkeyAttr,
319 &onwebkitplaybacktargetavailabilitychangedAttr,
darin@apple.com25da4122015-03-11 02:21:20 +0000320 &onwebkitpresentationmodechangedAttr,
bdakin@apple.comd7c6a1e2014-01-30 19:25:25 +0000321 &onwebkitwillrevealbottomAttr,
322 &onwebkitwillrevealleftAttr,
323 &onwebkitwillrevealrightAttr,
324 &onwebkitwillrevealtopAttr,
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000325 &onwheelAttr,
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000326 };
327
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000328 populateEventHandlerNameMap(map, table);
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000329
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000330 struct UnusualMapping {
darin@apple.com5b7f3072013-09-15 08:50:06 +0000331 const QualifiedName& attributeName;
332 const AtomicString& eventName;
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000333 };
334
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000335 const UnusualMapping unusualPairsTable[] = {
darin@apple.com5b7f3072013-09-15 08:50:06 +0000336 { onwebkitanimationendAttr, eventNames().webkitAnimationEndEvent },
337 { onwebkitanimationiterationAttr, eventNames().webkitAnimationIterationEvent },
338 { onwebkitanimationstartAttr, eventNames().webkitAnimationStartEvent },
339 { onwebkittransitionendAttr, eventNames().webkitTransitionEndEvent },
darin@apple.com8ceb5ba2013-09-14 16:19:14 +0000340 };
341
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000342 for (auto& entry : unusualPairsTable)
343 map.add(entry.attributeName.localName().impl(), entry.eventName);
344
345 return map;
346}
347
348void HTMLElement::populateEventHandlerNameMap(EventHandlerNameMap& map, const QualifiedName* const table[], size_t tableSize)
349{
350 for (size_t i = 0; i < tableSize; ++i) {
351 auto* entry = table[i];
352
353 // FIXME: Would be nice to check these against the actual event names in eventNames().
354 // Not obvious how to do that simply, though.
355 auto& attributeName = entry->localName();
356
357 // Remove the "on" prefix. Requires some memory allocation and computing a hash, but by not
358 // using pointers from eventNames(), the passed-in table can be initialized at compile time.
359 AtomicString eventName = attributeName.string().substring(2);
360
aestes@apple.com13aae082016-01-02 08:03:08 +0000361 map.add(attributeName.impl(), WTFMove(eventName));
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000362 }
363}
364
365const AtomicString& HTMLElement::eventNameForEventHandlerAttribute(const QualifiedName& attributeName, const EventHandlerNameMap& map)
366{
367 ASSERT(!attributeName.localName().isNull());
368
369 // Event handler attributes have no namespace.
370 if (!attributeName.namespaceURI().isNull())
371 return nullAtom;
372
373 // Fast early return for names that don't start with "on".
374 AtomicStringImpl& localName = *attributeName.localName().impl();
375 if (localName.length() < 3 || localName[0] != 'o' || localName[1] != 'n')
376 return nullAtom;
377
378 auto it = map.find(&localName);
379 return it == map.end() ? nullAtom : it->value;
380}
381
382const AtomicString& HTMLElement::eventNameForEventHandlerAttribute(const QualifiedName& attributeName)
383{
384 static NeverDestroyed<EventHandlerNameMap> map = createEventHandlerNameMap();
385 return eventNameForEventHandlerAttribute(attributeName, map.get());
keishi@webkit.orgb61c3832013-03-29 09:59:09 +0000386}
387
rniwa@webkit.orgdbb2a292015-03-01 19:52:21 +0000388Node::Editability HTMLElement::editabilityFromContentEditableAttr(const Node& node)
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000389{
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000390 if (auto* startElement = is<Element>(node) ? &downcast<Element>(node) : node.parentElement()) {
391 for (auto& element : lineageOfType<HTMLElement>(*startElement)) {
392 switch (contentEditableType(element)) {
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000393 case ContentEditableType::True:
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000394 return Editability::CanEditRichly;
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000395 case ContentEditableType::PlaintextOnly:
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000396 return Editability::CanEditPlainText;
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000397 case ContentEditableType::False:
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000398 return Editability::ReadOnly;
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000399 case ContentEditableType::Inherit:
400 break;
401 }
402 }
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000403 }
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000404
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000405 auto& document = node.document();
cdumez@apple.com21bd4282014-09-29 16:58:42 +0000406 if (is<HTMLDocument>(document))
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000407 return downcast<HTMLDocument>(document).inDesignMode() ? Editability::CanEditRichly : Editability::ReadOnly;
rniwa@webkit.orgdbb2a292015-03-01 19:52:21 +0000408
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000409 return Editability::ReadOnly;
rniwa@webkit.orgdbb2a292015-03-01 19:52:21 +0000410}
411
412bool HTMLElement::matchesReadWritePseudoClass() const
413{
414 return editabilityFromContentEditableAttr(*this) != Editability::ReadOnly;
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000415}
416
akling@apple.com43e9d042012-11-18 16:55:06 +0000417void HTMLElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
darinb9481ed2006-03-20 02:57:59 +0000418{
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000419 if (name == dirAttr) {
akling@apple.com43e9d042012-11-18 16:55:06 +0000420 dirAttributeChanged(value);
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000421 return;
422 }
423
424 if (name == tabindexAttr) {
akling@apple.com43e9d042012-11-18 16:55:06 +0000425 if (value.isEmpty())
rniwa@webkit.org2015feb2013-01-14 23:57:39 +0000426 clearTabIndexExplicitlyIfNeeded();
cdumez@apple.com825cfbb2016-03-08 06:38:10 +0000427 else if (Optional<int> tabIndex = parseHTMLInteger(value))
428 setTabIndexExplicitly(tabIndex.value());
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000429 return;
ggaren59d1d762006-04-22 07:33:04 +0000430 }
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000431
432 auto& eventName = eventNameForEventHandlerAttribute(name);
433 if (!eventName.isNull())
434 setAttributeEventListener(eventName, name, value);
darinb9481ed2006-03-20 02:57:59 +0000435}
436
darin@apple.com66d41182016-10-29 02:32:20 +0000437ExceptionOr<Ref<DocumentFragment>> HTMLElement::textToFragment(const String& text)
commit-queue@webkit.org129fb5f2011-01-13 22:49:44 +0000438{
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000439 auto fragment = DocumentFragment::create(document());
440
441 for (unsigned start = 0, length = text.length(); start < length; ) {
commit-queue@webkit.org129fb5f2011-01-13 22:49:44 +0000442
443 // Find next line break.
pvollan@apple.com63945512016-08-26 13:29:31 +0000444 UChar c = 0;
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000445 unsigned i;
commit-queue@webkit.org129fb5f2011-01-13 22:49:44 +0000446 for (i = start; i < length; i++) {
darin@apple.comd8db0872013-10-11 15:07:12 +0000447 c = text[i];
448 if (c == '\r' || c == '\n')
449 break;
commit-queue@webkit.org129fb5f2011-01-13 22:49:44 +0000450 }
451
darin@apple.com4a588ff2016-11-11 20:16:03 +0000452 auto appendResult = fragment->appendChild(Text::create(document(), text.substring(start, i - start)));
453 if (appendResult.hasException())
454 return appendResult.releaseException();
commit-queue@webkit.org129fb5f2011-01-13 22:49:44 +0000455
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000456 if (i == length)
457 break;
458
darin@apple.com4a588ff2016-11-11 20:16:03 +0000459 appendResult = fragment->appendChild(HTMLBRElement::create(document()));
460 if (appendResult.hasException())
461 return appendResult.releaseException();
darin@apple.comc52c9bf2015-03-15 17:00:33 +0000462
463 // Make sure \r\n doesn't result in two line breaks.
464 if (c == '\r' && i + 1 < length && text[i + 1] == '\n')
465 ++i;
commit-queue@webkit.org129fb5f2011-01-13 22:49:44 +0000466
467 start = i + 1; // Character after line break.
468 }
469
darin@apple.com66d41182016-10-29 02:32:20 +0000470 return WTFMove(fragment);
commit-queue@webkit.org129fb5f2011-01-13 22:49:44 +0000471}
472
darin@apple.com15708b12014-03-16 16:38:58 +0000473static inline bool shouldProhibitSetInnerOuterText(const HTMLElement& element)
474{
475 return element.hasTagName(colTag)
476 || element.hasTagName(colgroupTag)
477 || element.hasTagName(framesetTag)
478 || element.hasTagName(headTag)
479 || element.hasTagName(htmlTag)
480 || element.hasTagName(tableTag)
481 || element.hasTagName(tbodyTag)
482 || element.hasTagName(tfootTag)
483 || element.hasTagName(theadTag)
484 || element.hasTagName(trTag);
485}
486
cdumez@apple.come9e8f112015-01-27 15:59:58 +0000487// Returns the conforming 'dir' value associated with the state the attribute is in (in its canonical case), if any,
488// or the empty string if the attribute is in a state that has no associated keyword value or if the attribute is
489// not in a defined state (e.g. the attribute is missing and there is no missing value default).
490// http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#limited-to-only-known-values
491static inline const AtomicString& toValidDirValue(const AtomicString& value)
492{
493 static NeverDestroyed<AtomicString> ltrValue("ltr", AtomicString::ConstructFromLiteral);
494 static NeverDestroyed<AtomicString> rtlValue("rtl", AtomicString::ConstructFromLiteral);
495 static NeverDestroyed<AtomicString> autoValue("auto", AtomicString::ConstructFromLiteral);
darin@apple.com048cc3a2016-01-22 17:17:04 +0000496 if (equalLettersIgnoringASCIICase(value, "ltr"))
cdumez@apple.come9e8f112015-01-27 15:59:58 +0000497 return ltrValue;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000498 if (equalLettersIgnoringASCIICase(value, "rtl"))
cdumez@apple.come9e8f112015-01-27 15:59:58 +0000499 return rtlValue;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000500 if (equalLettersIgnoringASCIICase(value, "auto"))
cdumez@apple.come9e8f112015-01-27 15:59:58 +0000501 return autoValue;
502 return nullAtom;
503}
504
505const AtomicString& HTMLElement::dir() const
506{
rniwa@webkit.orge999a052016-07-16 15:21:55 +0000507 return toValidDirValue(attributeWithoutSynchronization(dirAttr));
cdumez@apple.come9e8f112015-01-27 15:59:58 +0000508}
509
510void HTMLElement::setDir(const AtomicString& value)
511{
cdumez@apple.com36059222016-07-15 21:35:40 +0000512 setAttributeWithoutSynchronization(dirAttr, value);
cdumez@apple.come9e8f112015-01-27 15:59:58 +0000513}
514
darin@apple.com66d41182016-10-29 02:32:20 +0000515ExceptionOr<void> HTMLElement::setInnerText(const String& text)
darinb9481ed2006-03-20 02:57:59 +0000516{
darin@apple.com66d41182016-10-29 02:32:20 +0000517 if (ieForbidsInsertHTML())
518 return Exception { NO_MODIFICATION_ALLOWED_ERR };
519 if (shouldProhibitSetInnerOuterText(*this))
520 return Exception { NO_MODIFICATION_ALLOWED_ERR };
darinb9481ed2006-03-20 02:57:59 +0000521
darin38ae5342006-07-25 04:39:25 +0000522 // FIXME: This doesn't take whitespace collapsing into account at all.
anderscac1c14c92006-07-07 01:00:32 +0000523
darin38ae5342006-07-25 04:39:25 +0000524 if (!text.contains('\n') && !text.contains('\r')) {
darin48ef06c2007-05-29 19:39:14 +0000525 if (text.isEmpty()) {
526 removeChildren();
darin@apple.com66d41182016-10-29 02:32:20 +0000527 return { };
darin48ef06c2007-05-29 19:39:14 +0000528 }
darin@apple.com66d41182016-10-29 02:32:20 +0000529 return replaceChildrenWithText(*this, text);
anderscac1c14c92006-07-07 01:00:32 +0000530 }
darin38ae5342006-07-25 04:39:25 +0000531
532 // FIXME: Do we need to be able to detect preserveNewline style even when there's no renderer?
hyatt@apple.comf6d72f32009-04-10 00:05:02 +0000533 // FIXME: Can the renderer be out of date here? Do we need to call updateStyleIfNeeded?
darin38ae5342006-07-25 04:39:25 +0000534 // For example, for the contents of textarea elements that are display:none?
darin@apple.com8cdf7122013-09-30 02:40:50 +0000535 auto r = renderer();
antti@apple.com4942ea52013-12-20 14:44:23 +0000536 if ((r && r->style().preserveNewline()) || (inDocument() && isTextControlInnerTextElement())) {
darin@apple.com66d41182016-10-29 02:32:20 +0000537 if (!text.contains('\r'))
538 return replaceChildrenWithText(*this, text);
darin48ef06c2007-05-29 19:39:14 +0000539 String textWithConsistentLineBreaks = text;
darin38ae5342006-07-25 04:39:25 +0000540 textWithConsistentLineBreaks.replace("\r\n", "\n");
541 textWithConsistentLineBreaks.replace('\r', '\n');
darin@apple.com66d41182016-10-29 02:32:20 +0000542 return replaceChildrenWithText(*this, textWithConsistentLineBreaks);
darin38ae5342006-07-25 04:39:25 +0000543 }
544
545 // Add text nodes and <br> elements.
darin@apple.com66d41182016-10-29 02:32:20 +0000546 auto fragment = textToFragment(text);
547 if (fragment.hasException())
548 return fragment.releaseException();
549 return replaceChildrenWithFragment(*this, fragment.releaseReturnValue());
commit-queue@webkit.org129fb5f2011-01-13 22:49:44 +0000550}
551
darin@apple.com66d41182016-10-29 02:32:20 +0000552ExceptionOr<void> HTMLElement::setOuterText(const String& text)
darinb9481ed2006-03-20 02:57:59 +0000553{
darin@apple.com66d41182016-10-29 02:32:20 +0000554 if (ieForbidsInsertHTML())
555 return Exception { NO_MODIFICATION_ALLOWED_ERR };
556 if (shouldProhibitSetInnerOuterText(*this))
557 return Exception { NO_MODIFICATION_ALLOWED_ERR };
darinb9481ed2006-03-20 02:57:59 +0000558
darin@apple.comd8db0872013-10-11 15:07:12 +0000559 RefPtr<ContainerNode> parent = parentNode();
darin@apple.com66d41182016-10-29 02:32:20 +0000560 if (!parent)
561 return Exception { NO_MODIFICATION_ALLOWED_ERR };
darinb9481ed2006-03-20 02:57:59 +0000562
commit-queue@webkit.org129fb5f2011-01-13 22:49:44 +0000563 RefPtr<Node> prev = previousSibling();
564 RefPtr<Node> next = nextSibling();
565 RefPtr<Node> newChild;
darin@apple.com66d41182016-10-29 02:32:20 +0000566
commit-queue@webkit.org129fb5f2011-01-13 22:49:44 +0000567 // Convert text to fragment with <br> tags instead of linebreaks if needed.
darin@apple.com66d41182016-10-29 02:32:20 +0000568 if (text.contains('\r') || text.contains('\n')) {
569 auto result = textToFragment(text);
570 if (result.hasException())
571 return result.releaseException();
572 newChild = result.releaseReturnValue();
573 } else
weinig@apple.comf2a10f32013-09-15 13:31:54 +0000574 newChild = Text::create(document(), text);
commit-queue@webkit.org129fb5f2011-01-13 22:49:44 +0000575
ddkilzer@apple.com824b19e22014-09-06 15:02:58 +0000576 if (!parentNode())
darin@apple.com66d41182016-10-29 02:32:20 +0000577 return Exception { HIERARCHY_REQUEST_ERR };
578
darin@apple.com4a588ff2016-11-11 20:16:03 +0000579 auto replaceResult = parent->replaceChild(*newChild, *this);
580 if (replaceResult.hasException())
581 return replaceResult.releaseException();
darinb9481ed2006-03-20 02:57:59 +0000582
darin@apple.comd8db0872013-10-11 15:07:12 +0000583 RefPtr<Node> node = next ? next->previousSibling() : nullptr;
darin@apple.com66d41182016-10-29 02:32:20 +0000584 if (is<Text>(node.get())) {
darin@apple.com5e46c8582016-10-30 22:36:07 +0000585 auto result = mergeWithNextTextNode(downcast<Text>(*node));
586 if (result.hasException())
587 return result.releaseException();
darin@apple.com66d41182016-10-29 02:32:20 +0000588 }
589 if (is<Text>(prev.get())) {
darin@apple.com5e46c8582016-10-30 22:36:07 +0000590 auto result = mergeWithNextTextNode(downcast<Text>(*prev));
591 if (result.hasException())
592 return result.releaseException();
darin@apple.com66d41182016-10-29 02:32:20 +0000593 }
594 return { };
darinb9481ed2006-03-20 02:57:59 +0000595}
596
antti@apple.come5428c52013-11-28 20:53:22 +0000597void HTMLElement::applyAlignmentAttributeToStyle(const AtomicString& alignment, MutableStyleProperties& style)
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000598{
enrica@apple.com46e6d6a2010-02-23 21:31:11 +0000599 // Vertical alignment with respect to the current baseline of the text
600 // right or left means floating images.
alexis@webkit.org71873a02013-06-19 22:07:23 +0000601 CSSValueID floatValue = CSSValueInvalid;
602 CSSValueID verticalAlignValue = CSSValueInvalid;
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000603
darin@apple.com048cc3a2016-01-22 17:17:04 +0000604 if (equalLettersIgnoringASCIICase(alignment, "absmiddle"))
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000605 verticalAlignValue = CSSValueMiddle;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000606 else if (equalLettersIgnoringASCIICase(alignment, "absbottom"))
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000607 verticalAlignValue = CSSValueBottom;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000608 else if (equalLettersIgnoringASCIICase(alignment, "left")) {
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000609 floatValue = CSSValueLeft;
610 verticalAlignValue = CSSValueTop;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000611 } else if (equalLettersIgnoringASCIICase(alignment, "right")) {
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000612 floatValue = CSSValueRight;
613 verticalAlignValue = CSSValueTop;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000614 } else if (equalLettersIgnoringASCIICase(alignment, "top"))
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000615 verticalAlignValue = CSSValueTop;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000616 else if (equalLettersIgnoringASCIICase(alignment, "middle"))
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000617 verticalAlignValue = CSSValueWebkitBaselineMiddle;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000618 else if (equalLettersIgnoringASCIICase(alignment, "center"))
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000619 verticalAlignValue = CSSValueMiddle;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000620 else if (equalLettersIgnoringASCIICase(alignment, "bottom"))
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000621 verticalAlignValue = CSSValueBaseline;
darin@apple.com048cc3a2016-01-22 17:17:04 +0000622 else if (equalLettersIgnoringASCIICase(alignment, "texttop"))
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000623 verticalAlignValue = CSSValueTextTop;
624
625 if (floatValue != CSSValueInvalid)
kling@webkit.org569556d2012-11-12 23:52:12 +0000626 addPropertyToPresentationAttributeStyle(style, CSSPropertyFloat, floatValue);
zimmermann@webkit.orgfcd8b3c2008-12-11 23:42:12 +0000627
628 if (verticalAlignValue != CSSValueInvalid)
kling@webkit.org569556d2012-11-12 23:52:12 +0000629 addPropertyToPresentationAttributeStyle(style, CSSPropertyVerticalAlign, verticalAlignValue);
darinb9481ed2006-03-20 02:57:59 +0000630}
631
yosin@chromium.org77701e62012-08-28 05:41:50 +0000632bool HTMLElement::hasCustomFocusLogic() const
633{
634 return false;
635}
636
abarth@webkit.org40933792009-09-07 05:10:12 +0000637bool HTMLElement::supportsFocus() const
darinb9481ed2006-03-20 02:57:59 +0000638{
antti@apple.comf02be1e2013-12-21 18:51:04 +0000639 return Element::supportsFocus() || (hasEditableStyle() && parentNode() && !parentNode()->hasEditableStyle());
darinb9481ed2006-03-20 02:57:59 +0000640}
641
commit-queue@webkit.org595681f2011-03-25 16:21:30 +0000642String HTMLElement::contentEditable() const
darinb9481ed2006-03-20 02:57:59 +0000643{
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000644 switch (contentEditableType(*this)) {
645 case ContentEditableType::Inherit:
darin@apple.comd8db0872013-10-11 15:07:12 +0000646 return ASCIILiteral("inherit");
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000647 case ContentEditableType::True:
darin@apple.comd8db0872013-10-11 15:07:12 +0000648 return ASCIILiteral("true");
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000649 case ContentEditableType::False:
darin@apple.comd8db0872013-10-11 15:07:12 +0000650 return ASCIILiteral("false");
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000651 case ContentEditableType::PlaintextOnly:
darin@apple.comd8db0872013-10-11 15:07:12 +0000652 return ASCIILiteral("plaintext-only");
benjamin@webkit.orgec644552014-09-09 21:03:29 +0000653 }
darin@apple.comd8db0872013-10-11 15:07:12 +0000654 return ASCIILiteral("inherit");
darinb9481ed2006-03-20 02:57:59 +0000655}
656
darin@apple.com66d41182016-10-29 02:32:20 +0000657ExceptionOr<void> HTMLElement::setContentEditable(const String& enabled)
darinb9481ed2006-03-20 02:57:59 +0000658{
darin@apple.com048cc3a2016-01-22 17:17:04 +0000659 if (equalLettersIgnoringASCIICase(enabled, "true"))
cdumez@apple.com36059222016-07-15 21:35:40 +0000660 setAttributeWithoutSynchronization(contenteditableAttr, AtomicString("true", AtomicString::ConstructFromLiteral));
darin@apple.com048cc3a2016-01-22 17:17:04 +0000661 else if (equalLettersIgnoringASCIICase(enabled, "false"))
cdumez@apple.com36059222016-07-15 21:35:40 +0000662 setAttributeWithoutSynchronization(contenteditableAttr, AtomicString("false", AtomicString::ConstructFromLiteral));
darin@apple.com048cc3a2016-01-22 17:17:04 +0000663 else if (equalLettersIgnoringASCIICase(enabled, "plaintext-only"))
cdumez@apple.com36059222016-07-15 21:35:40 +0000664 setAttributeWithoutSynchronization(contenteditableAttr, AtomicString("plaintext-only", AtomicString::ConstructFromLiteral));
darin@apple.com048cc3a2016-01-22 17:17:04 +0000665 else if (equalLettersIgnoringASCIICase(enabled, "inherit"))
adamk@chromium.org05ffa332011-12-21 01:32:54 +0000666 removeAttribute(contenteditableAttr);
commit-queue@webkit.org290528b2012-08-22 01:42:43 +0000667 else
darin@apple.com66d41182016-10-29 02:32:20 +0000668 return Exception { SYNTAX_ERR };
669 return { };
darinb9481ed2006-03-20 02:57:59 +0000670}
671
darin@apple.com2fbab982009-07-14 01:04:19 +0000672bool HTMLElement::draggable() const
673{
rniwa@webkit.orge999a052016-07-16 15:21:55 +0000674 return equalLettersIgnoringASCIICase(attributeWithoutSynchronization(draggableAttr), "true");
darin@apple.com2fbab982009-07-14 01:04:19 +0000675}
676
677void HTMLElement::setDraggable(bool value)
678{
cdumez@apple.com36059222016-07-15 21:35:40 +0000679 setAttributeWithoutSynchronization(draggableAttr, value
darin@apple.comd8db0872013-10-11 15:07:12 +0000680 ? AtomicString("true", AtomicString::ConstructFromLiteral)
681 : AtomicString("false", AtomicString::ConstructFromLiteral));
darin@apple.com2fbab982009-07-14 01:04:19 +0000682}
683
morrita@google.comd165d1d2010-10-28 10:41:58 +0000684bool HTMLElement::spellcheck() const
685{
686 return isSpellCheckingEnabled();
687}
688
689void HTMLElement::setSpellcheck(bool enable)
690{
cdumez@apple.com36059222016-07-15 21:35:40 +0000691 setAttributeWithoutSynchronization(spellcheckAttr, enable
darin@apple.comd8db0872013-10-11 15:07:12 +0000692 ? AtomicString("true", AtomicString::ConstructFromLiteral)
693 : AtomicString("false", AtomicString::ConstructFromLiteral));
morrita@google.comd165d1d2010-10-28 10:41:58 +0000694}
695
darinf1bb0042006-12-01 22:46:21 +0000696void HTMLElement::click()
darinb9481ed2006-03-20 02:57:59 +0000697{
cdumez@apple.com16b46d72016-10-19 17:46:42 +0000698 simulateClick(*this, nullptr, SendNoEvents, DoNotShowPressedLook, SimulatedClickSource::Bindings);
darinb9481ed2006-03-20 02:57:59 +0000699}
700
commit-queue@webkit.org5bc308c2011-11-18 21:19:14 +0000701void HTMLElement::accessKeyAction(bool sendMouseEvents)
darinb9481ed2006-03-20 02:57:59 +0000702{
darin@apple.comd8db0872013-10-11 15:07:12 +0000703 dispatchSimulatedClick(nullptr, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
darinb9481ed2006-03-20 02:57:59 +0000704}
705
eseidel95944d22007-02-05 11:21:15 +0000706String HTMLElement::title() const
707{
rniwa@webkit.orge999a052016-07-16 15:21:55 +0000708 return attributeWithoutSynchronization(titleAttr);
eseidel95944d22007-02-05 11:21:15 +0000709}
710
cdumez@apple.com825cfbb2016-03-08 06:38:10 +0000711int HTMLElement::tabIndex() const
alice.liu@apple.com86484822008-04-29 01:18:52 +0000712{
713 if (supportsFocus())
714 return Element::tabIndex();
715 return -1;
716}
717
commit-queue@webkit.org22bfed62012-02-16 05:42:02 +0000718bool HTMLElement::translate() const
719{
weinig@apple.comc77041e2013-12-14 18:05:45 +0000720 for (auto& element : lineageOfType<HTMLElement>(*this)) {
darin@apple.com66d41182016-10-29 02:32:20 +0000721 const AtomicString& value = element.attributeWithoutSynchronization(translateAttr);
722 if (equalLettersIgnoringASCIICase(value, "yes") || (value.isEmpty() && !value.isNull()))
723 return true;
724 if (equalLettersIgnoringASCIICase(value, "no"))
725 return false;
commit-queue@webkit.org22bfed62012-02-16 05:42:02 +0000726 }
commit-queue@webkit.org22bfed62012-02-16 05:42:02 +0000727 // Default on the root element is translate=yes.
728 return true;
729}
730
731void HTMLElement::setTranslate(bool enable)
732{
cdumez@apple.com36059222016-07-15 21:35:40 +0000733 setAttributeWithoutSynchronization(translateAttr, enable ? "yes" : "no");
commit-queue@webkit.org22bfed62012-02-16 05:42:02 +0000734}
735
antti@apple.comb74dfb62013-08-20 21:22:53 +0000736bool HTMLElement::rendererIsNeeded(const RenderStyle& style)
anttiabbddd22007-09-19 09:45:13 +0000737{
darin@apple.com15708b12014-03-16 16:38:58 +0000738 if (hasTagName(noscriptTag)) {
akling@apple.com622b1a42013-08-30 14:30:12 +0000739 Frame* frame = document().frame();
psolanki@apple.comc5b5dad2013-08-16 17:55:32 +0000740 if (frame && frame->script().canExecuteScripts(NotAboutToExecuteScript))
anttiabbddd22007-09-19 09:45:13 +0000741 return false;
darin@apple.com15708b12014-03-16 16:38:58 +0000742 } else if (hasTagName(noembedTag)) {
akling@apple.com622b1a42013-08-30 14:30:12 +0000743 Frame* frame = document().frame();
andersca@apple.com0ea9a032015-08-04 21:41:02 +0000744 if (frame && frame->loader().subframeLoader().allowPlugins())
abarth@webkit.orgbb9d1af2010-08-07 01:56:07 +0000745 return false;
746 }
antti@apple.comb74dfb62013-08-20 21:22:53 +0000747 return StyledElement::rendererIsNeeded(style);
anttiabbddd22007-09-19 09:45:13 +0000748}
abarth@webkit.orgbb9d1af2010-08-07 01:56:07 +0000749
antti@apple.com454418f2016-04-25 19:49:23 +0000750RenderPtr<RenderElement> HTMLElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
darin55ae73e2007-05-11 15:47:28 +0000751{
aestes@apple.com13aae082016-01-02 08:03:08 +0000752 return RenderElement::createFor(*this, WTFMove(style));
darin55ae73e2007-05-11 15:47:28 +0000753}
754
darin9efc76e2007-05-29 17:41:17 +0000755HTMLFormElement* HTMLElement::virtualForm() const
756{
rniwa@webkit.orgf7bf3762013-08-29 01:35:21 +0000757 return HTMLFormElement::findClosestFormAncestor(*this);
darin9efc76e2007-05-29 17:41:17 +0000758}
759
weinig@apple.comc77041e2013-12-14 18:05:45 +0000760static inline bool elementAffectsDirectionality(const Node& node)
rniwa@webkit.org00fa4f32012-03-22 01:08:22 +0000761{
cdumez@apple.comcd131532014-09-27 01:32:34 +0000762 if (!is<HTMLElement>(node))
763 return false;
764 const HTMLElement& element = downcast<HTMLElement>(node);
rniwa@webkit.orgbda54a02016-07-18 00:39:37 +0000765 return is<HTMLBDIElement>(element) || element.hasAttributeWithoutSynchronization(dirAttr);
rniwa@webkit.org00fa4f32012-03-22 01:08:22 +0000766}
767
darin@apple.comd8db0872013-10-11 15:07:12 +0000768static void setHasDirAutoFlagRecursively(Node* firstNode, bool flag, Node* lastNode = nullptr)
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000769{
770 firstNode->setSelfOrAncestorHasDirAutoAttribute(flag);
771
772 Node* node = firstNode->firstChild();
773
774 while (node) {
775 if (node->selfOrAncestorHasDirAutoAttribute() == flag)
776 return;
777
weinig@apple.comc77041e2013-12-14 18:05:45 +0000778 if (elementAffectsDirectionality(*node)) {
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000779 if (node == lastNode)
780 return;
cdumez@apple.comb7f48502015-01-26 22:36:36 +0000781 node = NodeTraversal::nextSkippingChildren(*node, firstNode);
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000782 continue;
783 }
784 node->setSelfOrAncestorHasDirAutoAttribute(flag);
785 if (node == lastNode)
786 return;
cdumez@apple.comb7f48502015-01-26 22:36:36 +0000787 node = NodeTraversal::next(*node, firstNode);
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000788 }
789}
790
antti@apple.com1acee922013-09-02 15:17:50 +0000791void HTMLElement::childrenChanged(const ChildChange& change)
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000792{
antti@apple.com1acee922013-09-02 15:17:50 +0000793 StyledElement::childrenChanged(change);
794 adjustDirectionalityIfNeededAfterChildrenChanged(change.previousSiblingElement, change.type);
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000795}
796
rniwa@webkit.org00fa4f32012-03-22 01:08:22 +0000797bool HTMLElement::hasDirectionAuto() const
798{
rniwa@webkit.orge999a052016-07-16 15:21:55 +0000799 const AtomicString& direction = attributeWithoutSynchronization(dirAttr);
darin@apple.com048cc3a2016-01-22 17:17:04 +0000800 return (hasTagName(bdiTag) && direction.isNull()) || equalLettersIgnoringASCIICase(direction, "auto");
rniwa@webkit.org00fa4f32012-03-22 01:08:22 +0000801}
802
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000803TextDirection HTMLElement::directionalityIfhasDirAutoAttribute(bool& isAuto) const
804{
rniwa@webkit.org00fa4f32012-03-22 01:08:22 +0000805 if (!(selfOrAncestorHasDirAutoAttribute() && hasDirectionAuto())) {
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000806 isAuto = false;
807 return LTR;
808 }
809
810 isAuto = true;
811 return directionality();
812}
813
814TextDirection HTMLElement::directionality(Node** strongDirectionalityTextNode) const
815{
cdumez@apple.comcd131532014-09-27 01:32:34 +0000816 if (is<HTMLTextFormControlElement>(*this)) {
817 HTMLTextFormControlElement& textElement = downcast<HTMLTextFormControlElement>(const_cast<HTMLElement&>(*this));
yael.aharon@nokia.com0a5d0e52011-08-05 14:36:33 +0000818 bool hasStrongDirectionality;
cdumez@apple.com72754ba2014-09-23 22:03:15 +0000819 UCharDirection textDirection = textElement.value().defaultWritingDirection(&hasStrongDirectionality);
tkent@chromium.org400caab2011-10-22 10:53:41 +0000820 if (strongDirectionalityTextNode)
cdumez@apple.com72754ba2014-09-23 22:03:15 +0000821 *strongDirectionalityTextNode = hasStrongDirectionality ? &textElement : nullptr;
darin@apple.com2eb5f4d2013-10-12 04:16:42 +0000822 return (textDirection == U_LEFT_TO_RIGHT) ? LTR : RTL;
yael.aharon@nokia.com0a5d0e52011-08-05 14:36:33 +0000823 }
824
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000825 Node* node = firstChild();
826 while (node) {
yael.aharon@nokia.com0a5d0e52011-08-05 14:36:33 +0000827 // Skip bdi, script, style and text form controls.
darin@apple.com048cc3a2016-01-22 17:17:04 +0000828 if (equalLettersIgnoringASCIICase(node->nodeName(), "bdi") || node->hasTagName(scriptTag) || node->hasTagName(styleTag)
cdumez@apple.coma9c60c92014-10-02 19:39:41 +0000829 || (is<Element>(*node) && downcast<Element>(*node).isTextFormControl())) {
cdumez@apple.comb7f48502015-01-26 22:36:36 +0000830 node = NodeTraversal::nextSkippingChildren(*node, this);
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000831 continue;
832 }
833
834 // Skip elements with valid dir attribute
cdumez@apple.coma9c60c92014-10-02 19:39:41 +0000835 if (is<Element>(*node)) {
rniwa@webkit.orge999a052016-07-16 15:21:55 +0000836 AtomicString dirAttributeValue = downcast<Element>(*node).attributeWithoutSynchronization(dirAttr);
darin@apple.com048cc3a2016-01-22 17:17:04 +0000837 if (isLTROrRTLIgnoringCase(dirAttributeValue) || equalLettersIgnoringASCIICase(dirAttributeValue, "auto")) {
cdumez@apple.comb7f48502015-01-26 22:36:36 +0000838 node = NodeTraversal::nextSkippingChildren(*node, this);
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000839 continue;
840 }
841 }
842
843 if (node->isTextNode()) {
844 bool hasStrongDirectionality;
darin@apple.com2eb5f4d2013-10-12 04:16:42 +0000845 UCharDirection textDirection = node->textContent(true).defaultWritingDirection(&hasStrongDirectionality);
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000846 if (hasStrongDirectionality) {
847 if (strongDirectionalityTextNode)
848 *strongDirectionalityTextNode = node;
darin@apple.com2eb5f4d2013-10-12 04:16:42 +0000849 return (textDirection == U_LEFT_TO_RIGHT) ? LTR : RTL;
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000850 }
851 }
cdumez@apple.comb7f48502015-01-26 22:36:36 +0000852 node = NodeTraversal::next(*node, this);
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000853 }
854 if (strongDirectionalityTextNode)
darin@apple.comd8db0872013-10-11 15:07:12 +0000855 *strongDirectionalityTextNode = nullptr;
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000856 return LTR;
857}
858
akling@apple.com43e9d042012-11-18 16:55:06 +0000859void HTMLElement::dirAttributeChanged(const AtomicString& value)
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000860{
861 Element* parent = parentElement();
862
cdumez@apple.coma9c60c92014-10-02 19:39:41 +0000863 if (is<HTMLElement>(parent) && parent->selfOrAncestorHasDirAutoAttribute())
cdumez@apple.comcd131532014-09-27 01:32:34 +0000864 downcast<HTMLElement>(*parent).adjustDirectionalityIfNeededAfterChildAttributeChanged(this);
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000865
darin@apple.com048cc3a2016-01-22 17:17:04 +0000866 if (equalLettersIgnoringASCIICase(value, "auto"))
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000867 calculateAndAdjustDirectionality();
868}
869
870void HTMLElement::adjustDirectionalityIfNeededAfterChildAttributeChanged(Element* child)
871{
872 ASSERT(selfOrAncestorHasDirAutoAttribute());
873 Node* strongDirectionalityTextNode;
874 TextDirection textDirection = directionality(&strongDirectionalityTextNode);
875 setHasDirAutoFlagRecursively(child, false);
akling@apple.com827be9c2013-10-29 02:58:43 +0000876 if (!renderer() || renderer()->style().direction() == textDirection)
antti@apple.com08281fa2013-09-01 10:33:08 +0000877 return;
weinig@apple.comc77041e2013-12-14 18:05:45 +0000878 for (auto& elementToAdjust : elementLineage(this)) {
879 if (elementAffectsDirectionality(elementToAdjust)) {
antti@apple.com1c455832016-10-18 12:28:55 +0000880 elementToAdjust.invalidateStyleForSubtree();
antti@apple.com08281fa2013-09-01 10:33:08 +0000881 return;
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000882 }
883 }
884}
885
886void HTMLElement::calculateAndAdjustDirectionality()
887{
888 Node* strongDirectionalityTextNode;
889 TextDirection textDirection = directionality(&strongDirectionalityTextNode);
890 setHasDirAutoFlagRecursively(this, true, strongDirectionalityTextNode);
akling@apple.com827be9c2013-10-29 02:58:43 +0000891 if (renderer() && renderer()->style().direction() != textDirection)
antti@apple.com1c455832016-10-18 12:28:55 +0000892 invalidateStyleForSubtree();
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000893}
894
antti@apple.com1acee922013-09-02 15:17:50 +0000895void HTMLElement::adjustDirectionalityIfNeededAfterChildrenChanged(Element* beforeChange, ChildChangeType changeType)
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000896{
antti@apple.com1acee922013-09-02 15:17:50 +0000897 // FIXME: This function looks suspicious.
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000898
899 if (!selfOrAncestorHasDirAutoAttribute())
900 return;
901
darin@apple.comd8db0872013-10-11 15:07:12 +0000902 Node* oldMarkedNode = nullptr;
antti@apple.com1acee922013-09-02 15:17:50 +0000903 if (beforeChange)
cdumez@apple.comb7f48502015-01-26 22:36:36 +0000904 oldMarkedNode = changeType == ElementInserted ? ElementTraversal::nextSibling(*beforeChange) : beforeChange->nextSibling();
antti@apple.com1acee922013-09-02 15:17:50 +0000905
weinig@apple.comc77041e2013-12-14 18:05:45 +0000906 while (oldMarkedNode && elementAffectsDirectionality(*oldMarkedNode))
antti@apple.com1acee922013-09-02 15:17:50 +0000907 oldMarkedNode = oldMarkedNode->nextSibling();
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000908 if (oldMarkedNode)
909 setHasDirAutoFlagRecursively(oldMarkedNode, false);
910
weinig@apple.comc77041e2013-12-14 18:05:45 +0000911 for (auto& elementToAdjust : lineageOfType<HTMLElement>(*this)) {
912 if (elementAffectsDirectionality(elementToAdjust)) {
913 elementToAdjust.calculateAndAdjustDirectionality();
yael.aharon@nokia.comc542de52011-02-18 21:28:32 +0000914 return;
915 }
916 }
917}
918
antti@apple.come5428c52013-11-28 20:53:22 +0000919void HTMLElement::addHTMLLengthToStyle(MutableStyleProperties& style, CSSPropertyID propertyID, const String& value)
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000920{
921 // FIXME: This function should not spin up the CSS parser, but should instead just figure out the correct
922 // length unit and make the appropriate parsed value.
923
darin@apple.comd8db0872013-10-11 15:07:12 +0000924 if (StringImpl* string = value.impl()) {
925 unsigned parsedLength = 0;
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000926
darin@apple.comd8db0872013-10-11 15:07:12 +0000927 while (parsedLength < string->length() && (*string)[parsedLength] <= ' ')
928 ++parsedLength;
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000929
darin@apple.comd8db0872013-10-11 15:07:12 +0000930 for (; parsedLength < string->length(); ++parsedLength) {
931 UChar cc = (*string)[parsedLength];
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000932 if (cc > '9')
933 break;
934 if (cc < '0') {
935 if (cc == '%' || cc == '*')
darin@apple.comd8db0872013-10-11 15:07:12 +0000936 ++parsedLength;
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000937 if (cc != '.')
938 break;
939 }
940 }
941
darin@apple.comd8db0872013-10-11 15:07:12 +0000942 if (parsedLength != string->length()) {
943 addPropertyToPresentationAttributeStyle(style, propertyID, string->substring(0, parsedLength));
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000944 return;
945 }
946 }
947
kling@webkit.org569556d2012-11-12 23:52:12 +0000948 addPropertyToPresentationAttributeStyle(style, propertyID, value);
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000949}
950
kling@webkit.orgc92997c2012-02-23 01:40:12 +0000951static RGBA32 parseColorStringWithCrazyLegacyRules(const String& colorString)
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000952{
953 // Per spec, only look at the first 128 digits of the string.
954 const size_t maxColorLength = 128;
955 // We'll pad the buffer with two extra 0s later, so reserve two more than the max.
956 Vector<char, maxColorLength+2> digitBuffer;
957
958 size_t i = 0;
959 // Skip a leading #.
960 if (colorString[0] == '#')
961 i = 1;
962
963 // Grab the first 128 characters, replacing non-hex characters with 0.
964 // Non-BMP characters are replaced with "00" due to them appearing as two "characters" in the String.
965 for (; i < colorString.length() && digitBuffer.size() < maxColorLength; i++) {
966 if (!isASCIIHexDigit(colorString[i]))
967 digitBuffer.append('0');
968 else
969 digitBuffer.append(colorString[i]);
970 }
971
972 if (!digitBuffer.size())
kling@webkit.orgc92997c2012-02-23 01:40:12 +0000973 return Color::black;
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000974
975 // Pad the buffer out to at least the next multiple of three in size.
976 digitBuffer.append('0');
977 digitBuffer.append('0');
978
979 if (digitBuffer.size() < 6)
kling@webkit.orgc92997c2012-02-23 01:40:12 +0000980 return makeRGB(toASCIIHexValue(digitBuffer[0]), toASCIIHexValue(digitBuffer[1]), toASCIIHexValue(digitBuffer[2]));
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000981
982 // Split the digits into three components, then search the last 8 digits of each component.
983 ASSERT(digitBuffer.size() >= 6);
984 size_t componentLength = digitBuffer.size() / 3;
andersca@apple.comff9adb82013-10-25 01:15:36 +0000985 size_t componentSearchWindowLength = std::min<size_t>(componentLength, 8);
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000986 size_t redIndex = componentLength - componentSearchWindowLength;
987 size_t greenIndex = componentLength * 2 - componentSearchWindowLength;
988 size_t blueIndex = componentLength * 3 - componentSearchWindowLength;
989 // Skip digits until one of them is non-zero, or we've only got two digits left in the component.
990 while (digitBuffer[redIndex] == '0' && digitBuffer[greenIndex] == '0' && digitBuffer[blueIndex] == '0' && (componentLength - redIndex) > 2) {
991 redIndex++;
992 greenIndex++;
993 blueIndex++;
994 }
995 ASSERT(redIndex + 1 < componentLength);
996 ASSERT(greenIndex >= componentLength);
997 ASSERT(greenIndex + 1 < componentLength * 2);
998 ASSERT(blueIndex >= componentLength * 2);
inferno@chromium.orga227be62013-02-11 08:06:45 +0000999 ASSERT_WITH_SECURITY_IMPLICATION(blueIndex + 1 < digitBuffer.size());
kling@webkit.orgc92997c2012-02-23 01:40:12 +00001000
1001 int redValue = toASCIIHexValue(digitBuffer[redIndex], digitBuffer[redIndex + 1]);
1002 int greenValue = toASCIIHexValue(digitBuffer[greenIndex], digitBuffer[greenIndex + 1]);
1003 int blueValue = toASCIIHexValue(digitBuffer[blueIndex], digitBuffer[blueIndex + 1]);
1004 return makeRGB(redValue, greenValue, blueValue);
kling@webkit.org8b0e8432012-02-11 19:29:49 +00001005}
1006
1007// Color parsing that matches HTML's "rules for parsing a legacy color value"
antti@apple.come5428c52013-11-28 20:53:22 +00001008void HTMLElement::addHTMLColorToStyle(MutableStyleProperties& style, CSSPropertyID propertyID, const String& attributeValue)
kling@webkit.org8b0e8432012-02-11 19:29:49 +00001009{
1010 // An empty string doesn't apply a color. (One containing only whitespace does, which is why this check occurs before stripping.)
1011 if (attributeValue.isEmpty())
1012 return;
1013
1014 String colorString = attributeValue.stripWhiteSpace();
1015
1016 // "transparent" doesn't apply a color either.
darin@apple.com048cc3a2016-01-22 17:17:04 +00001017 if (equalLettersIgnoringASCIICase(colorString, "transparent"))
kling@webkit.org8b0e8432012-02-11 19:29:49 +00001018 return;
1019
dino@apple.com2e87e372016-05-06 01:26:26 +00001020 Color color;
dino@apple.com54017652016-10-18 00:12:00 +00001021 // We can't always use the default Color constructor because it accepts
1022 // 4/8-digit hex, which conflict with some legacy HTML content using attributes.
1023 if ((colorString.length() != 5 && colorString.length() != 9) || colorString[0] != '#')
dino@apple.com2e87e372016-05-06 01:26:26 +00001024 color = Color(colorString);
1025 if (!color.isValid())
dino@apple.com54017652016-10-18 00:12:00 +00001026 color = Color(parseColorStringWithCrazyLegacyRules(colorString));
dino@apple.com2e87e372016-05-06 01:26:26 +00001027
1028 style.setProperty(propertyID, CSSValuePool::singleton().createColorValue(color.rgb()));
kling@webkit.org8b0e8432012-02-11 19:29:49 +00001029}
1030
dbates@webkit.org1edd81d2013-12-18 00:15:02 +00001031bool HTMLElement::willRespondToMouseMoveEvents()
1032{
1033 return !isDisabledFormControl() && Element::willRespondToMouseMoveEvents();
1034}
1035
1036bool HTMLElement::willRespondToMouseWheelEvents()
1037{
1038 return !isDisabledFormControl() && Element::willRespondToMouseWheelEvents();
1039}
1040
1041bool HTMLElement::willRespondToMouseClickEvents()
1042{
1043 return !isDisabledFormControl() && Element::willRespondToMouseClickEvents();
1044}
1045
akling@apple.com4d48f412016-08-26 21:46:07 +00001046bool HTMLElement::canBeActuallyDisabled() const
1047{
1048 return is<HTMLButtonElement>(*this)
1049 || is<HTMLInputElement>(*this)
1050 || is<HTMLSelectElement>(*this)
1051 || is<HTMLTextAreaElement>(*this)
1052 || is<HTMLOptGroupElement>(*this)
1053 || is<HTMLOptionElement>(*this)
1054 || is<HTMLFieldSetElement>(*this);
1055}
1056
1057bool HTMLElement::isActuallyDisabled() const
1058{
1059 return canBeActuallyDisabled() && isDisabledFormControl();
1060}
1061
wenson_hsieh@apple.coma8fbaa42016-11-12 00:20:00 +00001062#if ENABLE(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
1063
1064const AtomicString& HTMLElement::autocapitalize() const
1065{
1066 return stringForAutocapitalizeType(autocapitalizeType());
1067}
1068
1069AutocapitalizeType HTMLElement::autocapitalizeType() const
1070{
1071 return autocapitalizeTypeForAttributeValue(attributeWithoutSynchronization(HTMLNames::autocapitalizeAttr));
1072}
1073
1074void HTMLElement::setAutocapitalize(const AtomicString& value)
1075{
1076 setAttributeWithoutSynchronization(autocapitalizeAttr, value);
1077}
1078
1079bool HTMLElement::shouldAutocorrect() const
1080{
1081 auto autocorrectValue = attributeWithoutSynchronization(HTMLNames::autocorrectAttr);
1082 // Unrecognized values fall back to "on".
1083 return !equalLettersIgnoringASCIICase(autocorrectValue, "off");
1084}
1085
1086void HTMLElement::setAutocorrect(bool autocorrect)
1087{
1088 setAttributeWithoutSynchronization(autocorrectAttr, autocorrect ? AtomicString("on", AtomicString::ConstructFromLiteral) : AtomicString("off", AtomicString::ConstructFromLiteral));
1089}
1090
1091#endif
1092
weinig3975ff62007-05-28 19:38:29 +00001093} // namespace WebCore
ggaren007c6562007-06-21 02:46:18 +00001094
1095#ifndef NDEBUG
andersca@apple.com3c1e6d92009-01-23 20:50:59 +00001096
1097// For use in the debugger
andersca@apple.comd8dda092009-01-23 19:52:19 +00001098void dumpInnerHTML(WebCore::HTMLElement*);
1099
ggaren007c6562007-06-21 02:46:18 +00001100void dumpInnerHTML(WebCore::HTMLElement* element)
1101{
1102 printf("%s\n", element->innerHTML().ascii().data());
1103}
darin@apple.comd8db0872013-10-11 15:07:12 +00001104
ggaren007c6562007-06-21 02:46:18 +00001105#endif