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