autofill from vault with specified dataset

This commit is contained in:
Kyle Spearrin 2017-11-21 11:29:00 -05:00
parent cfe34355bd
commit bc04211b79
6 changed files with 48 additions and 26 deletions

View file

@ -9,11 +9,14 @@ using Bit.App.Abstractions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.App.Resources; using Bit.App.Resources;
using Bit.App.Enums; using Bit.App.Enums;
using Android.Views.Autofill;
namespace Bit.Android.Autofill namespace Bit.Android.Autofill
{ {
public static class AutofillHelpers public static class AutofillHelpers
{ {
private static int _pendingIntentId = 0;
public static async Task<List<FilledItem>> GetFillItemsAsync(Parser parser, ICipherService service) public static async Task<List<FilledItem>> GetFillItemsAsync(Parser parser, ICipherService service)
{ {
var items = new List<FilledItem>(); var items = new List<FilledItem>();
@ -43,7 +46,7 @@ namespace Bit.Android.Autofill
return items; return items;
} }
public static FillResponse BuildFillResponse(Context context, Parser parser, List<FilledItem> items) public static FillResponse BuildFillResponse(Context context, Parser parser, List<FilledItem> items, bool locked)
{ {
var responseBuilder = new FillResponse.Builder(); var responseBuilder = new FillResponse.Builder();
if(items != null && items.Count > 0) if(items != null && items.Count > 0)
@ -58,6 +61,7 @@ namespace Bit.Android.Autofill
} }
} }
responseBuilder.AddDataset(BuildVaultDataset(context, parser.FieldCollection, parser.Uri, locked));
AddSaveInfo(responseBuilder, parser.FieldCollection); AddSaveInfo(responseBuilder, parser.FieldCollection);
responseBuilder.SetIgnoredIds(parser.FieldCollection.IgnoreAutofillIds.ToArray()); responseBuilder.SetIgnoredIds(parser.FieldCollection.IgnoreAutofillIds.ToArray());
return responseBuilder.Build(); return responseBuilder.Build();
@ -74,11 +78,8 @@ namespace Bit.Android.Autofill
return null; return null;
} }
public static FillResponse BuildAuthResponse(Context context, FieldCollection fields, string uri) public static Dataset BuildVaultDataset(Context context, FieldCollection fields, string uri, bool locked)
{ {
var responseBuilder = new FillResponse.Builder();
var view = BuildListView(context.PackageName, AppResources.AutofillWithBitwarden,
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) if(fields.FillableForLogin)
@ -98,11 +99,22 @@ namespace Bit.Android.Autofill
return null; return null;
} }
intent.PutExtra("autofillFrameworkUri", uri); intent.PutExtra("autofillFrameworkUri", uri);
var pendingIntent = PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent); var pendingIntent = PendingIntent.GetActivity(context, ++_pendingIntentId, intent,
responseBuilder.SetAuthentication(fields.AutofillIds.ToArray(), pendingIntent.IntentSender, view); PendingIntentFlags.CancelCurrent);
AddSaveInfo(responseBuilder, fields);
responseBuilder.SetIgnoredIds(fields.IgnoreAutofillIds.ToArray()); var view = BuildListView(context.PackageName, AppResources.AutofillWithBitwarden,
return responseBuilder.Build(); locked ? AppResources.VaultIsLocked : AppResources.GoToMyVault, Resource.Drawable.icon);
var datasetBuilder = new Dataset.Builder(view);
datasetBuilder.SetAuthentication(pendingIntent.IntentSender);
// Dataset must have a value set. We will reset this in the main activity when the real item is chosen.
foreach(var autofillId in fields.AutofillIds)
{
datasetBuilder.SetValue(autofillId, AutofillValue.ForText("PLACEHOLDER"));
}
return datasetBuilder.Build();
} }
public static RemoteViews BuildListView(string packageName, string text, string subtext, int iconId) public static RemoteViews BuildListView(string packageName, string text, string subtext, int iconId)

View file

@ -8,6 +8,7 @@ using Android.Widget;
using Bit.App; using Bit.App;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Enums; using Bit.App.Enums;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using XLabs.Ioc; using XLabs.Ioc;
@ -44,22 +45,20 @@ namespace Bit.Android.Autofill
_lockService = Resolver.Resolve<ILockService>(); _lockService = Resolver.Resolve<ILockService>();
} }
var isLocked = (await _lockService.GetLockTypeAsync(false)) != LockType.None; List<FilledItem> items = null;
if(isLocked) var locked = (await _lockService.GetLockTypeAsync(false)) != LockType.None;
if(!locked)
{ {
var authResponse = AutofillHelpers.BuildAuthResponse(this, parser.FieldCollection, parser.Uri); if(_cipherService == null)
callback.OnSuccess(authResponse); {
return; _cipherService = Resolver.Resolve<ICipherService>();
} }
if(_cipherService == null) items = await AutofillHelpers.GetFillItemsAsync(parser, _cipherService);
{
_cipherService = Resolver.Resolve<ICipherService>();
} }
// build response // build response
var items = await AutofillHelpers.GetFillItemsAsync(parser, _cipherService); var response = AutofillHelpers.BuildFillResponse(this, parser, items, locked);
var response = AutofillHelpers.BuildFillResponse(this, parser, items);
callback.OnSuccess(response); callback.OnSuccess(response);
} }

View file

@ -169,10 +169,9 @@ namespace Bit.Android
return; return;
} }
var items = new List<FilledItem> { new FilledItem(cipher.CipherModel) }; var dataset = AutofillHelpers.BuildDataset(this, parser.FieldCollection, new FilledItem(cipher.CipherModel));
var response = AutofillHelpers.BuildFillResponse(this, parser, items);
var replyIntent = new Intent(); var replyIntent = new Intent();
replyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, response); replyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, dataset);
SetResult(Result.Ok, replyIntent); SetResult(Result.Ok, replyIntent);
Finish(); Finish();
} }

View file

@ -14,8 +14,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:maxWidth="25dp" android:maxWidth="20dp"
android:maxHeight="25dp" android:maxHeight="20dp"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:src="@drawable/login" /> android:src="@drawable/login" />
<LinearLayout <LinearLayout

View file

@ -1429,6 +1429,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Go to my vault.
/// </summary>
public static string GoToMyVault {
get {
return ResourceManager.GetString("GoToMyVault", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Go To Website. /// Looks up a localized string similar to Go To Website.
/// </summary> /// </summary>

View file

@ -1191,4 +1191,7 @@
<data name="VaultIsLocked" xml:space="preserve"> <data name="VaultIsLocked" xml:space="preserve">
<value>Vault is locked</value> <value>Vault is locked</value>
</data> </data>
<data name="GoToMyVault" xml:space="preserve">
<value>Go to my vault</value>
</data>
</root> </root>