Richard Pospesel pushed to branch android-components-102.0.14-12.0-1 at The Tor Project / Applications / android-components
Commits:
-
b65622fa
by Arturo Mejia at 2022-08-30T21:22:54+00:00
4 changed files:
- components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt
- + components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMediaDelegate.kt
- components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt
- + components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaDelegateTest.kt
Changes:
... | ... | @@ -16,6 +16,7 @@ import kotlinx.coroutines.MainScope |
16 | 16 | import kotlinx.coroutines.launch
|
17 | 17 | import mozilla.components.browser.engine.gecko.ext.isExcludedForTrackingProtection
|
18 | 18 | import mozilla.components.browser.engine.gecko.fetch.toResponse
|
19 | +import mozilla.components.browser.engine.gecko.media.GeckoMediaDelegate
|
|
19 | 20 | import mozilla.components.browser.engine.gecko.mediasession.GeckoMediaSessionDelegate
|
20 | 21 | import mozilla.components.browser.engine.gecko.permission.GeckoPermissionRequest
|
21 | 22 | import mozilla.components.browser.engine.gecko.prompt.GeckoPromptDelegate
|
... | ... | @@ -1098,6 +1099,7 @@ class GeckoEngineSession( |
1098 | 1099 | geckoSession.contentBlockingDelegate = createContentBlockingDelegate()
|
1099 | 1100 | geckoSession.permissionDelegate = createPermissionDelegate()
|
1100 | 1101 | geckoSession.promptDelegate = GeckoPromptDelegate(this)
|
1102 | + geckoSession.mediaDelegate = GeckoMediaDelegate(this)
|
|
1101 | 1103 | geckoSession.historyDelegate = createHistoryDelegate()
|
1102 | 1104 | geckoSession.mediaSessionDelegate = GeckoMediaSessionDelegate(this)
|
1103 | 1105 | geckoSession.scrollDelegate = createScrollDelegate()
|
1 | +/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2 | + * License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3 | + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
4 | + |
|
5 | +package mozilla.components.browser.engine.gecko.media
|
|
6 | + |
|
7 | +import androidx.annotation.VisibleForTesting
|
|
8 | +import mozilla.components.browser.engine.gecko.GeckoEngineSession
|
|
9 | +import mozilla.components.concept.engine.media.RecordingDevice
|
|
10 | +import org.mozilla.geckoview.GeckoSession
|
|
11 | +import java.security.InvalidParameterException
|
|
12 | +import org.mozilla.geckoview.GeckoSession.MediaDelegate.RecordingDevice as GeckoRecordingDevice
|
|
13 | + |
|
14 | +/**
|
|
15 | + * Gecko-based GeckoMediaDelegate implementation.
|
|
16 | + */
|
|
17 | +internal class GeckoMediaDelegate(private val geckoEngineSession: GeckoEngineSession) :
|
|
18 | + GeckoSession.MediaDelegate {
|
|
19 | + |
|
20 | + override fun onRecordingStatusChanged(
|
|
21 | + session: GeckoSession,
|
|
22 | + geckoDevices: Array<out GeckoRecordingDevice>
|
|
23 | + ) {
|
|
24 | + val devices = geckoDevices.map { geckoRecording ->
|
|
25 | + val type = geckoRecording.toType()
|
|
26 | + val status = geckoRecording.toStatus()
|
|
27 | + RecordingDevice(type, status)
|
|
28 | + }
|
|
29 | + geckoEngineSession.notifyObservers { onRecordingStateChanged(devices) }
|
|
30 | + }
|
|
31 | +}
|
|
32 | + |
|
33 | +@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
|
34 | +internal fun GeckoRecordingDevice.toType(): RecordingDevice.Type {
|
|
35 | + return when (type) {
|
|
36 | + GeckoRecordingDevice.Type.CAMERA -> RecordingDevice.Type.CAMERA
|
|
37 | + GeckoRecordingDevice.Type.MICROPHONE -> RecordingDevice.Type.MICROPHONE
|
|
38 | + else -> {
|
|
39 | + throw InvalidParameterException("Unexpected Gecko Media type $type status $status")
|
|
40 | + }
|
|
41 | + }
|
|
42 | +}
|
|
43 | + |
|
44 | +@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
|
45 | +internal fun GeckoRecordingDevice.toStatus(): RecordingDevice.Status {
|
|
46 | + return when (status) {
|
|
47 | + GeckoRecordingDevice.Status.RECORDING -> RecordingDevice.Status.RECORDING
|
|
48 | + GeckoRecordingDevice.Status.INACTIVE -> RecordingDevice.Status.INACTIVE
|
|
49 | + else -> {
|
|
50 | + throw InvalidParameterException("Unexpected Gecko Media type $type status $status")
|
|
51 | + }
|
|
52 | + }
|
|
53 | +} |
... | ... | @@ -113,6 +113,7 @@ class GeckoEngineSessionTest { |
113 | 113 | |
114 | 114 | private lateinit var navigationDelegate: ArgumentCaptor<GeckoSession.NavigationDelegate>
|
115 | 115 | private lateinit var progressDelegate: ArgumentCaptor<GeckoSession.ProgressDelegate>
|
116 | + private lateinit var mediaDelegate: ArgumentCaptor<GeckoSession.MediaDelegate>
|
|
116 | 117 | private lateinit var contentDelegate: ArgumentCaptor<GeckoSession.ContentDelegate>
|
117 | 118 | private lateinit var permissionDelegate: ArgumentCaptor<GeckoSession.PermissionDelegate>
|
118 | 119 | private lateinit var contentBlockingDelegate: ArgumentCaptor<ContentBlocking.Delegate>
|
... | ... | @@ -140,6 +141,7 @@ class GeckoEngineSessionTest { |
140 | 141 | whenever(runtime.settings).thenReturn(mock())
|
141 | 142 | navigationDelegate = ArgumentCaptor.forClass(GeckoSession.NavigationDelegate::class.java)
|
142 | 143 | progressDelegate = ArgumentCaptor.forClass(GeckoSession.ProgressDelegate::class.java)
|
144 | + mediaDelegate = ArgumentCaptor.forClass(GeckoSession.MediaDelegate::class.java)
|
|
143 | 145 | contentDelegate = ArgumentCaptor.forClass(GeckoSession.ContentDelegate::class.java)
|
144 | 146 | permissionDelegate = ArgumentCaptor.forClass(GeckoSession.PermissionDelegate::class.java)
|
145 | 147 | contentBlockingDelegate = ArgumentCaptor.forClass(ContentBlocking.Delegate::class.java)
|
... | ... | @@ -156,6 +158,7 @@ class GeckoEngineSessionTest { |
156 | 158 | verify(geckoSession).permissionDelegate = permissionDelegate.capture()
|
157 | 159 | verify(geckoSession).contentBlockingDelegate = contentBlockingDelegate.capture()
|
158 | 160 | verify(geckoSession).historyDelegate = historyDelegate.capture()
|
161 | + verify(geckoSession).mediaDelegate = mediaDelegate.capture()
|
|
159 | 162 | }
|
160 | 163 | |
161 | 164 | @Test
|
1 | +/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2 | + * License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3 | + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
4 | + |
|
5 | +package mozilla.components.browser.engine.gecko.media
|
|
6 | + |
|
7 | +import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
8 | +import junit.framework.TestCase.assertEquals
|
|
9 | +import junit.framework.TestCase.assertTrue
|
|
10 | +import junit.framework.TestCase.fail
|
|
11 | +import mozilla.components.browser.engine.gecko.GeckoEngineSession
|
|
12 | +import mozilla.components.concept.engine.EngineSession
|
|
13 | +import mozilla.components.concept.engine.media.RecordingDevice
|
|
14 | +import mozilla.components.support.test.mock
|
|
15 | +import mozilla.components.support.test.whenever
|
|
16 | +import mozilla.components.test.ReflectionUtils
|
|
17 | +import org.junit.Before
|
|
18 | +import org.junit.Test
|
|
19 | +import org.junit.runner.RunWith
|
|
20 | +import org.mozilla.geckoview.GeckoRuntime
|
|
21 | +import java.security.InvalidParameterException
|
|
22 | +import org.mozilla.geckoview.GeckoSession.MediaDelegate.RecordingDevice as GeckoRecordingDevice
|
|
23 | + |
|
24 | +@RunWith(AndroidJUnit4::class)
|
|
25 | +class GeckoMediaDelegateTest {
|
|
26 | + private lateinit var runtime: GeckoRuntime
|
|
27 | + |
|
28 | + @Before
|
|
29 | + fun setup() {
|
|
30 | + runtime = mock()
|
|
31 | + whenever(runtime.settings).thenReturn(mock())
|
|
32 | + }
|
|
33 | + |
|
34 | + @Test
|
|
35 | + fun `WHEN onRecordingStatusChanged is called THEN notify onRecordingStateChanged`() {
|
|
36 | + val mockSession = GeckoEngineSession(runtime)
|
|
37 | + var onRecordingWasCalled = false
|
|
38 | + val geckoRecordingDevice = createGeckoRecordingDevice(
|
|
39 | + status = GeckoRecordingDevice.Status.RECORDING, type = GeckoRecordingDevice.Type.CAMERA
|
|
40 | + )
|
|
41 | + val gecko = GeckoMediaDelegate(mockSession)
|
|
42 | + |
|
43 | + mockSession.register(object : EngineSession.Observer {
|
|
44 | + override fun onRecordingStateChanged(devices: List<RecordingDevice>) {
|
|
45 | + onRecordingWasCalled = true
|
|
46 | + }
|
|
47 | + })
|
|
48 | + |
|
49 | + gecko.onRecordingStatusChanged(mock(), arrayOf(geckoRecordingDevice))
|
|
50 | + |
|
51 | + assertTrue(onRecordingWasCalled)
|
|
52 | + }
|
|
53 | + |
|
54 | + @Test
|
|
55 | + fun `GIVEN a GeckoRecordingDevice status WHEN calling toStatus THEN covert to the RecordingDevice status`() {
|
|
56 | + val geckoRecordingDevice = createGeckoRecordingDevice(
|
|
57 | + status = GeckoRecordingDevice.Status.RECORDING
|
|
58 | + )
|
|
59 | + val geckoInactiveDevice = createGeckoRecordingDevice(
|
|
60 | + status = GeckoRecordingDevice.Status.INACTIVE
|
|
61 | + )
|
|
62 | + |
|
63 | + assertEquals(RecordingDevice.Status.RECORDING, geckoRecordingDevice.toStatus())
|
|
64 | + assertEquals(RecordingDevice.Status.INACTIVE, geckoInactiveDevice.toStatus())
|
|
65 | + }
|
|
66 | + |
|
67 | + @Test
|
|
68 | + fun `GIVEN an invalid GeckoRecordingDevice status WHEN calling toStatus THEN throw an exception`() {
|
|
69 | + val geckoInvalidDevice = createGeckoRecordingDevice(
|
|
70 | + status = 12
|
|
71 | + )
|
|
72 | + try {
|
|
73 | + geckoInvalidDevice.toStatus()
|
|
74 | + fail()
|
|
75 | + } catch (_: InvalidParameterException) {
|
|
76 | + }
|
|
77 | + }
|
|
78 | + |
|
79 | + @Test
|
|
80 | + fun `GIVEN a GeckoRecordingDevice type WHEN calling toType THEN covert to the RecordingDevice type`() {
|
|
81 | + val geckoCameraDevice = createGeckoRecordingDevice(
|
|
82 | + type = GeckoRecordingDevice.Type.CAMERA
|
|
83 | + )
|
|
84 | + val geckoMicDevice = createGeckoRecordingDevice(
|
|
85 | + type = GeckoRecordingDevice.Type.MICROPHONE
|
|
86 | + )
|
|
87 | + |
|
88 | + assertEquals(RecordingDevice.Type.CAMERA, geckoCameraDevice.toType())
|
|
89 | + assertEquals(RecordingDevice.Type.MICROPHONE, geckoMicDevice.toType())
|
|
90 | + }
|
|
91 | + |
|
92 | + @Test
|
|
93 | + fun `GIVEN an invalid GeckoRecordingDevice type WHEN calling toType THEN throw an exception`() {
|
|
94 | + val geckoInvalidDevice = createGeckoRecordingDevice(
|
|
95 | + type = 12
|
|
96 | + )
|
|
97 | + try {
|
|
98 | + geckoInvalidDevice.toType()
|
|
99 | + fail()
|
|
100 | + } catch (_: InvalidParameterException) {
|
|
101 | + }
|
|
102 | + }
|
|
103 | + |
|
104 | + private fun createGeckoRecordingDevice(
|
|
105 | + status: Long = GeckoRecordingDevice.Status.RECORDING,
|
|
106 | + type: Long = GeckoRecordingDevice.Type.CAMERA
|
|
107 | + ): GeckoRecordingDevice {
|
|
108 | + val device: GeckoRecordingDevice = mock()
|
|
109 | + ReflectionUtils.setField(device, "status", status)
|
|
110 | + ReflectionUtils.setField(device, "type", type)
|
|
111 | + return device
|
|
112 | + }
|
|
113 | +} |