1 /*
2 * Copyright (c) 2002-2025 Gargoyle Software Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit;
16
17 import static org.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
18 import static org.htmlunit.javascript.configuration.SupportedBrowser.EDGE;
19 import static org.htmlunit.javascript.configuration.SupportedBrowser.FF;
20 import static org.htmlunit.javascript.configuration.SupportedBrowser.FF_ESR;
21
22 import org.htmlunit.javascript.configuration.BrowserFeature;
23
24 /**
25 * Constants of various features of each {@link BrowserVersion}.
26 *
27 * @author Ahmed Ashour
28 * @author Marc Guillemot
29 * @author Sudhan Moghe
30 * @author Ronald Brill
31 * @author Frank Danek
32 * @author Carsten Steul
33 * @author Anton Demydenko
34 */
35 public enum BrowserVersionFeatures {
36
37 /** Ignore target when {@code href} is a javascript snippet. */
38 @BrowserFeature({CHROME, EDGE})
39 ANCHOR_SEND_PING_REQUEST,
40
41 /** Background image is 'initial'. */
42 @BrowserFeature({CHROME, EDGE})
43 CSS_BACKGROUND_INITIAL,
44
45 /** Background image is 'rgba(0, 0, 0, 0)'. */
46 @BrowserFeature({FF, FF_ESR})
47 CSS_BACKGROUND_RGBA,
48
49 /** Is display style 'block'. */
50 @BrowserFeature({FF, FF_ESR})
51 CSS_DISPLAY_BLOCK,
52
53 /** The default value of the display property for the 'noscript' tag is 'inline' instead of the default one. */
54 @BrowserFeature({CHROME, EDGE})
55 CSS_NOSCRIPT_DISPLAY_INLINE,
56
57 /** The default value of the display property for the 'rp' tag is 'none'. */
58 @BrowserFeature({FF, FF_ESR})
59 CSS_RP_DISPLAY_NONE,
60
61 /** The default value of the display property for the 'rt' tag is always 'ruby-text'. */
62 @BrowserFeature({FF, FF_ESR})
63 CSS_RT_DISPLAY_RUBY_TEXT_ALWAYS,
64
65 /** The context menu MouseEvent has a detail of 1. */
66 @BrowserFeature({FF, FF_ESR})
67 EVENT_CONTEXT_MENU_HAS_DETAIL_1,
68
69 /** Triggers the onfocus event when focusing the body on load. */
70 @BrowserFeature({FF, FF_ESR})
71 EVENT_FOCUS_ON_LOAD,
72
73 /** <code>AnimationEvent</code> can not be created by calling document.createEvent('AnimationEvent'). */
74 @BrowserFeature({FF, FF_ESR})
75 EVENT_ONANIMATION_DOCUMENT_CREATE_NOT_SUPPORTED,
76
77 /** <code>CloseEvent</code> can not be created by calling document.createEvent('CloseEvent'). */
78 @BrowserFeature({FF, FF_ESR})
79 EVENT_ONCLOSE_DOCUMENT_CREATE_NOT_SUPPORTED,
80
81 /** <code>PopStateEvent</code> can not be created by calling document.createEvent('PopStateEvent'). */
82 @BrowserFeature({FF, FF_ESR})
83 EVENT_ONPOPSTATE_DOCUMENT_CREATE_NOT_SUPPORTED,
84
85 /** Scroll events are of type 'UIEvent'. */
86 @BrowserFeature({FF, FF_ESR})
87 EVENT_SCROLL_UIEVENT,
88
89 /** Supports event type 'MutationEvent'. */
90 @BrowserFeature(FF_ESR)
91 EVENT_TYPE_MUTATIONEVENT,
92
93 /** Supports event type 'WheelEvent'. */
94 @BrowserFeature({CHROME, EDGE})
95 EVENT_TYPE_WHEELEVENT,
96
97 /** Form elements are able to refer to the for by using the form attribute. */
98 @BrowserFeature({CHROME, EDGE})
99 FORM_IGNORE_REL_NOREFERRER,
100
101 /** Form submit includes the Cache-Control: max-age=0 header. */
102 @BrowserFeature({CHROME, EDGE})
103 FORM_SUBMISSION_HEADER_CACHE_CONTROL_MAX_AGE,
104
105 /** Should org.htmlunit.javascript.host.html.HTMLBaseFontElement#isEndTagForbidden(). */
106 @BrowserFeature({FF, FF_ESR})
107 HTMLBASEFONT_END_TAG_FORBIDDEN,
108
109 /** willValidate does not check the readonly property. */
110 @BrowserFeature({FF, FF_ESR})
111 HTMLBUTTON_WILL_VALIDATE_IGNORES_READONLY,
112
113 /** HtmlCollection.namedItem searches by id first. */
114 @BrowserFeature({CHROME, EDGE})
115 HTMLCOLLECTION_NAMED_ITEM_ID_FIRST,
116
117 /**
118 /** {@code document.getElementsByName} returns an empty list if called with the empty string.
119 */
120 @BrowserFeature({FF, FF_ESR})
121 HTMLDOCUMENT_ELEMENTS_BY_NAME_EMPTY,
122
123 /** Removing the active element from the dom tree triggers the onblur event. */
124 @BrowserFeature({CHROME, EDGE})
125 HTMLELEMENT_REMOVE_ACTIVE_TRIGGERS_BLUR_EVENT,
126
127 /** Handle blank source like empty. */
128 @BrowserFeature({CHROME, EDGE})
129 HTMLIMAGE_BLANK_SRC_AS_EMPTY,
130
131 /** Empty src attribute sets display to false. */
132 @BrowserFeature({FF, FF_ESR})
133 HTMLIMAGE_EMPTY_SRC_DISPLAY_FALSE,
134
135 /** Is document.cretaeElement('image') an HTMLElement. */
136 @BrowserFeature({FF, FF_ESR})
137 HTMLIMAGE_HTMLELEMENT,
138
139 /** Is document.cretaeElement('image') an HTMLUnknownElement. */
140 @BrowserFeature({CHROME, EDGE})
141 HTMLIMAGE_HTMLUNKNOWNELEMENT,
142
143 /** HTMLInputElement image type is not supported. */
144 @BrowserFeature({CHROME, EDGE})
145 HTMLINPUT_TYPE_IMAGE_IGNORES_CUSTOM_VALIDITY,
146
147 /** HTMLInputElement month type is supported. */
148 @BrowserFeature({CHROME, EDGE})
149 HTMLINPUT_TYPE_MONTH_SUPPORTED,
150
151 /** HTMLInputElement week type is supported. */
152 @BrowserFeature({CHROME, EDGE})
153 HTMLINPUT_TYPE_WEEK_SUPPORTED,
154
155 /** For a stylesheet link report an error if the response type is not text/css. */
156 @BrowserFeature({FF, FF_ESR})
157 HTMLLINK_CHECK_RESPONSE_TYPE_FOR_STYLESHEET,
158
159 /** If the type is present for a link only use if type is text/css. */
160 @BrowserFeature({CHROME, EDGE})
161 HTMLLINK_CHECK_TYPE_FOR_STYLESHEET,
162
163 /** willValidate does not check the readonly property. */
164 @BrowserFeature({FF, FF_ESR})
165 HTMLSELECT_WILL_VALIDATE_IGNORES_READONLY,
166
167 /** Should org.htmlunit.javascript.host.html.HTMLTrackElement#isEndTagForbidden(). */
168 @BrowserFeature({FF, FF_ESR})
169 HTMLTRACK_END_TAG_FORBIDDEN,
170
171 /** HTML parser supports the 'command' tag. */
172 @BrowserFeature({CHROME, EDGE})
173 HTML_COMMAND_TAG,
174
175 /** HTML parser supports the 'layer' tag. */
176 @BrowserFeature({CHROME, EDGE})
177 HTML_LAYER_TAG,
178
179 /** Additionally support dates in format "d/M/yyyy". */
180 @BrowserFeature({FF, FF_ESR})
181 HTTP_COOKIE_EXTENDED_DATE_PATTERNS_1,
182
183 /** Dates format pattern 2. */
184 @BrowserFeature({CHROME, EDGE})
185 HTTP_COOKIE_EXTENDED_DATE_PATTERNS_2,
186
187 /** domain '.org' is handled as 'org'. */
188 @BrowserFeature({FF, FF_ESR})
189 HTTP_COOKIE_REMOVE_DOT_FROM_ROOT_DOMAINS,
190
191 /** Browser sends Sec-ch headers. */
192 @BrowserFeature({CHROME, EDGE})
193 HTTP_HEADER_CH_UA,
194
195 /** Browser sends Priority headers. */
196 @BrowserFeature({FF, FF_ESR})
197 HTTP_HEADER_PRIORITY,
198
199 /** The anchor hostname setter ignores blank url's. */
200 @BrowserFeature({FF, FF_ESR})
201 JS_ANCHOR_HOSTNAME_IGNORE_BLANK,
202
203 /**
204 * The anchor pathname detects url's starting with one letter as file url's
205 * and replaces them with the file protocol. */
206 @BrowserFeature({CHROME, EDGE})
207 JS_ANCHOR_PATHNAME_DETECT_WIN_DRIVES_URL_REPLACE,
208
209 /** The anchor pathname prefixes file url's with '/'. */
210 @BrowserFeature({CHROME, EDGE})
211 JS_ANCHOR_PATHNAME_PREFIX_WIN_DRIVES_URL,
212
213 /** The anchor protocol property converts drive letters to uppercase. */
214 @BrowserFeature({CHROME, EDGE})
215 JS_ANCHOR_PROTOCOL_COLON_UPPER_CASE_DRIVE_LETTERS,
216
217 /** An area element without a href attribute is focusable. */
218 @BrowserFeature({FF, FF_ESR})
219 JS_AREA_WITHOUT_HREF_FOCUSABLE,
220
221 /** Sorting an array using a user defined comperator accepts inconsistent iterators. */
222 @BrowserFeature({FF, FF_ESR})
223 JS_ARRAY_SORT_ACCEPTS_INCONSISTENT_COMPERATOR,
224
225 /** AudioProcessingEvent ctor is callable. */
226 @BrowserFeature({CHROME, EDGE})
227 JS_AUDIO_PROCESSING_EVENT_CTOR,
228
229 /** toDataURL for canvas returns the CHROME version of the PNG. */
230 @BrowserFeature({CHROME, EDGE})
231 JS_CANVAS_DATA_URL_CHROME_PNG,
232
233 /** ClientHeight for input is 17. */
234 @BrowserFeature({CHROME, EDGE})
235 JS_CLIENTHEIGHT_INPUT_17,
236
237 /** ClientHeight for input is 18. */
238 @BrowserFeature({FF, FF_ESR})
239 JS_CLIENTHEIGHT_INPUT_18,
240
241 /** ClientHeight for radio button and checkbox is 14. */
242 @BrowserFeature({FF, FF_ESR})
243 JS_CLIENTHEIGHT_RADIO_CHECKBOX_14,
244
245 /** ClientHeight for rb is 17. */
246 @BrowserFeature({FF, FF_ESR})
247 JS_CLIENTHEIGHT_RB_17,
248
249 /** ClientHeight for rt is 9. */
250 @BrowserFeature({FF, FF_ESR})
251 JS_CLIENTHEIGHT_RT_9,
252
253 /** ClientHeight for ruby is 17. */
254 @BrowserFeature({FF, FF_ESR})
255 JS_CLIENTHEIGHT_RUBY_17,
256
257 /** ClientWidth for text/password input is 173. */
258 @BrowserFeature({CHROME, EDGE})
259 JS_CLIENTWIDTH_INPUT_TEXT_173,
260
261 /** ClientWidth for radio button and checkbox is 14. */
262 @BrowserFeature({FF, FF_ESR})
263 JS_CLIENTWIDTH_RADIO_CHECKBOX_14,
264
265 /** item is enumerated before length property of CSSRuleList. */
266 @BrowserFeature({FF, FF_ESR})
267 JS_CSSRULELIST_ENUM_ITEM_LENGTH,
268
269 /** Javascript document.evaluate() creates a new result object even if provided as param. */
270 @BrowserFeature({CHROME, EDGE})
271 JS_DOCUMENT_EVALUATE_RECREATES_RESULT,
272
273 /** The browser has selection {@code rangeCount}. */
274 @BrowserFeature({FF, FF_ESR})
275 JS_DOCUMENT_SELECTION_RANGE_COUNT,
276
277 /** Javascript {@code Error.stackTraceLimit}. */
278 @BrowserFeature({CHROME, EDGE})
279 JS_ERROR_STACK_TRACE_LIMIT,
280
281 /** Javascript InputEvent reads the inputType property from data. */
282 @BrowserFeature({FF, FF_ESR})
283 JS_EVENT_INPUT_CTOR_INPUTTYPE,
284
285 /** Javascript KeyboardEvent reads the which property from data. */
286 @BrowserFeature({FF, FF_ESR})
287 JS_EVENT_KEYBOARD_CTOR_WHICH,
288
289 /** form.dispatchEvent(e) submits the form if the event is of type 'submit'. */
290 @BrowserFeature({FF, FF_ESR})
291 JS_FORM_DISPATCHEVENT_SUBMITS,
292
293 /** Executes the {@code onload} handler, regardless of the element was already attached to the page. */
294 @BrowserFeature({FF, FF_ESR})
295 JS_IFRAME_ALWAYS_EXECUTE_ONLOAD,
296
297 /**
298 * Getting the width and height of an image tag without a source returns 16x16;
299 * for invalid values returns 0.
300 */
301 @BrowserFeature({CHROME, EDGE})
302 JS_IMAGE_WIDTH_HEIGHT_RETURNS_16x16_0x0,
303
304 /**
305 * Getting the width and height of an image tag without a source returns 24x24;
306 * for invalid values returns 0x0.
307 */
308 @BrowserFeature({FF, FF_ESR})
309 JS_IMAGE_WIDTH_HEIGHT_RETURNS_24x24_0x0,
310
311 /** Indicates that innerText add a nl when reaching svg element. */
312 @BrowserFeature({CHROME, EDGE})
313 JS_INNER_TEXT_SVG_NL,
314
315 /** The value is ignored when the type of the week/month input is changed. */
316 @BrowserFeature({CHROME, EDGE})
317 JS_INPUT_CHANGE_TYPE_DROPS_VALUE_WEEK_MONTH,
318
319 /** FF accepts all chars. */
320 @BrowserFeature({FF, FF_ESR})
321 JS_INPUT_NUMBER_ACCEPT_ALL,
322
323 /** FF comma at end is not an integer. */
324 @BrowserFeature({FF, FF_ESR})
325 JS_INPUT_NUMBER_DOT_AT_END_IS_DOUBLE,
326
327 /** Indicates that Intl.v8BreakIterator is supported. */
328 @BrowserFeature({CHROME, EDGE})
329 JS_INTL_V8_BREAK_ITERATOR,
330
331 /** For the 'about' protocol the location always returns an empty query. */
332 @BrowserFeature({FF, FF_ESR})
333 JS_LOCATION_IGNORE_QUERY_FOR_ABOUT_PROTOCOL,
334
335 /** Reload sends a referrer header. */
336 @BrowserFeature({CHROME, EDGE})
337 JS_LOCATION_RELOAD_REFERRER,
338
339 /** Type property of menu returns the current (maybe invalid) value. */
340 @BrowserFeature({FF, FF_ESR})
341 JS_MENU_TYPE_PASS,
342
343 /** Indicates if the String representation of a native function is without newline. */
344 @BrowserFeature({CHROME, EDGE})
345 JS_NATIVE_FUNCTION_TOSTRING_COMPACT,
346
347 /** Indicates if the String representation of a native function has a newline for empty parameter list. */
348 @BrowserFeature({FF, FF_ESR})
349 JS_NATIVE_FUNCTION_TOSTRING_NL,
350
351 /** Navigator.doNotTrack returns unspecified if not set. */
352 @BrowserFeature({FF, FF_ESR})
353 JS_NAVIGATOR_DO_NOT_TRACK_UNSPECIFIED,
354
355 /** Indicates that someObj.offsetParent returns null, it someObj has fixed style. */
356 @BrowserFeature({CHROME, EDGE, FF})
357 JS_OFFSET_PARENT_NULL_IF_FIXED,
358
359 /** element.outerHTML removes all children from detached node. */
360 @BrowserFeature({CHROME, EDGE})
361 JS_OUTER_HTML_THROWS_FOR_DETACHED,
362
363 /** Indicates that the {@code Object.getOwnPropertyDescriptor.get} contains name. */
364 @BrowserFeature({FF, FF_ESR})
365 JS_PROPERTY_DESCRIPTOR_NAME,
366
367 /** script tags created from js as child of templates is processed if added to the dom. */
368 @BrowserFeature({CHROME, EDGE})
369 JS_SCRIPT_IN_TEMPLATE_EXECUTED_ON_ATTACH,
370
371 /** Javascript selectorText property returns selectors in lower case. */
372 @BrowserFeature({CHROME, EDGE})
373 JS_SELECTOR_TEXT_LOWERCASE,
374
375 /** Indicates that select.options.remove ignores the call if index is too large. */
376 @BrowserFeature({FF, FF_ESR})
377 JS_SELECT_REMOVE_IGNORE_IF_INDEX_OUTSIDE,
378
379 /** Whether to add to the storage even preserved words. */
380 @BrowserFeature({FF, FF_ESR})
381 JS_STORAGE_PRESERVED_INCLUDED,
382
383 /** Indicates letterSpacing support percent values. */
384 @BrowserFeature({FF, FF_ESR})
385 JS_STYLE_LETTER_SPACING_ACCEPTS_PERCENT,
386
387 /** Indicates wordSpacing support percent values. */
388 @BrowserFeature({FF, FF_ESR})
389 JS_STYLE_WORD_SPACING_ACCEPTS_PERCENT,
390
391 /** window.getComputedStyle works with pseudo selectors without colon in front. */
392 @BrowserFeature({CHROME, EDGE})
393 JS_WINDOW_COMPUTED_STYLE_PSEUDO_ACCEPT_WITHOUT_COLON,
394
395 /** Javascript InstallTrigger property set to null. */
396 @BrowserFeature({FF, FF_ESR})
397 JS_WINDOW_INSTALL_TRIGGER_NULL,
398
399 /**
400 * Difference of window.outer/inner height is 138.
401 */
402 @BrowserFeature(EDGE)
403 JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_138,
404
405 /**
406 * Difference of window.outer/inner height is 147.
407 */
408 @BrowserFeature(CHROME)
409 JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_147,
410
411 /**
412 * Difference of window.outer/inner height is 94.
413 */
414 @BrowserFeature({FF, FF_ESR})
415 JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_94,
416
417 /** Window.getSelection returns null, if the window is not visible. */
418 @BrowserFeature({FF, FF_ESR})
419 JS_WINDOW_SELECTION_NULL_IF_INVISIBLE,
420
421 /** {@code XSLTProcessor.transformToDocument} supports output indent attribute. */
422 @BrowserFeature({CHROME, EDGE})
423 JS_XSLT_TRANSFORM_INDENT,
424
425 /** With special keys [in .type(int)], should we trigger onkeypress event or not. */
426 @BrowserFeature({FF, FF_ESR})
427 KEYBOARD_EVENT_SPECIAL_KEYPRESS,
428
429 /**
430 * Indicates that the Browser handles async and sync network errors the same way.
431 */
432 @BrowserFeature({FF, FF_ESR})
433 XHR_HANDLE_SYNC_NETWORK_ERRORS,
434
435 /** XMLHttpRequest triggers the load events also if the abort was signaled. */
436 @BrowserFeature({FF, FF_ESR})
437 XHR_LOAD_ALWAYS_AFTER_DONE,
438
439 /** If state unsent the response text is empty even if the response type is wrong. */
440 @BrowserFeature({FF, FF_ESR})
441 XHR_RESPONSE_TEXT_EMPTY_UNSENT,
442
443 /** Indicates if the XMLHttpRequest.send() method will throw if aborted. */
444 @BrowserFeature({CHROME, EDGE})
445 XHR_SEND_NETWORK_ERROR_IF_ABORTED,
446 }