Loading components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt +2 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import mozilla.components.browser.engine.gecko.ext.isExcludedForTrackingProtection import mozilla.components.browser.engine.gecko.fetch.toResponse import mozilla.components.browser.engine.gecko.media.GeckoMediaDelegate import mozilla.components.browser.engine.gecko.mediasession.GeckoMediaSessionDelegate import mozilla.components.browser.engine.gecko.permission.GeckoPermissionRequest import mozilla.components.browser.engine.gecko.prompt.GeckoPromptDelegate Loading Loading @@ -1098,6 +1099,7 @@ class GeckoEngineSession( geckoSession.contentBlockingDelegate = createContentBlockingDelegate() geckoSession.permissionDelegate = createPermissionDelegate() geckoSession.promptDelegate = GeckoPromptDelegate(this) geckoSession.mediaDelegate = GeckoMediaDelegate(this) geckoSession.historyDelegate = createHistoryDelegate() geckoSession.mediaSessionDelegate = GeckoMediaSessionDelegate(this) geckoSession.scrollDelegate = createScrollDelegate() Loading components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMediaDelegate.kt 0 → 100644 +53 −0 Original line number Diff line number Diff line /* 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.browser.engine.gecko.media import androidx.annotation.VisibleForTesting import mozilla.components.browser.engine.gecko.GeckoEngineSession import mozilla.components.concept.engine.media.RecordingDevice import org.mozilla.geckoview.GeckoSession import java.security.InvalidParameterException import org.mozilla.geckoview.GeckoSession.MediaDelegate.RecordingDevice as GeckoRecordingDevice /** * Gecko-based GeckoMediaDelegate implementation. */ internal class GeckoMediaDelegate(private val geckoEngineSession: GeckoEngineSession) : GeckoSession.MediaDelegate { override fun onRecordingStatusChanged( session: GeckoSession, geckoDevices: Array<out GeckoRecordingDevice> ) { val devices = geckoDevices.map { geckoRecording -> val type = geckoRecording.toType() val status = geckoRecording.toStatus() RecordingDevice(type, status) } geckoEngineSession.notifyObservers { onRecordingStateChanged(devices) } } } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal fun GeckoRecordingDevice.toType(): RecordingDevice.Type { return when (type) { GeckoRecordingDevice.Type.CAMERA -> RecordingDevice.Type.CAMERA GeckoRecordingDevice.Type.MICROPHONE -> RecordingDevice.Type.MICROPHONE else -> { throw InvalidParameterException("Unexpected Gecko Media type $type status $status") } } } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal fun GeckoRecordingDevice.toStatus(): RecordingDevice.Status { return when (status) { GeckoRecordingDevice.Status.RECORDING -> RecordingDevice.Status.RECORDING GeckoRecordingDevice.Status.INACTIVE -> RecordingDevice.Status.INACTIVE else -> { throw InvalidParameterException("Unexpected Gecko Media type $type status $status") } } } components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt +3 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ class GeckoEngineSessionTest { private lateinit var navigationDelegate: ArgumentCaptor<GeckoSession.NavigationDelegate> private lateinit var progressDelegate: ArgumentCaptor<GeckoSession.ProgressDelegate> private lateinit var mediaDelegate: ArgumentCaptor<GeckoSession.MediaDelegate> private lateinit var contentDelegate: ArgumentCaptor<GeckoSession.ContentDelegate> private lateinit var permissionDelegate: ArgumentCaptor<GeckoSession.PermissionDelegate> private lateinit var contentBlockingDelegate: ArgumentCaptor<ContentBlocking.Delegate> Loading Loading @@ -140,6 +141,7 @@ class GeckoEngineSessionTest { whenever(runtime.settings).thenReturn(mock()) navigationDelegate = ArgumentCaptor.forClass(GeckoSession.NavigationDelegate::class.java) progressDelegate = ArgumentCaptor.forClass(GeckoSession.ProgressDelegate::class.java) mediaDelegate = ArgumentCaptor.forClass(GeckoSession.MediaDelegate::class.java) contentDelegate = ArgumentCaptor.forClass(GeckoSession.ContentDelegate::class.java) permissionDelegate = ArgumentCaptor.forClass(GeckoSession.PermissionDelegate::class.java) contentBlockingDelegate = ArgumentCaptor.forClass(ContentBlocking.Delegate::class.java) Loading @@ -156,6 +158,7 @@ class GeckoEngineSessionTest { verify(geckoSession).permissionDelegate = permissionDelegate.capture() verify(geckoSession).contentBlockingDelegate = contentBlockingDelegate.capture() verify(geckoSession).historyDelegate = historyDelegate.capture() verify(geckoSession).mediaDelegate = mediaDelegate.capture() } @Test Loading components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaDelegateTest.kt 0 → 100644 +113 −0 Original line number Diff line number Diff line /* 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.browser.engine.gecko.media import androidx.test.ext.junit.runners.AndroidJUnit4 import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertTrue import junit.framework.TestCase.fail import mozilla.components.browser.engine.gecko.GeckoEngineSession import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.media.RecordingDevice import mozilla.components.support.test.mock import mozilla.components.support.test.whenever import mozilla.components.test.ReflectionUtils import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mozilla.geckoview.GeckoRuntime import java.security.InvalidParameterException import org.mozilla.geckoview.GeckoSession.MediaDelegate.RecordingDevice as GeckoRecordingDevice @RunWith(AndroidJUnit4::class) class GeckoMediaDelegateTest { private lateinit var runtime: GeckoRuntime @Before fun setup() { runtime = mock() whenever(runtime.settings).thenReturn(mock()) } @Test fun `WHEN onRecordingStatusChanged is called THEN notify onRecordingStateChanged`() { val mockSession = GeckoEngineSession(runtime) var onRecordingWasCalled = false val geckoRecordingDevice = createGeckoRecordingDevice( status = GeckoRecordingDevice.Status.RECORDING, type = GeckoRecordingDevice.Type.CAMERA ) val gecko = GeckoMediaDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onRecordingStateChanged(devices: List<RecordingDevice>) { onRecordingWasCalled = true } }) gecko.onRecordingStatusChanged(mock(), arrayOf(geckoRecordingDevice)) assertTrue(onRecordingWasCalled) } @Test fun `GIVEN a GeckoRecordingDevice status WHEN calling toStatus THEN covert to the RecordingDevice status`() { val geckoRecordingDevice = createGeckoRecordingDevice( status = GeckoRecordingDevice.Status.RECORDING ) val geckoInactiveDevice = createGeckoRecordingDevice( status = GeckoRecordingDevice.Status.INACTIVE ) assertEquals(RecordingDevice.Status.RECORDING, geckoRecordingDevice.toStatus()) assertEquals(RecordingDevice.Status.INACTIVE, geckoInactiveDevice.toStatus()) } @Test fun `GIVEN an invalid GeckoRecordingDevice status WHEN calling toStatus THEN throw an exception`() { val geckoInvalidDevice = createGeckoRecordingDevice( status = 12 ) try { geckoInvalidDevice.toStatus() fail() } catch (_: InvalidParameterException) { } } @Test fun `GIVEN a GeckoRecordingDevice type WHEN calling toType THEN covert to the RecordingDevice type`() { val geckoCameraDevice = createGeckoRecordingDevice( type = GeckoRecordingDevice.Type.CAMERA ) val geckoMicDevice = createGeckoRecordingDevice( type = GeckoRecordingDevice.Type.MICROPHONE ) assertEquals(RecordingDevice.Type.CAMERA, geckoCameraDevice.toType()) assertEquals(RecordingDevice.Type.MICROPHONE, geckoMicDevice.toType()) } @Test fun `GIVEN an invalid GeckoRecordingDevice type WHEN calling toType THEN throw an exception`() { val geckoInvalidDevice = createGeckoRecordingDevice( type = 12 ) try { geckoInvalidDevice.toType() fail() } catch (_: InvalidParameterException) { } } private fun createGeckoRecordingDevice( status: Long = GeckoRecordingDevice.Status.RECORDING, type: Long = GeckoRecordingDevice.Type.CAMERA ): GeckoRecordingDevice { val device: GeckoRecordingDevice = mock() ReflectionUtils.setField(device, "status", status) ReflectionUtils.setField(device, "type", type) return device } } Loading
components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt +2 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import mozilla.components.browser.engine.gecko.ext.isExcludedForTrackingProtection import mozilla.components.browser.engine.gecko.fetch.toResponse import mozilla.components.browser.engine.gecko.media.GeckoMediaDelegate import mozilla.components.browser.engine.gecko.mediasession.GeckoMediaSessionDelegate import mozilla.components.browser.engine.gecko.permission.GeckoPermissionRequest import mozilla.components.browser.engine.gecko.prompt.GeckoPromptDelegate Loading Loading @@ -1098,6 +1099,7 @@ class GeckoEngineSession( geckoSession.contentBlockingDelegate = createContentBlockingDelegate() geckoSession.permissionDelegate = createPermissionDelegate() geckoSession.promptDelegate = GeckoPromptDelegate(this) geckoSession.mediaDelegate = GeckoMediaDelegate(this) geckoSession.historyDelegate = createHistoryDelegate() geckoSession.mediaSessionDelegate = GeckoMediaSessionDelegate(this) geckoSession.scrollDelegate = createScrollDelegate() Loading
components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMediaDelegate.kt 0 → 100644 +53 −0 Original line number Diff line number Diff line /* 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.browser.engine.gecko.media import androidx.annotation.VisibleForTesting import mozilla.components.browser.engine.gecko.GeckoEngineSession import mozilla.components.concept.engine.media.RecordingDevice import org.mozilla.geckoview.GeckoSession import java.security.InvalidParameterException import org.mozilla.geckoview.GeckoSession.MediaDelegate.RecordingDevice as GeckoRecordingDevice /** * Gecko-based GeckoMediaDelegate implementation. */ internal class GeckoMediaDelegate(private val geckoEngineSession: GeckoEngineSession) : GeckoSession.MediaDelegate { override fun onRecordingStatusChanged( session: GeckoSession, geckoDevices: Array<out GeckoRecordingDevice> ) { val devices = geckoDevices.map { geckoRecording -> val type = geckoRecording.toType() val status = geckoRecording.toStatus() RecordingDevice(type, status) } geckoEngineSession.notifyObservers { onRecordingStateChanged(devices) } } } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal fun GeckoRecordingDevice.toType(): RecordingDevice.Type { return when (type) { GeckoRecordingDevice.Type.CAMERA -> RecordingDevice.Type.CAMERA GeckoRecordingDevice.Type.MICROPHONE -> RecordingDevice.Type.MICROPHONE else -> { throw InvalidParameterException("Unexpected Gecko Media type $type status $status") } } } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal fun GeckoRecordingDevice.toStatus(): RecordingDevice.Status { return when (status) { GeckoRecordingDevice.Status.RECORDING -> RecordingDevice.Status.RECORDING GeckoRecordingDevice.Status.INACTIVE -> RecordingDevice.Status.INACTIVE else -> { throw InvalidParameterException("Unexpected Gecko Media type $type status $status") } } }
components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt +3 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ class GeckoEngineSessionTest { private lateinit var navigationDelegate: ArgumentCaptor<GeckoSession.NavigationDelegate> private lateinit var progressDelegate: ArgumentCaptor<GeckoSession.ProgressDelegate> private lateinit var mediaDelegate: ArgumentCaptor<GeckoSession.MediaDelegate> private lateinit var contentDelegate: ArgumentCaptor<GeckoSession.ContentDelegate> private lateinit var permissionDelegate: ArgumentCaptor<GeckoSession.PermissionDelegate> private lateinit var contentBlockingDelegate: ArgumentCaptor<ContentBlocking.Delegate> Loading Loading @@ -140,6 +141,7 @@ class GeckoEngineSessionTest { whenever(runtime.settings).thenReturn(mock()) navigationDelegate = ArgumentCaptor.forClass(GeckoSession.NavigationDelegate::class.java) progressDelegate = ArgumentCaptor.forClass(GeckoSession.ProgressDelegate::class.java) mediaDelegate = ArgumentCaptor.forClass(GeckoSession.MediaDelegate::class.java) contentDelegate = ArgumentCaptor.forClass(GeckoSession.ContentDelegate::class.java) permissionDelegate = ArgumentCaptor.forClass(GeckoSession.PermissionDelegate::class.java) contentBlockingDelegate = ArgumentCaptor.forClass(ContentBlocking.Delegate::class.java) Loading @@ -156,6 +158,7 @@ class GeckoEngineSessionTest { verify(geckoSession).permissionDelegate = permissionDelegate.capture() verify(geckoSession).contentBlockingDelegate = contentBlockingDelegate.capture() verify(geckoSession).historyDelegate = historyDelegate.capture() verify(geckoSession).mediaDelegate = mediaDelegate.capture() } @Test Loading
components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaDelegateTest.kt 0 → 100644 +113 −0 Original line number Diff line number Diff line /* 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.browser.engine.gecko.media import androidx.test.ext.junit.runners.AndroidJUnit4 import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertTrue import junit.framework.TestCase.fail import mozilla.components.browser.engine.gecko.GeckoEngineSession import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.media.RecordingDevice import mozilla.components.support.test.mock import mozilla.components.support.test.whenever import mozilla.components.test.ReflectionUtils import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mozilla.geckoview.GeckoRuntime import java.security.InvalidParameterException import org.mozilla.geckoview.GeckoSession.MediaDelegate.RecordingDevice as GeckoRecordingDevice @RunWith(AndroidJUnit4::class) class GeckoMediaDelegateTest { private lateinit var runtime: GeckoRuntime @Before fun setup() { runtime = mock() whenever(runtime.settings).thenReturn(mock()) } @Test fun `WHEN onRecordingStatusChanged is called THEN notify onRecordingStateChanged`() { val mockSession = GeckoEngineSession(runtime) var onRecordingWasCalled = false val geckoRecordingDevice = createGeckoRecordingDevice( status = GeckoRecordingDevice.Status.RECORDING, type = GeckoRecordingDevice.Type.CAMERA ) val gecko = GeckoMediaDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onRecordingStateChanged(devices: List<RecordingDevice>) { onRecordingWasCalled = true } }) gecko.onRecordingStatusChanged(mock(), arrayOf(geckoRecordingDevice)) assertTrue(onRecordingWasCalled) } @Test fun `GIVEN a GeckoRecordingDevice status WHEN calling toStatus THEN covert to the RecordingDevice status`() { val geckoRecordingDevice = createGeckoRecordingDevice( status = GeckoRecordingDevice.Status.RECORDING ) val geckoInactiveDevice = createGeckoRecordingDevice( status = GeckoRecordingDevice.Status.INACTIVE ) assertEquals(RecordingDevice.Status.RECORDING, geckoRecordingDevice.toStatus()) assertEquals(RecordingDevice.Status.INACTIVE, geckoInactiveDevice.toStatus()) } @Test fun `GIVEN an invalid GeckoRecordingDevice status WHEN calling toStatus THEN throw an exception`() { val geckoInvalidDevice = createGeckoRecordingDevice( status = 12 ) try { geckoInvalidDevice.toStatus() fail() } catch (_: InvalidParameterException) { } } @Test fun `GIVEN a GeckoRecordingDevice type WHEN calling toType THEN covert to the RecordingDevice type`() { val geckoCameraDevice = createGeckoRecordingDevice( type = GeckoRecordingDevice.Type.CAMERA ) val geckoMicDevice = createGeckoRecordingDevice( type = GeckoRecordingDevice.Type.MICROPHONE ) assertEquals(RecordingDevice.Type.CAMERA, geckoCameraDevice.toType()) assertEquals(RecordingDevice.Type.MICROPHONE, geckoMicDevice.toType()) } @Test fun `GIVEN an invalid GeckoRecordingDevice type WHEN calling toType THEN throw an exception`() { val geckoInvalidDevice = createGeckoRecordingDevice( type = 12 ) try { geckoInvalidDevice.toType() fail() } catch (_: InvalidParameterException) { } } private fun createGeckoRecordingDevice( status: Long = GeckoRecordingDevice.Status.RECORDING, type: Long = GeckoRecordingDevice.Type.CAMERA ): GeckoRecordingDevice { val device: GeckoRecordingDevice = mock() ReflectionUtils.setField(device, "status", status) ReflectionUtils.setField(device, "type", type) return device } }