OLD | NEW |
---|---|
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.download.items; | 5 package org.chromium.chrome.browser.download.items; |
6 | 6 |
7 import org.chromium.chrome.browser.download.DownloadInfo; | 7 import org.chromium.chrome.browser.download.DownloadInfo; |
8 import org.chromium.chrome.browser.download.DownloadItem; | 8 import org.chromium.chrome.browser.download.DownloadItem; |
9 import org.chromium.chrome.browser.download.DownloadManagerService; | |
10 import org.chromium.chrome.browser.download.DownloadNotifier; | 9 import org.chromium.chrome.browser.download.DownloadNotifier; |
11 import org.chromium.chrome.browser.download.DownloadServiceDelegate; | 10 import org.chromium.chrome.browser.download.DownloadServiceDelegate; |
12 import org.chromium.components.offline_items_collection.ContentId; | 11 import org.chromium.components.offline_items_collection.ContentId; |
13 import org.chromium.components.offline_items_collection.OfflineContentProvider; | 12 import org.chromium.components.offline_items_collection.OfflineContentProvider; |
14 import org.chromium.components.offline_items_collection.OfflineItem; | 13 import org.chromium.components.offline_items_collection.OfflineItem; |
15 import org.chromium.components.offline_items_collection.OfflineItemState; | 14 import org.chromium.components.offline_items_collection.OfflineItemState; |
15 import org.chromium.components.offline_items_collection.OfflineItemVisuals; | |
16 | 16 |
17 import java.util.ArrayList; | 17 import java.util.ArrayList; |
18 import java.util.HashMap; | |
18 | 19 |
19 /** | 20 /** |
20 * A glue class that bridges the Profile-attached OfflineContentProvider with th e | 21 * A glue class that bridges the Profile-attached OfflineContentProvider with th e |
21 * download notification code (SystemDownloadNotifier and DownloadServiceDelegat e). | 22 * download notification code (SystemDownloadNotifier and DownloadServiceDelegat e). |
22 */ | 23 */ |
23 public class OfflineContentAggregatorNotificationBridgeUi | 24 public class OfflineContentAggregatorNotificationBridgeUi |
24 implements DownloadServiceDelegate, OfflineContentProvider.Observer { | 25 implements DownloadServiceDelegate, OfflineContentProvider.Observer, |
26 OfflineContentProvider.VisualsCallback { | |
27 // TODO(dtrainor): Should this just be part of the OfflineContentProvider ca llback guarantee? | |
28 private static final OfflineItemVisuals sEmptyOfflineItemVisuals = new Offli neItemVisuals(); | |
29 | |
25 private final OfflineContentProvider mProvider; | 30 private final OfflineContentProvider mProvider; |
26 | 31 |
32 private final DownloadNotifier mUi; | |
33 | |
34 /** Holds a list of {@link OfflineItem} updates that are waiting for visuals . */ | |
35 private final HashMap<ContentId, OfflineItem> mOutstandingRequests = new Has hMap<>(); | |
36 | |
37 /** | |
38 * Holds a list of {@link OfflineItemVisuals} for all {@link OfflineItem}s t hat are currently in | |
39 * progress. Once an {@link OfflineItem} is no longer in progress it will b e removed from this | |
40 * cache. | |
41 * TODO(dtrainor): Flush this list aggressively if we get onLowMemory/onTrim Memory. | |
42 * TODO(dtrainor): Add periodic clean up in case something goes wrong with t he underlying | |
43 * downloads. | |
44 */ | |
45 private final HashMap<ContentId, OfflineItemVisuals> mVisualsCache = new Has hMap<>(); | |
46 | |
27 /** | 47 /** |
28 * Creates a new OfflineContentAggregatorNotificationBridgeUi based on {@cod e provider}. | 48 * Creates a new OfflineContentAggregatorNotificationBridgeUi based on {@cod e provider}. |
29 */ | 49 */ |
30 public OfflineContentAggregatorNotificationBridgeUi(OfflineContentProvider p rovider) { | 50 public OfflineContentAggregatorNotificationBridgeUi( |
51 OfflineContentProvider provider, DownloadNotifier notifier) { | |
31 mProvider = provider; | 52 mProvider = provider; |
53 mUi = notifier; | |
32 | 54 |
33 mProvider.addObserver(this); | 55 mProvider.addObserver(this); |
34 } | 56 } |
35 | 57 |
36 /** | 58 /** |
37 * Destroys this class and detaches it from associated objects. | 59 * Destroys this class and detaches it from associated objects. |
38 */ | 60 */ |
39 public void destroy() { | 61 public void destroy() { |
40 mProvider.removeObserver(this); | 62 mProvider.removeObserver(this); |
41 destroyServiceDelegate(); | 63 destroyServiceDelegate(); |
42 } | 64 } |
43 | 65 |
44 // OfflineContentProvider.Observer implementation. | 66 // OfflineContentProvider.Observer implementation. |
45 @Override | 67 @Override |
46 public void onItemsAvailable() {} | 68 public void onItemsAvailable() {} |
47 | 69 |
48 @Override | 70 @Override |
49 public void onItemsAdded(ArrayList<OfflineItem> items) { | 71 public void onItemsAdded(ArrayList<OfflineItem> items) { |
50 for (int i = 0; i < items.size(); i++) { | 72 for (int i = 0; i < items.size(); i++) { |
51 OfflineItem item = items.get(i); | 73 OfflineItem item = items.get(i); |
52 | 74 if (shouldPushNewItemToUi(item)) getVisualsAndUpdateItem(item); |
53 // Only update the UI for new OfflineItems that are in progress or p ending. | |
54 if (item.state == OfflineItemState.IN_PROGRESS | |
55 || item.state == OfflineItemState.PENDING) { | |
56 visuallyUpdateOfflineItem(item); | |
57 } | |
58 } | 75 } |
59 } | 76 } |
60 | 77 |
61 @Override | 78 @Override |
62 public void onItemRemoved(ContentId id) {} | 79 public void onItemRemoved(ContentId id) { |
80 mOutstandingRequests.remove(id); | |
81 mVisualsCache.remove(id); | |
82 mUi.notifyDownloadCanceled(id); | |
83 } | |
63 | 84 |
64 @Override | 85 @Override |
65 public void onItemUpdated(OfflineItem item) { | 86 public void onItemUpdated(OfflineItem item) { |
66 visuallyUpdateOfflineItem(item); | 87 // Assume that any item sending updates should have them reflected in th e UI. |
88 getVisualsAndUpdateItem(item); | |
89 } | |
90 | |
91 // OfflineContentProvider.VisualsCallback implementation. | |
92 @Override | |
93 public void onVisualsAvailable(ContentId id, OfflineItemVisuals visuals) { | |
94 OfflineItem item = mOutstandingRequests.remove(id); | |
95 if (item == null) return; | |
96 | |
97 if (visuals == null) visuals = sEmptyOfflineItemVisuals; | |
98 | |
99 // Only cache the visuals if the update we are about to push is interest ing and we think we | |
100 // will need them in the future. | |
101 if (shouldCacheVisuals(item)) mVisualsCache.put(id, visuals); | |
102 pushItemToUi(item, visuals); | |
67 } | 103 } |
68 | 104 |
69 // DownloadServiceDelegate implementation. | 105 // DownloadServiceDelegate implementation. |
70 @Override | 106 @Override |
71 public void cancelDownload(ContentId id, boolean isOffTheRecord) { | 107 public void cancelDownload(ContentId id, boolean isOffTheRecord) { |
72 mProvider.cancelDownload(id); | 108 mProvider.cancelDownload(id); |
73 } | 109 } |
74 | 110 |
75 @Override | 111 @Override |
76 public void pauseDownload(ContentId id, boolean isOffTheRecord) { | 112 public void pauseDownload(ContentId id, boolean isOffTheRecord) { |
77 mProvider.pauseDownload(id); | 113 mProvider.pauseDownload(id); |
78 } | 114 } |
79 | 115 |
80 @Override | 116 @Override |
81 public void resumeDownload(ContentId id, DownloadItem item, boolean hasUserG esture) { | 117 public void resumeDownload(ContentId id, DownloadItem item, boolean hasUserG esture) { |
82 mProvider.resumeDownload(id); | 118 mProvider.resumeDownload(id); |
83 } | 119 } |
84 | 120 |
85 @Override | 121 @Override |
86 public void destroyServiceDelegate() {} | 122 public void destroyServiceDelegate() {} |
87 | 123 |
88 /** | 124 private void getVisualsAndUpdateItem(OfflineItem item) { |
89 * Calls into the proper {@link DownloadNotifier} by converting an {@link Of flineItem} to a | 125 OfflineItemVisuals visuals = mVisualsCache.get(item.id); |
90 * {@link DownloadInfo}. | 126 |
91 * @param item The {@link OfflineItem} that needs a UI refresh. | 127 if (!needsVisualsForUi(item)) { |
nyquist
2017/04/13 05:08:24
If you flip this else around you don't need the !
David Trainor- moved to gerrit
2017/04/13 07:20:23
Done.
| |
92 */ | 128 // We don't need the visuals to show this item at this point. Cance l any requests. |
93 private void visuallyUpdateOfflineItem(OfflineItem item) { | 129 mOutstandingRequests.remove(item.id); |
94 DownloadInfo info = DownloadInfo.fromOfflineItem(item); | 130 mVisualsCache.remove(item.id); |
95 DownloadNotifier notifier = | 131 } else { |
96 DownloadManagerService.getDownloadManagerService().getDownloadNo tifier(); | 132 if (visuals == null) { |
133 // We don't have any visuals for this item yet. Stash the curre nt OfflineItem and, | |
134 // if we haven't already, queue up a request for the visuals. | |
135 // TODO(dtrainor): Check if this delay is too much. If so, just send the update | |
136 // through. | |
137 boolean requestVisuals = !mOutstandingRequests.containsKey(item. id); | |
138 mOutstandingRequests.put(item.id, item); | |
139 if (requestVisuals) mProvider.getVisualsForItem(item.id, this); | |
140 return; | |
141 } | |
142 } | |
143 | |
144 pushItemToUi(item, visuals); | |
145 // We will no longer be needing the visuals for this item after this not ification. | |
146 if (!shouldCacheVisuals(item)) mVisualsCache.remove(item.id); | |
147 } | |
148 | |
149 private void pushItemToUi(OfflineItem item, OfflineItemVisuals visuals) { | |
150 DownloadInfo info = DownloadInfo.fromOfflineItem(item, visuals); | |
97 switch (item.state) { | 151 switch (item.state) { |
98 case OfflineItemState.IN_PROGRESS: | 152 case OfflineItemState.IN_PROGRESS: |
99 notifier.notifyDownloadProgress(info, item.creationTimeMs, item. allowMetered); | 153 mUi.notifyDownloadProgress(info, item.creationTimeMs, item.allow Metered); |
100 break; | 154 break; |
101 case OfflineItemState.COMPLETE: | 155 case OfflineItemState.COMPLETE: |
102 notifier.notifyDownloadSuccessful(info, -1L, false, false); | 156 mUi.notifyDownloadSuccessful(info, -1L, false, false); |
103 break; | 157 break; |
104 case OfflineItemState.CANCELLED: | 158 case OfflineItemState.CANCELLED: |
105 notifier.notifyDownloadCanceled(item.id); | 159 mUi.notifyDownloadCanceled(item.id); |
106 break; | 160 break; |
107 case OfflineItemState.INTERRUPTED: | 161 case OfflineItemState.INTERRUPTED: |
108 // TODO(dtrainor): Push the correct value for auto resume. | 162 // TODO(dtrainor): Push the correct value for auto resume. |
109 notifier.notifyDownloadInterrupted(info, true); | 163 mUi.notifyDownloadInterrupted(info, true); |
110 break; | 164 break; |
111 case OfflineItemState.PAUSED: | 165 case OfflineItemState.PAUSED: |
112 notifier.notifyDownloadPaused(info); | 166 mUi.notifyDownloadPaused(info); |
113 break; | 167 break; |
168 case OfflineItemState.FAILED: | |
169 mUi.notifyDownloadFailed(info); | |
170 break; | |
171 } | |
172 } | |
173 | |
174 private boolean needsVisualsForUi(OfflineItem item) { | |
175 switch (item.state) { | |
176 case OfflineItemState.IN_PROGRESS: | |
nyquist
2017/04/13 05:08:24
Often I want to ask the author to add . // Intenti
David Trainor- moved to gerrit
2017/04/13 07:20:23
Yeah I wasn't sure what looked nicer, but this loo
| |
177 case OfflineItemState.PENDING: | |
178 case OfflineItemState.COMPLETE: | |
179 case OfflineItemState.INTERRUPTED: | |
180 case OfflineItemState.FAILED: | |
181 case OfflineItemState.PAUSED: | |
182 return true; | |
183 case OfflineItemState.CANCELLED: | |
114 default: | 184 default: |
115 assert false; | 185 return false; |
186 } | |
187 } | |
188 | |
189 private boolean shouldPushNewItemToUi(OfflineItem item) { | |
190 switch (item.state) { | |
191 case OfflineItemState.IN_PROGRESS: | |
192 return true; | |
193 case OfflineItemState.PENDING: | |
194 case OfflineItemState.COMPLETE: | |
195 case OfflineItemState.INTERRUPTED: | |
196 case OfflineItemState.FAILED: | |
197 case OfflineItemState.PAUSED: | |
198 case OfflineItemState.CANCELLED: | |
199 default: | |
200 return false; | |
201 } | |
202 } | |
203 | |
204 private boolean shouldCacheVisuals(OfflineItem item) { | |
205 switch (item.state) { | |
206 case OfflineItemState.IN_PROGRESS: | |
207 case OfflineItemState.PENDING: | |
208 case OfflineItemState.INTERRUPTED: | |
209 case OfflineItemState.PAUSED: | |
210 return true; | |
211 case OfflineItemState.FAILED: | |
212 case OfflineItemState.COMPLETE: | |
213 case OfflineItemState.CANCELLED: | |
214 default: | |
215 return false; | |
116 } | 216 } |
117 } | 217 } |
118 } | 218 } |
OLD | NEW |