Skip to content

Commit b4d18a5

Browse files
committed
feat: CookieManager
- A Toolkit class to easily work with cookies in the browser (#5431)
1 parent 78f96e0 commit b4d18a5

File tree

5 files changed

+158
-0
lines changed

5 files changed

+158
-0
lines changed

src/Uno.UI.Toolkit/Web/Cookie.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#if __WASM__
2+
#nullable enable
3+
4+
namespace Uno.UI.Toolkit.Web
5+
{
6+
public class Cookie
7+
{
8+
public Cookie(string name, string value)
9+
{
10+
Name = name ?? throw new System.ArgumentNullException(nameof(name));
11+
Value = value ?? throw new System.ArgumentNullException(nameof(value));
12+
}
13+
14+
public string Name { get; }
15+
16+
public string Value { get; }
17+
}
18+
}
19+
#endif
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#if __WASM__
2+
#nullable enable
3+
4+
using System;
5+
using System.Linq;
6+
using System.Text;
7+
using Uno.Foundation;
8+
9+
namespace Uno.UI.Toolkit.Web
10+
{
11+
public class CookieManager
12+
{
13+
private const char ValueSeparator = '=';
14+
private const char AttributeSeparator = ';';
15+
16+
private static readonly Lazy<CookieManager> _cookieManager = new Lazy<CookieManager>(() => new CookieManager());
17+
18+
private CookieManager()
19+
{
20+
}
21+
22+
public static CookieManager GetDefault() => _cookieManager.Value;
23+
24+
public void SetCookie(SetCookieRequest cookie)
25+
{
26+
var builder = new StringBuilder();
27+
builder.Append(Uri.EscapeDataString(cookie.Name));
28+
builder.Append(ValueSeparator);
29+
builder.Append(Uri.EscapeDataString(cookie.Value));
30+
31+
static void AppendAttribute(StringBuilder builder, string name, object? value)
32+
{
33+
if (value == null)
34+
{
35+
return;
36+
}
37+
builder.Append(AttributeSeparator);
38+
builder.Append(name);
39+
builder.Append(ValueSeparator);
40+
builder.Append(value);
41+
}
42+
43+
AppendAttribute(builder, "path", cookie.Path);
44+
AppendAttribute(builder, "domain", cookie.Domain);
45+
AppendAttribute(builder, "max-age", cookie.MaxAge?.ToString());
46+
AppendAttribute(builder, "expires", cookie.Expires?.ToString("r"));
47+
AppendAttribute(builder, "samesite", cookie.SameSite?.ToString("g")?.ToLowerInvariant());
48+
if (cookie.Secure)
49+
{
50+
builder.Append(AttributeSeparator);
51+
builder.Append("secure");
52+
}
53+
54+
var escapedCookie = WebAssemblyRuntime.EscapeJs(builder.ToString());
55+
var jsInvoke = $"document.cookie = '{escapedCookie}'";
56+
WebAssemblyRuntime.InvokeJS(jsInvoke);
57+
}
58+
59+
public void DeleteCookie(string name, string? path = null)
60+
{
61+
var setCookieRequest = new SetCookieRequest(name, string.Empty)
62+
{
63+
Expires = DateTimeOffset.MinValue,
64+
Path = path
65+
};
66+
67+
SetCookie(setCookieRequest);
68+
}
69+
70+
public Cookie? GetCookie(string name) => GetCookies().FirstOrDefault(c => c.Name == name);
71+
72+
public Cookie[] GetCookies()
73+
{
74+
Cookie ParseCookie(string cookieString)
75+
{
76+
var cookieParts = cookieString.Split("=");
77+
var name = Uri.UnescapeDataString(cookieParts[0]);
78+
var value = Uri.UnescapeDataString(cookieParts[1]);
79+
return new Cookie(name, value);
80+
}
81+
82+
var cookies = WebAssemblyRuntime.InvokeJS("document.cookie");
83+
if (string.IsNullOrWhiteSpace(cookies))
84+
{
85+
return Array.Empty<Cookie>();
86+
}
87+
88+
var cookieStrings = cookies.Split(";", StringSplitOptions.RemoveEmptyEntries);
89+
return cookieStrings.Select(part => ParseCookie(part)).ToArray();
90+
}
91+
}
92+
}
93+
#endif
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#if __WASM__
2+
namespace Uno.UI.Toolkit.Web
3+
{
4+
public enum CookieSameSite
5+
{
6+
Lax,
7+
Strict,
8+
None
9+
}
10+
}
11+
#endif
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#if __WASM__
2+
#nullable enable
3+
4+
5+
using System;
6+
7+
namespace Uno.UI.Toolkit.Web
8+
{
9+
public class SetCookieRequest
10+
{
11+
public SetCookieRequest(string name, string value)
12+
{
13+
Name = name;
14+
Value = value;
15+
}
16+
17+
public string Name { get; }
18+
19+
public string Value { get; }
20+
21+
public string? Path { get; set; }
22+
23+
public string? Domain { get; set; }
24+
25+
public int? MaxAge { get; set; }
26+
27+
public DateTimeOffset? Expires { get; set; }
28+
29+
public bool Secure { get; set; }
30+
31+
public CookieSameSite? SameSite { get; set; }
32+
}
33+
}
34+
#endif

src/Uno.UWP/AssemblyInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
[assembly: InternalsVisibleTo("Uno.UI.Wasm")]
77
[assembly: InternalsVisibleTo("Uno.UI.RuntimeTests")]
88
[assembly: InternalsVisibleTo("Uno.UI.Tests")]
9+
[assembly: InternalsVisibleTo("Uno.UI.Toolkit")]
910

1011
#if __IOS__
1112
[assembly: Foundation.LinkerSafe]

0 commit comments

Comments
 (0)