Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move authority and ContentProvider creation to LocalDataStore #1272

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,6 @@ class SyncerTest {
override val dataStore: LocalTestStore =
theDataStore

override val authority: String
get() = throw NotImplementedError()

override val serviceType: String
get() = throw NotImplementedError()

Expand All @@ -189,6 +186,13 @@ class SyncerTest {

class LocalTestStore : LocalDataStore<LocalTestCollection> {

override val authority: String
get() = throw NotImplementedError()

override fun acquireContentProvider(): ContentProviderClient? {
throw NotImplementedError()
}

override fun create(
provider: ContentProviderClient,
fromCollection: Collection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class LocalAddressBookStore @Inject constructor(
private val settings: SettingsManager
): LocalDataStore<LocalAddressBook> {

override val authority: String
get() = ContactsContract.AUTHORITY

/** whether a (usually managed) setting wants all address-books to be read-only **/
val forceAllReadOnly: Boolean
get() = settings.getBoolean(Settings.FORCE_READ_ONLY_ADDRESSBOOKS)
Expand Down Expand Up @@ -67,6 +70,8 @@ class LocalAddressBookStore @Inject constructor(
return sb.toString()
}

override fun acquireContentProvider() =
context.contentResolver.acquireContentProviderClient(authority)

override fun create(provider: ContentProviderClient, fromCollection: Collection): LocalAddressBook? {
val service = serviceRepository.get(fromCollection.serviceId) ?: throw IllegalArgumentException("Couldn't fetch DB service from collection")
Expand Down Expand Up @@ -106,7 +111,6 @@ class LocalAddressBookStore @Inject constructor(
return addressBookAccount
}


override fun getAll(account: Account, provider: ContentProviderClient): List<LocalAddressBook> {
val accountManager = AccountManager.get(context)
return accountManager.getAccountsByType(context.getString(R.string.account_type_address_book))
Expand All @@ -119,7 +123,6 @@ class LocalAddressBookStore @Inject constructor(
}
}


override fun update(provider: ContentProviderClient, localCollection: LocalAddressBook, fromCollection: Collection) {
var currentAccount = localCollection.addressBookAccount
logger.log(Level.INFO, "Updating local address book $currentAccount from collection $fromCollection")
Expand Down Expand Up @@ -171,7 +174,6 @@ class LocalAddressBookStore @Inject constructor(
}
}


override fun delete(localCollection: LocalAddressBook) {
val accountManager = AccountManager.get(context)
accountManager.removeAccountExplicitly(localCollection.addressBookAccount)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ class LocalCalendarStore @Inject constructor(
private val serviceRepository: DavServiceRepository
): LocalDataStore<LocalCalendar> {

override val authority: String
get() = CalendarContract.AUTHORITY

override fun acquireContentProvider() =
context.contentResolver.acquireContentProviderClient(authority)

override fun create(provider: ContentProviderClient, fromCollection: Collection): LocalCalendar? {
val service = serviceRepository.get(fromCollection.serviceId) ?: throw IllegalArgumentException("Couldn't fetch DB service from collection")
val account = Account(service.accountName, context.getString(R.string.account_type))
Expand Down Expand Up @@ -67,11 +73,9 @@ class LocalCalendarStore @Inject constructor(
return AndroidCalendar.findByID(account, provider, LocalCalendar.Factory, ContentUris.parseId(uri))
}


override fun getAll(account: Account, provider: ContentProviderClient) =
AndroidCalendar.find(account, provider, LocalCalendar.Factory, "${Calendars.SYNC_EVENTS}!=0", null)


override fun update(provider: ContentProviderClient, localCollection: LocalCalendar, fromCollection: Collection) {
val accountSettings = accountSettingsFactory.create(localCollection.account)
val values = valuesFromCollectionInfo(fromCollection, withColor = accountSettings.getManageCalendarColors())
Expand Down Expand Up @@ -106,6 +110,11 @@ class LocalCalendarStore @Inject constructor(
return values
}

override fun delete(localCollection: LocalCalendar) {
logger.log(Level.INFO, "Deleting local calendar", localCollection)
localCollection.delete()
}

override fun updateAccount(oldAccount: Account, newAccount: Account) {
val values = contentValuesOf(Calendars.ACCOUNT_NAME to newAccount.name)
val uri = Calendars.CONTENT_URI.asSyncAdapter(oldAccount)
Expand All @@ -114,10 +123,4 @@ class LocalCalendarStore @Inject constructor(
}
}


override fun delete(localCollection: LocalCalendar) {
logger.log(Level.INFO, "Deleting local calendar", localCollection)
localCollection.delete()
}

}
17 changes: 17 additions & 0 deletions app/src/main/kotlin/at/bitfire/davdroid/resource/LocalDataStore.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ import at.bitfire.davdroid.db.Collection
*/
interface LocalDataStore<T: LocalCollection<*>> {

/**
* Content provider authority for the data store.
*/
val authority: String

/**
* Acquires a content provider client for the data store. The result of this call
* should be passed to all other methods of this class.
*
* **The caller is responsible for closing the content provider client!**
*
* @return the content provider client, or `null` if the content provider could not be acquired
*
* @throws SecurityException on missing permissions
*/
fun acquireContentProvider(): ContentProviderClient?

/**
* Creates a new local collection from the given (remote) collection info.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ class LocalJtxCollectionStore @Inject constructor(

private val serviceDao = db.serviceDao()

override val authority: String
get() = JtxContract.AUTHORITY

override fun acquireContentProvider() =
context.contentResolver.acquireContentProviderClient(JtxContract.AUTHORITY)

override fun create(provider: ContentProviderClient, fromCollection: Collection): LocalJtxCollection? {
val service = serviceDao.get(fromCollection.serviceId) ?: throw IllegalArgumentException("Couldn't fetch DB service from collection")
val account = Account(service.accountName, context.getString(R.string.account_type))
Expand Down Expand Up @@ -82,22 +88,15 @@ class LocalJtxCollectionStore @Inject constructor(
}
}


override fun getAll(account: Account, provider: ContentProviderClient): List<LocalJtxCollection> =
JtxCollection.find(account, provider, context, LocalJtxCollection.Factory, null, null)


override fun update(provider: ContentProviderClient, localCollection: LocalJtxCollection, fromCollection: Collection) {
val accountSettings = accountSettingsFactory.create(localCollection.account)
val values = valuesFromCollection(fromCollection, account = localCollection.account, withColor = accountSettings.getManageCalendarColors())
localCollection.update(values)
}


override fun delete(localCollection: LocalJtxCollection) {
localCollection.delete()
}

override fun updateAccount(oldAccount: Account, newAccount: Account) {
TaskProvider.acquire(context, TaskProvider.ProviderName.JtxBoard)?.use { provider ->
val values = contentValuesOf(JtxContract.JtxCollection.ACCOUNT_NAME to newAccount.name)
Expand All @@ -106,4 +105,8 @@ class LocalJtxCollectionStore @Inject constructor(
}
}

override fun delete(localCollection: LocalJtxCollection) {
localCollection.delete()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ class LocalTaskListStore @AssistedInject constructor(

private val serviceDao = db.serviceDao()

override val authority: String
get() = providerName.authority

override fun acquireContentProvider() =
context.contentResolver.acquireContentProviderClient(authority)

override fun create(provider: ContentProviderClient, fromCollection: Collection): LocalTaskList? {
val service = serviceDao.get(fromCollection.serviceId) ?: throw IllegalArgumentException("Couldn't fetch DB service from collection")
Expand Down Expand Up @@ -89,22 +94,15 @@ class LocalTaskListStore @AssistedInject constructor(
return values
}


override fun getAll(account: Account, provider: ContentProviderClient) =
DmfsTaskList.find(account, LocalTaskList.Factory, provider, providerName, null, null)


override fun update(provider: ContentProviderClient, localCollection: LocalTaskList, fromCollection: Collection) {
logger.log(Level.FINE, "Updating local task list ${fromCollection.url}", fromCollection)
val accountSettings = accountSettingsFactory.create(localCollection.account)
localCollection.update(valuesFromCollectionInfo(fromCollection, withColor = accountSettings.getManageCalendarColors()))
}


override fun delete(localCollection: LocalTaskList) {
localCollection.delete()
}

override fun updateAccount(oldAccount: Account, newAccount: Account) {
TaskProvider.acquire(context, providerName)?.use { provider ->
val values = contentValuesOf(Tasks.ACCOUNT_NAME to newAccount.name)
Expand All @@ -113,4 +111,8 @@ class LocalTaskListStore @AssistedInject constructor(
}
}

override fun delete(localCollection: LocalTaskList) {
localCollection.delete()
}

}
13 changes: 10 additions & 3 deletions app/src/main/kotlin/at/bitfire/davdroid/sync/AddressBookSyncer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ class AddressBookSyncer @AssistedInject constructor(

override val serviceType: String
get() = Service.TYPE_CARDDAV
override val authority: String
get() = ContactsContract.AUTHORITY // Address books use the contacts authority for sync


override fun getDbSyncCollections(serviceId: Long): List<Collection> =
Expand Down Expand Up @@ -100,7 +98,16 @@ class AddressBookSyncer @AssistedInject constructor(
}
accountManager.setAndVerifyUserData(addressBook.addressBookAccount, PREVIOUS_GROUP_METHOD, groupMethod)

val syncManager = contactsSyncManagerFactory.contactsSyncManager(account, httpClient.value, extras, authority, syncResult, provider, addressBook, collection)
val syncManager = contactsSyncManagerFactory.contactsSyncManager(
account,
httpClient.value,
extras,
dataStore.authority,
syncResult,
provider,
addressBook,
collection
)
syncManager.performSync()

} catch(e: Exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package at.bitfire.davdroid.sync

import android.accounts.Account
import android.content.ContentProviderClient
import android.provider.CalendarContract
import at.bitfire.davdroid.db.Collection
import at.bitfire.davdroid.db.Service
import at.bitfire.davdroid.resource.LocalCalendar
Expand Down Expand Up @@ -38,8 +37,6 @@ class CalendarSyncer @AssistedInject constructor(

override val serviceType: String
get() = Service.TYPE_CALDAV
override val authority: String
get() = CalendarContract.AUTHORITY


override fun prepare(provider: ContentProviderClient): Boolean {
Expand All @@ -62,7 +59,7 @@ class CalendarSyncer @AssistedInject constructor(
account,
extras,
httpClient.value,
authority,
dataStore.authority,
syncResult,
localCollection,
remoteCollection
Expand Down
4 changes: 1 addition & 3 deletions app/src/main/kotlin/at/bitfire/davdroid/sync/JtxSyncer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ class JtxSyncer @AssistedInject constructor(

override val serviceType: String
get() = Service.TYPE_CALDAV
override val authority: String
get() = TaskProvider.ProviderName.JtxBoard.authority


override fun prepare(provider: ContentProviderClient): Boolean {
Expand Down Expand Up @@ -74,7 +72,7 @@ class JtxSyncer @AssistedInject constructor(
account,
extras,
httpClient.value,
authority,
dataStore.authority,
syncResult,
localCollection,
remoteCollection
Expand Down
18 changes: 9 additions & 9 deletions app/src/main/kotlin/at/bitfire/davdroid/sync/Syncer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ abstract class Syncer<StoreType: LocalDataStore<CollectionType>, CollectionType:
@Inject
lateinit var serviceRepository: DavServiceRepository

abstract val authority: String
@ServiceType
abstract val serviceType: String

Expand Down Expand Up @@ -214,7 +213,8 @@ abstract class Syncer<StoreType: LocalDataStore<CollectionType>, CollectionType:
/**
* For collection specific sync preparations.
*
* @param provider Content provider for syncer specific authority
* @param provider Content provider for data store
*
* @return *true* to run the sync; *false* to abort
*/
open fun prepare(provider: ContentProviderClient): Boolean = true
Expand All @@ -223,6 +223,7 @@ abstract class Syncer<StoreType: LocalDataStore<CollectionType>, CollectionType:
* Get the local database collections which are sync-enabled (should by synchronized).
*
* @param serviceId The CalDAV or CardDAV service (account) to be synchronized
*
* @return Database collections to be synchronized
*/
abstract fun getDbSyncCollections(serviceId: Long): List<Collection>
Expand All @@ -244,13 +245,12 @@ abstract class Syncer<StoreType: LocalDataStore<CollectionType>, CollectionType:
* - handle occurring sync errors
*/
operator fun invoke() {
logger.log(Level.INFO, "$authority sync of $account initiated", extras.joinToString(", "))
logger.log(Level.INFO, "${dataStore.authority} sync of $account initiated", extras.joinToString(", "))

// Acquire ContentProviderClient
try {
context.contentResolver.acquireContentProviderClient(authority)
dataStore.acquireContentProvider()
} catch (e: SecurityException) {
logger.log(Level.WARNING, "Missing permissions for authority $authority", e)
logger.log(Level.WARNING, "Missing permissions for content provider authority ${dataStore.authority}", e)
notificationRegistry.notifyPermissions()
null
}.use { provider ->
Expand All @@ -259,7 +259,7 @@ abstract class Syncer<StoreType: LocalDataStore<CollectionType>, CollectionType:
- we're not allowed to access the content provider, or
- the content provider is not available at all, for instance because the tasks app has been uninstalled
or the respective system app (like "calendar storage") is disabled */
logger.warning("Couldn't connect to content provider of authority $authority")
logger.warning("Couldn't connect to content provider of authority ${dataStore.authority}")
syncResult.contentProviderError = true

return // Don't continue without provider
Expand All @@ -281,15 +281,15 @@ abstract class Syncer<StoreType: LocalDataStore<CollectionType>, CollectionType:
logger.log(Level.WARNING, "Account was removed during synchronization", e)

} catch (e: Exception) {
logger.log(Level.SEVERE, "Couldn't sync $authority", e)
logger.log(Level.SEVERE, "Couldn't sync ${dataStore.authority}", e)
syncResult.numUnclassifiedErrors++ // Hard sync error

} finally {
if (httpClient.isInitialized())
httpClient.value.close()
logger.log(
Level.INFO,
"$authority sync of $account finished",
"${dataStore.authority} sync of $account finished",
extras.joinToString(", "))
}
}
Expand Down
Loading
Loading