mirror of
https://github.com/bitwarden/android.git
synced 2024-12-25 18:38:27 +03:00
parse saved item info for save
This commit is contained in:
parent
184f13b148
commit
abf75cffd9
13 changed files with 172 additions and 236 deletions
|
@ -300,6 +300,7 @@
|
||||||
<Compile Include="Autofill\AutofillHelpers.cs" />
|
<Compile Include="Autofill\AutofillHelpers.cs" />
|
||||||
<Compile Include="Autofill\CipherFilledItem.cs" />
|
<Compile Include="Autofill\CipherFilledItem.cs" />
|
||||||
<Compile Include="Autofill\IFilledItem.cs" />
|
<Compile Include="Autofill\IFilledItem.cs" />
|
||||||
|
<Compile Include="Autofill\SavedItem.cs" />
|
||||||
<Compile Include="Controls\CustomLabelRenderer.cs" />
|
<Compile Include="Controls\CustomLabelRenderer.cs" />
|
||||||
<Compile Include="Controls\CustomSearchBarRenderer.cs" />
|
<Compile Include="Controls\CustomSearchBarRenderer.cs" />
|
||||||
<Compile Include="Controls\CustomButtonRenderer.cs" />
|
<Compile Include="Controls\CustomButtonRenderer.cs" />
|
||||||
|
@ -307,8 +308,6 @@
|
||||||
<Compile Include="Controls\ExtendedButtonRenderer.cs" />
|
<Compile Include="Controls\ExtendedButtonRenderer.cs" />
|
||||||
<Compile Include="Controls\ExtendedTabbedPageRenderer.cs" />
|
<Compile Include="Controls\ExtendedTabbedPageRenderer.cs" />
|
||||||
<Compile Include="Controls\ExtendedTableViewRenderer.cs" />
|
<Compile Include="Controls\ExtendedTableViewRenderer.cs" />
|
||||||
<Compile Include="Autofill\FilledField.cs" />
|
|
||||||
<Compile Include="Autofill\FilledFieldCollection.cs" />
|
|
||||||
<Compile Include="HockeyAppCrashManagerListener.cs" />
|
<Compile Include="HockeyAppCrashManagerListener.cs" />
|
||||||
<Compile Include="AutofillService.cs" />
|
<Compile Include="AutofillService.cs" />
|
||||||
<Compile Include="Controls\ExtendedEditorRenderer.cs" />
|
<Compile Include="Controls\ExtendedEditorRenderer.cs" />
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Android.Runtime;
|
|
||||||
using Android.Views;
|
|
||||||
using Android.Widget;
|
using Android.Widget;
|
||||||
using Android.Support.V7.App;
|
using Android.Support.V7.App;
|
||||||
using Android.Views.Autofill;
|
using Android.Views.Autofill;
|
||||||
|
@ -92,7 +88,7 @@ namespace Bit.Android.Autofill
|
||||||
}
|
}
|
||||||
|
|
||||||
var parser = new Parser(structure);
|
var parser = new Parser(structure);
|
||||||
parser.ParseForFill();
|
parser.Parse();
|
||||||
if(!parser.FieldCollection.Fields.Any() || string.IsNullOrWhiteSpace(parser.Uri))
|
if(!parser.FieldCollection.Fields.Any() || string.IsNullOrWhiteSpace(parser.Uri))
|
||||||
{
|
{
|
||||||
_replyIntent = null;
|
_replyIntent = null;
|
||||||
|
|
|
@ -4,6 +4,8 @@ using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Android.Runtime;
|
using Android.Runtime;
|
||||||
using Android.Service.Autofill;
|
using Android.Service.Autofill;
|
||||||
|
using Android.Widget;
|
||||||
|
using Bit.App;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Enums;
|
using Bit.App.Enums;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -29,7 +31,7 @@ namespace Bit.Android.Autofill
|
||||||
}
|
}
|
||||||
|
|
||||||
var parser = new Parser(structure);
|
var parser = new Parser(structure);
|
||||||
parser.ParseForFill();
|
parser.Parse();
|
||||||
|
|
||||||
if(!parser.FieldCollection.Fields.Any() || string.IsNullOrWhiteSpace(parser.Uri) ||
|
if(!parser.FieldCollection.Fields.Any() || string.IsNullOrWhiteSpace(parser.Uri) ||
|
||||||
parser.Uri == "androidapp://com.x8bit.bitwarden" || parser.Uri == "androidapp://android")
|
parser.Uri == "androidapp://com.x8bit.bitwarden" || parser.Uri == "androidapp://android")
|
||||||
|
@ -70,16 +72,32 @@ namespace Bit.Android.Autofill
|
||||||
}
|
}
|
||||||
|
|
||||||
var parser = new Parser(structure);
|
var parser = new Parser(structure);
|
||||||
parser.ParseForSave();
|
parser.Parse();
|
||||||
|
|
||||||
|
var savedItem = parser.FieldCollection.GetSavedItem();
|
||||||
|
if(savedItem == null)
|
||||||
|
{
|
||||||
|
Toast.MakeText(this, "Unable to save this form.", ToastLength.Short).Show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var intent = new Intent(this, typeof(MainActivity));
|
var intent = new Intent(this, typeof(MainActivity));
|
||||||
|
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTop);
|
||||||
intent.PutExtra("autofillFramework", true);
|
intent.PutExtra("autofillFramework", true);
|
||||||
intent.PutExtra("autofillFrameworkSave", true);
|
intent.PutExtra("autofillFrameworkSave", true);
|
||||||
intent.PutExtra("autofillFrameworkType", (int)CipherType.Login);
|
intent.PutExtra("autofillFrameworkType", (int)savedItem.Type);
|
||||||
intent.PutExtra("autofillFrameworkUri", parser.Uri);
|
switch(savedItem.Type)
|
||||||
intent.PutExtra("autofillFrameworkUsername", "username");
|
{
|
||||||
intent.PutExtra("autofillFrameworkPassword", "pass123");
|
case CipherType.Login:
|
||||||
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTop);
|
intent.PutExtra("autofillFrameworkName", parser.Uri.Replace(Constants.AndroidAppProtocol, string.Empty));
|
||||||
|
intent.PutExtra("autofillFrameworkUri", parser.Uri);
|
||||||
|
intent.PutExtra("autofillFrameworkUsername", savedItem.Login.Username);
|
||||||
|
intent.PutExtra("autofillFrameworkPassword", savedItem.Login.Password);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Toast.MakeText(this, "Unable to save this type of form.", ToastLength.Short).Show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
StartActivity(intent);
|
StartActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,11 @@ namespace Bit.Android.Autofill
|
||||||
|
|
||||||
public bool ApplyToFields(FieldCollection fieldCollection, Dataset.Builder datasetBuilder)
|
public bool ApplyToFields(FieldCollection fieldCollection, Dataset.Builder datasetBuilder)
|
||||||
{
|
{
|
||||||
|
if(!fieldCollection?.Fields.Any() ?? true)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(Type == CipherType.Login)
|
if(Type == CipherType.Login)
|
||||||
{
|
{
|
||||||
var passwordField = fieldCollection.Fields.FirstOrDefault(
|
var passwordField = fieldCollection.Fields.FirstOrDefault(
|
||||||
|
|
|
@ -25,6 +25,26 @@ namespace Bit.Android.Autofill
|
||||||
Visible = node.Visibility == ViewStates.Visible;
|
Visible = node.Visibility == ViewStates.Visible;
|
||||||
Hints = AutofillHelpers.FilterForSupportedHints(node.GetAutofillHints());
|
Hints = AutofillHelpers.FilterForSupportedHints(node.GetAutofillHints());
|
||||||
AutofillOptions = node.GetAutofillOptions()?.ToList();
|
AutofillOptions = node.GetAutofillOptions()?.ToList();
|
||||||
|
|
||||||
|
if(node.AutofillValue != null)
|
||||||
|
{
|
||||||
|
if(node.AutofillValue.IsList)
|
||||||
|
{
|
||||||
|
var autofillOptions = node.GetAutofillOptions();
|
||||||
|
if(autofillOptions != null && autofillOptions.Length > 0)
|
||||||
|
{
|
||||||
|
TextValue = autofillOptions[node.AutofillValue.ListValue];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(node.AutofillValue.IsDate)
|
||||||
|
{
|
||||||
|
DateValue = node.AutofillValue.DateValue;
|
||||||
|
}
|
||||||
|
else if(node.AutofillValue.IsText)
|
||||||
|
{
|
||||||
|
TextValue = node.AutofillValue.TextValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SaveDataType SaveType { get; set; } = SaveDataType.Generic;
|
public SaveDataType SaveType { get; set; } = SaveDataType.Generic;
|
||||||
|
@ -47,6 +67,9 @@ namespace Bit.Android.Autofill
|
||||||
public bool Clickable { get; private set; }
|
public bool Clickable { get; private set; }
|
||||||
public bool Visible { get; private set; }
|
public bool Visible { get; private set; }
|
||||||
public List<string> AutofillOptions { get; set; }
|
public List<string> AutofillOptions { get; set; }
|
||||||
|
public string TextValue { get; set; }
|
||||||
|
public long? DateValue { get; set; }
|
||||||
|
public bool? ToggleValue { get; set; }
|
||||||
|
|
||||||
public int GetAutofillOptionIndex(string value)
|
public int GetAutofillOptionIndex(string value)
|
||||||
{
|
{
|
||||||
|
@ -106,5 +129,44 @@ namespace Bit.Android.Autofill
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ValueIsNull()
|
||||||
|
{
|
||||||
|
return TextValue == null && DateValue == null && ToggleValue == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if(this == obj)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(obj == null || GetType() != obj.GetType())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var field = obj as Field;
|
||||||
|
if(TextValue != null ? !TextValue.Equals(field.TextValue) : field.TextValue != null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(DateValue != null ? !DateValue.Equals(field.DateValue) : field.DateValue != null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ToggleValue != null ? ToggleValue.Equals(field.ToggleValue) : field.ToggleValue == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
var result = TextValue != null ? TextValue.GetHashCode() : 0;
|
||||||
|
result = 31 * result + (DateValue != null ? DateValue.GetHashCode() : 0);
|
||||||
|
result = 31 * result + (ToggleValue != null ? ToggleValue.GetHashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Android.Service.Autofill;
|
using Android.Service.Autofill;
|
||||||
using Android.Views.Autofill;
|
using Android.Views.Autofill;
|
||||||
|
using System.Linq;
|
||||||
|
using Android.Text;
|
||||||
|
|
||||||
namespace Bit.Android.Autofill
|
namespace Bit.Android.Autofill
|
||||||
{
|
{
|
||||||
|
@ -49,5 +51,43 @@ namespace Bit.Android.Autofill
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SavedItem GetSavedItem()
|
||||||
|
{
|
||||||
|
if(!Fields?.Any() ?? true)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var passwordField = Fields.FirstOrDefault(
|
||||||
|
f => f.InputType.HasFlag(InputTypes.TextVariationPassword) && !string.IsNullOrWhiteSpace(f.TextValue));
|
||||||
|
if(passwordField == null)
|
||||||
|
{
|
||||||
|
passwordField = Fields.FirstOrDefault(
|
||||||
|
f => (f.IdEntry?.ToLower().Contains("password") ?? false) && !string.IsNullOrWhiteSpace(f.TextValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(passwordField == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var savedItem = new SavedItem
|
||||||
|
{
|
||||||
|
Type = App.Enums.CipherType.Login,
|
||||||
|
Login = new SavedItem.LoginItem
|
||||||
|
{
|
||||||
|
Password = passwordField.TextValue
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var usernameField = Fields.TakeWhile(f => f.Id != passwordField.Id).LastOrDefault();
|
||||||
|
if(usernameField != null && !string.IsNullOrWhiteSpace(usernameField.TextValue))
|
||||||
|
{
|
||||||
|
savedItem.Login.Username = usernameField.TextValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return savedItem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,81 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using static Android.App.Assist.AssistStructure;
|
|
||||||
|
|
||||||
namespace Bit.Android.Autofill
|
|
||||||
{
|
|
||||||
public class FilledField
|
|
||||||
{
|
|
||||||
public FilledField() { }
|
|
||||||
|
|
||||||
public FilledField(ViewNode node)
|
|
||||||
{
|
|
||||||
Hints = AutofillHelpers.FilterForSupportedHints(node.GetAutofillHints());
|
|
||||||
|
|
||||||
if(node.AutofillValue == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(node.AutofillValue.IsList)
|
|
||||||
{
|
|
||||||
var autofillOptions = node.GetAutofillOptions();
|
|
||||||
if(autofillOptions != null && autofillOptions.Length > 0)
|
|
||||||
{
|
|
||||||
TextValue = autofillOptions[node.AutofillValue.ListValue];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(node.AutofillValue.IsDate)
|
|
||||||
{
|
|
||||||
DateValue = node.AutofillValue.DateValue;
|
|
||||||
}
|
|
||||||
else if(node.AutofillValue.IsText)
|
|
||||||
{
|
|
||||||
TextValue = node.AutofillValue.TextValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string TextValue { get; set; }
|
|
||||||
public long? DateValue { get; set; }
|
|
||||||
public bool? ToggleValue { get; set; }
|
|
||||||
public List<string> Hints { get; set; }
|
|
||||||
|
|
||||||
public bool IsNull()
|
|
||||||
{
|
|
||||||
return TextValue == null && DateValue == null && ToggleValue == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object o)
|
|
||||||
{
|
|
||||||
if(this == o)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(o == null || GetType() != o.GetType())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var field = o as FilledField;
|
|
||||||
if(TextValue != null ? !TextValue.Equals(field.TextValue) : field.TextValue != null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(DateValue != null ? !DateValue.Equals(field.DateValue) : field.DateValue != null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ToggleValue != null ? ToggleValue.Equals(field.ToggleValue) : field.ToggleValue == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
var result = TextValue != null ? TextValue.GetHashCode() : 0;
|
|
||||||
result = 31 * result + (DateValue != null ? DateValue.GetHashCode() : 0);
|
|
||||||
result = 31 * result + (ToggleValue != null ? ToggleValue.GetHashCode() : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Android.Service.Autofill;
|
|
||||||
using Android.Views;
|
|
||||||
using Android.Views.Autofill;
|
|
||||||
using System.Linq;
|
|
||||||
using Android.Text;
|
|
||||||
|
|
||||||
namespace Bit.Android.Autofill
|
|
||||||
{
|
|
||||||
public class FilledFieldCollection : IFilledItem
|
|
||||||
{
|
|
||||||
public FilledFieldCollection()
|
|
||||||
: this(null, new Dictionary<string, FilledField>())
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public FilledFieldCollection(string datasetName, IDictionary<string, FilledField> hintMap)
|
|
||||||
{
|
|
||||||
HintToFieldMap = hintMap;
|
|
||||||
Name = datasetName;
|
|
||||||
Subtitle = "subtitle";
|
|
||||||
Icon = Resource.Drawable.login;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDictionary<string, FilledField> HintToFieldMap { get; private set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Subtitle { get; set; }
|
|
||||||
public int Icon { get; set; }
|
|
||||||
|
|
||||||
public void Add(FilledField filledField)
|
|
||||||
{
|
|
||||||
if(filledField == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(filledField));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(var hint in filledField.Hints)
|
|
||||||
{
|
|
||||||
HintToFieldMap.Add(hint, filledField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ApplyToFields(FieldCollection fieldCollection, Dataset.Builder datasetBuilder)
|
|
||||||
{
|
|
||||||
var setValue = false;
|
|
||||||
foreach(var hint in fieldCollection.Hints)
|
|
||||||
{
|
|
||||||
if(!fieldCollection.HintToFieldsMap.ContainsKey(hint))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fillableFields = fieldCollection.HintToFieldsMap[hint];
|
|
||||||
for(var i = 0; i < fillableFields.Count; i++)
|
|
||||||
{
|
|
||||||
if(!HintToFieldMap.ContainsKey(hint))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var field = fillableFields[i];
|
|
||||||
var filledField = HintToFieldMap[hint];
|
|
||||||
|
|
||||||
switch(field.AutofillType)
|
|
||||||
{
|
|
||||||
case AutofillType.List:
|
|
||||||
int listValue = field.GetAutofillOptionIndex(filledField.TextValue);
|
|
||||||
if(listValue != -1)
|
|
||||||
{
|
|
||||||
datasetBuilder.SetValue(field.AutofillId, AutofillValue.ForList(listValue));
|
|
||||||
setValue = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AutofillType.Date:
|
|
||||||
var dateValue = filledField.DateValue;
|
|
||||||
if(dateValue != null)
|
|
||||||
{
|
|
||||||
datasetBuilder.SetValue(field.AutofillId, AutofillValue.ForDate(dateValue.Value));
|
|
||||||
setValue = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AutofillType.Text:
|
|
||||||
var textValue = filledField.TextValue;
|
|
||||||
if(textValue != null)
|
|
||||||
{
|
|
||||||
datasetBuilder.SetValue(field.AutofillId, AutofillValue.ForText(textValue));
|
|
||||||
setValue = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AutofillType.Toggle:
|
|
||||||
var toggleValue = filledField.ToggleValue;
|
|
||||||
if(toggleValue != null)
|
|
||||||
{
|
|
||||||
datasetBuilder.SetValue(field.AutofillId, AutofillValue.ForToggle(toggleValue.Value));
|
|
||||||
setValue = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AutofillType.None:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return setValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HelpsWithHints(List<String> autofillHints)
|
|
||||||
{
|
|
||||||
return autofillHints.Any(h => HintToFieldMap.ContainsKey(h) && !HintToFieldMap[h].IsNull());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
using static Android.App.Assist.AssistStructure;
|
using static Android.App.Assist.AssistStructure;
|
||||||
using Android.App.Assist;
|
using Android.App.Assist;
|
||||||
|
using Bit.App;
|
||||||
|
|
||||||
namespace Bit.Android.Autofill
|
namespace Bit.Android.Autofill
|
||||||
{
|
{
|
||||||
|
@ -14,7 +15,6 @@ namespace Bit.Android.Autofill
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldCollection FieldCollection { get; private set; } = new FieldCollection();
|
public FieldCollection FieldCollection { get; private set; } = new FieldCollection();
|
||||||
public FilledFieldCollection FilledFieldCollection { get; private set; } = new FilledFieldCollection();
|
|
||||||
public string Uri
|
public string Uri
|
||||||
{
|
{
|
||||||
get => _uri;
|
get => _uri;
|
||||||
|
@ -26,30 +26,20 @@ namespace Bit.Android.Autofill
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_uri = $"androidapp://{value}";
|
_uri = string.Concat(Constants.AndroidAppProtocol, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ParseForFill()
|
public void Parse()
|
||||||
{
|
|
||||||
Parse(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ParseForSave()
|
|
||||||
{
|
|
||||||
Parse(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Parse(bool forFill)
|
|
||||||
{
|
{
|
||||||
for(var i = 0; i < _structure.WindowNodeCount; i++)
|
for(var i = 0; i < _structure.WindowNodeCount; i++)
|
||||||
{
|
{
|
||||||
var node = _structure.GetWindowNodeAt(i);
|
var node = _structure.GetWindowNodeAt(i);
|
||||||
ParseNode(forFill, node.RootViewNode);
|
ParseNode(node.RootViewNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ParseNode(bool forFill, ViewNode node)
|
private void ParseNode(ViewNode node)
|
||||||
{
|
{
|
||||||
var hints = node.GetAutofillHints();
|
var hints = node.GetAutofillHints();
|
||||||
var isEditText = node.ClassName == "android.widget.EditText";
|
var isEditText = node.ClassName == "android.widget.EditText";
|
||||||
|
@ -59,20 +49,12 @@ namespace Bit.Android.Autofill
|
||||||
{
|
{
|
||||||
Uri = node.IdPackage;
|
Uri = node.IdPackage;
|
||||||
}
|
}
|
||||||
|
FieldCollection.Add(new Field(node));
|
||||||
if(forFill)
|
|
||||||
{
|
|
||||||
FieldCollection.Add(new Field(node));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FilledFieldCollection.Add(new FilledField(node));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var i = 0; i < node.ChildCount; i++)
|
for(var i = 0; i < node.ChildCount; i++)
|
||||||
{
|
{
|
||||||
ParseNode(forFill, node.GetChildAt(i));
|
ParseNode(node.GetChildAt(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
26
src/Android/Autofill/SavedItem.cs
Normal file
26
src/Android/Autofill/SavedItem.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using Bit.App.Enums;
|
||||||
|
|
||||||
|
namespace Bit.Android.Autofill
|
||||||
|
{
|
||||||
|
public class SavedItem
|
||||||
|
{
|
||||||
|
public CipherType Type { get; set; }
|
||||||
|
public LoginItem Login { get; set; }
|
||||||
|
public CardItem Card { get; set; }
|
||||||
|
|
||||||
|
public class LoginItem
|
||||||
|
{
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CardItem
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Number { get; set; }
|
||||||
|
public string ExpMonth { get; set; }
|
||||||
|
public string ExpYear { get; set; }
|
||||||
|
public string Code { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -161,7 +161,7 @@ namespace Bit.Android
|
||||||
}
|
}
|
||||||
|
|
||||||
var parser = new Parser(structure);
|
var parser = new Parser(structure);
|
||||||
parser.ParseForFill();
|
parser.Parse();
|
||||||
if(!parser.FieldCollection.Fields.Any() || string.IsNullOrWhiteSpace(parser.Uri))
|
if(!parser.FieldCollection.Fields.Any() || string.IsNullOrWhiteSpace(parser.Uri))
|
||||||
{
|
{
|
||||||
SetResult(Result.Canceled);
|
SetResult(Result.Canceled);
|
||||||
|
@ -438,6 +438,7 @@ namespace Bit.Android
|
||||||
if(Intent.GetBooleanExtra("autofillFrameworkSave", false))
|
if(Intent.GetBooleanExtra("autofillFrameworkSave", false))
|
||||||
{
|
{
|
||||||
options.SaveType = (CipherType)Intent.GetIntExtra("autofillFrameworkType", 0);
|
options.SaveType = (CipherType)Intent.GetIntExtra("autofillFrameworkType", 0);
|
||||||
|
options.SaveName = Intent.GetStringExtra("autofillFrameworkName");
|
||||||
options.SaveUsername = Intent.GetStringExtra("autofillFrameworkUsername");
|
options.SaveUsername = Intent.GetStringExtra("autofillFrameworkUsername");
|
||||||
options.SavePassword = Intent.GetStringExtra("autofillFrameworkPassword");
|
options.SavePassword = Intent.GetStringExtra("autofillFrameworkPassword");
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace Bit.App.Models
|
||||||
public bool FromAutofillFramework { get; set; }
|
public bool FromAutofillFramework { 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 SaveUsername { get; set; }
|
public string SaveUsername { get; set; }
|
||||||
public string SavePassword { get; set; }
|
public string SavePassword { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace Bit.App.Pages
|
||||||
private DateTime? _lastAction;
|
private DateTime? _lastAction;
|
||||||
|
|
||||||
public VaultAddCipherPage(AppOptions options)
|
public VaultAddCipherPage(AppOptions options)
|
||||||
: this(options.SaveType.Value, options.Uri, options.Uri, options.FromAutofillFramework, false)
|
: this(options.SaveType.Value, options.Uri, options.SaveName, options.FromAutofillFramework, false)
|
||||||
{
|
{
|
||||||
_defaultUsername = options.SaveUsername;
|
_defaultUsername = options.SaveUsername;
|
||||||
_defaultPassword = options.SavePassword;
|
_defaultPassword = options.SavePassword;
|
||||||
|
|
Loading…
Reference in a new issue