OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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.Activity; | 7 import android.app.Activity; |
8 import android.app.PendingIntent; | 8 import android.app.PendingIntent; |
9 import android.content.ActivityNotFoundException; | 9 import android.content.ActivityNotFoundException; |
10 import android.content.Context; | 10 import android.content.Context; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; | 45 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; |
46 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils; | 46 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils; |
47 import org.chromium.chrome.browser.offlinepages.downloads.OfflinePageDownloadBri
dge; | 47 import org.chromium.chrome.browser.offlinepages.downloads.OfflinePageDownloadBri
dge; |
48 import org.chromium.chrome.browser.profiles.Profile; | 48 import org.chromium.chrome.browser.profiles.Profile; |
49 import org.chromium.chrome.browser.tab.Tab; | 49 import org.chromium.chrome.browser.tab.Tab; |
50 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; | 50 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; |
51 import org.chromium.chrome.browser.tabmodel.document.TabDelegate; | 51 import org.chromium.chrome.browser.tabmodel.document.TabDelegate; |
52 import org.chromium.chrome.browser.util.IntentUtils; | 52 import org.chromium.chrome.browser.util.IntentUtils; |
53 import org.chromium.components.feature_engagement_tracker.EventConstants; | 53 import org.chromium.components.feature_engagement_tracker.EventConstants; |
54 import org.chromium.components.feature_engagement_tracker.FeatureEngagementTrack
er; | 54 import org.chromium.components.feature_engagement_tracker.FeatureEngagementTrack
er; |
| 55 import org.chromium.components.offline_items_collection.OfflineItem.Progress; |
| 56 import org.chromium.components.offline_items_collection.OfflineItemProgressUnit; |
55 import org.chromium.content_public.browser.DownloadState; | 57 import org.chromium.content_public.browser.DownloadState; |
56 import org.chromium.content_public.browser.LoadUrlParams; | 58 import org.chromium.content_public.browser.LoadUrlParams; |
57 import org.chromium.ui.base.DeviceFormFactor; | 59 import org.chromium.ui.base.DeviceFormFactor; |
58 import org.chromium.ui.widget.Toast; | 60 import org.chromium.ui.widget.Toast; |
59 | 61 |
60 import java.io.File; | 62 import java.io.File; |
61 import java.lang.annotation.Retention; | 63 import java.lang.annotation.Retention; |
62 import java.lang.annotation.RetentionPolicy; | 64 import java.lang.annotation.RetentionPolicy; |
63 import java.text.NumberFormat; | 65 import java.text.NumberFormat; |
64 import java.util.ArrayList; | 66 import java.util.ArrayList; |
65 import java.util.Calendar; | 67 import java.util.Calendar; |
66 import java.util.Date; | 68 import java.util.Date; |
67 import java.util.List; | 69 import java.util.List; |
68 import java.util.Locale; | 70 import java.util.Locale; |
| 71 import java.util.concurrent.TimeUnit; |
69 | 72 |
70 /** | 73 /** |
71 * A class containing some utility static methods. | 74 * A class containing some utility static methods. |
72 */ | 75 */ |
73 public class DownloadUtils { | 76 public class DownloadUtils { |
74 | 77 |
75 /** Strings indicating how many bytes have been downloaded for different uni
ts. */ | 78 /** Strings indicating how many bytes have been downloaded for different uni
ts. */ |
76 @VisibleForTesting | 79 @VisibleForTesting |
77 static final int[] BYTES_DOWNLOADED_STRINGS = { | 80 static final int[] BYTES_DOWNLOADED_STRINGS = { |
78 R.string.file_size_downloaded_kb, | 81 R.string.file_size_downloaded_kb, |
79 R.string.file_size_downloaded_mb, | 82 R.string.file_size_downloaded_mb, |
80 R.string.file_size_downloaded_gb | 83 R.string.file_size_downloaded_gb |
81 }; | 84 }; |
82 | 85 |
83 private static final String TAG = "download"; | 86 private static final String TAG = "download"; |
84 | 87 |
85 private static final String DEFAULT_MIME_TYPE = "*/*"; | 88 private static final String DEFAULT_MIME_TYPE = "*/*"; |
86 private static final String MIME_TYPE_DELIMITER = "/"; | 89 private static final String MIME_TYPE_DELIMITER = "/"; |
87 private static final String MIME_TYPE_VIDEO = "video"; | 90 private static final String MIME_TYPE_VIDEO = "video"; |
88 | 91 |
89 private static final String EXTRA_IS_OFF_THE_RECORD = | 92 private static final String EXTRA_IS_OFF_THE_RECORD = |
90 "org.chromium.chrome.browser.download.IS_OFF_THE_RECORD"; | 93 "org.chromium.chrome.browser.download.IS_OFF_THE_RECORD"; |
91 | 94 |
92 private static final long BYTES_PER_KILOBYTE = 1024; | 95 private static final long BYTES_PER_KILOBYTE = 1024; |
93 private static final long BYTES_PER_MEGABYTE = 1024 * 1024; | 96 private static final long BYTES_PER_MEGABYTE = 1024 * 1024; |
94 private static final long BYTES_PER_GIGABYTE = 1024 * 1024 * 1024; | 97 private static final long BYTES_PER_GIGABYTE = 1024 * 1024 * 1024; |
95 | 98 |
96 @VisibleForTesting | 99 @VisibleForTesting |
| 100 static final long SECONDS_PER_MINUTE = TimeUnit.MINUTES.toSeconds(1); |
| 101 @VisibleForTesting |
| 102 static final long SECONDS_PER_HOUR = TimeUnit.HOURS.toSeconds(1); |
| 103 @VisibleForTesting |
| 104 static final long SECONDS_PER_DAY = TimeUnit.DAYS.toSeconds(1); |
| 105 |
| 106 @VisibleForTesting |
97 static final String ELLIPSIS = "\u2026"; | 107 static final String ELLIPSIS = "\u2026"; |
98 | 108 |
99 /** | 109 /** |
100 * Possible sizes of type-based icons. | 110 * Possible sizes of type-based icons. |
101 */ | 111 */ |
102 @IntDef({ICON_SIZE_24_DP, ICON_SIZE_36_DP}) | 112 @IntDef({ICON_SIZE_24_DP, ICON_SIZE_36_DP}) |
103 @Retention(RetentionPolicy.SOURCE) | 113 @Retention(RetentionPolicy.SOURCE) |
104 public @interface IconSize {} | 114 public @interface IconSize {} |
105 | 115 |
106 public static final int ICON_SIZE_24_DP = 24; | 116 public static final int ICON_SIZE_24_DP = 24; |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 * Create a string that represents the percentage of the file that has downl
oaded. | 584 * Create a string that represents the percentage of the file that has downl
oaded. |
575 * @param percentage Current percentage of the file. | 585 * @param percentage Current percentage of the file. |
576 * @return String representing the percentage of the file that has been down
loaded. | 586 * @return String representing the percentage of the file that has been down
loaded. |
577 */ | 587 */ |
578 public static String getPercentageString(int percentage) { | 588 public static String getPercentageString(int percentage) { |
579 NumberFormat formatter = NumberFormat.getPercentInstance(Locale.getDefau
lt()); | 589 NumberFormat formatter = NumberFormat.getPercentInstance(Locale.getDefau
lt()); |
580 return formatter.format(percentage / 100.0); | 590 return formatter.format(percentage / 100.0); |
581 } | 591 } |
582 | 592 |
583 /** | 593 /** |
584 * Determine what String to show for a given download. | 594 * Creates a string that shows the time left or number of files left. |
| 595 * @param context The application context. |
| 596 * @param progress The download progress. |
| 597 * @param timeRemainingInMillis The remaining time in milli seconds. |
| 598 * @return Formatted string representing the time left or the number of file
s left. |
| 599 */ |
| 600 public static String getTimeOrFilesLeftString( |
| 601 Context context, Progress progress, long timeRemainingInMillis) { |
| 602 if (progress.unit == OfflineItemProgressUnit.FILES) { |
| 603 return formatRemainingFiles(context, progress); |
| 604 } else { |
| 605 return formatRemainingTime(context, timeRemainingInMillis); |
| 606 } |
| 607 } |
| 608 |
| 609 /** |
| 610 * Creates a string that represents the number of files left to be downloade
d. |
| 611 * @param progress Current download progress. |
| 612 * @return String representing the number of files left. |
| 613 */ |
| 614 public static String formatRemainingFiles(Context context, Progress progress
) { |
| 615 int filesLeft = (int) (progress.max - progress.value); |
| 616 if (filesLeft == 1) { |
| 617 return context.getResources().getString(R.string.one_file_left); |
| 618 } else { |
| 619 return context.getResources().getString(R.string.files_left, filesLe
ft); |
| 620 } |
| 621 } |
| 622 |
| 623 /** |
| 624 * Format remaining time for the given millis, in the following format: |
| 625 * 5 hours; will include 1 unit, can go down to seconds precision. |
| 626 * This is similar to what android.java.text.Formatter.formatShortElapsedTim
e() does. Don't use |
| 627 * ui::TimeFormat::Simple() as it is very expensive. |
| 628 * |
| 629 * @param context the application context. |
| 630 * @param millis the remaining time in milli seconds. |
| 631 * @return the formatted remaining time. |
| 632 */ |
| 633 @VisibleForTesting |
| 634 public static String formatRemainingTime(Context context, long millis) { |
| 635 long secondsLong = millis / 1000; |
| 636 |
| 637 int days = 0; |
| 638 int hours = 0; |
| 639 int minutes = 0; |
| 640 if (secondsLong >= SECONDS_PER_DAY) { |
| 641 days = (int) (secondsLong / SECONDS_PER_DAY); |
| 642 secondsLong -= days * SECONDS_PER_DAY; |
| 643 } |
| 644 if (secondsLong >= SECONDS_PER_HOUR) { |
| 645 hours = (int) (secondsLong / SECONDS_PER_HOUR); |
| 646 secondsLong -= hours * SECONDS_PER_HOUR; |
| 647 } |
| 648 if (secondsLong >= SECONDS_PER_MINUTE) { |
| 649 minutes = (int) (secondsLong / SECONDS_PER_MINUTE); |
| 650 secondsLong -= minutes * SECONDS_PER_MINUTE; |
| 651 } |
| 652 int seconds = (int) secondsLong; |
| 653 |
| 654 if (days >= 2) { |
| 655 days += (hours + 12) / 24; |
| 656 return context.getString(R.string.remaining_duration_days, days); |
| 657 } else if (days > 0) { |
| 658 return context.getString(R.string.remaining_duration_one_day); |
| 659 } else if (hours >= 2) { |
| 660 hours += (minutes + 30) / 60; |
| 661 return context.getString(R.string.remaining_duration_hours, hours); |
| 662 } else if (hours > 0) { |
| 663 return context.getString(R.string.remaining_duration_one_hour); |
| 664 } else if (minutes >= 2) { |
| 665 minutes += (seconds + 30) / 60; |
| 666 return context.getString(R.string.remaining_duration_minutes, minute
s); |
| 667 } else if (minutes > 0) { |
| 668 return context.getString(R.string.remaining_duration_one_minute); |
| 669 } else if (seconds == 1) { |
| 670 return context.getString(R.string.remaining_duration_one_second); |
| 671 } else { |
| 672 return context.getString(R.string.remaining_duration_seconds, second
s); |
| 673 } |
| 674 } |
| 675 |
| 676 /** |
| 677 * Determine what String to show for a given download in download home. |
585 * @param item Download to check the status of. | 678 * @param item Download to check the status of. |
586 * @return ID of a String resource to use, or 0 if the status couldn't be de
termined. | 679 * @return String representing the current download status. |
587 */ | 680 */ |
588 public static String getStatusString(DownloadItem item) { | 681 public static String getStatusString(DownloadItem item) { |
589 Context context = ContextUtils.getApplicationContext(); | 682 Context context = ContextUtils.getApplicationContext(); |
590 DownloadInfo info = item.getDownloadInfo(); | 683 DownloadInfo info = item.getDownloadInfo(); |
| 684 Progress progress = info.getProgress(); |
591 | 685 |
592 int state = info.state(); | 686 int state = info.state(); |
593 if (state == DownloadState.COMPLETE) { | 687 if (state == DownloadState.COMPLETE) { |
594 return context.getString(R.string.download_notification_completed); | 688 return context.getString(R.string.download_notification_completed); |
595 } | 689 } |
596 | 690 |
597 DownloadSharedPreferenceHelper helper = DownloadSharedPreferenceHelper.g
etInstance(); | 691 DownloadSharedPreferenceHelper helper = DownloadSharedPreferenceHelper.g
etInstance(); |
598 DownloadSharedPreferenceEntry entry = | 692 DownloadSharedPreferenceEntry entry = |
599 helper.getDownloadSharedPreferenceEntry(item.getContentId()); | 693 helper.getDownloadSharedPreferenceEntry(item.getContentId()); |
600 boolean isDownloadPending = | 694 boolean isDownloadPending = |
601 entry != null && state == DownloadState.INTERRUPTED && entry.isA
utoResumable; | 695 entry != null && state == DownloadState.INTERRUPTED && entry.isA
utoResumable; |
602 | 696 |
603 if (isDownloadPending) { | 697 if (isDownloadPending) { |
604 return context.getString(R.string.download_notification_pending); | 698 return context.getString(R.string.download_notification_pending); |
605 } else if (isDownloadPaused(item)) { | 699 } else if (isDownloadPaused(item)) { |
606 return context.getString(R.string.download_notification_paused); | 700 return context.getString(R.string.download_notification_paused); |
607 } | 701 } |
608 | 702 |
609 if (info.getBytesReceived() == 0 | 703 if (info.getBytesReceived() == 0 |
610 || (!item.isIndeterminate() && info.getTimeRemainingInMillis() <
0)) { | 704 || (!item.isIndeterminate() && info.getTimeRemainingInMillis() <
0)) { |
611 // We lack enough information about the download to display a useful
string. | 705 // We lack enough information about the download to display a useful
string. |
612 return context.getString(R.string.download_started); | 706 return context.getString(R.string.download_started); |
613 } else if (item.isIndeterminate()) { | 707 } else if (item.isIndeterminate()) { |
614 // Count up the bytes. | 708 // Count up the bytes. |
615 long bytes = info.getBytesReceived(); | 709 long bytes = info.getBytesReceived(); |
616 return DownloadUtils.getStringForDownloadedBytes(context, bytes); | 710 return DownloadUtils.getStringForDownloadedBytes(context, bytes); |
617 } else { | 711 } else { |
618 // Count down the time. | 712 // Count down the time or number of files. |
619 long msRemaining = info.getTimeRemainingInMillis(); | 713 return getTimeOrFilesLeftString(context, progress, info.getTimeRemai
ningInMillis()); |
620 return DownloadNotificationService.formatRemainingTime(context, msRe
maining); | |
621 } | 714 } |
622 } | 715 } |
623 | 716 |
624 /** | 717 /** |
625 * Query the Download backends about whether a download is paused. | 718 * Query the Download backends about whether a download is paused. |
626 * | 719 * |
627 * The Java-side contains more information about the status of a download th
an is persisted | 720 * The Java-side contains more information about the status of a download th
an is persisted |
628 * by the native backend, so it is queried first. | 721 * by the native backend, so it is queried first. |
629 * | 722 * |
630 * @param item Download to check the status of. | 723 * @param item Download to check the status of. |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 public static Date getDateAtMidnight(long timestamp) { | 875 public static Date getDateAtMidnight(long timestamp) { |
783 Calendar cal = Calendar.getInstance(); | 876 Calendar cal = Calendar.getInstance(); |
784 cal.setTimeInMillis(timestamp); | 877 cal.setTimeInMillis(timestamp); |
785 cal.set(Calendar.HOUR_OF_DAY, 0); | 878 cal.set(Calendar.HOUR_OF_DAY, 0); |
786 cal.set(Calendar.MINUTE, 0); | 879 cal.set(Calendar.MINUTE, 0); |
787 cal.set(Calendar.SECOND, 0); | 880 cal.set(Calendar.SECOND, 0); |
788 cal.set(Calendar.MILLISECOND, 0); | 881 cal.set(Calendar.MILLISECOND, 0); |
789 return cal.getTime(); | 882 return cal.getTime(); |
790 } | 883 } |
791 } | 884 } |
OLD | NEW |