Chromium Code Reviews| 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 |