Commit 8a3c2e92 authored by bsheedy's avatar bsheedy Committed by Commit Bot

Add test support for WebVR auto presentation

Adds test utility code that allows Chrome to think it's received an intent
from a trusted app. This allows us to test Chrome's ability to auto present
WebVR content when given a link from a trusted app (or test its rejection
if the app is not trusted). Also adds one test using the new code.

Also contains a drive-by fix for flakiness in
WebVrTransitionTest#testNfcFiresVrdisplayactivate caused by a race
condition when adding the vrdisplayactivate listener.

Bug: 746086
Change-Id: Ic6b55df18d915a4e36b36ca43bd11f4c773f6d33
Reviewed-on: https://chromium-review.googlesource.com/578527
Commit-Queue: Brian Sheedy <bsheedy@chromium.org>
Reviewed-by: default avatarMichael Thiessen <mthiesse@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488408}
parent 9694c119
...@@ -556,6 +556,7 @@ if (enable_vr) { ...@@ -556,6 +556,7 @@ if (enable_vr) {
"javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java", "javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java",
"javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrCoreVersionCheckerImpl.java", "javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrCoreVersionCheckerImpl.java",
"javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrDaydreamApi.java", "javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrDaydreamApi.java",
"javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrIntentHandler.java",
"javatests/src/org/chromium/chrome/browser/vr_shell/nfc_apk/SimNfcActivity.java", "javatests/src/org/chromium/chrome/browser/vr_shell/nfc_apk/SimNfcActivity.java",
"javatests/src/org/chromium/chrome/browser/vr_shell/util/CardboardUtils.java", "javatests/src/org/chromium/chrome/browser/vr_shell/util/CardboardUtils.java",
"javatests/src/org/chromium/chrome/browser/vr_shell/util/NfcSimUtils.java", "javatests/src/org/chromium/chrome/browser/vr_shell/util/NfcSimUtils.java",
...@@ -590,6 +591,7 @@ if (enable_vr) { ...@@ -590,6 +591,7 @@ if (enable_vr) {
"//third_party/android_support_test_runner:runner_java", "//third_party/android_support_test_runner:runner_java",
"//third_party/android_tools:android_support_v7_appcompat_java", "//third_party/android_tools:android_support_v7_appcompat_java",
"//third_party/android_tools:android_support_v7_recyclerview_java", "//third_party/android_tools:android_support_v7_recyclerview_java",
"//third_party/custom_tabs_client:custom_tabs_support_java",
"//third_party/gvr-android-sdk:controller_test_api_java", "//third_party/gvr-android-sdk:controller_test_api_java",
"//third_party/gvr-android-sdk:gvr_common_java", "//third_party/gvr-android-sdk:gvr_common_java",
"//third_party/junit", "//third_party/junit",
......
...@@ -36,11 +36,17 @@ public interface VrDaydreamApi { ...@@ -36,11 +36,17 @@ public interface VrDaydreamApi {
Intent createVrIntent(final ComponentName componentName); Intent createVrIntent(final ComponentName componentName);
/** /**
* Launch the given Intent in VR mode. * Launch the given PendingIntent in VR mode.
* @return false if unable to acquire DaydreamApi instance. * @return false if unable to acquire DaydreamApi instance.
*/ */
boolean launchInVr(final PendingIntent pendingIntent); boolean launchInVr(final PendingIntent pendingIntent);
/**
* Launch the given Intent in VR mode.
* @return false if unable to acquire DaydreamApi instance.
*/
boolean launchInVr(final Intent intent);
/** /**
* @param requestCode The requestCode used by startActivityForResult. * @param requestCode The requestCode used by startActivityForResult.
* @param intent The data passed to VrCore as part of the exit request. * @param intent The data passed to VrCore as part of the exit request.
......
...@@ -67,6 +67,15 @@ public class VrDaydreamApiImpl implements VrDaydreamApi { ...@@ -67,6 +67,15 @@ public class VrDaydreamApiImpl implements VrDaydreamApi {
return true; return true;
} }
@Override
public boolean launchInVr(final Intent intent) {
DaydreamApi daydreamApi = DaydreamApi.create(mContext);
if (daydreamApi == null) return false;
daydreamApi.launchInVr(intent);
daydreamApi.close();
return true;
}
@Override @Override
public boolean exitFromVr(int requestCode, final Intent intent) { public boolean exitFromVr(int requestCode, final Intent intent) {
Activity activity = WindowAndroid.activityFromContext(mContext); Activity activity = WindowAndroid.activityFromContext(mContext);
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// 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_shell;
import android.content.Intent;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.IntentHandler;
// TODO(bsheedy): Move more VR intent related code into here even if it doesn't need
// to be overridden for testing
/**
* Handles VR intent checking for VrShellDelegate.
*/
public class VrIntentHandler {
private static VrIntentHandler sInstance;
private static final String DAYDREAM_HOME_PACKAGE = "com.google.android.vr.home";
/**
* Determines whether the given intent is a VR intent from Daydream Home.
* @param intent The intent to check
* @return Whether the intent is a VR intent and originated from Daydream Home
*/
public boolean isTrustedDaydreamIntent(Intent intent) {
return VrShellDelegate.isVrIntent(intent)
&& IntentHandler.isIntentFromTrustedApp(intent, DAYDREAM_HOME_PACKAGE);
}
/**
* Gets the static VrIntentHandler instance.
* @return The VrIntentHandler instance
*/
public static VrIntentHandler getInstance() {
if (sInstance == null) {
sInstance = new VrIntentHandler();
}
return sInstance;
}
@VisibleForTesting
public static void setInstanceForTesting(VrIntentHandler handler) {
sInstance = handler;
}
}
...@@ -46,7 +46,6 @@ import org.chromium.chrome.R; ...@@ -46,7 +46,6 @@ import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.customtabs.CustomTabActivity;
import org.chromium.chrome.browser.help.HelpAndFeedback; import org.chromium.chrome.browser.help.HelpAndFeedback;
import org.chromium.chrome.browser.infobar.InfoBarIdentifier; import org.chromium.chrome.browser.infobar.InfoBarIdentifier;
...@@ -95,8 +94,7 @@ public class VrShellDelegate ...@@ -95,8 +94,7 @@ public class VrShellDelegate
@IntDef({VR_NOT_AVAILABLE, VR_CARDBOARD, VR_DAYDREAM}) @IntDef({VR_NOT_AVAILABLE, VR_CARDBOARD, VR_DAYDREAM})
private @interface VrSupportLevel {} private @interface VrSupportLevel {}
private static final String DAYDREAM_VR_EXTRA = "android.intent.extra.VR_LAUNCH"; public static final String DAYDREAM_VR_EXTRA = "android.intent.extra.VR_LAUNCH";
private static final String DAYDREAM_HOME_PACKAGE = "com.google.android.vr.home";
static final String VR_FRE_INTENT_EXTRA = "org.chromium.chrome.browser.vr_shell.VR_FRE"; static final String VR_FRE_INTENT_EXTRA = "org.chromium.chrome.browser.vr_shell.VR_FRE";
// Linter and formatter disagree on how the line below should be formatted. // Linter and formatter disagree on how the line below should be formatted.
...@@ -843,11 +841,6 @@ public class VrShellDelegate ...@@ -843,11 +841,6 @@ public class VrShellDelegate
sBlackOverlayView = null; sBlackOverlayView = null;
} }
private static boolean isTrustedDaydreamIntent(Intent intent) {
return isVrIntent(intent)
&& IntentHandler.isIntentFromTrustedApp(intent, DAYDREAM_HOME_PACKAGE);
}
private void onAutopresentIntent() { private void onAutopresentIntent() {
// Autopresent intents are only expected from trusted first party apps while // Autopresent intents are only expected from trusted first party apps while
// we're not in vr. // we're not in vr.
...@@ -878,7 +871,7 @@ public class VrShellDelegate ...@@ -878,7 +871,7 @@ public class VrShellDelegate
VrShellDelegate instance = getInstance(activity); VrShellDelegate instance = getInstance(activity);
if (instance == null) return; if (instance == null) return;
instance.onVrIntent(); instance.onVrIntent();
if (isTrustedDaydreamIntent(intent)) { if (VrIntentHandler.getInstance().isTrustedDaydreamIntent(intent)) {
if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEBVR_AUTOPRESENT) if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEBVR_AUTOPRESENT)
|| !activitySupportsPresentation(activity) || !activitySupportsPresentation(activity)
|| !isVrShellEnabled(instance.mVrSupportLevel)) { || !isVrShellEnabled(instance.mVrSupportLevel)) {
...@@ -893,7 +886,7 @@ public class VrShellDelegate ...@@ -893,7 +886,7 @@ public class VrShellDelegate
* This is called when ChromeTabbedActivity gets a new intent before native is initialized. * This is called when ChromeTabbedActivity gets a new intent before native is initialized.
*/ */
public static void maybeHandleVrIntentPreNative(ChromeActivity activity, Intent intent) { public static void maybeHandleVrIntentPreNative(ChromeActivity activity, Intent intent) {
if (isTrustedDaydreamIntent(intent)) { if (VrIntentHandler.getInstance().isTrustedDaydreamIntent(intent)) {
// We add a black overlay view so that we can show black while the VR UI is loading. // We add a black overlay view so that we can show black while the VR UI is loading.
// Note that this alone isn't sufficient to prevent 2D UI from showing when // Note that this alone isn't sufficient to prevent 2D UI from showing when
// auto-presenting WebVR. See comment about the custom animation in {@link // auto-presenting WebVR. See comment about the custom animation in {@link
......
...@@ -1307,6 +1307,7 @@ chrome_vr_java_sources = [ ...@@ -1307,6 +1307,7 @@ chrome_vr_java_sources = [
"java/src/org/chromium/chrome/browser/vr_shell/VrCoreVersionCheckerImpl.java", "java/src/org/chromium/chrome/browser/vr_shell/VrCoreVersionCheckerImpl.java",
"java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApiImpl.java", "java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApiImpl.java",
"java/src/org/chromium/chrome/browser/vr_shell/VrExternalNavigationDelegate.java", "java/src/org/chromium/chrome/browser/vr_shell/VrExternalNavigationDelegate.java",
"java/src/org/chromium/chrome/browser/vr_shell/VrIntentHandler.java",
"java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java", "java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java",
"java/src/org/chromium/chrome/browser/vr_shell/VrWindowAndroid.java", "java/src/org/chromium/chrome/browser/vr_shell/VrWindowAndroid.java",
"java/src/org/chromium/chrome/browser/vr_shell/OnDispatchTouchEventCallback.java", "java/src/org/chromium/chrome/browser/vr_shell/OnDispatchTouchEventCallback.java",
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
package org.chromium.chrome.browser.vr_shell; package org.chromium.chrome.browser.vr_shell;
import static org.chromium.chrome.browser.vr_shell.VrTestRule.PAGE_LOAD_TIMEOUT_S; import static org.chromium.chrome.browser.vr_shell.VrTestRule.PAGE_LOAD_TIMEOUT_S;
import static org.chromium.chrome.browser.vr_shell.VrTestRule.POLL_CHECK_INTERVAL_SHORT_MS;
import static org.chromium.chrome.browser.vr_shell.VrTestRule.POLL_TIMEOUT_LONG_MS;
import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_DON_ENABLED; import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_DON_ENABLED;
import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM; import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM;
...@@ -19,12 +21,16 @@ import org.junit.runner.RunWith; ...@@ -19,12 +21,16 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.MinAndroidSdkLevel;
import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.Restriction;
import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.vr_shell.mock.MockVrIntentHandler;
import org.chromium.chrome.browser.vr_shell.util.NfcSimUtils; import org.chromium.chrome.browser.vr_shell.util.NfcSimUtils;
import org.chromium.chrome.browser.vr_shell.util.VrTransitionUtils; import org.chromium.chrome.browser.vr_shell.util.VrTransitionUtils;
import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.content.browser.test.util.Criteria;
import org.chromium.content.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.WebContents;
/** /**
* End-to-end tests for transitioning between WebVR's magic window and * End-to-end tests for transitioning between WebVR's magic window and
...@@ -59,11 +65,12 @@ public class WebVrTransitionTest { ...@@ -59,11 +65,12 @@ public class WebVrTransitionTest {
@Test @Test
@MediumTest @MediumTest
@Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM) @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
@RetryOnFailure(message = "crbug.com/736527")
public void testNfcFiresVrdisplayactivate() throws InterruptedException { public void testNfcFiresVrdisplayactivate() throws InterruptedException {
mVrTestRule.loadUrlAndAwaitInitialization( mVrTestRule.loadUrlAndAwaitInitialization(
VrTestRule.getHtmlTestFile("test_nfc_fires_vrdisplayactivate"), VrTestRule.getHtmlTestFile("test_nfc_fires_vrdisplayactivate"),
PAGE_LOAD_TIMEOUT_S); PAGE_LOAD_TIMEOUT_S);
mVrTestRule.runJavaScriptOrFail(
"addListener()", POLL_TIMEOUT_LONG_MS, mVrTestRule.getFirstTabWebContents());
NfcSimUtils.simNfcScan(mVrTestRule.getActivity()); NfcSimUtils.simNfcScan(mVrTestRule.getActivity());
mVrTestRule.waitOnJavaScriptStep(mVrTestRule.getFirstTabWebContents()); mVrTestRule.waitOnJavaScriptStep(mVrTestRule.getFirstTabWebContents());
mVrTestRule.endTest(mVrTestRule.getFirstTabWebContents()); mVrTestRule.endTest(mVrTestRule.getFirstTabWebContents());
...@@ -84,4 +91,31 @@ public class WebVrTransitionTest { ...@@ -84,4 +91,31 @@ public class WebVrTransitionTest {
mVrTestRule.getFirstTabCvc(), mVrTestRule.getFirstTabWebContents()); mVrTestRule.getFirstTabCvc(), mVrTestRule.getFirstTabWebContents());
mVrTestRule.endTest(mVrTestRule.getFirstTabWebContents()); mVrTestRule.endTest(mVrTestRule.getFirstTabWebContents());
} }
/**
* Tests that an intent from a trusted app such as Daydream Home allows WebVR content
* to auto present without the need for a user gesture.
*/
@Test
@MediumTest
@Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
public void testTrustedIntentAllowsAutoPresent() throws InterruptedException {
VrIntentHandler.setInstanceForTesting(new MockVrIntentHandler(
true /* useMockImplementation */, true /* treatIntentsAsTrusted */));
VrTransitionUtils.sendDaydreamAutopresentIntent(
mVrTestRule.getHtmlTestFile("test_webvr_autopresent"), mVrTestRule.getActivity());
// Wait until the link is opened in a new tab
final ChromeActivity act = mVrTestRule.getActivity();
CriteriaHelper.pollUiThread(new Criteria() {
@Override
public boolean isSatisfied() {
return act.getTabModelSelector().getTotalTabCount() == 2;
}
}, POLL_TIMEOUT_LONG_MS, POLL_CHECK_INTERVAL_SHORT_MS);
WebContents wc = mVrTestRule.getActivity().getActivityTab().getWebContents();
mVrTestRule.waitOnJavaScriptStep(wc);
mVrTestRule.endTest(wc);
}
} }
...@@ -42,6 +42,11 @@ public class MockVrDaydreamApi implements VrDaydreamApi { ...@@ -42,6 +42,11 @@ public class MockVrDaydreamApi implements VrDaydreamApi {
return true; return true;
} }
@Override
public boolean launchInVr(final Intent intent) {
return true;
}
@Override @Override
public boolean exitFromVr(int requestCode, final Intent intent) { public boolean exitFromVr(int requestCode, final Intent intent) {
return true; return true;
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// 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_shell.mock;
import android.content.Intent;
import org.chromium.chrome.browser.vr_shell.VrIntentHandler;
/**
* Mock version of VrIntentHandler for testing.
*/
public class MockVrIntentHandler extends VrIntentHandler {
private boolean mUseMockImplementation;
private boolean mTreatIntentsAsTrusted;
public MockVrIntentHandler(boolean useMockImplementation, boolean treatIntentsAsTrusted) {
mUseMockImplementation = useMockImplementation;
mTreatIntentsAsTrusted = treatIntentsAsTrusted;
}
@Override
public boolean isTrustedDaydreamIntent(Intent intent) {
if (mUseMockImplementation) {
return mTreatIntentsAsTrusted;
}
return super.isTrustedDaydreamIntent(intent);
}
public void setUseMockImplementation(boolean enabled) {
mUseMockImplementation = enabled;
}
public void setTreatIntentsAsTrusted(boolean trusted) {
mTreatIntentsAsTrusted = trusted;
}
}
...@@ -7,9 +7,17 @@ package org.chromium.chrome.browser.vr_shell.util; ...@@ -7,9 +7,17 @@ package org.chromium.chrome.browser.vr_shell.util;
import static org.chromium.chrome.browser.vr_shell.VrTestRule.POLL_CHECK_INTERVAL_SHORT_MS; import static org.chromium.chrome.browser.vr_shell.VrTestRule.POLL_CHECK_INTERVAL_SHORT_MS;
import static org.chromium.chrome.browser.vr_shell.VrTestRule.POLL_TIMEOUT_LONG_MS; import static org.chromium.chrome.browser.vr_shell.VrTestRule.POLL_TIMEOUT_LONG_MS;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.support.customtabs.CustomTabsIntent;
import com.google.vr.ndk.base.DaydreamApi;
import org.junit.Assert; import org.junit.Assert;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.chrome.browser.vr_shell.VrClassesWrapperImpl;
import org.chromium.chrome.browser.vr_shell.VrShellDelegate; import org.chromium.chrome.browser.vr_shell.VrShellDelegate;
import org.chromium.chrome.browser.vr_shell.VrTestRule; import org.chromium.chrome.browser.vr_shell.VrTestRule;
import org.chromium.content.browser.ContentViewCore; import org.chromium.content.browser.ContentViewCore;
...@@ -130,4 +138,31 @@ public class VrTransitionUtils { ...@@ -130,4 +138,31 @@ public class VrTransitionUtils {
}); });
return isBackButtonEnabled.get(); return isBackButtonEnabled.get();
} }
/**
* Sends an intent to Chrome telling it to autopresent the given URL. This
* is expected to fail unless the trusted intent check is disabled in VrShellDelegate.
*
* @param url String containing the URL to open
* @param activity The activity to launch the intent from
*/
public static void sendDaydreamAutopresentIntent(String url, final Activity activity) {
// Create an intent that will launch Chrome at the specified URL with autopresent
final Intent intent =
activity.getPackageManager().getLaunchIntentForPackage(activity.getPackageName());
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
intent.putExtra(VrShellDelegate.DAYDREAM_VR_EXTRA, true);
DaydreamApi.setupVrIntent(intent);
intent.removeCategory("com.google.intent.category.DAYDREAM");
CustomTabsIntent.setAlwaysUseBrowserUI(intent);
final VrClassesWrapperImpl wrapper = new VrClassesWrapperImpl();
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
wrapper.createVrDaydreamApi(activity).launchInVr(intent);
}
});
}
} }
...@@ -13,8 +13,10 @@ vrdisplayactivate event ...@@ -13,8 +13,10 @@ vrdisplayactivate event
<script src="../resources/webvr_e2e.js"></script> <script src="../resources/webvr_e2e.js"></script>
<script> <script>
var t = async_test("NFC scan fires the vrdisplayactivate event"); var t = async_test("NFC scan fires the vrdisplayactivate event");
window.addEventListener("vrdisplayactivate", () => {t.done();}, false); function addListener() {
// NFC scan triggered after page load window.addEventListener("vrdisplayactivate", () => {t.done();}, false);
}
// NFC scan triggered after page loaded and listener added
</script> </script>
</body> </body>
</html> </html>
<!doctype html>
<!--
Tests that an intent from a trusted app allows a page to auto present without
the need for a user gesture.
-->
<html>
<head>
<link rel="stylesheet" type="text/css" href="../resources/webvr_e2e.css">
</head>
<body>
<canvas id="webgl-canvas"></canvas>
<script src="../../../../../../third_party/WebKit/LayoutTests/resources/testharness.js"></script>
<script src="../resources/webvr_e2e.js"></script>
<script src="../resources/webvr_boilerplate.js"></script>
<script>
var t = async_test("Trusted intents allow auto present");
// We need to wait for vrDisplay to be non-null before adding the
// listener, so poll it
function pollVrDisplay() {
if (vrDisplay == null) {
window.setTimeout(pollVrDisplay, 100);
return
}
window.addEventListener("vrdisplayactivate", () => {
vrDisplay.requestPresent([{source: webglCanvas}]).then( () => {
// Do nothing
}, () => {
t.step( () => {
assert_unreached("requestPresent promise rejected");
});
}).then( () => {
t.done();
});
}, false);
}
window.setTimeout(pollVrDisplay, 100);
</script>
</body>
</html>
...@@ -87,7 +87,6 @@ gl.enable(gl.DEPTH_TEST); ...@@ -87,7 +87,6 @@ gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE); gl.enable(gl.CULL_FACE);
window.addEventListener("resize", onResize, false); window.addEventListener("resize", onResize, false);
window.addEventListener("vrdisplaypresentchange", onVrPresentChange, false); window.addEventListener("vrdisplaypresentchange", onVrPresentChange, false);
window.addEventListener('vrdisplayactivate', onVrRequestPresent, false);
window.requestAnimationFrame(onAnimationFrame); window.requestAnimationFrame(onAnimationFrame);
webglCanvas.onclick = onVrRequestPresent; webglCanvas.onclick = onVrRequestPresent;
onResize(); onResize();
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