1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.download;
6 
7 import android.graphics.Bitmap;
8 
9 import org.chromium.base.annotations.CalledByNative;
10 import org.chromium.components.download.DownloadState;
11 import org.chromium.components.offline_items_collection.ContentId;
12 import org.chromium.components.offline_items_collection.FailState;
13 import org.chromium.components.offline_items_collection.LegacyHelpers;
14 import org.chromium.components.offline_items_collection.OfflineItem;
15 import org.chromium.components.offline_items_collection.OfflineItem.Progress;
16 import org.chromium.components.offline_items_collection.OfflineItemProgressUnit;
17 import org.chromium.components.offline_items_collection.OfflineItemSchedule;
18 import org.chromium.components.offline_items_collection.OfflineItemState;
19 import org.chromium.components.offline_items_collection.OfflineItemVisuals;
20 import org.chromium.components.offline_items_collection.PendingState;
21 
22 /**
23  * Class representing the state of a single download.
24  */
25 public final class DownloadInfo {
26     private final String mUrl;
27     private final String mUserAgent;
28     private final String mMimeType;
29     private final String mCookie;
30     private final String mFileName;
31     private final String mDescription;
32     private final String mFilePath;
33     private final String mReferrer;
34     private final String mOriginalUrl;
35     private final long mBytesReceived;
36     private final long mBytesTotalSize;
37     private final String mDownloadGuid;
38     private final boolean mHasUserGesture;
39     private final String mContentDisposition;
40     private final boolean mIsGETRequest;
41     private final Progress mProgress;
42     private final long mTimeRemainingInMillis;
43     private final boolean mIsResumable;
44     private final boolean mIsPaused;
45     private final boolean mIsOffTheRecord;
46     private final boolean mIsOfflinePage;
47     private final int mState;
48     private final long mLastAccessTime;
49     private final boolean mIsDangerous;
50 
51     // New variables to assist with the migration to OfflineItems.
52     private final ContentId mContentId;
53     private final boolean mIsOpenable;
54     private final boolean mIsTransient;
55     private final boolean mIsParallelDownload;
56     private final Bitmap mIcon;
57     @PendingState
58     private final int mPendingState;
59     @FailState
60     private final int mFailState;
61     private final boolean mShouldPromoteOrigin;
62     private final OfflineItemSchedule mSchedule;
63 
DownloadInfo(Builder builder)64     private DownloadInfo(Builder builder) {
65         mUrl = builder.mUrl;
66         mUserAgent = builder.mUserAgent;
67         mMimeType = builder.mMimeType;
68         mCookie = builder.mCookie;
69         mFileName = builder.mFileName;
70         mDescription = builder.mDescription;
71         mFilePath = builder.mFilePath;
72         mReferrer = builder.mReferrer;
73         mOriginalUrl = builder.mOriginalUrl;
74         mBytesReceived = builder.mBytesReceived;
75         mBytesTotalSize = builder.mBytesTotalSize;
76         mDownloadGuid = builder.mDownloadGuid;
77         mHasUserGesture = builder.mHasUserGesture;
78         mIsGETRequest = builder.mIsGETRequest;
79         mContentDisposition = builder.mContentDisposition;
80         mProgress = builder.mProgress;
81         mTimeRemainingInMillis = builder.mTimeRemainingInMillis;
82         mIsResumable = builder.mIsResumable;
83         mIsPaused = builder.mIsPaused;
84         mIsOffTheRecord = builder.mIsOffTheRecord;
85         mIsOfflinePage = builder.mIsOfflinePage;
86         mState = builder.mState;
87         mLastAccessTime = builder.mLastAccessTime;
88         mIsDangerous = builder.mIsDangerous;
89 
90         if (builder.mContentId != null) {
91             mContentId = builder.mContentId;
92         } else {
93             mContentId = LegacyHelpers.buildLegacyContentId(mIsOfflinePage, mDownloadGuid);
94         }
95         mIsOpenable = builder.mIsOpenable;
96         mIsTransient = builder.mIsTransient;
97         mIsParallelDownload = builder.mIsParallelDownload;
98         mIcon = builder.mIcon;
99         mPendingState = builder.mPendingState;
100         mFailState = builder.mFailState;
101         mShouldPromoteOrigin = builder.mShouldPromoteOrigin;
102         mSchedule = builder.mSchedule;
103     }
104 
getUrl()105     public String getUrl() {
106         return mUrl;
107     }
108 
getUserAgent()109     public String getUserAgent() {
110         return mUserAgent;
111     }
112 
getMimeType()113     public String getMimeType() {
114         return mMimeType;
115     }
116 
getCookie()117     public String getCookie() {
118         return mCookie;
119     }
120 
getFileName()121     public String getFileName() {
122         return mFileName;
123     }
124 
getDescription()125     public String getDescription() {
126         return mDescription;
127     }
128 
getFilePath()129     public String getFilePath() {
130         return mFilePath;
131     }
132 
getReferrer()133     public String getReferrer() {
134         return mReferrer;
135     }
136 
getOriginalUrl()137     public String getOriginalUrl() {
138         return mOriginalUrl;
139     }
140 
getBytesReceived()141     public long getBytesReceived() {
142         return mBytesReceived;
143     }
144 
getBytesTotalSize()145     public long getBytesTotalSize() {
146         return mBytesTotalSize;
147     }
148 
isGETRequest()149     public boolean isGETRequest() {
150         return mIsGETRequest;
151     }
152 
getDownloadGuid()153     public String getDownloadGuid() {
154         return mDownloadGuid;
155     }
156 
hasUserGesture()157     public boolean hasUserGesture() {
158         return mHasUserGesture;
159     }
160 
getContentDisposition()161     public String getContentDisposition() {
162         return mContentDisposition;
163     }
164 
getProgress()165     public Progress getProgress() {
166         return mProgress;
167     }
168 
169     /**
170      * @return Remaining download time in milliseconds or -1 if it is unknown.
171      */
getTimeRemainingInMillis()172     public long getTimeRemainingInMillis() {
173         return mTimeRemainingInMillis;
174     }
175 
isResumable()176     public boolean isResumable() {
177         return mIsResumable;
178     }
179 
isPaused()180     public boolean isPaused() {
181         return mIsPaused;
182     }
183 
isOffTheRecord()184     public boolean isOffTheRecord() {
185         return mIsOffTheRecord;
186     }
187 
isOfflinePage()188     public boolean isOfflinePage() {
189         return mIsOfflinePage;
190     }
191 
state()192     public int state() {
193         return mState;
194     }
195 
getLastAccessTime()196     public long getLastAccessTime() {
197         return mLastAccessTime;
198     }
199 
getIsDangerous()200     public boolean getIsDangerous() {
201         return mIsDangerous;
202     }
203 
getContentId()204     public ContentId getContentId() {
205         return mContentId;
206     }
207 
getIsOpenable()208     public boolean getIsOpenable() {
209         return mIsOpenable;
210     }
211 
getIsTransient()212     public boolean getIsTransient() {
213         return mIsTransient;
214     }
215 
getIsParallelDownload()216     public boolean getIsParallelDownload() {
217         return mIsParallelDownload;
218     }
219 
getIcon()220     public Bitmap getIcon() {
221         return mIcon;
222     }
223 
getPendingState()224     public @PendingState int getPendingState() {
225         return mPendingState;
226     }
227 
getFailState()228     public @FailState int getFailState() {
229         return mFailState;
230     }
231 
getShouldPromoteOrigin()232     public boolean getShouldPromoteOrigin() {
233         return mShouldPromoteOrigin;
234     }
235 
getOfflineItemSchedule()236     public OfflineItemSchedule getOfflineItemSchedule() {
237         return mSchedule;
238     }
239 
240     /**
241      * Helper method to build a {@link DownloadInfo} from an {@link OfflineItem}.
242      * @param item    The {@link OfflineItem} to mimic.
243      * @param visuals The {@link OfflineItemVisuals} to mimic.
244      * @return        A {@link DownloadInfo} containing the relevant fields from {@code item}.
245      */
fromOfflineItem(OfflineItem item, OfflineItemVisuals visuals)246     public static DownloadInfo fromOfflineItem(OfflineItem item, OfflineItemVisuals visuals) {
247         return builderFromOfflineItem(item, visuals).build();
248     }
249 
250     /**
251      * Helper method to build a {@link DownloadInfo.Builder} from an {@link OfflineItem}.
252      * @param item    The {@link OfflineItem} to mimic.
253      * @param visuals The {@link OfflineItemVisuals} to mimic.
254      * @return        A {@link DownloadInfo.Builder} containing the relevant fields from
255      *                {@code item}.
256      */
builderFromOfflineItem( OfflineItem item, OfflineItemVisuals visuals)257     public static DownloadInfo.Builder builderFromOfflineItem(
258             OfflineItem item, OfflineItemVisuals visuals) {
259         int state;
260         switch (item.state) {
261             case OfflineItemState.COMPLETE:
262                 state = DownloadState.COMPLETE;
263                 break;
264             case OfflineItemState.CANCELLED:
265                 state = DownloadState.CANCELLED;
266                 break;
267             case OfflineItemState.INTERRUPTED:
268                 state = DownloadState.INTERRUPTED;
269                 break;
270             case OfflineItemState.FAILED:
271                 state = DownloadState.INTERRUPTED; // TODO(dtrainor): Validate what this state is.
272                 break;
273             case OfflineItemState.PENDING: // TODO(dtrainor): Validate what this state is.
274             case OfflineItemState.IN_PROGRESS:
275             case OfflineItemState.PAUSED: // TODO(dtrainor): Validate what this state is.
276             default:
277                 state = DownloadState.IN_PROGRESS;
278                 break;
279         }
280 
281         return new DownloadInfo.Builder()
282                 .setContentId(item.id)
283                 .setDownloadGuid(item.id.id)
284                 .setFileName(item.title)
285                 .setFilePath(item.filePath)
286                 .setDescription(item.description)
287                 .setIsTransient(item.isTransient)
288                 .setLastAccessTime(item.lastAccessedTimeMs)
289                 .setIsOpenable(item.isOpenable)
290                 .setMimeType(item.mimeType)
291                 .setUrl(item.pageUrl)
292                 .setOriginalUrl(item.originalUrl)
293                 .setIsOffTheRecord(item.isOffTheRecord)
294                 .setState(state)
295                 .setIsPaused(item.state == OfflineItemState.PAUSED)
296                 .setIsResumable(item.isResumable)
297                 .setBytesReceived(item.receivedBytes)
298                 .setBytesTotalSize(item.totalSizeBytes)
299                 .setProgress(item.progress)
300                 .setTimeRemainingInMillis(item.timeRemainingMs)
301                 .setIsDangerous(item.isDangerous)
302                 .setIsParallelDownload(item.isAccelerated)
303                 .setIcon(visuals == null ? null : visuals.icon)
304                 .setPendingState(item.pendingState)
305                 .setFailState(item.failState)
306                 .setShouldPromoteOrigin(item.promoteOrigin)
307                 .setOfflineItemSchedule(item.schedule);
308     }
309 
310     /**
311      * Helper class for building the DownloadInfo object.
312      */
313     public static class Builder {
314         private String mUrl;
315         private String mUserAgent;
316         private String mMimeType;
317         private String mCookie;
318         private String mFileName;
319         private String mDescription;
320         private String mFilePath;
321         private String mReferrer;
322         private String mOriginalUrl;
323         private long mBytesReceived;
324         private long mBytesTotalSize;
325         private boolean mIsGETRequest;
326         private String mDownloadGuid;
327         private boolean mHasUserGesture;
328         private String mContentDisposition;
329         private Progress mProgress = Progress.createIndeterminateProgress();
330         private long mTimeRemainingInMillis;
331         private boolean mIsResumable = true;
332         private boolean mIsPaused;
333         private boolean mIsOffTheRecord;
334         private boolean mIsOfflinePage;
335         private int mState = DownloadState.IN_PROGRESS;
336         private long mLastAccessTime;
337         private boolean mIsDangerous;
338         private ContentId mContentId;
339         private boolean mIsOpenable = true;
340         private boolean mIsTransient;
341         private boolean mIsParallelDownload;
342         private Bitmap mIcon;
343         @PendingState
344         private int mPendingState;
345         @FailState
346         private int mFailState;
347         private boolean mShouldPromoteOrigin;
348         private OfflineItemSchedule mSchedule;
349 
setUrl(String url)350         public Builder setUrl(String url) {
351             mUrl = url;
352             return this;
353         }
354 
setUserAgent(String userAgent)355         public Builder setUserAgent(String userAgent) {
356             mUserAgent = userAgent;
357             return this;
358         }
359 
setMimeType(String mimeType)360         public Builder setMimeType(String mimeType) {
361             mMimeType = mimeType;
362             return this;
363         }
364 
setCookie(String cookie)365         public Builder setCookie(String cookie) {
366             mCookie = cookie;
367             return this;
368         }
369 
setFileName(String fileName)370         public Builder setFileName(String fileName) {
371             mFileName = fileName;
372             return this;
373         }
374 
setDescription(String description)375         public Builder setDescription(String description) {
376             mDescription = description;
377             return this;
378         }
379 
setFilePath(String filePath)380         public Builder setFilePath(String filePath) {
381             mFilePath = filePath;
382             return this;
383         }
384 
setReferrer(String referer)385         public Builder setReferrer(String referer) {
386             mReferrer = referer;
387             return this;
388         }
389 
setOriginalUrl(String originalUrl)390         public Builder setOriginalUrl(String originalUrl) {
391             mOriginalUrl = originalUrl;
392             return this;
393         }
394 
setBytesReceived(long bytesReceived)395         public Builder setBytesReceived(long bytesReceived) {
396             mBytesReceived = bytesReceived;
397             return this;
398         }
399 
setBytesTotalSize(long bytesTotalSize)400         public Builder setBytesTotalSize(long bytesTotalSize) {
401             mBytesTotalSize = bytesTotalSize;
402             return this;
403         }
404 
setIsGETRequest(boolean isGETRequest)405         public Builder setIsGETRequest(boolean isGETRequest) {
406             mIsGETRequest = isGETRequest;
407             return this;
408         }
409 
setDownloadGuid(String downloadGuid)410         public Builder setDownloadGuid(String downloadGuid) {
411             mDownloadGuid = downloadGuid;
412             return this;
413         }
414 
setHasUserGesture(boolean hasUserGesture)415         public Builder setHasUserGesture(boolean hasUserGesture) {
416             mHasUserGesture = hasUserGesture;
417             return this;
418         }
419 
setContentDisposition(String contentDisposition)420         public Builder setContentDisposition(String contentDisposition) {
421             mContentDisposition = contentDisposition;
422             return this;
423         }
424 
setProgress(OfflineItem.Progress progress)425         public Builder setProgress(OfflineItem.Progress progress) {
426             mProgress = progress;
427             return this;
428         }
429 
setTimeRemainingInMillis(long timeRemainingInMillis)430         public Builder setTimeRemainingInMillis(long timeRemainingInMillis) {
431             mTimeRemainingInMillis = timeRemainingInMillis;
432             return this;
433         }
434 
setIsResumable(boolean isResumable)435         public Builder setIsResumable(boolean isResumable) {
436             mIsResumable = isResumable;
437             return this;
438         }
439 
setIsPaused(boolean isPaused)440         public Builder setIsPaused(boolean isPaused) {
441             mIsPaused = isPaused;
442             return this;
443         }
444 
setIsOffTheRecord(boolean isOffTheRecord)445         public Builder setIsOffTheRecord(boolean isOffTheRecord) {
446             mIsOffTheRecord = isOffTheRecord;
447             return this;
448         }
449 
setIsOfflinePage(boolean isOfflinePage)450         public Builder setIsOfflinePage(boolean isOfflinePage) {
451             mIsOfflinePage = isOfflinePage;
452             return this;
453         }
454 
setState(int downloadState)455         public Builder setState(int downloadState) {
456             mState = downloadState;
457             return this;
458         }
459 
setLastAccessTime(long lastAccessTime)460         public Builder setLastAccessTime(long lastAccessTime) {
461             mLastAccessTime = lastAccessTime;
462             return this;
463         }
464 
setIsDangerous(boolean isDangerous)465         public Builder setIsDangerous(boolean isDangerous) {
466             mIsDangerous = isDangerous;
467             return this;
468         }
469 
setContentId(ContentId contentId)470         public Builder setContentId(ContentId contentId) {
471             mContentId = contentId;
472             return this;
473         }
474 
setIsOpenable(boolean isOpenable)475         public Builder setIsOpenable(boolean isOpenable) {
476             mIsOpenable = isOpenable;
477             return this;
478         }
479 
setIsTransient(boolean isTransient)480         public Builder setIsTransient(boolean isTransient) {
481             mIsTransient = isTransient;
482             return this;
483         }
484 
setIsParallelDownload(boolean isParallelDownload)485         public Builder setIsParallelDownload(boolean isParallelDownload) {
486             mIsParallelDownload = isParallelDownload;
487             return this;
488         }
489 
setIcon(Bitmap icon)490         public Builder setIcon(Bitmap icon) {
491             mIcon = icon;
492             return this;
493         }
494 
setPendingState(@endingState int pendingState)495         public Builder setPendingState(@PendingState int pendingState) {
496             mPendingState = pendingState;
497             return this;
498         }
499 
setFailState(@ailState int failState)500         public Builder setFailState(@FailState int failState) {
501             mFailState = failState;
502             return this;
503         }
504 
setShouldPromoteOrigin(boolean shouldPromoteOrigin)505         public Builder setShouldPromoteOrigin(boolean shouldPromoteOrigin) {
506             mShouldPromoteOrigin = shouldPromoteOrigin;
507             return this;
508         }
509 
setOfflineItemSchedule(OfflineItemSchedule schedule)510         public Builder setOfflineItemSchedule(OfflineItemSchedule schedule) {
511             mSchedule = schedule;
512             return this;
513         }
514 
build()515         public DownloadInfo build() {
516             return new DownloadInfo(this);
517         }
518 
519         /**
520          * Create a builder from the DownloadInfo object.
521          * @param downloadInfo DownloadInfo object from which builder fields are populated.
522          * @return A builder initialized with fields from downloadInfo object.
523          */
fromDownloadInfo(final DownloadInfo downloadInfo)524         public static Builder fromDownloadInfo(final DownloadInfo downloadInfo) {
525             Builder builder = new Builder();
526             builder.setUrl(downloadInfo.getUrl())
527                     .setUserAgent(downloadInfo.getUserAgent())
528                     .setMimeType(downloadInfo.getMimeType())
529                     .setCookie(downloadInfo.getCookie())
530                     .setFileName(downloadInfo.getFileName())
531                     .setDescription(downloadInfo.getDescription())
532                     .setFilePath(downloadInfo.getFilePath())
533                     .setReferrer(downloadInfo.getReferrer())
534                     .setOriginalUrl(downloadInfo.getOriginalUrl())
535                     .setBytesReceived(downloadInfo.getBytesReceived())
536                     .setBytesTotalSize(downloadInfo.getBytesTotalSize())
537                     .setDownloadGuid(downloadInfo.getDownloadGuid())
538                     .setHasUserGesture(downloadInfo.hasUserGesture())
539                     .setContentDisposition(downloadInfo.getContentDisposition())
540                     .setIsGETRequest(downloadInfo.isGETRequest())
541                     .setProgress(downloadInfo.getProgress())
542                     .setTimeRemainingInMillis(downloadInfo.getTimeRemainingInMillis())
543                     .setIsDangerous(downloadInfo.getIsDangerous())
544                     .setIsResumable(downloadInfo.isResumable())
545                     .setIsPaused(downloadInfo.isPaused())
546                     .setIsOffTheRecord(downloadInfo.isOffTheRecord())
547                     .setIsOfflinePage(downloadInfo.isOfflinePage())
548                     .setState(downloadInfo.state())
549                     .setLastAccessTime(downloadInfo.getLastAccessTime())
550                     .setIsTransient(downloadInfo.getIsTransient())
551                     .setIsParallelDownload(downloadInfo.getIsParallelDownload())
552                     .setIcon(downloadInfo.getIcon())
553                     .setPendingState(downloadInfo.getPendingState())
554                     .setFailState(downloadInfo.getFailState())
555                     .setShouldPromoteOrigin(downloadInfo.getShouldPromoteOrigin())
556                     .setOfflineItemSchedule(downloadInfo.getOfflineItemSchedule());
557             return builder;
558         }
559     }
560 
561     @CalledByNative
createDownloadInfo(String downloadGuid, String fileName, String filePath, String url, String mimeType, long bytesReceived, long bytesTotalSize, boolean isIncognito, int state, int percentCompleted, boolean isPaused, boolean hasUserGesture, boolean isResumable, boolean isParallelDownload, String originalUrl, String referrerUrl, long timeRemainingInMs, long lastAccessTime, boolean isDangerous, @FailState int failState, OfflineItemSchedule schedule)562     private static DownloadInfo createDownloadInfo(String downloadGuid, String fileName,
563             String filePath, String url, String mimeType, long bytesReceived, long bytesTotalSize,
564             boolean isIncognito, int state, int percentCompleted, boolean isPaused,
565             boolean hasUserGesture, boolean isResumable, boolean isParallelDownload,
566             String originalUrl, String referrerUrl, long timeRemainingInMs, long lastAccessTime,
567             boolean isDangerous, @FailState int failState, OfflineItemSchedule schedule) {
568         String remappedMimeType = MimeUtils.remapGenericMimeType(mimeType, url, fileName);
569 
570         Progress progress = new Progress(bytesReceived,
571                 percentCompleted == -1 ? null : bytesTotalSize, OfflineItemProgressUnit.BYTES);
572 
573         return new DownloadInfo.Builder()
574                 .setBytesReceived(bytesReceived)
575                 .setBytesTotalSize(bytesTotalSize)
576                 .setDescription(fileName)
577                 .setDownloadGuid(downloadGuid)
578                 .setFileName(fileName)
579                 .setFilePath(filePath)
580                 .setHasUserGesture(hasUserGesture)
581                 .setIsOffTheRecord(isIncognito)
582                 .setIsPaused(isPaused)
583                 .setIsResumable(isResumable)
584                 .setIsParallelDownload(isParallelDownload)
585                 .setMimeType(remappedMimeType)
586                 .setOriginalUrl(originalUrl)
587                 .setProgress(progress)
588                 .setReferrer(referrerUrl)
589                 .setState(state)
590                 .setTimeRemainingInMillis(timeRemainingInMs)
591                 .setLastAccessTime(lastAccessTime)
592                 .setIsDangerous(isDangerous)
593                 .setUrl(url)
594                 .setFailState(failState)
595                 .setOfflineItemSchedule(schedule)
596                 .build();
597     }
598 }
599