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 java.io.File;
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.io.Serializable;
21  import java.net.InetAddress;
22  import java.net.URL;
23  import java.security.KeyStore;
24  import java.security.KeyStoreException;
25  import java.security.NoSuchAlgorithmException;
26  import java.security.cert.CertificateException;
27  
28  import javax.net.ssl.SSLContext;
29  
30  import org.apache.commons.io.FileUtils;
31  
32  /**
33   * Represents options of a {@link WebClient}.
34   *
35   * @author Ahmed Ashour
36   * @author Marc Guillemot
37   * @author Madis Pärn
38   * @author Ronald Brill
39   */
40  @SuppressWarnings("PMD.TooManyFields")
41  public class WebClientOptions implements Serializable {
42  
43      /** 1920. */
44      private static final int DEFAULT_SCRREN_WIDTH = 1920;
45      /** 1080. */
46      private static final int DEFAULT_SCRREN_HEIGHT = 1080;
47  
48      private boolean javaScriptEnabled_ = true;
49      private boolean cssEnabled_ = true;
50      private boolean printContentOnFailingStatusCode_ = true;
51      private boolean throwExceptionOnFailingStatusCode_ = true;
52      private boolean throwExceptionOnScriptError_ = true;
53      private boolean popupBlockerEnabled_;
54      private boolean isRedirectEnabled_ = true;
55      private File tempFileDirectory_;
56  
57      private transient KeyStore sslClientCertificateStore_;
58      private char[] sslClientCertificatePassword_;
59      private transient KeyStore sslTrustStore_;
60      private String[] sslClientProtocols_;
61      private String[] sslClientCipherSuites_;
62  
63      private transient SSLContext sslContext_;
64      private boolean useInsecureSSL_; // default is secure SSL
65      private String sslInsecureProtocol_;
66  
67      private boolean doNotTrackEnabled_;
68      private String homePage_ = "https://www.htmlunit.org/";
69      private ProxyConfig proxyConfig_;
70      private int timeout_ = 90_000; // like Firefox 16 default's value for network.http.connection-timeout
71      private long connectionTimeToLive_ = -1; // HttpClient default
72  
73      private boolean fileProtocolForXMLHttpRequestsAllowed_;
74  
75      private int maxInMemory_ = 500 * 1024;
76      private int historySizeLimit_ = 50;
77      private int historyPageCacheLimit_ = Integer.MAX_VALUE;
78      private InetAddress localAddress_;
79      private boolean downloadImages_;
80      private int screenWidth_ = DEFAULT_SCRREN_WIDTH;
81      private int screenHeight_ = DEFAULT_SCRREN_HEIGHT;
82  
83      private boolean geolocationEnabled_;
84      private Geolocation geolocation_;
85  
86      private int nekoReaderBufferSize_ = -1;
87  
88      private boolean webSocketEnabled_ = true;
89      private int webSocketMaxTextMessageSize_ = -1;
90      private int webSocketMaxTextMessageBufferSize_ = -1;
91      private int webSocketMaxBinaryMessageSize_ = -1;
92      private int webSocketMaxBinaryMessageBufferSize_ = -1;
93  
94      private boolean isFetchPolyfillEnabled_;
95  
96      /**
97       * Sets the SSLContext; if this is set it is used and some other settings are ignored
98       * (protocol, keyStore, keyStorePassword, trustStore, sslClientCertificateStore, sslClientCertificatePassword).
99       * <p>This property is transient (because SSLContext is not serializable)
100      * @param sslContext the SSLContext, {@code null} to use for default value
101      */
102     public void setSSLContext(final SSLContext sslContext) {
103         sslContext_ = sslContext;
104     }
105 
106     /**
107      * Gets the SSLContext; if this is set this is used and some other settings are ignored
108      * (protocol, keyStore, keyStorePassword, trustStore, sslClientCertificateStore, sslClientCertificatePassword).
109      * <p>This property is transient (because SSLContext is not serializable)
110      * @return the SSLContext
111      */
112     public SSLContext getSSLContext() {
113         return sslContext_;
114     }
115 
116     /**
117      * If set to {@code true}, the client will accept connections to any host, regardless of
118      * whether they have valid certificates or not. This is especially useful when you are trying to
119      * connect to a server with expired or corrupt certificates.
120      * @param useInsecureSSL whether or not to use insecure SSL
121      */
122     public void setUseInsecureSSL(final boolean useInsecureSSL) {
123         useInsecureSSL_ = useInsecureSSL;
124     }
125 
126     /**
127      * Indicates if insecure SSL should be used.
128      * @return {@code true} if insecure SSL should be used. Default is {@code false}.
129      */
130     public boolean isUseInsecureSSL() {
131         return useInsecureSSL_;
132     }
133 
134     /**
135      * Sets whether or not redirections will be followed automatically on receipt of a redirect
136      * status code from the server.
137      * @param enabled true to enable automatic redirection
138      */
139     public void setRedirectEnabled(final boolean enabled) {
140         isRedirectEnabled_ = enabled;
141     }
142 
143     /**
144      * Returns the directory to be used for storing the response content in
145      * a temporary file see {@link #getMaxInMemory()}.
146      * @return the directory to be used for storing temp files or null to use the system default
147      */
148     public File getTempFileDirectory() {
149         return tempFileDirectory_;
150     }
151 
152     /**
153      * Sets the directory to be used for storing the response content in
154      * a temporary file see {@link #setMaxInMemory(int)}.
155      * If the given directory does not exist, this creates it.
156      *
157      * @param tempFileDirectory the directory to be used or null to use the system default
158      * @throws IOException in case of error
159      */
160     public void setTempFileDirectory(final File tempFileDirectory) throws IOException {
161         if (tempFileDirectory != null) {
162             if (tempFileDirectory.exists() && !tempFileDirectory.isDirectory()) {
163                 throw new IllegalArgumentException("The provided file '" + tempFileDirectory
164                         + "' points to an already existing file");
165             }
166 
167             if (!tempFileDirectory.exists()) {
168                 FileUtils.forceMkdir(tempFileDirectory);
169             }
170         }
171         tempFileDirectory_ = tempFileDirectory;
172     }
173 
174     /**
175      * Returns whether or not redirections will be followed automatically on receipt of
176      * a redirect status code from the server.
177      * @return true if automatic redirection is enabled
178      */
179     public boolean isRedirectEnabled() {
180         return isRedirectEnabled_;
181     }
182 
183     /**
184      * Sets the SSL client certificate {@link KeyStore} to use.
185      * <p>
186      * If the web server requires Renegotiation, you have to set system property
187      * "sun.security.ssl.allowUnsafeRenegotiation" to true, as hinted in
188      * <a href="http://www.oracle.com/technetwork/java/javase/documentation/tlsreadme2-176330.html">
189      * TLS Renegotiation Issue</a>.
190      * <p>
191      * In some cases the impl seems to pick old certificates from the {@link KeyStore}. To avoid
192      * that, wrap your {@link KeyStore} inside your own {@link KeyStore} impl and filter out outdated
193      * certificates.
194      * <p>This property is transient (because KeyStore is not serializable)
195      *
196      * @param keyStore {@link KeyStore} to use
197      * @param keyStorePassword the keystore password
198      */
199     public void setSSLClientCertificateKeyStore(final KeyStore keyStore, final char[] keyStorePassword) {
200         sslClientCertificateStore_ = keyStore;
201         sslClientCertificatePassword_ = keyStorePassword;
202     }
203 
204     /**
205      * Sets the SSL client certificate to use.
206      * The needed parameters are used to construct a {@link java.security.KeyStore}.
207      * <p>
208      * If the web server requires Renegotiation, you have to set system property
209      * "sun.security.ssl.allowUnsafeRenegotiation" to true, as hinted in
210      * <a href="http://www.oracle.com/technetwork/java/javase/documentation/tlsreadme2-176330.html">
211      * TLS Renegotiation Issue</a>.
212      * <p>This property is transient (because KeyStore is not serializable)
213      *
214      * @param keyStoreUrl the URL which locates the certificate {@link KeyStore}
215      * @param keyStorePassword the certificate {@link KeyStore} password
216      * @param keyStoreType the type of certificate {@link KeyStore}, usually {@code jks} or {@code pkcs12}
217      *
218      */
219     public void setSSLClientCertificateKeyStore(final URL keyStoreUrl, final String keyStorePassword,
220             final String keyStoreType) {
221         try (InputStream is = keyStoreUrl.openStream()) {
222             sslClientCertificateStore_ = getKeyStore(is, keyStorePassword, keyStoreType);
223             sslClientCertificatePassword_ = keyStorePassword == null ? null : keyStorePassword.toCharArray();
224         }
225         catch (final Exception e) {
226             throw new RuntimeException(e);
227         }
228     }
229 
230     /**
231      * Sets the SSL client certificate {@link KeyStore} to use. The parameters are used to
232      * construct the {@link KeyStore}.
233      * <p>
234      * If the web server requires Renegotiation, you have to set system property
235      * "sun.security.ssl.allowUnsafeRenegotiation" to true, as hinted in
236      * <a href="http://www.oracle.com/technetwork/java/javase/documentation/tlsreadme2-176330.html">
237      * TLS Renegotiation Issue</a>.
238      * <p>
239      * In some cases the impl seems to pick old certificates from the {@link KeyStore}. To avoid
240      * that, wrap your {@link KeyStore} inside your own {@link KeyStore} impl and filter out outdated
241      * certificates. Provide the {@link KeyStore} to the options instead of the input stream.
242      *
243      * @param keyStoreInputStream the input stream which represents the {@link KeyStore} holding the certificates
244      * @param keyStorePassword the {@link KeyStore} password
245      * @param keyStoreType the type of {@link KeyStore}, usually {@code jks} or {@code pkcs12}
246      */
247     public void setSSLClientCertificateKeyStore(final InputStream keyStoreInputStream,
248             final String keyStorePassword, final String keyStoreType) {
249         try {
250             setSSLClientCertificateKeyStore(
251                     getKeyStore(keyStoreInputStream, keyStorePassword, keyStoreType),
252                     keyStorePassword.toCharArray());
253         }
254         catch (final Exception e) {
255             throw new RuntimeException(e);
256         }
257     }
258 
259     /**
260      * Gets the SSLClientCertificateStore.
261      * <p>This property is transient (because KeyStore is not serializable)
262      *
263      * @return the KeyStore for use on SSL connections
264      */
265     public KeyStore getSSLClientCertificateStore() {
266         return sslClientCertificateStore_;
267     }
268 
269     /**
270      * Gets the SSLClientCertificatePassword.
271      * @return the password
272      */
273     public char[] getSSLClientCertificatePassword() {
274         return sslClientCertificatePassword_;
275     }
276 
277     /**
278      * Gets the protocol versions enabled for use on SSL connections.
279      * @return the protocol versions enabled for use on SSL connections
280      * @see #setSSLClientProtocols(String...)
281      */
282     public String[] getSSLClientProtocols() {
283         return sslClientProtocols_;
284     }
285 
286     /**
287      * Sets the protocol versions enabled for use on SSL connections,
288      * {@code null} to use default ones.
289      *
290      * @param sslClientProtocols the protocol versions
291      * @see javax.net.ssl.SSLSocket#setEnabledProtocols(String[])
292      * @see #getSSLClientProtocols()
293      */
294     public void setSSLClientProtocols(final String... sslClientProtocols) {
295         sslClientProtocols_ = sslClientProtocols;
296     }
297 
298     /**
299      * Gets the cipher suites enabled for use on SSL connections.
300      * @return the cipher suites enabled for use on SSL connections
301      * @see #setSSLClientCipherSuites(String...)
302      */
303     public String[] getSSLClientCipherSuites() {
304         return sslClientCipherSuites_;
305     }
306 
307     /**
308      * Sets the cipher suites enabled for use on SSL connections,
309      * {@code null} to use default ones.
310      *
311      * @param sslClientCipherSuites the cipher suites
312      * @see javax.net.ssl.SSLSocket#setEnabledCipherSuites(String[])
313      * @see #getSSLClientCipherSuites()
314      */
315     public void setSSLClientCipherSuites(final String... sslClientCipherSuites) {
316         sslClientCipherSuites_ = sslClientCipherSuites;
317     }
318 
319     /**
320      * Enables/disables JavaScript support. By default, this property is enabled.
321      *
322      * @param enabled {@code true} to enable JavaScript support
323      */
324     public void setJavaScriptEnabled(final boolean enabled) {
325         javaScriptEnabled_ = enabled;
326     }
327 
328     /**
329      * Returns {@code true} if JavaScript is enabled and the script engine was loaded successfully.
330      *
331      * @return {@code true} if JavaScript is enabled
332      */
333     public boolean isJavaScriptEnabled() {
334         return javaScriptEnabled_;
335     }
336 
337     /**
338      * Enables/disables CSS support. By default, this property is enabled.
339      * If disabled HtmlUnit will not download the linked css files and also
340      * not triggered the associated onload/onerror events.
341      *
342      * @param enabled {@code true} to enable CSS support
343      */
344     public void setCssEnabled(final boolean enabled) {
345         cssEnabled_ = enabled;
346     }
347 
348     /**
349      * Returns {@code true} if CSS is enabled.
350      *
351      * @return {@code true} if CSS is enabled
352      */
353     public boolean isCssEnabled() {
354         return cssEnabled_;
355     }
356 
357     /**
358      * Enable/disable the popup window blocker. By default, the popup blocker is disabled, and popup
359      * windows are allowed. When set to {@code true}, <code>window.open()</code> has no effect and
360      * returns {@code null}.
361      *
362      * @param enabled {@code true} to enable the popup window blocker
363      */
364     public void setPopupBlockerEnabled(final boolean enabled) {
365         popupBlockerEnabled_ = enabled;
366     }
367 
368     /**
369      * Returns {@code true} if the popup window blocker is enabled.
370      *
371      * @return {@code true} if the popup window blocker is enabled
372      */
373     public boolean isPopupBlockerEnabled() {
374         return popupBlockerEnabled_;
375     }
376 
377     /**
378      * Enables/disables "Do Not Track" support. By default, this property is disabled.
379      *
380      * @param enabled {@code true} to enable "Do Not Track" support
381      */
382     public void setDoNotTrackEnabled(final boolean enabled) {
383         doNotTrackEnabled_ = enabled;
384     }
385 
386     /**
387      * Returns {@code true} if "Do Not Track" is enabled.
388      *
389      * @return {@code true} if "Do Not Track" is enabled
390      */
391     public boolean isDoNotTrackEnabled() {
392         return doNotTrackEnabled_;
393     }
394 
395     /**
396      * Specify whether or not the content of the resulting document will be
397      * printed to the console in the event of a failing response code.
398      * Successful response codes are in the range 200-299. The default is true.
399      *
400      * @param enabled True to enable this feature
401      */
402     public void setPrintContentOnFailingStatusCode(final boolean enabled) {
403         printContentOnFailingStatusCode_ = enabled;
404     }
405 
406     /**
407      * Returns {@code true} if the content of the resulting document will be printed to
408      * the console in the event of a failing response code.
409      *
410      * @return {@code true} if the content of the resulting document will be printed to
411      *         the console in the event of a failing response code
412      * @see #setPrintContentOnFailingStatusCode
413      */
414     public boolean isPrintContentOnFailingStatusCode() {
415         return printContentOnFailingStatusCode_;
416     }
417 
418     /**
419      * Specify whether or not an exception will be thrown in the event of a
420      * failing status code. Successful status codes are in the range 200-299.
421      * The default is true.
422      *
423      * @param enabled {@code true} to enable this feature
424      */
425     public void setThrowExceptionOnFailingStatusCode(final boolean enabled) {
426         throwExceptionOnFailingStatusCode_ = enabled;
427     }
428 
429     /**
430      * Returns {@code true} if an exception will be thrown in the event of a failing response code.
431      * @return {@code true} if an exception will be thrown in the event of a failing response code
432      * @see #setThrowExceptionOnFailingStatusCode
433      */
434     public boolean isThrowExceptionOnFailingStatusCode() {
435         return throwExceptionOnFailingStatusCode_;
436     }
437 
438     /**
439      * Indicates if an exception should be thrown when a script execution fails
440      * (the default) or if it should be caught and just logged to allow page
441      * execution to continue.
442      * @return {@code true} if an exception is thrown on script error (the default)
443      */
444     public boolean isThrowExceptionOnScriptError() {
445         return throwExceptionOnScriptError_;
446     }
447 
448     /**
449      * Changes the behavior of this webclient when a script error occurs.
450      * @param enabled indicates if exception should be thrown or not
451      */
452     public void setThrowExceptionOnScriptError(final boolean enabled) {
453         throwExceptionOnScriptError_ = enabled;
454     }
455 
456     /**
457      * Returns the client's current homepage.
458      * @return the client's current homepage
459      */
460     public String getHomePage() {
461         return homePage_;
462     }
463 
464     /**
465      * Sets the client's homepage.
466      * @param homePage the new homepage URL
467      */
468     public void setHomePage(final String homePage) {
469         homePage_ = homePage;
470     }
471 
472     /**
473      * Returns the proxy configuration for this client.
474      * @return the proxy configuration for this client
475      */
476     public ProxyConfig getProxyConfig() {
477         return proxyConfig_;
478     }
479 
480     /**
481      * Sets the proxy configuration for this client.
482      * @param proxyConfig the proxy configuration for this client
483      */
484     public void setProxyConfig(final ProxyConfig proxyConfig) {
485         WebAssert.notNull("proxyConfig", proxyConfig);
486         proxyConfig_ = proxyConfig;
487     }
488 
489     /**
490      * Gets the timeout value for the {@link WebConnection}.
491      * The default timeout is 90 seconds.
492      * @return the timeout value in milliseconds
493      * @see WebClientOptions#setTimeout(int)
494      */
495     public int getTimeout() {
496         return timeout_;
497     }
498 
499     /**
500      * <p>Sets the timeout of the {@link WebConnection}. Set to zero for an infinite wait.</p>
501      *
502      * <p>Note: The timeout is used twice. The first is for making the socket connection, the second is
503      * for data retrieval. If the time is critical you must allow for twice the time specified here.</p>
504      *
505      * @param timeout the value of the timeout in milliseconds
506      */
507     public void setTimeout(final int timeout) {
508         timeout_ = timeout;
509     }
510 
511     /**
512      * Gets the connTimeToLive value for the HttpClient connection pool.
513      *
514      * @return the timeout value in milliseconds
515      */
516     public long getConnectionTimeToLive() {
517         return connectionTimeToLive_;
518     }
519 
520     /**
521      * Sets the connTimeToLive of the HttpClient connection pool.
522      * Use this if you are working with web pages behind a DNS based load balancer.
523      * Set to -1 (default) for disabling this timeout.
524      *
525      * @param connectionTimeToLive the value of the timeout in milliseconds
526      */
527     public void setConnectionTimeToLive(final long connectionTimeToLive) {
528         connectionTimeToLive_ = connectionTimeToLive;
529     }
530 
531     /**
532      * Sets the SSL protocol, used only when {@link #setUseInsecureSSL(boolean)} is set to {@code true}.
533      * @param sslInsecureProtocol the SSL protocol for insecure SSL connections,
534      *      {@code null} to use for default value
535      */
536     public void setSSLInsecureProtocol(final String sslInsecureProtocol) {
537         sslInsecureProtocol_ = sslInsecureProtocol;
538     }
539 
540     /**
541      * Gets the SSL protocol, to be used only when {@link #setUseInsecureSSL(boolean)} is set to {@code true}.
542      * @return the SSL protocol for insecure SSL connections
543      */
544     public String getSSLInsecureProtocol() {
545         return sslInsecureProtocol_;
546     }
547 
548     /**
549      * Sets the SSL server certificate trust store. All server certificates will be validated against
550      * this trust store.
551      * <p>This property is transient (because KeyStore is not serializable)
552      * <p>The needed parameters are used to construct a {@link java.security.KeyStore}.
553      *
554      * @param sslTrustStoreUrl the URL which locates the trust store
555      * @param sslTrustStorePassword the trust store password
556      * @param sslTrustStoreType the type of trust store, usually {@code jks} or {@code pkcs12}
557      */
558     public void setSSLTrustStore(final URL sslTrustStoreUrl, final String sslTrustStorePassword,
559             final String sslTrustStoreType) {
560         try (InputStream is = sslTrustStoreUrl.openStream()) {
561             sslTrustStore_ = getKeyStore(is, sslTrustStorePassword, sslTrustStoreType);
562         }
563         catch (final Exception e) {
564             throw new RuntimeException(e);
565         }
566     }
567 
568     void setSSLTrustStore(final KeyStore keyStore) {
569         sslTrustStore_ = keyStore;
570     }
571 
572     /**
573      * Gets the SSL TrustStore.
574      * <p>This property is transient (because KeyStore is not serializable)
575      * @return the SSL TrustStore for insecure SSL connections
576      */
577     public KeyStore getSSLTrustStore() {
578         return sslTrustStore_;
579     }
580 
581     private static KeyStore getKeyStore(final InputStream inputStream, final String keystorePassword,
582             final String keystoreType)
583                     throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
584         if (inputStream == null) {
585             return null;
586         }
587 
588         final KeyStore keyStore = KeyStore.getInstance(keystoreType);
589         final char[] passwordChars = keystorePassword == null ? null : keystorePassword.toCharArray();
590         keyStore.load(inputStream, passwordChars);
591         return keyStore;
592     }
593 
594     /**
595      * Returns the maximum bytes to have in memory, after which the content is saved to a temporary file.
596      * Default is 500 * 1024.
597      * @return the maximum bytes in memory
598      */
599     public int getMaxInMemory() {
600         return maxInMemory_;
601     }
602 
603     /**
604      * Sets the maximum bytes to have in memory, after which the content is saved to a temporary file.
605      * Set this to zero or -1 to deactivate the saving at all.
606      * @param maxInMemory maximum bytes in memory
607      */
608     public void setMaxInMemory(final int maxInMemory) {
609         maxInMemory_ = maxInMemory;
610     }
611 
612     /**
613      * Returns the maximum number of {@link Page pages} kept in {@link WebWindow#getHistory()}.
614      * @return the maximum number of pages in history
615      */
616     public int getHistorySizeLimit() {
617         return historySizeLimit_;
618     }
619 
620     /**
621      * Sets the History size limit. HtmlUnit uses SoftReferences&lt;Page&gt; for
622      * storing the pages that are part of the history. If you like to fine tune this
623      * you can use {@link #setHistoryPageCacheLimit(int)} to limit the number of page references
624      * stored by the history.
625      * @param historySizeLimit maximum number of pages in history
626      */
627     public void setHistorySizeLimit(final int historySizeLimit) {
628         historySizeLimit_ = historySizeLimit;
629     }
630 
631     /**
632      * Returns the maximum number of {@link Page pages} to cache in history.
633      * @return the maximum number of pages to cache in history
634      */
635     public int getHistoryPageCacheLimit() {
636         return historyPageCacheLimit_;
637     }
638 
639     /**
640      * Sets the maximum number of {@link Page pages} to cache in history.
641      * If this value is smaller than the {{@link #getHistorySizeLimit()} than
642      * HtmlUnit will only use soft references for the first historyPageCacheLimit
643      * entries in the history. For older entries only the url is saved; the page
644      * will be (re)retrieved on demand.
645      * @param historyPageCacheLimit maximum number of pages to cache in history
646      *        default is Integer.MAX_VALUE; negative values are having the same effect
647      *        as setting this to zero.
648      */
649     public void setHistoryPageCacheLimit(final int historyPageCacheLimit) {
650         historyPageCacheLimit_ = historyPageCacheLimit;
651     }
652 
653     /**
654      * Returns local address to be used for request execution.
655      * <p>
656      * On machines with multiple network interfaces, this parameter can be used to select the network interface
657      * from which the connection originates.
658      * <p>
659      * Default: {@code null}
660      *
661      * @return the local address
662      */
663     public InetAddress getLocalAddress() {
664         return localAddress_;
665     }
666 
667     /**
668      * Sets the local address to be used for request execution.
669      * <p>
670      * On machines with multiple network interfaces, this parameter can be used to select the network interface
671      * from which the connection originates.
672      *
673      * @param localAddress the local address
674      */
675     public void setLocalAddress(final InetAddress localAddress) {
676         localAddress_ = localAddress;
677     }
678 
679     /**
680      * Sets whether to automatically download images by default, or not.
681      * @param downloadImages whether to automatically download images by default, or not
682      */
683     public void setDownloadImages(final boolean downloadImages) {
684         downloadImages_ = downloadImages;
685     }
686 
687     /**
688      * Returns whether to automatically download images by default, or not.
689      * @return whether to automatically download images by default, or not.
690      */
691     public boolean isDownloadImages() {
692         return downloadImages_;
693     }
694 
695     /**
696      * Sets the screen width.
697      *
698      * @param screenWidth the screen width
699      */
700     public void setScreenWidth(final int screenWidth) {
701         screenWidth_ = screenWidth;
702     }
703 
704     /**
705      * Returns the screen width.
706      *
707      * @return the screen width
708      */
709     public int getScreenWidth() {
710         return screenWidth_;
711     }
712 
713     /**
714      * Sets the screen height.
715      *
716      * @param screenHeight the screen height
717      */
718     public void setScreenHeight(final int screenHeight) {
719         screenHeight_ = screenHeight;
720     }
721 
722     /**
723      * Returns the screen height.
724      *
725      * @return the screen height
726      */
727     public int getScreenHeight() {
728         return screenHeight_;
729     }
730 
731     /**
732      * @return the Neko Html parser reader buffer size
733      */
734     public int getNekoReaderBufferSize() {
735         return nekoReaderBufferSize_;
736     }
737 
738     /**
739      * Sets the Neko Html parser reader buffer size.
740      *
741      * @param nekoReaderBufferSize the new value
742      */
743     public void setNekoReaderBufferSize(final int nekoReaderBufferSize) {
744         nekoReaderBufferSize_ = nekoReaderBufferSize;
745     }
746 
747 
748     /**
749      * Enables/disables WebSocket support. By default, this property is enabled.
750      *
751      * @param enabled {@code true} to enable WebSocket support
752      */
753     public void setWebSocketEnabled(final boolean enabled) {
754         webSocketEnabled_ = enabled;
755     }
756 
757     /**
758      * Returns {@code true} if WebSockets are enabled.
759      *
760      * @return {@code true} if WebSockets are enabled
761      */
762     public boolean isWebSocketEnabled() {
763         return webSocketEnabled_;
764     }
765 
766     /**
767      * @return the WebSocket maxTextMessageSize
768      */
769     public int getWebSocketMaxTextMessageSize() {
770         return webSocketMaxTextMessageSize_;
771     }
772 
773     /**
774      * Sets the WebSocket maxTextMessageSize.
775      *
776      * @param webSocketMaxTextMessageSize the new value
777      */
778     public void setWebSocketMaxTextMessageSize(final int webSocketMaxTextMessageSize) {
779         webSocketMaxTextMessageSize_ = webSocketMaxTextMessageSize;
780     }
781 
782     /**
783      * @return the WebSocket maxTextMessageBufferSize
784      */
785     public int getWebSocketMaxTextMessageBufferSize() {
786         return webSocketMaxTextMessageBufferSize_;
787     }
788 
789     /**
790      * Sets the WebSocket maxTextMessageBufferSize.
791      *
792      * @param webSocketMaxTextMessageBufferSize the new value
793      */
794     public void setWebSocketMaxTextMessageBufferSize(final int webSocketMaxTextMessageBufferSize) {
795         webSocketMaxTextMessageBufferSize_ = webSocketMaxTextMessageBufferSize;
796     }
797 
798     /**
799      * @return the WebSocket maxTextMessageSize
800      */
801     public int getWebSocketMaxBinaryMessageSize() {
802         return webSocketMaxBinaryMessageSize_;
803     }
804 
805     /**
806      * Sets the WebSocket maxBinaryMessageSize.
807      *
808      * @param webSocketMaxBinaryMessageSize the new value
809      */
810     public void setWebSocketMaxBinaryMessageSize(final int webSocketMaxBinaryMessageSize) {
811         webSocketMaxBinaryMessageSize_ = webSocketMaxBinaryMessageSize;
812     }
813 
814     /**
815      * @return the WebSocket maxBinaryMessageBufferSize
816      */
817     public int getWebSocketMaxBinaryMessageBufferSize() {
818         return webSocketMaxBinaryMessageBufferSize_;
819     }
820 
821     /**
822      * Sets the WebSocket maxBinaryMessageBufferSize.
823      *
824      * @param webSocketMaxBinaryMessageBufferSize the new value
825      */
826     public void setWebSocketMaxBinaryMessageBufferSize(final int webSocketMaxBinaryMessageBufferSize) {
827         webSocketMaxBinaryMessageBufferSize_ = webSocketMaxBinaryMessageBufferSize;
828     }
829 
830     /**
831      * Sets whether or not fetch polyfill should be used.
832      * @param enabled true to enable fetch polyfill
833      */
834     public void setFetchPolyfillEnabled(final boolean enabled) {
835         isFetchPolyfillEnabled_ = enabled;
836     }
837 
838     /**
839      * @return true if the fetch api polyfill is enabled
840      */
841     public boolean isFetchPolyfillEnabled() {
842         return isFetchPolyfillEnabled_;
843     }
844 
845     /**
846      * Enables/disables Geolocation support. By default, this property is disabled.
847      *
848      * @param enabled {@code true} to enable Geolocation support
849      */
850     public void setGeolocationEnabled(final boolean enabled) {
851         geolocationEnabled_ = enabled;
852     }
853 
854     /**
855      * @return {@code true} if Geolocation is enabled
856      */
857     public boolean isGeolocationEnabled() {
858         return geolocationEnabled_;
859     }
860 
861     /**
862      * @return the {@link Geolocation}
863      */
864     public Geolocation getGeolocation() {
865         return geolocation_;
866     }
867 
868     /**
869      * Sets the {@link Geolocation} to be used.
870      * @param geolocation the new location or null
871      */
872     public void setGeolocation(final Geolocation geolocation) {
873         geolocation_ = geolocation;
874     }
875 
876     /**
877      * Support class for Geolocation.
878      */
879     public static class Geolocation implements Serializable {
880         private final double accuracy_;
881         private final double latitude_;
882         private final double longitude_;
883         private final Double altitude_;
884         private final Double altitudeAccuracy_;
885         private final Double heading_;
886         private final Double speed_;
887 
888         /**
889          * Ctor.
890          *
891          * @param accuracy the accuracy
892          * @param latitude the latitude
893          * @param longitude the longitude
894          * @param altitude the altitude or null
895          * @param altitudeAccuracy the altitudeAccuracy or null
896          * @param heading the heading or null
897          * @param speed the speed or null
898          */
899         public Geolocation(
900                 final double latitude,
901                 final double longitude,
902                 final double accuracy,
903                 final Double altitude,
904                 final Double altitudeAccuracy,
905                 final Double heading,
906                 final Double speed) {
907             latitude_ = latitude;
908             longitude_ = longitude;
909             accuracy_ = accuracy;
910             altitude_ = altitude;
911             altitudeAccuracy_ = altitudeAccuracy;
912             heading_ = heading;
913             speed_ = speed;
914         }
915 
916         /**
917          * @return the accuracy
918          */
919         public double getAccuracy() {
920             return accuracy_;
921         }
922 
923         /**
924          * @return the latitude
925          */
926         public double getLatitude() {
927             return latitude_;
928         }
929 
930         /**
931          * @return the longitude
932          */
933         public double getLongitude() {
934             return longitude_;
935         }
936 
937         /**
938          * @return the longitude
939          */
940         public Double getAltitude() {
941             return altitude_;
942         }
943 
944         /**
945          * @return the altitudeAccuracy
946          */
947         public Double getAltitudeAccuracy() {
948             return altitudeAccuracy_;
949         }
950 
951         /**
952          * @return the heading
953          */
954         public Double getHeading() {
955             return heading_;
956         }
957 
958         /**
959          * @return the speed
960          */
961         public Double getSpeed() {
962             return speed_;
963         }
964     }
965 
966     /**
967      * If set to {@code true}, the client will accept XMLHttpRequests to URL's
968      * using the 'file' protocol. Allowing this introduces security problems and is
969      * therefore not allowed by current browsers. But some browsers have special settings
970      * to open this door; therefore we have this option.
971      * @param fileProtocolForXMLHttpRequestsAllowed whether or not allow (local) file access
972      */
973     public void setFileProtocolForXMLHttpRequestsAllowed(final boolean fileProtocolForXMLHttpRequestsAllowed) {
974         fileProtocolForXMLHttpRequestsAllowed_ = fileProtocolForXMLHttpRequestsAllowed;
975     }
976 
977     /**
978      * Indicates if the client will accept XMLHttpRequests to URL's
979      * using the 'file' protocol.
980      * @return {@code true} if access to local files is allowed.
981      */
982     public boolean isFileProtocolForXMLHttpRequestsAllowed() {
983         return fileProtocolForXMLHttpRequestsAllowed_;
984     }
985 }