Path: blob/trunk/java/src/org/openqa/selenium/Cookie.java
4010 views
// Licensed to the Software Freedom Conservancy (SFC) under one1// or more contributor license agreements. See the NOTICE file2// distributed with this work for additional information3// regarding copyright ownership. The SFC licenses this file4// to you under the Apache License, Version 2.0 (the5// "License"); you may not use this file except in compliance6// with the License. You may obtain a copy of the License at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing,11// software distributed under the License is distributed on an12// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13// KIND, either express or implied. See the License for the14// specific language governing permissions and limitations15// under the License.1617package org.openqa.selenium;1819import java.io.Serializable;20import java.text.SimpleDateFormat;21import java.util.Date;22import java.util.Map;23import java.util.Objects;24import java.util.TimeZone;25import java.util.TreeMap;26import org.jspecify.annotations.Nullable;2728public class Cookie implements Serializable {29private static final long serialVersionUID = 4115876353625612383L;3031private final String name;32private final String value;33private final String path;34private final @Nullable String domain;35private final @Nullable Date expiry;36private final boolean isSecure;37private final boolean isHttpOnly;38private final @Nullable String sameSite;3940/**41* Creates an insecure non-httpOnly cookie with no domain specified.42*43* @param name The name of the cookie; may not be null or an empty string.44* @param value The cookie value; may not be null.45* @param path The path the cookie is visible to. If left blank or set to null, will be set to46* "/".47* @param expiry The cookie's expiration date; may be null.48* @see #Cookie(String, String, String, String, Date)49*/50public Cookie(String name, String value, @Nullable String path, @Nullable Date expiry) {51this(name, value, null, path, expiry);52}5354/**55* Creates an insecure non-httpOnly cookie.56*57* @param name The name of the cookie; may not be null or an empty string.58* @param value The cookie value; may not be null.59* @param domain The domain the cookie is visible to.60* @param path The path the cookie is visible to. If left blank or set to null, will be set to61* "/".62* @param expiry The cookie's expiration date; may be null.63* @see #Cookie(String, String, String, String, Date, boolean)64*/65public Cookie(66String name,67String value,68@Nullable String domain,69@Nullable String path,70@Nullable Date expiry) {71this(name, value, domain, path, expiry, false);72}7374/**75* Creates a non-httpOnly cookie.76*77* @param name The name of the cookie; may not be null or an empty string.78* @param value The cookie value; may not be null.79* @param domain The domain the cookie is visible to.80* @param path The path the cookie is visible to. If left blank or set to null, will be set to81* "/".82* @param expiry The cookie's expiration date; may be null.83* @param isSecure Whether this cookie requires a secure connection.84*/85public Cookie(86String name,87String value,88@Nullable String domain,89@Nullable String path,90@Nullable Date expiry,91boolean isSecure) {92this(name, value, domain, path, expiry, isSecure, false);93}9495/**96* Creates a cookie.97*98* @param name The name of the cookie; may not be null or an empty string.99* @param value The cookie value; may not be null.100* @param domain The domain the cookie is visible to.101* @param path The path the cookie is visible to. If left blank or set to null, will be set to102* "/".103* @param expiry The cookie's expiration date; may be null.104* @param isSecure Whether this cookie requires a secure connection.105* @param isHttpOnly Whether this cookie is a httpOnly cooke.106*/107public Cookie(108String name,109String value,110@Nullable String domain,111@Nullable String path,112@Nullable Date expiry,113boolean isSecure,114boolean isHttpOnly) {115this(name, value, domain, path, expiry, isSecure, isHttpOnly, null);116}117118/**119* Creates a cookie.120*121* @param name The name of the cookie; may not be null or an empty string.122* @param value The cookie value; may not be null.123* @param domain The domain the cookie is visible to.124* @param path The path the cookie is visible to. If left blank or set to null, will be set to125* "/".126* @param expiry The cookie's expiration date; may be null.127* @param isSecure Whether this cookie requires a secure connection.128* @param isHttpOnly Whether this cookie is a httpOnly cookie.129* @param sameSite The samesite attribute of this cookie; e.g. None, Lax, Strict.130*/131public Cookie(132String name,133String value,134@Nullable String domain,135@Nullable String path,136@Nullable Date expiry,137boolean isSecure,138boolean isHttpOnly,139@Nullable String sameSite) {140this.name = name;141this.value = value;142this.path = path == null || path.isEmpty() ? "/" : path;143144this.domain = stripPort(domain);145this.isSecure = isSecure;146this.isHttpOnly = isHttpOnly;147148if (expiry != null) {149// Expiration date is specified in seconds since (UTC) epoch time, so truncate the date.150this.expiry = new Date(expiry.getTime() / 1000 * 1000);151} else {152this.expiry = null;153}154155this.sameSite = sameSite;156}157158/**159* Create a cookie for the default path with the given name and value with no expiry set.160*161* @param name The cookie's name162* @param value The cookie's value163*/164public Cookie(String name, String value) {165this(name, value, "/", null);166}167168/**169* Create a cookie.170*171* @param name The cookie's name172* @param value The cookie's value173* @param path The path the cookie is for174*/175public Cookie(String name, String value, String path) {176this(name, value, path, null);177}178179public String getName() {180return name;181}182183public String getValue() {184return value;185}186187public @Nullable String getDomain() {188return domain;189}190191public String getPath() {192return path;193}194195public boolean isSecure() {196return isSecure;197}198199public boolean isHttpOnly() {200return isHttpOnly;201}202203public @Nullable Date getExpiry() {204return expiry == null ? null : new Date(expiry.getTime());205}206207public @Nullable String getSameSite() {208return sameSite;209}210211private static @Nullable String stripPort(@Nullable String domain) {212return (domain == null) ? null : domain.split(":")[0];213}214215public void validate() {216if (name == null || name.isEmpty() || value == null || path == null) {217throw new IllegalArgumentException(218"Required attributes are not set or " + "any non-null attribute set to null");219}220221if (name.indexOf(';') != -1) {222throw new IllegalArgumentException("Cookie names cannot contain a ';': " + name);223}224225if (domain != null && domain.contains(":")) {226throw new IllegalArgumentException("Domain should not contain a port: " + domain);227}228}229230/**231* JSON object keys are defined in232* https://w3c.github.io/webdriver/#dfn-table-for-cookie-conversion.233*/234public Map<String, Object> toJson() {235Map<String, Object> toReturn = new TreeMap<>();236237if (getDomain() != null) {238toReturn.put("domain", getDomain());239}240241if (getExpiry() != null) {242toReturn.put("expiry", getExpiry());243}244245if (getName() != null) {246toReturn.put("name", getName());247}248249if (getPath() != null) {250toReturn.put("path", getPath());251}252253if (getValue() != null) {254toReturn.put("value", getValue());255}256257toReturn.put("secure", isSecure());258toReturn.put("httpOnly", isHttpOnly());259260if (getSameSite() != null) {261toReturn.put("sameSite", getSameSite());262}263264return toReturn;265}266267@Override268public String toString() {269SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");270sdf.setTimeZone(TimeZone.getTimeZone("GMT"));271return name272+ "="273+ value274+ (expiry == null ? "" : "; expires=" + sdf.format(expiry))275+ ("".equals(path) ? "" : "; path=" + path)276+ (domain == null ? "" : "; domain=" + domain)277+ (isSecure ? ";secure;" : "")278+ (sameSite == null ? "" : "; sameSite=" + sameSite);279}280281/** Two cookies are equal if the name and value match */282@Override283public boolean equals(@Nullable Object o) {284if (this == o) {285return true;286}287if (!(o instanceof Cookie)) {288return false;289}290291Cookie cookie = (Cookie) o;292293if (!name.equals(cookie.name)) {294return false;295}296return Objects.equals(value, cookie.value);297}298299@Override300public int hashCode() {301return name.hashCode();302}303304public static class Builder {305306private final String name;307private final String value;308private @Nullable String path;309private @Nullable String domain;310private @Nullable Date expiry;311private boolean secure;312private boolean httpOnly;313private @Nullable String sameSite;314315public Builder(String name, String value) {316this.name = name;317this.value = value;318}319320public Builder domain(@Nullable String host) {321this.domain = stripPort(host);322return this;323}324325public Builder path(@Nullable String path) {326this.path = path;327return this;328}329330public Builder expiresOn(@Nullable Date expiry) {331this.expiry = expiry == null ? null : new Date(expiry.getTime());332return this;333}334335public Builder isSecure(boolean secure) {336this.secure = secure;337return this;338}339340public Builder isHttpOnly(boolean httpOnly) {341this.httpOnly = httpOnly;342return this;343}344345public Builder sameSite(@Nullable String sameSite) {346this.sameSite = sameSite;347return this;348}349350public Cookie build() {351return new Cookie(name, value, domain, path, expiry, secure, httpOnly, sameSite);352}353}354}355356357