1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.vr;
6 
7 import androidx.annotation.IntDef;
8 
9 import org.junit.Assert;
10 
11 import org.chromium.chrome.browser.vr.rules.VrTestRule;
12 import org.chromium.chrome.browser.vr.util.PermissionUtils;
13 import org.chromium.chrome.browser.vr.util.VrShellDelegateUtils;
14 import org.chromium.chrome.test.ChromeActivityTestRule;
15 import org.chromium.content_public.browser.WebContents;
16 
17 import java.lang.annotation.Retention;
18 import java.lang.annotation.RetentionPolicy;
19 
20 /**
21  * Extension of VrTestFramework containing WebXR for VR-specific functionality.
22  */
23 public class WebXrVrTestFramework extends WebXrTestFramework {
24     @Retention(RetentionPolicy.SOURCE)
25     @IntDef({PERMISSION_PROMPT_ACTION_DO_NOTHING, PERMISSION_PROMPT_ACTION_ALLOW,
26             PERMISSION_PROMPT_ACTION_DENY})
27     public @interface PermissionPromptAction {}
28 
29     public static final int PERMISSION_PROMPT_ACTION_DO_NOTHING = 0;
30     public static final int PERMISSION_PROMPT_ACTION_ALLOW = 1;
31     public static final int PERMISSION_PROMPT_ACTION_DENY = 2;
32 
33     @PermissionPromptAction
34     protected int mPermissionPromptAction = PERMISSION_PROMPT_ACTION_ALLOW;
35 
WebXrVrTestFramework(ChromeActivityTestRule rule)36     public WebXrVrTestFramework(ChromeActivityTestRule rule) {
37         super(rule);
38         if (!TestVrShellDelegate.isOnStandalone()) {
39             Assert.assertFalse("Test started in VR", VrShellDelegate.isInVr());
40         }
41     }
42 
43     /**
44      * Set the default action to be taken when the permission prompt is displayed.
45      *
46      * @param action The action to take on a permission prompt.
47      */
setPermissionPromptAction(@ermissionPromptAction int action)48     public void setPermissionPromptAction(@PermissionPromptAction int action) {
49         mPermissionPromptAction = action;
50     }
51 
52     /**
53      * VR-specific implementation of enterSessionWithUserGesture that includes a workaround for
54      * receiving broadcasts late.
55      *
56      * @param webContents The WebContents for the tab to enter the VR session in.
57      */
58     @Override
enterSessionWithUserGesture(WebContents webContents)59     public void enterSessionWithUserGesture(WebContents webContents) {
60         // TODO(https://crbug.com/762724): Remove this workaround when the issue with being resumed
61         // before receiving the VR broadcast is fixed on VrCore's end.
62         // However, we don't want to enable the workaround if the DON flow is enabled, as that
63         // causes issues.
64         if (!((VrTestRule) getRule()).isDonEnabled()) {
65             VrShellDelegateUtils.getDelegateInstance().setExpectingBroadcast();
66         }
67         super.enterSessionWithUserGesture(webContents);
68 
69         if (!shouldExpectPermissionPrompt()) return;
70         PermissionUtils.waitForPermissionPrompt();
71         if (mPermissionPromptAction == PERMISSION_PROMPT_ACTION_ALLOW) {
72             PermissionUtils.acceptPermissionPrompt();
73         } else if (mPermissionPromptAction == PERMISSION_PROMPT_ACTION_DENY) {
74             PermissionUtils.denyPermissionPrompt();
75         }
76     }
77 
78     /**
79      * 'enterSessionWithUserGestureOrFail' is specific to immersive sessions. This method does the
80      * same, but for the magic window session.
81      */
enterMagicWindowSessionWithUserGestureOrFail()82     public void enterMagicWindowSessionWithUserGestureOrFail() {
83         runJavaScriptOrFail(
84                 "sessionTypeToRequest = sessionTypes.MAGIC_WINDOW", POLL_TIMEOUT_SHORT_MS);
85         enterSessionWithUserGesture();
86         pollJavaScriptBooleanOrFail(
87                 "sessionInfos[sessionTypes.MAGIC_WINDOW].currentSession != null",
88                 POLL_TIMEOUT_LONG_MS);
89     }
90 
91     /**
92      * WebXR for VR-specific implementation of enterSessionWithUserGestureOrFail.
93      *
94      * @param webContents The WebContents of the tab to enter the immersive session in.
95      */
96     @Override
enterSessionWithUserGestureOrFail(WebContents webContents)97     public void enterSessionWithUserGestureOrFail(WebContents webContents) {
98         runJavaScriptOrFail(
99                 "sessionTypeToRequest = sessionTypes.IMMERSIVE", POLL_TIMEOUT_LONG_MS, webContents);
100         enterSessionWithUserGesture(webContents);
101 
102         pollJavaScriptBooleanOrFail("sessionInfos[sessionTypes.IMMERSIVE].currentSession != null",
103                 POLL_TIMEOUT_LONG_MS, webContents);
104         Assert.assertTrue("Immersive session started, but VR Shell not in presentation mode",
105                 TestVrShellDelegate.getVrShellForTesting().getWebVrModeEnabled());
106     }
107 
108     /**
109      * End an immersive session and wait until that session has actually ended.
110      *
111      * @param webContents The WebContents for the tab to end the session in.
112      */
113     @Override
endSession(WebContents webContents)114     public void endSession(WebContents webContents) {
115         // Use a long timeout for session.end(), this can unexpectedly take more than
116         // a second. TODO(https://crbug.com/1014159): investigate why.
117         runJavaScriptOrFail("sessionInfos[sessionTypes.IMMERSIVE].currentSession.end()",
118                 POLL_TIMEOUT_LONG_MS, webContents);
119 
120         // Wait for the session to end before proceeding with followup tests.
121         pollJavaScriptBooleanOrFail("sessionInfos[sessionTypes.IMMERSIVE].currentSession == null",
122                 POLL_TIMEOUT_LONG_MS, webContents);
123     }
124 
125     /**
126      * Checks whether an immersive VR session would trigger the permission prompt.
127      *
128      * @param webContents The WebContents to check in.
129      * @return True if an immersive VR session request would trigger the permission prompt,
130      *         otherwise
131      *     false.
132      */
133     @Override
shouldExpectPermissionPrompt(WebContents webContents)134     public boolean shouldExpectPermissionPrompt(WebContents webContents) {
135         return shouldExpectPermissionPrompt("sessionTypeToRequest", webContents);
136     }
137 }
138