mirror of
https://github.com/bitwarden/android.git
synced 2024-12-24 18:08:26 +03:00
add other items to autofill from app page
This commit is contained in:
parent
6268130998
commit
84e79e92b4
9 changed files with 89 additions and 49 deletions
|
@ -8,6 +8,7 @@ using Android.App;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
|
using Bit.App.Enums;
|
||||||
|
|
||||||
namespace Bit.Android.Autofill
|
namespace Bit.Android.Autofill
|
||||||
{
|
{
|
||||||
|
@ -33,7 +34,7 @@ namespace Bit.Android.Autofill
|
||||||
else if(parser.FieldCollection.FillableForCard)
|
else if(parser.FieldCollection.FillableForCard)
|
||||||
{
|
{
|
||||||
var ciphers = await service.GetAllAsync();
|
var ciphers = await service.GetAllAsync();
|
||||||
foreach(var cipher in ciphers.Where(c => c.Type == App.Enums.CipherType.Card))
|
foreach(var cipher in ciphers.Where(c => c.Type == CipherType.Card))
|
||||||
{
|
{
|
||||||
items.Add(new FilledItem(cipher));
|
items.Add(new FilledItem(cipher));
|
||||||
}
|
}
|
||||||
|
@ -80,6 +81,22 @@ namespace Bit.Android.Autofill
|
||||||
AppResources.VaultIsLocked, Resource.Drawable.icon);
|
AppResources.VaultIsLocked, Resource.Drawable.icon);
|
||||||
var intent = new Intent(context, typeof(MainActivity));
|
var intent = new Intent(context, typeof(MainActivity));
|
||||||
intent.PutExtra("autofillFramework", true);
|
intent.PutExtra("autofillFramework", true);
|
||||||
|
if(fields.FillableForLogin)
|
||||||
|
{
|
||||||
|
intent.PutExtra("autofillFrameworkFillType", (int)CipherType.Login);
|
||||||
|
}
|
||||||
|
else if(fields.FillableForCard)
|
||||||
|
{
|
||||||
|
intent.PutExtra("autofillFrameworkFillType", (int)CipherType.Card);
|
||||||
|
}
|
||||||
|
else if(fields.FillableForIdentity)
|
||||||
|
{
|
||||||
|
intent.PutExtra("autofillFrameworkFillType", (int)CipherType.Identity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
intent.PutExtra("autofillFrameworkUri", uri);
|
intent.PutExtra("autofillFrameworkUri", uri);
|
||||||
var pendingIntent = PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent);
|
var pendingIntent = PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent);
|
||||||
responseBuilder.SetAuthentication(fields.AutofillIds.ToArray(), pendingIntent.IntentSender, view);
|
responseBuilder.SetAuthentication(fields.AutofillIds.ToArray(), pendingIntent.IntentSender, view);
|
||||||
|
|
|
@ -4,7 +4,6 @@ using Android.Views.Autofill;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Bit.App.Models;
|
using Bit.App.Models;
|
||||||
using Bit.App.Enums;
|
using Bit.App.Enums;
|
||||||
using Bit.App.Models.Page;
|
|
||||||
using Android.Views;
|
using Android.Views;
|
||||||
|
|
||||||
namespace Bit.Android.Autofill
|
namespace Bit.Android.Autofill
|
||||||
|
@ -107,23 +106,6 @@ namespace Bit.Android.Autofill
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FilledItem(VaultListPageModel.Cipher cipher)
|
|
||||||
{
|
|
||||||
Name = cipher.Name ?? "--";
|
|
||||||
Type = cipher.Type;
|
|
||||||
|
|
||||||
switch(Type)
|
|
||||||
{
|
|
||||||
case CipherType.Login:
|
|
||||||
Subtitle = cipher.LoginUsername ?? string.Empty;
|
|
||||||
_password = cipher.LoginPassword;
|
|
||||||
Icon = Resource.Drawable.login;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Subtitle { get; set; } = string.Empty;
|
public string Subtitle { get; set; } = string.Empty;
|
||||||
public int Icon { get; set; } = Resource.Drawable.login;
|
public int Icon { get; set; } = Resource.Drawable.login;
|
||||||
|
|
|
@ -169,7 +169,7 @@ namespace Bit.Android
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var items = new List<FilledItem> { new FilledItem(cipher) };
|
var items = new List<FilledItem> { new FilledItem(cipher.CipherModel) };
|
||||||
var response = AutofillHelpers.BuildFillResponse(this, parser, items);
|
var response = AutofillHelpers.BuildFillResponse(this, parser, items);
|
||||||
var replyIntent = new Intent();
|
var replyIntent = new Intent();
|
||||||
replyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, response);
|
replyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, response);
|
||||||
|
@ -435,6 +435,12 @@ namespace Bit.Android
|
||||||
FromAutofillFramework = Intent.GetBooleanExtra("autofillFramework", false)
|
FromAutofillFramework = Intent.GetBooleanExtra("autofillFramework", false)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var fillType = Intent.GetIntExtra("autofillFrameworkFillType", 0);
|
||||||
|
if(fillType > 0)
|
||||||
|
{
|
||||||
|
options.FillType = (CipherType)fillType;
|
||||||
|
}
|
||||||
|
|
||||||
if(Intent.GetBooleanExtra("autofillFrameworkSave", false))
|
if(Intent.GetBooleanExtra("autofillFrameworkSave", false))
|
||||||
{
|
{
|
||||||
options.SaveType = (CipherType)Intent.GetIntExtra("autofillFrameworkType", 0);
|
options.SaveType = (CipherType)Intent.GetIntExtra("autofillFrameworkType", 0);
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Bit.App.Abstractions
|
||||||
Task<Cipher> GetByIdAsync(string id);
|
Task<Cipher> GetByIdAsync(string id);
|
||||||
Task<IEnumerable<Cipher>> GetAllAsync();
|
Task<IEnumerable<Cipher>> GetAllAsync();
|
||||||
Task<IEnumerable<Cipher>> GetAllAsync(bool favorites);
|
Task<IEnumerable<Cipher>> GetAllAsync(bool favorites);
|
||||||
Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString);
|
Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString);
|
||||||
Task<ApiResult<CipherResponse>> SaveAsync(Cipher cipher);
|
Task<ApiResult<CipherResponse>> SaveAsync(Cipher cipher);
|
||||||
Task UpsertDataAsync(CipherData cipher);
|
Task UpsertDataAsync(CipherData cipher);
|
||||||
Task<ApiResult> DeleteAsync(string id);
|
Task<ApiResult> DeleteAsync(string id);
|
||||||
|
|
|
@ -74,7 +74,7 @@ namespace Bit.App
|
||||||
}
|
}
|
||||||
else if(_options.Uri != null)
|
else if(_options.Uri != null)
|
||||||
{
|
{
|
||||||
MainPage = new ExtendedNavigationPage(new VaultAutofillListCiphersPage(_options.Uri));
|
MainPage = new ExtendedNavigationPage(new VaultAutofillListCiphersPage(_options));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace Bit.App.Models
|
||||||
{
|
{
|
||||||
public bool MyVault { get; set; }
|
public bool MyVault { get; set; }
|
||||||
public bool FromAutofillFramework { get; set; }
|
public bool FromAutofillFramework { get; set; }
|
||||||
|
public CipherType? FillType { get; set; }
|
||||||
public string Uri { get; set; }
|
public string Uri { get; set; }
|
||||||
public CipherType? SaveType { get; set; }
|
public CipherType? SaveType { get; set; }
|
||||||
public string SaveName { get; set; }
|
public string SaveName { get; set; }
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace Bit.App.Models.Page
|
||||||
{
|
{
|
||||||
public Cipher(Models.Cipher cipher, IAppSettingsService appSettings)
|
public Cipher(Models.Cipher cipher, IAppSettingsService appSettings)
|
||||||
{
|
{
|
||||||
|
CipherModel = cipher;
|
||||||
Id = cipher.Id;
|
Id = cipher.Id;
|
||||||
Shared = !string.IsNullOrWhiteSpace(cipher.OrganizationId);
|
Shared = !string.IsNullOrWhiteSpace(cipher.OrganizationId);
|
||||||
HasAttachments = cipher.Attachments?.Any() ?? false;
|
HasAttachments = cipher.Attachments?.Any() ?? false;
|
||||||
|
@ -114,6 +115,7 @@ namespace Bit.App.Models.Page
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Models.Cipher CipherModel { get; set; }
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public bool Shared { get; set; }
|
public bool Shared { get; set; }
|
||||||
public bool HasAttachments { get; set; }
|
public bool HasAttachments { get; set; }
|
||||||
|
|
|
@ -25,17 +25,18 @@ namespace Bit.App.Pages
|
||||||
private readonly IAppSettingsService _appSettingsService;
|
private readonly IAppSettingsService _appSettingsService;
|
||||||
private CancellationTokenSource _filterResultsCancellationTokenSource;
|
private CancellationTokenSource _filterResultsCancellationTokenSource;
|
||||||
private readonly string _name;
|
private readonly string _name;
|
||||||
|
private readonly AppOptions _appOptions;
|
||||||
|
|
||||||
public VaultAutofillListCiphersPage(string uriString)
|
public VaultAutofillListCiphersPage(AppOptions appOptions)
|
||||||
: base(true)
|
: base(true)
|
||||||
{
|
{
|
||||||
Uri = uriString;
|
_appOptions = appOptions;
|
||||||
|
Uri = appOptions.Uri;
|
||||||
if(uriString?.StartsWith(Constants.AndroidAppProtocol) ?? false)
|
if(Uri.StartsWith(Constants.AndroidAppProtocol))
|
||||||
{
|
{
|
||||||
_name = uriString.Substring(Constants.AndroidAppProtocol.Length);
|
_name = Uri.Substring(Constants.AndroidAppProtocol.Length);
|
||||||
}
|
}
|
||||||
else if(!System.Uri.TryCreate(uriString, UriKind.Absolute, out Uri uri) ||
|
else if(!System.Uri.TryCreate(Uri, UriKind.Absolute, out Uri uri) ||
|
||||||
!DomainName.TryParseBaseDomain(uri.Host, out _name))
|
!DomainName.TryParseBaseDomain(uri.Host, out _name))
|
||||||
{
|
{
|
||||||
_name = "--";
|
_name = "--";
|
||||||
|
@ -166,25 +167,41 @@ namespace Bit.App.Pages
|
||||||
var autofillGroupings = new List<VaultListPageModel.AutofillGrouping>();
|
var autofillGroupings = new List<VaultListPageModel.AutofillGrouping>();
|
||||||
var ciphers = await _cipherService.GetAllAsync(Uri);
|
var ciphers = await _cipherService.GetAllAsync(Uri);
|
||||||
|
|
||||||
var normalLogins = ciphers?.Item1.Select(l => new VaultListPageModel.AutofillCipher(
|
if(_appOptions.FillType.HasValue && _appOptions.FillType.Value != CipherType.Login)
|
||||||
l, _appSettingsService, false))
|
|
||||||
.OrderBy(s => s.Name)
|
|
||||||
.ThenBy(s => s.Subtitle)
|
|
||||||
.ToList();
|
|
||||||
if(normalLogins?.Any() ?? false)
|
|
||||||
{
|
{
|
||||||
autofillGroupings.Add(new VaultListPageModel.AutofillGrouping(normalLogins, AppResources.MatchingItems));
|
var others = ciphers?.Item3.Where(c => c.Type == _appOptions.FillType.Value)
|
||||||
|
.Select(c => new VaultListPageModel.AutofillCipher(c, _appSettingsService, false))
|
||||||
|
.OrderBy(s => s.Name)
|
||||||
|
.ThenBy(s => s.Subtitle)
|
||||||
|
.ToList();
|
||||||
|
if(others?.Any() ?? false)
|
||||||
|
{
|
||||||
|
autofillGroupings.Add(new VaultListPageModel.AutofillGrouping(others, AppResources.Items));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
var fuzzyLogins = ciphers?.Item2.Select(l => new VaultListPageModel.AutofillCipher(
|
|
||||||
l, _appSettingsService, true))
|
|
||||||
.OrderBy(s => s.Name)
|
|
||||||
.ThenBy(s => s.LoginUsername)
|
|
||||||
.ToList();
|
|
||||||
if(fuzzyLogins?.Any() ?? false)
|
|
||||||
{
|
{
|
||||||
autofillGroupings.Add(new VaultListPageModel.AutofillGrouping(fuzzyLogins,
|
var normalLogins = ciphers?.Item1
|
||||||
AppResources.PossibleMatchingItems));
|
.Select(l => new VaultListPageModel.AutofillCipher(l, _appSettingsService, false))
|
||||||
|
.OrderBy(s => s.Name)
|
||||||
|
.ThenBy(s => s.Subtitle)
|
||||||
|
.ToList();
|
||||||
|
if(normalLogins?.Any() ?? false)
|
||||||
|
{
|
||||||
|
autofillGroupings.Add(new VaultListPageModel.AutofillGrouping(normalLogins,
|
||||||
|
AppResources.MatchingItems));
|
||||||
|
}
|
||||||
|
|
||||||
|
var fuzzyLogins = ciphers?.Item2
|
||||||
|
.Select(l => new VaultListPageModel.AutofillCipher(l, _appSettingsService, true))
|
||||||
|
.OrderBy(s => s.Name)
|
||||||
|
.ThenBy(s => s.Subtitle)
|
||||||
|
.ToList();
|
||||||
|
if(fuzzyLogins?.Any() ?? false)
|
||||||
|
{
|
||||||
|
autofillGroupings.Add(new VaultListPageModel.AutofillGrouping(fuzzyLogins,
|
||||||
|
AppResources.PossibleMatchingItems));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Device.BeginInvokeOnMainThread(() =>
|
Device.BeginInvokeOnMainThread(() =>
|
||||||
|
@ -235,8 +252,15 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
private async void AddCipherAsync()
|
private async void AddCipherAsync()
|
||||||
{
|
{
|
||||||
var page = new VaultAddCipherPage(CipherType.Login, Uri, _name, true);
|
if(_appOptions.FillType.HasValue && _appOptions.FillType != CipherType.Login)
|
||||||
await Navigation.PushForDeviceAsync(page);
|
{
|
||||||
|
var pageForOther = new VaultAddCipherPage(_appOptions.FillType.Value, null, null, true);
|
||||||
|
await Navigation.PushForDeviceAsync(pageForOther);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pageForLogin = new VaultAddCipherPage(CipherType.Login, Uri, _name, true);
|
||||||
|
await Navigation.PushForDeviceAsync(pageForLogin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void MoreClickedAsync(VaultListPageModel.Cipher cipher)
|
private async void MoreClickedAsync(VaultListPageModel.Cipher cipher)
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace Bit.App.Services
|
||||||
return cipher;
|
return cipher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString)
|
public async Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString)
|
||||||
{
|
{
|
||||||
if(string.IsNullOrWhiteSpace(uriString))
|
if(string.IsNullOrWhiteSpace(uriString))
|
||||||
{
|
{
|
||||||
|
@ -135,9 +135,16 @@ namespace Bit.App.Services
|
||||||
var matchingFuzzyDomainsArray = matchingFuzzyDomains.ToArray();
|
var matchingFuzzyDomainsArray = matchingFuzzyDomains.ToArray();
|
||||||
var matchingLogins = new List<Cipher>();
|
var matchingLogins = new List<Cipher>();
|
||||||
var matchingFuzzyLogins = new List<Cipher>();
|
var matchingFuzzyLogins = new List<Cipher>();
|
||||||
|
var others = new List<Cipher>();
|
||||||
var ciphers = await GetAllAsync();
|
var ciphers = await GetAllAsync();
|
||||||
foreach(var cipher in ciphers)
|
foreach(var cipher in ciphers)
|
||||||
{
|
{
|
||||||
|
if(cipher.Type != Enums.CipherType.Login)
|
||||||
|
{
|
||||||
|
others.Add(cipher);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(cipher.Type != Enums.CipherType.Login || cipher.Login?.Uri == null)
|
if(cipher.Type != Enums.CipherType.Login || cipher.Login?.Uri == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -190,7 +197,7 @@ namespace Bit.App.Services
|
||||||
if(mobileApp && mobileAppSearchTerms != null && mobileAppSearchTerms.Length > 0)
|
if(mobileApp && mobileAppSearchTerms != null && mobileAppSearchTerms.Length > 0)
|
||||||
{
|
{
|
||||||
var addedFromSearchTerm = false;
|
var addedFromSearchTerm = false;
|
||||||
var loginNameString = cipher.Name == null ? null :
|
var loginNameString = cipher.Name == null ? null :
|
||||||
cipher.Name.Decrypt(cipher.OrganizationId)?.ToLowerInvariant();
|
cipher.Name.Decrypt(cipher.OrganizationId)?.ToLowerInvariant();
|
||||||
foreach(var term in mobileAppSearchTerms)
|
foreach(var term in mobileAppSearchTerms)
|
||||||
{
|
{
|
||||||
|
@ -216,7 +223,8 @@ namespace Bit.App.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>>(matchingLogins, matchingFuzzyLogins);
|
return new Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>, IEnumerable<Cipher>>(
|
||||||
|
matchingLogins, matchingFuzzyLogins, others);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResult<CipherResponse>> SaveAsync(Cipher cipher)
|
public async Task<ApiResult<CipherResponse>> SaveAsync(Cipher cipher)
|
||||||
|
|
Loading…
Reference in a new issue