Commit dc7c6cbb authored by bsheedy's avatar bsheedy Committed by Commit Bot

Automate WebXR controller and permission tests

Automates the manual tests from https://crbug.com/887551, which relate
to the Daydream controller while in a WebXR immersive session and
permissions, e.g. ensuring that in-use permissions are displayed when
long-pressing the app button.

As a side-effect, updates the test code for waiting on a VR UI element
to change visibility to instead wait for a specific visibility state.

Bug: 887551
Change-Id: I0f845231d2242c711a7b8d6f1465105ec8dc6383
Reviewed-on: https://chromium-review.googlesource.com/c/1318063Reviewed-by: default avatarMichael Thiessen <mthiesse@chromium.org>
Commit-Queue: Brian Sheedy <bsheedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#605452}
parent e734bc5e
......@@ -136,6 +136,23 @@ public class VrShell extends GvrLayout
private ArrayList<Integer> mUiOperationResults;
private ArrayList<Runnable> mUiOperationResultCallbacks;
/**
* A struct-like object for registering UI operations during tests.
*/
@VisibleForTesting
public static class UiOperationData {
// The UiTestOperationType of this operation.
public int actionType;
// The callback to run when the operation completes.
public Runnable resultCallback;
// The timeout of the operation.
public int timeoutMs;
// The UserFriendlyElementName to perform the operation on.
public int elementName;
// The desired visibility status of the element.
public boolean visibility;
}
public VrShell(
ChromeActivity activity, VrShellDelegate delegate, TabModelSelector tabModelSelector) {
super(activity);
......@@ -1233,8 +1250,8 @@ public class VrShell extends GvrLayout
});
}
public void registerUiOperationCallbackForTesting(
int actionType, Runnable resultCallback, int timeoutMs, int elementName) {
public void registerUiOperationCallbackForTesting(UiOperationData operationData) {
int actionType = operationData.actionType;
assert actionType < UiTestOperationType.NUM_UI_TEST_OPERATION_TYPES;
// Fill the ArrayLists if this is the first time the method has been called.
if (mUiOperationResults == null) {
......@@ -1248,14 +1265,15 @@ public class VrShell extends GvrLayout
}
}
mUiOperationResults.set(actionType, UiTestOperationResult.UNREPORTED);
mUiOperationResultCallbacks.set(actionType, resultCallback);
mUiOperationResultCallbacks.set(actionType, operationData.resultCallback);
// In the case of the UI activity quiescence callback type, we need to let the native UI
// know how long to wait before timing out.
if (actionType == UiTestOperationType.UI_ACTIVITY_RESULT) {
nativeSetUiExpectingActivityForTesting(mNativeVrShell, timeoutMs);
} else if (actionType == UiTestOperationType.ELEMENT_VISIBILITY_CHANGE) {
nativeWatchElementForVisibilityChangeForTesting(mNativeVrShell, elementName, timeoutMs);
nativeSetUiExpectingActivityForTesting(mNativeVrShell, operationData.timeoutMs);
} else if (actionType == UiTestOperationType.ELEMENT_VISIBILITY_STATUS) {
nativeWatchElementForVisibilityStatusForTesting(mNativeVrShell,
operationData.elementName, operationData.timeoutMs, operationData.visibility);
}
}
......@@ -1327,8 +1345,8 @@ public class VrShell extends GvrLayout
long nativeVrShell, int quiescenceTimeoutMs);
private native void nativeSaveNextFrameBufferToDiskForTesting(
long nativeVrShell, String filepathBase);
private native void nativeWatchElementForVisibilityChangeForTesting(
long nativeVrShell, int elementName, int timeoutMs);
private native void nativeWatchElementForVisibilityStatusForTesting(
long nativeVrShell, int elementName, int timeoutMs, boolean visibility);
private native void nativeResumeContentRendering(long nativeVrShell);
private native void nativeOnOverlayTextureEmptyChanged(long nativeVrShell, boolean empty);
}
......@@ -78,7 +78,7 @@ public class EmulatedVrController {
}
/**
* Either presses or releases the Daydream controller's touchpad button depending on wheter
* Either presses or releases the Daydream controller's touchpad button depending on whether
* the button is currently pressed or not.
*/
public void sendClickButtonToggleEvent() {
......@@ -93,6 +93,14 @@ public class EmulatedVrController {
getApi().buttonEvent.sendClickButtonEvent();
}
/**
* Either presses or releases the Daydream controller's app button depending on whether the
* button is currently pressed or not.
*/
public void sendAppButtonToggleEvent() {
getApi().buttonEvent.sendAppButtonToggleEvent();
}
/**
* Presses and quickly releases the Daydream controller's app button.
* Or, if the button is already pressed, releases and quickly presses again.
......
......@@ -98,10 +98,8 @@ public class TestVrShellDelegate extends VrShellDelegate {
getVrShell().performKeyboardInputForTesting(inputType, inputString);
}
public void registerUiOperationCallbackForTesting(
int actionType, Runnable resultCallback, int timeoutMs, int elementName) {
getVrShell().registerUiOperationCallbackForTesting(
actionType, resultCallback, timeoutMs, elementName);
public void registerUiOperationCallbackForTesting(VrShell.UiOperationData operationData) {
getVrShell().registerUiOperationCallbackForTesting(operationData);
}
public void saveNextFrameBufferToDiskForTesting(String filepathBase) {
......
......@@ -409,7 +409,7 @@ public class VrBrowserControllerInputTest {
NativeUiUtils.revertToRealInput();
// Wait for the URL bar to re-appear, which we take as a signal that we've exited omnibox
// text input mode.
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.URL, () -> { mController.pressReleaseAppButton(); });
NativeUiUtils.performActionAndWaitForVisibilityStatus(UserFriendlyElementName.URL,
true /* visible */, () -> { mController.pressReleaseAppButton(); });
}
}
......@@ -152,8 +152,8 @@ public class VrBrowserNativeUiTest {
NativeUiUtils.inputBackspace();
}
// Wait for suggestions to change so that our navigation succeeds.
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.SUGGESTION_BOX,
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("version/"); });
NativeUiUtils.inputEnter();
ChromeTabUtils.waitForTabPageLoaded(
......@@ -181,8 +181,9 @@ public class VrBrowserNativeUiTest {
UserFriendlyElementName.OMNIBOX_TEXT_FIELD, new PointF(-0.45f, 0.0f));
// We expect this to delete an "a" instead of anything in "chrome://". Do so and wait for
// the suggestions to appear.
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.SUGGESTION_BOX, () -> { NativeUiUtils.inputBackspace(); });
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputBackspace(); });
NativeUiUtils.inputEnter();
// Navigating automatically appends a "/".
ChromeTabUtils.waitForTabPageLoaded(
......@@ -201,8 +202,8 @@ public class VrBrowserNativeUiTest {
NativeUiUtils.enableMockedKeyboard();
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
// Input text and close the omnibox without committing.
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.SUGGESTION_BOX,
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://version/"); });
NativeUiUtils.clickElementAndWaitForUiQuiescence(
UserFriendlyElementName.OMNIBOX_CLOSE_BUTTON, new PointF());
......@@ -215,8 +216,8 @@ public class VrBrowserNativeUiTest {
for (int i = 0; i < 11; ++i) {
NativeUiUtils.inputBackspace();
}
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.SUGGESTION_BOX,
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visibile */,
() -> { NativeUiUtils.inputString("chrome://version/"); });
NativeUiUtils.inputEnter();
// This should only succeed if the original "chrome://version/" we input is not present -
......@@ -241,8 +242,8 @@ public class VrBrowserNativeUiTest {
// Test that autocompletion works with only one option left.
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
// This should autocomplete to "chrome://version".
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.SUGGESTION_BOX,
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://v"); });
NativeUiUtils.inputEnter();
ChromeTabUtils.waitForTabPageLoaded(
......@@ -252,8 +253,8 @@ public class VrBrowserNativeUiTest {
// Test that autocompletion updates successfully when entering more text.
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.SUGGESTION_BOX,
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://v"); });
NativeUiUtils.inputString("e");
// Since suggestions are already visible, we need to wait for suggestions to update via
......@@ -267,8 +268,8 @@ public class VrBrowserNativeUiTest {
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
// This could be either "chrome://net-export" or "chrome://net-internals", so it shouldn't
// autocomplete to anything.
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.SUGGESTION_BOX,
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://net-"); });
NativeUiUtils.inputEnter();
ChromeTabUtils.waitForTabPageLoaded(
......@@ -277,8 +278,8 @@ public class VrBrowserNativeUiTest {
// Test that autocompletion cancels if a non-matching character is input.
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
// This should autocomplete to "chrome://version".
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.SUGGESTION_BOX,
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://v"); });
NativeUiUtils.inputString("a");
NativeUiUtils.waitNumFrames(NativeUiUtils.NUM_FRAMES_FOR_SUGGESTION_UPDATE);
......
......@@ -693,8 +693,8 @@ public class VrBrowserNavigationTest {
// having suggestions present, waiting for a number of frames before committing seemed
// stable. Adding an operation to listen for suggestion changes would also work, but
// would add some pretty niche test-only code to the native side.
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.SUGGESTION_BOX,
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://version/"); });
NativeUiUtils.inputEnter();
ChromeTabUtils.waitForTabPageLoaded(
......@@ -728,8 +728,8 @@ public class VrBrowserNavigationTest {
private void testSuggestionClickTriggersNavigationImpl() throws InterruptedException {
NativeUiUtils.enableMockedKeyboard();
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.SUGGESTION_BOX,
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://"); });
// Blindly clicking in the center of the suggestion box should end up clicking the middle
// suggestion, which for "chrome://" should be a valid chrome:// URL.
......
......@@ -186,8 +186,8 @@ public class VrInstallUpdateInfoBarTest {
// prompt to become visible before waiting for quiescence.
NativeUiUtils.performActionAndWaitForUiQuiescence(() -> {
try {
NativeUiUtils.performActionAndWaitForVisibilityChange(
UserFriendlyElementName.EXIT_PROMPT,
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.EXIT_PROMPT, true /* visible */,
() -> { NativeUiUtils.clickElement(uiElementToClick, new PointF()); });
} catch (InterruptedException e) {
Assert.fail("Interrupted while waiting for UI visibility change");
......
......@@ -5,8 +5,11 @@
package org.chromium.chrome.browser.vr;
import static org.chromium.chrome.browser.vr.XrTestFramework.PAGE_LOAD_TIMEOUT_S;
import static org.chromium.chrome.browser.vr.XrTestFramework.POLL_TIMEOUT_SHORT_MS;
import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE;
import android.os.Build;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import org.junit.Before;
......@@ -15,16 +18,22 @@ import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
import org.chromium.base.test.params.ParameterSet;
import org.chromium.base.test.params.ParameterizedRunner;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.MinAndroidSdkLevel;
import org.chromium.base.test.util.Restriction;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
import org.chromium.chrome.browser.vr.util.NativeUiUtils;
import org.chromium.chrome.browser.vr.util.PermissionUtils;
import org.chromium.chrome.browser.vr.util.VrTestRuleUtils;
import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
import org.chromium.net.test.EmbeddedTestServer;
import java.util.List;
import java.util.concurrent.Callable;
......@@ -93,4 +102,72 @@ public class WebXrVrTabTest {
framework.executeStepAndWait("stepCheckFrameDataWhileNonFocusedTab()");
framework.endTest();
}
/**
* Tests that permissions in use by other tabs are shown while in a WebXR for VR immersive
* session.
*/
@Test
@MediumTest
@Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE)
@CommandLineFlags
.Remove({"enable-webvr"})
@CommandLineFlags.Add({"enable-features=WebXR"})
public void testPermissionsInOtherTab() throws InterruptedException {
testPermissionsInOtherTabImpl(false /* incognito */);
}
@Test
@MediumTest
@Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE)
@CommandLineFlags
.Remove({"enable-webvr"})
@CommandLineFlags.Add({"enable-features=WebXR"})
public void testPermissionsInOtherTabIncognito() throws InterruptedException {
testPermissionsInOtherTabImpl(true /* incognito */);
}
private void testPermissionsInOtherTabImpl(boolean incognito) throws InterruptedException {
EmbeddedTestServer server = mTestRule.getTestServer();
boolean teardownServer = false;
if (server == null) {
server = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
teardownServer = true;
}
mWebXrVrTestFramework.loadUrlAndAwaitInitialization(
server.getURL(WebXrVrTestFramework.getEmbeddedServerPathForHtmlTestFile(
"generic_webxr_permission_page")),
PAGE_LOAD_TIMEOUT_S);
// Be sure to store the stream we're given so that the permission is actually in use, as
// otherwise the toast doesn't show up since another tab isn't actually using the
// permission.
WebXrVrTestFramework.runJavaScriptOrFail(
"requestPermission({audio:true}, true /* storeValue */)", POLL_TIMEOUT_SHORT_MS,
mTestRule.getWebContents());
PermissionUtils.waitForPermissionPrompt();
PermissionUtils.acceptPermissionPrompt();
WebXrVrTestFramework.waitOnJavaScriptStep(mTestRule.getWebContents());
if (incognito) {
ThreadUtils.runOnUiThreadBlocking(() -> {
mTestRule.getActivity()
.getTabCreator(true /* incognito */)
.launchUrl("about:blank", TabLaunchType.FROM_LINK);
});
} else {
mTestRule.loadUrlInNewTab("about:blank");
}
mWebXrVrTestFramework.loadUrlAndAwaitInitialization(
WebXrVrTestFramework.getFileUrlForHtmlTestFile("generic_webxr_page"),
PAGE_LOAD_TIMEOUT_S);
mWebXrVrTestFramework.enterSessionWithUserGestureOrFail(mTestRule.getWebContents());
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, () -> {});
if (teardownServer) {
server.stopAndDestroyServer();
}
}
}
......@@ -43,6 +43,7 @@ import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.vr.rules.VrSettingsFile;
import org.chromium.chrome.browser.vr.rules.XrActivityRestriction;
import org.chromium.chrome.browser.vr.util.NativeUiUtils;
import org.chromium.chrome.browser.vr.util.NfcSimUtils;
import org.chromium.chrome.browser.vr.util.VrSettingsServiceUtils;
import org.chromium.chrome.browser.vr.util.VrTestRuleUtils;
......@@ -485,4 +486,24 @@ public class WebXrVrTransitionTest {
mWebXrVrTestFramework.executeStepAndWait("stepAfterImmersive()");
mWebXrVrTestFramework.endTest();
}
/**
* Tests that the "Press app button to exit" toast appears when entering an immersive WebXR for
* VR session with Daydream View paired.
*/
@Test
@MediumTest
@Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE)
@CommandLineFlags
.Remove({"enable-webvr"})
@CommandLineFlags.Add({"enable-features=WebXR"})
@XrActivityRestriction({XrActivityRestriction.SupportedActivity.CTA})
public void testAppButtonExitToast() throws InterruptedException {
mWebXrVrTestFramework.loadUrlAndAwaitInitialization(
WebXrVrTestFramework.getFileUrlForHtmlTestFile("generic_webxr_page"),
PAGE_LOAD_TIMEOUT_S);
mWebXrVrTestFramework.enterSessionWithUserGestureOrFail();
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.APP_BUTTON_EXIT_TOAST, true /* visible*/, () -> {});
}
}
......@@ -223,14 +223,16 @@ public class NativeUiUtils {
throws InterruptedException {
final TestVrShellDelegate instance = TestVrShellDelegate.getInstance();
final CountDownLatch resultLatch = new CountDownLatch(1);
final VrShell.UiOperationData operationData = new VrShell.UiOperationData();
operationData.actionType = UiTestOperationType.UI_ACTIVITY_RESULT;
operationData.resultCallback = () -> {
resultLatch.countDown();
};
operationData.timeoutMs = DEFAULT_UI_QUIESCENCE_TIMEOUT_MS;
// Run on the UI thread to prevent issues with registering a new callback before
// ReportUiOperationResultForTesting has finished.
ThreadUtils.runOnUiThreadBlocking(() -> {
instance.registerUiOperationCallbackForTesting(
UiTestOperationType.UI_ACTIVITY_RESULT, () -> {
resultLatch.countDown();
}, DEFAULT_UI_QUIESCENCE_TIMEOUT_MS, 0 /* unused */);
});
ThreadUtils.runOnUiThreadBlocking(
() -> { instance.registerUiOperationCallbackForTesting(operationData); });
action.run();
// Wait for any outstanding animations to finish.
......@@ -243,32 +245,38 @@ public class NativeUiUtils {
}
/**
* Runs the given Runnable and waits until the specified element changes its visibility.
* Runs the given Runnable and waits until the specified element matches the requested
* visibility.
*
* @param elementName The UserFriendlyElementName to wait on to change visibility.
* @param status The visibility status to wait for.
* @param action A Runnable containing the action to perform.
*/
public static void performActionAndWaitForVisibilityChange(
final int elementName, Runnable action) throws InterruptedException {
public static void performActionAndWaitForVisibilityStatus(final int elementName,
final boolean visible, Runnable action) throws InterruptedException {
final TestVrShellDelegate instance = TestVrShellDelegate.getInstance();
final CountDownLatch resultLatch = new CountDownLatch(1);
final VrShell.UiOperationData operationData = new VrShell.UiOperationData();
operationData.actionType = UiTestOperationType.ELEMENT_VISIBILITY_STATUS;
operationData.resultCallback = () -> {
resultLatch.countDown();
};
operationData.timeoutMs = DEFAULT_UI_QUIESCENCE_TIMEOUT_MS;
operationData.elementName = elementName;
operationData.visibility = visible;
// Run on the UI thread to prevent issues with registering a new callback before
// ReportUiOperationResultForTesting has finished.
ThreadUtils.runOnUiThreadBlocking(() -> {
instance.registerUiOperationCallbackForTesting(
UiTestOperationType.ELEMENT_VISIBILITY_CHANGE, () -> {
resultLatch.countDown();
}, DEFAULT_UI_QUIESCENCE_TIMEOUT_MS, elementName);
});
ThreadUtils.runOnUiThreadBlocking(
() -> { instance.registerUiOperationCallbackForTesting(operationData); });
action.run();
// Wait for the result to be reported.
resultLatch.await();
int result = instance.getLastUiOperationResultForTesting(
UiTestOperationType.ELEMENT_VISIBILITY_CHANGE);
UiTestOperationType.ELEMENT_VISIBILITY_STATUS);
Assert.assertEquals("UI reported non-visibility-changed result '"
+ uiTestOperationResultToString(result) + "'",
UiTestOperationResult.VISIBILITY_CHANGE, result);
UiTestOperationResult.VISIBILITY_MATCH, result);
}
/**
......@@ -310,13 +318,16 @@ public class NativeUiUtils {
final TestVrShellDelegate instance = TestVrShellDelegate.getInstance();
final CountDownLatch resultLatch = new CountDownLatch(1);
final VrShell.UiOperationData operationData = new VrShell.UiOperationData();
operationData.actionType = UiTestOperationType.FRAME_BUFFER_DUMPED;
operationData.resultCallback = () -> {
resultLatch.countDown();
};
// Run on the UI thread to prevent issues with registering a new callback before
// ReportUiOperationResultForTesting has finished.
ThreadUtils.runOnUiThreadBlocking(() -> {
instance.registerUiOperationCallbackForTesting(UiTestOperationType.FRAME_BUFFER_DUMPED,
() -> { resultLatch.countDown(); }, 0 /* unused */, 0 /* unused */);
});
ThreadUtils.runOnUiThreadBlocking(
() -> { instance.registerUiOperationCallbackForTesting(operationData); });
instance.saveNextFrameBufferToDiskForTesting(filepathBase);
resultLatch.await();
}
......@@ -372,10 +383,10 @@ public class NativeUiUtils {
return "Timeout (UI activity not started)";
case UiTestOperationResult.TIMEOUT_NO_END:
return "Timeout (UI activity not stopped)";
case UiTestOperationResult.VISIBILITY_CHANGE:
return "Visibility change";
case UiTestOperationResult.TIMEOUT_NO_CHANGE:
return "Timeout (Element visibility did not change)";
case UiTestOperationResult.VISIBILITY_MATCH:
return "Visibility match";
case UiTestOperationResult.TIMEOUT_NO_VISIBILITY_MATCH:
return "Timeout (Element visibility did not match)";
default:
return "Unknown result";
}
......
......@@ -1266,19 +1266,21 @@ void VrShell::SaveNextFrameBufferToDiskForTesting(
base::android::ConvertJavaStringToUTF8(env, filepath_base)));
}
void VrShell::WatchElementForVisibilityChangeForTesting(
void VrShell::WatchElementForVisibilityStatusForTesting(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint element_name,
jint timeout_ms) {
jint timeout_ms,
jboolean visibility) {
VisibilityChangeExpectation visibility_expectation;
visibility_expectation.element_name =
static_cast<UserFriendlyElementName>(element_name);
visibility_expectation.timeout_ms = timeout_ms;
visibility_expectation.visibility = visibility;
PostToGlThread(
FROM_HERE,
base::BindOnce(
&BrowserRenderer::WatchElementForVisibilityChangeForTesting,
&BrowserRenderer::WatchElementForVisibilityStatusForTesting,
gl_thread_->GetBrowserRenderer(), visibility_expectation));
}
......
......@@ -285,11 +285,12 @@ class VrShell : device::GvrGamepadDataProvider,
const base::android::JavaParamRef<jobject>& obj,
jstring filepath_base);
void WatchElementForVisibilityChangeForTesting(
void WatchElementForVisibilityStatusForTesting(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint element_name,
jint timeout_ms);
jint timeout_ms,
jboolean visibility);
void ReportUiOperationResultForTesting(UiTestOperationType action_type,
UiTestOperationResult result);
......
......@@ -231,7 +231,7 @@ void BrowserRenderer::SaveNextFrameBufferToDiskForTesting(
frame_buffer_dump_filepath_base_ = filepath_base;
}
void BrowserRenderer::WatchElementForVisibilityChangeForTesting(
void BrowserRenderer::WatchElementForVisibilityStatusForTesting(
VisibilityChangeExpectation visibility_expectation) {
DCHECK(ui_visibility_state_ == nullptr) << "Attempted to watch a UI element "
"for visibility changes with one "
......@@ -240,8 +240,7 @@ void BrowserRenderer::WatchElementForVisibilityChangeForTesting(
ui_visibility_state_->timeout_ms =
base::TimeDelta::FromMilliseconds(visibility_expectation.timeout_ms);
ui_visibility_state_->element_to_watch = visibility_expectation.element_name;
ui_visibility_state_->initially_visible = ui_->GetElementVisibilityForTesting(
ui_visibility_state_->element_to_watch);
ui_visibility_state_->expected_visibile = visibility_expectation.visibility;
}
void BrowserRenderer::AcceptDoffPromptForTesting() {
......@@ -405,13 +404,13 @@ void BrowserRenderer::ReportElementVisibilityStatusForTesting(
base::TimeDelta time_since_start =
current_time - ui_visibility_state_->start_time;
if (ui_->GetElementVisibilityForTesting(
ui_visibility_state_->element_to_watch) !=
ui_visibility_state_->initially_visible) {
ui_visibility_state_->element_to_watch) ==
ui_visibility_state_->expected_visibile) {
ReportElementVisibilityResultForTesting(
UiTestOperationResult::kVisibilityChange);
UiTestOperationResult::kVisibilityMatch);
} else if (time_since_start > ui_visibility_state_->timeout_ms) {
ReportElementVisibilityResultForTesting(
UiTestOperationResult::kTimeoutNoChange);
UiTestOperationResult::kTimeoutNoVisibilityMatch);
}
}
......@@ -419,7 +418,7 @@ void BrowserRenderer::ReportElementVisibilityResultForTesting(
UiTestOperationResult result) {
ui_visibility_state_ = nullptr;
browser_->ReportUiOperationResultForTesting(
UiTestOperationType::kElementVisibilityChange, result);
UiTestOperationType::kElementVisibilityStatus, result);
}
} // namespace vr
......@@ -74,7 +74,7 @@ class VR_EXPORT BrowserRenderer : public SchedulerBrowserRendererInterface {
void SetUiExpectingActivityForTesting(
UiTestActivityExpectation ui_expectation);
void SaveNextFrameBufferToDiskForTesting(std::string filepath_base);
void WatchElementForVisibilityChangeForTesting(
void WatchElementForVisibilityStatusForTesting(
VisibilityChangeExpectation visibility_expectation);
void AcceptDoffPromptForTesting();
void ConnectPresentingService(
......
......@@ -77,6 +77,12 @@ UiElementName UserFriendlyElementNameToUiElementName(
return kOmniboxTextField;
case UserFriendlyElementName::kOmniboxCloseButton:
return kOmniboxCloseButton;
case UserFriendlyElementName::kAppButtonExitToast:
return kWebVrExclusiveScreenToast;
case UserFriendlyElementName::kWebXrAudioIndicator:
return kWebVrAudioCaptureIndicator;
case UserFriendlyElementName::kWebXrHostedContent:
return kWebVrHostedUiContent;
default:
NOTREACHED();
return kNone;
......
......@@ -30,6 +30,12 @@ enum class UserFriendlyElementName : int {
kOmniboxTextField, // The Omnibox's text input field that shows up when the
// URL bar is clicked.
kOmniboxCloseButton, // The button the exits the omnibox's text input mode.
kAppButtonExitToast, // The "Press app button to exit" toast when entring
// an immersive session.
kWebXrAudioIndicator, // Toast in WebXR indicating the microphone permission
// is in use.
kWebXrHostedContent, // Hosted content in a WebXR immersive session, e.g.
// permission prompts.
};
// These are the types of actions that Java can request callbacks for once
......@@ -38,7 +44,8 @@ enum class UserFriendlyElementName : int {
enum class UiTestOperationType : int {
kUiActivityResult = 0, // Result after being told to wait for quiescence
kFrameBufferDumped, // Signal that the frame buffer was dumped to disk
kElementVisibilityChange, // Signal that a watched element changed visibility
kElementVisibilityStatus, // Signal that a watched element matches the
// desired visibility.
kNumUiTestOperationTypes, // Must be last
};
......@@ -49,10 +56,10 @@ enum class UiTestOperationResult : int {
kQuiescent, // The UI reached quiescence (kUiActivityResult)
kTimeoutNoStart, // Timed out, UI activity never started (kUiActivityResult)
kTimeoutNoEnd, // Timed out, UI activity never finished (kUiActivityResult)
kVisibilityChange, // The watched element's visibility changed
// (kElementVisibilityChange)
kTimeoutNoChange, // Timed out, visibility never changed
// (kElementVisibilityChange)
kVisibilityMatch, // The watched element's visibility matches the expectation
// (kElementVisibilityStatus)
kTimeoutNoVisibilityMatch, // Timed out, visibility doesn't match expectation
// (kElementVisibilityStatus)
};
// These are used to specify what type of action should be performed on a UI
......@@ -100,6 +107,7 @@ struct UiTestActivityExpectation {
struct VisibilityChangeExpectation {
UserFriendlyElementName element_name;
int timeout_ms;
bool visibility;
};
// Holds all the information necessary to keep track of and report whether the
......@@ -119,8 +127,8 @@ struct UiTestState {
struct UiVisibilityState {
// The UI element being watched.
UserFriendlyElementName element_to_watch = UserFriendlyElementName::kUrl;
// The initial visibility state of the element.
bool initially_visible = false;
// The desired visibility state of the element.
bool expected_visibile = false;
// How long to wait for a visibility change before timing out.
base::TimeDelta timeout_ms = base::TimeDelta::Min();
// The point in time that we started watching for visibility changes.
......
<!doctype html>
<!--
WebXR page with the ability to request permissions.
-->
<html>
<head>
<link rel="stylesheet" type="text/css" href="../resources/webxr_e2e.css">
</head>
<body>
<canvas id="webgl-canvas"></canvas>
<script src="../../../../../../third_party/WebKit/LayoutTests/resources/testharness.js"></script>
<script src="../resources/webxr_e2e.js"></script>
<script src="../resources/webxr_boilerplate.js"></script>
<script>
var lastPermissionRequestSucceeded = false;
var storedValue = null;
function requestPermission(permissionObject, storeValue) {
navigator.getUserMedia(permissionObject,
(val) => {
lastPermissionRequestSucceeded = true;
if (storeValue) {
storedValue = val;
}
finishJavaScriptStep();
},
() => {
lastPermissionRequestSucceeded = false;
finishJavaScriptStep();
});
}
</script>
</body>
</html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment