Refactor default and auto-logon tile handling

Refactored `CredentialProviderBase` and `CredentialTile` to improve the handling of default and auto-logon tiles. Key changes include:

- Introduced `SetDefaultTile` method with validation and tile refresh.
- Refactored `IsAutoLogon` and `IsDefault` properties to be read only properties.
- Added `ShouldAutoLogon` method to be called when a tile is selected.
This commit is contained in:
Ryan Newington
2024-10-21 06:43:05 +11:00
parent 96bff2852a
commit 3fe3999e0d
4 changed files with 47 additions and 29 deletions
@@ -169,23 +169,20 @@ namespace Lithnet.CredentialProvider
this.notifyOnTileCollectionChange = true; this.notifyOnTileCollectionChange = true;
var autoLogonTile = this.Tiles.FirstOrDefault(t => t.IsAutoLogon); var defaultTile = this.DefaultTile;
var defaultTile = this.Tiles.FirstOrDefault(t => t.IsDefault);
uint defaultIndex = CREDENTIAL_PROVIDER_NO_DEFAULT; if (defaultTile != null)
if (autoLogonTile != null)
{ {
defaultIndex = (uint)this.tiles.IndexOf(autoLogonTile); var index = this.tiles.IndexOf(defaultTile);
if (index >= 0)
{
pdwDefault = (uint)index;
pbAutoLogonWithDefault = this.DefaultTileAutoLogon ? 1 : 0;
} }
else if (defaultTile != null)
{
defaultIndex = (uint)this.tiles.IndexOf(defaultTile);
} }
pdwCount = (uint)this.Tiles.Count; pdwCount = (uint)this.Tiles.Count;
pdwDefault = defaultIndex;
pbAutoLogonWithDefault = autoLogonTile == null ? 0 : 1;
this.logger.LogTrace($"GetCredentialCount returning pdwCount: {pdwCount}, pdwDefault: {pdwDefault}, pbAutoLogonWithDefault: {pbAutoLogonWithDefault}"); this.logger.LogTrace($"GetCredentialCount returning pdwCount: {pdwCount}, pdwDefault: {pdwDefault}, pbAutoLogonWithDefault: {pbAutoLogonWithDefault}");
return HRESULT.S_OK; return HRESULT.S_OK;
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Lithnet.CredentialProvider.Interop; using Lithnet.CredentialProvider.Interop;
@@ -115,6 +116,27 @@ namespace Lithnet.CredentialProvider
/// </summary> /// </summary>
public abstract bool ShouldIncludeGenericTile(); public abstract bool ShouldIncludeGenericTile();
protected internal CredentialTile DefaultTile { get; set; }
protected internal bool DefaultTileAutoLogon { get; set; }
public void SetDefaultTile(CredentialTile tile, bool autoLogon)
{
if (this.DefaultTile == tile && this.DefaultTileAutoLogon == autoLogon)
{
return;
}
if (!this.Tiles.Contains(tile))
{
throw new InvalidOperationException("The default tile must be one of the tiles provided by the credential provider");
}
this.DefaultTile = tile;
this.DefaultTileAutoLogon = autoLogon;
this.ReloadUserTiles();
}
/// <summary> /// <summary>
/// Notifies LogonUI that one of more of the tile items has been modified, and should be reloaded /// Notifies LogonUI that one of more of the tile items has been modified, and should be reloaded
/// </summary> /// </summary>
@@ -66,8 +66,8 @@ namespace Lithnet.CredentialProvider
{ {
this.logger.LogTrace("SetSelected"); this.logger.LogTrace("SetSelected");
this.IsSelected = true; this.IsSelected = true;
this.OnSelected(out bool autoLogon); this.OnSelected();
pbAutoLogon = autoLogon ? 1 : 0; pbAutoLogon = this.ShouldAutoLogon() ? 1 : 0;
return HRESULT.S_OK; return HRESULT.S_OK;
} }
catch (Exception ex) catch (Exception ex)
@@ -40,19 +40,16 @@ namespace Lithnet.CredentialProvider
/// </summary> /// </summary>
public bool IsAutoLogon public bool IsAutoLogon
{ {
get => this.isAutoLogon; get => this.CredentialProvider.DefaultTile == this && this.CredentialProvider.DefaultTileAutoLogon;
set
{
this.isAutoLogon = value;
this.CredentialProvider.ReloadUserTiles();
}
} }
/// <summary> /// <summary>
/// Gets a value indicating if this should be the default time /// Gets a value indicating if this should be the default tile
/// </summary> /// </summary>
public bool IsDefault { get; set; } public bool IsDefault
{
get => this.CredentialProvider.DefaultTile == this;
}
/// <summary> /// <summary>
/// Gets the current usage scenario /// Gets the current usage scenario
@@ -164,14 +161,16 @@ namespace Lithnet.CredentialProvider
/// <summary> /// <summary>
/// Called when the user selects this tile /// Called when the user selects this tile
/// </summary> /// </summary>
/// <param name="autoLogon">A value that indicates if logon should be performed immediately, without waiting for further user input</param> protected virtual void OnSelected() { }
/// <summary>
/// Called after a tiles is selected to determine if the user should be automatically logged on
/// </summary>
/// <returns>True, if a logon should be immediately attempted</returns>
/// <remarks> /// <remarks>
/// In Windows 10, if a credential provider wants to automatically log the user on in a situation Windows does not think is appropriate, the system will display a sign in button as a speed bump. One example of this is when a user with an empty password locks the computer or signs out. In that scenario, Windows does not directly log the user back in. /// In Windows 10, if a credential provider wants to automatically log the user on in a situation Windows does not think is appropriate, the system will display a sign in button as a speed bump. One example of this is when a user with an empty password locks the computer or signs out. In that scenario, Windows does not directly log the user back in.
/// </remarks> /// </remarks>
protected virtual void OnSelected(out bool autoLogon) protected virtual bool ShouldAutoLogon() => false;
{
autoLogon = false;
}
/// <summary> /// <summary>
/// Called when a user deselects this tile /// Called when a user deselects this tile