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

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

Issue 2887383002: Show an infobar prompting the user to enter feedback when they exit VR (Closed)
Patch Set: add comments Created 3 years, 7 months 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 e698b1ce2c7afe5c990cfdaeeeb53024c58af532..7a1cfb2f259b1b9bd15c4b96ccd1fefde9828e33 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
@@ -89,6 +89,9 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
private static final long REENTER_VR_TIMEOUT_MS = 1000;
+ // TODO(ymalik): This should be configurable via Finch.
+ private static final int FEEDBACK_FREQUENCY = 10;
+
private static final int VR_SYSTEM_UI_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN
@@ -106,6 +109,9 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
@VrSupportLevel
private int mVrSupportLevel;
+ // How often to prompt the user to enter VR feedback.
+ private int mFeedbackFrequency;
+
private final VrClassesWrapper mVrClassesWrapper;
private VrShell mVrShell;
private NonPresentingGvrContext mNonPresentingGvrContext;
@@ -132,6 +138,10 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
private boolean mListeningForWebVrActivate;
private boolean mListeningForWebVrActivateBeforePause;
+ // Set to true if performed VR browsing at least once. That is, this was not simply a WebVr
+ // presentation experience.
+ private boolean mVrBrowserUsed;
+
private static final class VrBroadcastReceiver extends BroadcastReceiver {
private final WeakReference<ChromeActivity> mTargetActivity;
@@ -325,6 +335,10 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
return false;
}
+ private static boolean activitySupportsExitFeedback(Activity activity) {
+ return activity instanceof ChromeTabbedActivity;
+ }
+
/**
* @return A helper class for creating VR-specific classes that may not be available at compile
* time.
@@ -399,6 +413,7 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
mPaused = ApplicationStatus.getStateForActivity(activity) != ActivityState.RESUMED;
updateVrSupportLevel();
mNativeVrShellDelegate = nativeInit();
+ mFeedbackFrequency = FEEDBACK_FREQUENCY;
Choreographer choreographer = Choreographer.getInstance();
choreographer.postFrameCallback(new FrameCallback() {
@Override
@@ -433,7 +448,8 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
} else {
// We should never reach this state currently, but just in case...
assert false;
- shutdownVr(true, false);
+ shutdownVr(true /* disableVrMode */, false /* canReenter */,
+ false /* stayingInChrome */);
}
}
if (!activitySupportsPresentation(activity)) return;
@@ -551,7 +567,11 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
addVrViews();
mVrShell.initializeNative(mActivity.getActivityTab(), mRequestedWebVr || tentativeWebVrMode,
mActivity instanceof CustomTabActivity);
- mVrShell.setWebVrModeEnabled(mRequestedWebVr || tentativeWebVrMode);
+ boolean webVrMode = mRequestedWebVr || tentativeWebVrMode;
+ mVrShell.setWebVrModeEnabled(webVrMode);
+
+ // We're entering VR, but not in WebVr mode.
+ mVrBrowserUsed = !webVrMode;
// onResume needs to be called on GvrLayout after initialization to make sure DON flow work
// properly.
@@ -670,7 +690,10 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
return false;
}
mVrShell.setWebVrModeEnabled(false);
- shutdownVr(true, false);
+ shutdownVr(
+ true /* disableVrMode */, false /* canReenter */, true /* stayingInChrome */);
+ } else {
+ mVrBrowserUsed = true;
}
return true;
}
@@ -750,13 +773,13 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
// 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.
- shutdownVr(true, true);
+ shutdownVr(true /* disableVrMode */, true /* canReenter */, false /* stayingInChrome */);
}
private boolean onBackPressedInternal() {
if (mVrSupportLevel == VR_NOT_AVAILABLE) return false;
if (!mInVr) return false;
- shutdownVr(true, false);
+ shutdownVr(true /* disableVrMode */, false /* canReenter */, true /* stayingInChrome */);
return true;
}
@@ -772,7 +795,9 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
if (!success && mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent())) return;
mShowingDaydreamDoff = false;
- shutdownVr(true, false);
+
+ shutdownVr(true /* disableVrMode */, false /* canReenter */,
+ !mExitingCct /* stayingInChrome */);
if (mExitingCct) ((CustomTabActivity) mActivity).finishAndClose(false);
mExitingCct = false;
}
@@ -811,7 +836,8 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
/**
* Exits VR Shell, performing all necessary cleanup.
*/
- /* package */ void shutdownVr(boolean setVrMode, boolean canReenter) {
+ /* package */ void shutdownVr(
+ boolean disableVrMode, boolean canReenter, boolean stayingInChrome) {
if (!mInVr) return;
if (mShowingDaydreamDoff) {
onExitVrResult(true);
@@ -829,7 +855,9 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
removeVrViews();
destroyVrShell();
mActivity.getFullscreenManager().setPositionsForTabToNonFullscreen();
- if (setVrMode) mVrClassesWrapper.setVrModeEnabled(mActivity, false);
+ if (disableVrMode) mVrClassesWrapper.setVrModeEnabled(mActivity, false);
+
+ promptForFeedbackIfNeeded(stayingInChrome);
}
/* package */ void showDoffAndExitVr() {
@@ -838,7 +866,7 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
mShowingDaydreamDoff = true;
return;
}
- shutdownVr(true, false);
+ shutdownVr(true /* disableVrMode */, false /* canReenter */, true /* stayingInChrome */);
}
/* package */ void exitCct() {
@@ -851,7 +879,55 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
return;
}
}
- ((CustomTabActivity) mActivity).finishAndClose(false);
+ }
+
+ private static void promptForFeedback(Tab tab) {
+ final ChromeActivity activity = tab.getActivity();
+ SimpleConfirmInfoBarBuilder.Listener listener = new SimpleConfirmInfoBarBuilder.Listener() {
+ @Override
+ public void onInfoBarDismissed() {}
+
+ @Override
+ public boolean onInfoBarButtonClicked(boolean isPrimary) {
+ if (isPrimary) {
+ // TODO(ymalik): This just calls Chrome's help and feedback page for now. It
+ // should instead start a VR-specific Feedback activity.
+ activity.startHelpAndFeedback(activity.getActivityTab(), "vrExitFeedback");
+ } else {
+ VrFeedbackStatus.setFeedbackOptOut(true);
+ }
+ return false;
+ }
+ };
+
+ SimpleConfirmInfoBarBuilder.create(tab, listener,
+ InfoBarIdentifier.VR_FEEDBACK_INFOBAR_ANDROID, R.drawable.vr_services,
+ activity.getString(R.string.vr_shell_feedback_infobar_description),
+ activity.getString(R.string.vr_shell_feedback_infobar_feedback_button),
+ activity.getString(R.string.no_thanks), true /* autoExpire */);
+ }
+
+ /**
+ * Prompts the user to enter feedback for their VR Browsing experience.
+ */
+ private void promptForFeedbackIfNeeded(boolean stayingInChrome) {
+ // We only prompt for feedback if:
+ // 1) The user hasn't explicitly opted-out of it in the past
+ // 2) The user has performed VR browsing
+ // 3) The user is exiting VR and going back into 2D Chrome
+ // 4) Every n'th visit (where n = mFeedbackFrequency)
+
+ if (!activitySupportsExitFeedback(mActivity)) return;
+ if (!stayingInChrome) return;
+ if (VrFeedbackStatus.getFeedbackOptOut()) return;
+ if (!mVrBrowserUsed) return;
+
+ int exitCount = VrFeedbackStatus.getUserExitedAndEntered2DCount();
+ VrFeedbackStatus.setUserExitedAndEntered2DCount((exitCount + 1) % mFeedbackFrequency);
+
+ if (exitCount > 0) return;
+
+ promptForFeedback(mActivity.getActivityTab());
}
private static boolean isVrCoreCompatible(
@@ -989,6 +1065,14 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
}
/**
+ * @param frequency Sets how often to show the feedback prompt.
+ */
+ @VisibleForTesting
+ public void setFeedbackFrequencyForTesting(int frequency) {
+ mFeedbackFrequency = frequency;
+ }
+
+ /**
* @return Pointer to the native VrShellDelegate object.
*/
@CalledByNative
@@ -998,7 +1082,7 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener,
private void destroy() {
if (sInstance == null) return;
- shutdownVr(false, false);
+ shutdownVr(false /* disableVrMode */, false /* canReenter */, false /* stayingInChrome */);
if (mNativeVrShellDelegate != 0) nativeDestroy(mNativeVrShellDelegate);
mNativeVrShellDelegate = 0;
ApplicationStatus.unregisterActivityStateListener(this);

Powered by Google App Engine
This is Rietveld 408576698