start working on Oreo AutofillService (issue #9):

* upgraded target version to 26
* added service, parses autofill structure but does not yet retrieve/fill passwords
This commit is contained in:
Philipp Crocoll
2017-12-19 22:25:16 +01:00
parent 4a738990ae
commit 7720e8005e
34 changed files with 1005 additions and 26 deletions

1
.gitignore vendored
View File

@@ -153,3 +153,4 @@ intermediates
/src/java/Kp2aAccServiceLib/app/app.iml
/src/java/Kp2aAccServiceLib/gradle
adbprompt.ps1
/src/java/KP2ASoftkeyboard_AS/build/android-profile/*.rawproto

View File

@@ -10,7 +10,7 @@
<RootNamespace>AndroidFileChooserBinding</RootNamespace>
<AssemblyName>AndroidFileChooserBinding</AssemblyName>
<FileAlignment>512</FileAlignment>
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

View File

@@ -11,7 +11,7 @@
<AssemblyName>JavaFileStorageBindings</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

View File

@@ -10,7 +10,7 @@
<RootNamespace>KP2AKdbLibraryBinding</RootNamespace>
<AssemblyName>KP2AKdbLibraryBinding</AssemblyName>
<FileAlignment>512</FileAlignment>
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

View File

@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2009
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassLib2Android", "KeePassLib2Android\KeePassLib2Android.csproj", "{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}"
EndProject
@@ -27,6 +27,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.FtpClient.Androi
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamsungPass", "SamsungPass\Xamarin.SamsungPass\SamsungPass\SamsungPass.csproj", "{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aAutofillBinding", "Kp2aAutofillBinding\Kp2aAutofillBinding.csproj", "{39D433EC-253C-44D8-89A0-85C06A41FB8C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aAutofillLib", "Kp2aAutofillLib\Kp2aAutofillLib.csproj", "{612D3DD7-995B-4484-8D40-1607889EF0B8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutofillTestApp", "AutofillTestApp\AutofillTestApp.csproj", "{C75CFA4A-F969-4E27-B9AC-A73706B10E39}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -283,10 +289,97 @@ Global
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Win32.ActiveCfg = Debug|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Win32.Build.0 = Debug|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|x64.ActiveCfg = Debug|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|x64.Build.0 = Debug|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Any CPU.Build.0 = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Win32.ActiveCfg = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Win32.Build.0 = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|x64.ActiveCfg = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|x64.Build.0 = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Win32.ActiveCfg = Debug|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Win32.Build.0 = Debug|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|x64.ActiveCfg = Debug|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|x64.Build.0 = Debug|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Any CPU.Build.0 = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Win32.ActiveCfg = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Win32.Build.0 = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|x64.ActiveCfg = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|x64.Build.0 = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Win32.ActiveCfg = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Win32.Build.0 = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Win32.Deploy.0 = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|x64.ActiveCfg = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|x64.Build.0 = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|x64.Deploy.0 = Debug|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Any CPU.Build.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Any CPU.Deploy.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Mixed Platforms.Deploy.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Win32.ActiveCfg = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Win32.Build.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Win32.Deploy.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|x64.ActiveCfg = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|x64.Build.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|x64.Deploy.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Any CPU.Deploy.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Mixed Platforms.Deploy.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Win32.Deploy.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
{C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|x64.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2B48EDA2-ABCE-4DB5-A609-DFDF5FAAE767}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
Policies = $0
$0.DotNetNamingPolicy = $1

View File

@@ -12,7 +12,7 @@
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
<AndroidResgenClass>Resource</AndroidResgenClass>
<AssemblyName>KeePassLib2Android</AssemblyName>
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<NuGetPackageImportStamp>8482b288</NuGetPackageImportStamp>
</PropertyGroup>

View File

@@ -12,7 +12,7 @@
<FileAlignment>512</FileAlignment>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
<NuGetPackageImportStamp>06ffb71c</NuGetPackageImportStamp>
</PropertyGroup>

View File

@@ -11,7 +11,7 @@
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<AssemblyName>Kp2aKeyboardBinding</AssemblyName>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>

View File

@@ -11,7 +11,7 @@
<AssemblyName>PluginSdkBinding</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -53,8 +53,8 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<LibraryProjectZip Include="..\java\Keepass2AndroidPluginSDK2\app\build\outputs\aar\app-debug.aar">
<Link>Jars\app-debug.aar</Link>
<LibraryProjectZip Include="..\java\Keepass2AndroidPluginSDK2\app\build\outputs\aar\Keepass2AndroidPluginSDK2-debug.aar">
<Link>Jars\Keepass2AndroidPluginSDK2-debug.aar</Link>
</LibraryProjectZip>
<None Include="Jars\AboutJars.txt" />
<None Include="Additions\AboutAdditions.txt" />

View File

@@ -13,7 +13,7 @@
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

View File

@@ -13,7 +13,7 @@
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<AssemblyName>ZlibAndroid</AssemblyName>
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

View File

@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
classpath 'com.android.tools.build:gradle:3.0.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@@ -1,6 +1,6 @@
#Mon May 22 10:43:15 CEST 2017
#Mon Dec 18 11:13:13 CET 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip

View File

@@ -1,7 +1,7 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 'Google Inc.:Google APIs:23'
buildToolsVersion '23.0.1'
buildToolsVersion '26.0.2'
defaultConfig {
minSdkVersion 8

View File

@@ -10,7 +10,6 @@
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
</application>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -4,7 +4,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.android.tools.build:gradle:2.2.1'
}
}

View File

@@ -1,6 +1,6 @@
#Wed Apr 10 15:27:10 PDT 2013
#Mon Dec 18 11:08:40 CET 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

View File

@@ -1030,4 +1030,7 @@ Initial public release
<string name="ClearClipboardWarning">Make sure this works on your system and consider using the built-in keyboard if not.</string>
<string name="PluginDescription">Description provided by the plugin:</string>
<string name="autofill_sign_in_prompt">Fill with Keepass2Android</string>
<string name="invalid_link_association">Could not associate web domain %1$s with app %2$s</string>
</resources>

View File

@@ -15,10 +15,10 @@
<AssemblyName>keepass2android</AssemblyName>
<newfilesearch>OnLoad</newfilesearch>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<MandroidI18n />
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<NuGetPackageImportStamp>9e78b013</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -41,10 +41,12 @@
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
<BundleAssemblies>False</BundleAssemblies>
<BundleAssemblies>false</BundleAssemblies>
<AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
<AndroidEnableMultiDex>false</AndroidEnableMultiDex>
<EnableProguard>true</EnableProguard>
<AotAssemblies>false</AotAssemblies>
<EnableLLVM>false</EnableLLVM>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
@@ -185,6 +187,16 @@
<Compile Include="fileselect\FileDbHelper.cs" />
<Compile Include="search\SearchProvider.cs" />
<Compile Include="SelectStorageLocationActivity.cs" />
<Compile Include="services\AutofillBase\AutofillFieldMetadata.cs" />
<Compile Include="services\AutofillBase\AutofillFieldMetadataCollection.cs" />
<Compile Include="services\AutofillBase\AutofillHelper.cs" />
<Compile Include="services\AutofillBase\AutofillServiceBase.cs" />
<Compile Include="services\AutofillBase\CommonUtil.cs" />
<Compile Include="services\AutofillBase\Kp2aDigitalAssetLinksDataSource.cs" />
<Compile Include="services\AutofillBase\model\FilledAutofillField.cs" />
<Compile Include="services\AutofillBase\model\FilledAutofillFieldCollection.cs" />
<Compile Include="services\AutofillBase\StructureParser.cs" />
<Compile Include="services\Kp2aAutofillService.cs" />
<Compile Include="services\OngoingNotificationsService.cs" />
<Compile Include="settings\Argon2Preference.cs" />
<Compile Include="settings\DatabaseSettingsActivity.cs" />
@@ -1723,6 +1735,12 @@
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\ic_picture.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\xml\autofillservice.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\autofill_service_list_item.xml" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">

View File

@@ -0,0 +1,101 @@
using System;
using Android.App.Assist;
using Android.Service.Autofill;
using Android.Views;
using Android.Views.Autofill;
namespace keepass2android.services.AutofillBase
{
/// <summary>
/// A stripped down version of a {@link ViewNode} that contains only autofill-relevant metadata. It
/// also contains a {@code mSaveType} flag that is calculated based on the {@link ViewNode}]'s
/// autofill hints.
/// </summary>
public class AutofillFieldMetadata
{
public SaveDataType SaveType { get; set; }
public string[] AutofillHints { get; set; }
public AutofillId AutofillId { get; }
public AutofillType AutofillType { get; }
string[] AutofillOptions { get; }
public bool Focused { get; }
public AutofillFieldMetadata(AssistStructure.ViewNode view)
{
AutofillId = view.AutofillId;
AutofillType = view.AutofillType;
AutofillOptions = view.GetAutofillOptions();
Focused = view.IsFocused;
//TODO port and use AutoFillHints
SetHints(AutofillHelper.FilterForSupportedHints(view.GetAutofillHints()));
}
void SetHints(string[] value)
{
AutofillHints = value;
UpdateSaveTypeFromHints();
}
/// <summary>
/// When the ViewNode is a list that the user needs to choose a string from (i.e. a
/// spinner), this is called to return the index of a specific item in the list.
/// </summary>
/// <returns>The autofill option index.</returns>
/// <param name="value">Value.</param>
public int GetAutofillOptionIndex(String value)
{
for (int i = 0; i < AutofillOptions.Length; i++)
{
if (AutofillOptions[i].Equals(value))
{
return i;
}
}
return -1;
}
void UpdateSaveTypeFromHints()
{
SaveType = 0;
if (AutofillHints == null)
{
return;
}
foreach (var hint in AutofillHints)
{
switch (hint)
{
case View.AutofillHintCreditCardExpirationDate:
case View.AutofillHintCreditCardExpirationDay:
case View.AutofillHintCreditCardExpirationMonth:
case View.AutofillHintCreditCardExpirationYear:
case View.AutofillHintCreditCardNumber:
case View.AutofillHintCreditCardSecurityCode:
SaveType |= SaveDataType.CreditCard;
break;
case View.AutofillHintEmailAddress:
SaveType |= SaveDataType.EmailAddress;
break;
case View.AutofillHintPhone:
case View.AutofillHintName:
SaveType |= SaveDataType.Generic;
break;
case View.AutofillHintPassword:
SaveType |= SaveDataType.Password;
SaveType &= ~SaveDataType.EmailAddress;
SaveType &= ~SaveDataType.Username;
break;
case View.AutofillHintPostalAddress:
case View.AutofillHintPostalCode:
SaveType |= SaveDataType.Address;
break;
case View.AutofillHintUsername:
SaveType |= SaveDataType.Username;
break;
}
}
}
}
}

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using Android.Service.Autofill;
using Android.Views.Autofill;
namespace keepass2android.services.AutofillBase
{
/// <summary>
/// Data structure that stores a collection of AutofillFieldMetadatas. Contains all of the
/// client's View hierarchy autofill-relevant metadata.
/// </summary>
public class AutofillFieldMetadataCollection
{
List<AutofillId> AutofillIds = new List<AutofillId>();
Dictionary<string, List<keepass2android.services.AutofillBase.AutofillFieldMetadata>> AutofillHintsToFieldsMap = new Dictionary<string, List<keepass2android.services.AutofillBase.AutofillFieldMetadata>>();
public List<string> AllAutofillHints { get; }
public List<string> FocusedAutofillHints { get; }
int Size = 0;
public SaveDataType SaveType { get; set; }
public AutofillFieldMetadataCollection()
{
SaveType = 0;
FocusedAutofillHints = new List<string>();
AllAutofillHints = new List<string>();
}
public void Add(keepass2android.services.AutofillBase.AutofillFieldMetadata autofillFieldMetadata)
{
SaveType |= autofillFieldMetadata.SaveType;
Size++;
AutofillIds.Add(autofillFieldMetadata.AutofillId);
var hintsList = autofillFieldMetadata.AutofillHints;
AllAutofillHints.AddRange(hintsList);
if (autofillFieldMetadata.Focused)
{
FocusedAutofillHints.AddRange(hintsList);
}
foreach (var hint in autofillFieldMetadata.AutofillHints)
{
if (!AutofillHintsToFieldsMap.ContainsKey(hint))
{
AutofillHintsToFieldsMap.Add(hint, new List<keepass2android.services.AutofillBase.AutofillFieldMetadata>());
}
AutofillHintsToFieldsMap[hint].Add(autofillFieldMetadata);
}
}
public AutofillId[] GetAutofillIds()
{
return AutofillIds.ToArray();
}
public List<keepass2android.services.AutofillBase.AutofillFieldMetadata> GetFieldsForHint(String hint)
{
return AutofillHintsToFieldsMap[hint];
}
}
}

View File

@@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using Android.Content;
using Android.Service.Autofill;
using Android.Util;
using Android.Views;
using Android.Widget;
using FilledAutofillFieldCollection = keepass2android.services.AutofillBase.model.FilledAutofillFieldCollection;
//TODO compare port
namespace keepass2android.services.AutofillBase
{
/// <summary>
/// This is a class containing helper methods for building Autofill Datasets and Responses.
/// </summary>
public class AutofillHelper
{
/// <summary>
/// Wraps autofill data in a LoginCredential Dataset object which can then be sent back to the
/// client View.
/// </summary>
/// <returns>The dataset.</returns>
/// <param name="context">Context.</param>
/// <param name="autofillFields">Autofill fields.</param>
/// <param name="filledAutofillFieldCollection">Filled autofill field collection.</param>
/// <param name="datasetAuth">If set to <c>true</c> dataset auth.</param>
public static Dataset NewDataset(Context context,
keepass2android.services.AutofillBase.AutofillFieldMetadataCollection autofillFields, FilledAutofillFieldCollection filledAutofillFieldCollection, bool datasetAuth, IAutofillIntentBuilder intentBuilder)
{
var datasetName = filledAutofillFieldCollection.DatasetName;
if (datasetName != null)
{
Dataset.Builder datasetBuilder;
if (datasetAuth)
{
datasetBuilder = new Dataset.Builder
(NewRemoteViews(context.PackageName, datasetName,
Resource.Drawable.ic_launcher));
IntentSender sender = intentBuilder.GetAuthIntentSenderForDataset(context, datasetName);
datasetBuilder.SetAuthentication(sender);
}
else
{
datasetBuilder = new Dataset.Builder
(NewRemoteViews(context.PackageName, datasetName,
Resource.Drawable.ic_launcher));
}
var setValueAtLeastOnce = filledAutofillFieldCollection.ApplyToFields(autofillFields, datasetBuilder);
if (setValueAtLeastOnce)
{
return datasetBuilder.Build();
}
}
return null;
}
public static RemoteViews NewRemoteViews(string packageName, string remoteViewsText,int drawableId)
{
RemoteViews presentation = new RemoteViews(packageName, Resource.Layout.autofill_service_list_item);
presentation.SetTextViewText(Resource.Id.text, remoteViewsText);
presentation.SetImageViewResource(Resource.Id.icon, drawableId);
return presentation;
}
/// <summary>
/// Wraps autofill data in a Response object (essentially a series of Datasets) which can then
/// be sent back to the client View.
/// </summary>
/// <returns>The response.</returns>
/// <param name="context">Context.</param>
/// <param name="datasetAuth">If set to <c>true</c> dataset auth.</param>
/// <param name="autofillFields">Autofill fields.</param>
/// <param name="clientFormDataMap">Client form data map.</param>
/// <param name="intentBuilder"></param>
public static FillResponse NewResponse(Context context, bool datasetAuth, keepass2android.services.AutofillBase.AutofillFieldMetadataCollection autofillFields, Dictionary<string, FilledAutofillFieldCollection> clientFormDataMap, IAutofillIntentBuilder intentBuilder)
{
var responseBuilder = new FillResponse.Builder();
if (clientFormDataMap != null)
{
var datasetNames = clientFormDataMap.Keys;
foreach (var datasetName in datasetNames)
{
var filledAutofillFieldCollection = clientFormDataMap[datasetName];
if (filledAutofillFieldCollection != null)
{
var dataset = NewDataset(context, autofillFields, filledAutofillFieldCollection, datasetAuth, intentBuilder);
if (dataset != null)
{
responseBuilder.AddDataset(dataset);
}
}
}
}
if (autofillFields.SaveType != 0)
{
var autofillIds = autofillFields.GetAutofillIds();
responseBuilder.SetSaveInfo
(new SaveInfo.Builder(autofillFields.SaveType, autofillIds).Build());
return responseBuilder.Build();
}
else
{
Log.Debug(CommonUtil.Tag, "These fields are not meant to be saved by autofill.");
return null;
}
}
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,101 @@
using System;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Service.Autofill;
using Android.Util;
namespace keepass2android.services.AutofillBase
{
public interface IAutofillIntentBuilder
{
IntentSender GetAuthIntentSenderForResponse(Context context);
IntentSender GetAuthIntentSenderForDataset(Context context, string dataset);
}
public abstract class AutofillServiceBase: AutofillService, IAutofillIntentBuilder
{
public AutofillServiceBase()
{
}
public AutofillServiceBase(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
public override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal, FillCallback callback)
{
Log.Debug(CommonUtil.Tag, "onFillRequest");
var structure = request.FillContexts[request.FillContexts.Count - 1].Structure;
//TODO package signature verification?
var clientState = request.ClientState;
Log.Debug(CommonUtil.Tag, "onFillRequest(): data=" + CommonUtil.BundleToString(clientState));
cancellationSignal.CancelEvent += (sender, e) => {
Log.Warn(CommonUtil.Tag, "Cancel autofill not implemented yet.");
};
// Parse AutoFill data in Activity
var parser = new StructureParser(this, structure);
try
{
parser.ParseForFill();
}
catch (Java.Lang.SecurityException e)
{
Log.Warn(CommonUtil.Tag, "Security exception handling request");
callback.OnFailure(e.Message);
return;
}
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)
{
// If the entire Autofill Response is authenticated, AuthActivity is used
// to generate Response.
var sender = GetAuthIntentSenderForResponse(this);
var presentation = keepass2android.services.AutofillBase.AutofillHelper
.NewRemoteViews(PackageName, GetString(Resource.String.autofill_sign_in_prompt),
Resource.Drawable.ic_launcher);
responseBuilder
.SetAuthentication(autofillIds, sender, presentation);
callback.OnSuccess(responseBuilder.Build());
}
else
{
var datasetAuth = true;
var response = keepass2android.services.AutofillBase.AutofillHelper.NewResponse(this, datasetAuth, autofillFields, null, this);
callback.OnSuccess(response);
}
}
public override void OnSaveRequest(SaveRequest request, SaveCallback callback)
{
//TODO implement
callback.OnFailure("not implemented");
}
public override void OnConnected()
{
Log.Debug(CommonUtil.Tag, "onConnected");
}
public override void OnDisconnected()
{
Log.Debug(CommonUtil.Tag, "onDisconnected");
}
public abstract IntentSender GetAuthIntentSenderForResponse(Context context);
public abstract IntentSender GetAuthIntentSenderForDataset(Context context, string dataset);
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Text;
using Android.OS;
using Java.Util;
namespace keepass2android.services.AutofillBase
{
public class CommonUtil
{
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)
{
var keySet = data.KeySet();
builder.Append("[Bundle with ").Append(keySet.Count).Append(" keys:");
foreach (var key in keySet)
{
builder.Append(' ').Append(key).Append('=');
Object value = data.Get(key);
if (value is Bundle)
{
BundleToString(builder, (Bundle)value);
}
else
{
builder.Append((value is Object[])
? Arrays.ToString((bool[])value) : value);
}
}
builder.Append(']');
}
public static string BundleToString(Bundle data)
{
if (data == null)
{
return "N/A";
}
StringBuilder builder = new StringBuilder();
BundleToString(builder, data);
return builder.ToString();
}
}
}

View File

@@ -0,0 +1,30 @@
using Android.Content;
namespace keepass2android.services.AutofillBase
{
internal class Kp2aDigitalAssetLinksDataSource
{
private static Kp2aDigitalAssetLinksDataSource instance;
private Kp2aDigitalAssetLinksDataSource() { }
public static Kp2aDigitalAssetLinksDataSource Instance
{
get
{
if (instance == null)
{
instance = new Kp2aDigitalAssetLinksDataSource();
}
return instance;
}
}
public bool IsValid(Context context, string webDomain, string packageName)
{
//TODO implement
return true;
}
}
}

View File

@@ -0,0 +1,115 @@
using System;
using Android.App.Assist;
using Android.Content;
using Android.Util;
using FilledAutofillFieldCollection = keepass2android.services.AutofillBase.model.FilledAutofillFieldCollection;
namespace keepass2android.services.AutofillBase
{
/// <summary>
/// Parser for an AssistStructure object. This is invoked when the Autofill Service receives an
/// AssistStructure from the client Activity, representing its View hierarchy. In this sample, it
/// parses the hierarchy and collects autofill metadata from {@link ViewNode}s along the way.
/// </summary>
public sealed class StructureParser
{
public Context mContext { get; }
public keepass2android.services.AutofillBase.AutofillFieldMetadataCollection AutofillFields { get; set; }
AssistStructure Structure;
public FilledAutofillFieldCollection ClientFormData { get; set; }
public StructureParser(Context context, AssistStructure structure)
{
mContext = context;
Structure = structure;
AutofillFields = new keepass2android.services.AutofillBase.AutofillFieldMetadataCollection();
}
public void ParseForFill()
{
Parse(true);
}
public void ParseForSave()
{
Parse(false);
}
/// <summary>
/// Traverse AssistStructure and add ViewNode metadata to a flat list.
/// </summary>
/// <returns>The parse.</returns>
/// <param name="forFill">If set to <c>true</c> for fill.</param>
void Parse(bool forFill)
{
Log.Debug(keepass2android.services.AutofillBase.CommonUtil.Tag, "Parsing structure for " + Structure.ActivityComponent);
var nodes = Structure.WindowNodeCount;
ClientFormData = new FilledAutofillFieldCollection();
String webDomain = null;
for (int i = 0; i < nodes; i++)
{
var node = Structure.GetWindowNodeAt(i);
var view = node.RootViewNode;
ParseLocked(forFill, view, ref webDomain);
}
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}");
}
else
{
Log.Debug(keepass2android.services.AutofillBase.CommonUtil.Tag, "no web domain");
}
}
void ParseLocked(bool forFill, AssistStructure.ViewNode viewNode, ref string validWebdomain)
{
String webDomain = viewNode.WebDomain;
if (webDomain != null)
{
Log.Debug(keepass2android.services.AutofillBase.CommonUtil.Tag, $"child web domain: {webDomain}");
if (!string.IsNullOrEmpty(validWebdomain))
{
if (webDomain == validWebdomain)
{
throw new Java.Lang.SecurityException($"Found multiple web domains: valid= {validWebdomain}, child={webDomain}");
}
}
else
{
validWebdomain = webDomain;
}
}
if (viewNode.GetAutofillHints() != null && viewNode.GetAutofillHints().Length > 0)
{
if (forFill)
{
AutofillFields.Add(new keepass2android.services.AutofillBase.AutofillFieldMetadata(viewNode));
}
else
{
//TODO implement
throw new NotImplementedException("TODO: Port and use AutoFill hints");
//ClientFormData.Add(new FilledAutofillField(viewNode));
}
}
var childrenSize = viewNode.ChildCount;
if (childrenSize > 0)
{
for (int i = 0; i < childrenSize; i++)
{
ParseLocked(forFill, viewNode.GetChildAt(i), ref validWebdomain);
}
}
}
}
}

View File

@@ -0,0 +1,84 @@
using Android.App.Assist;
using Android.Views.Autofill;
namespace keepass2android.services.AutofillBase.model
{
/// <summary>
/// JSON serializable data class containing the same data as an {@link AutofillValue}.
/// </summary>
public class FilledAutofillField
{
public string TextValue { get; set; }
public long? DateValue { get; set; }
public bool? ToggleValue { get; set; }
/// <summary>
/// Does not need to be serialized into persistent storage, so it's not exposed.
/// </summary>
/// <value>The autofill hints.</value>
public string[] AutofillHints { get; set; }
public FilledAutofillField()
{}
public FilledAutofillField(AssistStructure.ViewNode viewNode)
{
AutofillHints = AutofillHelper.FilterForSupportedHints(viewNode.GetAutofillHints());
//TODO port updated FilledAutofillField?
AutofillValue autofillValue = viewNode.AutofillValue;
if (autofillValue != null)
{
if (autofillValue.IsList)
{
string[] autofillOptions = viewNode.GetAutofillOptions();
int index = autofillValue.ListValue;
if (autofillOptions != null && autofillOptions.Length > 0)
{
TextValue = autofillOptions[index];
}
}
else if (autofillValue.IsDate)
{
DateValue = autofillValue.DateValue;
}
else if (autofillValue.IsText)
{
// Using toString of AutofillValue.getTextValue in order to save it to
// SharedPreferences.
TextValue = autofillValue.TextValue;
}
}
}
public bool IsNull()
{
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;
FilledAutofillField that = (FilledAutofillField)obj;
if (TextValue != null ? !TextValue.Equals(that.TextValue) : that.TextValue != null)
return false;
if (DateValue != null ? !DateValue.Equals(that.DateValue) : that.DateValue != null)
return false;
return ToggleValue != null ? ToggleValue.Equals(that.ToggleValue) : that.ToggleValue == null;
}
public override int GetHashCode()
{
unchecked
{
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;
}
}
}
}

View File

@@ -0,0 +1,137 @@
using System.Collections.Generic;
using Android.Service.Autofill;
using Android.Util;
using Android.Views;
using Android.Views.Autofill;
namespace keepass2android.services.AutofillBase.model
{
/// <summary>
/// FilledAutofillFieldCollection is the model that holds all of the data on a client app's page,
/// plus the dataset name associated with it.
/// </summary>
public class FilledAutofillFieldCollection
{
public Dictionary<string, keepass2android.services.AutofillBase.model.FilledAutofillField> HintMap { get; set; }
public string DatasetName { get; set; }
public FilledAutofillFieldCollection(Dictionary<string, keepass2android.services.AutofillBase.model.FilledAutofillField> hintMap, string datasetName = "")
{
HintMap = hintMap;
DatasetName = datasetName;
}
public FilledAutofillFieldCollection() : this(new Dictionary<string, keepass2android.services.AutofillBase.model.FilledAutofillField>())
{}
/// <summary>
/// Adds a filledAutofillField to the collection, indexed by all of its hints.
/// </summary>
/// <returns>The add.</returns>
/// <param name="filledAutofillField">Filled autofill field.</param>
public void Add(keepass2android.services.AutofillBase.model.FilledAutofillField filledAutofillField)
{
string[] autofillHints = filledAutofillField.AutofillHints;
//TODO apply W3C transformation
foreach (string hint in autofillHints)
{
HintMap.Add(hint, filledAutofillField);
}
}
/// <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;
List<string> allHints = autofillFieldMetadataCollection.AllAutofillHints;
for (int hintIndex = 0; hintIndex < allHints.Count; hintIndex++)
{
string hint = allHints[hintIndex];
List<AutofillFieldMetadata> fillableAutofillFields = autofillFieldMetadataCollection.GetFieldsForHint(hint);
if (fillableAutofillFields == null)
{
continue;
}
for (int autofillFieldIndex = 0; autofillFieldIndex < fillableAutofillFields.Count; autofillFieldIndex++)
{
keepass2android.services.AutofillBase.model.FilledAutofillField filledAutofillField = HintMap[hint];
if (filledAutofillField == null)
{
continue;
}
AutofillFieldMetadata autofillFieldMetadata = fillableAutofillFields[autofillFieldIndex];
var autofillId = autofillFieldMetadata.AutofillId;
var autofillType = autofillFieldMetadata.AutofillType;
switch (autofillType)
{
case AutofillType.List:
var listValue = autofillFieldMetadata.GetAutofillOptionIndex(filledAutofillField.TextValue);
if (listValue != -1)
{
datasetBuilder.SetValue(autofillId, AutofillValue.ForList(listValue));
setValueAtLeastOnce = true;
}
break;
case AutofillType.Date:
var dateValue = filledAutofillField.DateValue;
datasetBuilder.SetValue(autofillId, AutofillValue.ForDate((long)dateValue));
setValueAtLeastOnce = true;
break;
case AutofillType.Text:
var textValue = filledAutofillField.TextValue;
if (textValue != null)
{
datasetBuilder.SetValue(autofillId, AutofillValue.ForText(textValue));
setValueAtLeastOnce = true;
}
break;
case AutofillType.Toggle:
var toggleValue = filledAutofillField.ToggleValue;
if (toggleValue != null)
{
datasetBuilder.SetValue(autofillId, AutofillValue.ForToggle(toggleValue.Value));
setValueAtLeastOnce = true;
}
break;
default:
Log.Warn(CommonUtil.Tag, "Invalid autofill type - " + autofillType);
break;
}
}
}
return setValueAtLeastOnce;
}
/// <summary>
/// Takes in a list of autofill hints (`autofillHints`), usually associated with a View or set of
/// Views. Returns whether any of the filled fields on the page have at least 1 of these
/// `autofillHint`s.
/// </summary>
/// <returns><c>true</c>, if with hints was helpsed, <c>false</c> otherwise.</returns>
/// <param name="autofillHints">Autofill hints.</param>
public bool HelpsWithHints(List<string> autofillHints)
{
for (int i = 0; i < autofillHints.Count; i++)
{
var autofillHint = autofillHints[i];
if (HintMap.ContainsKey(autofillHint) && !HintMap[autofillHint].IsNull())
{
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using Android;
using Android.App;
using Android.Content;
using Android.Runtime;
using AutofillServiceBase = keepass2android.services.AutofillBase.AutofillServiceBase;
namespace keepass2android.services
{
[Service(Label = "Keepass2Android Autofill Service", Permission=Manifest.Permission.BindAutofillService)]
[IntentFilter(new [] {"android.service.autofill.AutofillService"})]
[MetaData("android.autofill", Resource = "@xml/autofillservice")]
[Register("keepass2android.services.Kp2aAutofillService")]
public class Kp2aAutofillService: AutofillServiceBase
{
public Kp2aAutofillService()
{
}
public Kp2aAutofillService(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
public override IntentSender GetAuthIntentSenderForResponse(Context context)
{
Intent intent = new Intent(context, typeof(KeePass));
return PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent).IntentSender;
}
public override IntentSender GetAuthIntentSenderForDataset(Context context, string dataset)
{
//TODO implement
return GetAuthIntentSenderForResponse(context);
}
}
}