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/download/download_danger_prompt.h" 6 7 #include "base/bind.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "chrome/browser/chrome_notification_types.h" 10 #include "chrome/browser/download/chrome_download_manager_delegate.h" 11 #include "chrome/browser/download/download_stats.h" 12 #include "chrome/browser/ui/tab_modal_confirm_dialog.h" 13 #include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h" 14 #include "content/public/browser/download_danger_type.h" 15 #include "content/public/browser/download_item.h" 16 #include "grit/chromium_strings.h" 17 #include "grit/generated_resources.h" 18 #include "ui/base/l10n/l10n_util.h" 19 20 namespace { 21 22 // TODO(wittman): Create a native web contents modal dialog implementation of 23 // this dialog for non-Views platforms, to support bold formatting of the 24 // message lead. 25 26 // Implements DownloadDangerPrompt using a TabModalConfirmDialog. 27 class DownloadDangerPromptImpl : public DownloadDangerPrompt, 28 public content::DownloadItem::Observer, 29 public TabModalConfirmDialogDelegate { 30 public: 31 DownloadDangerPromptImpl(content::DownloadItem* item, 32 content::WebContents* web_contents, 33 bool show_context, 34 const OnDone& done); 35 virtual ~DownloadDangerPromptImpl(); 36 37 // DownloadDangerPrompt: 38 virtual void InvokeActionForTesting(Action action) OVERRIDE; 39 40 private: 41 // content::DownloadItem::Observer: 42 virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE; 43 44 // TabModalConfirmDialogDelegate: 45 virtual base::string16 GetTitle() OVERRIDE; 46 virtual base::string16 GetMessage() OVERRIDE; 47 virtual base::string16 GetAcceptButtonTitle() OVERRIDE; 48 virtual base::string16 GetCancelButtonTitle() OVERRIDE; 49 virtual void OnAccepted() OVERRIDE; 50 virtual void OnCanceled() OVERRIDE; 51 virtual void OnClosed() OVERRIDE; 52 53 void RunDone(Action action); 54 55 content::DownloadItem* download_; 56 bool show_context_; 57 OnDone done_; 58 59 DISALLOW_COPY_AND_ASSIGN(DownloadDangerPromptImpl); 60 }; 61 62 DownloadDangerPromptImpl::DownloadDangerPromptImpl( 63 content::DownloadItem* download, 64 content::WebContents* web_contents, 65 bool show_context, 66 const OnDone& done) 67 : TabModalConfirmDialogDelegate(web_contents), 68 download_(download), 69 show_context_(show_context), 70 done_(done) { 71 DCHECK(!done_.is_null()); 72 download_->AddObserver(this); 73 RecordOpenedDangerousConfirmDialog(download_->GetDangerType()); 74 } 75 76 DownloadDangerPromptImpl::~DownloadDangerPromptImpl() { 77 // |this| might be deleted without invoking any callbacks. E.g. pressing Esc 78 // on GTK or if the user navigates away from the page showing the prompt. 79 RunDone(DISMISS); 80 } 81 82 void DownloadDangerPromptImpl::InvokeActionForTesting(Action action) { 83 switch (action) { 84 case ACCEPT: Accept(); break; 85 case CANCEL: Cancel(); break; 86 case DISMISS: 87 RunDone(DISMISS); 88 Cancel(); 89 break; 90 } 91 } 92 93 void DownloadDangerPromptImpl::OnDownloadUpdated( 94 content::DownloadItem* download) { 95 // If the download is nolonger dangerous (accepted externally) or the download 96 // is in a terminal state, then the download danger prompt is no longer 97 // necessary. 98 if (!download->IsDangerous() || download->IsDone()) { 99 RunDone(DISMISS); 100 Cancel(); 101 } 102 } 103 104 base::string16 DownloadDangerPromptImpl::GetTitle() { 105 if (show_context_) 106 return l10n_util::GetStringUTF16(IDS_CONFIRM_KEEP_DANGEROUS_DOWNLOAD_TITLE); 107 switch (download_->GetDangerType()) { 108 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: 109 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: 110 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: 111 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: { 112 return l10n_util::GetStringUTF16( 113 IDS_RESTORE_KEEP_DANGEROUS_DOWNLOAD_TITLE); 114 } 115 default: { 116 return l10n_util::GetStringUTF16( 117 IDS_CONFIRM_KEEP_DANGEROUS_DOWNLOAD_TITLE); 118 } 119 } 120 } 121 122 base::string16 DownloadDangerPromptImpl::GetMessage() { 123 if (show_context_) { 124 switch (download_->GetDangerType()) { 125 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: { 126 return l10n_util::GetStringFUTF16( 127 IDS_PROMPT_DANGEROUS_DOWNLOAD, 128 download_->GetFileNameToReportUser().LossyDisplayName()); 129 } 130 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: // Fall through 131 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: 132 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: { 133 return l10n_util::GetStringFUTF16( 134 IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT, 135 download_->GetFileNameToReportUser().LossyDisplayName()); 136 } 137 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: { 138 return l10n_util::GetStringFUTF16( 139 IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT, 140 download_->GetFileNameToReportUser().LossyDisplayName()); 141 } 142 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: { 143 return l10n_util::GetStringFUTF16( 144 IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS, 145 download_->GetFileNameToReportUser().LossyDisplayName()); 146 } 147 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS: 148 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT: 149 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED: 150 case content::DOWNLOAD_DANGER_TYPE_MAX: { 151 break; 152 } 153 } 154 } else { 155 switch (download_->GetDangerType()) { 156 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: 157 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: 158 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: { 159 return l10n_util::GetStringUTF16( 160 IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_LEAD) + 161 ASCIIToUTF16("\n\n") + 162 l10n_util::GetStringUTF16( 163 IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_BODY); 164 } 165 default: { 166 return l10n_util::GetStringUTF16( 167 IDS_PROMPT_CONFIRM_KEEP_DANGEROUS_DOWNLOAD); 168 } 169 } 170 } 171 NOTREACHED(); 172 return base::string16(); 173 } 174 175 base::string16 DownloadDangerPromptImpl::GetAcceptButtonTitle() { 176 if (show_context_) 177 return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD); 178 switch (download_->GetDangerType()) { 179 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: 180 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: 181 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: 182 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: { 183 return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD_AGAIN_MALICIOUS); 184 } 185 default: 186 return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD_AGAIN); 187 } 188 } 189 190 base::string16 DownloadDangerPromptImpl::GetCancelButtonTitle() { 191 if (show_context_) 192 return l10n_util::GetStringUTF16(IDS_CANCEL); 193 switch (download_->GetDangerType()) { 194 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: 195 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: 196 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: 197 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: { 198 return l10n_util::GetStringUTF16(IDS_CONFIRM_CANCEL_AGAIN_MALICIOUS); 199 } 200 default: 201 return l10n_util::GetStringUTF16(IDS_CANCEL); 202 } 203 } 204 205 void DownloadDangerPromptImpl::OnAccepted() { 206 RunDone(ACCEPT); 207 } 208 209 void DownloadDangerPromptImpl::OnCanceled() { 210 RunDone(CANCEL); 211 } 212 213 void DownloadDangerPromptImpl::OnClosed() { 214 RunDone(DISMISS); 215 } 216 217 void DownloadDangerPromptImpl::RunDone(Action action) { 218 // Invoking the callback can cause the download item state to change or cause 219 // the constrained window to close, and |callback| refers to a member 220 // variable. 221 OnDone done = done_; 222 done_.Reset(); 223 if (download_ != NULL) { 224 download_->RemoveObserver(this); 225 download_ = NULL; 226 } 227 if (!done.is_null()) 228 done.Run(action); 229 } 230 231 } // namespace 232 233 #if !(defined(OS_WIN) || defined(USE_AURA)) 234 // static 235 DownloadDangerPrompt* DownloadDangerPrompt::Create( 236 content::DownloadItem* item, 237 content::WebContents* web_contents, 238 bool show_context, 239 const OnDone& done) { 240 DownloadDangerPromptImpl* prompt = new DownloadDangerPromptImpl( 241 item, web_contents, show_context, done); 242 // |prompt| will be deleted when the dialog is done. 243 TabModalConfirmDialog::Create(prompt, web_contents); 244 return prompt; 245 } 246 #endif 247