diff --git a/src/Android/Autofill/AutofillHelpers.cs b/src/Android/Autofill/AutofillHelpers.cs index 5e4c38613..d1ccb23b2 100644 --- a/src/Android/Autofill/AutofillHelpers.cs +++ b/src/Android/Autofill/AutofillHelpers.cs @@ -8,6 +8,7 @@ using Android.App; using Bit.App.Abstractions; using System.Threading.Tasks; using Bit.App.Resources; +using Bit.App.Enums; namespace Bit.Android.Autofill { @@ -33,7 +34,7 @@ namespace Bit.Android.Autofill else if(parser.FieldCollection.FillableForCard) { 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)); } @@ -80,6 +81,22 @@ namespace Bit.Android.Autofill AppResources.VaultIsLocked, Resource.Drawable.icon); var intent = new Intent(context, typeof(MainActivity)); 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); var pendingIntent = PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent); responseBuilder.SetAuthentication(fields.AutofillIds.ToArray(), pendingIntent.IntentSender, view); diff --git a/src/Android/Autofill/FilledItem.cs b/src/Android/Autofill/FilledItem.cs index 878a0bf22..854b4531d 100644 --- a/src/Android/Autofill/FilledItem.cs +++ b/src/Android/Autofill/FilledItem.cs @@ -4,7 +4,6 @@ using Android.Views.Autofill; using System.Linq; using Bit.App.Models; using Bit.App.Enums; -using Bit.App.Models.Page; using Android.Views; 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 Subtitle { get; set; } = string.Empty; public int Icon { get; set; } = Resource.Drawable.login; diff --git a/src/Android/MainActivity.cs b/src/Android/MainActivity.cs index dbe79b55d..0c376c105 100644 --- a/src/Android/MainActivity.cs +++ b/src/Android/MainActivity.cs @@ -169,7 +169,7 @@ namespace Bit.Android return; } - var items = new List { new FilledItem(cipher) }; + var items = new List { new FilledItem(cipher.CipherModel) }; var response = AutofillHelpers.BuildFillResponse(this, parser, items); var replyIntent = new Intent(); replyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, response); @@ -435,6 +435,12 @@ namespace Bit.Android FromAutofillFramework = Intent.GetBooleanExtra("autofillFramework", false) }; + var fillType = Intent.GetIntExtra("autofillFrameworkFillType", 0); + if(fillType > 0) + { + options.FillType = (CipherType)fillType; + } + if(Intent.GetBooleanExtra("autofillFrameworkSave", false)) { options.SaveType = (CipherType)Intent.GetIntExtra("autofillFrameworkType", 0); diff --git a/src/App/Abstractions/Services/ICipherService.cs b/src/App/Abstractions/Services/ICipherService.cs index 9f5713e8b..53afa3a7a 100644 --- a/src/App/Abstractions/Services/ICipherService.cs +++ b/src/App/Abstractions/Services/ICipherService.cs @@ -12,7 +12,7 @@ namespace Bit.App.Abstractions Task GetByIdAsync(string id); Task> GetAllAsync(); Task> GetAllAsync(bool favorites); - Task, IEnumerable>> GetAllAsync(string uriString); + Task, IEnumerable, IEnumerable>> GetAllAsync(string uriString); Task> SaveAsync(Cipher cipher); Task UpsertDataAsync(CipherData cipher); Task DeleteAsync(string id); diff --git a/src/App/App.cs b/src/App/App.cs index 5f6f2f37f..572b29637 100644 --- a/src/App/App.cs +++ b/src/App/App.cs @@ -74,7 +74,7 @@ namespace Bit.App } else if(_options.Uri != null) { - MainPage = new ExtendedNavigationPage(new VaultAutofillListCiphersPage(_options.Uri)); + MainPage = new ExtendedNavigationPage(new VaultAutofillListCiphersPage(_options)); } else { diff --git a/src/App/Models/AppOptions.cs b/src/App/Models/AppOptions.cs index a2461773d..44e7ebede 100644 --- a/src/App/Models/AppOptions.cs +++ b/src/App/Models/AppOptions.cs @@ -6,6 +6,7 @@ namespace Bit.App.Models { public bool MyVault { get; set; } public bool FromAutofillFramework { get; set; } + public CipherType? FillType { get; set; } public string Uri { get; set; } public CipherType? SaveType { get; set; } public string SaveName { get; set; } diff --git a/src/App/Models/Page/VaultListPageModel.cs b/src/App/Models/Page/VaultListPageModel.cs index 122d54bf7..8b4c77590 100644 --- a/src/App/Models/Page/VaultListPageModel.cs +++ b/src/App/Models/Page/VaultListPageModel.cs @@ -13,6 +13,7 @@ namespace Bit.App.Models.Page { public Cipher(Models.Cipher cipher, IAppSettingsService appSettings) { + CipherModel = cipher; Id = cipher.Id; Shared = !string.IsNullOrWhiteSpace(cipher.OrganizationId); 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 bool Shared { get; set; } public bool HasAttachments { get; set; } diff --git a/src/App/Pages/Vault/VaultAutofillListCiphersPage.cs b/src/App/Pages/Vault/VaultAutofillListCiphersPage.cs index 2cb6c7917..5f1ba98f0 100644 --- a/src/App/Pages/Vault/VaultAutofillListCiphersPage.cs +++ b/src/App/Pages/Vault/VaultAutofillListCiphersPage.cs @@ -25,17 +25,18 @@ namespace Bit.App.Pages private readonly IAppSettingsService _appSettingsService; private CancellationTokenSource _filterResultsCancellationTokenSource; private readonly string _name; + private readonly AppOptions _appOptions; - public VaultAutofillListCiphersPage(string uriString) + public VaultAutofillListCiphersPage(AppOptions appOptions) : base(true) { - Uri = uriString; - - if(uriString?.StartsWith(Constants.AndroidAppProtocol) ?? false) + _appOptions = appOptions; + Uri = appOptions.Uri; + 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)) { _name = "--"; @@ -166,25 +167,41 @@ namespace Bit.App.Pages var autofillGroupings = new List(); var ciphers = await _cipherService.GetAllAsync(Uri); - var normalLogins = ciphers?.Item1.Select(l => new VaultListPageModel.AutofillCipher( - l, _appSettingsService, false)) - .OrderBy(s => s.Name) - .ThenBy(s => s.Subtitle) - .ToList(); - if(normalLogins?.Any() ?? false) + if(_appOptions.FillType.HasValue && _appOptions.FillType.Value != CipherType.Login) { - 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)); + } } - - 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) + else { - autofillGroupings.Add(new VaultListPageModel.AutofillGrouping(fuzzyLogins, - AppResources.PossibleMatchingItems)); + var normalLogins = ciphers?.Item1 + .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(() => @@ -235,8 +252,15 @@ namespace Bit.App.Pages private async void AddCipherAsync() { - var page = new VaultAddCipherPage(CipherType.Login, Uri, _name, true); - await Navigation.PushForDeviceAsync(page); + if(_appOptions.FillType.HasValue && _appOptions.FillType != CipherType.Login) + { + 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) diff --git a/src/App/Services/CipherService.cs b/src/App/Services/CipherService.cs index 22f31fb41..5803f20f3 100644 --- a/src/App/Services/CipherService.cs +++ b/src/App/Services/CipherService.cs @@ -78,7 +78,7 @@ namespace Bit.App.Services return cipher; } - public async Task, IEnumerable>> GetAllAsync(string uriString) + public async Task, IEnumerable, IEnumerable>> GetAllAsync(string uriString) { if(string.IsNullOrWhiteSpace(uriString)) { @@ -135,9 +135,16 @@ namespace Bit.App.Services var matchingFuzzyDomainsArray = matchingFuzzyDomains.ToArray(); var matchingLogins = new List(); var matchingFuzzyLogins = new List(); + var others = new List(); var ciphers = await GetAllAsync(); 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) { continue; @@ -190,7 +197,7 @@ namespace Bit.App.Services if(mobileApp && mobileAppSearchTerms != null && mobileAppSearchTerms.Length > 0) { var addedFromSearchTerm = false; - var loginNameString = cipher.Name == null ? null : + var loginNameString = cipher.Name == null ? null : cipher.Name.Decrypt(cipher.OrganizationId)?.ToLowerInvariant(); foreach(var term in mobileAppSearchTerms) { @@ -216,7 +223,8 @@ namespace Bit.App.Services } } - return new Tuple, IEnumerable>(matchingLogins, matchingFuzzyLogins); + return new Tuple, IEnumerable, IEnumerable>( + matchingLogins, matchingFuzzyLogins, others); } public async Task> SaveAsync(Cipher cipher)