first working (but still very rudimentary) version of Oreo Autofill (#9).

Not yet implemented and/or tested: partitioning, autofill fields without hints, saving, filling of other fields than username or password, package signature verification, DAL
This commit is contained in:
Philipp Crocoll
2017-12-28 03:04:03 +01:00
parent 7561afd92d
commit 1ed1e91189
16 changed files with 336 additions and 162 deletions

View File

@@ -16,7 +16,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:background="#eeeeff"
android:orientation="horizontal">
<TextView
@@ -24,6 +24,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textColor="#738282"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"

View File

@@ -142,8 +142,13 @@ namespace keepass2android
FragmentManager.FindFragmentById<GroupListFragment>(Resource.Id.list_fragment).ListAdapter = new PwGroupListAdapter(this, Group);
View selectOtherEntry = FindViewById (Resource.Id.select_other_entry);
selectOtherEntry.Click += (sender, e) => {
GroupActivity.Launch (this, new SelectEntryForUrlTask(url));
var newTask = new SelectEntryForUrlTask(url);
if (AppTask is SelectEntryTask currentSelectTask)
newTask.ShowUserNotifications = currentSelectTask.ShowUserNotifications;
selectOtherEntry.Click += (sender, e) => {
GroupActivity.Launch (this, newTask);
};

View File

@@ -217,6 +217,7 @@
<Compile Include="services\AutofillBase\AutofillFieldMetadata.cs" />
<Compile Include="services\AutofillBase\AutofillFieldMetadataCollection.cs" />
<Compile Include="services\AutofillBase\AutofillHelper.cs" />
<Compile Include="services\AutofillBase\AutofillHintsHelper.cs" />
<Compile Include="services\AutofillBase\AutofillServiceBase.cs" />
<Compile Include="services\AutofillBase\ChooseForAutofillActivityBase.cs" />
<Compile Include="services\AutofillBase\CommonUtil.cs" />

View File

@@ -28,9 +28,11 @@ namespace keepass2android.services.AutofillBase
AutofillType = view.AutofillType;
AutofillOptions = view.GetAutofillOptions();
Focused = view.IsFocused;
//TODO port and use AutoFillHints
SetHints(AutofillHelper.FilterForSupportedHints(view.GetAutofillHints()));
}
var supportedHints = AutofillHintsHelper.FilterForSupportedHints(view.GetAutofillHints());
var storedHints = AutofillHintsHelper.ConvertToStoredHints(supportedHints);
SetHints(storedHints.ToArray());
}
void SetHints(string[] value)
{
@@ -58,6 +60,7 @@ namespace keepass2android.services.AutofillBase
void UpdateSaveTypeFromHints()
{
//TODO future add savetypes for W3cHints
SaveType = 0;
if (AutofillHints == null)
{

View File

@@ -40,7 +40,7 @@ namespace keepass2android.services.AutofillBase
{
if (!AutofillHintsToFieldsMap.ContainsKey(hint))
{
AutofillHintsToFieldsMap.Add(hint, new List<keepass2android.services.AutofillBase.AutofillFieldMetadata>());
AutofillHintsToFieldsMap.Add(hint, new List<AutofillFieldMetadata>());
}
AutofillHintsToFieldsMap[hint].Add(autofillFieldMetadata);
}
@@ -51,7 +51,7 @@ namespace keepass2android.services.AutofillBase
return AutofillIds.ToArray();
}
public List<keepass2android.services.AutofillBase.AutofillFieldMetadata> GetFieldsForHint(String hint)
public List<AutofillFieldMetadata> GetFieldsForHint(String hint)
{
return AutofillHintsToFieldsMap[hint];
}

View File

@@ -7,7 +7,6 @@ using Android.Views;
using Android.Widget;
using FilledAutofillFieldCollection = keepass2android.services.AutofillBase.model.FilledAutofillFieldCollection;
//TODO compare port
namespace keepass2android.services.AutofillBase
{
/// <summary>
@@ -93,6 +92,7 @@ namespace keepass2android.services.AutofillBase
}
if (autofillFields.SaveType != 0)
{
//TODO implement save
var autofillIds = autofillFields.GetAutofillIds();
responseBuilder.SetSaveInfo
(new SaveInfo.Builder(autofillFields.SaveType, autofillIds).Build());
@@ -105,47 +105,5 @@ namespace keepass2android.services.AutofillBase
}
}
public static string[] FilterForSupportedHints(string[] hints)
{
var filteredHints = new string[hints.Length];
int i = 0;
foreach (var hint in hints)
{
if (IsValidHint(hint))
{
filteredHints[i++] = hint;
}
else
{
Log.Debug(CommonUtil.Tag, "Invalid autofill hint: " + hint);
}
}
var finalFilteredHints = new string[i];
Array.Copy(filteredHints, 0, finalFilteredHints, 0, i);
return finalFilteredHints;
}
public static bool IsValidHint(String hint)
{
switch (hint)
{
case View.AutofillHintCreditCardExpirationDate:
case View.AutofillHintCreditCardExpirationDay:
case View.AutofillHintCreditCardExpirationMonth:
case View.AutofillHintCreditCardExpirationYear:
case View.AutofillHintCreditCardNumber:
case View.AutofillHintCreditCardSecurityCode:
case View.AutofillHintEmailAddress:
case View.AutofillHintPhone:
case View.AutofillHintName:
case View.AutofillHintPassword:
case View.AutofillHintPostalAddress:
case View.AutofillHintPostalCode:
case View.AutofillHintUsername:
return true;
default:
return false;
}
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using keepass2android.services.AutofillBase.model;
namespace keepass2android.services.AutofillBase
{
class AutofillHintsHelper
{
private static readonly HashSet<string> validHints = new HashSet<string>()
{
View.AutofillHintUsername,
View.AutofillHintPassword,
W3cHints.USERNAME,
W3cHints.CURRENT_PASSWORD,
W3cHints.NEW_PASSWORD
};
private static readonly Dictionary<string, string> hintReplacements= new Dictionary<string, string>()
{
{W3cHints.EMAIL, View.AutofillHintEmailAddress},
{W3cHints.USERNAME, View.AutofillHintUsername},
{W3cHints.CURRENT_PASSWORD, View.AutofillHintPassword},
{W3cHints.NEW_PASSWORD, View.AutofillHintPassword},
{W3cHints.CC_EXPIRATION_MONTH, View.AutofillHintCreditCardExpirationMonth },
{W3cHints.CC_EXPIRATION_YEAR, View.AutofillHintCreditCardExpirationYear },
{W3cHints.CC_EXPIRATION, View.AutofillHintCreditCardExpirationDate },
{W3cHints.CC_NUMBER, View.AutofillHintCreditCardNumber },
{W3cHints.CC_CSC, View.AutofillHintCreditCardSecurityCode },
{W3cHints.POSTAL_CODE, View.AutofillHintPostalCode },
};
public static bool IsValidHint(string hint)
{
return validHints.Contains(hint);
}
public static string[] FilterForSupportedHints(string[] hints)
{
var filteredHints = new string[hints.Length];
int i = 0;
foreach (var hint in hints)
{
if (IsValidHint(hint))
{
filteredHints[i++] = hint;
}
else
{
Log.Debug(CommonUtil.Tag, "Invalid autofill hint: " + hint);
}
}
var finalFilteredHints = new string[i];
Array.Copy(filteredHints, 0, finalFilteredHints, 0, i);
return finalFilteredHints;
}
public static List<string> ConvertToStoredHints(string[] supportedHints)
{
List<string> result = new List<string>();
foreach (string hint in supportedHints)
{
string storedHint = hint;
if (hintReplacements.ContainsKey(hint))
storedHint = hintReplacements[hint];
result.Add(storedHint);
}
return result;
}
}
}

View File

@@ -4,6 +4,8 @@ using Android.OS;
using Android.Runtime;
using Android.Service.Autofill;
using Android.Util;
using Android.Views.Autofill;
using Android.Widget;
namespace keepass2android.services.AutofillBase
{
@@ -47,6 +49,7 @@ namespace keepass2android.services.AutofillBase
try
{
query = parser.ParseForFill();
}
catch (Java.Lang.SecurityException e)
{
@@ -56,20 +59,30 @@ namespace keepass2android.services.AutofillBase
}
AutofillFieldMetadataCollection autofillFields = parser.AutofillFields;
var responseBuilder = new FillResponse.Builder();
// Check user's settings for authenticating Responses and Datasets.
bool responseAuth = true;
var autofillIds = autofillFields.GetAutofillIds();
if (responseAuth && autofillIds.Length != 0)
{
var responseBuilder = new FillResponse.Builder();
// If the entire Autofill Response is authenticated, AuthActivity is used
// to generate Response.
var sender = IntentBuilder.GetAuthIntentSenderForResponse(this, query);
var presentation = keepass2android.services.AutofillBase.AutofillHelper
RemoteViews presentation = keepass2android.services.AutofillBase.AutofillHelper
.NewRemoteViews(PackageName, GetString(Resource.String.autofill_sign_in_prompt),
Resource.Drawable.ic_launcher);
responseBuilder
.SetAuthentication(autofillIds, sender, presentation);
var datasetBuilder = new Dataset.Builder(presentation);
datasetBuilder
.SetAuthentication(sender);
foreach (var autofillId in autofillIds)
{
datasetBuilder.SetValue(autofillId, AutofillValue.ForText("PLACEHOLDER"));
}
responseBuilder.AddDataset(datasetBuilder.Build());
callback.OnSuccess(responseBuilder.Build());
}
else

View File

@@ -22,7 +22,7 @@ namespace keepass2android.services.AutofillBase
public static string ExtraQueryString => "EXTRA_QUERY_STRING";
public int RequestCodeQuery => 663245;
public int RequestCodeQuery => 6245;
protected override void OnCreate(Bundle savedInstanceState)
{
@@ -48,6 +48,11 @@ namespace keepass2android.services.AutofillBase
StartActivityForResult(i, RequestCodeQuery);
}
protected override void OnStart()
{
base.OnStart();
}
protected abstract Intent GetQueryIntent(string requestedUrl);
protected void RestartApp()
@@ -80,21 +85,12 @@ namespace keepass2android.services.AutofillBase
protected void OnSuccess(FilledAutofillFieldCollection clientFormDataMap)
{
var intent = Intent;
var forResponse = intent.GetBooleanExtra(CommonUtil.EXTRA_FOR_RESPONSE, true);
AssistStructure structure = (AssistStructure)intent.GetParcelableExtra(AutofillManager.ExtraAssistStructure);
StructureParser parser = new StructureParser(this, structure);
parser.ParseForFill();
AutofillFieldMetadataCollection autofillFields = parser.AutofillFields;
ReplyIntent = new Intent();
if (forResponse)
{
Dictionary<string, FilledAutofillFieldCollection> dict = new Dictionary<string, FilledAutofillFieldCollection> { {clientFormDataMap.DatasetName, clientFormDataMap }};
SetResponseIntent(AutofillHelper.NewResponse(this, false, autofillFields, dict, IntentBuilder));
}
else
{
SetDatasetIntent(AutofillHelper.NewDataset(this, autofillFields, clientFormDataMap, false, IntentBuilder));
}
SetDatasetIntent(AutofillHelper.NewDataset(this, autofillFields, clientFormDataMap, false, IntentBuilder));
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
@@ -103,16 +99,21 @@ namespace keepass2android.services.AutofillBase
if (requestCode == RequestCodeQuery)
{
if (resultCode != Result.Ok)
OnFailure();
else
if (resultCode == ExpectedActivityResult)
OnSuccess(GetDataset(data));
else
OnFailure();
Finish();
}
}
protected virtual Result ExpectedActivityResult
{
get { return Result.Ok; }
}
/// <summary>
/// Creates the FilledAutofillFieldCollection from the intent returned from the query activity
/// </summary>

View File

@@ -1,6 +1,7 @@
using System;
using System.Text;
using Android.OS;
using Android.Util;
using Java.Util;
namespace keepass2android.services.AutofillBase
@@ -9,8 +10,6 @@ namespace keepass2android.services.AutofillBase
{
public const string Tag = "Kp2aAutofill";
public const bool Debug = true;
public const string EXTRA_DATASET_NAME = "dataset_name";
public const string EXTRA_FOR_RESPONSE = "for_response";
static void BundleToString(StringBuilder builder, Bundle data)
{
@@ -43,5 +42,17 @@ namespace keepass2android.services.AutofillBase
BundleToString(builder, data);
return builder.ToString();
}
public static void logd(string s)
{
#if DEBUG
Log.Debug(Tag, s);
#endif
}
public static void loge(string s)
{
Kp2aLog.Log(s);
}
}
}

View File

@@ -52,20 +52,21 @@ namespace keepass2android.services.AutofillBase
var view = node.RootViewNode;
ParseLocked(forFill, view, ref webDomain);
}
if (!string.IsNullOrEmpty(webDomain))
String packageName = Structure.ActivityComponent.PackageName;
if (!string.IsNullOrEmpty(webDomain))
{
String packageName = Structure.ActivityComponent.PackageName;
bool valid = Kp2aDigitalAssetLinksDataSource.Instance.IsValid(mContext, webDomain, packageName);
if (!valid)
{
throw new Java.Lang.SecurityException(mContext.GetString(
Resource.String.invalid_link_association, webDomain, packageName));
}
Log.Debug(keepass2android.services.AutofillBase.CommonUtil.Tag, $"Domain {webDomain} is valid for {packageName}");
Log.Debug(keepass2android.services.AutofillBase.CommonUtil.Tag, $"Domain {webDomain} is valid for {packageName}");
}
else
{
Log.Debug(keepass2android.services.AutofillBase.CommonUtil.Tag, "no web domain");
webDomain = "androidapp://" + packageName;
Log.Debug(keepass2android.services.AutofillBase.CommonUtil.Tag, "no web domain. Using package name.");
}
return webDomain;
}
@@ -93,7 +94,7 @@ namespace keepass2android.services.AutofillBase
{
if (forFill)
{
AutofillFields.Add(new keepass2android.services.AutofillBase.AutofillFieldMetadata(viewNode));
AutofillFields.Add(new AutofillFieldMetadata(viewNode));
}
else
{

View File

@@ -11,12 +11,13 @@ namespace keepass2android.services.AutofillBase.model
public string[] AutofillHints { get; set; }
public FilledAutofillField()
{}
public FilledAutofillField(AssistStructure.ViewNode viewNode)
/*public FilledAutofillField(AssistStructure.ViewNode viewNode)
{
AutofillHints = AutofillHelper.FilterForSupportedHints(viewNode.GetAutofillHints());
AutofillHintsHelper = AutofillHelper.FilterForSupportedHints(viewNode.GetAutofillHints());
//TODO port updated FilledAutofillField?
AutofillValue autofillValue = viewNode.AutofillValue;
@@ -40,7 +41,7 @@ namespace keepass2android.services.AutofillBase.model
TextValue = autofillValue.TextValue;
}
}
}
}*/
public bool IsNull()
{

View File

@@ -32,26 +32,114 @@ namespace keepass2android.services.AutofillBase.model
public void Add(FilledAutofillField filledAutofillField)
{
string[] autofillHints = filledAutofillField.AutofillHints;
//TODO apply W3C transformation
foreach (string hint in autofillHints)
{
HintMap.Add(hint, filledAutofillField);
}
string nextHint = null;
for (int i = 0; i < autofillHints.Length; i++)
{
string hint = autofillHints[i];
if (i < autofillHints.Length - 1)
{
nextHint = autofillHints[i + 1];
}
// First convert the compound W3C autofill hints
if (isW3cSectionPrefix(hint) && i < autofillHints.Length - 1)
{
hint = autofillHints[++i];
CommonUtil.logd($"Hint is a W3C section prefix; using {hint} instead");
if (i < autofillHints.Length - 1)
{
nextHint = autofillHints[i + 1];
}
}
if (isW3cTypePrefix(hint) && nextHint != null && isW3cTypeHint(nextHint))
{
hint = nextHint;
i++;
CommonUtil.logd($"Hint is a W3C type prefix; using {hint} instead");
}
if (isW3cAddressType(hint) && nextHint != null)
{
hint = nextHint;
i++;
CommonUtil.logd($"Hint is a W3C address prefix; using {hint} instead");
}
// Then check if the "actual" hint is supported.
if (AutofillHintsHelper.IsValidHint(hint))
{
HintMap.Add(hint, filledAutofillField);
}
else
{
CommonUtil.loge($"Invalid hint: {autofillHints[i]}");
}
}
}
/// <summary>
/// Populates a Dataset.Builder with appropriate values for each AutofillId
/// in a AutofillFieldMetadataCollection.
///
/// In other words, it constructs an autofill Dataset.Builder
/// by applying saved values (from this FilledAutofillFieldCollection)
/// to Views specified in a AutofillFieldMetadataCollection, which represents the current
/// page the user is on.
/// </summary>
/// <returns><c>true</c>, if to fields was applyed, <c>false</c> otherwise.</returns>
/// <param name="autofillFieldMetadataCollection">Autofill field metadata collection.</param>
/// <param name="datasetBuilder">Dataset builder.</param>
public bool ApplyToFields(AutofillFieldMetadataCollection autofillFieldMetadataCollection,
private static bool isW3cSectionPrefix(string hint)
{
return hint.StartsWith(W3cHints.PREFIX_SECTION);
}
private static bool isW3cAddressType(string hint)
{
switch (hint)
{
case W3cHints.SHIPPING:
case W3cHints.BILLING:
return true;
}
return false;
}
private static bool isW3cTypePrefix(string hint)
{
switch (hint)
{
case W3cHints.PREFIX_WORK:
case W3cHints.PREFIX_FAX:
case W3cHints.PREFIX_HOME:
case W3cHints.PREFIX_PAGER:
return true;
}
return false;
}
private static bool isW3cTypeHint(string hint)
{
switch (hint)
{
case W3cHints.TEL:
case W3cHints.TEL_COUNTRY_CODE:
case W3cHints.TEL_NATIONAL:
case W3cHints.TEL_AREA_CODE:
case W3cHints.TEL_LOCAL:
case W3cHints.TEL_LOCAL_PREFIX:
case W3cHints.TEL_LOCAL_SUFFIX:
case W3cHints.TEL_EXTENSION:
case W3cHints.EMAIL:
case W3cHints.IMPP:
return true;
}
Log.Warn(CommonUtil.Tag, "Invalid W3C type hint: " + hint);
return false;
}
/// <summary>
/// Populates a Dataset.Builder with appropriate values for each AutofillId
/// in a AutofillFieldMetadataCollection.
///
/// In other words, it constructs an autofill Dataset.Builder
/// by applying saved values (from this FilledAutofillFieldCollection)
/// to Views specified in a AutofillFieldMetadataCollection, which represents the current
/// page the user is on.
/// </summary>
/// <returns><c>true</c>, if to fields was applyed, <c>false</c> otherwise.</returns>
/// <param name="autofillFieldMetadataCollection">Autofill field metadata collection.</param>
/// <param name="datasetBuilder">Dataset builder.</param>
public bool ApplyToFields(AutofillFieldMetadataCollection autofillFieldMetadataCollection,
Dataset.Builder datasetBuilder)
{
bool setValueAtLeastOnce = false;
@@ -66,8 +154,8 @@ namespace keepass2android.services.AutofillBase.model
}
for (int autofillFieldIndex = 0; autofillFieldIndex < fillableAutofillFields.Count; autofillFieldIndex++)
{
keepass2android.services.AutofillBase.model.FilledAutofillField filledAutofillField = HintMap[hint];
if (filledAutofillField == null)
FilledAutofillField filledAutofillField;
if (!HintMap.TryGetValue(hint, out filledAutofillField) || (filledAutofillField == null))
{
continue;
}

View File

@@ -4,68 +4,68 @@
{
// Supported W3C autofill tokens (https://html.spec.whatwg.org/multipage/forms.html#autofill)
public static string HONORIFIC_PREFIX = "honorific-prefix";
public static string NAME = "name";
public static string GIVEN_NAME = "given-name";
public static string ADDITIONAL_NAME = "additional-name";
public static string FAMILY_NAME = "family-name";
public static string HONORIFIC_SUFFIX = "honorific-suffix";
public static string USERNAME = "username";
public static string NEW_PASSWORD = "new-password";
public static string CURRENT_PASSWORD = "current-password";
public static string ORGANIZATION_TITLE = "organization-title";
public static string ORGANIZATION = "organization";
public static string STREET_ADDRESS = "street-address";
public static string ADDRESS_LINE1 = "address-line1";
public static string ADDRESS_LINE2 = "address-line2";
public static string ADDRESS_LINE3 = "address-line3";
public static string ADDRESS_LEVEL4 = "address-level4";
public static string ADDRESS_LEVEL3 = "address-level3";
public static string ADDRESS_LEVEL2 = "address-level2";
public static string ADDRESS_LEVEL1 = "address-level1";
public static string COUNTRY = "country";
public static string COUNTRY_NAME = "country-name";
public static string POSTAL_CODE = "postal-code";
public static string CC_NAME = "cc-name";
public static string CC_GIVEN_NAME = "cc-given-name";
public static string CC_ADDITIONAL_NAME = "cc-additional-name";
public static string CC_FAMILY_NAME = "cc-family-name";
public static string CC_NUMBER = "cc-number";
public static string CC_EXPIRATION = "cc-exp";
public static string CC_EXPIRATION_MONTH = "cc-exp-month";
public static string CC_EXPIRATION_YEAR = "cc-exp-year";
public static string CC_CSC = "cc-csc";
public static string CC_TYPE = "cc-type";
public static string TRANSACTION_CURRENCY = "transaction-currency";
public static string TRANSACTION_AMOUNT = "transaction-amount";
public static string LANGUAGE = "language";
public static string BDAY = "bday";
public static string BDAY_DAY = "bday-day";
public static string BDAY_MONTH = "bday-month";
public static string BDAY_YEAR = "bday-year";
public static string SEX = "sex";
public static string URL = "url";
public static string PHOTO = "photo";
public const string HONORIFIC_PREFIX = "honorific-prefix";
public const string NAME = "name";
public const string GIVEN_NAME = "given-name";
public const string ADDITIONAL_NAME = "additional-name";
public const string FAMILY_NAME = "family-name";
public const string HONORIFIC_SUFFIX = "honorific-suffix";
public const string USERNAME = "username";
public const string NEW_PASSWORD = "new-password";
public const string CURRENT_PASSWORD = "current-password";
public const string ORGANIZATION_TITLE = "organization-title";
public const string ORGANIZATION = "organization";
public const string STREET_ADDRESS = "street-address";
public const string ADDRESS_LINE1 = "address-line1";
public const string ADDRESS_LINE2 = "address-line2";
public const string ADDRESS_LINE3 = "address-line3";
public const string ADDRESS_LEVEL4 = "address-level4";
public const string ADDRESS_LEVEL3 = "address-level3";
public const string ADDRESS_LEVEL2 = "address-level2";
public const string ADDRESS_LEVEL1 = "address-level1";
public const string COUNTRY = "country";
public const string COUNTRY_NAME = "country-name";
public const string POSTAL_CODE = "postal-code";
public const string CC_NAME = "cc-name";
public const string CC_GIVEN_NAME = "cc-given-name";
public const string CC_ADDITIONAL_NAME = "cc-additional-name";
public const string CC_FAMILY_NAME = "cc-family-name";
public const string CC_NUMBER = "cc-number";
public const string CC_EXPIRATION = "cc-exp";
public const string CC_EXPIRATION_MONTH = "cc-exp-month";
public const string CC_EXPIRATION_YEAR = "cc-exp-year";
public const string CC_CSC = "cc-csc";
public const string CC_TYPE = "cc-type";
public const string TRANSACTION_CURRENCY = "transaction-currency";
public const string TRANSACTION_AMOUNT = "transaction-amount";
public const string LANGUAGE = "language";
public const string BDAY = "bday";
public const string BDAY_DAY = "bday-day";
public const string BDAY_MONTH = "bday-month";
public const string BDAY_YEAR = "bday-year";
public const string SEX = "sex";
public const string URL = "url";
public const string PHOTO = "photo";
// Optional W3C prefixes
public static string PREFIX_SECTION = "section-";
public static string SHIPPING = "shipping";
public static string BILLING = "billing";
public const string PREFIX_SECTION = "section-";
public const string SHIPPING = "shipping";
public const string BILLING = "billing";
// W3C prefixes below...
public static string PREFIX_HOME = "home";
public static string PREFIX_WORK = "work";
public static string PREFIX_FAX = "fax";
public static string PREFIX_PAGER = "pager";
public const string PREFIX_HOME = "home";
public const string PREFIX_WORK = "work";
public const string PREFIX_FAX = "fax";
public const string PREFIX_PAGER = "pager";
// ... require those suffix
public static string TEL = "tel";
public static string TEL_COUNTRY_CODE = "tel-country-code";
public static string TEL_NATIONAL = "tel-national";
public static string TEL_AREA_CODE = "tel-area-code";
public static string TEL_LOCAL = "tel-local";
public static string TEL_LOCAL_PREFIX = "tel-local-prefix";
public static string TEL_LOCAL_SUFFIX = "tel-local-suffix";
public static string TEL_EXTENSION = "tel_extension";
public static string EMAIL = "email";
public static string IMPP = "impp";
public const string TEL = "tel";
public const string TEL_COUNTRY_CODE = "tel-country-code";
public const string TEL_NATIONAL = "tel-national";
public const string TEL_AREA_CODE = "tel-area-code";
public const string TEL_LOCAL = "tel-local";
public const string TEL_LOCAL_PREFIX = "tel-local-prefix";
public const string TEL_LOCAL_SUFFIX = "tel-local-suffix";
public const string TEL_EXTENSION = "tel_extension";
public const string EMAIL = "email";
public const string IMPP = "impp";
private W3cHints()
{

View File

@@ -34,6 +34,8 @@ namespace keepass2android.services.Kp2aAutofill
return i;
}
protected override Result ExpectedActivityResult => KeePass.ExitCloseAfterTaskComplete;
protected override FilledAutofillFieldCollection GetDataset(Intent data)
{
if (!App.Kp2a.GetDb().Loaded || (App.Kp2a.QuickLocked))
@@ -45,13 +47,13 @@ namespace keepass2android.services.Kp2aAutofill
FilledAutofillField pwdField =
new FilledAutofillField
{
AutofillHints = new[] {W3cHints.NAME, W3cHints.EMAIL},
AutofillHints = new[] {View.AutofillHintPassword},
TextValue = password
};
FilledAutofillField userField = new FilledAutofillField
{
AutofillHints = new[] {W3cHints.NEW_PASSWORD, W3cHints.CURRENT_PASSWORD},
AutofillHints = new[] {View.AutofillHintUsername},
TextValue = username
};

View File

@@ -9,6 +9,7 @@ using Android.Runtime;
using Android.Views;
using Android.Widget;
using keepass2android.services.AutofillBase;
using keepass2android.services.Kp2aAutofill;
namespace keepass2android.services
{
@@ -17,7 +18,8 @@ namespace keepass2android.services
public IntentSender GetAuthIntentSenderForResponse(Context context, string query)
{
Intent intent = new Intent(context, typeof(KeePass));
Intent intent = new Intent(context, typeof(ChooseForAutofillActivity));
intent.PutExtra(ChooseForAutofillActivityBase.ExtraQueryString, query);
return PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent).IntentSender;
}