View Javadoc
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      /** {@code CSSFontFaceRule.cssText} uses one more blank. */
50      @BrowserFeature(FF_ESR)
51      CSS_CSSTEXT_FF_STYLE,
52  
53      /** Is display style 'block'. */
54      @BrowserFeature({FF, FF_ESR})
55      CSS_DISPLAY_BLOCK,
56  
57      /** The default value of the display property for the 'noscript' tag is 'inline' instead of the default one. */
58      @BrowserFeature({CHROME, EDGE})
59      CSS_NOSCRIPT_DISPLAY_INLINE,
60  
61      /** The default value of the display property for the 'rp' tag is 'none'. */
62      @BrowserFeature({FF, FF_ESR})
63      CSS_RP_DISPLAY_NONE,
64  
65      /** The default value of the display property for the 'rt' tag is always 'ruby-text'. */
66      @BrowserFeature({FF, FF_ESR})
67      CSS_RT_DISPLAY_RUBY_TEXT_ALWAYS,
68  
69      /** The context menu MouseEvent has a detail of 1. */
70      @BrowserFeature(FF)
71      EVENT_CONTEXT_MENU_HAS_DETAIL_1,
72  
73      /** Triggers the onfocus event when focusing the body on load. */
74      @BrowserFeature({FF, FF_ESR})
75      EVENT_FOCUS_ON_LOAD,
76  
77      /** <code>AnimationEvent</code> can not be created by calling document.createEvent('AnimationEvent'). */
78      @BrowserFeature({FF, FF_ESR})
79      EVENT_ONANIMATION_DOCUMENT_CREATE_NOT_SUPPORTED,
80  
81      /** Triggers 'onclick' event handler using <code>PointerEvent</code>. */
82      @BrowserFeature({CHROME, EDGE, FF})
83      EVENT_ONCLICK_USES_POINTEREVENT,
84  
85      /** <code>CloseEvent</code> can not be created by calling document.createEvent('CloseEvent'). */
86      @BrowserFeature({FF, FF_ESR})
87      EVENT_ONCLOSE_DOCUMENT_CREATE_NOT_SUPPORTED,
88  
89      /** <code>PopStateEvent</code> can not be created by calling document.createEvent('PopStateEvent'). */
90      @BrowserFeature({FF, FF_ESR})
91      EVENT_ONPOPSTATE_DOCUMENT_CREATE_NOT_SUPPORTED,
92  
93      /** Scroll events are of type 'UIEvent'. */
94      @BrowserFeature({FF, FF_ESR})
95      EVENT_SCROLL_UIEVENT,
96  
97      /** Supports event type 'TextEvent'. */
98      @BrowserFeature({FF, FF_ESR})
99      EVENT_TYPE_MUTATIONEVENT,
100 
101     /** Supports event type 'TextEvent'. */
102     @BrowserFeature({CHROME, EDGE, FF})
103     EVENT_TYPE_TEXTEVENT,
104 
105     /** Supports event type 'WheelEvent'. */
106     @BrowserFeature({CHROME, EDGE})
107     EVENT_TYPE_WHEELEVENT,
108 
109     /** Form elements are able to refer to the for by using the from attribute. */
110     @BrowserFeature({CHROME, EDGE})
111     FORM_IGNORE_REL_NOREFERRER,
112 
113     /** Form submit includes the Cache-Control: max-age=0 header. */
114     @BrowserFeature({CHROME, EDGE})
115     FORM_SUBMISSION_HEADER_CACHE_CONTROL_MAX_AGE,
116 
117     /** Should org.htmlunit.javascript.host.html.HTMLBaseFontElement#isEndTagForbidden(). */
118     @BrowserFeature({FF, FF_ESR})
119     HTMLBASEFONT_END_TAG_FORBIDDEN,
120 
121     /** willValidate does not check the readonly property. */
122     @BrowserFeature({FF, FF_ESR})
123     HTMLBUTTON_WILL_VALIDATE_IGNORES_READONLY,
124 
125     /** HtmlCollection.namedItem searches by id first. */
126     @BrowserFeature({CHROME, EDGE})
127     HTMLCOLLECTION_NAMED_ITEM_ID_FIRST,
128 
129     /** Calling cookies setter with blank string does not reset the cookies. */
130     @BrowserFeature({CHROME, EDGE, FF})
131     HTMLDOCUMENT_COOKIES_IGNORE_BLANK,
132 
133     /**
134     /** {@code document.getElementsByName} returns an empty list if called with the empty string.
135      */
136     @BrowserFeature({FF, FF_ESR})
137     HTMLDOCUMENT_ELEMENTS_BY_NAME_EMPTY,
138 
139     /** Calls to <code>document.XYZ</code> also looks at frames. */
140     @BrowserFeature({CHROME, EDGE})
141     HTMLDOCUMENT_GET_ALSO_FRAMES,
142 
143     /** Removing the active element from the dom tree triggers the onblur event. */
144     @BrowserFeature({CHROME, EDGE})
145     HTMLELEMENT_REMOVE_ACTIVE_TRIGGERS_BLUR_EVENT,
146 
147     /** Handle blank source like empty. */
148     @BrowserFeature({CHROME, EDGE})
149     HTMLIMAGE_BLANK_SRC_AS_EMPTY,
150 
151     /** Empty src attribute sets display to false. */
152     @BrowserFeature({FF, FF_ESR})
153     HTMLIMAGE_EMPTY_SRC_DISPLAY_FALSE,
154 
155     /** Is document.cretaeElement('image') an HTMLElement. */
156     @BrowserFeature({FF, FF_ESR})
157     HTMLIMAGE_HTMLELEMENT,
158 
159     /** Is document.cretaeElement('image') an HTMLUnknownElement. */
160     @BrowserFeature({CHROME, EDGE})
161     HTMLIMAGE_HTMLUNKNOWNELEMENT,
162 
163     /** Clicking an image input submits the value as param if defined. */
164     @BrowserFeature({CHROME, EDGE})
165     HTMLIMAGE_NAME_VALUE_PARAMS,
166 
167     /** HTMLInputElement image type is not supported. */
168     @BrowserFeature({CHROME, EDGE})
169     HTMLINPUT_TYPE_IMAGE_IGNORES_CUSTOM_VALIDITY,
170 
171     /** HTMLInputElement month type is supported. */
172     @BrowserFeature({CHROME, EDGE})
173     HTMLINPUT_TYPE_MONTH_SUPPORTED,
174 
175     /** HTMLInputElement week type is supported. */
176     @BrowserFeature({CHROME, EDGE})
177     HTMLINPUT_TYPE_WEEK_SUPPORTED,
178 
179     /** If the type is present for a link only use if type is text/css. */
180     @BrowserFeature({CHROME, EDGE})
181     HTMLLINK_CHECK_TYPE_FOR_STYLESHEET,
182 
183     /** willValidate does not check the readonly property. */
184     @BrowserFeature({FF, FF_ESR})
185     HTMLSELECT_WILL_VALIDATE_IGNORES_READONLY,
186 
187     /** Should org.htmlunit.javascript.host.html.HTMLTrackElement#isEndTagForbidden(). */
188     @BrowserFeature({FF, FF_ESR})
189     HTMLTRACK_END_TAG_FORBIDDEN,
190 
191     /** HTML parser supports the 'command' tag. */
192     @BrowserFeature({CHROME, EDGE})
193     HTML_COMMAND_TAG,
194 
195     /** HTML parser supports the 'layer' tag. */
196     @BrowserFeature({CHROME, EDGE})
197     HTML_LAYER_TAG,
198 
199     /** Additionally support dates in format "d/M/yyyy". */
200     @BrowserFeature({FF, FF_ESR})
201     HTTP_COOKIE_EXTENDED_DATE_PATTERNS_1,
202 
203     /** Dates format pattern 2. */
204     @BrowserFeature({CHROME, EDGE})
205     HTTP_COOKIE_EXTENDED_DATE_PATTERNS_2,
206 
207     /** domain '.org' is handled as 'org'. */
208     @BrowserFeature({FF, FF_ESR})
209     HTTP_COOKIE_REMOVE_DOT_FROM_ROOT_DOMAINS,
210 
211     /** Browser sends Sec-ch headers. */
212     @BrowserFeature({CHROME, EDGE})
213     HTTP_HEADER_CH_UA,
214 
215     /** Browser sends Priority headers. */
216     @BrowserFeature({FF, FF_ESR})
217     HTTP_HEADER_PRIORITY,
218 
219     /** The anchor hostname setter ignores blank url's. */
220     @BrowserFeature({FF, FF_ESR})
221     JS_ANCHOR_HOSTNAME_IGNORE_BLANK,
222 
223     /** The anchor pathname detects url's starting with one letter as file url's. */
224     @BrowserFeature(FF_ESR)
225     JS_ANCHOR_PATHNAME_DETECT_WIN_DRIVES_URL,
226 
227     /**
228      * The anchor pathname detects url's starting with one letter as file url's
229      * and replaces them with the file protocol. */
230     @BrowserFeature({CHROME, EDGE})
231     JS_ANCHOR_PATHNAME_DETECT_WIN_DRIVES_URL_REPLACE,
232 
233     /** The anchor pathname prefixes file url's with '/'. */
234     @BrowserFeature({CHROME, EDGE})
235     JS_ANCHOR_PATHNAME_PREFIX_WIN_DRIVES_URL,
236 
237     /** The anchor protocol property converts drive letters to uppercase. */
238     @BrowserFeature({CHROME, EDGE})
239     JS_ANCHOR_PROTOCOL_COLON_UPPER_CASE_DRIVE_LETTERS,
240 
241     /** An area element without a href attribute is focusable. */
242     @BrowserFeature({FF, FF_ESR})
243     JS_AREA_WITHOUT_HREF_FOCUSABLE,
244 
245     /** Sorting an array using a user defined comperator accepts inconsistent iterators. */
246     @BrowserFeature({FF, FF_ESR})
247     JS_ARRAY_SORT_ACCEPTS_INCONSISTENT_COMPERATOR,
248 
249     /** AudioProcessingEvent ctor is callable. */
250     @BrowserFeature({CHROME, EDGE})
251     JS_AUDIO_PROCESSING_EVENT_CTOR,
252 
253     /** toDataURL for canvas returns the CHROME version of the PNG. */
254     @BrowserFeature({CHROME, EDGE})
255     JS_CANVAS_DATA_URL_CHROME_PNG,
256 
257     /** ClientHeight for input is 17. */
258     @BrowserFeature({CHROME, EDGE})
259     JS_CLIENTHEIGHT_INPUT_17,
260 
261     /** ClientHeight for input is 18. */
262     @BrowserFeature({FF, FF_ESR})
263     JS_CLIENTHEIGHT_INPUT_18,
264 
265     /** ClientHeight for radio button and checkbox is 10. */
266     @BrowserFeature(FF_ESR)
267     JS_CLIENTHEIGHT_RADIO_CHECKBOX_10,
268 
269     /** ClientHeight for radio button and checkbox is 14. */
270     @BrowserFeature(FF)
271     JS_CLIENTHEIGHT_RADIO_CHECKBOX_14,
272 
273     /** ClientHeight for rb is 17. */
274     @BrowserFeature({FF, FF_ESR})
275     JS_CLIENTHEIGHT_RB_17,
276 
277     /** ClientHeight for rt is 9. */
278     @BrowserFeature({FF, FF_ESR})
279     JS_CLIENTHEIGHT_RT_9,
280 
281     /** ClientHeight for ruby is 17. */
282     @BrowserFeature({FF, FF_ESR})
283     JS_CLIENTHEIGHT_RUBY_17,
284 
285     /** ClientWidth for text/password input is 154. */
286     @BrowserFeature(FF_ESR)
287     JS_CLIENTWIDTH_INPUT_TEXT_154,
288 
289     /** ClientWidth for text/password input is 173. */
290     @BrowserFeature({CHROME, EDGE})
291     JS_CLIENTWIDTH_INPUT_TEXT_173,
292 
293     /** ClientWidth for radio button and checkbox is 10. */
294     @BrowserFeature(FF_ESR)
295     JS_CLIENTWIDTH_RADIO_CHECKBOX_10,
296 
297     /** ClientWidth for radio button and checkbox is 14. */
298     @BrowserFeature(FF)
299     JS_CLIENTWIDTH_RADIO_CHECKBOX_14,
300 
301     /** item is enumerated before length property of CSSRuleList. */
302     @BrowserFeature({FF, FF_ESR})
303     JS_CSSRULELIST_ENUM_ITEM_LENGTH,
304 
305     /** Javascript document.evaluate creates a new result object even if provided as param. */
306     @BrowserFeature({CHROME, EDGE})
307     JS_DOCUMENT_EVALUATE_RECREATES_RESULT,
308 
309     /** The browser has selection {@code rangeCount}. */
310     @BrowserFeature({FF, FF_ESR})
311     JS_DOCUMENT_SELECTION_RANGE_COUNT,
312 
313     /** Javascript {@code Error.captureStackTrace}. */
314     @BrowserFeature({CHROME, EDGE})
315     JS_ERROR_CAPTURE_STACK_TRACE,
316 
317     /** Javascript {@code Error.stackTraceLimit}. */
318     @BrowserFeature({CHROME, EDGE})
319     JS_ERROR_STACK_TRACE_LIMIT,
320 
321     /** Javascript InputEvent reads the inputType property from data. */
322     @BrowserFeature({FF, FF_ESR})
323     JS_EVENT_INPUT_CTOR_INPUTTYPE,
324 
325     /** Javascript KeyboardEvent reads the which property from data. */
326     @BrowserFeature({FF, FF_ESR})
327     JS_EVENT_KEYBOARD_CTOR_WHICH,
328 
329     /** form.dispatchEvent(e) submits the form if the event is of type 'submit'. */
330     @BrowserFeature({FF, FF_ESR})
331     JS_FORM_DISPATCHEVENT_SUBMITS,
332 
333     /** Executes the {@code onload} handler, regardless of the whether the element was already attached to the page. */
334     @BrowserFeature({FF, FF_ESR})
335     JS_IFRAME_ALWAYS_EXECUTE_ONLOAD,
336 
337     /**
338      * Getting the width and height of an image tag without a source returns 16x16;
339      * for invalid values returns 0.
340      */
341     @BrowserFeature({CHROME, EDGE})
342     JS_IMAGE_WIDTH_HEIGHT_RETURNS_16x16_0x0,
343 
344     /**
345      * Getting the width and height of an image tag without a source returns 24x24;
346      * for invalid values returns 0x0.
347      */
348     @BrowserFeature({FF, FF_ESR})
349     JS_IMAGE_WIDTH_HEIGHT_RETURNS_24x24_0x0,
350 
351     /** Indicates that innerText add a nl when reaching svg element. */
352     @BrowserFeature({CHROME, EDGE})
353     JS_INNER_TEXT_SVG_NL,
354 
355     /** The value is ignored when the type of an week/month input is changed. */
356     @BrowserFeature({CHROME, EDGE})
357     JS_INPUT_CHANGE_TYPE_DROPS_VALUE_WEEK_MONTH,
358 
359     /** FF accepts all chars. */
360     @BrowserFeature({FF, FF_ESR})
361     JS_INPUT_NUMBER_ACCEPT_ALL,
362 
363     /** FF comma at end is not an integer. */
364     @BrowserFeature({FF, FF_ESR})
365     JS_INPUT_NUMBER_DOT_AT_END_IS_DOUBLE,
366 
367     /** Indicates that Intl.v8BreakIterator is supported. */
368     @BrowserFeature({CHROME, EDGE})
369     JS_INTL_V8_BREAK_ITERATOR,
370 
371     /** Indicates that window.Iterator is supported. */
372     @BrowserFeature({CHROME, EDGE, FF})
373     JS_ITERATOR_VISIBLE_IN_WINDOW,
374 
375     /** For the 'about' protocol the location always returns an empty query. */
376     @BrowserFeature({FF, FF_ESR})
377     JS_LOCATION_IGNORE_QUERY_FOR_ABOUT_PROTOCOL,
378 
379     /** Reload sends a referrer header. */
380     @BrowserFeature({CHROME, EDGE})
381     JS_LOCATION_RELOAD_REFERRER,
382 
383     /** Type property of menu returns the current (maybe invalid) value. */
384     @BrowserFeature({FF, FF_ESR})
385     JS_MENU_TYPE_PASS,
386 
387     /** Indicates if the String representation of a native function is without newline. */
388     @BrowserFeature({CHROME, EDGE})
389     JS_NATIVE_FUNCTION_TOSTRING_COMPACT,
390 
391     /** Indicates if the String representation of a native function has a newline for empty parameter list. */
392     @BrowserFeature({FF, FF_ESR})
393     JS_NATIVE_FUNCTION_TOSTRING_NL,
394 
395     /** Navigator.doNotTrack returns unspecified if not set. */
396     @BrowserFeature({FF, FF_ESR})
397     JS_NAVIGATOR_DO_NOT_TRACK_UNSPECIFIED,
398 
399     /** Indicates that someObj.offsetParent returns null, it someObj has fixed style. */
400     @BrowserFeature({CHROME, EDGE})
401     JS_OFFSET_PARENT_NULL_IF_FIXED,
402 
403     /** element.outerHTML removes all children from detached node. */
404     @BrowserFeature({CHROME, EDGE})
405     JS_OUTER_HTML_THROWS_FOR_DETACHED,
406 
407     /** Indicates that the {@code Object.getOwnPropertyDescriptor.get} contains name. */
408     @BrowserFeature({FF, FF_ESR})
409     JS_PROPERTY_DESCRIPTOR_NAME,
410 
411     /** script tags created from js as child of templates are processed if added to the dom. */
412     @BrowserFeature({CHROME, EDGE})
413     JS_SCRIPT_IN_TEMPLATE_EXECUTED_ON_ATTACH,
414 
415     /** Javascript selectorText property returns selectors in lower case. */
416     @BrowserFeature({CHROME, EDGE})
417     JS_SELECTOR_TEXT_LOWERCASE,
418 
419     /** Indicates that select.options.remove ignores the call if index is too large. */
420     @BrowserFeature({FF, FF_ESR})
421     JS_SELECT_REMOVE_IGNORE_IF_INDEX_OUTSIDE,
422 
423     /** Whether to add to the storage even preserved words. */
424     @BrowserFeature({FF, FF_ESR})
425     JS_STORAGE_PRESERVED_INCLUDED,
426 
427     /** Indicates letterSpacing support percent values. */
428     @BrowserFeature(FF)
429     JS_STYLE_LETTER_SPACING_ACCEPTS_PERCENT,
430 
431     /** Indicates wordSpacing support percent values. */
432     @BrowserFeature({FF, FF_ESR})
433     JS_STYLE_WORD_SPACING_ACCEPTS_PERCENT,
434 
435     /** window.getComputedStyle works with pseudo selectors without colon in front. */
436     @BrowserFeature({CHROME, EDGE})
437     JS_WINDOW_COMPUTED_STYLE_PSEUDO_ACCEPT_WITHOUT_COLON,
438 
439     /** Javascript InstallTrigger property set to null. */
440     @BrowserFeature({FF, FF_ESR})
441     JS_WINDOW_INSTALL_TRIGGER_NULL,
442 
443     /**
444      * Difference of window.outer/inner height is 138.
445      */
446     @BrowserFeature(EDGE)
447     JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_138,
448 
449     /**
450      * Difference of window.outer/inner height is 147.
451      */
452     @BrowserFeature(CHROME)
453     JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_147,
454 
455     /**
456      * Difference of window.outer/inner height is 91.
457      */
458     @BrowserFeature(FF_ESR)
459     JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_91,
460 
461     /**
462      * Difference of window.outer/inner height is 93.
463      */
464     @BrowserFeature(FF)
465     JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_93,
466 
467     /** Window.getSelection returns null, if the window is not visible. */
468     @BrowserFeature({FF, FF_ESR})
469     JS_WINDOW_SELECTION_NULL_IF_INVISIBLE,
470 
471     /** {@code XSLTProcessor.transformToDocument} supports output indent attribute. */
472     @BrowserFeature({CHROME, EDGE})
473     JS_XSLT_TRANSFORM_INDENT,
474 
475     /** With special keys [in .type(int)], should we trigger onkeypress event or not. */
476     @BrowserFeature({FF, FF_ESR})
477     KEYBOARD_EVENT_SPECIAL_KEYPRESS,
478 
479     /** XMLHttpRequest.getAllResponseHeaders() uses only Lf as separator. */
480     @BrowserFeature({FF, FF_ESR})
481     XHR_ALL_RESPONSE_HEADERS_SEPARATE_BY_LF,
482 
483     /**
484      * Indicates that the Browser handles async and sync network errors the same way.
485      */
486     @BrowserFeature({FF, FF_ESR})
487     XHR_HANDLE_SYNC_NETWORK_ERRORS,
488 
489     /** XMLHttpRequest triggers the load events also if the abort was signaled. */
490     @BrowserFeature({FF, FF_ESR})
491     XHR_LOAD_ALWAYS_AFTER_DONE,
492 
493     /** If state unsent the response text is empty even if the response type is wrong. */
494     @BrowserFeature({FF, FF_ESR})
495     XHR_RESPONSE_TEXT_EMPTY_UNSENT,
496 
497     /** Indicates if the XMLHttpRequest.send() method will throw if aborted. */
498     @BrowserFeature({CHROME, EDGE})
499     XHR_SEND_NETWORK_ERROR_IF_ABORTED,
500 }