OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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; | 5 package org.chromium.chrome.browser.download; |
6 | 6 |
7 import android.app.Notification; | 7 import android.app.Notification; |
8 import android.app.NotificationManager; | 8 import android.app.NotificationManager; |
9 import android.app.PendingIntent; | 9 import android.app.PendingIntent; |
10 import android.app.Service; | 10 import android.app.Service; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 public static final String ACTION_DOWNLOAD_RESUME_ALL = | 55 public static final String ACTION_DOWNLOAD_RESUME_ALL = |
56 "org.chromium.chrome.browser.download.DOWNLOAD_RESUME_ALL"; | 56 "org.chromium.chrome.browser.download.DOWNLOAD_RESUME_ALL"; |
57 static final int INVALID_DOWNLOAD_PERCENTAGE = -1; | 57 static final int INVALID_DOWNLOAD_PERCENTAGE = -1; |
58 @VisibleForTesting | 58 @VisibleForTesting |
59 static final String PENDING_DOWNLOAD_NOTIFICATIONS = "PendingDownloadNotific
ations"; | 59 static final String PENDING_DOWNLOAD_NOTIFICATIONS = "PendingDownloadNotific
ations"; |
60 static final String NOTIFICATION_NAMESPACE = "DownloadNotificationService"; | 60 static final String NOTIFICATION_NAMESPACE = "DownloadNotificationService"; |
61 private static final String TAG = "DownloadNotification"; | 61 private static final String TAG = "DownloadNotification"; |
62 private static final String NEXT_DOWNLOAD_NOTIFICATION_ID = "NextDownloadNot
ificationId"; | 62 private static final String NEXT_DOWNLOAD_NOTIFICATION_ID = "NextDownloadNot
ificationId"; |
63 // Notification Id starting value, to avoid conflicts from IDs used in prior
versions. | 63 // Notification Id starting value, to avoid conflicts from IDs used in prior
versions. |
64 private static final int STARTING_NOTIFICATION_ID = 1000000; | 64 private static final int STARTING_NOTIFICATION_ID = 1000000; |
| 65 private static final String AUTO_RESUMPTION_ATTEMPT_LEFT = "ResumptionAttemp
tLeft"; |
| 66 private static final int MAX_RESUMPTION_ATTEMPT_LEFT = 5; |
65 @VisibleForTesting static final int SECONDS_PER_MINUTE = 60; | 67 @VisibleForTesting static final int SECONDS_PER_MINUTE = 60; |
66 @VisibleForTesting static final int SECONDS_PER_HOUR = 60 * 60; | 68 @VisibleForTesting static final int SECONDS_PER_HOUR = 60 * 60; |
67 @VisibleForTesting static final int SECONDS_PER_DAY = 24 * 60 * 60; | 69 @VisibleForTesting static final int SECONDS_PER_DAY = 24 * 60 * 60; |
68 private final IBinder mBinder = new LocalBinder(); | 70 private final IBinder mBinder = new LocalBinder(); |
69 private final List<DownloadSharedPreferenceEntry> mDownloadSharedPreferenceE
ntries = | 71 private final List<DownloadSharedPreferenceEntry> mDownloadSharedPreferenceE
ntries = |
70 new ArrayList<DownloadSharedPreferenceEntry>(); | 72 new ArrayList<DownloadSharedPreferenceEntry>(); |
71 private final List<String> mDownloadsInProgress = new ArrayList<String>(); | 73 private final List<String> mDownloadsInProgress = new ArrayList<String>(); |
72 private NotificationManager mNotificationManager; | 74 private NotificationManager mNotificationManager; |
73 private SharedPreferences mSharedPrefs; | 75 private SharedPreferences mSharedPrefs; |
74 private Context mContext; | 76 private Context mContext; |
75 private int mNextNotificationId; | 77 private int mNextNotificationId; |
| 78 private int mNumAutoResumptionAttemptLeft; |
76 | 79 |
77 /** | 80 /** |
78 * Class for clients to access. | 81 * Class for clients to access. |
79 */ | 82 */ |
80 public class LocalBinder extends Binder { | 83 public class LocalBinder extends Binder { |
81 DownloadNotificationService getService() { | 84 DownloadNotificationService getService() { |
82 return DownloadNotificationService.this; | 85 return DownloadNotificationService.this; |
83 } | 86 } |
84 } | 87 } |
85 | 88 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 */ | 122 */ |
120 private void onBrowserKilled() { | 123 private void onBrowserKilled() { |
121 pauseAllDownloads(); | 124 pauseAllDownloads(); |
122 if (!mDownloadSharedPreferenceEntries.isEmpty()) { | 125 if (!mDownloadSharedPreferenceEntries.isEmpty()) { |
123 boolean allowMeteredConnection = false; | 126 boolean allowMeteredConnection = false; |
124 for (int i = 0; i < mDownloadSharedPreferenceEntries.size(); ++i) { | 127 for (int i = 0; i < mDownloadSharedPreferenceEntries.size(); ++i) { |
125 if (mDownloadSharedPreferenceEntries.get(i).canDownloadWhileMete
red) { | 128 if (mDownloadSharedPreferenceEntries.get(i).canDownloadWhileMete
red) { |
126 allowMeteredConnection = true; | 129 allowMeteredConnection = true; |
127 } | 130 } |
128 } | 131 } |
129 DownloadResumptionScheduler.getDownloadResumptionScheduler(mContext)
.schedule( | 132 if (mNumAutoResumptionAttemptLeft > 0) { |
130 allowMeteredConnection); | 133 DownloadResumptionScheduler.getDownloadResumptionScheduler(mCont
ext).schedule( |
| 134 allowMeteredConnection); |
| 135 } |
131 } | 136 } |
132 stopSelf(); | 137 stopSelf(); |
133 } | 138 } |
134 | 139 |
135 @Override | 140 @Override |
136 public int onStartCommand(final Intent intent, int flags, int startId) { | 141 public int onStartCommand(final Intent intent, int flags, int startId) { |
137 if (isDownloadOperationIntent(intent)) { | 142 if (isDownloadOperationIntent(intent)) { |
138 handleDownloadOperation(intent); | 143 handleDownloadOperation(intent); |
139 DownloadResumptionScheduler.getDownloadResumptionScheduler(mContext)
.cancelTask(); | 144 DownloadResumptionScheduler.getDownloadResumptionScheduler(mContext)
.cancelTask(); |
| 145 // Limit the number of auto resumption attempts in case Chrome falls
into a vicious |
| 146 // cycle. |
| 147 if (intent.getAction() == ACTION_DOWNLOAD_RESUME_ALL) { |
| 148 if (mNumAutoResumptionAttemptLeft > 0) { |
| 149 mNumAutoResumptionAttemptLeft--; |
| 150 updateResumptionAttemptLeft(); |
| 151 } |
| 152 } else { |
| 153 // Reset number of attempts left if the action is triggered by u
ser. |
| 154 mNumAutoResumptionAttemptLeft = MAX_RESUMPTION_ATTEMPT_LEFT; |
| 155 clearResumptionAttemptLeft(); |
| 156 } |
140 } | 157 } |
141 | |
142 // This should restart the service after Chrome gets killed. However, th
is | 158 // This should restart the service after Chrome gets killed. However, th
is |
143 // doesn't work on Android 4.4.2. | 159 // doesn't work on Android 4.4.2. |
144 return START_STICKY; | 160 return START_STICKY; |
145 } | 161 } |
146 | 162 |
147 @Override | 163 @Override |
148 public IBinder onBind(Intent intent) { | 164 public IBinder onBind(Intent intent) { |
149 return mBinder; | 165 return mBinder; |
150 } | 166 } |
151 | 167 |
152 /** | 168 /** |
| 169 * Helper method to update the remaining number of background resumption att
empts left. |
| 170 * @param attamptLeft Number of attempt left. |
| 171 */ |
| 172 private void updateResumptionAttemptLeft() { |
| 173 SharedPreferences.Editor editor = mSharedPrefs.edit(); |
| 174 editor.putInt(AUTO_RESUMPTION_ATTEMPT_LEFT, mNumAutoResumptionAttemptLef
t); |
| 175 editor.apply(); |
| 176 } |
| 177 |
| 178 /** |
| 179 * Helper method to clear the remaining number of background resumption atte
mpts left. |
| 180 */ |
| 181 static void clearResumptionAttemptLeft() { |
| 182 SharedPreferences SharedPrefs = ContextUtils.getAppSharedPreferences(); |
| 183 SharedPreferences.Editor editor = SharedPrefs.edit(); |
| 184 editor.remove(AUTO_RESUMPTION_ATTEMPT_LEFT); |
| 185 editor.apply(); |
| 186 } |
| 187 |
| 188 /** |
153 * Add a in-progress download notification. | 189 * Add a in-progress download notification. |
154 * @param downloadGuid GUID of the download. | 190 * @param downloadGuid GUID of the download. |
155 * @param fileName File name of the download. | 191 * @param fileName File name of the download. |
156 * @param percentage Percentage completed. Value should be between 0 to 100
if | 192 * @param percentage Percentage completed. Value should be between 0 to 100
if |
157 * the percentage can be determined, or -1 if it is unknown. | 193 * the percentage can be determined, or -1 if it is unknown. |
158 * @param timeRemainingInMillis Remaining download time in milliseconds. | 194 * @param timeRemainingInMillis Remaining download time in milliseconds. |
159 * @param startTime Time when download started. | 195 * @param startTime Time when download started. |
160 * @param isResumable Whether the download can be resumed. | 196 * @param isResumable Whether the download can be resumed. |
161 * @param canDownloadWhileMetered Whether the download can happen in metered
network. | 197 * @param canDownloadWhileMetered Whether the download can happen in metered
network. |
162 */ | 198 */ |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 DownloadSharedPreferenceEntry entry = mDownloadSharedPreferenceEntri
es.get(i); | 576 DownloadSharedPreferenceEntry entry = mDownloadSharedPreferenceEntri
es.get(i); |
541 if (!entry.canDownloadWhileMetered && isNetworkMetered) continue; | 577 if (!entry.canDownloadWhileMetered && isNetworkMetered) continue; |
542 if (mDownloadsInProgress.contains(entry.downloadGuid)) continue; | 578 if (mDownloadsInProgress.contains(entry.downloadGuid)) continue; |
543 notifyDownloadProgress(entry.downloadGuid, entry.fileName, | 579 notifyDownloadProgress(entry.downloadGuid, entry.fileName, |
544 INVALID_DOWNLOAD_PERCENTAGE, 0, 0, true, entry.canDownloadWh
ileMetered); | 580 INVALID_DOWNLOAD_PERCENTAGE, 0, 0, true, entry.canDownloadWh
ileMetered); |
545 service.resumeDownload(entry.buildDownloadItem(), false); | 581 service.resumeDownload(entry.buildDownloadItem(), false); |
546 } | 582 } |
547 } | 583 } |
548 | 584 |
549 /** | 585 /** |
550 * Parse the DownloadSharedPreferenceEntry from the shared preference and re
turn a list of them. | 586 * Parse a list of the DownloadSharedPreferenceEntry and the number of auto
resumption attempt |
551 * @return a list of parsed DownloadSharedPreferenceEntry. | 587 * left from the shared preference. |
552 */ | 588 */ |
553 void parseDownloadSharedPrefs() { | 589 void parseDownloadSharedPrefs() { |
| 590 mNumAutoResumptionAttemptLeft = mSharedPrefs.getInt(AUTO_RESUMPTION_ATTE
MPT_LEFT, |
| 591 MAX_RESUMPTION_ATTEMPT_LEFT); |
554 if (!mSharedPrefs.contains(PENDING_DOWNLOAD_NOTIFICATIONS)) return; | 592 if (!mSharedPrefs.contains(PENDING_DOWNLOAD_NOTIFICATIONS)) return; |
555 Set<String> entries = DownloadManagerService.getStoredDownloadInfo( | 593 Set<String> entries = DownloadManagerService.getStoredDownloadInfo( |
556 mSharedPrefs, PENDING_DOWNLOAD_NOTIFICATIONS); | 594 mSharedPrefs, PENDING_DOWNLOAD_NOTIFICATIONS); |
557 for (String entryString : entries) { | 595 for (String entryString : entries) { |
558 DownloadSharedPreferenceEntry entry = | 596 DownloadSharedPreferenceEntry entry = |
559 DownloadSharedPreferenceEntry.parseFromString(entryString); | 597 DownloadSharedPreferenceEntry.parseFromString(entryString); |
560 if (entry.notificationId > 0) { | 598 if (entry.notificationId > 0) { |
561 mDownloadSharedPreferenceEntries.add( | 599 mDownloadSharedPreferenceEntries.add( |
562 DownloadSharedPreferenceEntry.parseFromString(entryStrin
g)); | 600 DownloadSharedPreferenceEntry.parseFromString(entryStrin
g)); |
563 } | 601 } |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 return context.getString(R.string.remaining_duration_minutes, minute
s); | 689 return context.getString(R.string.remaining_duration_minutes, minute
s); |
652 } else if (minutes > 0) { | 690 } else if (minutes > 0) { |
653 return context.getString(R.string.remaining_duration_one_minute); | 691 return context.getString(R.string.remaining_duration_one_minute); |
654 } else if (seconds == 1) { | 692 } else if (seconds == 1) { |
655 return context.getString(R.string.remaining_duration_one_second); | 693 return context.getString(R.string.remaining_duration_one_second); |
656 } else { | 694 } else { |
657 return context.getString(R.string.remaining_duration_seconds, second
s); | 695 return context.getString(R.string.remaining_duration_seconds, second
s); |
658 } | 696 } |
659 } | 697 } |
660 } | 698 } |
OLD | NEW |