chromium/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTestFramework.java

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.vr;

import androidx.annotation.IntDef;

import org.chromium.chrome.browser.vr.util.PermissionUtils;
import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.content_public.browser.WebContents;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/** Extension of VrTestFramework containing WebXR for VR-specific functionality. */
public class WebXrVrTestFramework extends WebXrTestFramework {
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
        PERMISSION_PROMPT_ACTION_DO_NOTHING,
        PERMISSION_PROMPT_ACTION_ALLOW,
        PERMISSION_PROMPT_ACTION_DENY
    })
    public @interface PermissionPromptAction {}

    public static final int PERMISSION_PROMPT_ACTION_DO_NOTHING = 0;
    public static final int PERMISSION_PROMPT_ACTION_ALLOW = 1;
    public static final int PERMISSION_PROMPT_ACTION_DENY = 2;

    protected @PermissionPromptAction int mPermissionPromptAction = PERMISSION_PROMPT_ACTION_ALLOW;

    public WebXrVrTestFramework(ChromeActivityTestRule rule) {
        super(rule);
    }

    /**
     * Set the default action to be taken when the permission prompt is displayed.
     *
     * @param action The action to take on a permission prompt.
     */
    public void setPermissionPromptAction(@PermissionPromptAction int action) {
        mPermissionPromptAction = action;
    }

    /**
     * VR-specific implementation of enterSessionWithUserGesture that includes a workaround for
     * receiving broadcasts late.
     *
     * @param webContents The WebContents for the tab to enter the VR session in.
     */
    @Override
    public void enterSessionWithUserGesture(WebContents webContents) {
        super.enterSessionWithUserGesture(webContents);

        if (!shouldExpectPermissionPrompt()) return;
        PermissionUtils.waitForPermissionPrompt();
        if (mPermissionPromptAction == PERMISSION_PROMPT_ACTION_ALLOW) {
            PermissionUtils.acceptPermissionPrompt();
        } else if (mPermissionPromptAction == PERMISSION_PROMPT_ACTION_DENY) {
            PermissionUtils.denyPermissionPrompt();
        }
    }

    /**
     * 'enterSessionWithUserGestureOrFail' is specific to immersive sessions. This method does the
     * same, but for the magic window session.
     */
    public void enterMagicWindowSessionWithUserGestureOrFail() {
        runJavaScriptOrFail(
                "sessionTypeToRequest = sessionTypes.MAGIC_WINDOW", POLL_TIMEOUT_SHORT_MS);
        enterSessionWithUserGesture();
        pollJavaScriptBooleanOrFail(
                "sessionInfos[sessionTypes.MAGIC_WINDOW].currentSession != null",
                POLL_TIMEOUT_LONG_MS);
    }

    /**
     * WebXR for VR-specific implementation of enterSessionWithUserGestureOrFail.
     *
     * @param webContents The WebContents of the tab to enter the immersive session in.
     */
    @Override
    public void enterSessionWithUserGestureOrFail(
            WebContents webContents, boolean needsCameraPermission) {
        runJavaScriptOrFail(
                "sessionTypeToRequest = sessionTypes.IMMERSIVE", POLL_TIMEOUT_LONG_MS, webContents);

        boolean willPromptForCamera =
                needsCameraPermission && permissionRequestWouldTriggerPrompt("camera");

        enterSessionWithUserGesture(webContents);

        if (willPromptForCamera) {
            PermissionUtils.waitForPermissionPrompt();
            PermissionUtils.acceptPermissionPrompt();
        }

        pollJavaScriptBooleanOrFail(
                "sessionInfos[sessionTypes.IMMERSIVE].currentSession != null",
                POLL_TIMEOUT_LONG_MS,
                webContents);
    }

    /**
     * End an immersive session and wait until that session has actually ended.
     *
     * @param webContents The WebContents for the tab to end the session in.
     */
    @Override
    public void endSession(WebContents webContents) {
        // Use a long timeout for session.end(), this can unexpectedly take more than
        // a second. TODO(crbug.com/40653025): investigate why.
        runJavaScriptOrFail(
                "sessionInfos[sessionTypes.IMMERSIVE].currentSession.end()",
                POLL_TIMEOUT_LONG_MS,
                webContents);

        // Wait for the session to end before proceeding with followup tests.
        pollJavaScriptBooleanOrFail(
                "sessionInfos[sessionTypes.IMMERSIVE].currentSession == null",
                POLL_TIMEOUT_LONG_MS,
                webContents);
    }

    /**
     * Checks whether an immersive VR session would trigger the permission prompt.
     *
     * @param webContents The WebContents to check in.
     * @return True if an immersive VR session request would trigger the permission prompt,
     *     otherwise false.
     */
    @Override
    public boolean shouldExpectPermissionPrompt(WebContents webContents) {
        return shouldExpectPermissionPrompt("sessionTypeToRequest", webContents);
    }
}