summaryrefslogtreecommitdiffstats
path: root/mobile/android/android-components/components/concept/push
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/android-components/components/concept/push')
-rw-r--r--mobile/android/android-components/components/concept/push/README.md23
-rw-r--r--mobile/android/android-components/components/concept/push/build.gradle38
-rw-r--r--mobile/android/android-components/components/concept/push/src/main/AndroidManifest.xml4
-rw-r--r--mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/PushProcessor.kt87
-rw-r--r--mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/PushService.kt41
-rw-r--r--mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/exceptions/SubscriptionException.kt17
-rw-r--r--mobile/android/android-components/components/concept/push/src/test/java/mozilla/components/concept/push/PushErrorTest.kt32
-rw-r--r--mobile/android/android-components/components/concept/push/src/test/java/mozilla/components/concept/push/PushProcessorTest.kt55
-rw-r--r--mobile/android/android-components/components/concept/push/src/test/resources/robolectric.properties1
9 files changed, 298 insertions, 0 deletions
diff --git a/mobile/android/android-components/components/concept/push/README.md b/mobile/android/android-components/components/concept/push/README.md
new file mode 100644
index 0000000000..dd596fdc78
--- /dev/null
+++ b/mobile/android/android-components/components/concept/push/README.md
@@ -0,0 +1,23 @@
+# [Android Components](../../../README.md) > Concept > Push
+
+An abstract definition of a push service component.
+
+## Usage
+
+### Setting up the dependency
+
+Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md)):
+
+```Groovy
+implementation "org.mozilla.components:concept-push:{latest-version}"
+```
+
+### Implementing a Push service.
+
+TBD
+
+## License
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/
diff --git a/mobile/android/android-components/components/concept/push/build.gradle b/mobile/android/android-components/components/concept/push/build.gradle
new file mode 100644
index 0000000000..a1999b52c9
--- /dev/null
+++ b/mobile/android/android-components/components/concept/push/build.gradle
@@ -0,0 +1,38 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+android {
+ defaultConfig {
+ minSdkVersion config.minSdkVersion
+ compileSdk config.compileSdkVersion
+ targetSdkVersion config.targetSdkVersion
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ namespace 'mozilla.components.concept.push'
+}
+
+dependencies {
+ implementation project(':support-base')
+
+ testImplementation project(':support-test')
+ testImplementation ComponentsDependencies.testing_junit
+}
+
+apply from: '../../../android-lint.gradle'
+apply from: '../../../publish.gradle'
+ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description)
diff --git a/mobile/android/android-components/components/concept/push/src/main/AndroidManifest.xml b/mobile/android/android-components/components/concept/push/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e16cda1d34
--- /dev/null
+++ b/mobile/android/android-components/components/concept/push/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<manifest />
diff --git a/mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/PushProcessor.kt b/mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/PushProcessor.kt
new file mode 100644
index 0000000000..909ee23737
--- /dev/null
+++ b/mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/PushProcessor.kt
@@ -0,0 +1,87 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.concept.push
+
+import androidx.annotation.VisibleForTesting
+
+/**
+ * A push notification processor that handles registration and new messages from the [PushService] provided.
+ * Starting Push in the Application's onCreate is recommended.
+ */
+interface PushProcessor {
+
+ /**
+ * Start the push processor and any service associated.
+ */
+ fun initialize()
+
+ /**
+ * Removes all push subscriptions from the device.
+ */
+ fun shutdown()
+
+ /**
+ * A new registration token has been received.
+ */
+ fun onNewToken(newToken: String)
+
+ /**
+ * A new push message has been received.
+ * The message contains the payload as sent by the
+ * Autopush server, and it will be read at a lower
+ * abstraction layer.
+ */
+ fun onMessageReceived(message: Map<String, String>)
+
+ /**
+ * An error has occurred.
+ */
+ fun onError(error: PushError)
+
+ /**
+ * Requests the [PushService] to renew it's registration with it's provider.
+ */
+ fun renewRegistration()
+
+ companion object {
+ /**
+ * Initialize and installs the PushProcessor into the application.
+ * This needs to be called in the application's onCreate before a push service has started.
+ */
+ fun install(processor: PushProcessor) {
+ instance = processor
+ }
+
+ @Volatile
+ private var instance: PushProcessor? = null
+
+ @VisibleForTesting
+ internal fun reset() {
+ instance = null
+ }
+ val requireInstance: PushProcessor
+ get() = instance ?: throw IllegalStateException(
+ "You need to call PushProcessor.install() on your Push instance from Application.onCreate().",
+ )
+ }
+}
+
+/**
+ * Various error types.
+ */
+sealed class PushError(override val message: String) : Exception() {
+ data class Registration(override val message: String) : PushError(message)
+ data class Network(override val message: String) : PushError(message)
+
+ /**
+ * @property cause Original exception from Rust code.
+ */
+ data class Rust(
+ override val cause: Throwable?,
+ override val message: String = cause?.message.orEmpty(),
+ ) : PushError(message)
+ data class MalformedMessage(override val message: String) : PushError(message)
+ data class ServiceUnavailable(override val message: String) : PushError(message)
+}
diff --git a/mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/PushService.kt b/mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/PushService.kt
new file mode 100644
index 0000000000..4308fb2d1e
--- /dev/null
+++ b/mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/PushService.kt
@@ -0,0 +1,41 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.concept.push
+
+import android.content.Context
+
+/**
+ * Implemented by push services like Firebase Cloud Messaging SDKs to allow
+ * the [PushProcessor] to manage their lifecycle.
+ */
+interface PushService {
+
+ /**
+ * Starts the push service.
+ */
+ fun start(context: Context)
+
+ /**
+ * Stops the push service.
+ */
+ fun stop()
+
+ /**
+ * Tells the push service to delete the registration token.
+ */
+ fun deleteToken()
+
+ /**
+ * If the push service is support on the device.
+ */
+ fun isServiceAvailable(context: Context): Boolean
+
+ companion object {
+ /**
+ * Message key for "channel ID" in a push message.
+ */
+ const val MESSAGE_KEY_CHANNEL_ID = "chid"
+ }
+}
diff --git a/mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/exceptions/SubscriptionException.kt b/mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/exceptions/SubscriptionException.kt
new file mode 100644
index 0000000000..de60f5b071
--- /dev/null
+++ b/mobile/android/android-components/components/concept/push/src/main/java/mozilla/components/concept/push/exceptions/SubscriptionException.kt
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+@file:Suppress("MatchingDeclarationName")
+
+package mozilla.components.concept.push.exceptions
+
+/**
+ * Signals that a subscription method has been invoked at an illegal or inappropriate time.
+ *
+ * See also [Exception].
+ */
+class SubscriptionException(
+ override val message: String? = null,
+ override val cause: Throwable? = null,
+) : Exception()
diff --git a/mobile/android/android-components/components/concept/push/src/test/java/mozilla/components/concept/push/PushErrorTest.kt b/mobile/android/android-components/components/concept/push/src/test/java/mozilla/components/concept/push/PushErrorTest.kt
new file mode 100644
index 0000000000..13e2013597
--- /dev/null
+++ b/mobile/android/android-components/components/concept/push/src/test/java/mozilla/components/concept/push/PushErrorTest.kt
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.concept.push
+
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class PushErrorTest {
+ @Test
+ fun `all PushError sets description`() {
+ // This test is mostly to satisfy coverage.
+
+ var error: PushError = PushError.MalformedMessage("message")
+ assertEquals("message", error.message)
+
+ error = PushError.Network("network")
+ assertEquals("network", error.message)
+
+ error = PushError.Registration("reg")
+ assertEquals("reg", error.message)
+
+ val exception = IllegalStateException()
+ val rustError = PushError.Rust(exception, "rust")
+ assertEquals("rust", rustError.message)
+ assertEquals(exception, rustError.cause)
+
+ error = PushError.ServiceUnavailable("service")
+ assertEquals("service", error.message)
+ }
+}
diff --git a/mobile/android/android-components/components/concept/push/src/test/java/mozilla/components/concept/push/PushProcessorTest.kt b/mobile/android/android-components/components/concept/push/src/test/java/mozilla/components/concept/push/PushProcessorTest.kt
new file mode 100644
index 0000000000..f8fad03aed
--- /dev/null
+++ b/mobile/android/android-components/components/concept/push/src/test/java/mozilla/components/concept/push/PushProcessorTest.kt
@@ -0,0 +1,55 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.concept.push
+
+import mozilla.components.support.test.mock
+import org.junit.Assert.assertNotNull
+import org.junit.Before
+import org.junit.Test
+
+class PushProcessorTest {
+
+ @Before
+ fun setup() {
+ PushProcessor.reset()
+ }
+
+ @Test
+ fun install() {
+ val processor: PushProcessor = mock()
+
+ PushProcessor.install(processor)
+
+ assertNotNull(PushProcessor.requireInstance)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun `requireInstance throws if install not called first`() {
+ PushProcessor.requireInstance
+ }
+
+ @Test
+ fun init() {
+ val push = TestPushProcessor()
+
+ PushProcessor.install(push)
+
+ assertNotNull(PushProcessor.requireInstance)
+ }
+
+ class TestPushProcessor : PushProcessor {
+ override fun initialize() {}
+
+ override fun shutdown() {}
+
+ override fun onNewToken(newToken: String) {}
+
+ override fun onMessageReceived(message: Map<String, String>) {}
+
+ override fun onError(error: PushError) {}
+
+ override fun renewRegistration() {}
+ }
+}
diff --git a/mobile/android/android-components/components/concept/push/src/test/resources/robolectric.properties b/mobile/android/android-components/components/concept/push/src/test/resources/robolectric.properties
new file mode 100644
index 0000000000..932b01b9eb
--- /dev/null
+++ b/mobile/android/android-components/components/concept/push/src/test/resources/robolectric.properties
@@ -0,0 +1 @@
+sdk=28