<lambda>null1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
2  * Any copyright is dedicated to the Public Domain.
3    http://creativecommons.org/publicdomain/zero/1.0/ */
4 
5 package org.mozilla.geckoview.test
6 
7 import android.content.pm.ActivityInfo
8 import android.content.res.Configuration
9 import androidx.test.ext.junit.rules.ActivityScenarioRule
10 import androidx.test.filters.MediumTest
11 import androidx.test.ext.junit.runners.AndroidJUnit4
12 
13 import org.hamcrest.Matchers.*
14 import org.junit.Rule
15 
16 import org.junit.Test
17 import org.junit.rules.RuleChain
18 import org.junit.runner.RunWith
19 
20 import org.mozilla.geckoview.*
21 import org.mozilla.geckoview.GeckoSession.ContentDelegate
22 import org.mozilla.geckoview.OrientationController
23 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule
24 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
25 
26 @RunWith(AndroidJUnit4::class)
27 @MediumTest
28 class OrientationDelegateTest : BaseSessionTest() {
29     val activityRule = ActivityScenarioRule(GeckoViewTestActivity::class.java)
30 
31     @get:Rule
32     override val rules: RuleChain = RuleChain.outerRule(activityRule).around(sessionRule)
33 
34     private fun goFullscreen() {
35         sessionRule.setPrefsUntilTestEnd(mapOf("full-screen-api.allow-trusted-requests-only" to false))
36         mainSession.loadTestPath(FULLSCREEN_PATH)
37         mainSession.waitForPageStop()
38         val promise = mainSession.evaluatePromiseJS("document.querySelector('#fullscreen').requestFullscreen()")
39         sessionRule.waitUntilCalled(object : ContentDelegate {
40             @AssertCalled(count = 1)
41             override  fun onFullScreen(session: GeckoSession, fullScreen: Boolean) {
42                 assertThat("Div went fullscreen", fullScreen, equalTo(true))
43             }
44         })
45         promise.value
46     }
47 
48     private fun lockPortrait() {
49         val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('portrait-primary')")
50         sessionRule.delegateDuringNextWait(object : OrientationController.OrientationDelegate {
51             @AssertCalled(count = 1)
52             override fun onOrientationLock(aOrientation: Int): GeckoResult<AllowOrDeny> {
53                 assertThat(
54                     "The orientation should be portrait",
55                     aOrientation,
56                     equalTo(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
57                 )
58                 activityRule.scenario.onActivity { activity ->
59                     activity.requestedOrientation = aOrientation
60                 }
61                 return GeckoResult.allow()
62             }
63         })
64         sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_PORTRAIT)
65         promise.value
66         // Remove previous delegate
67         mainSession.waitForRoundTrip()
68     }
69 
70     private fun lockLandscape() {
71         val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('landscape-primary')")
72         sessionRule.delegateDuringNextWait(object : OrientationController.OrientationDelegate {
73             @AssertCalled(count = 1)
74             override fun onOrientationLock(aOrientation: Int): GeckoResult<AllowOrDeny> {
75                 assertThat(
76                     "The orientation should be landscape",
77                     aOrientation,
78                     equalTo(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
79                 )
80                 activityRule.scenario.onActivity { activity ->
81                     activity.requestedOrientation = aOrientation
82                 }
83                 return GeckoResult.allow()
84             }
85         })
86         sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_LANDSCAPE)
87         promise.value
88         // Remove previous delegate
89         mainSession.waitForRoundTrip()
90     }
91 
92     @Test fun orientationLock() {
93         sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
94         goFullscreen()
95         activityRule.scenario.onActivity { activity ->
96             // If the orientation is landscape, lock to portrait and wait for delegate. If portrait, lock to landscape instead.
97             if (activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){
98                 lockPortrait()
99             } else if (activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
100                 lockLandscape()
101             }
102         }
103     }
104 
105     @Test fun orientationUnlock() {
106         sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
107         goFullscreen()
108         mainSession.evaluateJS("screen.orientation.unlock()")
109         sessionRule.waitUntilCalled(object : OrientationController.OrientationDelegate {
110             @AssertCalled(count = 1)
111             override fun onOrientationUnlock() {
112                 activityRule.scenario.onActivity { activity ->
113                     activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
114                 }
115             }
116         })
117     }
118 
119     @Test fun orientationLockedAlready() {
120         sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
121         goFullscreen()
122         // Lock to landscape twice to verify successful locking with existing lock
123         lockLandscape()
124         lockLandscape()
125     }
126 
127     @Test fun orientationLockedExistingOrientation() {
128         sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
129         goFullscreen()
130         // Lock to landscape twice to verify successful locking to existing orientation
131         activityRule.scenario.onActivity { activity ->
132             activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
133         }
134         lockLandscape()
135     }
136 
137     @Test(expected = GeckoSessionTestRule.RejectedPromiseException::class)
138     fun orientationLockNoFullscreen() {
139         // Verify if fullscreen pre-lock conditions are not met, a rejected promise is returned.
140         sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
141         mainSession.loadTestPath(FULLSCREEN_PATH)
142         mainSession.waitForPageStop()
143         mainSession.evaluateJS("screen.orientation.lock('landscape-primary')")
144     }
145 
146     @Test fun orientationLockUnlock() {
147         sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
148         goFullscreen()
149 
150         val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('landscape-primary')")
151         sessionRule.delegateDuringNextWait(object : OrientationController.OrientationDelegate {
152             @AssertCalled(count = 1)
153             override fun onOrientationLock(aOrientation: Int): GeckoResult<AllowOrDeny> {
154                 assertThat(
155                     "The orientation value is as expected",
156                     aOrientation,
157                     equalTo(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
158                 )
159                 activityRule.scenario.onActivity { activity ->
160                     activity.requestedOrientation = aOrientation
161                 }
162                 return GeckoResult.allow()
163             }
164         })
165         sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_LANDSCAPE)
166         promise.value
167         // Remove previous delegate
168         mainSession.waitForRoundTrip()
169 
170         // after locking to orientation landscape, unlock to default
171         mainSession.evaluateJS("screen.orientation.unlock()")
172         sessionRule.waitUntilCalled(object : OrientationController.OrientationDelegate {
173             @AssertCalled(count = 1)
174             override fun onOrientationUnlock() {
175                 activityRule.scenario.onActivity { activity ->
176                     activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
177                 }
178             }
179         })
180     }
181 
182     @Test fun orientationLockUnsupported() {
183         // If no delegate, orientation.lock must throws NotSupportedError
184         sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
185         goFullscreen()
186 
187         val promise = mainSession.evaluatePromiseJS("""
188           new Promise(r => {
189             screen.orientation.lock('landscape-primary')
190             .then(() => r("successful"))
191             .catch(e => r(e.name))
192           })
193         """.trimIndent())
194 
195         assertThat("The operation must throw NotSupportedError",
196                    promise.value,
197                    equalTo("NotSupportedError"))
198 
199         val promise2 = mainSession.evaluatePromiseJS("""
200           new Promise(r => {
201             screen.orientation.lock(screen.orientation.type)
202             .then(() => r("successful"))
203             .catch(e => r(e.name))
204           })
205         """.trimIndent())
206 
207         assertThat("The operation must throw NotSupportedError even if same orientation",
208                    promise2.value,
209                    equalTo("NotSupportedError"))
210     }
211 }
212