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