...19import com.google.common.collect.ImmutableMap;20import com.google.common.reflect.TypeToken;21import org.openqa.selenium.Beta;22import org.openqa.selenium.devtools.Command;23import org.openqa.selenium.devtools.Event;24import org.openqa.selenium.devtools.network.model.AuthChallengeResponse;25import org.openqa.selenium.devtools.network.model.ConnectionType;26import org.openqa.selenium.devtools.network.model.Cookie;27import org.openqa.selenium.devtools.network.model.Cookies;28import org.openqa.selenium.devtools.network.model.DataReceived;29import org.openqa.selenium.devtools.network.model.ErrorReason;30import org.openqa.selenium.devtools.network.model.EventSourceMessageReceived;31import org.openqa.selenium.devtools.network.model.InterceptionId;32import org.openqa.selenium.devtools.network.model.LoadingFailed;33import org.openqa.selenium.devtools.network.model.LoadingFinished;34import org.openqa.selenium.devtools.network.model.RequestId;35import org.openqa.selenium.devtools.network.model.RequestIntercepted;36import org.openqa.selenium.devtools.network.model.RequestPattern;37import org.openqa.selenium.devtools.network.model.RequestWillBeSent;38import org.openqa.selenium.devtools.network.model.ResourceChangedPriority;39import org.openqa.selenium.devtools.network.model.ResponseBody;40import org.openqa.selenium.devtools.network.model.ResponseReceived;41import org.openqa.selenium.devtools.network.model.SearchMatch;42import org.openqa.selenium.devtools.network.model.SignedExchangeReceived;43import org.openqa.selenium.devtools.network.model.WebSocketClosed;44import org.openqa.selenium.devtools.network.model.WebSocketCreated;45import org.openqa.selenium.devtools.network.model.WebSocketFrame;46import org.openqa.selenium.devtools.network.model.WebSocketFrameError;47import java.util.List;48import java.util.Map;49import java.util.Objects;50import java.util.Optional;51/**52 * All available DevTools Network methods and events53 */54@SuppressWarnings("OptionalUsedAsFieldOrParameterType")55public class Network {56 private final static String DOMAIN_NAME = "Network";57 public static Command<Void> clearBrowserCache() {58 return new Command<>(DOMAIN_NAME + ".clearBrowserCache", ImmutableMap.of());59 }60 public static Command<Void> clearBrowserCookies() {61 return new Command<>(DOMAIN_NAME + ".clearBrowserCookies", ImmutableMap.of());62 }63 /**64 * Response to Network.requestIntercepted which either modifies the request to continue with any modifications, or blocks it, or completes it with the provided response bytes.65 * If a network fetch occurs as a result which encounters a redirect an additional Network.requestIntercepted event will be sent with the same InterceptionId.66 * (EXPERIMENTAL)67 *68 * @param interceptionId - Identifier for the intercepted request69 * @param errorReason (Optional) - If set this causes the request to fail with the given reason.70 * Passing Aborted for requests marked with isNavigationRequest also cancels the navigation. Must not be set in response to an authChallenge71 * @param rawResponse (Optional) - If set the requests completes using with the provided base64 encoded raw response, including HTTP status line and headers etc...72 * Must not be set in response to an authChallenge73 * @param url (Optional) - If set the request url will be modified in a way that's not observable by page. Must not be set in response to an authChallenge74 * @param method (Optional) - If set this allows the request method to be overridden. Must not be set in response to an authChallenge75 * @param postData (Optional) - If set this allows postData to be set. Must not be set in response to an authChallenge76 * @param headers (Optional) - If set this allows the request headers to be changed. Must not be set in response to an authChallenge77 * @param authChallengeResponse (Optional) - Response to a requestIntercepted with an authChallenge. Must not be set otherwise78 * @return DevTools Command79 */80 @Beta81 public static Command<Void> continueInterceptedRequest(InterceptionId interceptionId,82 Optional<ErrorReason> errorReason,83 Optional<String> rawResponse,84 Optional<String> url,85 Optional<String> method,86 Optional<String> postData,87 Optional<Map<String, String>> headers,88 Optional<AuthChallengeResponse> authChallengeResponse) {89 Objects.requireNonNull(interceptionId, "interceptionId must be set.");90 final ImmutableMap.Builder<String, Object> params = ImmutableMap.builder();91 params.put("interceptionId", interceptionId.toString());92 errorReason.ifPresent(reason -> params.put("errorReason", errorReason.get().name()));93 rawResponse.ifPresent(string -> params.put("rawResponse", rawResponse.toString()));94 url.ifPresent(string -> params.put("url", url.toString()));95 method.ifPresent(string -> params.put("method", method.toString()));96 postData.ifPresent(string -> params.put("postData", postData.toString()));97 headers.ifPresent(map -> params.put("headers", headers));98 authChallengeResponse.ifPresent(response -> params.put("authChallengeResponse", authChallengeResponse));99 return new Command<>(DOMAIN_NAME + ".continueInterceptedRequest", params.build());100 }101 /**102 * Deletes browser cookies with matching name and url or domain/path pair103 *104 * @param name - Name of the cookies to remove105 * @param url (Optional) - If specified, deletes all the cookies with the given name where domain and path match provided URL106 * @param domain (Optional) - If specified, deletes only cookies with the exact domain.107 * @param path (Optional) - If specified, deletes only cookies with the exact path108 * @return DevTools Command109 */110 public static Command<Void> deleteCookies(String name, Optional<String> url,111 Optional<String> domain, Optional<String> path) {112 Objects.requireNonNull(name, "name must be set.");113 final ImmutableMap.Builder<String, Object> params = ImmutableMap.builder();114 params.put("name", name);115 url.ifPresent(string -> params.put("url", url.toString()));116 domain.ifPresent(string -> params.put("domain", domain.toString()));117 path.ifPresent(string -> params.put("path", path.toString()));118 return new Command<>(DOMAIN_NAME + ".deleteCookies", params.build());119 }120 /**121 * Disables network tracking, prevents network events from being sent to the client.122 *123 * @return DevTools Command124 */125 public static Command<Void> disable() {126 return new Command<>(DOMAIN_NAME + ".disable", ImmutableMap.of());127 }128 /**129 * Activates emulation of network conditions.130 *131 * @param offline - True to emulate internet disconnection.132 * @param latency - Minimum latency from request sent to response headers received (ms).133 * @param downloadThroughput - Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.134 * @param uploadThroughput - Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.135 * @param connectionType (Optional) - The underlying connection technology that the browser is supposedly using.136 * @return DevTools Command137 */138 public static Command<Void> emulateNetworkConditions(boolean offline, double latency,139 double downloadThroughput,140 double uploadThroughput,141 Optional<ConnectionType> connectionType) {142 final ImmutableMap.Builder<String, Object> params = ImmutableMap.builder();143 params.put("offline", offline);144 params.put("latency", latency);145 params.put("downloadThroughput", downloadThroughput);146 params.put("uploadThroughput", uploadThroughput);147 connectionType148 .ifPresent(ConnectionType -> params.put("connectionType", connectionType.get().name()));149 return new Command<>(DOMAIN_NAME + ".emulateNetworkConditions", params.build());150 }151 /**152 * Enables network tracking, network events will now be delivered to the client.153 *154 * @param maxTotalBufferSize (Optional) - Buffer size in bytes to use when preserving network payloads (XHRs, etc).155 * @param maxResourceBufferSize (Optional) - Per-resource buffer size in bytes to use when preserving network payloads (XHRs, etc).156 * @param maxPostDataSize (Optional) - Longest post body size (in bytes) that would be included in requestWillBeSent notification157 * @return DevTools Command158 */159 public static Command<Void> enable(Optional<Integer> maxTotalBufferSize,160 Optional<Integer> maxResourceBufferSize,161 Optional<Integer> maxPostDataSize) {162 final ImmutableMap.Builder<String, Object> params = ImmutableMap.builder();163 maxTotalBufferSize.ifPresent(integer -> params.put("maxTotalBufferSize", integer));164 maxResourceBufferSize.ifPresent(integer -> params.put("maxResourceBufferSize", integer));165 maxPostDataSize.ifPresent(integer -> params.put("maxPostDataSize", integer));166 return new Command<>(DOMAIN_NAME + ".enable", params.build());167 }168 /**169 * Returns all browser cookies. Depending on the backend support, will return detailed cookie information in the cookies field170 *171 * @return Array of Cookies with a "asSeleniumCookies" method172 */173 public static Command<Cookies> getAllCookies() {174 return new Command<>(DOMAIN_NAME + ".getAllCookies", ImmutableMap.of(),175 map("cookies", Cookies.class));176 }177 /**178 * Returns the DER-encoded certificate (EXPERIMENTAL)179 *180 * @param origin Origin to get certificate for181 * @return List of tableNames182 */183 @Beta184 public static Command<List<String>> getCertificate(String origin) {185 Objects.requireNonNull(origin, "origin must be set.");186 return new Command<>(DOMAIN_NAME + ".getCertificate", ImmutableMap.of("origin", origin),187 map("tableNames", new TypeToken<List<String>>() {188 }.getType()));189 }190 /**191 * Returns all browser cookies for the current URL. Depending on the backend support, will return detailed cookie information in the cookies field192 *193 * @param urls (Optional) - The list of URLs for which applicable cookies will be fetched194 * @return Array of cookies195 */196 public static Command<Cookies> getCookies(Optional<List<String>> urls) {197 final ImmutableMap.Builder<String, Object> params = ImmutableMap.builder();198 urls.ifPresent(list -> params.put("urls", urls));199 return new Command<>(DOMAIN_NAME + ".getCookies", params.build(),200 map("cookies", Cookies.class));201 }202 /**203 * Returns content served for the given request204 *205 * @param requestId Identifier of the network request to get content for206 * @return ResponseBody object207 */208 public static Command<ResponseBody> getResponseBody(RequestId requestId) {209 Objects.requireNonNull(requestId, "requestId must be set.");210 return new Command<>(DOMAIN_NAME + ".getResponseBody",211 ImmutableMap.of("requestId", requestId.toString()),212 map("body", ResponseBody.class));213 }214 /**215 * Returns post data sent with the request. Returns an error when no data was sent with the request.216 *217 * @param requestId - Identifier of the network request to get content for.218 * @return DevTools Command with Request body string, omitting files from multipart requests219 */220 public static Command<String> getRequestPostData(RequestId requestId) {221 Objects.requireNonNull(requestId, "requestId must be set.");222 return new Command<>(DOMAIN_NAME + ".getRequestPostData",223 ImmutableMap.of("requestId", requestId.toString()),224 map("postData", String.class));225 }226 /**227 * Returns content served for the given currently intercepted request (EXPERIMENTAL)228 *229 * @param interceptionId - Identifier for the intercepted request to get body for230 * @return ResponseBody object231 */232 @Beta233 public static Command<ResponseBody> getResponseBodyForInterception(234 InterceptionId interceptionId) {235 Objects.requireNonNull(interceptionId.toString(), "interceptionId must be set.");236 return new Command<>(DOMAIN_NAME + ".getResponseBodyForInterception",237 ImmutableMap.of("interceptionId", interceptionId),238 map("body", ResponseBody.class));239 }240 /**241 * Returns a handle to the stream representing the response body. Note that after this command, the intercepted request can't be continued as is -- you either need to cancel it or to provide the response body.242 * The stream only supports sequential read, IO.read will fail if the position is specified (EXPERIMENTAL)243 *244 * @param interceptionId - Identifier for the intercepted request to get body for245 * @return HTTP response body Stream as a String246 */247 @Beta248 public static Command<String> takeResponseBodyForInterceptionAsStream(249 InterceptionId interceptionId) {250 Objects.requireNonNull(interceptionId, "interceptionId must be set.");251 return new Command<>(DOMAIN_NAME + ".takeResponseBodyForInterceptionAsStream",252 ImmutableMap.of("interceptionId", interceptionId),253 map("stream", String.class));254 }255 /**256 * @param requestId - Identifier of XHR to replay257 * @return - DevTools Command258 */259 public static Command<Void> replayXHR(RequestId requestId) {260 Objects.requireNonNull(requestId, "requestId must be set.");261 return new Command<>(DOMAIN_NAME + ".replayXHR", ImmutableMap.of("requestId", requestId.toString()));262 }263 /**264 * Searches for given string in response content (EXPERIMENTAL)265 *266 * @param requestId - Identifier of the network response to search267 * @param query - String to search for.268 * @param caseSensitive - If true, search is case sensitive269 * @param isRegex - If true, treats string parameter as regex270 * @return List of SearchMatch271 */272 @Beta273 public static Command<List<SearchMatch>> searchInResponseBody(RequestId requestId, String query,274 Optional<Boolean> caseSensitive,275 Optional<Boolean> isRegex) {276 Objects.requireNonNull(requestId, "requestId must be set.");277 Objects.requireNonNull(query, "query must be set.");278 final ImmutableMap.Builder<String, Object> params = ImmutableMap.builder();279 params.put("requestId", requestId.toString());280 params.put("query", query);281 caseSensitive.ifPresent(bool -> params.put("caseSensitive", caseSensitive));282 isRegex.ifPresent(bool -> params.put("isRegex", isRegex));283 return new Command<>(DOMAIN_NAME + ".searchInResponseBody", params.build(),284 map("result", new TypeToken<List<SearchMatch>>() {285 }.getType()));286 }287 /**288 * Blocks URLs from loading (EXPERIMENTAL)289 *290 * @param urls - URL patterns to block. Wildcards ('*') are allowed.291 * @return DevTools Command292 */293 @Beta294 public static Command<Void> setBlockedURLs(List<String> urls) {295 Objects.requireNonNull(urls, "urls must be set.");296 return new Command<>(DOMAIN_NAME + ".setBlockedURLs", ImmutableMap.of("urls", urls));297 }298 /**299 * Toggles ignoring of service worker for each request. (EXPERIMENTAL)300 *301 * @param bypass - Bypass service worker and load from network302 * @return - DevTools Command303 */304 @Beta305 public static Command<Void> setBypassServiceWorker(boolean bypass) {306 return new Command<>(DOMAIN_NAME + ".setBypassServiceWorker",307 ImmutableMap.of("bypass", bypass));308 }309 /**310 * Toggles ignoring cache for each request. If true, cache will not be used.311 *312 * @param cacheDisabled - Cache disabled state.313 * @return DevTools Command314 */315 public static Command<Void> setCacheDisabled(boolean cacheDisabled) {316 return new Command<>(DOMAIN_NAME + ".setCacheDisabled",317 ImmutableMap.of("cacheDisabled", cacheDisabled));318 }319 /**320 * implementation using CDP Cookie321 */322 private static Command<Boolean> setCookie(Cookie cookie, Optional<String> url) {323 Objects.requireNonNull(cookie.getName(), "cookieName must be set.");324 Objects.requireNonNull(cookie.getValue(), "cookieValue must be set.");325 final ImmutableMap.Builder<String, Object> params = ImmutableMap.builder();326 params.put("name", cookie.getName());327 params.put("value", cookie.getValue());328 url.ifPresent(string -> params.put("url", url.toString()));329 if (cookie.getDomain() != null) {330 params.put("domain", cookie.getDomain());331 }332 if (cookie.getPath() != null) {333 params.put("path", cookie.getPath());334 }335 params.put("secure", cookie.isSecure());336 params.put("httpOnly", cookie.isHttpOnly());337 if (cookie.getExpires() != 0) {338 params.put("expires", cookie.getExpires());339 }340 return new Command<>(DOMAIN_NAME + ".setCookie", params.build(), map("success", Boolean.class));341 }342 /**343 * Sets a cookie with the given cookie data; may overwrite equivalent cookies if they exist344 *345 * @param cookie - Cookie object where Name and Value are mandatory346 * @param url - The request-URI to associate with the setting of the cookie. This value can affect the default domain and path values of the created cookie347 * @return - Boolean348 */349 public static Command<Boolean> setCookie(org.openqa.selenium.Cookie cookie,350 Optional<String> url) {351 return setCookie(Cookie.fromSeleniumCookie(cookie), url);352 }353 /**354 * (EXPERIMENTAL)355 *356 * @param maxTotalSize - Maximum total buffer size357 * @param maxResourceSize - Maximum per-resource size358 * @return DevTools Command359 */360 @Beta361 public static Command<Void> setDataSizeLimitsForTest(int maxTotalSize, int maxResourceSize) {362 return new Command<>(DOMAIN_NAME + ".setDataSizeLimitsForTest", ImmutableMap363 .of("maxTotalSize", maxTotalSize, "maxResourceSize", maxResourceSize));364 }365 /**366 * Specifies whether to always send extra HTTP headers with the requests from this page.367 *368 * @param headers - Map with extra HTTP headers.369 * @return DevTools Command370 */371 public static Command<Void> setExtraHTTPHeaders(Map<String, String> headers) {372 Objects.requireNonNull(headers, "headers must be set.");373 return new Command<>(DOMAIN_NAME + ".setExtraHTTPHeaders", ImmutableMap.of("headers", headers));374 }375 /**376 * Sets the requests to intercept that match the provided patterns and optionally resource types (EXPERIMENTAL)377 *378 * @param patterns - Requests matching any of these patterns will be forwarded and wait for the corresponding continueInterceptedRequest call.379 * @return DevTools Command380 */381 @Beta382 public static Command<Void> setRequestInterception(List<RequestPattern> patterns) {383 Objects.requireNonNull(patterns, "patterns must be set.");384 return new Command<>(DOMAIN_NAME + ".setRequestInterception",385 ImmutableMap.of("patterns", patterns));386 }387 /**388 * Allows overriding user agent with the given string389 *390 * @param userAgent - User agent to use391 * @param acceptLanguage - Browser langugage to emulate392 * @param platform - The platform navigator.platform should return393 * @return DevTools Command394 */395 public static Command<Void> setUserAgentOverride(String userAgent,396 Optional<String> acceptLanguage,397 Optional<String> platform) {398 Objects.requireNonNull(userAgent, "userAgent must be set.");399 final ImmutableMap.Builder<String, Object> params = ImmutableMap.builder();400 params.put("userAgent", userAgent);401 acceptLanguage.ifPresent(string -> params.put("acceptLanguage", acceptLanguage.toString()));402 platform.ifPresent(string -> params.put("platform", platform.toString()));403 return new Command<>(DOMAIN_NAME + ".setUserAgentOverride", params.build());404 }405 /**406 * Fired when data chunk was received over the network.407 *408 * @return DataReceived Event409 */410 public static Event<DataReceived> dataReceived() {411 return new Event<>(DOMAIN_NAME + ".dataReceived", map("requestId", DataReceived.class));412 }413 /**414 * Fired when EventSource message is received415 *416 * @return EventSourceMessageReceived Event417 */418 public static Event<EventSourceMessageReceived> eventSourceMessageReceived() {419 return new Event<>(DOMAIN_NAME + ".eventSourceMessageReceived",420 map("requestId", EventSourceMessageReceived.class));421 }422 /**423 * Fired when HTTP request has failed to load424 *425 * @return LoadingFailed object426 */427 public static Event<LoadingFailed> loadingFailed() {428 return new Event<>(DOMAIN_NAME + ".loadingFailed", map("requestId", LoadingFailed.class));429 }430 /**431 * Fired when HTTP request has finished loading432 *433 * @return LoadingFinished object434 */435 public static Event<LoadingFinished> loadingFinished() {436 return new Event<>(DOMAIN_NAME + ".loadingFinished", map("requestId", LoadingFinished.class));437 }438 /**439 * Fired if request ended up loading from cache440 *441 * @return RequestId object442 */443 public static Event<RequestId> requestServedFromCache() {444 return new Event<>(DOMAIN_NAME + ".requestServedFromCache", map("requestId", RequestId.class));445 }446 /**447 * Fired when resource loading priority is changed (EXPERIMENTAL)448 *449 * @return ResourceChangedPriority object450 */451 @Beta452 public static Event<ResourceChangedPriority> resourceChangedPriority() {453 return new Event<>(DOMAIN_NAME + ".resourceChangedPriority",454 map("requestId", ResourceChangedPriority.class));455 }456 /**457 * Fired when a signed exchange was received over the network (EXPERIMENTAL)458 *459 * @return SignedExchangeReceived object460 */461 @Beta462 public static Event<SignedExchangeReceived> signedExchangeReceived() {463 return new Event<>(DOMAIN_NAME + ".signedExchangeReceived",464 map("requestId", SignedExchangeReceived.class));465 }466 /**467 * Fired when page is about to send HTTP request468 *469 * @return RequestWillBeSent object470 */471 public static Event<RequestWillBeSent> requestWillBeSent() {472 return new Event<>(DOMAIN_NAME + ".requestWillBeSent",473 map("requestId", RequestWillBeSent.class));474 }475 /**476 * Details of an intercepted HTTP request, which must be either allowed, blocked, modified or mocked.(EXPERIMENTAL)477 *478 * @return {@link RequestIntercepted} Object479 */480 @Beta481 public static Event<RequestIntercepted> requestIntercepted() {482 return new Event<>(DOMAIN_NAME + ".requestIntercepted",483 map("interceptionId", RequestIntercepted.class));484 }485 /**486 * Fired when HTTP response is available.487 *488 * @return {@link ResponseReceived} Object489 */490 public static Event<ResponseReceived> responseReceived() {491 return new Event<>(DOMAIN_NAME + ".responseReceived", map("requestId", ResponseReceived.class));492 }493 /**494 * Fired when WebSocket message error occurs.495 */496 public static Event<WebSocketFrameError> webSocketFrameError() {497 return new Event<>(DOMAIN_NAME + ".webSocketFrameError",498 map("requestId", WebSocketFrameError.class));499 }500 /**501 * Fired upon WebSocket creation.502 */503 public static Event<WebSocketCreated> webSocketCreated() {504 return new Event<>(DOMAIN_NAME + ".webSocketCreated", map("requestId", WebSocketCreated.class));505 }506 /**507 * Fired upon WebSocket creation.508 */509 public static Event<WebSocketClosed> webSocketClosed() {510 return new Event<>(DOMAIN_NAME + ".webSocketClosed", map("requestId", WebSocketClosed.class));511 }512 /**513 * Fired when WebSocket message is received.514 */515 public static Event<WebSocketFrame> webSocketFrameReceived() {516 return new Event<>(DOMAIN_NAME + ".webSocketFrameReceived",517 map("requestId", WebSocketFrame.class));518 }519 /**520 * Fired when WebSocket message is sent.521 */522 public static Event<WebSocketFrame> webSocketFrameSent() {523 return new Event<>(DOMAIN_NAME + ".webSocketFrameSent", map("requestId", WebSocketFrame.class));524 }525}...