Skip to content

Commit

Permalink
feat: CookieManager
Browse files Browse the repository at this point in the history
- A Toolkit class to easily work with cookies in the browser (#5431)
  • Loading branch information
MartinZikmund committed Mar 31, 2021
1 parent 78f96e0 commit b4d18a5
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/Uno.UI.Toolkit/Web/Cookie.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#if __WASM__
#nullable enable

namespace Uno.UI.Toolkit.Web
{
public class Cookie
{
public Cookie(string name, string value)
{
Name = name ?? throw new System.ArgumentNullException(nameof(name));
Value = value ?? throw new System.ArgumentNullException(nameof(value));
}

public string Name { get; }

public string Value { get; }
}
}
#endif
93 changes: 93 additions & 0 deletions src/Uno.UI.Toolkit/Web/CookieManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#if __WASM__
#nullable enable

using System;
using System.Linq;
using System.Text;
using Uno.Foundation;

namespace Uno.UI.Toolkit.Web
{
public class CookieManager
{
private const char ValueSeparator = '=';
private const char AttributeSeparator = ';';

private static readonly Lazy<CookieManager> _cookieManager = new Lazy<CookieManager>(() => new CookieManager());

private CookieManager()
{
}

public static CookieManager GetDefault() => _cookieManager.Value;

public void SetCookie(SetCookieRequest cookie)
{
var builder = new StringBuilder();
builder.Append(Uri.EscapeDataString(cookie.Name));
builder.Append(ValueSeparator);
builder.Append(Uri.EscapeDataString(cookie.Value));

static void AppendAttribute(StringBuilder builder, string name, object? value)
{
if (value == null)
{
return;
}
builder.Append(AttributeSeparator);
builder.Append(name);
builder.Append(ValueSeparator);
builder.Append(value);
}

AppendAttribute(builder, "path", cookie.Path);
AppendAttribute(builder, "domain", cookie.Domain);
AppendAttribute(builder, "max-age", cookie.MaxAge?.ToString());
AppendAttribute(builder, "expires", cookie.Expires?.ToString("r"));
AppendAttribute(builder, "samesite", cookie.SameSite?.ToString("g")?.ToLowerInvariant());
if (cookie.Secure)
{
builder.Append(AttributeSeparator);
builder.Append("secure");
}

var escapedCookie = WebAssemblyRuntime.EscapeJs(builder.ToString());
var jsInvoke = $"document.cookie = '{escapedCookie}'";
WebAssemblyRuntime.InvokeJS(jsInvoke);
}

public void DeleteCookie(string name, string? path = null)
{
var setCookieRequest = new SetCookieRequest(name, string.Empty)
{
Expires = DateTimeOffset.MinValue,
Path = path
};

SetCookie(setCookieRequest);
}

public Cookie? GetCookie(string name) => GetCookies().FirstOrDefault(c => c.Name == name);

public Cookie[] GetCookies()
{
Cookie ParseCookie(string cookieString)
{
var cookieParts = cookieString.Split("=");
var name = Uri.UnescapeDataString(cookieParts[0]);
var value = Uri.UnescapeDataString(cookieParts[1]);
return new Cookie(name, value);
}

var cookies = WebAssemblyRuntime.InvokeJS("document.cookie");
if (string.IsNullOrWhiteSpace(cookies))
{
return Array.Empty<Cookie>();
}

var cookieStrings = cookies.Split(";", StringSplitOptions.RemoveEmptyEntries);
return cookieStrings.Select(part => ParseCookie(part)).ToArray();
}
}
}
#endif
11 changes: 11 additions & 0 deletions src/Uno.UI.Toolkit/Web/CookieSameSiteType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#if __WASM__
namespace Uno.UI.Toolkit.Web
{
public enum CookieSameSite
{
Lax,
Strict,
None
}
}
#endif
34 changes: 34 additions & 0 deletions src/Uno.UI.Toolkit/Web/SetCookieRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#if __WASM__
#nullable enable


using System;

namespace Uno.UI.Toolkit.Web
{
public class SetCookieRequest
{
public SetCookieRequest(string name, string value)
{
Name = name;
Value = value;
}

public string Name { get; }

public string Value { get; }

public string? Path { get; set; }

public string? Domain { get; set; }

public int? MaxAge { get; set; }

public DateTimeOffset? Expires { get; set; }

public bool Secure { get; set; }

public CookieSameSite? SameSite { get; set; }
}
}
#endif
1 change: 1 addition & 0 deletions src/Uno.UWP/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[assembly: InternalsVisibleTo("Uno.UI.Wasm")]
[assembly: InternalsVisibleTo("Uno.UI.RuntimeTests")]
[assembly: InternalsVisibleTo("Uno.UI.Tests")]
[assembly: InternalsVisibleTo("Uno.UI.Toolkit")]

#if __IOS__
[assembly: Foundation.LinkerSafe]
Expand Down

0 comments on commit b4d18a5

Please sign in to comment.