Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
25 changes: 20 additions & 5 deletions src/Foundation/NSUrlSessionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -399,27 +399,42 @@ public CookieContainer? CookieContainer {
}
}

/// <summary>Enable or disable the use of cookies.</summary>
/// <remarks>
/// <para>
/// For default and background sessions, the shared cookie storage (<see cref="NSHttpCookieStorage.SharedStorage" /> will be used.
/// This shared cookie storage will persist beyond app restarts; to clear the cookies call <c>NSHttpCookieStorage.SharedStorage.RemoveCookiesSinceDate(NSDate.DistantPast)</c>.
/// To use a custom cookie storage, use a custom <see cref="NSUrlSessionConfiguration" />, set the <see cref="NSUrlSessionConfiguration.HttpCookieStorage" /> property, and then pass in the custom session configuration when creating the <see cref="NSUrlSessionHandler(NSUrlSessionConfiguration)" />.
/// </para>
/// <para>Ephemeral sessions have by default a private cookie storage area. This private cookie storage area can't be recreated, which means that if the use of cookies is disabled, then it can't be re-enabled.</para>
/// </remarks>
public bool UseCookies {
get {
return session.Configuration.HttpCookieStorage is not null;
}
set {
EnsureModifiability ();
if (sessionType == NSUrlSessionConfiguration.SessionConfigurationType.Ephemeral)
throw new InvalidOperationException ("Cannot set the use of cookies in Ephemeral sessions.");

// first check if anything changed
if (value == UseCookies)
return;

// we have to consider the following table of cases:
// 1. Value is set to true and cookie storage is not null -> we do nothing
// 1. Value is set to true and cookie storage is not null -> we do nothing (already handled above)
// 2. Value is set to true and cookie storage is null -> we create/set the storage.
// 3. Value is false and cookie container is not null -> we clear the cookie storage
// 4. Value is false and cookie container is null -> we do nothing
// 4. Value is false and cookie container is null -> we do nothing (already handled above)
var oldSession = session;
var configuration = session.Configuration;
if (value && configuration.HttpCookieStorage is null) {
// create storage because the user wants to use it. Things are not that easy, we have to
// consider the following:
// 1. Default Session -> uses sharedHTTPCookieStorage
// 2. Background Session -> uses sharedHTTPCookieStorage
// 3. Ephemeral Session -> no allowed. apple does not provide a way to access to the private implementation of the storage class :/
// 3. Ephemeral Session -> we can't create an instance of a private cookie storage. Note that ephemeral sessions have a private cookie storage by default, so this can only happen if the developer disables cookies, and then re-enables them.
if (sessionType == NSUrlSessionConfiguration.SessionConfigurationType.Ephemeral)
throw new InvalidOperationException ("Can't re-enable the use of cookies in Ephemeral sessions.");

configuration.HttpCookieStorage = NSHttpCookieStorage.SharedStorage;
}
if (!value && configuration.HttpCookieStorage is not null) {
Expand Down
65 changes: 49 additions & 16 deletions tests/monotouch-test/System.Net.Http/MessageHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,22 @@ public void DnsFailure (Type handlerType)
Assert.IsInstanceOf (typeof (HttpRequestException), ex, "Exception");
}

// ensure that we do get the same cookies as the managed handler
// ensure that we do get the same cookies as the managed handler for the default session
[Test]
public void TestNSUrlSessionHandlerCookies ()
{
TestNSUrlSessionHandlerCookiesImpl (new NSUrlSessionHandler ());
}

// ensure that we do get the same cookies as the managed handler for ephemeral sessions
[Test]
public void TestNSUrlSessionEphemeralHandlerCookies ()
{
using var ephemeralConfig = NSUrlSessionConfiguration.EphemeralSessionConfiguration;
TestNSUrlSessionHandlerCookiesImpl (new NSUrlSessionHandler (ephemeralConfig));
}

void TestNSUrlSessionHandlerCookiesImpl (NSUrlSessionHandler nativeHandler)
{
var managedCookieResult = false;
var nativeCookieResult = false;
Expand All @@ -82,13 +95,12 @@ public void TestNSUrlSessionHandlerCookies ()
var managedResponse = await managedClient.GetAsync (url);
managedCookieResult = managedResponse.Headers.TryGetValues ("Set-Cookie", out managedCookies);

var nativeHandler = new NSUrlSessionHandler () {
AllowAutoRedirect = false,
};
nativeHandler.AllowAutoRedirect = true;
var nativeClient = new HttpClient (nativeHandler);
var nativeResponse = await nativeClient.GetAsync (url);
nativeCookieResult = nativeResponse.Headers.TryGetValues ("Set-Cookie", out nativeCookies);

Assert.That (nativeHandler.UseCookies, Is.EqualTo (true), "UseCookies");
}, out var ex);

if (!completed || !managedCookieResult || !nativeCookieResult)
Expand All @@ -106,6 +118,18 @@ public void TestNSUrlSessionHandlerCookies ()
// ensure that we can use a cookie container to set the cookies for a url
[Test]
public void TestNSUrlSessionHandlerCookieContainer ()
{
TestNSUrlSessionHandlerCookieContainerImpl (new NSUrlSessionHandler ());
}

[Test]
public void TestNSUrlSessionEphemeralHandlerCookieContainer ()
{
using var ephemeralConfig = NSUrlSessionConfiguration.EphemeralSessionConfiguration;
TestNSUrlSessionHandlerCookieContainerImpl (new NSUrlSessionHandler (ephemeralConfig));
}

void TestNSUrlSessionHandlerCookieContainerImpl (NSUrlSessionHandler nativeHandler)
{
var url = NetworkResources.Httpbin.CookiesUrl;
var cookie = new Cookie ("cookie", "chocolate-chip");
Expand All @@ -124,10 +148,8 @@ public void TestNSUrlSessionHandlerCookieContainer ()
var managedResponse = await managedClient.GetAsync (url);
managedCookieResult = await managedResponse.Content.ReadAsStringAsync ();

var nativeHandler = new NSUrlSessionHandler () {
AllowAutoRedirect = true,
CookieContainer = cookieContainer,
};
nativeHandler.AllowAutoRedirect = true;
nativeHandler.CookieContainer = cookieContainer;
var nativeClient = new HttpClient (nativeHandler);
var nativeResponse = await nativeClient.GetAsync (url);
nativeCookieResult = await nativeResponse.Content.ReadAsStringAsync ();
Expand Down Expand Up @@ -255,14 +277,25 @@ public void TestNSUrlSessionDefaultDisableCookiesWithManagedContainer ()
[Test]
public void TestNSUrlSessionEphemeralDisabledCookies ()
{
// assert we do throw an exception with ephmeral configs.
using (var config = NSUrlSessionConfiguration.EphemeralSessionConfiguration) {
Assert.True (config.SessionType == NSUrlSessionConfiguration.SessionConfigurationType.Ephemeral, "Session type.");
var nativeHandler = new NSUrlSessionHandler (config);
Assert.Throws<InvalidOperationException> (() => {
nativeHandler.UseCookies = false;
});
}
// assert that we can't re-enable cookies for ephemeral sessions
using var config = NSUrlSessionConfiguration.EphemeralSessionConfiguration;
Assert.That (config.SessionType, Is.EqualTo (NSUrlSessionConfiguration.SessionConfigurationType.Ephemeral), "Session type.");
var nativeHandler = new NSUrlSessionHandler (config);
Assert.That (nativeHandler.UseCookies, Is.EqualTo (true), "UseCookies #1");
nativeHandler.UseCookies = true;
Assert.That (nativeHandler.UseCookies, Is.EqualTo (true), "UseCookies #2");
nativeHandler.UseCookies = false;
Assert.That (nativeHandler.UseCookies, Is.EqualTo (false), "UseCookies #3");
nativeHandler.UseCookies = false;
Assert.That (nativeHandler.UseCookies, Is.EqualTo (false), "UseCookies #4");
Assert.Throws<InvalidOperationException> (() => {
nativeHandler.UseCookies = true;
}, "UseCookies #5");
Assert.That (nativeHandler.UseCookies, Is.EqualTo (false), "UseCookies #6");
Assert.Throws<InvalidOperationException> (() => {
nativeHandler.UseCookies = true;
}, "UseCookies #7");
Assert.That (nativeHandler.UseCookies, Is.EqualTo (false), "UseCookies #8");
}

[Test]
Expand Down
Loading