Timeout the installation of extensions after 10s

This commit is contained in:
inorichi 2018-02-06 22:11:36 +01:00
parent 636c027298
commit eb8479ac9a
2 changed files with 26 additions and 8 deletions

View File

@ -65,7 +65,7 @@ internal class ExtensionInstaller(private val context: Context) {
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
val id = downloadManager.enqueue(request) val id = downloadManager.enqueue(request)
activeDownloads.put(pkgName, id) activeDownloads[pkgName] = id
downloadsRelay.filter { it.first == id } downloadsRelay.filter { it.first == id }
.map { it.second } .map { it.second }
@ -73,6 +73,8 @@ internal class ExtensionInstaller(private val context: Context) {
.mergeWith(pollStatus(id)) .mergeWith(pollStatus(id))
// Force an error if the download takes more than 3 minutes // Force an error if the download takes more than 3 minutes
.mergeWith(Observable.timer(3, TimeUnit.MINUTES).map { InstallStep.Error }) .mergeWith(Observable.timer(3, TimeUnit.MINUTES).map { InstallStep.Error })
// Force an error if the install process takes more than 10 seconds
.flatMap { timeoutWhenInstalling(it) }
// Stop when the application is installed or errors // Stop when the application is installed or errors
.takeUntil { it.isCompleted() } .takeUntil { it.isCompleted() }
// Always notify on main thread // Always notify on main thread
@ -112,6 +114,22 @@ internal class ExtensionInstaller(private val context: Context) {
} }
} }
/**
* Returns an observable that timeouts the installation after a specified time when the apk has
* been downloaded.
*
* @param currentStep The current step of the installation process.
*/
private fun timeoutWhenInstalling(currentStep: InstallStep): Observable<InstallStep> {
return if (currentStep == InstallStep.Installing) {
Observable.timer(10, TimeUnit.SECONDS)
.map { InstallStep.Error }
.startWith(currentStep)
} else {
Observable.just(currentStep)
}
}
/** /**
* Starts an intent to install the extension at the given uri. * Starts an intent to install the extension at the given uri.
* *
@ -221,12 +239,12 @@ internal class ExtensionInstaller(private val context: Context) {
// it fails. // it fails.
try { try {
installApk(uri) installApk(uri)
} catch (e: ActivityNotFoundException) { } catch (_: ActivityNotFoundException) {
val query = DownloadManager.Query() val query = DownloadManager.Query().setFilterById(id)
query.setFilterById(id) downloadManager.query(query).use { cursor ->
downloadManager.query(query).use { if (cursor.moveToFirst()) {
if (it.moveToFirst()) { @Suppress("DEPRECATION")
val uriCompat = File(it.getString(it.getColumnIndex( val uriCompat = File(cursor.getString(cursor.getColumnIndex(
DownloadManager.COLUMN_LOCAL_FILENAME))).getUriCompat(context) DownloadManager.COLUMN_LOCAL_FILENAME))).getUriCompat(context)
installApk(uriCompat) installApk(uriCompat)
} }

View File

@ -105,7 +105,7 @@ open class ExtensionPresenter(
} }
private fun Observable<InstallStep>.subscribeToInstallUpdate(extension: Extension) { private fun Observable<InstallStep>.subscribeToInstallUpdate(extension: Extension) {
this.doOnNext { currentDownloads.put(extension.pkgName, it) } this.doOnNext { currentDownloads[extension.pkgName] = it }
.doOnUnsubscribe { currentDownloads.remove(extension.pkgName) } .doOnUnsubscribe { currentDownloads.remove(extension.pkgName) }
.map { state -> updateInstallStep(extension, state) } .map { state -> updateInstallStep(extension, state) }
.subscribeWithView({ view, item -> .subscribeWithView({ view, item ->