summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-09 20:40:06 +0000
committerjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-09 20:40:06 +0000
commit69444cc086ef3ddf9aaecb4d6bebcb24687c6977 (patch)
treeedf46ca873f1a736095f86614dbb4abff316f14c
parentedd32342189ef6329e894ff08456a2c565606355 (diff)
downloadchromium_src-69444cc086ef3ddf9aaecb4d6bebcb24687c6977.zip
chromium_src-69444cc086ef3ddf9aaecb4d6bebcb24687c6977.tar.gz
chromium_src-69444cc086ef3ddf9aaecb4d6bebcb24687c6977.tar.bz2
This CL adds a confirmation box when closing the browser with in-progress downloads.
BUG=1028 TEST=Start several bug downloads, close the browser. A dialog shows up to warn you are about to lose the downloads. Try the wait and continue button. Try again with several windows, and in Incognito mode. Review URL: http://codereview.chromium.org/62131 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13453 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/generated_resources.grd11
-rw-r--r--chrome/browser/browser.cc76
-rw-r--r--chrome/browser/browser.h28
-rw-r--r--chrome/browser/browser_window.h6
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.h1
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.mm5
-rw-r--r--chrome/browser/gtk/browser_window_gtk.cc5
-rw-r--r--chrome/browser/gtk/browser_window_gtk.h1
-rw-r--r--chrome/browser/views/frame/browser_view.cc76
-rw-r--r--chrome/browser/views/frame/browser_view.h1
-rw-r--r--chrome/test/test_browser_window.h1
11 files changed, 208 insertions, 3 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 3a69196..c28c691 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -1349,6 +1349,17 @@ each locale. -->
&amp;Remove
</message>
+ <!-- Remove in-progress downloads confirmation dialog -->
+ <message name="IDS_DOWNLOAD_REMOVE_CONFIRM_TITLE" desc="Title of the dialog asking for user confirmation to close the browser when downloads are in-progress.">
+ You have <ph name="DOWNLOAD_COUNT">$1<ex>3</ex></ph> download(s) in progress. If you close Google Chrome, uncompleted downloads will be canceled and removed.
+ </message>
+ <message name="IDS_DOWNLOAD_REMOVE_CONFIRM_OK_BUTTON_LABEL" desc="Button text for OKing to close the browser when downloads are in-progress.">
+ Close and remove downloads
+ </message>
+ <message name="IDS_DOWNLOAD_REMOVE_CONFIRM_CANCEL_BUTTON_LABEL" desc="Button text for canceling the closing of the browser when downloads are in-progress.">
+ Wait for downloads to finish
+ </message>
+
<!-- Gears shortcut strings -->
<message name="IDS_CREATE_SHORTCUTS" desc="Default installation menu label">
Create application &amp;shortcuts...
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 3923936..35e4e22 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -16,6 +16,7 @@
#include "chrome/browser/browser_window.h"
#include "chrome/browser/character_encoding.h"
#include "chrome/browser/debugger/devtools_manager.h"
+#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/find_bar.h"
#include "chrome/browser/find_bar_controller.h"
#include "chrome/browser/location_bar.h"
@@ -176,6 +177,7 @@ Browser::Browser(Type type, Profile* profile)
toolbar_model_(this),
chrome_updater_factory_(this),
is_attempting_to_close_browser_(false),
+ cancel_download_confirmation_state_(NOT_PROMPTED),
maximized_state_(MAXIMIZED_STATE_DEFAULT),
method_factory_(this),
idle_task_(new BrowserIdleTimer) {
@@ -442,9 +444,12 @@ bool Browser::ShouldShowDistributorLogo() const {
// Browser, OnBeforeUnload handling:
bool Browser::ShouldCloseWindow() {
- if (HasCompletedUnloadProcessing()) {
+ if (!CanCloseWithInProgressDownloads())
+ return false;
+
+ if (HasCompletedUnloadProcessing())
return true;
- }
+
is_attempting_to_close_browser_ = true;
for (int i = 0; i < tab_count(); ++i) {
@@ -484,7 +489,27 @@ void Browser::OnWindowClosing() {
CloseAllTabs();
}
-///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// In-progress download termination handling:
+
+void Browser::InProgressDownloadResponse(bool cancel_downloads) {
+ if (cancel_downloads) {
+ cancel_download_confirmation_state_ = RESPONSE_RECEIVED;
+ CloseWindow();
+ return;
+ }
+
+ // Sets the confirmation state to NOT_PROMPTED so that if the user tries to
+ // close again we'll show the warning again.
+ cancel_download_confirmation_state_ = NOT_PROMPTED;
+
+ // Show the download page so the user can figure-out what downloads are still
+ // in-progress.
+ ShowDownloadsTab();
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
// Browser, Tab adding/showing functions:
TabContents* Browser::AddTabWithURL(
@@ -2483,6 +2508,51 @@ void Browser::ClearUnloadState(TabContents* tab) {
///////////////////////////////////////////////////////////////////////////////
+// Browser, In-progress download termination handling (private):
+
+bool Browser::CanCloseWithInProgressDownloads() {
+ if (cancel_download_confirmation_state_ != NOT_PROMPTED) {
+ // This should probably not happen.
+ DCHECK(cancel_download_confirmation_state_ != WAITING_FOR_RESPONSE);
+ return true;
+ }
+
+ // If there are no download in-progress, our job is done.
+ DownloadManager* download_manager = profile_->GetDownloadManager();
+ if (!download_manager || download_manager->in_progress_count() == 0)
+ return true;
+
+ // Let's figure out if we are the last window for our profile.
+ // Note that we cannot just use BrowserList::GetBrowserCount as browser
+ // windows closing is delayed and the returned count might include windows
+ // that are being closed.
+ int count = 0;
+ for (BrowserList::const_iterator iter = BrowserList::begin();
+ iter != BrowserList::end(); ++iter) {
+ // Don't count this browser window or any other in the process of closing.
+ if (*iter == this || (*iter)->is_attempting_to_close_browser_)
+ continue;
+
+ // We test the original profile, because an incognito browser window keeps
+ // the original profile alive (and its DownloadManager).
+ // We also need to test explicitly the profile directly so that 2 incognito
+ // profiles count as a match.
+ if ((*iter)->profile() == profile() ||
+ (*iter)->profile()->GetOriginalProfile() == profile())
+ count++;
+ }
+ if (count > 0)
+ return true;
+
+ cancel_download_confirmation_state_ = WAITING_FOR_RESPONSE;
+ window_->ConfirmBrowserCloseWithPendingDownloads();
+
+ // Return false so the browser does not close. We'll close if the user
+ // confirms in the dialog.
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
// Browser, Assorted utility functions (private):
Browser* Browser::GetOrCreateTabbedBrowser() {
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h
index 63b28d5..9db95d5 100644
--- a/chrome/browser/browser.h
+++ b/chrome/browser/browser.h
@@ -187,6 +187,14 @@ class Browser : public TabStripModelDelegate,
// cleanup.
void OnWindowClosing();
+ // In-progress download termination handling /////////////////////////////////
+
+ // Called when the user has decided whether to proceed or not with the browser
+ // closure. |cancel_downloads| is true if the downloads should be canceled
+ // and the browser closed, false if the browser should stay open and the
+ // downloads running.
+ void InProgressDownloadResponse(bool cancel_downloads);
+
// TabStripModel pass-thrus /////////////////////////////////////////////////
TabStripModel* tabstrip_model() const {
@@ -551,6 +559,13 @@ class Browser : public TabStripModelDelegate,
// successfully fired.
void ClearUnloadState(TabContents* tab);
+ // In-progress download termination handling /////////////////////////////////
+
+ // Called when the window is closing to check if potential in-progress
+ // downloads should prevent it from closing.
+ // Returns true if the window can close, false otherwise.
+ bool CanCloseWithInProgressDownloads();
+
// Assorted utility functions ///////////////////////////////////////////////
// Retrieve the last active tabbed browser with the same profile as the
@@ -667,6 +682,19 @@ class Browser : public TabStripModelDelegate,
// in preparation for closing the browser.
bool is_attempting_to_close_browser_;
+ // In-progress download termination handling /////////////////////////////////
+
+ enum CancelDownloadConfirmationState {
+ NOT_PROMPTED, // We have not asked the user.
+ WAITING_FOR_RESPONSE, // We have asked the user and have not received a
+ // reponse yet.
+ RESPONSE_RECEIVED // The user was prompted and made a decision already.
+ };
+
+ // State used to figure-out whether we should prompt the user for confirmation
+ // when the browser is closed with in-progress downloads.
+ CancelDownloadConfirmationState cancel_download_confirmation_state_;
+
/////////////////////////////////////////////////////////////////////////////
// Override values for the bounds of the window and its maximized state.
diff --git a/chrome/browser/browser_window.h b/chrome/browser/browser_window.h
index 50d3dda..e7e8e4f 100644
--- a/chrome/browser/browser_window.h
+++ b/chrome/browser/browser_window.h
@@ -164,6 +164,12 @@ class BrowserWindow {
// Shows the New Profile dialog box.
virtual void ShowNewProfileDialog() = 0;
+ // Shows the confirmation dialog box warning that the browser is closing with
+ // in-progress downloads.
+ // This method should call Browser::InProgressDownloadResponse once the user
+ // has confirmed.
+ virtual void ConfirmBrowserCloseWithPendingDownloads() = 0;
+
// Shows a dialog box with HTML content, e.g. for Gears. |parent_window| is
// the window the dialog should be opened modal to and is a native window
// handle.
diff --git a/chrome/browser/cocoa/browser_window_cocoa.h b/chrome/browser/cocoa/browser_window_cocoa.h
index c13d779..d673a8d 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/cocoa/browser_window_cocoa.h
@@ -65,6 +65,7 @@ class BrowserWindowCocoa : public BrowserWindow {
virtual void ShowPasswordManager();
virtual void ShowSelectProfileDialog();
virtual void ShowNewProfileDialog();
+ virtual void ConfirmBrowserCloseWithPendingDownloads();
virtual void ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
void* parent_window);
diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm
index 792c2b3..da387cd 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/cocoa/browser_window_cocoa.mm
@@ -194,6 +194,11 @@ void BrowserWindowCocoa::ShowNewProfileDialog() {
NOTIMPLEMENTED();
}
+void BrowserWindowCocoa::ConfirmBrowserCloseWithPendingDownloads() {
+ NOTIMPLEMENTED();
+ browser_->InProgressDownloadResponse(false);
+}
+
void BrowserWindowCocoa::ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
void* parent_window) {
NOTIMPLEMENTED();
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc
index d8417ab..70ed15d 100644
--- a/chrome/browser/gtk/browser_window_gtk.cc
+++ b/chrome/browser/gtk/browser_window_gtk.cc
@@ -486,6 +486,11 @@ void BrowserWindowGtk::ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
NOTIMPLEMENTED();
}
+void BrowserWindowGtk::ConfirmBrowserCloseWithPendingDownloads() {
+ NOTIMPLEMENTED();
+ browser_->InProgressDownloadResponse(false);
+}
+
void BrowserWindowGtk::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h
index 2629fb1..e7d87cf 100644
--- a/chrome/browser/gtk/browser_window_gtk.h
+++ b/chrome/browser/gtk/browser_window_gtk.h
@@ -76,6 +76,7 @@ class BrowserWindowGtk : public BrowserWindow,
virtual void ShowPasswordManager();
virtual void ShowSelectProfileDialog();
virtual void ShowNewProfileDialog();
+ virtual void ConfirmBrowserCloseWithPendingDownloads();
virtual void ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
void* parent_window);
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index b746436..260b891 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
+#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/encoding_menu_controller_delegate.h"
#include "chrome/browser/find_bar_controller.h"
#include "chrome/browser/view_ids.h"
@@ -53,6 +54,7 @@
#include "chrome/common/resource_bundle.h"
#include "chrome/common/win_util.h"
#include "chrome/views/controls/scrollbar/native_scroll_bar.h"
+#include "chrome/views/fill_layout.h"
#include "chrome/views/view.h"
#include "chrome/views/widget/hwnd_notification_source.h"
#include "chrome/views/widget/root_view.h"
@@ -191,6 +193,73 @@ class ResizeCorner : public views::View {
DISALLOW_COPY_AND_ASSIGN(ResizeCorner);
};
+////////////////////////////////////////////////////////////////////////////////
+// DownloadInProgressConfirmDialogDelegate
+
+class DownloadInProgressConfirmDialogDelegate : public views::DialogDelegate,
+ public views::View {
+ public:
+ explicit DownloadInProgressConfirmDialogDelegate(Browser* browser)
+ : browser_(browser) {
+ int download_count = browser->profile()->GetDownloadManager()->
+ in_progress_count();
+ label_ = new views::Label(l10n_util::GetStringF(
+ IDS_DOWNLOAD_REMOVE_CONFIRM_TITLE, download_count));
+ label_->SetMultiLine(true);
+ label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ label_->set_border(views::Border::CreateEmptyBorder(10, 10, 10, 10));
+ AddChildView(label_);
+ SetParentOwned(false);
+ SetLayoutManager(new views::FillLayout());
+ }
+
+ // View implementation:
+ virtual gfx::Size GetPreferredSize() {
+ const int kContentWidth = 400;
+ return gfx::Size(kContentWidth, label_->GetHeightForWidth(kContentWidth));
+ }
+
+ // DialogDelegate implementation:
+ virtual int GetDefaultDialogButton() const {
+ return DIALOGBUTTON_CANCEL;
+ }
+
+ virtual std::wstring GetDialogButtonLabel(DialogButton button) const {
+ if (button == DIALOGBUTTON_OK)
+ return l10n_util::GetString(IDS_DOWNLOAD_REMOVE_CONFIRM_OK_BUTTON_LABEL);
+
+ DCHECK_EQ(DIALOGBUTTON_CANCEL, button);
+ return l10n_util::GetString(
+ IDS_DOWNLOAD_REMOVE_CONFIRM_CANCEL_BUTTON_LABEL);
+ }
+
+ virtual bool Accept() {
+ browser_->InProgressDownloadResponse(true);
+ return true;
+ }
+
+ virtual bool Cancel() {
+ browser_->InProgressDownloadResponse(false);
+ return true;
+ }
+
+ virtual void DeleteDelegate() {
+ delete this;
+ }
+
+ // WindowDelegate implementation:
+ virtual bool IsModal() const { return true; }
+
+ virtual views::View* GetContentsView() {
+ return this;
+ }
+
+ private:
+ Browser* browser_;
+ views::Label* label_;
+
+ DISALLOW_COPY_AND_ASSIGN(DownloadInProgressConfirmDialogDelegate);
+};
///////////////////////////////////////////////////////////////////////////////
// BrowserView, public:
@@ -822,6 +891,13 @@ void BrowserView::ShowNewProfileDialog() {
NewProfileDialog::RunDialog();
}
+void BrowserView::ConfirmBrowserCloseWithPendingDownloads() {
+ DownloadInProgressConfirmDialogDelegate* delegate =
+ new DownloadInProgressConfirmDialogDelegate(browser_.get());
+ views::Window::CreateChromeWindow(GetWidget()->GetNativeView(), gfx::Rect(),
+ delegate)->Show();
+}
+
void BrowserView::ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
void* parent_window) {
HWND parent_hwnd = reinterpret_cast<HWND>(parent_window);
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index f95c0fa..5479cdc 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -205,6 +205,7 @@ class BrowserView : public BrowserWindow,
virtual void ShowPasswordManager();
virtual void ShowSelectProfileDialog();
virtual void ShowNewProfileDialog();
+ virtual void ConfirmBrowserCloseWithPendingDownloads();
virtual void ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
void* parent_window);
diff --git a/chrome/test/test_browser_window.h b/chrome/test/test_browser_window.h
index 2be1bd7..7a8ad17 100644
--- a/chrome/test/test_browser_window.h
+++ b/chrome/test/test_browser_window.h
@@ -59,6 +59,7 @@ class TestBrowserWindow : public BrowserWindow {
virtual void ShowPasswordManager() {}
virtual void ShowSelectProfileDialog() {}
virtual void ShowNewProfileDialog() {}
+ virtual void ConfirmBrowserCloseWithPendingDownloads() {}
virtual void ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
void* parent_window) {}
protected: