Skip to content

Commit 1238854

Browse files
authored
Merge pull request #1 from freosc/CookieHandling
Implementation for electronjs cookie handling
2 parents 6d0fbde + d409c3a commit 1238854

File tree

9 files changed

+413
-1
lines changed

9 files changed

+413
-1
lines changed

ElectronNET.API/Cookies.cs

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using ElectronNET.API.Entities;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Linq;
6+
using Newtonsoft.Json.Serialization;
7+
8+
namespace ElectronNET.API
9+
{
10+
/// <summary>
11+
/// Query and modify a session's cookies.
12+
/// </summary>
13+
public class Cookies
14+
{
15+
/// <summary>
16+
/// Gets the identifier.
17+
/// </summary>
18+
/// <value>
19+
/// The identifier.
20+
/// </value>
21+
public int Id { get; private set; }
22+
23+
internal Cookies(int id)
24+
{
25+
Id = id;
26+
}
27+
28+
/// <summary>
29+
/// Emitted when a cookie is changed because it was added, edited, removed, or expired.
30+
/// </summary>
31+
public event Action<Cookie, CookieChangedCause, bool> OnChanged
32+
{
33+
add
34+
{
35+
if (_changed == null)
36+
{
37+
BridgeConnector.Socket.On("webContents-session-cookies-changed" + Id, (args) =>
38+
{
39+
Cookie cookie = ((JArray)args)[0].ToObject<Cookie>();
40+
CookieChangedCause cause = ((JArray)args)[1].ToObject<CookieChangedCause>();
41+
bool removed = ((JArray)args)[2].ToObject<bool>();
42+
_changed(cookie, cause, removed);
43+
});
44+
45+
BridgeConnector.Socket.Emit("register-webContents-session-cookies-changed", Id);
46+
}
47+
_changed += value;
48+
}
49+
remove
50+
{
51+
_changed -= value;
52+
53+
if (_changed == null)
54+
BridgeConnector.Socket.Off("webContents-session-cookies-changed" + Id);
55+
}
56+
}
57+
58+
private event Action<Cookie, CookieChangedCause, bool> _changed;
59+
60+
/// <summary>
61+
/// Sends a request to get all cookies matching filter, and resolves a callack with the response.
62+
/// </summary>
63+
/// <param name="filter">
64+
/// </param>
65+
/// <returns>A task which resolves an array of cookie objects.</returns>
66+
public Task<Cookie[]> GetAsync(CookieFilter filter)
67+
{
68+
var taskCompletionSource = new TaskCompletionSource<Cookie[]>();
69+
string guid = Guid.NewGuid().ToString();
70+
71+
BridgeConnector.Socket.On("webContents-session-cookies-get-completed" + guid, (cookies) =>
72+
{
73+
Cookie[] result = ((JArray)cookies).ToObject<Cookie[]>();
74+
75+
BridgeConnector.Socket.Off("webContents-session-cookies-get-completed" + guid);
76+
taskCompletionSource.SetResult(result);
77+
});
78+
79+
BridgeConnector.Socket.Emit("webContents-session-cookies-get", Id, JObject.FromObject(filter, _jsonSerializer), guid);
80+
81+
return taskCompletionSource.Task;
82+
}
83+
84+
/// <summary>
85+
///
86+
/// </summary>
87+
/// <param name="details"></param>
88+
/// <returns></returns>
89+
public Task SetAsync(CookieDetails details)
90+
{
91+
var taskCompletionSource = new TaskCompletionSource<object>();
92+
string guid = Guid.NewGuid().ToString();
93+
94+
BridgeConnector.Socket.On("webContents-session-cookies-set-completed" + guid, () =>
95+
{
96+
BridgeConnector.Socket.Off("webContents-session-cookies-set-completed" + guid);
97+
taskCompletionSource.SetResult(null);
98+
});
99+
100+
BridgeConnector.Socket.Emit("webContents-session-cookies-set", Id, JObject.FromObject(details, _jsonSerializer), guid);
101+
102+
return taskCompletionSource.Task;
103+
}
104+
105+
/// <summary>
106+
/// Removes the cookies matching url and name
107+
/// </summary>
108+
/// <param name="url">The URL associated with the cookie.</param>
109+
/// <param name="name">The name of cookie to remove.</param>
110+
/// <returns>A task which resolves when the cookie has been removed</returns>
111+
public Task RemoveAsync(string url, string name)
112+
{
113+
var taskCompletionSource = new TaskCompletionSource<object>();
114+
string guid = Guid.NewGuid().ToString();
115+
116+
BridgeConnector.Socket.On("webContents-session-cookies-remove-completed" + guid, () =>
117+
{
118+
BridgeConnector.Socket.Off("webContents-session-cookies-remove-completed" + guid);
119+
taskCompletionSource.SetResult(null);
120+
});
121+
122+
BridgeConnector.Socket.Emit("webContents-session-cookies-remove", Id, url, name, guid);
123+
124+
return taskCompletionSource.Task;
125+
}
126+
127+
/// <summary>
128+
/// Writes any unwritten cookies data to disk.
129+
/// </summary>
130+
/// <returns>A task which resolves when the cookie store has been flushed</returns>
131+
public Task FlushStoreAsync()
132+
{
133+
var taskCompletionSource = new TaskCompletionSource<object>();
134+
string guid = Guid.NewGuid().ToString();
135+
136+
BridgeConnector.Socket.On("webContents-session-cookies-flushStore-completed" + guid, () =>
137+
{
138+
BridgeConnector.Socket.Off("webContents-session-cookies-flushStore-completed" + guid);
139+
taskCompletionSource.SetResult(null);
140+
});
141+
142+
BridgeConnector.Socket.Emit("webContents-session-cookies-flushStore", Id, guid);
143+
144+
return taskCompletionSource.Task;
145+
}
146+
147+
private JsonSerializer _jsonSerializer = new JsonSerializer()
148+
{
149+
ContractResolver = new CamelCasePropertyNamesContractResolver(),
150+
NullValueHandling = NullValueHandling.Ignore,
151+
DefaultValueHandling = DefaultValueHandling.Ignore
152+
};
153+
}
154+
}

ElectronNET.API/Entities/Cookie.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
namespace ElectronNET.API.Entities {
2+
/// <summary>
3+
///
4+
/// </summary>
5+
public class Cookie {
6+
/// <summary>
7+
/// The name of the cookie.
8+
/// </summary>
9+
public string Name { get; set;}
10+
11+
/// <summary>
12+
/// The value of the cookie.
13+
/// </summary>
14+
public string Value { get; set; }
15+
16+
/// <summary>
17+
/// (optional) - The domain of the cookie; this will be normalized with a preceding dot so that it's also valid for subdomains.
18+
/// </summary>
19+
public string Domain { get; set; }
20+
21+
/// <summary>
22+
/// (optional) - Whether the cookie is a host-only cookie; this will only be true if no domain was passed.
23+
/// </summary>
24+
public bool HostOnly { get; set; }
25+
26+
/// <summary>
27+
/// (optional) - The path of the cookie.
28+
/// </summary>
29+
public string Path { get; set; }
30+
31+
/// <summary>
32+
/// (optional) - Whether the cookie is marked as secure.
33+
/// </summary>
34+
public bool Secure { get; set; }
35+
36+
/// <summary>
37+
/// (optional) - Whether the cookie is marked as HTTP only.
38+
/// </summary>
39+
public bool HttpOnly { get; set; }
40+
41+
/// <summary>
42+
/// (optional) - Whether the cookie is a session cookie or a persistent cookie with an expiration date.
43+
/// </summary>
44+
public bool Session { get; set; }
45+
46+
/// <summary>
47+
/// (optional) - The expiration date of the cookie as the number of seconds since the UNIX epoch. Not provided for session cookies.
48+
/// </summary>
49+
public long ExpirationDate { get; set; }
50+
}
51+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Newtonsoft.Json;
2+
using Newtonsoft.Json.Converters;
3+
4+
namespace ElectronNET.API.Entities {
5+
/// <summary>
6+
/// The cause of the change
7+
/// </summary>
8+
[JsonConverter(typeof(StringEnumConverter))]
9+
public enum CookieChangedCause
10+
{
11+
/// <summary>
12+
///The cookie was changed directly by a consumer's action.
13+
/// </summary>
14+
[JsonProperty("explicit")]
15+
@explicit,
16+
17+
/// <summary>
18+
/// The cookie was automatically removed due to an insert operation that overwrote it.
19+
/// </summary>
20+
overwrite,
21+
22+
/// <summary>
23+
/// The cookie was automatically removed as it expired.
24+
/// </summary>
25+
expired,
26+
27+
/// <summary>
28+
/// The cookie was automatically evicted during garbage collection.
29+
/// </summary>
30+
evicted,
31+
32+
/// <summary>
33+
/// The cookie was overwritten with an already-expired expiration date.
34+
/// </summary>
35+
[JsonProperty("expired_overwrite")]
36+
expiredOverwrite
37+
}
38+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System.ComponentModel;
2+
3+
namespace ElectronNET.API.Entities {
4+
/// <summary>
5+
///
6+
/// </summary>
7+
public class CookieDetails {
8+
/// <summary>
9+
/// The URL to associate the cookie with. The callback will be rejected if the URL is invalid.
10+
/// </summary>
11+
public string Url { get; set; }
12+
13+
/// <summary>
14+
/// (optional) - The name of the cookie. Empty by default if omitted.
15+
/// </summary>
16+
[DefaultValue("")]
17+
public string Name { get; set; }
18+
19+
/// <summary>
20+
/// (optional) - The value of the cookie. Empty by default if omitted.
21+
/// </summary>
22+
[DefaultValue("")]
23+
public string Value { get; set; }
24+
25+
/// <summary>
26+
/// (optional) - The domain of the cookie; this will be normalized with a preceding dot so that it's also valid for subdomains. Empty by default if omitted.
27+
/// </summary>
28+
[DefaultValue("")]
29+
public string Domain { get; set; }
30+
31+
/// <summary>
32+
/// (optional) - The path of the cookie. Empty by default if omitted.
33+
/// </summary>
34+
[DefaultValue("")]
35+
public string Path { get; set; }
36+
37+
/// <summary>
38+
/// (optional) - Whether the cookie is marked as secure. Defaults to false.
39+
/// </summary>
40+
[DefaultValue(false)]
41+
public bool Secure { get; set; }
42+
43+
/// <summary>
44+
/// (optional) - Whether the cookie is marked as HTTP only. Defaults to false.
45+
/// </summary>
46+
[DefaultValue(false)]
47+
public bool HttpOnly { get; set; }
48+
49+
/// <summary>
50+
/// (optional) - The expiration date of the cookie as the number of seconds since the UNIX epoch.
51+
/// If omitted then the cookie becomes a session cookie and will not be retained between sessions.
52+
/// </summary>
53+
[DefaultValue(0)]
54+
public long ExpirationDate { get; set; }
55+
}
56+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace ElectronNET.API.Entities
6+
{
7+
/// <summary>
8+
///
9+
/// </summary>
10+
public class CookieFilter
11+
{
12+
/// <summary>
13+
/// (optional) - Retrieves cookies which are associated with url.Empty implies retrieving cookies of all URLs.
14+
/// </summary>
15+
public string Url { get; set; }
16+
17+
/// <summary>
18+
/// (optional) - Filters cookies by name.
19+
/// </summary>
20+
public string Name { get; set; }
21+
22+
/// <summary>
23+
/// (optional) - Retrieves cookies whose domains match or are subdomains of domains.
24+
/// </summary>
25+
public string Domain { get; set; }
26+
27+
/// <summary>
28+
/// (optional) - Retrieves cookies whose path matches path.
29+
/// </summary>
30+
public string Path { get; set; }
31+
32+
/// <summary>
33+
/// (optional) - Filters cookies by their Secure property.
34+
/// </summary>
35+
public bool Secure { get; set; }
36+
37+
/// <summary>
38+
/// (optional) - Filters out session or persistent cookies.
39+
/// </summary>
40+
public bool Session { get; set; }
41+
42+
}
43+
}

ElectronNET.API/Session.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,15 @@ public class Session
2020
/// </value>
2121
public int Id { get; private set; }
2222

23+
/// <summary>
24+
/// Query and modify a session's cookies.
25+
/// </summary>
26+
public Cookies Cookies { get; }
27+
2328
internal Session(int id)
2429
{
2530
Id = id;
31+
Cookies = new Cookies(id);
2632
}
2733

2834
/// <summary>

ElectronNET.Host/api/webContents.js

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)