blob: 59f4b32024fd5f9954aa5fed83f3f3f081e265fc [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/download/download_danger_prompt.h"
#include "base/bind.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_danger_type.h"
#include "content/public/browser/download_item.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
namespace {
// Implements DownloadDangerPrompt using a TabModalConfirmDialog.
class DownloadDangerPromptImpl
: public DownloadDangerPrompt,
public content::DownloadItem::Observer,
public TabModalConfirmDialogDelegate {
public:
DownloadDangerPromptImpl(content::DownloadItem* item,
TabContents* tab_contents,
const base::Closure& accepted,
const base::Closure& canceled);
virtual ~DownloadDangerPromptImpl();
// DownloadDangerPrompt
virtual void InvokeActionForTesting(Action action) OVERRIDE;
private:
// content::DownloadItem::Observer
virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE;
virtual void OnDownloadOpened(content::DownloadItem* download) OVERRIDE;
// TabModalConfirmDialogDelegate
virtual string16 GetTitle() OVERRIDE;
virtual string16 GetMessage() OVERRIDE;
virtual string16 GetAcceptButtonTitle() OVERRIDE;
virtual void OnAccepted() OVERRIDE;
virtual void OnCanceled() OVERRIDE;
// Runs |callback|. PrepareToClose() is called beforehand. Doing so prevents
// this object from responding to state changes in |download_| that might
// result from invoking the callback. |callback| must refer to either
// |accepted_| or |canceled_|.
void RunCallback(const base::Closure& callback);
// Resets |accepted_|, |canceled_| and removes the observer from |download_|,
// in preparation for closing the prompt.
void PrepareToClose();
content::DownloadItem* download_;
base::Closure accepted_;
base::Closure canceled_;
DISALLOW_COPY_AND_ASSIGN(DownloadDangerPromptImpl);
};
DownloadDangerPromptImpl::DownloadDangerPromptImpl(
content::DownloadItem* download,
TabContents* tab_contents,
const base::Closure& accepted,
const base::Closure& canceled)
: TabModalConfirmDialogDelegate(tab_contents->web_contents()),
download_(download),
accepted_(accepted),
canceled_(canceled) {
DCHECK(!accepted_.is_null());
// canceled_ is allowed to be null.
DCHECK(download_);
download_->AddObserver(this);
}
DownloadDangerPromptImpl::~DownloadDangerPromptImpl() {
// |this| might be deleted without invoking any callbacks. E.g. pressing Esc
// on GTK or if the user navigates away from the page showing the prompt.
PrepareToClose();
}
void DownloadDangerPromptImpl::InvokeActionForTesting(Action action) {
if (action == ACCEPT)
Accept();
else
Cancel();
}
void DownloadDangerPromptImpl::OnDownloadUpdated(
content::DownloadItem* download) {
// If the download is nolonger dangerous (accepted externally) or the download
// doesn't exist anymore, the download danger prompt is no longer necessary.
if (!download->IsInProgress() || !download->IsDangerous())
Cancel();
}
void DownloadDangerPromptImpl::OnDownloadOpened(
content::DownloadItem* download) {
}
string16 DownloadDangerPromptImpl::GetTitle() {
return l10n_util::GetStringUTF16(IDS_CONFIRM_KEEP_DANGEROUS_DOWNLOAD_TITLE);
}
string16 DownloadDangerPromptImpl::GetMessage() {
return l10n_util::GetStringUTF16(IDS_PROMPT_CONFIRM_KEEP_DANGEROUS_DOWNLOAD);
}
string16 DownloadDangerPromptImpl::GetAcceptButtonTitle() {
return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD_AGAIN);
}
void DownloadDangerPromptImpl::OnAccepted() {
RunCallback(accepted_);
}
void DownloadDangerPromptImpl::OnCanceled() {
RunCallback(canceled_);
}
void DownloadDangerPromptImpl::RunCallback(const base::Closure& callback) {
// Invoking the callback can cause the download item state to change or cause
// the constrained window to close, and |callback| refers to a member
// variable.
base::Closure callback_copy = callback;
PrepareToClose();
if (!callback_copy.is_null())
callback_copy.Run();
}
void DownloadDangerPromptImpl::PrepareToClose() {
accepted_.Reset();
canceled_.Reset();
if (download_ != NULL) {
download_->RemoveObserver(this);
download_ = NULL;
}
}
} // namespace
// static
DownloadDangerPrompt* DownloadDangerPrompt::Create(
content::DownloadItem* item,
TabContents* tab_contents,
const base::Closure& accepted,
const base::Closure& canceled) {
DownloadDangerPromptImpl* prompt =
new DownloadDangerPromptImpl(item, tab_contents, accepted, canceled);
// |prompt| will be deleted when the dialog is done.
TabModalConfirmDialog::Create(prompt, tab_contents);
return prompt;
}