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