Chromium Code Reviews| 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 6ce254485561d69df4741de6dadc23831af663dc..7219713240a9b47b6e3aa590cf0f5b3dde5ecf62 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 |
| @@ -6,7 +6,7 @@ package org.chromium.chrome.browser.vr_shell; |
| import android.app.Activity; |
| import android.app.PendingIntent; |
| -import android.content.Context; |
| +import android.content.ComponentName; |
| import android.content.Intent; |
| import android.content.pm.ActivityInfo; |
| import android.os.StrictMode; |
| @@ -36,6 +36,7 @@ import java.lang.reflect.InvocationTargetException; |
| @JNINamespace("vr_shell") |
| public class VrShellDelegate { |
| private static final String TAG = "VrShellDelegate"; |
| + public static final int EXIT_VR_RESULT = 102; |
|
Ted C
2016/11/16 21:17:32
I would use a slightly higher number to avoid conf
mthiesse
2016/11/16 21:45:43
Done.
|
| private final ChromeTabbedActivity mActivity; |
| private final TabObserver mTabObserver; |
| @@ -56,12 +57,21 @@ public class VrShellDelegate { |
| private int mRestoreOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; |
| private long mNativeVrShellDelegate; |
| private Tab mTab; |
| + private boolean mRequestedWebVR; |
| - // TODO(bshe): This 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 this string. So hard code it here. |
| + // 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"; |
| - private static final String DAYDREAM_DON_AUTO_TRANSITION = |
| - "org.chromium.chrome.browser.vr_shell.DAYDREAM_DON_AUTO_TRANSITION"; |
| + private static final String DAYDREAM_CATEGORY = "com.google.intent.category.DAYDREAM"; |
| + private static final String CARDBOARD_CATEGORY = "com.google.intent.category.CARDBOARD"; |
| + |
| + 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; |
| public VrShellDelegate(ChromeTabbedActivity activity) { |
| mActivity = activity; |
| @@ -72,7 +82,7 @@ public class VrShellDelegate { |
| public void onContentChanged(Tab tab) { |
| if (tab.getNativePage() != null || tab.isShowingSadTab()) { |
| // For now we don't handle native pages. crbug.com/661609 |
| - exitVRIfNecessary(); |
| + exitVRIfNecessary(true); |
| } |
| } |
| @@ -117,40 +127,29 @@ public class VrShellDelegate { |
| } |
| } |
| - /** |
| - * Enters VR Shell, displaying browser UI and tab contents in VR. |
| - * |
| - * This function performs native initialization, and so must only be called after native |
| - * libraries are ready. |
| - * @param inWebVR If true should begin displaying WebVR content rather than the VrShell UI. |
| - * @return Whether or not we are in VR when this function returns. |
| - */ |
| - @CalledByNative |
| - public boolean enterVRIfNecessary(boolean inWebVR) { |
| - // 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)) { |
| - return false; |
| - } |
| - Tab tab = mActivity.getActivityTab(); |
| - // TODO(mthiesse): When we have VR UI for opening new tabs, etc., allow VR Shell to be |
| - // entered without any current tabs. |
| - if (tab == null || tab.getContentViewCore() == null) { |
| - return false; |
| - } |
| + public boolean enterVRFromIntent(Intent intent) { |
|
Ted C
2016/11/16 21:17:32
javadoc non-private methods
mthiesse
2016/11/16 21:45:43
Done.
|
| + assert isVrIntent(intent); |
| + int transitionType = intent.getIntExtra(DAYDREAM_DON_TYPE, DAYDREAM_DON_TYPE_VR_SHELL); |
| + mActivity.setIntent(null); |
|
Ted C
2016/11/16 21:17:32
why the need for this?
would it be better to stri
mthiesse
2016/11/16 21:45:42
Meant to delete this.
|
| + if (!isVrShellEnabled()) assert transitionType != DAYDREAM_DON_TYPE_VR_SHELL; |
|
Ted C
2016/11/16 21:17:32
while I "think" this is fine, asserts are removed
mthiesse
2016/11/16 21:45:43
Done.
|
| - // For now we don't handle native pages. crbug.com/661609 |
| - if (tab.getNativePage() != null || tab.isShowingSadTab()) { |
| - return false; |
| - } |
| + 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. |
| if (mInVr) return true; |
| + mVrDaydreamApi.setVrModeEnabled(true); |
| + |
| mTab = tab; |
| mTab.addObserver(mTabObserver); |
| mRestoreOrientation = mActivity.getRequestedOrientation(); |
| - // VrShell must be initialized in Landscape mode due to a bug in the GVR library. |
| mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); |
| if (!createVrShell()) { |
| mActivity.setRequestedOrientation(mRestoreOrientation); |
| @@ -160,7 +159,6 @@ public class VrShellDelegate { |
| setupVrModeWindowFlags(); |
| mVrShell.initializeNative(mTab, this); |
| if (inWebVR) mVrShell.setWebVrModeEnabled(true); |
| - mVrShell.setVrModeEnabled(true); |
| // onResume needs to be called on GvrLayout after initialization to make sure DON flow work |
| // properly. |
| mVrShell.resume(); |
| @@ -169,6 +167,52 @@ public class VrShellDelegate { |
| return true; |
| } |
| + private boolean canEnterVR(boolean inWebVR, 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)) { |
| + return false; |
| + } |
| + // TODO(mthiesse): When we have VR UI for opening new tabs, etc., allow VR Shell to be |
| + // entered without any current tabs. |
| + if (tab == null || tab.getContentViewCore() == null) { |
| + return false; |
| + } |
| + |
| + // For now we don't handle native pages. crbug.com/661609 |
| + if (tab.getNativePage() != null || tab.isShowingSadTab()) { |
| + return false; |
| + } |
| + 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. |
| + mRequestedWebVR = inWebVR; |
| + Intent intent = createDaydreamIntent( |
| + inWebVR ? DAYDREAM_DON_TYPE_WEBVR : DAYDREAM_DON_TYPE_VR_SHELL); |
| + |
| + mVrDaydreamApi.launchInVr( |
| + PendingIntent.getActivity(mActivity, 0, intent, PendingIntent.FLAG_ONE_SHOT)); |
| + } |
| + |
| @CalledByNative |
| private boolean exitWebVR() { |
| if (!mInVr) return false; |
| @@ -176,7 +220,7 @@ public class VrShellDelegate { |
| // TODO(bajones): Once VR Shell can be invoked outside of WebVR this |
| // should no longer exit the shell outright. Need a way to determine |
| // how VrShell was created. |
| - shutdownVR(); |
| + shutdownVR(true); |
| return true; |
| } |
| @@ -230,35 +274,48 @@ public class VrShellDelegate { |
| // TODO(mthiesse): When VR Shell lives in its own activity, and integrates with Daydream |
| // home, pause instead of exiting VR here. For now, because VR Apps shouldn't show up in the |
| // non-VR recents, and we don't want ChromeTabbedActivity disappearing, exit VR. |
| - exitVRIfNecessary(); |
| + exitVRIfNecessary(false); |
| } |
| /** |
| * Exits the current VR mode (WebVR or VRShell) |
| * @return Whether or not we exited VR. |
| */ |
| - public boolean exitVRIfNecessary() { |
| + public boolean exitVRIfNecessary(boolean returnTo2D) { |
| if (!mInVr) return false; |
| // If WebVR is presenting instruct it to exit. |
| nativeExitWebVRIfNecessary(mNativeVrShellDelegate); |
| - shutdownVR(); |
| + shutdownVR(returnTo2D); |
| return true; |
| } |
| + public void onExitVRResult(int resultCode) { |
| + if (resultCode == Activity.RESULT_OK) { |
| + mVrDaydreamApi.setVrModeEnabled(false); |
| + } else { |
| + // For now, we don't handle re-entering VR when exit fails, so keep trying to exit. |
| + mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent()); |
| + } |
| + } |
| + |
| + 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; |
| + } |
| + |
| /** |
| * Registers the Intent to fire after phone inserted into a headset. |
| */ |
| private void registerDaydreamIntent() { |
| if (mVrDaydreamApi == null) return; |
| - |
| - Intent intent = new Intent(); |
| - // TODO(bshe): Ideally, this should go through ChromeLauncherActivity. To avoid polluting |
| - // metrics, use ChromeTabbedActivity directly for now. |
| - intent.setClass(mActivity, ChromeTabbedActivity.class); |
| - intent.putExtra(DAYDREAM_DON_AUTO_TRANSITION, true); |
| - PendingIntent pendingIntent = |
| - PendingIntent.getActivity(mActivity, 0, intent, PendingIntent.FLAG_ONE_SHOT); |
| - mVrDaydreamApi.registerDaydreamIntent(pendingIntent); |
| + Intent intent = createDaydreamIntent(DAYDREAM_DON_TYPE_AUTO); |
| + mVrDaydreamApi.registerDaydreamIntent( |
| + PendingIntent.getActivity(mActivity, 0, intent, PendingIntent.FLAG_ONE_SHOT)); |
| } |
| /** |
| @@ -270,15 +327,6 @@ public class VrShellDelegate { |
| } |
| } |
| - /** |
| - * Closes DaydreamApi. |
| - */ |
| - public void close() { |
| - if (mVrDaydreamApi != null) { |
| - mVrDaydreamApi.close(); |
| - } |
| - } |
| - |
| @CalledByNative |
| private long createNonPresentingNativeContext() { |
| if (!mVrAvailable) return 0; |
| @@ -306,10 +354,14 @@ public class VrShellDelegate { |
| /** |
| * Exits VR Shell, performing all necessary cleanup. |
| */ |
| - private void shutdownVR() { |
| + private void shutdownVR(boolean returnTo2D) { |
| if (!mInVr) return; |
| + if (returnTo2D) { |
| + mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent()); |
| + } else { |
| + mVrDaydreamApi.setVrModeEnabled(false); |
| + } |
| mActivity.setRequestedOrientation(mRestoreOrientation); |
| - mVrShell.setVrModeEnabled(false); |
| mVrShell.pause(); |
| removeVrViews(); |
| clearVrModeWindowFlags(); |
| @@ -347,7 +399,7 @@ public class VrShellDelegate { |
| try { |
| Constructor<?> vrPrivateApiConstructor = |
| - mVrDaydreamApiClass.getConstructor(Context.class); |
| + mVrDaydreamApiClass.getConstructor(Activity.class); |
| mVrDaydreamApi = (VrDaydreamApi) vrPrivateApiConstructor.newInstance(mActivity); |
| } catch (InstantiationException | IllegalAccessException | IllegalArgumentException |
| | InvocationTargetException | NoSuchMethodException e) { |
| @@ -424,8 +476,9 @@ public class VrShellDelegate { |
| */ |
| public boolean isVrIntent(Intent intent) { |
| if (intent == null) return false; |
| - return intent.getBooleanExtra(DAYDREAM_DON_AUTO_TRANSITION, false) |
| - || intent.getBooleanExtra(DAYDREAM_VR_EXTRA, false); |
| + return intent.getBooleanExtra(DAYDREAM_VR_EXTRA, false) |
| + || intent.getCategories().contains(DAYDREAM_CATEGORY) |
| + || intent.getCategories().contains(CARDBOARD_CATEGORY); |
| } |
| /** |