Skip to content
This repository was archived by the owner on Nov 1, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -207,7 +207,7 @@ sealed class ContentAction : BrowserAction() {
/**
* Removes the [DownloadState] of the [ContentState] with the given [sessionId].
*/
data class ConsumeDownloadAction(val sessionId: String, val downloadId: Long) : ContentAction()
data class ConsumeDownloadAction(val sessionId: String, val downloadId: String) : ContentAction()

/**
* Updates the [HitResult] of the [ContentState] with the given [sessionId].
Expand Down Expand Up @@ -700,7 +700,7 @@ sealed class DownloadAction : BrowserAction() {
/**
* Updates the [BrowserState] to remove the download with the provided [downloadId].
*/
data class RemoveDownloadAction(val downloadId: Long) : DownloadAction()
data class RemoveDownloadAction(val downloadId: String) : DownloadAction()

/**
* Updates the [BrowserState] to remove all downloads.
Expand All @@ -711,6 +711,16 @@ sealed class DownloadAction : BrowserAction() {
* Updates the provided [download] on the [BrowserState].
*/
data class UpdateDownloadAction(val download: DownloadState) : DownloadAction()

/**
* Restores the [BrowserState.downloads] state from the storage.
*/
object RestoreDownloadsStateAction : DownloadAction()

/**
* Restores the given [download] from the storage.
*/
data class RestoreDownloadStateAction(val download: DownloadState) : DownloadAction()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ internal object DownloadStateReducer {
is DownloadAction.RemoveAllDownloadsAction -> {
state.copy(downloads = emptyMap())
}
is DownloadAction.RestoreDownloadsStateAction -> state
is DownloadAction.RestoreDownloadStateAction -> updateDownloads(state, action.download)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ data class BrowserState(
val containers: Map<String, ContainerState> = emptyMap(),
val extensions: Map<String, WebExtensionState> = emptyMap(),
val media: MediaState = MediaState(),
val downloads: Map<Long, DownloadState> = emptyMap(),
val downloads: Map<String, DownloadState> = emptyMap(),
val search: SearchState = SearchState()
) : State
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package mozilla.components.browser.state.state.content
import android.os.Environment
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
import kotlin.random.Random
import java.util.UUID

/**
* Value type that represents a download request.
Expand All @@ -24,7 +24,7 @@ import kotlin.random.Random
* @property referrerUrl The site that linked to this download.
* @property skipConfirmation Whether or not the confirmation dialog should be shown before the download begins.
* @property id The unique identifier of this download.
* @property sessionId Identifier of the session that spawned the download.
* @property createdTime A timestamp when the download was created.
* @
*/
@Suppress("Deprecation")
Expand All @@ -40,40 +40,42 @@ data class DownloadState(
val destinationDirectory: String = Environment.DIRECTORY_DOWNLOADS,
val referrerUrl: String? = null,
val skipConfirmation: Boolean = false,
val id: Long = Random.nextLong(),
val sessionId: String? = null
val id: String = UUID.randomUUID().toString(),
val sessionId: String? = null,
val createdTime: Long = System.currentTimeMillis()
) : Parcelable {
val filePath: String get() =
Environment.getExternalStoragePublicDirectory(destinationDirectory).path + "/" + fileName

/**
* Status that represents every state that a download can be in.
*/
enum class Status {
@Suppress("MagicNumber")
enum class Status(val id: Int) {
/**
* Indicates that the download is in the first state after creation but not yet [DOWNLOADING].
*/
INITIATED,
INITIATED(1),
/**
* Indicates that an [INITIATED] download is now actively being downloaded.
*/
DOWNLOADING,
DOWNLOADING(2),
/**
* Indicates that the download that has been [DOWNLOADING] has been paused.
*/
PAUSED,
PAUSED(3),
/**
* Indicates that the download that has been [DOWNLOADING] has been cancelled.
*/
CANCELLED,
CANCELLED(4),
/**
* Indicates that the download that has been [DOWNLOADING] has moved to failed because
* something unexpected has happened.
*/
FAILED,
FAILED(5),
/**
* Indicates that the [DOWNLOADING] download has been completed.
*/
COMPLETED
COMPLETED(6)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ class ContentActionTest {
@Test
fun `ConsumeDownloadAction removes download`() {
val download = DownloadState(
id = 1337L,
id = "1337",
url = "https://www.mozilla.org", sessionId = tab.id
)

Expand All @@ -360,7 +360,7 @@ class ContentActionTest {
assertEquals(download, tab.content.download)

store.dispatch(
ContentAction.ConsumeDownloadAction(tab.id, downloadId = 1337)
ContentAction.ConsumeDownloadAction(tab.id, downloadId = "1337")
).joinBlocking()

assertNull(tab.content.download)
Expand All @@ -369,7 +369,7 @@ class ContentActionTest {
@Test
fun `ConsumeDownloadAction does not remove download with different id`() {
val download = DownloadState(
id = 1337L,
id = "1337",
url = "https://www.mozilla.org", sessionId = tab.id
)

Expand All @@ -380,7 +380,7 @@ class ContentActionTest {
assertEquals(download, tab.content.download)

store.dispatch(
ContentAction.ConsumeDownloadAction(tab.id, downloadId = 4223)
ContentAction.ConsumeDownloadAction(tab.id, downloadId = "4223")
).joinBlocking()

assertNotNull(tab.content.download)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import mozilla.components.support.test.ext.joinBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Assert.assertSame
import org.junit.Test

class DownloadActionTest {
Expand All @@ -30,6 +31,30 @@ class DownloadActionTest {
assertEquals(2, store.state.downloads.size)
}

@Test
fun `RestoreDownloadStateAction adds download`() {
val store = BrowserStore(BrowserState())

val download1 = DownloadState("https://mozilla.org/download1", destinationDirectory = "")
store.dispatch(DownloadAction.RestoreDownloadStateAction(download1)).joinBlocking()
assertEquals(download1, store.state.downloads[download1.id])
assertEquals(1, store.state.downloads.size)

val download2 = DownloadState("https://mozilla.org/download2", destinationDirectory = "")
store.dispatch(DownloadAction.RestoreDownloadStateAction(download2)).joinBlocking()
assertEquals(download2, store.state.downloads[download2.id])
assertEquals(2, store.state.downloads.size)
}

@Test
fun `RestoreDownloadsStateAction does nothing`() {
val store = BrowserStore(BrowserState())

val state = store.state
store.dispatch(DownloadAction.RestoreDownloadsStateAction).joinBlocking()
assertSame(store.state, state)
}

@Test
fun `RemoveDownloadAction removes download`() {
val store = BrowserStore(BrowserState())
Expand Down
27 changes: 27 additions & 0 deletions components/feature/downloads/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
compileSdkVersion config.compileSdkVersion

defaultConfig {
minSdkVersion config.minSdkVersion
targetSdkVersion config.targetSdkVersion
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas".toString())
}
}
}

buildTypes {
Expand All @@ -20,6 +28,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

sourceSets {
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
}
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
Expand All @@ -43,6 +55,11 @@ dependencies {
implementation Dependencies.kotlin_stdlib
implementation Dependencies.androidx_recyclerview
implementation Dependencies.androidx_constraintlayout
implementation Dependencies.androidx_room_runtime
implementation Dependencies.androidx_paging
implementation Dependencies.androidx_lifecycle_livedata

kapt Dependencies.androidx_room_compiler

testImplementation Dependencies.androidx_test_core
testImplementation Dependencies.androidx_test_junit
Expand All @@ -52,6 +69,16 @@ dependencies {
testImplementation project(':concept-engine')
testImplementation project(':support-test')
testImplementation project(':support-test-libstate')

androidTestImplementation project(':support-android-test')

androidTestImplementation Dependencies.androidx_room_testing
androidTestImplementation Dependencies.androidx_arch_core_testing
androidTestImplementation Dependencies.androidx_test_core
androidTestImplementation Dependencies.androidx_test_runner
androidTestImplementation Dependencies.androidx_test_rules
androidTestImplementation Dependencies.testing_coroutines

}

apply from: '../../../publish.gradle'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "342d0e5d0a0fcde72b88ac4585caf842",
"entities": [
{
"tableName": "downloads",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `url` TEXT NOT NULL, `file_name` TEXT, `content_type` TEXT, `content_length` INTEGER, `status` INTEGER NOT NULL, `destination_directory` TEXT NOT NULL, `created_at` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "fileName",
"columnName": "file_name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "contentType",
"columnName": "content_type",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "contentLength",
"columnName": "content_length",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "status",
"columnName": "status",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "destinationDirectory",
"columnName": "destination_directory",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "createdAt",
"columnName": "created_at",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '342d0e5d0a0fcde72b88ac4585caf842')"
]
}
}
Loading