Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5478)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java

Issue 2510873003: Clean up WebVR RequestPresent and make callback asynchronous. (Closed)
Patch Set: Fix FakeVRDevice Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
index bea4861e16ca4a7407a987c0709897a0757c474d..ed98793eb158000bb485305bc3d2d4ab7ca7c919 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -11,6 +11,7 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.StrictMode;
import android.os.SystemClock;
+import android.support.annotation.IntDef;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
@@ -28,6 +29,8 @@ import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabObserver;
import org.chromium.content_public.common.BrowserControlsState;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -40,6 +43,13 @@ public class VrShellDelegate {
// Pseudo-random number to avoid request id collisions.
public static final int EXIT_VR_RESULT = 721251;
+ public static final int ENTER_VR_NOT_NECESSARY = 0;
+ public static final int ENTER_VR_CANCELLED = 1;
+ public static final int ENTER_VR_REQUESTED = 2;
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ENTER_VR_NOT_NECESSARY, ENTER_VR_CANCELLED, ENTER_VR_REQUESTED})
+ public @interface EnterVRResult {}
+
// TODO(bshe): These should be replaced by string provided by NDK. Currently, it only available
// in SDK and we don't want add dependency to SDK just to get these strings.
private static final String DAYDREAM_VR_EXTRA = "android.intent.extra.VR_LAUNCH";
@@ -48,16 +58,12 @@ public class VrShellDelegate {
private static final String VR_ACTIVITY_ALIAS =
"org.chromium.chrome.browser.VRChromeTabbedActivity";
- private static final String DAYDREAM_DON_TYPE = "DAYDREAM_DON_TYPE";
-
- private static final int DAYDREAM_DON_TYPE_VR_SHELL = 0;
- private static final int DAYDREAM_DON_TYPE_WEBVR = 1;
- private static final int DAYDREAM_DON_TYPE_AUTO = 2;
private static final long REENTER_VR_TIMEOUT_MS = 1000;
private final ChromeTabbedActivity mActivity;
private final TabObserver mTabObserver;
+ private final Intent mEnterVRIntent;
private boolean mVrAvailable;
private Boolean mVrShellEnabled;
@@ -80,8 +86,13 @@ public class VrShellDelegate {
public VrShellDelegate(ChromeTabbedActivity activity) {
mActivity = activity;
- mVrAvailable = maybeFindVrClasses() && isVrCoreCompatible();
- createVrDaydreamApi();
+ mVrAvailable = maybeFindVrClasses() && isVrCoreCompatible() && createVrDaydreamApi();
+ if (mVrAvailable) {
+ mEnterVRIntent = mVrDaydreamApi.createVrIntent(
+ new ComponentName(mActivity, VR_ACTIVITY_ALIAS));
+ } else {
+ mEnterVRIntent = null;
+ }
mTabObserver = new EmptyTabObserver() {
@Override
public void onContentChanged(Tab tab) {
@@ -105,9 +116,8 @@ public class VrShellDelegate {
* class can be initialized.
*/
public void onNativeLibraryReady() {
- if (mVrAvailable) {
- mNativeVrShellDelegate = nativeInit();
- }
+ if (!mVrAvailable) return;
+ mNativeVrShellDelegate = nativeInit();
}
@SuppressWarnings("unchecked")
@@ -135,28 +145,28 @@ public class VrShellDelegate {
/**
* Handle a VR intent, entering VR in the process.
*/
- public boolean enterVRFromIntent(Intent intent) {
+ public void enterVRFromIntent(Intent intent) {
+ if (!mVrAvailable) return;
assert isVrIntent(intent);
- int transitionType = intent.getIntExtra(DAYDREAM_DON_TYPE, DAYDREAM_DON_TYPE_VR_SHELL);
- if (!isVrShellEnabled()) {
- assert transitionType != DAYDREAM_DON_TYPE_VR_SHELL;
+ if (enterVR()) {
+ if (mRequestedWebVR) {
+ nativeSetPresentResult(mNativeVrShellDelegate, true);
+ mVrShell.setWebVrModeEnabled(true);
+ }
+ } else {
+ if (mRequestedWebVR) nativeSetPresentResult(mNativeVrShellDelegate, false);
+ mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent());
}
- boolean inWebVR = transitionType == DAYDREAM_DON_TYPE_WEBVR
- || (transitionType == DAYDREAM_DON_TYPE_AUTO
- && (!isVrShellEnabled() || mRequestedWebVR));
mRequestedWebVR = false;
- Tab tab = mActivity.getActivityTab();
- if (!canEnterVR(inWebVR, tab)) return false;
+ }
- // TODO(mthiesse): We should handle switching between webVR and VR Shell mode through
- // intents.
+ private boolean enterVR() {
if (mInVr) return true;
-
mVrDaydreamApi.setVrModeEnabled(true);
- mTab = tab;
- mTab.addObserver(mTabObserver);
+ Tab tab = mActivity.getActivityTab();
+ if (!canEnterVR(tab)) return false;
mRestoreOrientation = mActivity.getRequestedOrientation();
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
@@ -164,10 +174,12 @@ public class VrShellDelegate {
mActivity.setRequestedOrientation(mRestoreOrientation);
return false;
}
+ mInVr = true;
+ mTab = tab;
+ mTab.addObserver(mTabObserver);
addVrViews();
setupVrModeWindowFlags();
mVrShell.initializeNative(mTab, this);
- if (inWebVR) mVrShell.setWebVrModeEnabled(true);
mVrShell.setCloseButtonListener(new Runnable() {
@Override
public void run() {
@@ -177,18 +189,18 @@ public class VrShellDelegate {
// onResume needs to be called on GvrLayout after initialization to make sure DON flow work
// properly.
mVrShell.resume();
- mInVr = true;
mTab.updateFullscreenEnabledState();
return true;
}
- private boolean canEnterVR(boolean inWebVR, Tab tab) {
+ private boolean canEnterVR(Tab tab) {
if (!LibraryLoader.isInitialized()) {
return false;
}
// If vr isn't in the build, or we haven't initialized yet, or vr shell is not enabled and
// this is not a web vr request, then return immediately.
- if (!mVrAvailable || mNativeVrShellDelegate == 0 || (!isVrShellEnabled() && !inWebVR)) {
+ if (!mVrAvailable || mNativeVrShellDelegate == 0
+ || (!isVrShellEnabled() && !mRequestedWebVR)) {
return false;
}
// TODO(mthiesse): When we have VR UI for opening new tabs, etc., allow VR Shell to be
@@ -204,28 +216,38 @@ public class VrShellDelegate {
return true;
}
- /**
- * Enters VR Shell, displaying browser UI and tab contents in VR.
- *
- * @param inWebVR If true should begin displaying WebVR content rather than the VrShell UI.
- */
@CalledByNative
- public void enterVRIfNecessary(boolean inWebVR) {
- if (mInVr) {
- if (inWebVR) mVrShell.setWebVrModeEnabled(true);
- return;
- }
- if (!canEnterVR(inWebVR, mActivity.getActivityTab())) return;
-
- // TODO(mthiesse): There's a GVR bug where they're not calling us back with the intent we
- // ask them to when we call DaydreamApi#launchInVr. As a temporary hack, remember locally
- // that we want to enter webVR.
+ private void presentRequested(boolean inWebVR) {
+ // TODO(mthiesse): There's a GVR bug where they're not calling us back with the
+ // intent we ask them to when we call DaydreamApi#launchInVr. As a temporary hack,
+ // remember locally that we want to enter webVR.
mRequestedWebVR = inWebVR;
- Intent intent = createDaydreamIntent(
- inWebVR ? DAYDREAM_DON_TYPE_WEBVR : DAYDREAM_DON_TYPE_VR_SHELL);
+ switch (enterVRIfNecessary()) {
+ case ENTER_VR_NOT_NECESSARY:
+ mVrShell.setWebVrModeEnabled(true);
+ nativeSetPresentResult(mNativeVrShellDelegate, true);
+ mRequestedWebVR = false;
+ break;
+ case ENTER_VR_CANCELLED:
+ nativeSetPresentResult(mNativeVrShellDelegate, false);
+ mRequestedWebVR = false;
+ break;
+ case ENTER_VR_REQUESTED:
+ break;
+ }
+ }
- mVrDaydreamApi.launchInVr(
- PendingIntent.getActivity(mActivity, 0, intent, PendingIntent.FLAG_ONE_SHOT));
+ /**
+ * Enters VR Shell if necessary, displaying browser UI and tab contents in VR.
+ */
+ @EnterVRResult
+ public int enterVRIfNecessary() {
+ if (!mVrAvailable) return ENTER_VR_CANCELLED;
+ if (mInVr) return ENTER_VR_NOT_NECESSARY;
+ if (!canEnterVR(mActivity.getActivityTab())) return ENTER_VR_CANCELLED;
+
+ mVrDaydreamApi.launchInVr(getPendingEnterVRIntent());
+ return ENTER_VR_REQUESTED;
}
@CalledByNative
@@ -243,9 +265,18 @@ public class VrShellDelegate {
* Resumes VR Shell.
*/
public void maybeResumeVR() {
+ if (!mVrAvailable) return;
+ // TODO(mthiesse): Register the intent when on a page that supports WebVR, even if VrShell
+ // isn't enabled.
if (isVrShellEnabled()) {
registerDaydreamIntent();
}
+ // If this is still set, it means the user backed out of the DON flow, and we won't be
+ // receiving an intent from daydream.
+ if (mRequestedWebVR) {
+ nativeSetPresentResult(mNativeVrShellDelegate, false);
+ mRequestedWebVR = false;
+ }
// TODO(bshe): Ideally, we do not need two gvr context exist at the same time. We can
// probably shutdown non presenting gvr when presenting and create a new one after exit
@@ -272,7 +303,7 @@ public class VrShellDelegate {
StrictMode.setThreadPolicy(oldPolicy);
}
} else if (mLastVRExit + REENTER_VR_TIMEOUT_MS > SystemClock.uptimeMillis()) {
- enterVRIfNecessary(mRequestedWebVR);
+ enterVRIfNecessary();
}
}
@@ -280,9 +311,8 @@ public class VrShellDelegate {
* Pauses VR Shell.
*/
public void maybePauseVR() {
- if (isVrShellEnabled()) {
- unregisterDaydreamIntent();
- }
+ if (!mVrAvailable) return;
+ unregisterDaydreamIntent();
if (mNonPresentingGvrContext != null) {
mNonPresentingGvrContext.pause();
@@ -299,12 +329,14 @@ public class VrShellDelegate {
* @return Whether or not we exited VR.
*/
public boolean exitVRIfNecessary(boolean returnTo2D) {
+ if (!mVrAvailable) return false;
if (!mInVr) return false;
shutdownVR(returnTo2D);
return true;
}
public void onExitVRResult(int resultCode) {
+ assert mVrAvailable;
if (resultCode == Activity.RESULT_OK) {
mVrDaydreamApi.setVrModeEnabled(false);
} else {
@@ -313,33 +345,22 @@ public class VrShellDelegate {
}
}
- private Intent createDaydreamIntent(int transitionType) {
- if (mVrDaydreamApi == null) return null;
- // TODO(bshe): Ideally, this should go through ChromeLauncherActivity. To avoid polluting
- // metrics, use the VR Activity alias for now.
- Intent intent = mVrDaydreamApi.createVrIntent(
- new ComponentName(mActivity, VR_ACTIVITY_ALIAS));
- intent.putExtra(DAYDREAM_DON_TYPE, transitionType);
- return intent;
+ private PendingIntent getPendingEnterVRIntent() {
+ return PendingIntent.getActivity(mActivity, 0, mEnterVRIntent, PendingIntent.FLAG_ONE_SHOT);
}
/**
* Registers the Intent to fire after phone inserted into a headset.
*/
private void registerDaydreamIntent() {
- if (mVrDaydreamApi == null) return;
- Intent intent = createDaydreamIntent(DAYDREAM_DON_TYPE_AUTO);
- mVrDaydreamApi.registerDaydreamIntent(
- PendingIntent.getActivity(mActivity, 0, intent, PendingIntent.FLAG_ONE_SHOT));
+ mVrDaydreamApi.registerDaydreamIntent(getPendingEnterVRIntent());
}
/**
* Unregisters the Intent which registered by this context if any.
*/
private void unregisterDaydreamIntent() {
- if (mVrDaydreamApi != null) {
- mVrDaydreamApi.unregisterDaydreamIntent();
- }
+ mVrDaydreamApi.unregisterDaydreamIntent();
}
@CalledByNative
@@ -371,6 +392,7 @@ public class VrShellDelegate {
*/
private void shutdownVR(boolean returnTo2D) {
if (!mInVr) return;
+ mRequestedWebVR = false;
if (returnTo2D) {
mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent());
} else {
@@ -404,22 +426,20 @@ public class VrShellDelegate {
(VrCoreVersionChecker) mVrCoreVersionCheckerConstructor.newInstance();
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException e) {
- Log.e(TAG, "Unable to instantiate VrCoreVersionChecker", e);
+ Log.d(TAG, "Unable to instantiate VrCoreVersionChecker", e);
return false;
}
return mVrCoreVersionChecker.isVrCoreCompatible();
}
private boolean createVrDaydreamApi() {
- if (!mVrAvailable) return false;
-
try {
Constructor<?> vrPrivateApiConstructor =
mVrDaydreamApiClass.getConstructor(Activity.class);
mVrDaydreamApi = (VrDaydreamApi) vrPrivateApiConstructor.newInstance(mActivity);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
- | InvocationTargetException | NoSuchMethodException e) {
- Log.e(TAG, "Unable to instantiate VrDaydreamApi", e);
+ | InvocationTargetException | NoSuchMethodException | SecurityException e) {
+ Log.d(TAG, "Unable to instantiate VrDaydreamApi", e);
return false;
}
return true;
@@ -521,13 +541,6 @@ public class VrShellDelegate {
}
/**
- * @return Whether or not VR Shell is currently enabled.
- */
- public boolean isVrInitialized() {
- return mVrDaydreamApi != null;
- }
-
- /**
* @return Pointer to the native VrShellDelegate object.
*/
@CalledByNative
@@ -536,4 +549,5 @@ public class VrShellDelegate {
}
private native long nativeInit();
+ private native void nativeSetPresentResult(long nativeVrShellDelegate, boolean result);
}

Powered by Google App Engine
This is Rietveld 408576698