You can create a different browser setup by using the BrowserVersionFactory. *
- * String applicationName = "APPNAME"; - * String applicationVersion = "APPVERSION"; - * String userAgent = "USERAGENT"; - * int browserVersionNumeric = NUMERIC; + * final String applicationName = "APPNAME"; + * final String applicationVersion = "APPVERSION"; + * final String userAgent = "USERAGENT"; * - * BrowserVersion browser = new BrowserVersion.BrowserVersionFactory(FF52) - * .setApplicationName(applicationName) - * .setApplicationVersion(applicationVersion) - * .setUserAgent(userAgent) - * .build(); + * final BrowserVersion browser = + * new BrowserVersion.BrowserVersionBuilder(BrowserVersion.FIREFOX_68) + * .setApplicationName(applicationName) + * .setApplicationVersion(applicationVersion) + * .setUserAgent(userAgent) + * .build(); *- *
But keep in mind this now one still behaves like a FF52, only the stuff reported to the + *
But keep in mind this now one still behaves like a FF68, only the stuff reported to the
* outside is changed. This is more or less the same you can do with real browsers installing
* plugins like UserAgentSwitcher.
*
@@ -100,10 +100,10 @@ public final class BrowserVersion implements Serializable {
public static final BrowserVersion FIREFOX_60 = new BrowserVersion(60, "FF60");
/**
- * Firefox 52 ESR.
- * @since 2.26
+ * Firefox 68 ESR.
+ * @since 2.37
*/
- public static final BrowserVersion FIREFOX_52 = new BrowserVersion(52, "FF52");
+ public static final BrowserVersion FIREFOX_68 = new BrowserVersion(68, "FF68");
/** Internet Explorer 11. */
public static final BrowserVersion INTERNET_EXPLORER = new BrowserVersion(11, "IE");
@@ -147,30 +147,32 @@ public final class BrowserVersion implements Serializable {
116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130, 131, 132, 133, 135, 136, 138, 139,
139, 141, 142, 143, 144, 146, 147, 148, 149};
- // FF52
- FIREFOX_52.applicationVersion_ = "5.0 (Windows)";
- FIREFOX_52.userAgent_ = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0";
- FIREFOX_52.buildId_ = "20180621064021";
- FIREFOX_52.productSub_ = "20100101";
- FIREFOX_52.headerNamesOrdered_ = new String[] {
+ // FF68
+ FIREFOX_68.applicationVersion_ = "5.0 (Windows)";
+ FIREFOX_68.userAgent_ = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0";
+ FIREFOX_68.buildId_ = "20181001000000";
+ FIREFOX_68.productSub_ = "20100101";
+ FIREFOX_68.headerNamesOrdered_ = new String[] {
HttpHeader.HOST,
HttpHeader.USER_AGENT,
HttpHeader.ACCEPT,
HttpHeader.ACCEPT_LANGUAGE,
HttpHeader.ACCEPT_ENCODING,
HttpHeader.REFERER,
- HttpHeader.COOKIE,
HttpHeader.CONNECTION,
- "Upgrade-Insecure-Requests"};
- FIREFOX_52.htmlAcceptHeader_ = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
- FIREFOX_52.cssAcceptHeader_ = "text/css,*/*;q=0.1";
- FIREFOX_52.fontHeights_ = new int[] {
- 0, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50, 51, 52, 53, 53, 55, 57, 58,
- 59, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 82, 84, 85, 86, 87, 88,
- 89, 90, 91, 93, 94, 95, 96, 96, 98, 99, 100, 101, 103, 104, 105, 106, 106, 108, 109, 111, 112, 113, 115,
- 116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130, 131, 132, 133, 135, 136, 138, 139,
- 139, 141, 142, 143, 144, 146, 147, 148, 149};
+ HttpHeader.COOKIE};
+ FIREFOX_68.htmlAcceptHeader_ = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
+ FIREFOX_68.xmlHttpRequestAcceptHeader_ = "*/*";
+ FIREFOX_68.imgAcceptHeader_ = "image/webp,*/*";
+ FIREFOX_68.cssAcceptHeader_ = "text/css,*/*;q=0.1";
+ FIREFOX_68.fontHeights_ = new int[] {
+ 0, 2, 3, 5, 6, 6, 7, 9, 10, 11, 12, 13, 15, 16, 16, 17, 18, 20, 21, 22, 23, 25, 26, 26, 28, 29,
+ 31, 32, 33, 34, 35, 37, 38, 38, 39, 41, 42, 43, 44, 45, 47, 48, 48, 49, 51, 52, 53, 54, 56, 58, 59, 59,
+ 60, 61, 63, 64, 65, 66, 68, 69, 69, 70, 71, 73, 74, 75, 76, 77, 79, 79,
+ 80, 82, 84, 85, 86, 87, 88, 90, 91, 91, 92, 94, 95, 96, 97, 98,
+ 100, 101, 101, 102, 103, 105, 106, 107, 108, 111, 112, 112, 113, 114, 116, 117, 118, 119,
+ 120, 122, 122, 123, 124, 126, 127, 128, 129, 130, 132, 132, 133, 134, 137, 138, 139,
+ 140, 141, 143, 143, 144, 145, 146, 148};
// IE
INTERNET_EXPLORER.applicationVersion_ = "5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko";
@@ -199,8 +201,8 @@ public final class BrowserVersion implements Serializable {
139, 140, 141, 143, 144, 145, 146, 147};
// CHROME
- CHROME.applicationVersion_ = "5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36";
- CHROME.userAgent_ = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36";
+ CHROME.applicationVersion_ = "5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36";
+ CHROME.userAgent_ = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36";
CHROME.applicationCodeName_ = "Mozilla";
CHROME.vendor_ = "Google Inc.";
@@ -212,12 +214,17 @@ public final class BrowserVersion implements Serializable {
HttpHeader.CONNECTION,
"Upgrade-Insecure-Requests",
HttpHeader.USER_AGENT,
+ HttpHeader.SEC_FETCH_USER,
HttpHeader.ACCEPT,
+ HttpHeader.SEC_FETCH_SITE,
+ HttpHeader.SEC_FETCH_MODE,
HttpHeader.REFERER,
HttpHeader.ACCEPT_ENCODING,
HttpHeader.ACCEPT_LANGUAGE,
HttpHeader.COOKIE};
- CHROME.htmlAcceptHeader_ = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8";
+ CHROME.acceptEncodingHeader_ = "gzip, deflate, br";
+ CHROME.htmlAcceptHeader_ = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;"
+ + "q=0.8,application/signed-exchange;v=b3;q=0.9";
CHROME.imgAcceptHeader_ = "image/webp,image/apng,image/*,*/*;q=0.8";
CHROME.cssAcceptHeader_ = "text/css,*/*;q=0.1";
CHROME.scriptAcceptHeader_ = "*/*";
@@ -255,8 +262,8 @@ public final class BrowserVersion implements Serializable {
CHROME.registerUploadMimeType("xhtml", "application/xhtml+xml");
CHROME.registerUploadMimeType("xht", "application/xhtml+xml");
CHROME.registerUploadMimeType("xhtm", "application/xhtml+xml");
- CHROME.registerUploadMimeType("txt", "text/plain");
- CHROME.registerUploadMimeType("text", "text/plain");
+ CHROME.registerUploadMimeType("txt", MimeType.TEXT_PLAIN);
+ CHROME.registerUploadMimeType("text", MimeType.TEXT_PLAIN);
FIREFOX_60.registerUploadMimeType("html", MimeType.TEXT_HTML);
FIREFOX_60.registerUploadMimeType("htm", MimeType.TEXT_HTML);
@@ -279,32 +286,33 @@ public final class BrowserVersion implements Serializable {
FIREFOX_60.registerUploadMimeType("wav", "audio/wav");
FIREFOX_60.registerUploadMimeType("xhtml", "application/xhtml+xml");
FIREFOX_60.registerUploadMimeType("xht", "application/xhtml+xml");
- FIREFOX_60.registerUploadMimeType("txt", "text/plain");
- FIREFOX_60.registerUploadMimeType("text", "text/plain");
-
- FIREFOX_52.registerUploadMimeType("html", MimeType.TEXT_HTML);
- FIREFOX_52.registerUploadMimeType("htm", MimeType.TEXT_HTML);
- FIREFOX_52.registerUploadMimeType("css", MimeType.TEXT_CSS);
- FIREFOX_52.registerUploadMimeType("xml", MimeType.TEXT_XML);
- FIREFOX_52.registerUploadMimeType("gif", "image/gif");
- FIREFOX_52.registerUploadMimeType("jpeg", "image/jpeg");
- FIREFOX_52.registerUploadMimeType("jpg", "image/jpeg");
- FIREFOX_52.registerUploadMimeType("mp4", "video/mp4");
- FIREFOX_52.registerUploadMimeType("m4v", "video/mp4");
- FIREFOX_52.registerUploadMimeType("m4a", "audio/mp4");
- FIREFOX_52.registerUploadMimeType("png", "image/png");
- FIREFOX_52.registerUploadMimeType("mp3", "audio/mpeg");
- FIREFOX_52.registerUploadMimeType("ogv", "video/ogg");
- FIREFOX_52.registerUploadMimeType("ogm", "video/x-ogm");
- FIREFOX_52.registerUploadMimeType("ogg", "video/ogg");
- FIREFOX_52.registerUploadMimeType("oga", "audio/ogg");
- FIREFOX_52.registerUploadMimeType("opus", "audio/ogg");
- FIREFOX_52.registerUploadMimeType("webm", "video/webm");
- FIREFOX_52.registerUploadMimeType("wav", "audio/wav");
- FIREFOX_52.registerUploadMimeType("xhtml", "application/xhtml+xml");
- FIREFOX_52.registerUploadMimeType("xht", "application/xhtml+xml");
- FIREFOX_52.registerUploadMimeType("txt", "text/plain");
- FIREFOX_52.registerUploadMimeType("text", "text/plain");
+ FIREFOX_60.registerUploadMimeType("txt", MimeType.TEXT_PLAIN);
+ FIREFOX_60.registerUploadMimeType("text", MimeType.TEXT_PLAIN);
+
+ FIREFOX_68.registerUploadMimeType("html", MimeType.TEXT_HTML);
+ FIREFOX_68.registerUploadMimeType("htm", MimeType.TEXT_HTML);
+ FIREFOX_68.registerUploadMimeType("css", MimeType.TEXT_CSS);
+ FIREFOX_68.registerUploadMimeType("xml", MimeType.TEXT_XML);
+ FIREFOX_68.registerUploadMimeType("gif", "image/gif");
+ FIREFOX_68.registerUploadMimeType("jpeg", "image/jpeg");
+ FIREFOX_68.registerUploadMimeType("jpg", "image/jpeg");
+ FIREFOX_68.registerUploadMimeType("mp4", "video/mp4");
+ FIREFOX_68.registerUploadMimeType("m4v", "video/mp4");
+ FIREFOX_68.registerUploadMimeType("m4a", "audio/mp4");
+ FIREFOX_68.registerUploadMimeType("png", "image/png");
+ FIREFOX_68.registerUploadMimeType("mp3", "audio/mpeg");
+ FIREFOX_68.registerUploadMimeType("ogv", "video/ogg");
+ FIREFOX_68.registerUploadMimeType("ogm", "video/x-ogm");
+ FIREFOX_68.registerUploadMimeType("ogg", "video/ogg");
+ FIREFOX_68.registerUploadMimeType("oga", "audio/ogg");
+ FIREFOX_68.registerUploadMimeType("opus", "audio/ogg");
+ FIREFOX_68.registerUploadMimeType("webm", "video/webm");
+ FIREFOX_68.registerUploadMimeType("webp", "image/webp");
+ FIREFOX_68.registerUploadMimeType("wav", "audio/wav");
+ FIREFOX_68.registerUploadMimeType("xhtml", "application/xhtml+xml");
+ FIREFOX_68.registerUploadMimeType("xht", "application/xhtml+xml");
+ FIREFOX_68.registerUploadMimeType("txt", MimeType.TEXT_PLAIN);
+ FIREFOX_68.registerUploadMimeType("text", MimeType.TEXT_PLAIN);
INTERNET_EXPLORER.registerUploadMimeType("html", MimeType.TEXT_HTML);
INTERNET_EXPLORER.registerUploadMimeType("htm", MimeType.TEXT_HTML);
@@ -323,16 +331,10 @@ public final class BrowserVersion implements Serializable {
INTERNET_EXPLORER.registerUploadMimeType("wav", "audio/wav");
INTERNET_EXPLORER.registerUploadMimeType("xhtml", "application/xhtml+xml");
INTERNET_EXPLORER.registerUploadMimeType("xht", "application/xhtml+xml");
- INTERNET_EXPLORER.registerUploadMimeType("txt", "text/plain");
+ INTERNET_EXPLORER.registerUploadMimeType("txt", MimeType.TEXT_PLAIN);
// flush plugin (windows version)
- PluginConfiguration flash = new PluginConfiguration("Shockwave Flash",
- "Shockwave Flash 30.0 r0", "30.0.0.113", "NPSWF64_30_0_0_113.dll"); //NOPMD
- flash.getMimeTypes().add(new PluginConfiguration.MimeType("application/x-shockwave-flash",
- "Shockwave Flash", "swf"));
- FIREFOX_52.plugins_.add(flash);
-
- flash = new PluginConfiguration("Shockwave Flash",
+ final PluginConfiguration flash = new PluginConfiguration("Shockwave Flash",
"Shockwave Flash 30.0 r0", "30.0.0.113", "Flash32_30_0_0_113.ocx"); //NOPMD
flash.getMimeTypes().add(new PluginConfiguration.MimeType("application/x-shockwave-flash",
"Shockwave Flash", "swf"));
@@ -359,6 +361,7 @@ public final class BrowserVersion implements Serializable {
private String userLanguage_ = LANGUAGE_ENGLISH_US;
private final Set Check freshness return value if
+ * a) s-maxage specified
+ * b) max-age specified
+ * c) expired specified
+ * otherwise return {@code null} Check freshness return value if
- * a) s-maxage specified
- * b) max-age specified
- * c) expired specified
- * otherwise return {@code null}
- * @return whether or not this version version 52 of a Firefox browser
+ * @return whether or not this version version 60 of a Firefox browser
*/
- public boolean isFirefox52() {
- return isFirefox() && getBrowserVersionNumeric() == 52;
+ public boolean isFirefox60() {
+ return isFirefox() && getBrowserVersionNumeric() == 60;
}
/**
@@ -618,6 +622,14 @@ public String getUserLanguage() {
return userLanguage_;
}
+ /**
+ * Returns the value used by the browser for the {@code Accept_Encoding} header.
+ * @return the accept encoding header string
+ */
+ public String getAcceptEncodingHeader() {
+ return acceptEncodingHeader_;
+ }
+
/**
* Returns the value used by the browser for the {@code Accept} header if requesting a page.
* @return the accept header string
@@ -789,17 +801,17 @@ public BrowserVersionBuilder(final BrowserVersion version) {
.setPlatform(version.getPlatform())
.setSystemLanguage(version.getSystemLanguage())
.setSystemTimezone(version.getSystemTimezone())
- .setUserLanguage(version.getUserLanguage());
-
- workPiece_.buildId_ = version.getBuildId();
- workPiece_.productSub_ = version.getProductSub();
- workPiece_.htmlAcceptHeader_ = version.getHtmlAcceptHeader();
- workPiece_.imgAcceptHeader_ = version.getImgAcceptHeader();
- workPiece_.cssAcceptHeader_ = version.getCssAcceptHeader();
- workPiece_.scriptAcceptHeader_ = version.getScriptAcceptHeader();
- workPiece_.xmlHttpRequestAcceptHeader_ = version.getXmlHttpRequestAcceptHeader();
- workPiece_.headerNamesOrdered_ = version.getHeaderNamesOrdered();
- workPiece_.fontHeights_ = version.fontHeights_;
+ .setUserLanguage(version.getUserLanguage())
+ .setBuildId(version.getBuildId())
+ .setProductSub(version.getProductSub())
+ .setAcceptEncodingHeader(version.getAcceptEncodingHeader())
+ .setHtmlAcceptHeader(version.getHtmlAcceptHeader())
+ .setImgAcceptHeader(version.getImgAcceptHeader())
+ .setCssAcceptHeader(version.getCssAcceptHeader())
+ .setScriptAcceptHeader(version.getScriptAcceptHeader())
+ .setXmlHttpRequestAcceptHeader(version.getXmlHttpRequestAcceptHeader())
+ .setHeaderNamesOrdered(version.getHeaderNamesOrdered())
+ .setFontHeights(version.fontHeights_);
for (final PluginConfiguration pluginConf : version.getPlugins()) {
workPiece_.plugins_.add(pluginConf.clone());
@@ -933,6 +945,15 @@ public BrowserVersionBuilder setUserLanguage(final String userLanguage) {
return this;
}
+ /**
+ * @param acceptEncodingHeader the {@code Accept-Encoding} header
+ * @return this for fluent use
+ */
+ public BrowserVersionBuilder setAcceptEncodingHeader(final String acceptEncodingHeader) {
+ workPiece_.acceptEncodingHeader_ = acceptEncodingHeader;
+ return this;
+ }
+
/**
* @param htmlAcceptHeader the {@code Accept} header to be used when retrieving pages
* @return this for fluent use
@@ -978,5 +999,41 @@ public BrowserVersionBuilder setXmlHttpRequestAcceptHeader(final String xmlHttpR
workPiece_.xmlHttpRequestAcceptHeader_ = xmlHttpRequestAcceptHeader;
return this;
}
+
+ /**
+ * @param productSub the productSub
+ * @return this for fluent use
+ */
+ BrowserVersionBuilder setProductSub(final String productSub) {
+ workPiece_.productSub_ = productSub;
+ return this;
+ }
+
+ /**
+ * @param headerNamesOrdered the headerNamesOrdered
+ * @return this for fluent use
+ */
+ BrowserVersionBuilder setHeaderNamesOrdered(final String[] headerNamesOrdered) {
+ workPiece_.headerNamesOrdered_ = headerNamesOrdered;
+ return this;
+ }
+
+ /**
+ * @param headerNamesOrdered the headerNamesOrdered
+ * @return this for fluent use
+ */
+ BrowserVersionBuilder setFontHeights(final int[] fontHeights) {
+ workPiece_.fontHeights_ = fontHeights;
+ return this;
+ }
+
+ /**
+ * @param buildId the buildId
+ * @return this for fluent use
+ */
+ BrowserVersionBuilder setBuildId(final String buildId) {
+ workPiece_.buildId_ = buildId;
+ return this;
+ }
}
}
diff --git a/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java b/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java
index 3a42a056273..2d8e7be2c1d 100644
--- a/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java
+++ b/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002-2019 Gargoyle Software Inc.
+ * Copyright (c) 2002-2020 Gargoyle Software Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,8 @@
import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF;
-import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF52;
import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF60;
+import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF68;
import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.IE;
import com.gargoylesoftware.htmlunit.javascript.configuration.BrowserFeature;
@@ -47,26 +47,22 @@ public enum BrowserVersionFeatures {
/** Ignore target when {@code href} is a javascript snippet. */
@BrowserFeature(CHROME)
- ANCHOR_IGNORE_TARGET_FOR_JS_HREF,
+ ANCHOR_SEND_PING_REQUEST,
/** Background image is 'initial'. */
@BrowserFeature(CHROME)
CSS_BACKGROUND_INITIAL,
/** Background image is 'rgba(0, 0, 0, 0)'. */
- @BrowserFeature(FF60)
+ @BrowserFeature(FF)
CSS_BACKGROUND_RGBA,
- /** Computed {@code display} is {@code block} for non-attached elements. */
- @BrowserFeature(FF52)
- CSS_COMPUTED_BLOCK_IF_NOT_ATTACHED,
-
/** Computed {@code zIndex} is not considered. */
@BrowserFeature(CHROME)
CSS_COMPUTED_NO_Z_INDEX,
/** Is display style of HtmlDialog is 'none'. */
- @BrowserFeature({CHROME, FF60})
+ @BrowserFeature({CHROME, FF})
CSS_DIALOG_NONE,
/** Is display style 'block'. */
@@ -77,13 +73,17 @@ public enum BrowserVersionFeatures {
@BrowserFeature({CHROME, FF})
CSS_DISPLAY_BLOCK2,
- /** {@code CSSFontFaceRule.cssText} uses {@code \r\n} to break lines. */
- @BrowserFeature(IE)
- CSS_FONTFACERULE_CSSTEXT_CRLF,
-
/** {@code CSSFontFaceRule.cssText} has no {@code \n}. */
@BrowserFeature(CHROME)
- CSS_FONTFACERULE_CSSTEXT_NO_CRLF,
+ CSS_FONTFACERULE_CSSTEXT_CHROME_STYLE,
+
+ /** {@code CSSFontFaceRule.cssText} has no {@code \n}. */
+ @BrowserFeature(FF60)
+ CSS_FONTFACERULE_CSSTEXT_FF60_STYLE,
+
+ /** {@code CSSFontFaceRule.cssText} uses {@code \n\t} to break lines. */
+ @BrowserFeature(IE)
+ CSS_FONTFACERULE_CSSTEXT_IE_STYLE,
/** The default value of the display property for the 'input' tags is 'inline-block'. */
@BrowserFeature({CHROME, IE})
@@ -91,7 +91,7 @@ public enum BrowserVersionFeatures {
/** The default value of the display property for the 'input' tags of type
* radio or checkbox is 'inline-block'. */
- @BrowserFeature(FF60)
+ @BrowserFeature(FF)
CSS_INPUT_DISPLAY_RADIO_CHECKBOX_INLINE_BLOCK,
/** 'initial' is a valid length value. */
@@ -119,7 +119,7 @@ public enum BrowserVersionFeatures {
CSS_RP_DISPLAY_NONE,
/** The default value of the display property for the 'rt' tag is always 'ruby-text'. */
- @BrowserFeature({IE, FF60})
+ @BrowserFeature({IE, FF})
CSS_RT_DISPLAY_RUBY_TEXT_ALWAYS,
/** The default value of the display property for the 'ruby' tag is 'inline'. */
@@ -130,6 +130,14 @@ public enum BrowserVersionFeatures {
@BrowserFeature(IE)
CSS_SET_NULL_THROWS,
+ /** For disconnectd items style properties are blank. */
+ @BrowserFeature({CHROME, FF68})
+ CSS_STYLE_PROP_DISCONNECTED_IS_EMPTY,
+
+ /** For disconnectd items style font property is blank. */
+ @BrowserFeature(CHROME)
+ CSS_STYLE_PROP_FONT_DISCONNECTED_IS_EMPTY,
+
/** Internet Explorer versions 5 and later support the behavior property. The behavior property lets
* you use CSS to attach a script to a specific element in order to implement
* DHTML (Dynamic HTML) components.
@@ -230,17 +238,13 @@ public enum BrowserVersionFeatures {
EVENT_ONMOUSEUP_NOT_FOR_SELECT_OPTION,
/** PopStateEvent can not be created by calling document.createEvent('PopStateEvent'). */
- @BrowserFeature(FF60)
+ @BrowserFeature(FF)
EVENT_ONPOPSTATE_DOCUMENT_CREATE_NOT_SUPPORTED,
/** Supports event type 'BeforeUnloadEvent'. */
@BrowserFeature({CHROME, FF})
EVENT_TYPE_BEFOREUNLOADEVENT,
- /** Supports event type 'FocusEvent'. */
- @BrowserFeature({CHROME, FF60, IE})
- EVENT_TYPE_FOCUSEVENT,
-
/** Supports event type 'HashChangeEvent'. */
@BrowserFeature({CHROME, FF})
EVENT_TYPE_HASHCHANGEEVENT,
@@ -261,10 +265,6 @@ public enum BrowserVersionFeatures {
@BrowserFeature(IE)
EVENT_TYPE_PROGRESSEVENT,
- /** Supports event type 'SVGZoomEvent'. */
- @BrowserFeature(FF52)
- EVENT_TYPE_SVGZOOMEVENT,
-
/** Supports event type 'WheelEvent'. */
@BrowserFeature({CHROME, IE})
EVENT_TYPE_WHEELEVENT,
@@ -314,15 +314,15 @@ public enum BrowserVersionFeatures {
HTMLABBREVIATED,
/** HtmlAllCollection.item returns null instead of undefined if an element was not found. */
- @BrowserFeature({IE, FF})
+ @BrowserFeature({IE, FF60})
HTMLALLCOLLECTION_DO_NOT_CONVERT_STRINGS_TO_NUMBER,
/** HtmlAllCollection.item(int) is not supported. */
- @BrowserFeature(FF)
+ @BrowserFeature(FF60)
HTMLALLCOLLECTION_DO_NOT_SUPPORT_PARANTHESES,
/** HtmlAllCollection.item(int) requires int parameter. */
- @BrowserFeature(CHROME)
+ @BrowserFeature({CHROME, FF68})
HTMLALLCOLLECTION_INTEGER_INDEX,
/** HtmlCollection returns the first hit instead of a collection if many elements found. */
@@ -342,7 +342,7 @@ public enum BrowserVersionFeatures {
HTMLBASE_HREF_DEFAULT_EMPTY,
/** HtmlCollection.item() supports also doubles as index. */
- @BrowserFeature({IE, FF})
+ @BrowserFeature({IE, FF60})
HTMLCOLLECTION_ITEM_FUNCT_SUPPORTS_DOUBLE_INDEX_ALSO,
/** HtmlCollection.item[] supports also doubles as index. */
@@ -384,7 +384,7 @@ public enum BrowserVersionFeatures {
/**
/** {@code document.getElementsByName} returns an empty list if called with the empty string.
*/
- @BrowserFeature(FF60)
+ @BrowserFeature(FF)
HTMLDOCUMENT_ELEMENTS_BY_NAME_EMPTY,
/** We can used function in detached documents. */
@@ -458,16 +458,16 @@ public enum BrowserVersionFeatures {
@BrowserFeature({CHROME, FF})
HTMLINPUT_FILE_SELECTION_START_END_NULL,
- /** HTMLInputElement: type {@code file} value to be {@code fakepath}. */
- @BrowserFeature({CHROME, FF60, IE})
- HTMLINPUT_FILE_VALUE_FAKEPATH,
+ /** HTMLInputElement color type is not supported. */
+ @BrowserFeature(IE)
+ HTMLINPUT_TYPE_COLOR_NOT_SUPPORTED,
/** HTMLInputElement date and time types are supported. */
- @BrowserFeature({CHROME, FF60})
+ @BrowserFeature({CHROME, FF})
HTMLINPUT_TYPE_DATETIME_SUPPORTED,
- /** HTMLInputElement date and time types are supported. */
- @BrowserFeature(FF60)
+ /** HTMLInputElement date and time types are not supported. */
+ @BrowserFeature(FF)
HTMLINPUT_TYPE_MONTH_NOT_SUPPORTED,
/** Should the HTMLElement of {@code keygen} have no end tag. */
@@ -523,7 +523,7 @@ public enum BrowserVersionFeatures {
HTML_COMMAND_TAG,
/** HTML parser supports the 'isindex' tag. */
- @BrowserFeature({CHROME, FF60})
+ @BrowserFeature({CHROME, FF})
HTML_ISINDEX_TAG,
/** HTML parser supports the 'main' tag. */
@@ -559,6 +559,10 @@ public enum BrowserVersionFeatures {
@BrowserFeature({CHROME, FF})
HTTP_COOKIE_START_DATE_1970,
+ /** Browser sends Sec-Fetch headers. */
+ @BrowserFeature(CHROME)
+ HTTP_HEADER_SEC_FETCH,
+
/** Browser sends Upgrade-Insecure-Requests header. */
@BrowserFeature({CHROME, FF})
HTTP_HEADER_UPGRADE_INSECURE_REQUEST,
@@ -590,7 +594,7 @@ public enum BrowserVersionFeatures {
JS_ANCHOR_PATHNAME_DETECT_WIN_DRIVES_URL,
/** The anchor pathname property returns nothing for broken http(s) url's. */
- @BrowserFeature({CHROME, FF60})
+ @BrowserFeature({CHROME, FF})
JS_ANCHOR_PATHNAME_NONE_FOR_BROKEN_URL,
/** The anchor pathname property returns nothing for none http(s) url's. */
@@ -610,7 +614,7 @@ public enum BrowserVersionFeatures {
JS_ANCHOR_PROTOCOL_COLON_UPPER_CASE_DRIVE_LETTERS,
/** The anchor protocol property returns 'http' for broken http(s) url's. */
- @BrowserFeature(FF60)
+ @BrowserFeature(FF)
JS_ANCHOR_PROTOCOL_HTTP_FOR_BROKEN_URL,
/** Indicates that "someFunction.arguments" is a read-only view of the function's argument. */
@@ -657,8 +661,12 @@ public enum BrowserVersionFeatures {
@BrowserFeature(CHROME)
JS_CLIENTHIGHT_INPUT_17,
+ /** ClientHeight for input is 21. */
+ @BrowserFeature(FF60)
+ JS_CLIENTHIGHT_INPUT_21,
+
/** ClientRectList toString reports the first item. */
- @BrowserFeature(FF)
+ @BrowserFeature(FF60)
JS_CLIENTRECTLIST_DEFAUL_VALUE_FROM_FIRST,
/** ClientRectList.item throws instead of returning null if an element was not found. */
@@ -721,10 +729,6 @@ public enum BrowserVersionFeatures {
@BrowserFeature(IE)
JS_DOCUMENT_SETTING_DOMAIN_THROWS_FOR_ABOUT_BLANK,
- /** If setting the document.location inside onclick() of anchor element should be triggered. */
- @BrowserFeature({IE, FF})
- JS_DOCUMENT_SET_LOCATION_EXECUTED_IN_ANCHOR,
-
/** createHTMLDucument requires a title. */
@BrowserFeature(IE)
JS_DOMIMPLEMENTATION_CREATE_HTMLDOCOMENT_REQUIRES_TITLE,
@@ -846,17 +850,13 @@ public enum BrowserVersionFeatures {
JS_DOMTOKENLIST_GET_NULL_IF_OUTSIDE,
/** DOMTokenList ignores duplicates when determining the length. */
- @BrowserFeature({CHROME, FF60})
+ @BrowserFeature({CHROME, FF})
JS_DOMTOKENLIST_LENGTH_IGNORES_DUPLICATES,
/** DOMTokenList removed all whitespace chars during add. */
- @BrowserFeature({CHROME, FF60})
+ @BrowserFeature({CHROME, FF})
JS_DOMTOKENLIST_REMOVE_WHITESPACE_CHARS_ON_ADD,
- /** DOMTokenList removed all whitespace chars during edit. */
- @BrowserFeature({CHROME, FF60, IE})
- JS_DOMTOKENLIST_REMOVE_WHITESPACE_CHARS_ON_EDIT,
-
/** DOMTokenList removed all whitespace chars during remove. */
@BrowserFeature({CHROME, FF})
JS_DOMTOKENLIST_REMOVE_WHITESPACE_CHARS_ON_REMOVE,
@@ -902,13 +902,13 @@ public enum BrowserVersionFeatures {
JS_FILE_SHORT_DATE_FORMAT,
/** Indicates that the action property will not be expanded if defined as empty string. */
- @BrowserFeature(FF52)
- JS_FORM_ACTION_EXPANDURL_IGNORE_EMPTY,
-
- /** Indicates that the action property will not be expanded if defined as empty string. */
- @BrowserFeature({CHROME, FF60})
+ @BrowserFeature({CHROME, FF})
JS_FORM_ACTION_EXPANDURL_NOT_DEFINED,
+ /** use content-type text/plain if the file type is unknown'. */
+ @BrowserFeature(IE)
+ JS_FORM_DATA_CONTENT_TYPE_PLAIN_IF_FILE_TYPE_UNKNOWN,
+
/** form.dispatchEvent(e) submits the form if the event is of type 'submit'. */
@BrowserFeature(FF)
JS_FORM_DISPATCHEVENT_SUBMITS,
@@ -966,7 +966,7 @@ public enum BrowserVersionFeatures {
/**
* Getting the width and height of an image tag with an empty source returns 0x0.
*/
- @BrowserFeature({CHROME, FF60})
+ @BrowserFeature({CHROME, FF})
JS_IMAGE_WIDTH_HEIGHT_EMPTY_SOURCE_RETURNS_0x0,
/**
@@ -1003,7 +1003,7 @@ public enum BrowserVersionFeatures {
JS_INNER_TEXT_VALUE_NULL,
/** Ignore negative selection starts. */
- @BrowserFeature({CHROME, FF60})
+ @BrowserFeature({CHROME, FF})
JS_INPUT_IGNORE_NEGATIVE_SELECTION_START,
/** Chrome/FF returns null for selectionStart/selectionEnd. */
@@ -1015,7 +1015,7 @@ public enum BrowserVersionFeatures {
JS_INPUT_SET_TYPE_LOWERCASE,
/** Setting the value of an Input Date will check for correct format. */
- @BrowserFeature({CHROME, FF60})
+ @BrowserFeature({CHROME, FF})
JS_INPUT_SET_VALUE_DATE_SUPPORTED,
/** Setting the value of an Input Email to blank will result in an empty value. */
@@ -1034,9 +1034,9 @@ public enum BrowserVersionFeatures {
@BrowserFeature(CHROME)
JS_INTL_V8_BREAK_ITERATOR,
- /** Supports Iterator and StopIteration. */
- @BrowserFeature(FF52)
- JS_Iterator,
+ /** Indicates that isSearchProviderInstalled returns zero instead of undefined. */
+ @BrowserFeature({CHROME, FF60, IE})
+ JS_IS_SEARCH_PROVIDER_INSTALLED_ZERO,
/** Property form for label always returns null. */
@BrowserFeature({CHROME, FF})
@@ -1071,6 +1071,10 @@ public enum BrowserVersionFeatures {
@BrowserFeature({CHROME, FF})
JS_LOCATION_HREF_HASH_IS_ENCODED,
+ /** Reload sends a referrer header. */
+ @BrowserFeature(CHROME)
+ JS_LOCATION_RELOAD_REFERRER,
+
/** Indicates that an empty media list is represented by the string 'all'. */
@BrowserFeature(IE)
JS_MEDIA_LIST_ALL,
@@ -1084,7 +1088,7 @@ public enum BrowserVersionFeatures {
JS_MENU_TYPE_EMPTY,
/** Type property of menu returns the current (maybe invalid) value. */
- @BrowserFeature(FF60)
+ @BrowserFeature(FF)
JS_MENU_TYPE_PASS,
/** Indicates if the String representation of a native function is without newline. */
@@ -1096,7 +1100,7 @@ public enum BrowserVersionFeatures {
JS_NATIVE_FUNCTION_TOSTRING_NEW_LINE,
/** Indicates if the String representation of a native function has a newline for empty parameter list. */
- @BrowserFeature(FF60)
+ @BrowserFeature(FF)
JS_NATIVE_FUNCTION_TOSTRING_NL,
/** Navigator.doNotTrack returns unspecified if not set. */
@@ -1172,9 +1176,15 @@ public enum BrowserVersionFeatures {
@BrowserFeature(IE)
JS_REGEXP_GROUP0_RETURNS_WHOLE_MATCH,
- /** Javascript script tags supports the 'for' and the 'event' attribute.
+ /**
+ * Javascript script tags handles a 204 (no content) response for the src
+ * attrib as error.
*/
@BrowserFeature(IE)
+ JS_SCRIPT_HANDLE_204_AS_ERROR,
+
+ /** Javascript script tags supports the 'for' and the 'event' attribute. */
+ @BrowserFeature(IE)
JS_SCRIPT_SUPPORTS_FOR_AND_EVENT_WINDOW,
/** Javascript selectorText property returns selectors in lower case. */
@@ -1185,17 +1195,17 @@ public enum BrowserVersionFeatures {
@BrowserFeature({CHROME, FF})
JS_SELECT_FILE_THROWS,
- /** When expanding the collection by setting the length don't add
+ /** When expanding the options collection by setting the length don't add
* an empty text node. */
- @BrowserFeature({CHROME, IE})
- JS_SELECT_OPTIONS_DONT_ADD_EMPTY_TEXT_CHILD_WHEN_EXPANDING,
+ @BrowserFeature(FF60)
+ JS_SELECT_OPTIONS_ADD_EMPTY_TEXT_CHILD_WHEN_EXPANDING,
/** Indicates that select.options has a wong class name. */
@BrowserFeature(IE)
JS_SELECT_OPTIONS_HAS_SELECT_CLASS_NAME,
/** Ignore negative value when setting the length. */
- @BrowserFeature({CHROME, FF52})
+ @BrowserFeature(CHROME)
JS_SELECT_OPTIONS_IGNORE_NEGATIVE_LENGTH,
/** The 'in' operator returns always true for HtmlOptionsCollection. */
@@ -1207,14 +1217,14 @@ public enum BrowserVersionFeatures {
JS_SELECT_OPTIONS_NULL_FOR_OUTSIDE,
/** Indicates that select.options.remove ignores the call if index is too large. */
- @BrowserFeature(CHROME)
+ @BrowserFeature({CHROME, FF68})
JS_SELECT_OPTIONS_REMOVE_IGNORE_IF_INDEX_NEGATIVE,
/** Indicates that select.options.remove ignores the call if index is too large. */
- @BrowserFeature({CHROME, IE})
+ @BrowserFeature({CHROME, FF68, IE})
JS_SELECT_OPTIONS_REMOVE_IGNORE_IF_INDEX_TOO_LARGE,
- /** Indicates that select.options[i] throws an exception if the requested index is neagtive. */
+ /** Indicates that select.options[i] throws an exception if the requested index is negative. */
@BrowserFeature(IE)
JS_SELECT_OPTIONS_REMOVE_THROWS_IF_NEGATIV,
@@ -1240,7 +1250,7 @@ public enum BrowserVersionFeatures {
JS_STYLESHEETLIST_ACTIVE_ONLY,
/** Indicates if style.setProperty ignores case when determining the priority. */
- @BrowserFeature({CHROME, IE})
+ @BrowserFeature({CHROME, FF68, IE})
JS_STYLE_SET_PROPERTY_IMPORTANT_IGNORES_CASE,
/** IE supports accessing unsupported style elements via getter
@@ -1249,10 +1259,6 @@ public enum BrowserVersionFeatures {
@BrowserFeature(IE)
JS_STYLE_UNSUPPORTED_PROPERTY_GETTER,
- /** Indicates if style properties are always in lower case. */
- @BrowserFeature({CHROME, FF60, IE})
- JS_STYLE_VALUES_LOWERCASE,
-
/** Indicates wordSpacing support percent values. */
@BrowserFeature(FF)
JS_STYLE_WORD_SPACING_ACCEPTS_PERCENT,
@@ -1353,6 +1359,10 @@ public enum BrowserVersionFeatures {
@BrowserFeature({CHROME, FF})
JS_TYPE_ACCEPTS_ARBITRARY_VALUES,
+ /** Setting the property valign converts to lowercase. */
+ @BrowserFeature(IE)
+ JS_VALIGN_CONVERTS_TO_LOWERCASE,
+
/** Allow inheriting parent constants
* in {@link com.gargoylesoftware.htmlunit.javascript.host.event.WebGLContextEvent}. */
@BrowserFeature({CHROME, FF})
@@ -1389,12 +1399,6 @@ public enum BrowserVersionFeatures {
@BrowserFeature(IE)
JS_WINDOW_FRAME_BY_ID_RETURNS_WINDOW,
- /**
- * Difference of window.outer/inner height is 89.
- */
- @BrowserFeature(CHROME)
- JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_133,
-
/**
* Difference of window.outer/inner height is 63.
*/
@@ -1402,10 +1406,16 @@ public enum BrowserVersionFeatures {
JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_63,
/**
- * Difference of window.outer/inner height is 94.
+ * Difference of window.outer/inner height is 86.
*/
@BrowserFeature(FF)
- JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_94,
+ JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_86,
+
+ /**
+ * Difference of window.outer/inner height is 92.
+ */
+ @BrowserFeature(CHROME)
+ JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_92,
/** Window.getSelection returns null, if the window is not visible. */
@BrowserFeature(FF)
@@ -1447,6 +1457,10 @@ public enum BrowserVersionFeatures {
@BrowserFeature(IE)
JS_XML_SUPPORT_VIA_ACTIVEXOBJECT,
+ /** {@code XSLTProcessor.transformToDocument} supports output indent attribute. */
+ @BrowserFeature(CHROME)
+ JS_XSLT_TRANSFORM_INDENT,
+
/** With special keys [in .type(int)], should we trigger onkeypress event or not. */
@BrowserFeature(FF)
KEYBOARD_EVENT_SPECIAL_KEYPRESS,
@@ -1493,7 +1507,7 @@ public enum BrowserVersionFeatures {
RESETINPUT_DEFAULT_VALUE_IF_VALUE_NOT_DEFINED,
/** The default display style of slot is 'content'. */
- @BrowserFeature({CHROME, FF60})
+ @BrowserFeature({CHROME, FF})
SLOT_CONTENTS,
/** Indicates that string.includes() is supported. */
@@ -1556,6 +1570,14 @@ public enum BrowserVersionFeatures {
@BrowserFeature({CHROME, FF})
URL_MISSING_SLASHES,
+ /** Set the origin property for web socket events. */
+ @BrowserFeature({CHROME, FF})
+ WEBSOCKET_ORIGIN_SET,
+
+ /** Set the srcElement property for web socket events. */
+ @BrowserFeature({CHROME, FF68, IE})
+ WEBSOCKET_SRC_ELEMENT_SET,
+
/** Execute window events. */
@BrowserFeature(IE)
WINDOW_EXECUTE_EVENTS,
@@ -1565,7 +1587,7 @@ public enum BrowserVersionFeatures {
XHR_ALL_RESPONSE_HEADERS_APPEND_SEPARATOR,
/** XMLHttpRequest.getAllResponseHeaders() uses only Lf as separator. */
- @BrowserFeature({FF60, IE})
+ @BrowserFeature({FF, IE})
XHR_ALL_RESPONSE_HEADERS_SEPARATE_BY_LF,
/** XMLHttpRequest triggers the opened event at the beginning of the send method again. */
@@ -1594,13 +1616,9 @@ public enum BrowserVersionFeatures {
XHR_OPEN_ALLOW_EMTPY_URL,
/** Indicates that the content charset is used for response parsing. */
- @BrowserFeature(FF)
+ @BrowserFeature({FF, CHROME})
XHR_USE_CONTENT_CHARSET,
- /** Indicates that the request uses the charset from the requesting page. */
- @BrowserFeature(CHROME)
- XHR_USE_DEFAULT_CHARSET_FROM_PAGE,
-
/** Indicates that the "*" pattern is allowed when withCredential is enabled. */
@BrowserFeature(IE)
XHR_WITHCREDENTIALS_ALLOW_ORIGIN_ALL,
diff --git a/src/main/java/com/gargoylesoftware/htmlunit/Cache.java b/src/main/java/com/gargoylesoftware/htmlunit/Cache.java
index f95a84bc7bb..32f955de295 100644
--- a/src/main/java/com/gargoylesoftware/htmlunit/Cache.java
+++ b/src/main/java/com/gargoylesoftware/htmlunit/Cache.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002-2019 Gargoyle Software Inc.
+ * Copyright (c) 2002-2020 Gargoyle Software Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -46,7 +47,8 @@ public class Cache implements Serializable {
private int maxSize_ = 40;
private static final Pattern DATE_HEADER_PATTERN = Pattern.compile("-?\\d+");
- private static final long DELAY = 10 * org.apache.commons.lang3.time.DateUtils.MILLIS_PER_MINUTE;
+ static final long DELAY = 10 * org.apache.commons.lang3.time.DateUtils.MILLIS_PER_MINUTE;
+
/**
* The map which holds the cached responses. Note that when keying on URLs, we key on the string version
* of the URLs, rather than on the URLs themselves. This is done for performance, because a) the
@@ -110,6 +112,42 @@ public int hashCode() {
public void touch() {
lastAccess_ = System.currentTimeMillis();
}
+
+ /**
+ *