Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dotnet] Proper implementation of cookies management #14883

Open
wants to merge 7 commits into
base: trunk
Choose a base branch
from
Open
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
93 changes: 25 additions & 68 deletions dotnet/src/webdriver/CookieJar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,104 +23,61 @@

namespace OpenQA.Selenium
{
/// <summary>
/// Defines an interface allowing the user to manipulate cookies on the current page.
/// </summary>
internal class CookieJar : ICookieJar
internal class CookieJar(WebDriver driver) : ICookieJar
{
private WebDriver driver;
public ReadOnlyCollection<Cookie> AllCookies => GetAllCookies();

/// <summary>
/// Initializes a new instance of the <see cref="CookieJar"/> class.
/// </summary>
/// <param name="driver">The driver that is currently in use</param>
public CookieJar(WebDriver driver)
{
this.driver = driver;
}

/// <summary>
/// Gets all cookies defined for the current page.
/// </summary>
public ReadOnlyCollection<Cookie> AllCookies
{
get { return this.GetAllCookies(); }
}

/// <summary>
/// Method for creating a cookie in the browser
/// </summary>
/// <param name="cookie"><see cref="Cookie"/> that represents a cookie in the browser</param>
public void AddCookie(Cookie cookie)
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("cookie", cookie);
this.driver.InternalExecute(DriverCommand.AddCookie, parameters);
if (cookie is null)
{
throw new ArgumentNullException(nameof(cookie));
}

driver.InternalExecute(DriverCommand.AddCookie, new() { { "cookie", cookie } });
}

/// <summary>
/// Delete the cookie by passing in the name of the cookie
/// </summary>
/// <param name="name">The name of the cookie that is in the browser</param>
public void DeleteCookieNamed(string name)
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("name", name);
this.driver.InternalExecute(DriverCommand.DeleteCookie, parameters);
if (name is null)
{
throw new ArgumentNullException(nameof(name));
}

driver.InternalExecute(DriverCommand.DeleteCookie, new() { { "name", name } });
}

/// <summary>
/// Delete a cookie in the browser by passing in a copy of a cookie
/// </summary>
/// <param name="cookie">An object that represents a copy of the cookie that needs to be deleted</param>
public void DeleteCookie(Cookie cookie)
{
if (cookie != null)
if (cookie is null)
{
this.DeleteCookieNamed(cookie.Name);
throw new ArgumentNullException(nameof(cookie));
}

DeleteCookieNamed(cookie.Name);
}

/// <summary>
/// Delete All Cookies that are present in the browser
/// </summary>
public void DeleteAllCookies()
{
this.driver.InternalExecute(DriverCommand.DeleteAllCookies, null);
driver.InternalExecute(DriverCommand.DeleteAllCookies, null);
}

/// <summary>
/// Method for returning a getting a cookie by name
/// </summary>
/// <param name="name">name of the cookie that needs to be returned</param>
/// <returns>A Cookie from the name</returns>
public Cookie GetCookieNamed(string name)
{
Cookie cookieToReturn = null;
if (name != null)
if (name is null)
{
ReadOnlyCollection<Cookie> allCookies = this.AllCookies;
foreach (Cookie currentCookie in allCookies)
{
if (name.Equals(currentCookie.Name))
{
cookieToReturn = currentCookie;
break;
}
}
throw new ArgumentNullException(nameof(name));
}

return cookieToReturn;
var rawCookie = driver.InternalExecute(DriverCommand.GetCookie, new() { { "name", name } }).Value;

return Cookie.FromDictionary((Dictionary<string, object>)rawCookie);
}

/// <summary>
/// Method for getting a Collection of Cookies that are present in the browser
/// </summary>
/// <returns>ReadOnlyCollection of Cookies in the browser</returns>
private ReadOnlyCollection<Cookie> GetAllCookies()
{
List<Cookie> toReturn = new List<Cookie>();
object returned = this.driver.InternalExecute(DriverCommand.GetAllCookies, new Dictionary<string, object>()).Value;
object returned = driver.InternalExecute(DriverCommand.GetAllCookies, new Dictionary<string, object>()).Value;

try
{
Expand Down
9 changes: 7 additions & 2 deletions dotnet/src/webdriver/ICookieJar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// under the License.
// </copyright>

using System;
using System.Collections.ObjectModel;

namespace OpenQA.Selenium
Expand All @@ -35,26 +36,30 @@ public interface ICookieJar
/// Adds a cookie to the current page.
/// </summary>
/// <param name="cookie">The <see cref="Cookie"/> object to be added.</param>
/// <exception cref="ArgumentNullException">If <paramref name="cookie"/> is <see langword="null"/>.</exception>
void AddCookie(Cookie cookie);

/// <summary>
/// Gets a cookie with the specified name.
/// </summary>
/// <param name="name">The name of the cookie to retrieve.</param>
/// <returns>The <see cref="Cookie"/> containing the name. Returns <see langword="null"/>
/// if no cookie with the specified name is found.</returns>
/// <returns>The <see cref="Cookie"/> containing the name.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="name"/> is <see langword="null"/>.</exception>
/// <exception cref="NoSuchCookieException">If <paramref name="name"/> is not found.</exception>
Cookie GetCookieNamed(string name);

/// <summary>
/// Deletes the specified cookie from the page.
/// </summary>
/// <param name="cookie">The <see cref="Cookie"/> to be deleted.</param>
/// <exception cref="ArgumentNullException">If <paramref name="cookie"/> is <see langword="null"/>.</exception>
void DeleteCookie(Cookie cookie);

/// <summary>
/// Deletes the cookie with the specified name from the page.
/// </summary>
/// <param name="name">The name of the cookie to be deleted.</param>
/// <exception cref="ArgumentNullException">If <paramref name="name"/> is <see langword="null"/>.</exception>
void DeleteCookieNamed(string name);

/// <summary>
Expand Down
63 changes: 63 additions & 0 deletions dotnet/src/webdriver/NoSuchCookieException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// <copyright file="NoSuchCookieException.cs" company="Selenium Committers">
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// </copyright>

using System;

#nullable enable

namespace OpenQA.Selenium
{
/// <summary>
/// The exception that is thrown when a cookie is not found.
/// </summary>
[Serializable]
public class NoSuchCookieException : NotFoundException
{
/// <summary>
/// Initializes a new instance of the <see cref="NoSuchCookieException"/> class.
/// </summary>
public NoSuchCookieException()
: base()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="NoSuchCookieException"/> class with
/// a specified error message.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public NoSuchCookieException(string? message)
: base(message)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="NoSuchCookieException"/> class with
/// a specified error message and a reference to the inner exception that is the
/// cause of this exception.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception,
/// or <see langword="null"/> if no inner exception is specified.</param>
public NoSuchCookieException(string? message, Exception? innerException)
: base(message, innerException)
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ protected override void InitializeCommandDictionary()
this.TryAddCommand(DriverCommand.ExecuteScript, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/execute/sync"));
this.TryAddCommand(DriverCommand.ExecuteAsyncScript, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/execute/async"));
this.TryAddCommand(DriverCommand.GetAllCookies, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/cookie"));
this.TryAddCommand(DriverCommand.GetCookie, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/cookie/{name}"));
this.TryAddCommand(DriverCommand.GetCookie, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/cookie/{name}"));
this.TryAddCommand(DriverCommand.AddCookie, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/cookie"));
this.TryAddCommand(DriverCommand.DeleteCookie, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}/cookie/{name}"));
this.TryAddCommand(DriverCommand.DeleteAllCookies, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}/cookie"));
Expand Down
3 changes: 3 additions & 0 deletions dotnet/src/webdriver/WebDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,9 @@ private static void UnpackAndThrowOnError(Response errorResponse, string command
case WebDriverResult.InsecureCertificate:
throw new InsecureCertificateException(errorMessage);

case WebDriverResult.NoSuchCookie:
throw new NoSuchCookieException(errorMessage);

default:
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "{0} ({1})", errorMessage, errorResponse.Status));
}
Expand Down
6 changes: 2 additions & 4 deletions dotnet/test/common/CookieImplementationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,7 @@ public void SettingACookieThatExpiredInThePast()
IOptions options = driver.Manage();
options.Cookies.AddCookie(cookie);

cookie = options.Cookies.GetCookieNamed("expired");
Assert.That(cookie, Is.Null, "Cookie expired before it was set, so nothing should be returned: " + cookie);
Assert.That(() => options.Cookies.GetCookieNamed("expired"), Throws.InstanceOf<NoSuchCookieException>());
}

[Test]
Expand All @@ -579,9 +578,8 @@ public void CanSetCookieWithoutOptionalFieldsSet()
public void DeleteNotExistedCookie()
{
String key = GenerateUniqueKey();
AssertCookieIsNotPresentWithName(key);

driver.Manage().Cookies.DeleteCookieNamed(key);
Assert.That(() => driver.Manage().Cookies.DeleteCookieNamed(key), Throws.Nothing);
}

[Test]
Expand Down
Loading