Skip to content

Commit 5bcd6ee

Browse files
authored
Merge pull request #20105 from unoplatform/dev/mazi/picker-support-check
feat: Add File System Access API support check and `CookieManager` to WASM
2 parents 526bca6 + ea10cc9 commit 5bcd6ee

File tree

6 files changed

+180
-183
lines changed

6 files changed

+180
-183
lines changed

src/Uno.UI.Runtime.Skia.WebAssembly.Browser/Uno.UI.Runtime.Skia.WebAssembly.Browser.csproj

+5-4
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@
7474
</ItemGroup>
7575

7676
<ItemGroup>
77+
<Compile Include="..\Uno.UI.Runtime.WebAssembly\Storage\Pickers\FileSystemAccessApiInformation.cs" Link="Storage\Pickers\FileSystemAccessApiInformation.cs" />
78+
<Compile Include="..\Uno.UI.Runtime.WebAssembly\Web\Http\Cookie.cs" Link="Web\Http\Cookie.cs" />
79+
<Compile Include="..\Uno.UI.Runtime.WebAssembly\Web\Http\CookieManager.cs" Link="Web\Http\CookieManager.cs" />
80+
<Compile Include="..\Uno.UI.Runtime.WebAssembly\Web\Http\CookieSameSite.cs" Link="Web\Http\CookieSameSite.cs" />
81+
<Compile Include="..\Uno.UI.Runtime.WebAssembly\Web\Http\SetCookieRequest.cs" Link="Web\Http\SetCookieRequest.cs" />
7782
<Compile Include="..\Uno.UI\UI\Xaml\Controls\WebView\Native\Wasm\NativeWebView.Interop.wasm.cs" Link="UI\Xaml\Controls\WebView\NativeWebView.Interop.wasm.cs" />
7883
<Compile Include="..\Uno.UI\UI\Xaml\Controls\WebView\Native\Wasm\NativeWebView.wasm.cs" Link="UI\Xaml\Controls\WebView\NativeWebView.wasm.cs" />
7984
</ItemGroup>
@@ -125,8 +130,4 @@
125130
<_UnoEmbeddedResourcesInjectionAfterTargets Include="CompileTypeScriptWithTSConfig" />
126131
</ItemGroup>
127132

128-
<ItemGroup>
129-
130-
</ItemGroup>
131-
132133
</Project>

src/Uno.UI.Runtime.WebAssembly/Web/Http/Cookie.cs

+21-22
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,31 @@
22

33
using System;
44

5-
namespace Uno.Web.Http
5+
namespace Uno.Web.Http;
6+
7+
/// <summary>
8+
/// Contains basic cookie attributes.
9+
/// </summary>
10+
public class Cookie
611
{
712
/// <summary>
8-
/// Contains basic cookie attributes.
13+
/// Creates a cookie with given name and value.
914
/// </summary>
10-
public class Cookie
15+
/// <param name="name">Name.</param>
16+
/// <param name="value">Value.</param>
17+
public Cookie(string name, string value)
1118
{
12-
/// <summary>
13-
/// Creates a cookie with given name and value.
14-
/// </summary>
15-
/// <param name="name">Name.</param>
16-
/// <param name="value">Value.</param>
17-
public Cookie(string name, string value)
18-
{
19-
Name = name ?? throw new ArgumentNullException(nameof(name));
20-
Value = value ?? throw new ArgumentNullException(nameof(value));
21-
}
19+
Name = name ?? throw new ArgumentNullException(nameof(name));
20+
Value = value ?? throw new ArgumentNullException(nameof(value));
21+
}
2222

23-
/// <summary>
24-
/// Gets the cookie name.
25-
/// </summary>
26-
public string Name { get; }
23+
/// <summary>
24+
/// Gets the cookie name.
25+
/// </summary>
26+
public string Name { get; }
2727

28-
/// <summary>
29-
/// Gets the cookie value.
30-
/// </summary>
31-
public string Value { get; }
32-
}
28+
/// <summary>
29+
/// Gets the cookie value.
30+
/// </summary>
31+
public string Value { get; }
3332
}

src/Uno.UI.Runtime.WebAssembly/Web/Http/CookieManager.cs

+89-90
Original file line numberDiff line numberDiff line change
@@ -6,114 +6,113 @@
66
using Uno.Foundation;
77
using Windows.Web.Http;
88

9-
namespace Uno.Web.Http
9+
namespace Uno.Web.Http;
10+
11+
/// <summary>
12+
/// Provides read-write access to browser Cookies in WebAssembly.
13+
/// </summary>
14+
public class CookieManager
1015
{
16+
private const char ValueSeparator = '=';
17+
private const char AttributeSeparator = ';';
18+
19+
private static readonly Lazy<CookieManager> _cookieManager = new Lazy<CookieManager>(() => new CookieManager());
20+
21+
private CookieManager()
22+
{
23+
}
24+
1125
/// <summary>
12-
/// Provides read-write access to browser Cookies in WebAssembly.
26+
/// Retrieves the default instance of CookieManager.
1327
/// </summary>
14-
public class CookieManager
15-
{
16-
private const char ValueSeparator = '=';
17-
private const char AttributeSeparator = ';';
28+
/// <returns>Cookie manager instance.</returns>
29+
public static CookieManager GetDefault() => _cookieManager.Value;
1830

19-
private static readonly Lazy<CookieManager> _cookieManager = new Lazy<CookieManager>(() => new CookieManager());
31+
/// <summary>
32+
/// Sets a cookie given attributes.
33+
/// </summary>
34+
/// <param name="request">Set cookie request</param>
35+
public void SetCookie(SetCookieRequest request)
36+
{
37+
var httpCookie = new HttpCookie(request.Cookie.Name, request.Domain ?? string.Empty, request.Path ?? string.Empty)
38+
{
39+
Secure = request.Secure,
40+
Expires = request.Expires,
41+
Value = request.Cookie.Value,
42+
};
43+
var serializedCookie = httpCookie.ToString();
2044

21-
private CookieManager()
45+
if (request.MaxAge != null)
2246
{
47+
serializedCookie += $"; max-age={request.MaxAge.Value.ToString(CultureInfo.InvariantCulture)}";
2348
}
24-
25-
/// <summary>
26-
/// Retrieves the default instance of CookieManager.
27-
/// </summary>
28-
/// <returns>Cookie manager instance.</returns>
29-
public static CookieManager GetDefault() => _cookieManager.Value;
30-
31-
/// <summary>
32-
/// Sets a cookie given attributes.
33-
/// </summary>
34-
/// <param name="request">Set cookie request</param>
35-
public void SetCookie(SetCookieRequest request)
49+
if (request.SameSite != null)
3650
{
37-
var httpCookie = new HttpCookie(request.Cookie.Name, request.Domain ?? string.Empty, request.Path ?? string.Empty)
38-
{
39-
Secure = request.Secure,
40-
Expires = request.Expires,
41-
Value = request.Cookie.Value,
42-
};
43-
var serializedCookie = httpCookie.ToString();
44-
45-
if (request.MaxAge != null)
46-
{
47-
serializedCookie += $"; max-age={request.MaxAge.Value.ToString(CultureInfo.InvariantCulture)}";
48-
}
49-
if (request.SameSite != null)
50-
{
51-
serializedCookie += $"; samesite={request.SameSite.Value.ToString("g").ToLowerInvariant()}";
52-
}
53-
54-
var escapedCookie = WebAssemblyRuntime.EscapeJs(serializedCookie);
55-
var jsInvoke = $"document.cookie = '{escapedCookie}'";
56-
WebAssemblyRuntime.InvokeJS(jsInvoke);
51+
serializedCookie += $"; samesite={request.SameSite.Value.ToString("g").ToLowerInvariant()}";
5752
}
5853

59-
/// <summary>
60-
/// Deletes a cookies by name.
61-
/// </summary>
62-
/// <param name="name">Name of the cookie.</param>
63-
/// <param name="domain">Domain of the cookie (optional).</param>
64-
/// <param name="path">Path of the cookie (optional).</param>
65-
public void DeleteCookie(string name, string? domain = null, string? path = null)
54+
var escapedCookie = WebAssemblyRuntime.EscapeJs(serializedCookie);
55+
var jsInvoke = $"document.cookie = '{escapedCookie}'";
56+
WebAssemblyRuntime.InvokeJS(jsInvoke);
57+
}
58+
59+
/// <summary>
60+
/// Deletes a cookies by name.
61+
/// </summary>
62+
/// <param name="name">Name of the cookie.</param>
63+
/// <param name="domain">Domain of the cookie (optional).</param>
64+
/// <param name="path">Path of the cookie (optional).</param>
65+
public void DeleteCookie(string name, string? domain = null, string? path = null)
66+
{
67+
var setCookieRequest = new SetCookieRequest(new Cookie(name, string.Empty))
6668
{
67-
var setCookieRequest = new SetCookieRequest(new Cookie(name, string.Empty))
68-
{
69-
Expires = DateTimeOffset.MinValue,
70-
Path = path,
71-
Domain = domain
72-
};
69+
Expires = DateTimeOffset.MinValue,
70+
Path = path,
71+
Domain = domain
72+
};
7373

74-
SetCookie(setCookieRequest);
75-
}
74+
SetCookie(setCookieRequest);
75+
}
7676

77-
/// <summary>
78-
/// Retrieves a cookie by name.
79-
/// </summary>
80-
/// <param name="name">Cookie name.</param>
81-
/// <returns>Cookie or null if not found.</returns>
82-
public Cookie? FindCookie(string name) => GetCookies().FirstOrDefault(c => c.Name == name);
83-
84-
/// <summary>
85-
/// Gets array of currently active cookies.
86-
/// </summary>
87-
/// <returns>Active cookies.</returns>
88-
public Cookie[] GetCookies()
77+
/// <summary>
78+
/// Retrieves a cookie by name.
79+
/// </summary>
80+
/// <param name="name">Cookie name.</param>
81+
/// <returns>Cookie or null if not found.</returns>
82+
public Cookie? FindCookie(string name) => GetCookies().FirstOrDefault(c => c.Name == name);
83+
84+
/// <summary>
85+
/// Gets array of currently active cookies.
86+
/// </summary>
87+
/// <returns>Active cookies.</returns>
88+
public Cookie[] GetCookies()
89+
{
90+
Cookie? ParseCookie(string cookieString)
8991
{
90-
Cookie? ParseCookie(string cookieString)
92+
cookieString = cookieString.Trim();
93+
var valueSeparatorIndex = cookieString.IndexOf(ValueSeparator);
94+
if (valueSeparatorIndex == -1)
9195
{
92-
cookieString = cookieString.Trim();
93-
var valueSeparatorIndex = cookieString.IndexOf(ValueSeparator);
94-
if (valueSeparatorIndex == -1)
95-
{
96-
return null;
97-
}
98-
99-
var name = cookieString.Substring(0, valueSeparatorIndex);
100-
var valueStartIndex = valueSeparatorIndex + 1;
101-
var value = cookieString.Substring(valueStartIndex, cookieString.Length - valueStartIndex);
102-
return new Cookie(name, value);
96+
return null;
10397
}
10498

105-
var cookies = WebAssemblyRuntime.InvokeJS("document.cookie");
106-
if (string.IsNullOrWhiteSpace(cookies))
107-
{
108-
return Array.Empty<Cookie>();
109-
}
99+
var name = cookieString.Substring(0, valueSeparatorIndex);
100+
var valueStartIndex = valueSeparatorIndex + 1;
101+
var value = cookieString.Substring(valueStartIndex, cookieString.Length - valueStartIndex);
102+
return new Cookie(name, value);
103+
}
110104

111-
var cookieStrings = cookies.Split(new char[] { AttributeSeparator }, StringSplitOptions.RemoveEmptyEntries);
112-
return cookieStrings
113-
.Select(part => ParseCookie(part))
114-
.Where(cookie => cookie != null)
115-
.OfType<Cookie>()
116-
.ToArray();
105+
var cookies = WebAssemblyRuntime.InvokeJS("document.cookie");
106+
if (string.IsNullOrWhiteSpace(cookies))
107+
{
108+
return Array.Empty<Cookie>();
117109
}
110+
111+
var cookieStrings = cookies.Split(new char[] { AttributeSeparator }, StringSplitOptions.RemoveEmptyEntries);
112+
return cookieStrings
113+
.Select(part => ParseCookie(part))
114+
.Where(cookie => cookie != null)
115+
.OfType<Cookie>()
116+
.ToArray();
118117
}
119118
}
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
1-
namespace Uno.Web.Http
1+
namespace Uno.Web.Http;
2+
3+
/// <summary>
4+
/// Represents the valid options for the same-site
5+
/// attribute of HTTP cookies.
6+
/// </summary>
7+
public enum CookieSameSite
28
{
39
/// <summary>
4-
/// Represents the valid options for the same-site
5-
/// attribute of HTTP cookies.
10+
/// Cookies are not sent on normal cross-site subrequests (for example to load images or frames into a third party site),
11+
/// but are sent when a user is navigating to the origin site (i.e. when following a link).
12+
/// This is the default value when not specified.
613
/// </summary>
7-
public enum CookieSameSite
8-
{
9-
/// <summary>
10-
/// Cookies are not sent on normal cross-site subrequests (for example to load images or frames into a third party site),
11-
/// but are sent when a user is navigating to the origin site (i.e. when following a link).
12-
/// This is the default value when not specified.
13-
/// </summary>
14-
Lax,
14+
Lax,
1515

16-
/// <summary>
17-
/// Cookies will only be sent in a first-party context and not be sent along with requests initiated by third party websites.
18-
/// </summary>
19-
Strict,
16+
/// <summary>
17+
/// Cookies will only be sent in a first-party context and not be sent along with requests initiated by third party websites.
18+
/// </summary>
19+
Strict,
2020

21-
/// <summary>
22-
/// Cookies will be sent in all contexts, i.e in responses to both first-party and cross-origin requests.If SameSite=None is set,
23-
/// the cookie Secure attribute must also be set (or the cookie will be blocked).
24-
/// </summary>
25-
None
26-
}
21+
/// <summary>
22+
/// Cookies will be sent in all contexts, i.e in responses to both first-party and cross-origin requests.If SameSite=None is set,
23+
/// the cookie Secure attribute must also be set (or the cookie will be blocked).
24+
/// </summary>
25+
None
2726
}

0 commit comments

Comments
 (0)