Commit 68cf0b83 authored by avayvod's avatar avayvod Committed by Commit bot

[Cast,Android] Subscribe to onCancel and onDismiss correctly

Subclass DialogFragment classes to get notified about the dialog being cancelled and dismissed.
Don't call dismiss() from the onDismiss() handler.

BaseMediaRouteDialogManager:
- expose mDialogFragment to avoid calling closeDialog() from onDismiss()
- add SystemVisibilitySaver to handle the dialogs showing when in FS mode
  (before was handled by ChromeMediaRouteDialogFactory).

MediaRouteChooserDialogManager:
- use subclassed MediaRouteChooserDialogFragment
- use SystemVisibilitySaver and handle onCancel() and onDismiss()

MediaRouteControllerDialogManager:
- use subclassed MediaRouteControllerDialogFragment
- use SystemVisibilitySaver and handle onDismiss() as onCancel() isn't called.

ChromeMediaRouteDialogController:
- exit onDialogCancelled() early if onRouteClosed() was called before (see the comment).

BUG=551184

Review URL: https://codereview.chromium.org/1463693002

Cr-Commit-Position: refs/heads/master@{#361406}
parent 05373dc0
...@@ -4,15 +4,16 @@ ...@@ -4,15 +4,16 @@
package org.chromium.chrome.browser.media.router; package org.chromium.chrome.browser.media.router;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v7.app.MediaRouteDialogFactory;
import android.support.v7.media.MediaRouter; import android.support.v7.media.MediaRouter;
import android.view.View;
import android.widget.FrameLayout;
import org.chromium.base.ApplicationStatus; import org.chromium.base.ApplicationStatus;
import org.chromium.chrome.browser.media.remote.ChromeMediaRouteDialogFactory;
import org.chromium.chrome.browser.media.router.cast.MediaSource; import org.chromium.chrome.browser.media.router.cast.MediaSource;
import javax.annotation.Nullable; import javax.annotation.Nullable;
...@@ -22,11 +23,45 @@ import javax.annotation.Nullable; ...@@ -22,11 +23,45 @@ import javax.annotation.Nullable;
*/ */
public abstract class BaseMediaRouteDialogManager implements MediaRouteDialogManager { public abstract class BaseMediaRouteDialogManager implements MediaRouteDialogManager {
/**
* A helper class to handle the system visibility change caused by the dialog showing up.
* Call saveSystemVisibility() in onCreateDialog() of the DialogFragment and later
* restoreSystemVisibility() in onStop().
* TODO(avayvod): refactor this to avoid a redundant copy in ChromeMediaRouteDialogFactory.
*/
protected static class SystemVisibilitySaver {
private int mSystemVisibilityToRestore;
private boolean mWasFullscreenBeforeShowing;
void saveSystemVisibility(Activity activity) {
// If we are in fullscreen we may have also have hidden the system UI. This
// is overridden when we display the dialog. Save the system UI visibility
// state so we can restore it.
FrameLayout decor = (FrameLayout) activity.getWindow().getDecorView();
mSystemVisibilityToRestore = decor.getSystemUiVisibility();
mWasFullscreenBeforeShowing = (
(mSystemVisibilityToRestore & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0);
}
void restoreSystemVisibility(Activity activity) {
if (!mWasFullscreenBeforeShowing) return;
FrameLayout decor = (FrameLayout) activity.getWindow().getDecorView();
// In some cases we come out of fullscreen before closing this dialog. In these
// cases we don't want to restore the system UI visibility state.
boolean isStillFullscreen =
(decor.getSystemUiVisibility() & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0;
if (!isStillFullscreen) return;
decor.setSystemUiVisibility(mSystemVisibilityToRestore);
}
}
private final MediaSource mMediaSource; private final MediaSource mMediaSource;
private final MediaRouter mAndroidMediaRouter; private final MediaRouter mAndroidMediaRouter;
private final MediaRouteDialogDelegate mDelegate; private final MediaRouteDialogDelegate mDelegate;
private DialogFragment mDialogFragment; protected DialogFragment mDialogFragment;
@Override @Override
public void openDialog() { public void openDialog() {
...@@ -39,8 +74,7 @@ public abstract class BaseMediaRouteDialogManager implements MediaRouteDialogMan ...@@ -39,8 +74,7 @@ public abstract class BaseMediaRouteDialogManager implements MediaRouteDialogMan
FragmentManager fm = currentActivity.getSupportFragmentManager(); FragmentManager fm = currentActivity.getSupportFragmentManager();
if (fm == null) return; if (fm == null) return;
MediaRouteDialogFactory factory = new ChromeMediaRouteDialogFactory(); mDialogFragment = openDialogInternal(fm);
mDialogFragment = openDialogInternal(fm, factory);
} }
@Override @Override
...@@ -68,12 +102,10 @@ public abstract class BaseMediaRouteDialogManager implements MediaRouteDialogMan ...@@ -68,12 +102,10 @@ public abstract class BaseMediaRouteDialogManager implements MediaRouteDialogMan
* needed. * needed.
* *
* @param fm {@link FragmentManager} to use to show the dialog. * @param fm {@link FragmentManager} to use to show the dialog.
* @param factory {@link MediaRouteDialogFactory} to use to create the dialog.
* @return null if the initialization fails, otherwise the initialized dialog fragment. * @return null if the initialization fails, otherwise the initialized dialog fragment.
*/ */
@Nullable @Nullable
protected abstract DialogFragment openDialogInternal( protected abstract DialogFragment openDialogInternal(FragmentManager fm);
FragmentManager fm, MediaRouteDialogFactory factory);
protected MediaRouteDialogDelegate delegate() { protected MediaRouteDialogDelegate delegate() {
return mDelegate; return mDelegate;
......
...@@ -104,6 +104,12 @@ public class ChromeMediaRouterDialogController implements MediaRouteDialogDelega ...@@ -104,6 +104,12 @@ public class ChromeMediaRouterDialogController implements MediaRouteDialogDelega
@Override @Override
public void onDialogCancelled() { public void onDialogCancelled() {
// For MediaRouteControllerDialog this method will be called in case the route is closed
// since it only call onDismiss() and there's no way to distinguish between the two.
// Here we can figure it out: if mDialogManager is null, onRouteClosed() was called and
// there's no need to tell the native controller the dialog has been cancelled.
if (mDialogManager == null) return;
mDialogManager = null; mDialogManager = null;
nativeOnDialogCancelled(mNativeDialogController); nativeOnDialogCancelled(mNativeDialogController);
} }
......
...@@ -4,15 +4,11 @@ ...@@ -4,15 +4,11 @@
package org.chromium.chrome.browser.media.router; package org.chromium.chrome.browser.media.router;
import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnDismissListener;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v7.app.MediaRouteChooserDialogFragment; import android.support.v7.app.MediaRouteChooserDialogFragment;
import android.support.v7.app.MediaRouteDialogFactory;
import org.chromium.chrome.browser.media.router.cast.MediaSink; import org.chromium.chrome.browser.media.router.cast.MediaSink;
import org.chromium.chrome.browser.media.router.cast.MediaSource; import org.chromium.chrome.browser.media.router.cast.MediaSource;
...@@ -20,8 +16,7 @@ import org.chromium.chrome.browser.media.router.cast.MediaSource; ...@@ -20,8 +16,7 @@ import org.chromium.chrome.browser.media.router.cast.MediaSource;
/** /**
* Manages the dialog responsible for selecting a {@link MediaSink}. * Manages the dialog responsible for selecting a {@link MediaSink}.
*/ */
public class MediaRouteChooserDialogManager extends BaseMediaRouteDialogManager implements public class MediaRouteChooserDialogManager extends BaseMediaRouteDialogManager {
OnCancelListener, OnDismissListener {
private static final String DIALOG_FRAGMENT_TAG = private static final String DIALOG_FRAGMENT_TAG =
"android.support.v7.mediarouter:MediaRouteChooserDialogFragment"; "android.support.v7.mediarouter:MediaRouteChooserDialogFragment";
...@@ -34,39 +29,50 @@ public class MediaRouteChooserDialogManager extends BaseMediaRouteDialogManager ...@@ -34,39 +29,50 @@ public class MediaRouteChooserDialogManager extends BaseMediaRouteDialogManager
} }
@Override @Override
protected DialogFragment openDialogInternal(FragmentManager fm, protected DialogFragment openDialogInternal(FragmentManager fm) {
MediaRouteDialogFactory factory) {
if (fm.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) return null; if (fm.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) return null;
MediaRouteChooserDialogFragment fragment = factory.onCreateChooserDialogFragment(); MediaRouteChooserDialogFragment fragment = new MediaRouteChooserDialogFragment() {
fragment.setRouteSelector(mediaSource().buildRouteSelector()); final SystemVisibilitySaver mVisibilitySaver = new SystemVisibilitySaver();
fragment.show(fm, DIALOG_FRAGMENT_TAG);
fm.executePendingTransactions();
Dialog dialog = fragment.getDialog(); @Override
if (dialog == null) return null; public void onStart() {
mVisibilitySaver.saveSystemVisibility(getActivity());
super.onStart();
}
dialog.setOnCancelListener(this); @Override
dialog.setOnDismissListener(this); public void onStop() {
super.onStop();
mVisibilitySaver.restoreSystemVisibility(getActivity());
}
return fragment; @Override
} public void onCancel(DialogInterface dialog) {
mCancelled = true;
@Override delegate().onDialogCancelled();
public void onCancel(DialogInterface dialog) {
mCancelled = true;
delegate().onDialogCancelled(); super.onCancel(dialog);
} }
@Override @Override
public void onDismiss(DialogInterface dialog) { public void onDismiss(DialogInterface dialog) {
closeDialog(); super.onDismiss(dialog);
if (mCancelled) return; mDialogFragment = null;
MediaSink newSink = MediaSink.fromRoute(androidMediaRouter().getSelectedRoute()); if (mCancelled) return;
delegate().onSinkSelected(newSink);
} MediaSink newSink = MediaSink.fromRoute(androidMediaRouter().getSelectedRoute());
delegate().onSinkSelected(newSink);
}
};
fragment.setRouteSelector(mediaSource().buildRouteSelector());
fragment.show(fm, DIALOG_FRAGMENT_TAG);
fm.executePendingTransactions();
return fragment;
}
} }
...@@ -4,15 +4,11 @@ ...@@ -4,15 +4,11 @@
package org.chromium.chrome.browser.media.router; package org.chromium.chrome.browser.media.router;
import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnDismissListener;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v7.app.MediaRouteControllerDialogFragment; import android.support.v7.app.MediaRouteControllerDialogFragment;
import android.support.v7.app.MediaRouteDialogFactory;
import android.support.v7.media.MediaRouter; import android.support.v7.media.MediaRouter;
import org.chromium.chrome.browser.media.router.cast.MediaSource; import org.chromium.chrome.browser.media.router.cast.MediaSource;
...@@ -20,13 +16,13 @@ import org.chromium.chrome.browser.media.router.cast.MediaSource; ...@@ -20,13 +16,13 @@ import org.chromium.chrome.browser.media.router.cast.MediaSource;
/** /**
* Manages the dialog responsible for controlling an existing media route. * Manages the dialog responsible for controlling an existing media route.
*/ */
public class MediaRouteControllerDialogManager extends BaseMediaRouteDialogManager implements public class MediaRouteControllerDialogManager extends BaseMediaRouteDialogManager {
OnCancelListener, OnDismissListener {
private static final String DIALOG_FRAGMENT_TAG = private static final String DIALOG_FRAGMENT_TAG =
"android.support.v7.mediarouter:MediaRouteControllerDialogFragment"; "android.support.v7.mediarouter:MediaRouteControllerDialogFragment";
private final String mMediaRouteId; private final String mMediaRouteId;
private final MediaRouter.Callback mCallback = new MediaRouter.Callback() { private final MediaRouter.Callback mCallback = new MediaRouter.Callback() {
@Override @Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) { public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) {
...@@ -42,32 +38,38 @@ public class MediaRouteControllerDialogManager extends BaseMediaRouteDialogManag ...@@ -42,32 +38,38 @@ public class MediaRouteControllerDialogManager extends BaseMediaRouteDialogManag
} }
@Override @Override
protected DialogFragment openDialogInternal(FragmentManager fm, protected DialogFragment openDialogInternal(FragmentManager fm) {
MediaRouteDialogFactory factory) {
if (fm.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) return null; if (fm.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) return null;
MediaRouteControllerDialogFragment fragment = factory.onCreateControllerDialogFragment(); MediaRouteControllerDialogFragment fragment = new MediaRouteControllerDialogFragment() {
final SystemVisibilitySaver mVisibilitySaver = new SystemVisibilitySaver();
@Override
public void onStart() {
mVisibilitySaver.saveSystemVisibility(getActivity());
super.onStart();
}
@Override
public void onStop() {
super.onStop();
mVisibilitySaver.restoreSystemVisibility(getActivity());
}
@Override
public void onDismiss(DialogInterface dialog) {
delegate().onDialogCancelled();
androidMediaRouter().removeCallback(mCallback);
mDialogFragment = null;
super.onDismiss(dialog);
}
};
fragment.show(fm, DIALOG_FRAGMENT_TAG); fragment.show(fm, DIALOG_FRAGMENT_TAG);
fm.executePendingTransactions(); fm.executePendingTransactions();
Dialog dialog = fragment.getDialog();
if (dialog == null) return null;
dialog.setOnCancelListener(this);
dialog.setOnDismissListener(this);
androidMediaRouter().addCallback(mediaSource().buildRouteSelector(), mCallback); androidMediaRouter().addCallback(mediaSource().buildRouteSelector(), mCallback);
return fragment; return fragment;
} }
@Override
public void onCancel(DialogInterface dialog) {
delegate().onDialogCancelled();
}
@Override
public void onDismiss(DialogInterface dialog) {
androidMediaRouter().removeCallback(mCallback);
closeDialog();
}
} }
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