OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.vr_shell; | 5 package org.chromium.chrome.browser.vr_shell; |
6 | 6 |
7 import static org.chromium.chrome.browser.vr_shell.VrUtils.POLL_TIMEOUT_LONG_MS; | 7 import static org.chromium.chrome.browser.vr_shell.VrUtils.POLL_TIMEOUT_LONG_MS; |
8 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_D
EVICE_DAYDREAM; | 8 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_D
EVICE_DAYDREAM; |
9 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_D
EVICE_NON_DAYDREAM; | 9 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_D
EVICE_NON_DAYDREAM; |
10 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_V
IEWER_DAYDREAM; | 10 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_V
IEWER_DAYDREAM; |
11 | 11 |
12 import android.content.pm.ActivityInfo; | 12 import android.content.pm.ActivityInfo; |
| 13 import android.support.test.InstrumentationRegistry; |
13 import android.support.test.filters.MediumTest; | 14 import android.support.test.filters.MediumTest; |
14 import android.support.test.filters.SmallTest; | 15 import android.support.test.filters.SmallTest; |
15 import android.view.ViewGroup; | 16 import android.view.ViewGroup; |
16 | 17 |
| 18 import org.junit.Assert; |
| 19 import org.junit.Before; |
| 20 import org.junit.Rule; |
| 21 import org.junit.Test; |
| 22 import org.junit.runner.RunWith; |
| 23 |
17 import org.chromium.base.ThreadUtils; | 24 import org.chromium.base.ThreadUtils; |
18 import org.chromium.base.test.util.CommandLineFlags; | 25 import org.chromium.base.test.util.CommandLineFlags; |
19 import org.chromium.base.test.util.Feature; | 26 import org.chromium.base.test.util.Feature; |
20 import org.chromium.base.test.util.Restriction; | 27 import org.chromium.base.test.util.Restriction; |
21 import org.chromium.base.test.util.RetryOnFailure; | 28 import org.chromium.base.test.util.RetryOnFailure; |
22 import org.chromium.chrome.R; | 29 import org.chromium.chrome.R; |
| 30 import org.chromium.chrome.browser.ChromeSwitches; |
| 31 import org.chromium.chrome.browser.ChromeTabbedActivity; |
23 import org.chromium.chrome.browser.compositor.CompositorViewHolder; | 32 import org.chromium.chrome.browser.compositor.CompositorViewHolder; |
24 import org.chromium.chrome.browser.tabmodel.TabModelSelector; | 33 import org.chromium.chrome.browser.tabmodel.TabModelSelector; |
| 34 import org.chromium.chrome.test.ChromeActivityTestRule; |
| 35 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; |
| 36 import org.chromium.chrome.test.ChromeTabbedActivityTestRule; |
25 import org.chromium.chrome.test.util.RenderUtils.ViewRenderer; | 37 import org.chromium.chrome.test.util.RenderUtils.ViewRenderer; |
26 import org.chromium.content.browser.ContentViewCore; | 38 import org.chromium.content.browser.ContentViewCore; |
27 import org.chromium.content.browser.test.util.Criteria; | 39 import org.chromium.content.browser.test.util.Criteria; |
28 import org.chromium.content.browser.test.util.CriteriaHelper; | 40 import org.chromium.content.browser.test.util.CriteriaHelper; |
29 | 41 |
30 import java.io.IOException; | 42 import java.io.IOException; |
31 import java.util.concurrent.Callable; | 43 import java.util.concurrent.Callable; |
32 import java.util.concurrent.TimeoutException; | 44 import java.util.concurrent.TimeoutException; |
33 import java.util.concurrent.atomic.AtomicReference; | 45 import java.util.concurrent.atomic.AtomicReference; |
34 | 46 |
35 /** | 47 /** |
36 * End-to-end tests for VR browsing, aka "VR Shell". This may require | 48 * End-to-end tests for VR browsing, aka "VR Shell". This may require |
37 * interacting with WebVR in addition to the VR browser, so inherit from | 49 * interacting with WebVR in addition to the VR browser, so inherit from |
38 * VrTestBase for the WebVR test framework. | 50 * VrTestBase for the WebVR test framework. |
39 */ | 51 */ |
40 @CommandLineFlags.Add("enable-features=VrShell") | 52 @RunWith(ChromeJUnit4ClassRunner.class) |
41 public class VrShellTest extends VrTestBase { | 53 |
| 54 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, |
| 55 ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, "enable-features
=VrShell"}) |
| 56 public class VrShellTest { |
| 57 @Rule |
| 58 public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActi
vityTestRule(); |
| 59 |
42 private static final String GOLDEN_DIR = | 60 private static final String GOLDEN_DIR = |
43 "chrome/test/data/android/render_tests"; | 61 "chrome/test/data/android/render_tests"; |
44 | 62 |
45 private VrShellDelegate mDelegate; | 63 private VrShellDelegate mDelegate; |
46 private ViewRenderer mViewRenderer; | 64 private ViewRenderer mViewRenderer; |
47 | 65 |
48 @Override | 66 @Before |
49 protected void setUp() throws Exception { | 67 public void setUp() throws Exception { |
50 super.setUp(); | 68 mActivityTestRule.startMainActivityOnBlankPage(); |
| 69 mViewRenderer = new ViewRenderer( |
| 70 mActivityTestRule.getActivity(), GOLDEN_DIR, this.getClass().get
SimpleName()); |
51 mDelegate = VrUtils.getVrShellDelegateInstance(); | 71 mDelegate = VrUtils.getVrShellDelegateInstance(); |
52 } | 72 } |
53 | 73 |
54 @Override | |
55 public void startMainActivity() throws InterruptedException { | |
56 startMainActivityOnBlankPage(); | |
57 mViewRenderer = new ViewRenderer(getActivity(), | |
58 GOLDEN_DIR, this.getClass().getSimpleName()); | |
59 } | |
60 | |
61 private void enterExitVrMode(boolean supported) { | 74 private void enterExitVrMode(boolean supported) { |
62 MockVrDaydreamApi mockApi = new MockVrDaydreamApi(); | 75 MockVrDaydreamApi mockApi = new MockVrDaydreamApi(); |
63 if (!supported) { | 76 if (!supported) { |
64 mDelegate.overrideDaydreamApiForTesting(mockApi); | 77 mDelegate.overrideDaydreamApiForTesting(mockApi); |
65 } | 78 } |
66 VrUtils.forceEnterVr(); | 79 VrUtils.forceEnterVr(); |
67 if (supported) { | 80 if (supported) { |
68 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); | 81 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); |
69 assertTrue(VrShellDelegate.isInVr()); | 82 Assert.assertTrue(VrShellDelegate.isInVr()); |
70 } else { | 83 } else { |
71 assertFalse(mockApi.getLaunchInVrCalled()); | 84 Assert.assertFalse(mockApi.getLaunchInVrCalled()); |
72 assertFalse(VrShellDelegate.isInVr()); | 85 Assert.assertFalse(VrShellDelegate.isInVr()); |
73 } | 86 } |
74 VrUtils.forceExitVr(mDelegate); | 87 VrUtils.forceExitVr(mDelegate); |
75 assertFalse(VrShellDelegate.isInVr()); | 88 Assert.assertFalse(VrShellDelegate.isInVr()); |
76 } | 89 } |
77 | 90 |
78 private void enterExitVrModeImage(boolean supported) throws IOException { | 91 private void enterExitVrModeImage(boolean supported) throws IOException { |
79 int prevOrientation = getActivity().getRequestedOrientation(); | 92 ChromeTabbedActivity activity = mActivityTestRule.getActivity(); |
80 getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LA
NDSCAPE); | 93 int prevOrientation = activity.getRequestedOrientation(); |
81 getInstrumentation().waitForIdleSync(); | 94 mActivityTestRule.getActivity().setRequestedOrientation( |
| 95 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); |
| 96 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); |
82 mViewRenderer.renderAndCompare( | 97 mViewRenderer.renderAndCompare( |
83 getActivity().getWindow().getDecorView().getRootView(), | 98 activity.getWindow().getDecorView().getRootView(), "blank_page")
; |
84 "blank_page"); | |
85 | 99 |
86 VrUtils.forceEnterVr(); | 100 VrUtils.forceEnterVr(); |
87 // Currently, screenshots only show the static UI overlay, not the | 101 // Currently, screenshots only show the static UI overlay, not the |
88 // actual content. Thus, 1:1 pixel checking is reliable until a | 102 // actual content. Thus, 1:1 pixel checking is reliable until a |
89 // way to take screenshots of VR content is added, in which case | 103 // way to take screenshots of VR content is added, in which case |
90 // % similarity or some other method will need to be used. We're | 104 // % similarity or some other method will need to be used. We're |
91 // assuming that if the UI overlay is visible, then the device has | 105 // assuming that if the UI overlay is visible, then the device has |
92 // successfully entered VR mode. | 106 // successfully entered VR mode. |
93 if (supported) { | 107 if (supported) { |
94 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); | 108 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); |
95 mViewRenderer.renderAndCompare( | 109 mViewRenderer.renderAndCompare( |
96 getActivity().getWindow().getDecorView().getRootView(), | 110 activity.getWindow().getDecorView().getRootView(), "vr_enter
ed"); |
97 "vr_entered"); | |
98 } else { | 111 } else { |
99 // TODO(bsheedy): Find a good way to wait before taking a screenshot | 112 // TODO(bsheedy): Find a good way to wait before taking a screenshot |
100 // when running on an unsupported device | 113 // when running on an unsupported device |
101 mViewRenderer.renderAndCompare( | 114 mViewRenderer.renderAndCompare( |
102 getActivity().getWindow().getDecorView().getRootView(), | 115 activity.getWindow().getDecorView().getRootView(), "blank_pa
ge"); |
103 "blank_page"); | |
104 } | 116 } |
105 | 117 |
106 VrUtils.forceExitVr(mDelegate); | 118 VrUtils.forceExitVr(mDelegate); |
107 getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LA
NDSCAPE); | 119 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCA
PE); |
108 getInstrumentation().waitForIdleSync(); | 120 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); |
109 mViewRenderer.renderAndCompare( | 121 mViewRenderer.renderAndCompare( |
110 getActivity().getWindow().getDecorView().getRootView(), | 122 activity.getWindow().getDecorView().getRootView(), "blank_page")
; |
111 "blank_page"); | |
112 | 123 |
113 getActivity().setRequestedOrientation(prevOrientation); | 124 activity.setRequestedOrientation(prevOrientation); |
114 } | 125 } |
115 | 126 |
116 private void enterVrModeNfc(boolean supported) { | 127 private void enterVrModeNfc(boolean supported) { |
117 getInstrumentation().waitForIdleSync(); | 128 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); |
118 VrUtils.simNfc(getActivity()); | 129 VrUtils.simNfc(mActivityTestRule.getActivity()); |
119 if (supported) { | 130 if (supported) { |
120 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); | 131 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); |
121 assertTrue(VrShellDelegate.isInVr()); | 132 Assert.assertTrue(VrShellDelegate.isInVr()); |
122 } else { | 133 } else { |
123 assertFalse(VrShellDelegate.isInVr()); | 134 Assert.assertFalse(VrShellDelegate.isInVr()); |
124 } | 135 } |
125 VrUtils.forceExitVr(mDelegate); | 136 VrUtils.forceExitVr(mDelegate); |
126 // TODO(bsheedy): Figure out why NFC tests cause the next test to fail | 137 // TODO(bsheedy): Figure out why NFC tests cause the next test to fail |
127 // to enter VR unless we sleep for some amount of time after exiting VR | 138 // to enter VR unless we sleep for some amount of time after exiting VR |
128 // in the NFC test | 139 // in the NFC test |
129 } | 140 } |
130 | 141 |
131 /** | 142 /** |
132 * Verifies that browser successfully enters VR mode when Daydream headset | 143 * Verifies that browser successfully enters VR mode when Daydream headset |
133 * NFC tag is scanned on a Daydream-ready device. Requires that the phone | 144 * NFC tag is scanned on a Daydream-ready device. Requires that the phone |
134 * is unlocked. | 145 * is unlocked. |
135 */ | 146 */ |
| 147 @Test |
136 @Restriction({RESTRICTION_TYPE_DEVICE_DAYDREAM, RESTRICTION_TYPE_VIEWER_DAYD
REAM}) | 148 @Restriction({RESTRICTION_TYPE_DEVICE_DAYDREAM, RESTRICTION_TYPE_VIEWER_DAYD
REAM}) |
137 @MediumTest | 149 @MediumTest |
138 public void testSimNfcSupported() { | 150 public void testSimNfcSupported() { |
139 enterVrModeNfc(true); | 151 enterVrModeNfc(true); |
140 } | 152 } |
141 | 153 |
142 /** | 154 /** |
143 * Verifies that the browser does not enter VR mode on Non-Daydream-ready | 155 * Verifies that the browser does not enter VR mode on Non-Daydream-ready |
144 * devices when the Daydream headset NFC tag is scanned. | 156 * devices when the Daydream headset NFC tag is scanned. |
145 */ | 157 */ |
| 158 @Test |
146 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) | 159 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) |
147 @SmallTest | 160 @SmallTest |
148 public void testSimNfcUnsupported() { | 161 public void testSimNfcUnsupported() { |
149 enterVrModeNfc(false); | 162 enterVrModeNfc(false); |
150 } | 163 } |
151 | 164 |
152 /** | 165 /** |
153 * Verifies that browser successfully enters and exits VR mode when told to | 166 * Verifies that browser successfully enters and exits VR mode when told to |
154 * on Daydream-ready devices. Requires that the phone is unlocked. | 167 * on Daydream-ready devices. Requires that the phone is unlocked. |
155 */ | 168 */ |
| 169 @Test |
156 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM) | 170 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM) |
157 @SmallTest | 171 @SmallTest |
158 public void testEnterExitVrModeSupported() { | 172 public void testEnterExitVrModeSupported() { |
159 enterExitVrMode(true); | 173 enterExitVrMode(true); |
160 } | 174 } |
161 | 175 |
162 /** | 176 /** |
163 * Verifies that browser does not enter VR mode on Non-Daydream-ready device
s. | 177 * Verifies that browser does not enter VR mode on Non-Daydream-ready device
s. |
164 */ | 178 */ |
| 179 @Test |
165 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) | 180 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) |
166 @SmallTest | 181 @SmallTest |
167 public void testEnterExitVrModeUnsupported() { | 182 public void testEnterExitVrModeUnsupported() { |
168 enterExitVrMode(false); | 183 enterExitVrMode(false); |
169 } | 184 } |
170 | 185 |
171 /** | 186 /** |
172 * Verifies that browser successfully enters and exits VR mode when told to | 187 * Verifies that browser successfully enters and exits VR mode when told to |
173 * on Daydream-ready devices via a screendiffing check. | 188 * on Daydream-ready devices via a screendiffing check. |
174 * Requires that the phone is unlocked. | 189 * Requires that the phone is unlocked. |
175 */ | 190 */ |
| 191 @Test |
176 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM) | 192 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM) |
177 @Feature("RenderTest") | 193 @Feature("RenderTest") |
178 @MediumTest | 194 @MediumTest |
179 public void testEnterExitVrModeSupportedImage() throws IOException { | 195 public void testEnterExitVrModeSupportedImage() throws IOException { |
180 enterExitVrModeImage(true); | 196 enterExitVrModeImage(true); |
181 } | 197 } |
182 | 198 |
183 /** | 199 /** |
184 * Verifies that browser does not enter VR mode on Non-Daydream-ready device
s | 200 * Verifies that browser does not enter VR mode on Non-Daydream-ready device
s |
185 * via a screendiffing check. Requires that the phone is unlocked. | 201 * via a screendiffing check. Requires that the phone is unlocked. |
186 */ | 202 */ |
| 203 @Test |
187 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) | 204 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) |
188 @Feature("RenderTest") | 205 @Feature("RenderTest") |
189 @MediumTest | 206 @MediumTest |
190 public void testEnterExitVrModeUnsupportedImage() throws IOException { | 207 public void testEnterExitVrModeUnsupportedImage() throws IOException { |
191 enterExitVrModeImage(false); | 208 enterExitVrModeImage(false); |
192 } | 209 } |
193 | 210 |
194 /** | 211 /** |
195 * Verify that resizing the CompositorViewHolder does not cause the current
tab to resize while | 212 * Verify that resizing the CompositorViewHolder does not cause the current
tab to resize while |
196 * the CompositorViewHolder is detached from the TabModelSelector. See crbug
.com/680240. | 213 * the CompositorViewHolder is detached from the TabModelSelector. See crbug
.com/680240. |
197 * @throws InterruptedException | 214 * @throws InterruptedException |
198 * @throws TimeoutException | 215 * @throws TimeoutException |
199 */ | 216 */ |
| 217 @Test |
200 @SmallTest | 218 @SmallTest |
201 @RetryOnFailure | 219 @RetryOnFailure |
202 public void testResizeWithCompositorViewHolderDetached() | 220 public void testResizeWithCompositorViewHolderDetached() |
203 throws InterruptedException, TimeoutException { | 221 throws InterruptedException, TimeoutException { |
204 final AtomicReference<TabModelSelector> selector = new AtomicReference<>
(); | 222 final AtomicReference<TabModelSelector> selector = new AtomicReference<>
(); |
205 final AtomicReference<Integer> oldWidth = new AtomicReference<>(); | 223 final AtomicReference<Integer> oldWidth = new AtomicReference<>(); |
206 final int testWidth = 123; | 224 final int testWidth = 123; |
207 final ContentViewCore cvc = getActivity().getActivityTab().getActiveCont
entViewCore(); | 225 final ContentViewCore cvc = |
| 226 mActivityTestRule.getActivity().getActivityTab().getActiveConten
tViewCore(); |
208 | 227 |
209 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 228 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
210 @Override | 229 @Override |
211 public void run() { | 230 public void run() { |
212 CompositorViewHolder compositorViewHolder = (CompositorViewHolde
r) | 231 CompositorViewHolder compositorViewHolder = |
213 getActivity().findViewById(R.id.compositor_view_holder); | 232 (CompositorViewHolder) mActivityTestRule.getActivity().f
indViewById( |
| 233 R.id.compositor_view_holder); |
214 selector.set(compositorViewHolder.detachForVr()); | 234 selector.set(compositorViewHolder.detachForVr()); |
215 oldWidth.set(cvc.getViewportWidthPix()); | 235 oldWidth.set(cvc.getViewportWidthPix()); |
216 | 236 |
217 ViewGroup.LayoutParams layoutParams = compositorViewHolder.getLa
youtParams(); | 237 ViewGroup.LayoutParams layoutParams = compositorViewHolder.getLa
youtParams(); |
218 layoutParams.width = testWidth; | 238 layoutParams.width = testWidth; |
219 layoutParams.height = 456; | 239 layoutParams.height = 456; |
220 compositorViewHolder.requestLayout(); | 240 compositorViewHolder.requestLayout(); |
221 } | 241 } |
222 }); | 242 }); |
223 CriteriaHelper.pollUiThread(Criteria.equals(testWidth, new Callable<Inte
ger>() { | 243 CriteriaHelper.pollUiThread(Criteria.equals(testWidth, new Callable<Inte
ger>() { |
224 @Override | 244 @Override |
225 public Integer call() { | 245 public Integer call() { |
226 return getActivity().findViewById(R.id.compositor_view_holder).g
etMeasuredWidth(); | 246 return mActivityTestRule.getActivity() |
| 247 .findViewById(R.id.compositor_view_holder) |
| 248 .getMeasuredWidth(); |
227 } | 249 } |
228 })); | 250 })); |
229 | 251 |
230 assertEquals("Viewport width should not have changed when resizing a det
ached " | 252 Assert.assertEquals("Viewport width should not have changed when resizin
g a detached " |
231 + "CompositorViewHolder", | 253 + "CompositorViewHolder", |
232 cvc.getViewportWidthPix(), | 254 cvc.getViewportWidthPix(), oldWidth.get().intValue()); |
233 oldWidth.get().intValue()); | |
234 | 255 |
235 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 256 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
236 @Override | 257 @Override |
237 public void run() { | 258 public void run() { |
238 CompositorViewHolder compositorViewHolder = (CompositorViewHolde
r) getActivity() | 259 CompositorViewHolder compositorViewHolder = |
239 .findViewById(R.id.compositor_view_holder); | 260 (CompositorViewHolder) mActivityTestRule.getActivity().f
indViewById( |
| 261 R.id.compositor_view_holder); |
240 compositorViewHolder.onExitVr(selector.get()); | 262 compositorViewHolder.onExitVr(selector.get()); |
241 } | 263 } |
242 }); | 264 }); |
243 | 265 |
244 CriteriaHelper.pollUiThread(Criteria.equals(testWidth, new Callable<Inte
ger>() { | 266 CriteriaHelper.pollUiThread(Criteria.equals(testWidth, new Callable<Inte
ger>() { |
245 @Override | 267 @Override |
246 public Integer call() { | 268 public Integer call() { |
247 return cvc.getViewportWidthPix(); | 269 return cvc.getViewportWidthPix(); |
248 } | 270 } |
249 })); | 271 })); |
250 } | 272 } |
251 } | 273 } |
OLD | NEW |