Skip to content

Commit

Permalink
[dotnet] Add constructor for creating a Cookie instance with all opti…
Browse files Browse the repository at this point in the history
…onal arguments (#9361)

Co-authored-by: jimevans <james.h.evans.jr@gmail.com>
  • Loading branch information
pujagani and jimevans authored Oct 13, 2021
1 parent e6cd2a8 commit eb4c4fc
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 29 deletions.
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

0 comments on commit eb4c4fc

Please sign in to comment.