better detection for username/passwords

This commit is contained in:
Kyle Spearrin 2017-11-17 22:47:08 -05:00
parent da199deed1
commit 2c662c428c
3 changed files with 59 additions and 18 deletions

View file

@ -2,7 +2,6 @@
using Android.Service.Autofill; using Android.Service.Autofill;
using Android.Views.Autofill; using Android.Views.Autofill;
using System.Linq; using System.Linq;
using Android.Text;
using Bit.App.Models; using Bit.App.Models;
using Bit.App.Enums; using Bit.App.Enums;
using Bit.App.Models.Page; using Bit.App.Models.Page;
@ -61,23 +60,19 @@ namespace Bit.Android.Autofill
if(Type == CipherType.Login) if(Type == CipherType.Login)
{ {
var passwordField = fieldCollection.PasswordFields.FirstOrDefault(); if(!fieldCollection.PasswordFields.Any() || string.IsNullOrWhiteSpace(_password.Value))
if(passwordField == null)
{ {
return false; return false;
} }
if(string.IsNullOrWhiteSpace(_password.Value)) foreach(var passwordField in fieldCollection.PasswordFields)
{ {
return false; datasetBuilder.SetValue(passwordField.AutofillId, AutofillValue.ForText(_password.Value));
} }
datasetBuilder.SetValue(passwordField.AutofillId, AutofillValue.ForText(_password.Value)); if(fieldCollection.UsernameFields.Any() && !string.IsNullOrWhiteSpace(Subtitle))
var usernameField = fieldCollection.Fields.TakeWhile(f => f.Id != passwordField.Id).LastOrDefault();
if(usernameField != null)
{ {
if(!string.IsNullOrWhiteSpace(Subtitle)) foreach(var usernameField in fieldCollection.UsernameFields)
{ {
datasetBuilder.SetValue(usernameField.AutofillId, AutofillValue.ForText(Subtitle)); datasetBuilder.SetValue(usernameField.AutofillId, AutofillValue.ForText(Subtitle));
} }

View file

@ -8,7 +8,8 @@ namespace Bit.Android.Autofill
{ {
public class FieldCollection public class FieldCollection
{ {
private List<Field> _passwordFields; private List<Field> _passwordFields = null;
private List<Field> _usernameFields = null;
public HashSet<int> Ids { get; private set; } = new HashSet<int>(); public HashSet<int> Ids { get; private set; } = new HashSet<int>();
public List<AutofillId> AutofillIds { get; private set; } = new List<AutofillId>(); public List<AutofillId> AutofillIds { get; private set; } = new List<AutofillId>();
@ -40,7 +41,29 @@ namespace Bit.Android.Autofill
} }
} }
public bool FillableForLogin => PasswordFields.Any(); public List<Field> UsernameFields
{
get
{
if(_usernameFields != null)
{
return _usernameFields;
}
_usernameFields = new List<Field>();
foreach(var passwordField in PasswordFields)
{
var usernameField = Fields.TakeWhile(f => f.Id != passwordField.Id).LastOrDefault();
if(usernameField != null)
{
_usernameFields.Add(usernameField);
}
}
return _usernameFields;
}
}
public bool FillableForLogin => UsernameFields.Any(f => f.Focused) || PasswordFields.Any(f => f.Focused);
public void Add(Field field) public void Add(Field field)
{ {
@ -49,6 +72,8 @@ namespace Bit.Android.Autofill
return; return;
} }
_passwordFields = _usernameFields = null;
Ids.Add(field.Id); Ids.Add(field.Id);
Fields.Add(field); Fields.Add(field);
SaveType |= field.SaveType; SaveType |= field.SaveType;

View file

@ -8,6 +8,7 @@ namespace Bit.Android.Autofill
{ {
private readonly AssistStructure _structure; private readonly AssistStructure _structure;
private string _uri; private string _uri;
private string _packageName;
public Parser(AssistStructure structure) public Parser(AssistStructure structure)
{ {
@ -17,16 +18,36 @@ namespace Bit.Android.Autofill
public FieldCollection FieldCollection { get; private set; } = new FieldCollection(); public FieldCollection FieldCollection { get; private set; } = new FieldCollection();
public string Uri public string Uri
{ {
get => _uri; get
{
if(!string.IsNullOrWhiteSpace(_uri))
{
return _uri;
}
if(string.IsNullOrWhiteSpace(PackageName))
{
_uri = null;
}
else
{
_uri = string.Concat(Constants.AndroidAppProtocol, PackageName);
}
return _uri;
}
}
public string PackageName
{
get => _packageName;
set set
{ {
if(string.IsNullOrWhiteSpace(value)) if(string.IsNullOrWhiteSpace(value))
{ {
_uri = null; _packageName = _uri = null;
return;
} }
_uri = string.Concat(Constants.AndroidAppProtocol, value); _packageName = value;
} }
} }
@ -45,9 +66,9 @@ namespace Bit.Android.Autofill
var isEditText = node.ClassName == "android.widget.EditText"; var isEditText = node.ClassName == "android.widget.EditText";
if(isEditText || (hints?.Length ?? 0) > 0) if(isEditText || (hints?.Length ?? 0) > 0)
{ {
if(Uri == null) if(PackageName == null)
{ {
Uri = node.IdPackage; PackageName = node.IdPackage;
} }
FieldCollection.Add(new Field(node)); FieldCollection.Add(new Field(node));
} }