Commit 6df7df3b authored by Haiyang Pan's avatar Haiyang Pan Committed by Commit Bot

Revert "Download later: Implements lots of things in download later dialog."

This reverts commit 5a04dad7.

Reason for revert: Tests crash consistently since the builds
https://ci.chromium.org/p/chromium/builders/ci/android-pie-x86-rel/1294
https://ci.chromium.org/p/chromium/builders/ci/android-arm64-proguard-rel/2083
And flakily since https://ci.chromium.org/p/chromium/builders/ci/android-pie-arm64-rel/5696

Original change's description:
> Download later: Implements lots of things in download later dialog.
> 
> This CL does the following:
> 
> 1. Implements the checkbox.
> 2. Implements the edit location text, which triggers location dialog.
> 3. Make download later dialog owns a date time picker, so other callers
> can share the glue code between later dialog and date time picker.
> 4. Lots of tests added, lots of code refactored.
> 
> TBR=dtrainor@chromium.org
> 
> Bug: 1099989,1078454
> Change-Id: I3dd53c0a0694c91789398382c6deb11fbfe8006d
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2268467
> Reviewed-by: Shakti Sahu <shaktisahu@chromium.org>
> Reviewed-by: Hesen Zhang <hesen@chromium.org>
> Commit-Queue: Xing Liu <xingliu@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#784260}

TBR=dtrainor@chromium.org,qinmin@chromium.org,shaktisahu@chromium.org,xingliu@chromium.org,hesen@chromium.org

Change-Id: Idd5217d490c209c38a2fc1174d771daa9c877c62
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 1099989, 1078454
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2278124Reviewed-by: default avatarHaiyang Pan <hypan@google.com>
Commit-Queue: Haiyang Pan <hypan@google.com>
Cr-Commit-Position: refs/heads/master@{#784447}
parent 8d2ef827
...@@ -58,7 +58,8 @@ public class DownloadDateTimePickerDialogTest { ...@@ -58,7 +58,8 @@ public class DownloadDateTimePickerDialogTest {
.with(DownloadDateTimePickerDialogProperties.STATE, State.DATE) .with(DownloadDateTimePickerDialogProperties.STATE, State.DATE)
.with(DownloadDateTimePickerDialogProperties.INITIAL_TIME, now) .with(DownloadDateTimePickerDialogProperties.INITIAL_TIME, now)
.with(DownloadDateTimePickerDialogProperties.MIN_TIME, now) .with(DownloadDateTimePickerDialogProperties.MIN_TIME, now)
.with(DownloadDateTimePickerDialogProperties.MAX_TIME, now + 100000000) .with(DownloadDateTimePickerDialogProperties.MAX_TIME,
now + DownloadDateTimePickerDialogCoordinator.MAX_TIME)
.build(); .build();
mDialog = new DownloadDateTimePickerDialogCoordinator(); mDialog = new DownloadDateTimePickerDialogCoordinator();
Assert.assertNotNull(mController); Assert.assertNotNull(mController);
......
...@@ -4,13 +4,8 @@ ...@@ -4,13 +4,8 @@
package org.chromium.chrome.browser.download.dialogs; package org.chromium.chrome.browser.download.dialogs;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import androidx.test.filters.MediumTest; import androidx.test.filters.MediumTest;
...@@ -26,11 +21,9 @@ import org.chromium.base.test.util.CommandLineFlags; ...@@ -26,11 +21,9 @@ import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.chrome.browser.download.DownloadLaterPromptStatus; import org.chromium.chrome.browser.download.DownloadLaterPromptStatus;
import org.chromium.chrome.browser.download.R; import org.chromium.chrome.browser.download.R;
import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.components.browser_ui.widget.RadioButtonWithDescription; import org.chromium.components.browser_ui.widget.RadioButtonWithDescription;
import org.chromium.components.prefs.PrefService;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.ui.modaldialog.DialogDismissalCause; import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.ui.modaldialog.ModalDialogManager;
...@@ -44,8 +37,6 @@ import org.chromium.ui.modelutil.PropertyModel; ...@@ -44,8 +37,6 @@ import org.chromium.ui.modelutil.PropertyModel;
@RunWith(ChromeJUnit4ClassRunner.class) @RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class DownloadLaterDialogTest { public class DownloadLaterDialogTest {
private static final long INVALID_START_TIME = -1;
@Rule @Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
...@@ -55,12 +46,6 @@ public class DownloadLaterDialogTest { ...@@ -55,12 +46,6 @@ public class DownloadLaterDialogTest {
@Mock @Mock
private DownloadLaterDialogController mController; private DownloadLaterDialogController mController;
@Mock
DownloadDateTimePickerDialogCoordinator mDateTimePicker;
@Mock
PrefService mPrefService;
private ModalDialogManager getModalDialogManager() { private ModalDialogManager getModalDialogManager() {
return mActivityTestRule.getActivity().getModalDialogManager(); return mActivityTestRule.getActivity().getModalDialogManager();
} }
...@@ -73,12 +58,8 @@ public class DownloadLaterDialogTest { ...@@ -73,12 +58,8 @@ public class DownloadLaterDialogTest {
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
when(mPrefService.getInteger(Pref.DOWNLOAD_LATER_PROMPT_STATUS))
.thenReturn(DownloadLaterPromptStatus.SHOW_INITIAL);
mActivityTestRule.startMainActivityOnBlankPage(); mActivityTestRule.startMainActivityOnBlankPage();
TestThreadUtils.runOnUiThreadBlocking(() -> { TestThreadUtils.runOnUiThreadBlocking(() -> {
mDialogCoordinator = new DownloadLaterDialogCoordinator(mDateTimePicker);
mModel = new PropertyModel.Builder(DownloadLaterDialogProperties.ALL_KEYS) mModel = new PropertyModel.Builder(DownloadLaterDialogProperties.ALL_KEYS)
.with(DownloadLaterDialogProperties.CONTROLLER, mDialogCoordinator) .with(DownloadLaterDialogProperties.CONTROLLER, mDialogCoordinator)
.with(DownloadLaterDialogProperties.DOWNLOAD_TIME_INITIAL_SELECTION, .with(DownloadLaterDialogProperties.DOWNLOAD_TIME_INITIAL_SELECTION,
...@@ -86,6 +67,7 @@ public class DownloadLaterDialogTest { ...@@ -86,6 +67,7 @@ public class DownloadLaterDialogTest {
.with(DownloadLaterDialogProperties.DONT_SHOW_AGAIN_SELECTION, .with(DownloadLaterDialogProperties.DONT_SHOW_AGAIN_SELECTION,
DownloadLaterPromptStatus.SHOW_INITIAL) DownloadLaterPromptStatus.SHOW_INITIAL)
.build(); .build();
mDialogCoordinator = new DownloadLaterDialogCoordinator();
Assert.assertNotNull(mController); Assert.assertNotNull(mController);
mDialogCoordinator.initialize(mController); mDialogCoordinator.initialize(mController);
}); });
...@@ -93,7 +75,7 @@ public class DownloadLaterDialogTest { ...@@ -93,7 +75,7 @@ public class DownloadLaterDialogTest {
private void showDialog() { private void showDialog() {
mDialogCoordinator.showDialog( mDialogCoordinator.showDialog(
mActivityTestRule.getActivity(), getModalDialogManager(), mPrefService, mModel); mActivityTestRule.getActivity(), getModalDialogManager(), mModel);
} }
private void clickPositiveButton() { private void clickPositiveButton() {
...@@ -152,25 +134,8 @@ public class DownloadLaterDialogTest { ...@@ -152,25 +134,8 @@ public class DownloadLaterDialogTest {
getDownloadLaterDialogView().onCheckedChanged(null, -1); getDownloadLaterDialogView().onCheckedChanged(null, -1);
clickPositiveButton(); clickPositiveButton();
verify(mController) verify(mController)
.onDownloadLaterDialogComplete( .onDownloadLaterDialogComplete(eq(DownloadLaterDialogChoice.DOWNLOAD_NOW),
eq(DownloadLaterDialogChoice.DOWNLOAD_NOW), eq(INVALID_START_TIME)); eq(DownloadLaterPromptStatus.DONT_SHOW));
});
}
@Test
@MediumTest
public void testSelectDownloadLater() {
TestThreadUtils.runOnUiThreadBlocking(() -> {
showDialog();
RadioButtonWithDescription downloadLaterButton =
getDownloadLaterDialogView().findViewById(R.id.choose_date_time);
Assert.assertNotNull(downloadLaterButton);
downloadLaterButton.setChecked(true);
getDownloadLaterDialogView().onCheckedChanged(null, -1);
clickPositiveButton();
verify(mController, times(0)).onDownloadLaterDialogComplete(anyInt(), anyLong());
verify(mDateTimePicker).showDialog(any(), any(), any());
}); });
} }
} }
...@@ -5,11 +5,12 @@ ...@@ -5,11 +5,12 @@
package org.chromium.chrome.browser.download; package org.chromium.chrome.browser.download;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.download.dialogs.DownloadDateTimePickerDialogCoordinator; import org.chromium.chrome.browser.download.dialogs.DownloadDateTimePickerDialogCoordinator;
import org.chromium.chrome.browser.download.dialogs.DownloadDateTimePickerDialogProperties;
import org.chromium.chrome.browser.download.dialogs.DownloadDateTimePickerDialogProperties.State;
import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogChoice; import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogChoice;
import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogController; import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogController;
import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogCoordinator; import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogCoordinator;
...@@ -35,47 +36,49 @@ import org.chromium.ui.modelutil.PropertyModel; ...@@ -35,47 +36,49 @@ import org.chromium.ui.modelutil.PropertyModel;
* When {@link ChromeFeatureList#DOWNLOAD_LATER} is disabled, only the download location dialog will * When {@link ChromeFeatureList#DOWNLOAD_LATER} is disabled, only the download location dialog will
* be shown. * be shown.
*/ */
public class DownloadDialogBridge public class DownloadDialogBridge implements DownloadLocationDialogController,
implements DownloadLocationDialogController, DownloadLaterDialogController { DownloadLaterDialogController,
DownloadDateTimePickerDialogCoordinator.Controller {
private static final long INVALID_START_TIME = -1; private static final long INVALID_START_TIME = -1;
private long mNativeDownloadDialogBridge; private long mNativeDownloadDialogBridge;
private final DownloadLocationDialogCoordinator mLocationDialog; private final DownloadLocationDialogCoordinator mLocationDialog;
private final DownloadLaterDialogCoordinator mDownloadLaterDialog; private final DownloadLaterDialogCoordinator mDownloadLaterDialog;
private final DownloadDateTimePickerDialogCoordinator mDateTimePickerDialog;
private Context mContext; private Activity mActivity;
private ModalDialogManager mModalDialogManager; private ModalDialogManager mModalDialogManager;
private long mTotalBytes; private long mTotalBytes;
private @DownloadLocationDialogType int mLocationDialogType; private @DownloadLocationDialogType int mLocationDialogType;
private String mSuggestedPath; private String mSuggestedPath;
private PrefService mPrefService; private PrefService mPrefService;
// Whether the user clicked the edit text to open download location dialog.
private boolean mEditLocation;
@DownloadLaterDialogChoice @DownloadLaterDialogChoice
private int mDownloadLaterChoice = DownloadLaterDialogChoice.DOWNLOAD_NOW; private int mDownloadLaterChoice = DownloadLaterDialogChoice.DOWNLOAD_NOW;
@DownloadLaterPromptStatus
private int mDownloadLaterPromptStatus = DownloadLaterPromptStatus.SHOW_INITIAL;
private long mDownloadLaterTime = INVALID_START_TIME; private long mDownloadLaterTime = INVALID_START_TIME;
public DownloadDialogBridge(long nativeDownloadDialogBridge, public DownloadDialogBridge(long nativeDownloadDialogBridge,
DownloadLaterDialogCoordinator downloadLaterDialog, DownloadLaterDialogCoordinator downloadLaterDialog,
DownloadDateTimePickerDialogCoordinator dateTimePickerDialog,
DownloadLocationDialogCoordinator locationDialog) { DownloadLocationDialogCoordinator locationDialog) {
mNativeDownloadDialogBridge = nativeDownloadDialogBridge; mNativeDownloadDialogBridge = nativeDownloadDialogBridge;
mDownloadLaterDialog = downloadLaterDialog; mDownloadLaterDialog = downloadLaterDialog;
mDateTimePickerDialog = dateTimePickerDialog;
mLocationDialog = locationDialog; mLocationDialog = locationDialog;
} }
@CalledByNative @CalledByNative
private static DownloadDialogBridge create(long nativeDownloadDialogBridge) { private static DownloadDialogBridge create(long nativeDownloadDialogBridge) {
DownloadLocationDialogCoordinator locationDialog = new DownloadLocationDialogCoordinator(); DownloadLocationDialogCoordinator locationDialog = new DownloadLocationDialogCoordinator();
DownloadLaterDialogCoordinator downloadLaterDialog = new DownloadLaterDialogCoordinator();
DownloadDateTimePickerDialogCoordinator dateTimePickerDialog = DownloadDateTimePickerDialogCoordinator dateTimePickerDialog =
new DownloadDateTimePickerDialogCoordinator(); new DownloadDateTimePickerDialogCoordinator();
DownloadLaterDialogCoordinator downloadLaterDialog = DownloadDialogBridge bridge = new DownloadDialogBridge(nativeDownloadDialogBridge,
new DownloadLaterDialogCoordinator(dateTimePickerDialog); downloadLaterDialog, dateTimePickerDialog, locationDialog);
dateTimePickerDialog.initialize(downloadLaterDialog);
DownloadDialogBridge bridge = new DownloadDialogBridge(
nativeDownloadDialogBridge, downloadLaterDialog, locationDialog);
downloadLaterDialog.initialize(bridge); downloadLaterDialog.initialize(bridge);
dateTimePickerDialog.initialize(bridge);
locationDialog.initialize(bridge); locationDialog.initialize(bridge);
return bridge; return bridge;
} }
...@@ -91,6 +94,7 @@ public class DownloadDialogBridge ...@@ -91,6 +94,7 @@ public class DownloadDialogBridge
private void showDialog(WindowAndroid windowAndroid, long totalBytes, private void showDialog(WindowAndroid windowAndroid, long totalBytes,
@DownloadLocationDialogType int dialogType, String suggestedPath, @DownloadLocationDialogType int dialogType, String suggestedPath,
boolean supportsLaterDialog) { boolean supportsLaterDialog) {
if (mPrefService == null) mPrefService = getPrefService();
Activity activity = windowAndroid.getActivity().get(); Activity activity = windowAndroid.getActivity().get();
if (activity == null) { if (activity == null) {
onCancel(); onCancel();
...@@ -99,17 +103,15 @@ public class DownloadDialogBridge ...@@ -99,17 +103,15 @@ public class DownloadDialogBridge
ModalDialogManager modalDialogManager = ModalDialogManager modalDialogManager =
((ModalDialogManagerHolder) activity).getModalDialogManager(); ((ModalDialogManagerHolder) activity).getModalDialogManager();
showDialog(activity, modalDialogManager, getPrefService(), totalBytes, dialogType, showDialog(activity, modalDialogManager, totalBytes, dialogType, suggestedPath,
suggestedPath, supportsLaterDialog); supportsLaterDialog);
} }
void showDialog(Context context, ModalDialogManager modalDialogManager, PrefService prefService, void showDialog(Activity activity, ModalDialogManager modalDialogManager, long totalBytes,
long totalBytes, @DownloadLocationDialogType int dialogType, String suggestedPath, @DownloadLocationDialogType int dialogType, String suggestedPath,
boolean supportsLaterDialog) { boolean supportsLaterDialog) {
mContext = context; mActivity = activity;
mModalDialogManager = modalDialogManager; mModalDialogManager = modalDialogManager;
mPrefService = prefService;
mTotalBytes = totalBytes; mTotalBytes = totalBytes;
mLocationDialogType = dialogType; mLocationDialogType = dialogType;
mSuggestedPath = suggestedPath; mSuggestedPath = suggestedPath;
...@@ -117,23 +119,42 @@ public class DownloadDialogBridge ...@@ -117,23 +119,42 @@ public class DownloadDialogBridge
mDownloadLaterChoice = DownloadLaterDialogChoice.DOWNLOAD_NOW; mDownloadLaterChoice = DownloadLaterDialogChoice.DOWNLOAD_NOW;
mDownloadLaterTime = INVALID_START_TIME; mDownloadLaterTime = INVALID_START_TIME;
// Download later dialogs flow only when the network is cellular, where supportsLaterDialog // Download later dialogs flow.
// is true.
if (ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOAD_LATER) && supportsLaterDialog) { if (ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOAD_LATER) && supportsLaterDialog) {
showDownloadLaterDialog(); assert mPrefService != null;
@DownloadLaterPromptStatus
int promptStatus = mPrefService.getInteger(Pref.DOWNLOAD_LATER_PROMPT_STATUS);
PropertyModel model =
new PropertyModel.Builder(DownloadLaterDialogProperties.ALL_KEYS)
.with(DownloadLaterDialogProperties.CONTROLLER, mDownloadLaterDialog)
.with(DownloadLaterDialogProperties.DOWNLOAD_TIME_INITIAL_SELECTION,
DownloadLaterDialogChoice.DOWNLOAD_NOW)
.with(DownloadLaterDialogProperties.DONT_SHOW_AGAIN_SELECTION,
promptStatus)
.with(DownloadLaterDialogProperties.LOCATION_TEXT,
activity.getResources().getString(R.string.menu_downloads))
.build();
mDownloadLaterDialog.showDialog(mActivity, mModalDialogManager, model);
return; return;
} }
// Download location dialog flow.
mLocationDialog.showDialog( mLocationDialog.showDialog(
mContext, mModalDialogManager, totalBytes, dialogType, suggestedPath); mActivity, mModalDialogManager, totalBytes, dialogType, suggestedPath);
} }
private void onComplete() { private void onComplete(String returnedPath, boolean onlyOnWifi, long startTime) {
if (mNativeDownloadDialogBridge == 0) return; if (mNativeDownloadDialogBridge == 0) return;
boolean onlyOnWifi = (mDownloadLaterChoice == DownloadLaterDialogChoice.ON_WIFI); if (ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOAD_LATER)
&& mDownloadLaterPromptStatus != DownloadLaterPromptStatus.SHOW_INITIAL) {
assert mPrefService != null;
mPrefService.setInteger(Pref.DOWNLOAD_LATER_PROMPT_STATUS, mDownloadLaterPromptStatus);
}
DownloadDialogBridgeJni.get().onComplete(mNativeDownloadDialogBridge, DownloadDialogBridgeJni.get().onComplete(mNativeDownloadDialogBridge,
DownloadDialogBridge.this, mSuggestedPath, onlyOnWifi, mDownloadLaterTime); DownloadDialogBridge.this, returnedPath, onlyOnWifi, startTime);
} }
private void onCancel() { private void onCancel() {
...@@ -142,22 +163,37 @@ public class DownloadDialogBridge ...@@ -142,22 +163,37 @@ public class DownloadDialogBridge
mNativeDownloadDialogBridge, DownloadDialogBridge.this); mNativeDownloadDialogBridge, DownloadDialogBridge.this);
} }
private void showLocationDialog() {
mLocationDialog.showDialog(
mActivity, mModalDialogManager, mTotalBytes, mLocationDialogType, mSuggestedPath);
}
// DownloadLaterDialogController implementation. // DownloadLaterDialogController implementation.
@Override @Override
public void onDownloadLaterDialogComplete( public void onDownloadLaterDialogComplete(
@DownloadLaterDialogChoice int choice, long startTime) { @DownloadLaterDialogChoice int choice, @DownloadPromptStatus int promptStatus) {
// Cache the result from download later dialog.
mDownloadLaterChoice = choice; mDownloadLaterChoice = choice;
mDownloadLaterTime = startTime; mDownloadLaterPromptStatus = promptStatus;
// When there is no error message, skip the location dialog. mDownloadLaterDialog.dismissDialog(DialogDismissalCause.POSITIVE_BUTTON_CLICKED);
if (mLocationDialogType == DownloadLocationDialogType.DEFAULT) {
onComplete(); // Let the user to pick date and time if they choose to download later.
if (mDownloadLaterChoice == DownloadLaterDialogChoice.DOWNLOAD_LATER) {
long now = System.currentTimeMillis();
// TODO(xingliu): Round up default time to next hour from now.
PropertyModel model =
new PropertyModel.Builder(DownloadDateTimePickerDialogProperties.ALL_KEYS)
.with(DownloadDateTimePickerDialogProperties.STATE, State.DATE)
.with(DownloadDateTimePickerDialogProperties.INITIAL_TIME, now)
.with(DownloadDateTimePickerDialogProperties.MIN_TIME, now)
.build();
mDateTimePickerDialog.showDialog(mActivity, mModalDialogManager, model);
return; return;
} }
// The location dialog has error message text, show the location dialog after the download // For non download later options, show the next dialog.
// later dialog. showLocationDialog();
showLocationDialog(false /*editLocation*/);
} }
@Override @Override
...@@ -167,64 +203,34 @@ public class DownloadDialogBridge ...@@ -167,64 +203,34 @@ public class DownloadDialogBridge
@Override @Override
public void onEditLocationClicked() { public void onEditLocationClicked() {
mDownloadLaterDialog.dismissDialog(DialogDismissalCause.ACTION_ON_CONTENT); // TODO(xingliu): Trigger download location dialog. After it's done, come back to this flow.
// The user clicked the edit location text.
showLocationDialog(true /* editLocation */);
} }
private void showLocationDialog(boolean editLocation) { // DownloadDateTimePickerDialogCoordinator.Controller.
mEditLocation = editLocation; @Override
public void onDateTimePicked(long time) {
mDownloadLaterChoice = mDownloadLaterDialog.getChoice(); mDownloadLaterTime = time;
mLocationDialog.showDialog( // Show the next dialog.
mContext, mModalDialogManager, mTotalBytes, mLocationDialogType, mSuggestedPath); showLocationDialog();
} }
private void showDownloadLaterDialog() { @Override
assert mPrefService != null; public void onDateTimePickerCanceled() {
@DownloadLaterPromptStatus onCancel();
int promptStatus = mPrefService.getInteger(Pref.DOWNLOAD_LATER_PROMPT_STATUS);
PropertyModel model =
new PropertyModel.Builder(DownloadLaterDialogProperties.ALL_KEYS)
.with(DownloadLaterDialogProperties.CONTROLLER, mDownloadLaterDialog)
.with(DownloadLaterDialogProperties.DOWNLOAD_TIME_INITIAL_SELECTION,
mDownloadLaterChoice)
.with(DownloadLaterDialogProperties.DONT_SHOW_AGAIN_SELECTION, promptStatus)
.with(DownloadLaterDialogProperties.LOCATION_TEXT,
mContext.getResources().getString(R.string.menu_downloads))
.build();
mDownloadLaterDialog.showDialog(mContext, mModalDialogManager, mPrefService, model);
} }
// DownloadLocationDialogController implementation. // DownloadLocationDialogController implementation.
@Override @Override
public void onDownloadLocationDialogComplete(String returnedPath) { public void onDownloadLocationDialogComplete(String returnedPath) {
mSuggestedPath = returnedPath; boolean onlyOnWifi = false;
// The location dialog is triggered automatically, complete the flow. if (mDownloadLaterChoice == DownloadLaterDialogChoice.ON_WIFI) onlyOnWifi = true;
if (!mEditLocation) { onComplete(returnedPath, onlyOnWifi, mDownloadLaterTime);
onComplete();
return;
}
// The location dialog is triggered by the "Edit" text. Show the download later dialog
// again.
mEditLocation = false;
showDownloadLaterDialog();
} }
@Override @Override
public void onDownloadLocationDialogCanceled() { public void onDownloadLocationDialogCanceled() {
if (!mEditLocation) { onCancel();
onCancel();
return;
}
// The location dialog is triggered by the "Edit" text. Show the download later dialog
// again.
mEditLocation = false;
showDownloadLaterDialog();
} }
void setPrefServiceForTesting(PrefService prefService) { void setPrefServiceForTesting(PrefService prefService) {
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
package org.chromium.chrome.browser.download; package org.chromium.chrome.browser.download;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
...@@ -30,6 +29,7 @@ import org.robolectric.annotation.Config; ...@@ -30,6 +29,7 @@ import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLog; import org.robolectric.shadows.ShadowLog;
import org.chromium.base.test.util.JniMocker; import org.chromium.base.test.util.JniMocker;
import org.chromium.chrome.browser.download.dialogs.DownloadDateTimePickerDialogCoordinator;
import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogChoice; import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogChoice;
import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogCoordinator; import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogCoordinator;
import org.chromium.chrome.browser.download.dialogs.DownloadLocationDialogCoordinator; import org.chromium.chrome.browser.download.dialogs.DownloadLocationDialogCoordinator;
...@@ -51,10 +51,7 @@ public class DownloadDialogBridgeUnitTest { ...@@ -51,10 +51,7 @@ public class DownloadDialogBridgeUnitTest {
private static final long START_TIME = 1000; private static final long START_TIME = 1000;
private static final long TOTAL_BYTES = 100; private static final long TOTAL_BYTES = 100;
private static final @DownloadLocationDialogType int LOCATION_DIALOG_TYPE = private static final @DownloadLocationDialogType int LOCATION_DIALOG_TYPE =
DownloadLocationDialogType.DEFAULT; org.chromium.chrome.browser.download.DownloadLocationDialogType.DEFAULT;
private static final @DownloadLocationDialogType int LOCATION_DIALOG_ERROR_TYPE =
DownloadLocationDialogType.NAME_CONFLICT;
private static final String SUGGESTED_PATH = "sdcard/download.txt"; private static final String SUGGESTED_PATH = "sdcard/download.txt";
private static final String NEW_SUGGESTED_PATH = "sdcard/new_download.txt"; private static final String NEW_SUGGESTED_PATH = "sdcard/new_download.txt";
...@@ -80,6 +77,9 @@ public class DownloadDialogBridgeUnitTest { ...@@ -80,6 +77,9 @@ public class DownloadDialogBridgeUnitTest {
@Mock @Mock
DownloadLaterDialogCoordinator mDownloadLaterDialog; DownloadLaterDialogCoordinator mDownloadLaterDialog;
@Mock
DownloadDateTimePickerDialogCoordinator mDateTimePickerDialog;
@Mock @Mock
private PrefService mPrefService; private PrefService mPrefService;
...@@ -89,8 +89,8 @@ public class DownloadDialogBridgeUnitTest { ...@@ -89,8 +89,8 @@ public class DownloadDialogBridgeUnitTest {
ShadowLog.stream = System.out; ShadowLog.stream = System.out;
mJniMocker.mock(DownloadDialogBridgeJni.TEST_HOOKS, mNativeMock); mJniMocker.mock(DownloadDialogBridgeJni.TEST_HOOKS, mNativeMock);
mActivity = Robolectric.buildActivity(Activity.class).setup().get(); mActivity = Robolectric.buildActivity(Activity.class).setup().get();
mBridge = mBridge = new DownloadDialogBridge(
new DownloadDialogBridge(FAKE_NATIVE_HOLDER, mDownloadLaterDialog, mLocationDialog); FAKE_NATIVE_HOLDER, mDownloadLaterDialog, mDateTimePickerDialog, mLocationDialog);
mBridge.setPrefServiceForTesting(mPrefService); mBridge.setPrefServiceForTesting(mPrefService);
when(mPrefService.getInteger(Pref.DOWNLOAD_LATER_PROMPT_STATUS)) when(mPrefService.getInteger(Pref.DOWNLOAD_LATER_PROMPT_STATUS))
.thenReturn(DownloadLaterPromptStatus.SHOW_INITIAL); .thenReturn(DownloadLaterPromptStatus.SHOW_INITIAL);
...@@ -102,20 +102,6 @@ public class DownloadDialogBridgeUnitTest { ...@@ -102,20 +102,6 @@ public class DownloadDialogBridgeUnitTest {
mActivity = null; mActivity = null;
} }
private void showDialog() {
mBridge.showDialog(mActivity, mModalDialogManager, mPrefService, TOTAL_BYTES,
LOCATION_DIALOG_TYPE, SUGGESTED_PATH, true);
}
private void locationDialogWillReturn(String newPath) {
doAnswer(invocation -> {
mBridge.onDownloadLocationDialogComplete(newPath);
return null;
})
.when(mLocationDialog)
.showDialog(any(), any(), eq(TOTAL_BYTES), anyInt(), eq(SUGGESTED_PATH));
}
@Test @Test
@Features.DisableFeatures({ChromeFeatureList.DOWNLOAD_LATER}) @Features.DisableFeatures({ChromeFeatureList.DOWNLOAD_LATER})
public void testShowDialog_disableDownloadLater() { public void testShowDialog_disableDownloadLater() {
...@@ -127,7 +113,8 @@ public class DownloadDialogBridgeUnitTest { ...@@ -127,7 +113,8 @@ public class DownloadDialogBridgeUnitTest {
.showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE), .showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE),
eq(SUGGESTED_PATH)); eq(SUGGESTED_PATH));
showDialog(); mBridge.showDialog(mActivity, mModalDialogManager, TOTAL_BYTES, LOCATION_DIALOG_TYPE,
SUGGESTED_PATH, true);
verify(mLocationDialog) verify(mLocationDialog)
.showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE), .showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE),
eq(SUGGESTED_PATH)); eq(SUGGESTED_PATH));
...@@ -147,8 +134,8 @@ public class DownloadDialogBridgeUnitTest { ...@@ -147,8 +134,8 @@ public class DownloadDialogBridgeUnitTest {
.showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE), .showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE),
eq(SUGGESTED_PATH)); eq(SUGGESTED_PATH));
mBridge.showDialog(mActivity, mModalDialogManager, mPrefService, TOTAL_BYTES, mBridge.showDialog(mActivity, mModalDialogManager, TOTAL_BYTES, LOCATION_DIALOG_TYPE,
LOCATION_DIALOG_TYPE, SUGGESTED_PATH, false /*isOnMeteredNetwork*/); SUGGESTED_PATH, false /*isOnMeteredNetwork*/);
verify(mLocationDialog) verify(mLocationDialog)
.showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE), .showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE),
eq(SUGGESTED_PATH)); eq(SUGGESTED_PATH));
...@@ -174,7 +161,8 @@ public class DownloadDialogBridgeUnitTest { ...@@ -174,7 +161,8 @@ public class DownloadDialogBridgeUnitTest {
.showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE), .showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE),
eq(SUGGESTED_PATH)); eq(SUGGESTED_PATH));
showDialog(); mBridge.showDialog(mActivity, mModalDialogManager, TOTAL_BYTES, LOCATION_DIALOG_TYPE,
SUGGESTED_PATH, true);
verify(mNativeMock).onCanceled(anyLong(), any()); verify(mNativeMock).onCanceled(anyLong(), any());
} }
...@@ -183,17 +171,29 @@ public class DownloadDialogBridgeUnitTest { ...@@ -183,17 +171,29 @@ public class DownloadDialogBridgeUnitTest {
public void testDownloadLaterComplete_downloadNow() { public void testDownloadLaterComplete_downloadNow() {
doAnswer(invocation -> { doAnswer(invocation -> {
mBridge.onDownloadLaterDialogComplete( mBridge.onDownloadLaterDialogComplete(
DownloadLaterDialogChoice.DOWNLOAD_NOW, INVALID_START_TIME); DownloadLaterDialogChoice.DOWNLOAD_NOW, DownloadLaterPromptStatus.DONT_SHOW);
return null; return null;
}) })
.when(mDownloadLaterDialog) .when(mDownloadLaterDialog)
.showDialog(any(), any(), any(), any()); .showDialog(any(), any(), any());
doAnswer(invocation -> {
mBridge.onDownloadLocationDialogComplete(NEW_SUGGESTED_PATH);
return null;
})
.when(mLocationDialog)
.showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE),
eq(SUGGESTED_PATH));
mBridge.showDialog(mActivity, mModalDialogManager, TOTAL_BYTES, LOCATION_DIALOG_TYPE,
SUGGESTED_PATH, true);
verify(mDownloadLaterDialog).showDialog(any(), any(), any());
verify(mLocationDialog)
.showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE),
eq(SUGGESTED_PATH));
showDialog();
verify(mDownloadLaterDialog).showDialog(any(), any(), any(), any());
verify(mNativeMock) verify(mNativeMock)
.onComplete( .onComplete(anyLong(), any(), eq(NEW_SUGGESTED_PATH), eq(false),
anyLong(), any(), eq(SUGGESTED_PATH), eq(false), eq(INVALID_START_TIME)); eq(INVALID_START_TIME));
} }
@Test @Test
...@@ -201,16 +201,29 @@ public class DownloadDialogBridgeUnitTest { ...@@ -201,16 +201,29 @@ public class DownloadDialogBridgeUnitTest {
public void testDownloadLaterComplete_downloadOnWifi() { public void testDownloadLaterComplete_downloadOnWifi() {
doAnswer(invocation -> { doAnswer(invocation -> {
mBridge.onDownloadLaterDialogComplete( mBridge.onDownloadLaterDialogComplete(
DownloadLaterDialogChoice.ON_WIFI, INVALID_START_TIME); DownloadLaterDialogChoice.ON_WIFI, DownloadLaterPromptStatus.DONT_SHOW);
return null; return null;
}) })
.when(mDownloadLaterDialog) .when(mDownloadLaterDialog)
.showDialog(any(), any(), any(), any()); .showDialog(any(), any(), any());
doAnswer(invocation -> {
mBridge.onDownloadLocationDialogComplete(NEW_SUGGESTED_PATH);
return null;
})
.when(mLocationDialog)
.showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE),
eq(SUGGESTED_PATH));
mBridge.showDialog(mActivity, mModalDialogManager, TOTAL_BYTES, LOCATION_DIALOG_TYPE,
SUGGESTED_PATH, true);
verify(mDownloadLaterDialog).showDialog(any(), any(), any());
verify(mLocationDialog)
.showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE),
eq(SUGGESTED_PATH));
showDialog();
verify(mDownloadLaterDialog).showDialog(any(), any(), any(), any());
verify(mNativeMock) verify(mNativeMock)
.onComplete(anyLong(), any(), eq(SUGGESTED_PATH), eq(true), eq(INVALID_START_TIME)); .onComplete(
anyLong(), any(), eq(NEW_SUGGESTED_PATH), eq(true), eq(INVALID_START_TIME));
} }
@Test @Test
...@@ -218,62 +231,36 @@ public class DownloadDialogBridgeUnitTest { ...@@ -218,62 +231,36 @@ public class DownloadDialogBridgeUnitTest {
public void testDownloadLaterComplete_downloadLater() { public void testDownloadLaterComplete_downloadLater() {
doAnswer(invocation -> { doAnswer(invocation -> {
mBridge.onDownloadLaterDialogComplete( mBridge.onDownloadLaterDialogComplete(
DownloadLaterDialogChoice.DOWNLOAD_LATER, START_TIME); DownloadLaterDialogChoice.DOWNLOAD_LATER, DownloadLaterPromptStatus.DONT_SHOW);
return null; return null;
}) })
.when(mDownloadLaterDialog) .when(mDownloadLaterDialog)
.showDialog(any(), any(), any(), any()); .showDialog(any(), any(), any());
showDialog();
verify(mDownloadLaterDialog).showDialog(any(), any(), any(), any());
verify(mNativeMock)
.onComplete(anyLong(), any(), eq(SUGGESTED_PATH), eq(false), eq(START_TIME));
}
@Test
@Features.EnableFeatures({ChromeFeatureList.DOWNLOAD_LATER})
public void testLocationErrorMakeLocationDialogShow() {
doAnswer(invocation -> { doAnswer(invocation -> {
mBridge.onDownloadLaterDialogComplete( mBridge.onDownloadLocationDialogComplete(NEW_SUGGESTED_PATH);
DownloadLaterDialogChoice.DOWNLOAD_NOW, INVALID_START_TIME);
return null; return null;
}) })
.when(mDownloadLaterDialog) .when(mLocationDialog)
.showDialog(any(), any(), any(), any()); .showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE),
locationDialogWillReturn(NEW_SUGGESTED_PATH);
// Location dialog has error message, and it will show.
mBridge.showDialog(mActivity, mModalDialogManager, mPrefService, TOTAL_BYTES,
LOCATION_DIALOG_ERROR_TYPE, SUGGESTED_PATH, true);
verify(mDownloadLaterDialog).showDialog(any(), any(), any(), any());
verify(mLocationDialog)
.showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_ERROR_TYPE),
eq(SUGGESTED_PATH)); eq(SUGGESTED_PATH));
verify(mNativeMock)
.onComplete(anyLong(), any(), eq(NEW_SUGGESTED_PATH), eq(false),
eq(INVALID_START_TIME));
}
@Test doAnswer(invocation -> {
@Features.EnableFeatures({ChromeFeatureList.DOWNLOAD_LATER}) mBridge.onDateTimePicked(START_TIME);
public void testClickEditLocationText() { return null;
locationDialogWillReturn(NEW_SUGGESTED_PATH); })
.when(mDateTimePickerDialog)
// Click the "Edit" text to open location dialog. .showDialog(any(), any(), any());
mBridge.showDialog(mActivity, mModalDialogManager, mPrefService, TOTAL_BYTES,
LOCATION_DIALOG_TYPE, SUGGESTED_PATH, true);
mBridge.onEditLocationClicked();
// The flow will open download later dialog, then open location dialog, then open download mBridge.showDialog(mActivity, mModalDialogManager, TOTAL_BYTES, LOCATION_DIALOG_TYPE,
// later dialog again. SUGGESTED_PATH, true);
verify(mDownloadLaterDialog, times(2)).showDialog(any(), any(), any(), any()); verify(mDownloadLaterDialog).showDialog(any(), any(), any());
verify(mLocationDialog) verify(mLocationDialog)
.showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE), .showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE),
eq(SUGGESTED_PATH)); eq(SUGGESTED_PATH));
verify(mDateTimePickerDialog).showDialog(any(), any(), any());
// When finish location dialog, still on download later dialog without completing the flow. verify(mNativeMock)
verify(mNativeMock, times(0)).onComplete(anyLong(), any(), any(), anyBoolean(), anyLong()); .onComplete(anyLong(), any(), eq(NEW_SUGGESTED_PATH), eq(false), eq(START_TIME));
} }
@Test @Test
...@@ -284,10 +271,11 @@ public class DownloadDialogBridgeUnitTest { ...@@ -284,10 +271,11 @@ public class DownloadDialogBridgeUnitTest {
return null; return null;
}) })
.when(mDownloadLaterDialog) .when(mDownloadLaterDialog)
.showDialog(any(), any(), any(), any()); .showDialog(any(), any(), any());
showDialog(); mBridge.showDialog(mActivity, mModalDialogManager, TOTAL_BYTES, LOCATION_DIALOG_TYPE,
verify(mDownloadLaterDialog).showDialog(any(), any(), any(), any()); SUGGESTED_PATH, true);
verify(mDownloadLaterDialog).showDialog(any(), any(), any());
verify(mLocationDialog, times(0)) verify(mLocationDialog, times(0))
.showDialog(any(), any(), anyLong(), anyInt(), anyString()); .showDialog(any(), any(), anyLong(), anyInt(), anyString());
verify(mNativeMock).onCanceled(anyLong(), any()); verify(mNativeMock).onCanceled(anyLong(), any());
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.download.dialogs; package org.chromium.chrome.browser.download.dialogs;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.view.LayoutInflater; import android.view.LayoutInflater;
...@@ -17,6 +18,8 @@ import org.chromium.ui.modaldialog.ModalDialogProperties; ...@@ -17,6 +18,8 @@ import org.chromium.ui.modaldialog.ModalDialogProperties;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
import java.util.concurrent.TimeUnit;
/** /**
* The coordinator for download date time picker. The user can pick an exact time to start the * The coordinator for download date time picker. The user can pick an exact time to start the
* download later. The dialog has two stage: * download later. The dialog has two stage:
...@@ -24,6 +27,8 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor; ...@@ -24,6 +27,8 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
* 2. A clock to let the user to pick a time. * 2. A clock to let the user to pick a time.
*/ */
public class DownloadDateTimePickerDialogCoordinator implements ModalDialogProperties.Controller { public class DownloadDateTimePickerDialogCoordinator implements ModalDialogProperties.Controller {
/** The maximum time that the user can select in the dialog.*/
public static final long MAX_TIME = TimeUnit.DAYS.toMillis(7); /* 7 days */
/** /**
* The controller that receives events from the date time picker. * The controller that receives events from the date time picker.
*/ */
...@@ -59,25 +64,24 @@ public class DownloadDateTimePickerDialogCoordinator implements ModalDialogPrope ...@@ -59,25 +64,24 @@ public class DownloadDateTimePickerDialogCoordinator implements ModalDialogPrope
/** /**
* Shows the date time picker. * Shows the date time picker.
* @param context The {@link Context} for the date time picker.
* @param windowAndroid The window android handle that provides contexts. * @param windowAndroid The window android handle that provides contexts.
* @param model The model that defines the application data used to update the UI view. * @param model The model that defines the application data used to update the UI view.
*/ */
public void showDialog( public void showDialog(
Context context, ModalDialogManager modalDialogManager, PropertyModel model) { Activity activity, ModalDialogManager modalDialogManager, PropertyModel model) {
if (context == null || modalDialogManager == null) { if (activity == null || modalDialogManager == null) {
onDismiss(null, DialogDismissalCause.ACTIVITY_DESTROYED); onDismiss(null, DialogDismissalCause.ACTIVITY_DESTROYED);
return; return;
} }
mModalDialogManager = modalDialogManager; mModalDialogManager = modalDialogManager;
mModel = model; mModel = model;
mView = (DownloadDateTimePickerView) LayoutInflater.from(context).inflate( mView = (DownloadDateTimePickerView) LayoutInflater.from(activity).inflate(
R.layout.download_later_date_time_picker_dialog, null); R.layout.download_later_date_time_picker_dialog, null);
mProcessor = PropertyModelChangeProcessor.create(mModel, mView, mProcessor = PropertyModelChangeProcessor.create(mModel, mView,
DownloadDateTimePickerView.Binder::bind, true /*performInitialBind*/); DownloadDateTimePickerView.Binder::bind, true /*performInitialBind*/);
mModalDialogManager.showDialog( mModalDialogManager.showDialog(
getModalDialogModel(context), ModalDialogManager.ModalDialogType.APP); getModalDialogModel(activity), ModalDialogManager.ModalDialogType.APP);
} }
/** /**
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.download.dialogs; package org.chromium.chrome.browser.download.dialogs;
import org.chromium.chrome.browser.download.DownloadLaterPromptStatus;
/** /**
* Receives events from download later dialog. * Receives events from download later dialog.
*/ */
...@@ -11,10 +13,10 @@ public interface DownloadLaterDialogController { ...@@ -11,10 +13,10 @@ public interface DownloadLaterDialogController {
/** /**
* Called when the selection changed in the download later dialog. * Called when the selection changed in the download later dialog.
* @param choice The selection of the download time in the download later dialog. * @param choice The selection of the download time in the download later dialog.
* @param startTime The start time of the download, selected int the date time picker, or -1 * @param promptStatus The prompt status about the "don't show again" checkbox.
* if the user didn't select the time.
*/ */
void onDownloadLaterDialogComplete(@DownloadLaterDialogChoice int choice, long startTime); void onDownloadLaterDialogComplete(
@DownloadLaterDialogChoice int choice, @DownloadLaterPromptStatus int promptStatus);
/** /**
* Called when the user cancels or dismisses the download location dialog. * Called when the user cancels or dismisses the download location dialog.
......
...@@ -4,15 +4,14 @@ ...@@ -4,15 +4,14 @@
package org.chromium.chrome.browser.download.dialogs; package org.chromium.chrome.browser.download.dialogs;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.chromium.chrome.browser.download.DownloadLaterPromptStatus;
import org.chromium.chrome.browser.download.R; import org.chromium.chrome.browser.download.R;
import org.chromium.chrome.browser.download.dialogs.DownloadDateTimePickerDialogProperties.State;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.components.prefs.PrefService;
import org.chromium.ui.modaldialog.DialogDismissalCause; import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogProperties; import org.chromium.ui.modaldialog.ModalDialogProperties;
...@@ -24,34 +23,15 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor; ...@@ -24,34 +23,15 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
* Coordinator to construct the download later dialog. * Coordinator to construct the download later dialog.
*/ */
public class DownloadLaterDialogCoordinator public class DownloadLaterDialogCoordinator
implements ModalDialogProperties.Controller, DownloadLaterDialogView.Controller, implements ModalDialogProperties.Controller, DownloadLaterDialogView.Controller {
DownloadDateTimePickerDialogCoordinator.Controller {
private static final long INVALID_START_TIME = -1;
private PropertyModel mDownloadLaterDialogModel; private PropertyModel mDownloadLaterDialogModel;
private DownloadLaterDialogView mCustomView; private DownloadLaterDialogView mCustomView;
private Context mContext;
private ModalDialogManager mModalDialogManager; private ModalDialogManager mModalDialogManager;
private PrefService mPrefService;
private PropertyModel mDialogModel; private PropertyModel mDialogModel;
private PropertyModelChangeProcessor<PropertyModel, DownloadLaterDialogView, PropertyKey> private PropertyModelChangeProcessor<PropertyModel, DownloadLaterDialogView, PropertyKey>
mPropertyModelChangeProcessor; mPropertyModelChangeProcessor;
private DownloadLaterDialogController mController; private DownloadLaterDialogController mController;
private final DownloadDateTimePickerDialogCoordinator mDateTimePickerDialog;
@DownloadLaterDialogChoice
private int mDownloadLaterChoice = DownloadLaterDialogChoice.DOWNLOAD_NOW;
/**
* Creates the {@link DownloadLaterDialogCoordinator}.
* @param dateTimePickerDialog The date time selection widget.
*/
public DownloadLaterDialogCoordinator(
@NonNull DownloadDateTimePickerDialogCoordinator dateTimePickerDialog) {
mDateTimePickerDialog = dateTimePickerDialog;
}
/** /**
* Initializes the download location dialog. * Initializes the download location dialog.
...@@ -63,34 +43,28 @@ public class DownloadLaterDialogCoordinator ...@@ -63,34 +43,28 @@ public class DownloadLaterDialogCoordinator
/** /**
* Shows the download later dialog. * Shows the download later dialog.
* @param context The {@link Context} for the dialog. * @param activity The activity that provides android {@link Context} to the dialog.
* @param modalDialogManager {@link ModalDialogManager} to control the dialog. * @param modalDialogManager {@link ModalDialogManager} to control the dialog.
* @param prefService {@link PrefService} to write download later prompt status preference.
* @param model The data model that defines the UI details. * @param model The data model that defines the UI details.
*/ */
public void showDialog(Context context, ModalDialogManager modalDialogManager, public void showDialog(
PrefService prefService, PropertyModel model) { Activity activity, ModalDialogManager modalDialogManager, PropertyModel model) {
if (context == null || modalDialogManager == null) { if (activity == null || modalDialogManager == null) {
onDismiss(null, DialogDismissalCause.ACTIVITY_DESTROYED); onDismiss(null, DialogDismissalCause.ACTIVITY_DESTROYED);
return; return;
} }
mContext = context;
mModalDialogManager = modalDialogManager;
mPrefService = prefService;
// Set up the download later UI MVC. // Set up the download later UI MVC.
mDownloadLaterDialogModel = model; mDownloadLaterDialogModel = model;
mCustomView = (DownloadLaterDialogView) LayoutInflater.from(context).inflate( mCustomView = (DownloadLaterDialogView) LayoutInflater.from(activity).inflate(
R.layout.download_later_dialog, null); R.layout.download_later_dialog, null);
mPropertyModelChangeProcessor = mPropertyModelChangeProcessor =
PropertyModelChangeProcessor.create(mDownloadLaterDialogModel, mCustomView, PropertyModelChangeProcessor.create(mDownloadLaterDialogModel, mCustomView,
DownloadLaterDialogView.Binder::bind, true /*performInitialBind*/); DownloadLaterDialogView.Binder::bind, true /*performInitialBind*/);
mDownloadLaterChoice =
model.get(DownloadLaterDialogProperties.DOWNLOAD_TIME_INITIAL_SELECTION);
// Set up the modal dialog. // Set up the modal dialog.
mDialogModel = getModalDialogModel(context, this); mModalDialogManager = modalDialogManager;
mDialogModel = getModalDialogModel(activity, this);
mModalDialogManager.showDialog(mDialogModel, ModalDialogManager.ModalDialogType.APP); mModalDialogManager.showDialog(mDialogModel, ModalDialogManager.ModalDialogType.APP);
} }
...@@ -103,10 +77,6 @@ public class DownloadLaterDialogCoordinator ...@@ -103,10 +77,6 @@ public class DownloadLaterDialogCoordinator
mModalDialogManager.dismissDialog(mDialogModel, dismissalCause); mModalDialogManager.dismissDialog(mDialogModel, dismissalCause);
} }
public @DownloadLaterDialogChoice int getChoice() {
return mDownloadLaterChoice;
}
/** /**
* Destroy the download later dialog. * Destroy the download later dialog.
*/ */
...@@ -114,13 +84,10 @@ public class DownloadLaterDialogCoordinator ...@@ -114,13 +84,10 @@ public class DownloadLaterDialogCoordinator
if (mPropertyModelChangeProcessor != null) { if (mPropertyModelChangeProcessor != null) {
mPropertyModelChangeProcessor.destroy(); mPropertyModelChangeProcessor.destroy();
} }
if (mModalDialogManager != null) { if (mModalDialogManager != null) {
mModalDialogManager.dismissDialog( mModalDialogManager.dismissDialog(
mDialogModel, DialogDismissalCause.DISMISSED_BY_NATIVE); mDialogModel, DialogDismissalCause.DISMISSED_BY_NATIVE);
} }
mDateTimePickerDialog.destroy();
} }
private PropertyModel getModalDialogModel( private PropertyModel getModalDialogModel(
...@@ -136,51 +103,6 @@ public class DownloadLaterDialogCoordinator ...@@ -136,51 +103,6 @@ public class DownloadLaterDialogCoordinator
.build(); .build();
} }
private void onPositiveButtonClicked(@DownloadLaterDialogChoice int choice) {
mDownloadLaterChoice = choice;
// Immediately show the date time picker when selecting the "Download later".
if (choice == DownloadLaterDialogChoice.DOWNLOAD_LATER) {
dismissDialog(DialogDismissalCause.ACTION_ON_CONTENT);
showDateTimePicker();
return;
}
// The user select "Download now" or "On wifi", no time is selected.
notifyComplete(INVALID_START_TIME);
}
private void showDateTimePicker() {
long now = System.currentTimeMillis();
// TODO(xingliu): Round up default time to next hour from now.
PropertyModel model =
new PropertyModel.Builder(DownloadDateTimePickerDialogProperties.ALL_KEYS)
.with(DownloadDateTimePickerDialogProperties.STATE, State.DATE)
.with(DownloadDateTimePickerDialogProperties.INITIAL_TIME, now)
.with(DownloadDateTimePickerDialogProperties.MIN_TIME, now)
.build();
mDateTimePickerDialog.showDialog(mContext, mModalDialogManager, model);
}
private void notifyComplete(long time) {
assert mController != null;
updatePromptStatus();
mController.onDownloadLaterDialogComplete(mDownloadLaterChoice, time);
}
private void notifyCancel() {
assert mController != null;
updatePromptStatus();
mController.onDownloadLaterDialogCanceled();
}
private void updatePromptStatus() {
assert mCustomView != null;
assert mPrefService != null;
mPrefService.setInteger(Pref.DOWNLOAD_LATER_PROMPT_STATUS, mCustomView.getPromptStatus());
}
// ModalDialogProperties.Controller implementation. // ModalDialogProperties.Controller implementation.
@Override @Override
public void onClick(PropertyModel model, int buttonType) { public void onClick(PropertyModel model, int buttonType) {
...@@ -200,37 +122,23 @@ public class DownloadLaterDialogCoordinator ...@@ -200,37 +122,23 @@ public class DownloadLaterDialogCoordinator
@Override @Override
public void onDismiss(PropertyModel model, @DialogDismissalCause int dismissalCause) { public void onDismiss(PropertyModel model, @DialogDismissalCause int dismissalCause) {
if (dismissalCause == DialogDismissalCause.POSITIVE_BUTTON_CLICKED) { if (dismissalCause == DialogDismissalCause.POSITIVE_BUTTON_CLICKED) {
onPositiveButtonClicked(mDownloadLaterChoice); @DownloadLaterDialogChoice
int choice = (mCustomView == null) ? DownloadLaterDialogChoice.DOWNLOAD_NOW
: mCustomView.getChoice();
@DownloadLaterPromptStatus
int promptStatus = (mCustomView == null) ? DownloadLaterPromptStatus.SHOW_INITIAL
: mCustomView.getPromptStatus();
assert mController != null;
mController.onDownloadLaterDialogComplete(choice, promptStatus);
return; return;
} }
// Temporary dismiss due to the user clicking the "Edit" to open download location dialog. assert mController != null;
if (dismissalCause == DialogDismissalCause.ACTION_ON_CONTENT) return; mController.onDownloadLaterDialogCanceled();
notifyCancel();
}
// DownloadDateTimePickerDialogCoordinator.Controller implementation.
@Override
public void onDateTimePicked(long time) {
notifyComplete(time);
}
@Override
public void onDateTimePickerCanceled() {
notifyCancel();
} }
// DownloadLaterDialogView.Controller.
@Override @Override
public void onEditLocationClicked() { public void onEditLocationClicked() {
// Ask the controller to decide what to do, even though we can dismiss ourselves here.
assert mController != null;
mController.onEditLocationClicked(); mController.onEditLocationClicked();
} }
@Override
public void onCheckedChanged(int choice) {
mDownloadLaterChoice = choice;
}
} }
...@@ -6,16 +6,13 @@ package org.chromium.chrome.browser.download.dialogs; ...@@ -6,16 +6,13 @@ package org.chromium.chrome.browser.download.dialogs;
import android.content.Context; import android.content.Context;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.text.SpannableString;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.Spanned; import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RadioGroup; import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
...@@ -32,7 +29,8 @@ import org.chromium.ui.text.SpanApplier.SpanInfo; ...@@ -32,7 +29,8 @@ import org.chromium.ui.text.SpanApplier.SpanInfo;
/** /**
* The custom view in the download later dialog. * The custom view in the download later dialog.
*/ */
public class DownloadLaterDialogView extends LinearLayout implements OnCheckedChangeListener { public class DownloadLaterDialogView
extends LinearLayout implements RadioGroup.OnCheckedChangeListener {
private Controller mController; private Controller mController;
private RadioButtonWithDescription mDownloadNow; private RadioButtonWithDescription mDownloadNow;
...@@ -42,6 +40,9 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh ...@@ -42,6 +40,9 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh
private CheckBox mCheckBox; private CheckBox mCheckBox;
private TextView mEditText; private TextView mEditText;
// The item that the user selected in the download later dialog UI.
private @DownloadLaterDialogChoice int mChoice = DownloadLaterDialogChoice.DOWNLOAD_NOW;
/** /**
* The view binder to propagate events from model to view. * The view binder to propagate events from model to view.
*/ */
...@@ -71,12 +72,6 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh ...@@ -71,12 +72,6 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh
* Called when the edit location text is clicked. * Called when the edit location text is clicked.
*/ */
void onEditLocationClicked(); void onEditLocationClicked();
/**
* Called when the choice radio buttons changed.
* @param choice The choice that the user selected.
*/
void onCheckedChanged(@DownloadLaterDialogChoice int choice);
} }
public DownloadLaterDialogView(Context context, @Nullable AttributeSet attrs) { public DownloadLaterDialogView(Context context, @Nullable AttributeSet attrs) {
...@@ -114,11 +109,17 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh ...@@ -114,11 +109,17 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh
mDownloadLater.setChecked(true); mDownloadLater.setChecked(true);
break; break;
} }
mChoice = choice;
}
public @DownloadLaterDialogChoice int getChoice() {
return mChoice;
} }
void setCheckbox(@DownloadLaterPromptStatus int promptStatus) { void setCheckbox(@DownloadLaterPromptStatus int promptStatus) {
boolean checked = (promptStatus == DownloadLaterPromptStatus.SHOW_INITIAL) boolean checked = promptStatus == DownloadLaterPromptStatus.SHOW_INITIAL
|| (promptStatus == DownloadLaterPromptStatus.DONT_SHOW); || promptStatus == DownloadLaterPromptStatus.SHOW_PREFERENCE;
mCheckBox.setChecked(checked); mCheckBox.setChecked(checked);
} }
...@@ -128,21 +129,21 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh ...@@ -128,21 +129,21 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh
: DownloadLaterPromptStatus.SHOW_PREFERENCE; : DownloadLaterPromptStatus.SHOW_PREFERENCE;
} }
void setShowEditLocation(@Nullable String locationText) { void setShowEditLocation(String locationText) {
if (locationText == null) { if (locationText == null) {
mEditText.setVisibility(GONE); mEditText.setVisibility(GONE);
return; return;
} }
final SpannableString editText; final CharSequence editText;
final SpannableStringBuilder directorySpanBuilder = new SpannableStringBuilder(); final SpannableStringBuilder directorySpanBuilder = new SpannableStringBuilder();
directorySpanBuilder.append(locationText); directorySpanBuilder.append(locationText);
directorySpanBuilder.setSpan(new StyleSpan(Typeface.BOLD), 0, locationText.length(), directorySpanBuilder.setSpan(new StyleSpan(Typeface.BOLD), 0, locationText.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mEditText.setMovementMethod(LinkMovementMethod.getInstance()); NoUnderlineClickableSpan editSpan = new NoUnderlineClickableSpan(getResources(), (view) -> {
NoUnderlineClickableSpan editSpan = new NoUnderlineClickableSpan( if (mController != null) mController.onEditLocationClicked();
getResources(), (view) -> { onEditLocationClicked(); }); });
editText = SpanApplier.applySpans( editText = SpanApplier.applySpans(
getResources().getString(R.string.download_later_edit_location, locationText), getResources().getString(R.string.download_later_edit_location, locationText),
new SpanInfo("<b>", "</b>", directorySpanBuilder), new SpanInfo("<b>", "</b>", directorySpanBuilder),
...@@ -151,11 +152,6 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh ...@@ -151,11 +152,6 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh
mEditText.setVisibility(VISIBLE); mEditText.setVisibility(VISIBLE);
} }
private void onEditLocationClicked() {
assert mController != null : "Please bind the controller first.";
mController.onEditLocationClicked();
}
// RadioGroup.OnCheckedChangeListener overrides. // RadioGroup.OnCheckedChangeListener overrides.
@Override @Override
public void onCheckedChanged(RadioGroup radioGroup, int index) { public void onCheckedChanged(RadioGroup radioGroup, int index) {
...@@ -168,6 +164,6 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh ...@@ -168,6 +164,6 @@ public class DownloadLaterDialogView extends LinearLayout implements OnCheckedCh
} else if (mDownloadLater.isChecked()) { } else if (mDownloadLater.isChecked()) {
choice = DownloadLaterDialogChoice.DOWNLOAD_LATER; choice = DownloadLaterDialogChoice.DOWNLOAD_LATER;
} }
mController.onCheckedChanged(choice); mChoice = choice;
} }
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.download.dialogs; package org.chromium.chrome.browser.download.dialogs;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.text.TextUtils; import android.text.TextUtils;
...@@ -52,20 +53,20 @@ public class DownloadLocationDialogCoordinator implements ModalDialogProperties. ...@@ -52,20 +53,20 @@ public class DownloadLocationDialogCoordinator implements ModalDialogProperties.
/** /**
* Shows the download location dialog. * Shows the download location dialog.
* @param context The {@link Context} for the dialog. * @param activity The activity that provides android {@link Context} to the dialog.
* @param modalDialogManager {@link ModalDialogManager} to control the dialog. * @param modalDialogManager {@link ModalDialogManager} to control the dialog.
* @param totalBytes The total download file size. May be 0 if not available. * @param totalBytes The total download file size. May be 0 if not available.
* @param dialogType The type of the location dialog. * @param dialogType The type of the location dialog.
* @param suggestedPath The suggested file path used by the location dialog. * @param suggestedPath The suggested file path used by the location dialog.
*/ */
public void showDialog(Context context, ModalDialogManager modalDialogManager, long totalBytes, public void showDialog(Activity activity, ModalDialogManager modalDialogManager,
@DownloadLocationDialogType int dialogType, String suggestedPath) { long totalBytes, @DownloadLocationDialogType int dialogType, String suggestedPath) {
if (context == null || modalDialogManager == null) { if (activity == null || modalDialogManager == null) {
onDismiss(null, DialogDismissalCause.ACTIVITY_DESTROYED); onDismiss(null, DialogDismissalCause.ACTIVITY_DESTROYED);
return; return;
} }
mContext = context; mContext = activity;
mModalDialogManager = modalDialogManager; mModalDialogManager = modalDialogManager;
mTotalBytes = totalBytes; mTotalBytes = totalBytes;
mDialogType = dialogType; mDialogType = dialogType;
......
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