blob: 8aeac0df26f753036b4b637f2608b453ae734a4f [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.autofillframework.multidatasetservice.datasource
import android.content.Context
import android.content.SharedPreferences
import android.util.ArraySet
import com.example.android.autofillframework.multidatasetservice.model.ClientFormData
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
/**
* Singleton autofill data repository that stores autofill fields to SharedPreferences.
* Disclaimer: you should not store sensitive fields like user data unencrypted. This is done
* here only for simplicity and learning purposes.
*/
object SharedPrefsAutofillRepository : AutofillRepository {
private val SHARED_PREF_KEY = "com.example.android.autofillframework.service"
private val CLIENT_FORM_DATA_KEY = "loginCredentialDatasets"
private val DATASET_NUMBER_KEY = "datasetNumber"
private fun getPrefs(context: Context): SharedPreferences {
return context.applicationContext.getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE)
}
override fun getClientFormData(context: Context, focusedAutofillHints: List<String>,
allAutofillHints: List<String>): HashMap<String, ClientFormData>? {
var hasDataForFocusedAutofillHints = false
val clientFormDataMap = HashMap<String, ClientFormData>()
val clientFormDataStringSet = getAllAutofillDataStringSet(context)
for (clientFormDataString in clientFormDataStringSet) {
val type = object : TypeToken<ClientFormData>() {}.type
Gson().fromJson<ClientFormData>(clientFormDataString, type)?.let { clientFormData ->
if (clientFormData.helpsWithHints(focusedAutofillHints)) {
// Saved data has data relevant to at least 1 of the hints associated with the
// View in focus.
hasDataForFocusedAutofillHints = true
clientFormData.datasetName?.let { datasetName ->
if (clientFormData.helpsWithHints(allAutofillHints)) {
// Saved data has data relevant to at least 1 of these hints associated with any
// of the Views in the hierarchy.
clientFormDataMap.put(datasetName, clientFormData)
}
}
}
}
}
if (hasDataForFocusedAutofillHints) {
return clientFormDataMap
} else {
return null
}
}
override fun saveClientFormData(context: Context, clientFormData: ClientFormData) {
val datasetName = "dataset-" + getDatasetNumber(context)
clientFormData.datasetName = datasetName
val allAutofillData = getAllAutofillDataStringSet(context)
allAutofillData.add(Gson().toJson(clientFormData).toString())
saveAllAutofillDataStringSet(context, allAutofillData)
incrementDatasetNumber(context)
}
override fun clear(context: Context) {
getPrefs(context).edit().remove(CLIENT_FORM_DATA_KEY).remove(DATASET_NUMBER_KEY).apply()
}
private fun getAllAutofillDataStringSet(context: Context): MutableSet<String> {
return getPrefs(context).getStringSet(CLIENT_FORM_DATA_KEY, ArraySet<String>())
}
private fun saveAllAutofillDataStringSet(context: Context, allAutofillDataStringSet: Set<String>) {
getPrefs(context).edit().putStringSet(CLIENT_FORM_DATA_KEY, allAutofillDataStringSet).apply()
}
/**
* For simplicity, datasets will be named in the form "dataset-X" where X means
* this was the Xth dataset saved.
*/
private fun getDatasetNumber(context: Context): Int {
return getPrefs(context).getInt(DATASET_NUMBER_KEY, 0)
}
/**
* Every time a dataset is saved, this should be called to increment the dataset number.
* (only important for this service's dataset naming scheme).
*/
private fun incrementDatasetNumber(context: Context) {
getPrefs(context).edit().putInt(DATASET_NUMBER_KEY, getDatasetNumber(context) + 1).apply()
}
}