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
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.download;
6 
7 import android.app.Activity;
8 import android.app.DownloadManager;
9 import android.content.Intent;
10 
11 import org.chromium.base.ApplicationStatus;
12 import org.chromium.base.ContextUtils;
13 import org.chromium.chrome.R;
14 import org.chromium.chrome.browser.download.items.OfflineContentAggregatorNotificationBridgeUiFactory;
15 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
16 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
17 import org.chromium.components.offline_items_collection.LaunchLocation;
18 import org.chromium.components.offline_items_collection.LegacyHelpers;
19 import org.chromium.components.offline_items_collection.OpenParams;
20 
21 /**
22  * Class for displaying a snackbar when a download completes.
23  */
24 public class DownloadSnackbarController implements SnackbarManager.SnackbarController {
25     public static final int INVALID_NOTIFICATION_ID = -1;
26     private static final int SNACKBAR_DURATION_MS = 7000;
27 
28     private static class ActionDataInfo {
29         public final DownloadInfo downloadInfo;
30         public final int notificationId;
31         public final long systemDownloadId;
32         public final boolean usesAndroidDownloadManager;
33 
ActionDataInfo(DownloadInfo downloadInfo, int notificationId, long systemDownloadId, boolean usesAndroidDownloadManager)34         ActionDataInfo(DownloadInfo downloadInfo, int notificationId, long systemDownloadId,
35                 boolean usesAndroidDownloadManager) {
36             this.downloadInfo = downloadInfo;
37             this.notificationId = notificationId;
38             this.systemDownloadId = systemDownloadId;
39             this.usesAndroidDownloadManager = usesAndroidDownloadManager;
40         }
41     }
42 
43     @Override
onAction(Object actionData)44     public void onAction(Object actionData) {
45         if (!(actionData instanceof ActionDataInfo)) {
46             DownloadManagerService.openDownloadsPage(
47                     ContextUtils.getApplicationContext(), DownloadOpenSource.SNACK_BAR);
48             return;
49         }
50 
51         DownloadManagerService manager = DownloadManagerService.getDownloadManagerService();
52         final ActionDataInfo download = (ActionDataInfo) actionData;
53         if (LegacyHelpers.isLegacyDownload(download.downloadInfo.getContentId())) {
54             if (download.usesAndroidDownloadManager) {
55                 ContextUtils.getApplicationContext().startActivity(
56                         new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS)
57                                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
58             } else {
59                 manager.openDownloadedContent(download.downloadInfo, download.systemDownloadId,
60                         DownloadOpenSource.SNACK_BAR);
61             }
62         } else {
63             OfflineContentAggregatorNotificationBridgeUiFactory.instance().openItem(
64                     new OpenParams(LaunchLocation.PROGRESS_BAR),
65                     download.downloadInfo.getContentId());
66         }
67 
68         if (download.notificationId != INVALID_NOTIFICATION_ID) {
69             manager.getDownloadNotifier().removeDownloadNotification(
70                     download.notificationId, download.downloadInfo);
71         }
72     }
73 
74     @Override
onDismissNoAction(Object actionData)75     public void onDismissNoAction(Object actionData) {
76     }
77 
78     /**
79      * Called to display the download failed snackbar.
80      *
81      * @param errorMessage     The message to show on the snackbar.
82      * @param showAllDownloads Whether to show all downloads in case the failure is caused by
83      *                         duplicated files.
84      */
onDownloadFailed( String errorMessage, boolean showAllDownloads, boolean isOffTheRecord)85     public void onDownloadFailed(
86             String errorMessage, boolean showAllDownloads, boolean isOffTheRecord) {
87         if (isShowingDownloadInfoBar(isOffTheRecord)) return;
88         if (getSnackbarManager() == null) return;
89         // TODO(qinmin): Coalesce snackbars if multiple downloads finish at the same time.
90         Snackbar snackbar = Snackbar.make(errorMessage, this, Snackbar.TYPE_NOTIFICATION,
91                                             Snackbar.UMA_DOWNLOAD_FAILED)
92                                     .setSingleLine(false)
93                                     .setDuration(SNACKBAR_DURATION_MS);
94         if (showAllDownloads) {
95             snackbar.setAction(
96                     ContextUtils.getApplicationContext().getString(R.string.open_downloaded_label),
97                     null);
98         }
99         getSnackbarManager().showSnackbar(snackbar);
100     }
101 
102     /**
103      * Displays a snackbar that says alerts the user that some downloads may be missing because a
104      * missing SD card was detected.
105      */
onDownloadDirectoryNotFound()106     void onDownloadDirectoryNotFound() {
107         if (getSnackbarManager() == null) return;
108 
109         Snackbar snackbar = Snackbar.make(ContextUtils.getApplicationContext().getString(
110                                                   R.string.download_location_no_sd_card_snackbar),
111                                             this, Snackbar.TYPE_NOTIFICATION,
112                                             Snackbar.UMA_MISSING_FILES_NO_SD_CARD)
113                                     .setSingleLine(false)
114                                     .setDuration(SNACKBAR_DURATION_MS);
115         getSnackbarManager().showSnackbar(snackbar);
116     }
117 
getActivity()118     private Activity getActivity() {
119         if (ApplicationStatus.hasVisibleActivities()) {
120             return ApplicationStatus.getLastTrackedFocusedActivity();
121         } else {
122             return null;
123         }
124     }
125 
getSnackbarManager()126     public SnackbarManager getSnackbarManager() {
127         Activity activity = getActivity();
128         if (activity != null && activity instanceof SnackbarManager.SnackbarManageable) {
129             return ((SnackbarManager.SnackbarManageable) activity).getSnackbarManager();
130         }
131         return null;
132     }
133 
isShowingDownloadInfoBar(boolean isOffTheRecord)134     private boolean isShowingDownloadInfoBar(boolean isOffTheRecord) {
135         DownloadInfoBarController infoBarController =
136                 DownloadManagerService.getDownloadManagerService().getInfoBarController(
137                         isOffTheRecord);
138         return infoBarController == null ? false : infoBarController.isShowing();
139     }
140 }
141