Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 47 additions & 4 deletions dotnet/src/webdriver/Cookie.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// </copyright>

using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
Expand All @@ -35,8 +36,11 @@ public class Cookie
private string cookieValue;
private string cookiePath;
private string cookieDomain;
private bool isHttpOnly;
private string sameSite;
private bool secure;
private DateTime? cookieExpiry;
private readonly string[] sameSiteValues = {"Strict", "Lax", "None"};

/// <summary>
/// Initializes a new instance of the <see cref="Cookie"/> class with a specific name,
Expand Down Expand Up @@ -98,6 +102,44 @@ public Cookie(string name, string value, string path, DateTime? expiry)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="ReturnedCookie"/> class with a specific name,
/// value, domain, path and expiration date.
/// </summary>
/// <param name="name">The name of the cookie.</param>
/// <param name="value">The value of the cookie.</param>
/// <param name="domain">The domain of the cookie.</param>
/// <param name="path">The path of the cookie.</param>
/// <param name="expiry">The expiration date of the cookie.</param>
/// <param name="isSecure"><see langword="true"/> if the cookie is secure; otherwise <see langword="false"/></param>
/// <param name="isHttpOnly"><see langword="true"/> if the cookie is an HTTP-only cookie; otherwise <see langword="false"/></param>
/// <param name="sameSite">The SameSite value of cookie.</param>
/// <exception cref="ArgumentException">If the name is <see langword="null"/> or an empty string,
/// or if it contains a semi-colon.</exception>
/// <exception cref="ArgumentNullException">If the value or currentUrl is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">If the same site value is not valid or same site value is "None" but secure is set to false.</exception>
public Cookie(string name, string value, string domain, string path, DateTime? expiry, bool secure, bool isHttpOnly, string sameSite)
: this(name, value, domain, path, expiry)
{
this.isHttpOnly = isHttpOnly;
this.secure = secure;

if (!string.IsNullOrEmpty(sameSite))
{
if (!sameSiteValues.Contains(sameSite))
{
throw new ArgumentException("Invalid sameSite cookie value. It should either \"Lax\", \"Strict\" or \"None\" ", "sameSite");
}

if ("None".Equals(sameSite) && !this.secure)
{
throw new ArgumentException("Invalid cookie configuration: SameSite=None must be Secure");
}

this.sameSite = sameSite;
}
}

/// <summary>
/// Initializes a new instance of the <see cref="Cookie"/> class with a specific name,
/// value, and path.
Expand Down Expand Up @@ -168,7 +210,7 @@ public virtual string Path
[JsonProperty("secure")]
public virtual bool Secure
{
get { return false; }
get { return this.secure; }
}

/// <summary>
Expand All @@ -177,7 +219,8 @@ public virtual bool Secure
[JsonProperty("httpOnly")]
public virtual bool IsHttpOnly
{
get { return false; }
get { return this.isHttpOnly; }

}

/// <summary>
Expand All @@ -187,7 +230,6 @@ public virtual bool IsHttpOnly
public virtual string SameSite
{
get { return this.sameSite; }
protected set { this.sameSite = value; }
}

/// <summary>
Expand Down Expand Up @@ -287,7 +329,8 @@ public override string ToString()
return this.cookieName + "=" + this.cookieValue
+ (this.cookieExpiry == null ? string.Empty : "; expires=" + this.cookieExpiry.Value.ToUniversalTime().ToString("ddd MM dd yyyy hh:mm:ss UTC", CultureInfo.InvariantCulture))
+ (string.IsNullOrEmpty(this.cookiePath) ? string.Empty : "; path=" + this.cookiePath)
+ (string.IsNullOrEmpty(this.cookieDomain) ? string.Empty : "; domain=" + this.cookieDomain);
+ (string.IsNullOrEmpty(this.cookieDomain) ? string.Empty : "; domain=" + this.cookieDomain)
+ "; isHttpOnly= " + this.isHttpOnly + "; secure= " + this.secure + (string.IsNullOrEmpty(this.sameSite) ? string.Empty : "; sameSite=" + this.sameSite);
}

/// <summary>
Expand Down
31 changes: 6 additions & 25 deletions dotnet/src/webdriver/Internal/ReturnedCookie.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ namespace OpenQA.Selenium.Internal
/// </summary>
public class ReturnedCookie : Cookie
{
private bool isSecure;
private bool isHttpOnly;


/// <summary>
/// Initializes a new instance of the <see cref="ReturnedCookie"/> class with a specific name,
/// value, domain, path and expiration date.
Expand Down Expand Up @@ -64,27 +62,9 @@ public ReturnedCookie(string name, string value, string domain, string path, Dat
/// or if it contains a semi-colon.</exception>
/// <exception cref="ArgumentNullException">If the value or currentUrl is <see langword="null"/>.</exception>
public ReturnedCookie(string name, string value, string domain, string path, DateTime? expiry, bool isSecure, bool isHttpOnly, string sameSite)
: base(name, value, domain, path, expiry)
{
this.isSecure = isSecure;
this.isHttpOnly = isHttpOnly;
this.SameSite = sameSite;
}

/// <summary>
/// Gets a value indicating whether the cookie is secure.
/// </summary>
public override bool Secure
{
get { return this.isSecure; }
}

/// <summary>
/// Gets a value indicating whether the cookie is an HTTP-only cookie.
/// </summary>
public override bool IsHttpOnly
: base(name, value, domain, path, expiry, isSecure, isHttpOnly, sameSite)
{
get { return this.isHttpOnly; }

}

/// <summary>
Expand All @@ -97,8 +77,9 @@ public override string ToString()
+ (this.Expiry == null ? string.Empty : "; expires=" + this.Expiry.Value.ToUniversalTime().ToString("ddd MM/dd/yyyy HH:mm:ss UTC", CultureInfo.InvariantCulture))
+ (string.IsNullOrEmpty(this.Path) ? string.Empty : "; path=" + this.Path)
+ (string.IsNullOrEmpty(this.Domain) ? string.Empty : "; domain=" + this.Domain)
+ (this.isSecure ? "; secure" : string.Empty)
+ (this.isHttpOnly ? "; httpOnly" : string.Empty);
+ (this.Secure ? "; secure" : string.Empty)
+ (this.IsHttpOnly ? "; httpOnly" : string.Empty)
+ (string.IsNullOrEmpty(this.SameSite) ? string.Empty : "; sameSite=" + this.SameSite);
}
}
}
24 changes: 24 additions & 0 deletions dotnet/test/common/CookieTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,30 @@ public void ShouldThrowAnExceptionWhenTheNameIsNull()
Assert.That(() => new ReturnedCookie(null, "value", null, null, DateTime.Now, false, false), Throws.InstanceOf<ArgumentException>());
}

[Test]
public void ShouldThrowAnExceptionWhenSameSiteIsWrong()
{
Assert.That(() => new ReturnedCookie("name", "value", "" , "/", DateTime.Now, true, true, "Wrong"), Throws.InstanceOf<ArgumentException>());
}

[Test]
public void ShouldThrowAnExceptionWhenSameSiteIsNoneButNotSecure()
{
Assert.That(() => new ReturnedCookie("name", "value", "", "/", DateTime.Now, false, true, "None"), Throws.InstanceOf<ArgumentException>());
}

[Test]
public void CookiesShouldAllowOptionalParametersToBeSet()
{
DateTime expiry = DateTime.Now;
Cookie cookie = new Cookie ("name", "value", "test.com", "/", expiry, true, true, "None");
Assert.That(cookie.Domain, Is.EqualTo("test.com"));
Assert.That(cookie.Path, Is.EqualTo("/"));
Assert.That(cookie.IsHttpOnly, Is.True);
Assert.That(cookie.Secure, Is.True);
Assert.That(cookie.SameSite, Is.EqualTo("None"));
}

[Test]
public void CookiesShouldAllowSecureToBeSet()
{
Expand Down