Commit 7865e3c4 authored by Shakti Sahu's avatar Shakti Sahu Committed by Commit Bot

Fixed crash in recycler view due to duplicate stable ids in download home

Sometimes we incorrectly create two Just Now sections in download home.
This leads to a crash in RecyclerView as stable IDs should be unique.
This happens especially when there are two downloads very close to midnight,
one before midnight and one after midnight. This CL fixes this issue
and places both of them in one Just Now section.

Change-Id: I5af6560c29a7413f86a6245719859197d72268dd
Bug: 1020079
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2024068Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Commit-Queue: Shakti Sahu <shaktisahu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#735708}
parent 7d2d7ac4
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.download.home; package org.chromium.chrome.browser.download.home;
import androidx.annotation.VisibleForTesting;
import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.offline_items_collection.ContentId;
import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.components.offline_items_collection.OfflineItem;
import org.chromium.components.offline_items_collection.OfflineItemState; import org.chromium.components.offline_items_collection.OfflineItemState;
...@@ -24,7 +26,7 @@ public class JustNowProvider { ...@@ -24,7 +26,7 @@ public class JustNowProvider {
/** Constructor. */ /** Constructor. */
public JustNowProvider(DownloadManagerUiConfig config) { public JustNowProvider(DownloadManagerUiConfig config) {
mThresholdDate = new Date(new Date().getTime() - config.justNowThresholdSeconds * 1000); mThresholdDate = new Date(now().getTime() - config.justNowThresholdSeconds * 1000);
} }
/** /**
...@@ -41,4 +43,9 @@ public class JustNowProvider { ...@@ -41,4 +43,9 @@ public class JustNowProvider {
|| (item.state == OfflineItemState.INTERRUPTED && item.isResumable) || (item.state == OfflineItemState.INTERRUPTED && item.isResumable)
|| new Date(item.completionTimeMs).after(mThresholdDate); || new Date(item.completionTimeMs).after(mThresholdDate);
} }
}
@VisibleForTesting
protected Date now() {
return new Date();
}
}
\ No newline at end of file
...@@ -54,8 +54,11 @@ public class DateLabelAdder implements ListConsumer { ...@@ -54,8 +54,11 @@ public class DateLabelAdder implements ListConsumer {
if (!(listItem instanceof OfflineItemListItem)) continue; if (!(listItem instanceof OfflineItemListItem)) continue;
OfflineItem offlineItem = ((OfflineItemListItem) listItem).item; OfflineItem offlineItem = ((OfflineItemListItem) listItem).item;
if (startOfNewDay(offlineItem, previousItem) boolean startOfNewDay = startOfNewDay(offlineItem, previousItem);
|| justNowSectionsDiffer(offlineItem, previousItem)) { boolean isJustNow =
mJustNowProvider != null && mJustNowProvider.isJustNowItem(offlineItem);
if (isJustNow) startOfNewDay = false;
if (startOfNewDay || justNowSectionsDiffer(offlineItem, previousItem)) {
addDateHeader(listItems, offlineItem, i); addDateHeader(listItems, offlineItem, i);
} }
......
...@@ -145,7 +145,7 @@ public class DateOrderedListMutatorTest { ...@@ -145,7 +145,7 @@ public class DateOrderedListMutatorTest {
DateOrderedListMutator list = createMutatorWithJustNowProvider(); DateOrderedListMutator list = createMutatorWithJustNowProvider();
Assert.assertEquals(2, mModel.size()); Assert.assertEquals(2, mModel.size());
assertJustNowSection(mModel.get(0), false); assertJustNowSection(mModel.get(0));
assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), item1); assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), item1);
} }
...@@ -159,20 +159,56 @@ public class DateOrderedListMutatorTest { ...@@ -159,20 +159,56 @@ public class DateOrderedListMutatorTest {
*/ */
@Test @Test
public void testMultipleSectionsInJustNowSection() { public void testMultipleSectionsInJustNowSection() {
OfflineItem item1 = buildItem("1", buildCalendar(2018, 1, 1, 1), OfflineItemFilter.VIDEO); Calendar calendar = buildCalendar(2018, 1, 1, 1);
OfflineItem item2 = buildItem("2", buildCalendar(2018, 1, 1, 1), OfflineItemFilter.AUDIO); OfflineItem item1 = buildItem("1", calendar, OfflineItemFilter.VIDEO);
OfflineItem item2 = buildItem("2", calendar, OfflineItemFilter.AUDIO);
item1.state = OfflineItemState.IN_PROGRESS; item1.state = OfflineItemState.IN_PROGRESS;
item2.state = OfflineItemState.IN_PROGRESS; item2.state = OfflineItemState.COMPLETE;
item2.completionTimeMs = item2.creationTimeMs; item2.completionTimeMs = item2.creationTimeMs;
when(mSource.getItems()).thenReturn(CollectionUtil.newArrayList(item1, item2)); when(mSource.getItems()).thenReturn(CollectionUtil.newArrayList(item1, item2));
DateOrderedListMutator list = createMutatorWithJustNowProvider(); DateOrderedListMutator list =
createMutatorWithJustNowProvider(buildJustNowProvider(calendar.getTime()));
Assert.assertEquals(3, mModel.size()); Assert.assertEquals(3, mModel.size());
assertJustNowSection(mModel.get(0), false); assertJustNowSection(mModel.get(0));
assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), item1); assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), item1);
assertOfflineItem(mModel.get(2), buildCalendar(2018, 1, 1, 1), item2); assertOfflineItem(mModel.get(2), buildCalendar(2018, 1, 1, 1), item2);
} }
/**
* Action List
* 1. Set(item1 @ 0:10 1/2/2018 [ DATE Just Now,
* Video COMPLETE,
* item2 @ 23:55 1/1/2018 [ DATE Just Now,
* Video COMPLETE,
*
* item3 @ 10:00 1/1/2018 DATE 1/1/2018
* Audio COMPLETE) item3 @ 1:00 1/1/2018 ]
*/
@Test
public void testRecentItemBeforeMidnightShowsInJustNowSection() {
Calendar calendar1 = CalendarFactory.get();
calendar1.set(2018, 1, 2, 0, 10);
Calendar calendar2 = CalendarFactory.get();
calendar2.set(2018, 1, 1, 23, 50);
OfflineItem item1 = buildItem("1", calendar1, OfflineItemFilter.VIDEO);
OfflineItem item2 = buildItem("2", calendar2, OfflineItemFilter.AUDIO);
OfflineItem item3 = buildItem("3", buildCalendar(2018, 1, 1, 10), OfflineItemFilter.AUDIO);
item1.completionTimeMs = item1.creationTimeMs;
item2.completionTimeMs = item2.creationTimeMs;
when(mSource.getItems()).thenReturn(CollectionUtil.newArrayList(item1, item2, item3));
Calendar now = CalendarFactory.get();
now.set(2018, 1, 2, 0, 15);
createMutatorWithJustNowProvider(buildJustNowProvider(now.getTime()));
Assert.assertEquals(5, mModel.size());
assertJustNowSection(mModel.get(0));
assertOfflineItem(mModel.get(1), calendar1, item1);
assertOfflineItem(mModel.get(2), calendar2, item2);
assertSectionHeader(mModel.get(3), buildCalendar(2018, 1, 1, 0), true);
assertOfflineItem(mModel.get(4), buildCalendar(2018, 1, 1, 10), item3);
}
/** /**
* Action List * Action List
* 1. Set(item1 @ 1:00 1/1/2018 [ DATE Just Now, * 1. Set(item1 @ 1:00 1/1/2018 [ DATE Just Now,
...@@ -197,7 +233,7 @@ public class DateOrderedListMutatorTest { ...@@ -197,7 +233,7 @@ public class DateOrderedListMutatorTest {
mModel.addObserver(mObserver); mModel.addObserver(mObserver);
Assert.assertEquals(2, mModel.size()); Assert.assertEquals(2, mModel.size());
assertJustNowSection(mModel.get(0), false); assertJustNowSection(mModel.get(0));
assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), item1); assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), item1);
// Resume the download. // Resume the download.
...@@ -207,7 +243,7 @@ public class DateOrderedListMutatorTest { ...@@ -207,7 +243,7 @@ public class DateOrderedListMutatorTest {
list.onItemUpdated(item1, update1); list.onItemUpdated(item1, update1);
Assert.assertEquals(2, mModel.size()); Assert.assertEquals(2, mModel.size());
assertJustNowSection(mModel.get(0), false); assertJustNowSection(mModel.get(0));
assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), update1); assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), update1);
// Complete the download. // Complete the download.
...@@ -218,7 +254,7 @@ public class DateOrderedListMutatorTest { ...@@ -218,7 +254,7 @@ public class DateOrderedListMutatorTest {
list.onItemUpdated(update1, update2); list.onItemUpdated(update1, update2);
Assert.assertEquals(2, mModel.size()); Assert.assertEquals(2, mModel.size());
assertJustNowSection(mModel.get(0), false); assertJustNowSection(mModel.get(0));
assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), update2); assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), update2);
// Too much time has passed since completion of the download. // Too much time has passed since completion of the download.
...@@ -229,7 +265,7 @@ public class DateOrderedListMutatorTest { ...@@ -229,7 +265,7 @@ public class DateOrderedListMutatorTest {
list.onItemUpdated(update2, update3); list.onItemUpdated(update2, update3);
Assert.assertEquals(2, mModel.size()); Assert.assertEquals(2, mModel.size());
assertJustNowSection(mModel.get(0), false); assertJustNowSection(mModel.get(0));
assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), update3); assertOfflineItem(mModel.get(1), buildCalendar(2018, 1, 1, 1), update3);
} }
...@@ -250,7 +286,7 @@ public class DateOrderedListMutatorTest { ...@@ -250,7 +286,7 @@ public class DateOrderedListMutatorTest {
DateOrderedListMutator list = createMutatorWithJustNowProvider(); DateOrderedListMutator list = createMutatorWithJustNowProvider();
Assert.assertEquals(4, mModel.size()); Assert.assertEquals(4, mModel.size());
assertJustNowSection(mModel.get(0), false); assertJustNowSection(mModel.get(0));
assertOfflineItem(mModel.get(1), buildCalendar(2018, 2, 1, 1), item1); assertOfflineItem(mModel.get(1), buildCalendar(2018, 2, 1, 1), item1);
assertSectionHeader(mModel.get(2), buildCalendar(2018, 1, 1, 0), true); assertSectionHeader(mModel.get(2), buildCalendar(2018, 1, 1, 0), true);
assertOfflineItem(mModel.get(3), buildCalendar(2018, 1, 1, 1), item2); assertOfflineItem(mModel.get(3), buildCalendar(2018, 1, 1, 1), item2);
...@@ -871,11 +907,25 @@ public class DateOrderedListMutatorTest { ...@@ -871,11 +907,25 @@ public class DateOrderedListMutatorTest {
return item; return item;
} }
private DownloadManagerUiConfig createConfig() {
return new DownloadManagerUiConfig.Builder()
.setUseNewDownloadPath(true)
.setSupportsGrouping(false)
.build();
}
private JustNowProvider buildJustNowProvider(Date overrideNow) {
JustNowProvider justNowProvider = new JustNowProvider(createConfig()) {
@Override
protected Date now() {
return overrideNow;
}
};
return justNowProvider;
}
private DateOrderedListMutator createMutatorWithoutJustNowProvider() { private DateOrderedListMutator createMutatorWithoutJustNowProvider() {
DownloadManagerUiConfig config = new DownloadManagerUiConfig.Builder() DownloadManagerUiConfig config = createConfig();
.setUseNewDownloadPath(true)
.setSupportsGrouping(false)
.build();
JustNowProvider justNowProvider = new JustNowProvider(config) { JustNowProvider justNowProvider = new JustNowProvider(config) {
@Override @Override
public boolean isJustNowItem(OfflineItem item) { public boolean isJustNowItem(OfflineItem item) {
...@@ -889,14 +939,15 @@ public class DateOrderedListMutatorTest { ...@@ -889,14 +939,15 @@ public class DateOrderedListMutatorTest {
} }
private DateOrderedListMutator createMutatorWithJustNowProvider() { private DateOrderedListMutator createMutatorWithJustNowProvider() {
DownloadManagerUiConfig config = new DownloadManagerUiConfig.Builder() JustNowProvider justNowProvider = new JustNowProvider(createConfig());
.setUseNewDownloadPath(true) return createMutatorWithJustNowProvider(justNowProvider);
.setSupportsGrouping(false) }
.build();
JustNowProvider justNowProvider = new JustNowProvider(config); private DateOrderedListMutator createMutatorWithJustNowProvider(
JustNowProvider justNowProvider) {
DateOrderedListMutator mutator = DateOrderedListMutator mutator =
new DateOrderedListMutator(mSource, mModel, justNowProvider); new DateOrderedListMutator(mSource, mModel, justNowProvider);
new ListMutationController(config, justNowProvider, mutator, mModel); new ListMutationController(createConfig(), justNowProvider, mutator, mModel);
return mutator; return mutator;
} }
...@@ -923,11 +974,11 @@ public class DateOrderedListMutatorTest { ...@@ -923,11 +974,11 @@ public class DateOrderedListMutatorTest {
Assert.assertEquals(sectionHeader.showTopDivider, showDivider); Assert.assertEquals(sectionHeader.showTopDivider, showDivider);
} }
private static void assertJustNowSection(ListItem item, boolean showDivider) { private static void assertJustNowSection(ListItem item) {
Assert.assertTrue(item instanceof SectionHeaderListItem); Assert.assertTrue(item instanceof SectionHeaderListItem);
SectionHeaderListItem sectionHeader = (SectionHeaderListItem) item; SectionHeaderListItem sectionHeader = (SectionHeaderListItem) item;
Assert.assertTrue(sectionHeader.isJustNow); Assert.assertTrue(sectionHeader.isJustNow);
Assert.assertEquals(sectionHeader.showTopDivider, showDivider); Assert.assertEquals(false, sectionHeader.showTopDivider);
Assert.assertEquals(StableIds.JUST_NOW_SECTION, item.stableId); Assert.assertEquals(StableIds.JUST_NOW_SECTION, item.stableId);
} }
} }
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