1 // Copyright (c) 2012 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 #include "chrome/browser/ui/webui/downloads/downloads_ui.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/memory/ref_counted_memory.h"
12 #include "base/memory/singleton.h"
13 #include "base/strings/string_piece.h"
14 #include "base/threading/thread.h"
15 #include "base/values.h"
16 #include "chrome/browser/defaults.h"
17 #include "chrome/browser/enterprise/connectors/connectors_manager.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/safe_browsing/advanced_protection_status_manager.h"
20 #include "chrome/browser/safe_browsing/advanced_protection_status_manager_factory.h"
21 #include "chrome/browser/ui/webui/downloads/downloads.mojom.h"
22 #include "chrome/browser/ui/webui/downloads/downloads_dom_handler.h"
23 #include "chrome/browser/ui/webui/managed_ui_handler.h"
24 #include "chrome/browser/ui/webui/metrics_handler.h"
25 #include "chrome/browser/ui/webui/theme_source.h"
26 #include "chrome/browser/ui/webui/webui_util.h"
27 #include "chrome/common/buildflags.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/common/pref_names.h"
30 #include "chrome/common/url_constants.h"
31 #include "chrome/grit/chromium_strings.h"
32 #include "chrome/grit/downloads_resources.h"
33 #include "chrome/grit/downloads_resources_map.h"
34 #include "chrome/grit/generated_resources.h"
35 #include "chrome/grit/theme_resources.h"
36 #include "components/prefs/pref_service.h"
37 #include "content/public/browser/download_manager.h"
38 #include "content/public/browser/url_data_source.h"
39 #include "content/public/browser/web_contents.h"
40 #include "content/public/browser/web_ui.h"
41 #include "content/public/browser/web_ui_data_source.h"
42 #include "mojo/public/cpp/bindings/pending_receiver.h"
43 #include "mojo/public/cpp/bindings/pending_remote.h"
44 #include "mojo/public/cpp/bindings/receiver.h"
45 #include "ui/base/accelerators/accelerator.h"
46 #include "ui/base/l10n/l10n_util.h"
47 #include "ui/base/resource/resource_bundle.h"
48 #include "ui/base/webui/web_ui_util.h"
49 
50 using content::BrowserContext;
51 using content::DownloadManager;
52 using content::WebContents;
53 
54 namespace {
55 
CreateDownloadsUIHTMLSource(Profile * profile)56 content::WebUIDataSource* CreateDownloadsUIHTMLSource(Profile* profile) {
57   content::WebUIDataSource* source =
58       content::WebUIDataSource::Create(chrome::kChromeUIDownloadsHost);
59   webui::SetupWebUIDataSource(
60       source, base::make_span(kDownloadsResources, kDownloadsResourcesSize), "",
61       IDR_DOWNLOADS_DOWNLOADS_HTML);
62 
63   bool requests_ap_verdicts =
64       safe_browsing::AdvancedProtectionStatusManagerFactory::GetForProfile(
65           profile)
66           ->IsUnderAdvancedProtection();
67   source->AddBoolean("requestsApVerdicts", requests_ap_verdicts);
68 
69   static constexpr webui::LocalizedString kStrings[] = {
70       {"title", IDS_DOWNLOAD_TITLE},
71       {"searchResultsPlural", IDS_SEARCH_RESULTS_PLURAL},
72       {"searchResultsSingular", IDS_SEARCH_RESULTS_SINGULAR},
73       {"downloads", IDS_DOWNLOAD_TITLE},
74       {"actionMenuDescription", IDS_DOWNLOAD_ACTION_MENU_DESCRIPTION},
75       {"clearAll", IDS_DOWNLOAD_LINK_CLEAR_ALL},
76       {"clearSearch", IDS_CLEAR_SEARCH},
77       {"openDownloadsFolder", IDS_DOWNLOAD_LINK_OPEN_DOWNLOADS_FOLDER},
78       {"moreActions", IDS_DOWNLOAD_MORE_ACTIONS},
79       {"search", IDS_DOWNLOAD_SEARCH},
80 
81       // No results message that shows instead of the downloads list.
82       {"noDownloads", IDS_DOWNLOAD_NO_DOWNLOADS},
83       {"noSearchResults", IDS_SEARCH_NO_RESULTS},
84 
85       // Status.
86       {"statusCancelled", IDS_DOWNLOAD_TAB_CANCELLED},
87       {"statusRemoved", IDS_DOWNLOAD_FILE_REMOVED},
88 
89       // Dangerous file.
90       {"dangerFileDesc", IDS_BLOCK_REASON_GENERIC_DOWNLOAD},
91       {"dangerSave", IDS_CONFIRM_DOWNLOAD},
92       {"dangerRestore", IDS_CONFIRM_DOWNLOAD_RESTORE},
93       {"dangerDiscard", IDS_DISCARD_DOWNLOAD},
94 
95       // Deep scanning strings.
96       {"deepScannedSafeDesc", IDS_DEEP_SCANNED_SAFE_DESCRIPTION},
97       {"deepScannedOpenedDangerousDesc",
98        IDS_DEEP_SCANNED_OPENED_DANGEROUS_DESCRIPTION},
99       {"sensitiveContentWarningDesc",
100        IDS_BLOCK_REASON_SENSITIVE_CONTENT_WARNING},
101       {"sensitiveContentBlockedDesc",
102        IDS_SENSITIVE_CONTENT_BLOCKED_DESCRIPTION},
103       {"blockedTooLargeDesc", IDS_BLOCKED_TOO_LARGE_DESCRIPTION},
104       {"blockedPasswordProtectedDesc",
105        IDS_BLOCKED_PASSWORD_PROTECTED_DESCRIPTION},
106 
107       // Controls.
108       {"controlPause", IDS_DOWNLOAD_LINK_PAUSE},
109       {"controlCancel", IDS_DOWNLOAD_LINK_CANCEL},
110       {"controlResume", IDS_DOWNLOAD_LINK_RESUME},
111       {"controlRemoveFromList", IDS_DOWNLOAD_LINK_REMOVE},
112       {"controlRemoveFromListAriaLabel", IDS_DOWNLOAD_LINK_REMOVE_ARIA_LABEL},
113       {"controlRetry", IDS_DOWNLOAD_LINK_RETRY},
114       {"controlledByUrl", IDS_DOWNLOAD_BY_EXTENSION_URL},
115       {"controlOpenNow", IDS_OPEN_DOWNLOAD_NOW},
116       {"toastClearedAll", IDS_DOWNLOAD_TOAST_CLEARED_ALL},
117       {"toastRemovedFromList", IDS_DOWNLOAD_TOAST_REMOVED_FROM_LIST},
118       {"undo", IDS_DOWNLOAD_UNDO},
119   };
120   AddLocalizedStringsBulk(source, kStrings);
121 
122   source->AddLocalizedString("dangerDownloadDesc",
123                              IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD);
124   source->AddLocalizedString(
125       "dangerUncommonDesc",
126       requests_ap_verdicts
127           ? IDS_BLOCK_REASON_UNCOMMON_DOWNLOAD_IN_ADVANCED_PROTECTION
128           : IDS_BLOCK_REASON_UNCOMMON_DOWNLOAD);
129   source->AddLocalizedString("dangerSettingsDesc",
130                              IDS_BLOCK_REASON_UNWANTED_DOWNLOAD);
131   source->AddLocalizedString("mixedContentDownloadDesc",
132                              IDS_BLOCK_REASON_MIXED_CONTENT);
133   source->AddLocalizedString("asyncScanningDownloadDesc",
134                              IDS_BLOCK_REASON_DEEP_SCANNING);
135   if (browser_defaults::kDownloadPageHasShowInFolder)
136     source->AddLocalizedString("controlShowInFolder", IDS_DOWNLOAD_LINK_SHOW);
137 
138   // Build an Accelerator to describe undo shortcut
139   // NOTE: the undo shortcut is also defined in downloads/downloads.html
140   // TODO(crbug/893033): de-duplicate shortcut by moving all shortcut
141   // definitions from JS to C++.
142   ui::Accelerator undo_accelerator(ui::VKEY_Z, ui::EF_PLATFORM_ACCELERATOR);
143   source->AddString("undoDescription", l10n_util::GetStringFUTF16(
144                                            IDS_UNDO_DESCRIPTION,
145                                            undo_accelerator.GetShortcutText()));
146 
147   PrefService* prefs = profile->GetPrefs();
148   source->AddBoolean("allowDeletingHistory",
149                      prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory) &&
150                          !profile->IsSupervised());
151 
152   source->AddLocalizedString("inIncognito", IDS_DOWNLOAD_IN_INCOGNITO);
153 
154   source->AddBoolean(
155       "allowOpenNow",
156       !enterprise_connectors::ConnectorsManager::GetInstance()
157            ->DelayUntilVerdict(
158                enterprise_connectors::AnalysisConnector::FILE_DOWNLOADED));
159 
160   return source;
161 }
162 
163 }  // namespace
164 
165 ///////////////////////////////////////////////////////////////////////////////
166 //
167 // DownloadsUI
168 //
169 ///////////////////////////////////////////////////////////////////////////////
170 
DownloadsUI(content::WebUI * web_ui)171 DownloadsUI::DownloadsUI(content::WebUI* web_ui)
172     : ui::MojoWebUIController(web_ui, true) {
173   Profile* profile = Profile::FromWebUI(web_ui);
174   web_ui->AddMessageHandler(std::make_unique<MetricsHandler>());
175 
176   // Set up the chrome://downloads/ source.
177   content::WebUIDataSource* source = CreateDownloadsUIHTMLSource(profile);
178   ManagedUIHandler::Initialize(web_ui, source);
179   content::WebUIDataSource::Add(profile, source);
180   content::URLDataSource::Add(profile, std::make_unique<ThemeSource>(profile));
181 }
182 
183 WEB_UI_CONTROLLER_TYPE_IMPL(DownloadsUI)
184 
185 DownloadsUI::~DownloadsUI() = default;
186 
187 // static
GetFaviconResourceBytes(ui::ScaleFactor scale_factor)188 base::RefCountedMemory* DownloadsUI::GetFaviconResourceBytes(
189     ui::ScaleFactor scale_factor) {
190   return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
191       IDR_DOWNLOADS_FAVICON, scale_factor);
192 }
193 
BindInterface(mojo::PendingReceiver<downloads::mojom::PageHandlerFactory> receiver)194 void DownloadsUI::BindInterface(
195     mojo::PendingReceiver<downloads::mojom::PageHandlerFactory> receiver) {
196   page_factory_receiver_.reset();
197 
198   page_factory_receiver_.Bind(std::move(receiver));
199 }
200 
CreatePageHandler(mojo::PendingRemote<downloads::mojom::Page> page,mojo::PendingReceiver<downloads::mojom::PageHandler> receiver)201 void DownloadsUI::CreatePageHandler(
202     mojo::PendingRemote<downloads::mojom::Page> page,
203     mojo::PendingReceiver<downloads::mojom::PageHandler> receiver) {
204   DCHECK(page);
205   Profile* profile = Profile::FromWebUI(web_ui());
206   DownloadManager* dlm = BrowserContext::GetDownloadManager(profile);
207 
208   page_handler_ = std::make_unique<DownloadsDOMHandler>(
209       std::move(receiver), std::move(page), dlm, web_ui());
210 }
211