diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-25 01:06:05 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-25 01:06:05 +0000 |
commit | f86a07024080cd1b000105bce34ce45b2bd5159b (patch) | |
tree | d47e27fae62581ffb7f4e4209c7dd0106b88763f /chrome | |
parent | 2d42a37132679537eb9e8db9f45a6dfe92dde996 (diff) | |
download | chromium_src-f86a07024080cd1b000105bce34ce45b2bd5159b.zip chromium_src-f86a07024080cd1b000105bce34ce45b2bd5159b.tar.gz chromium_src-f86a07024080cd1b000105bce34ce45b2bd5159b.tar.bz2 |
Re-land 5929 (r5882) with crash fix and also this change:
http://codereview.chromium.org/11392/show
which fixes the remainder of the UI test issues apparently.
http://crbug.com/4620
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5954 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/browser.vcproj | 8 | ||||
-rw-r--r-- | chrome/browser/browser_init.cc | 53 | ||||
-rw-r--r-- | chrome/browser/infobar_delegate.cc | 42 | ||||
-rw-r--r-- | chrome/browser/infobar_delegate.h | 36 | ||||
-rw-r--r-- | chrome/browser/password_manager.cc | 68 | ||||
-rw-r--r-- | chrome/browser/password_manager.h | 43 | ||||
-rw-r--r-- | chrome/browser/plugin_installer.cc | 62 | ||||
-rw-r--r-- | chrome/browser/plugin_installer.h | 35 | ||||
-rw-r--r-- | chrome/browser/session_crashed_view.cc | 39 | ||||
-rw-r--r-- | chrome/browser/session_crashed_view.h | 30 | ||||
-rw-r--r-- | chrome/browser/tab_contents.cc | 10 | ||||
-rw-r--r-- | chrome/browser/tab_contents.h | 4 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view.cc | 1 | ||||
-rw-r--r-- | chrome/browser/views/infobars/infobar_container.cc | 19 | ||||
-rw-r--r-- | chrome/browser/views/infobars/infobars.cc | 111 | ||||
-rw-r--r-- | chrome/browser/views/infobars/infobars.h | 29 | ||||
-rw-r--r-- | chrome/browser/web_contents.cc | 7 | ||||
-rw-r--r-- | chrome/common/notification_types.h | 14 |
18 files changed, 338 insertions, 273 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 447618e..7d79e5d 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -562,14 +562,6 @@ > </File> <File - RelativePath=".\session_crashed_view.cc" - > - </File> - <File - RelativePath=".\session_crashed_view.h" - > - </File> - <File RelativePath=".\session_restore.cc" > </File> diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc index 209ebc3..88bb11c 100644 --- a/chrome/browser/browser_init.cc +++ b/chrome/browser/browser_init.cc @@ -17,14 +17,15 @@ #include "base/win_util.h" #include "chrome/app/locales/locale_settings.h" #include "chrome/app/result_codes.h" +#include "chrome/app/theme/theme_resources.h" #include "chrome/browser/automation/automation_provider.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/dom_ui/new_tab_ui.h" #include "chrome/browser/first_run.h" +#include "chrome/browser/infobar_delegate.h" #include "chrome/browser/navigation_controller.h" #include "chrome/browser/net/dns_global.h" -#include "chrome/browser/session_crashed_view.h" #include "chrome/browser/session_restore.h" #include "chrome/browser/session_startup_pref.h" #include "chrome/browser/tabs/tab_strip_model.h" @@ -38,6 +39,7 @@ #include "chrome/common/logging_chrome.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" +#include "chrome/common/resource_bundle.h" #include "chrome/common/win_util.h" #include "net/base/cookie_monster.h" #include "net/base/net_util.h" @@ -48,6 +50,43 @@ namespace { +// A delegate for the InfoBar shown when the previous session has crashed. The +// bar deletes itself automatically after it is closed. +class SessionCrashedInfoBarDelegate : public ConfirmInfoBarDelegate { + public: + explicit SessionCrashedInfoBarDelegate(TabContents* contents) + : profile_(contents->profile()), + ConfirmInfoBarDelegate(contents) { + } + + // Overridden from ConfirmInfoBarDelegate: + virtual void InfoBarClosed() { + delete this; + } + virtual std::wstring GetMessageText() const { + return l10n_util::GetString(IDS_SESSION_CRASHED_VIEW_MESSAGE); + } + virtual SkBitmap* GetIcon() const { + return ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_INFOBAR_RESTORE_SESSION); + } + virtual int GetButtons() const { return BUTTON_OK; } + virtual std::wstring GetButtonLabel(InfoBarButton button) const { + return l10n_util::GetString(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON); + } + virtual void Accept() { + // Restore the session. + SessionRestore::RestoreSession(profile_, NULL, false, true, false, + std::vector<GURL>()); + } + + private: + // The Profile that we restore sessions from. + Profile* profile_; + + DISALLOW_COPY_AND_ASSIGN(SessionCrashedInfoBarDelegate); +}; + void SetOverrideHomePage(const CommandLine& command_line, PrefService* prefs) { // If homepage is specified on the command line, canonify & store it. if (command_line.HasSwitch(switches::kHomePage)) { @@ -502,15 +541,11 @@ Browser* BrowserInit::LaunchWithProfile::OpenURLsInBrowser( void BrowserInit::LaunchWithProfile::AddCrashedInfoBarIfNecessary( TabContents* tab) { - WebContents* web_contents = tab->AsWebContents(); - if (!profile_->DidLastSessionExitCleanly() && web_contents) { + if (!profile_->DidLastSessionExitCleanly()) { // The last session didn't exit cleanly. Show an infobar to the user - // so that they can restore if they want. - // TODO(brettw) this should be done more cleanly, by adding a message to - // the view and not getting the info bar from inside it directly. - web_contents->view()->GetInfoBarView()-> - AddChildView(new SessionCrashedView(profile_)); - web_contents->view()->SetInfoBarVisible(true); + // so that they can restore if they want. The delegate deletes itself when + // it is closed. + tab->AddInfoBar(new SessionCrashedInfoBarDelegate(tab)); } } diff --git a/chrome/browser/infobar_delegate.cc b/chrome/browser/infobar_delegate.cc index 81965be..c974948c 100644 --- a/chrome/browser/infobar_delegate.cc +++ b/chrome/browser/infobar_delegate.cc @@ -5,11 +5,30 @@ #include "chrome/browser/infobar_delegate.h" #include "base/logging.h" +#include "chrome/browser/navigation_entry.h" +#include "chrome/browser/navigation_controller.h" +#include "chrome/browser/tab_contents.h" #include "chrome/common/l10n_util.h" #include "generated_resources.h" -// AlertInfoBarDelegate, InfoBarDelegate overrides: ---------------------------- +// InfoBarDelegate: ------------------------------------------------------------ + +bool InfoBarDelegate::ShouldExpire( + const NavigationController::LoadCommittedDetails& details) const { + bool is_reload = + PageTransition::StripQualifier(details.entry->transition_type()) == + PageTransition::RELOAD; + return is_reload || (contents_unique_id_ != details.entry->unique_id()); +} + +InfoBarDelegate::InfoBarDelegate(TabContents* contents) { + // Initialize the unique id that we use to expire. + NavigationEntry* active_entry = contents->controller()->GetActiveEntry(); + contents_unique_id_ = active_entry ? active_entry->unique_id() : 0; +} + +// AlertInfoBarDelegate: ------------------------------------------------------- bool AlertInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const { AlertInfoBarDelegate* alert_delegate = delegate->AsAlertInfoBarDelegate(); @@ -19,7 +38,11 @@ bool AlertInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const { return alert_delegate->GetMessageText() == GetMessageText(); } -// ConfirmInfoBarDelegate, public: --------------------------------------------- +AlertInfoBarDelegate::AlertInfoBarDelegate(TabContents* contents) + : InfoBarDelegate(contents) { +} + +// ConfirmInfoBarDelegate: ----------------------------------------------------- std::wstring ConfirmInfoBarDelegate::GetButtonLabel( InfoBarButton button) const { @@ -31,16 +54,21 @@ std::wstring ConfirmInfoBarDelegate::GetButtonLabel( return std::wstring(); } -// SimpleAlertInfoBarDelegate, public: ----------------------------------------- +ConfirmInfoBarDelegate::ConfirmInfoBarDelegate(TabContents* contents) + : AlertInfoBarDelegate(contents) { +} + +// SimpleAlertInfoBarDelegate: ------------------------------------------------- SimpleAlertInfoBarDelegate::SimpleAlertInfoBarDelegate( - const std::wstring& message, SkBitmap* icon) + TabContents* contents, + const std::wstring& message, + SkBitmap* icon) : message_(message), - icon_(icon) { + icon_(icon), + AlertInfoBarDelegate(contents) { } -// SimpleAlertInfoBarDelegate, AlertInfoBarDelegate implementation: ------------ - std::wstring SimpleAlertInfoBarDelegate::GetMessageText() const { return message_; } diff --git a/chrome/browser/infobar_delegate.h b/chrome/browser/infobar_delegate.h index 47f2532..33b750a 100644 --- a/chrome/browser/infobar_delegate.h +++ b/chrome/browser/infobar_delegate.h @@ -8,6 +8,7 @@ #include <string> #include "base/basictypes.h" +#include "chrome/browser/navigation_controller.h" #include "skia/include/SkBitmap.h" class AlertInfoBarDelegate; @@ -32,8 +33,10 @@ class InfoBarDelegate { } // Returns true if the InfoBar should be closed automatically after the page - // is navigated. - virtual bool ShouldCloseOnNavigate() const { return true; } + // is navigated. The default behavior is to return true if the page is + // navigated somewhere else or reloaded. + virtual bool ShouldExpire( + const NavigationController::LoadCommittedDetails& details) const; // Called after the InfoBar is closed. The delegate is free to delete itself // at this point. @@ -52,6 +55,21 @@ class InfoBarDelegate { virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate() { return NULL; } + + protected: + // Constructs the InfoBarDelegate for the specified TabContents' + // NavigationController. + explicit InfoBarDelegate(TabContents* contents); + + private: + // The TabContents this InfoBarDelegate was added to. + TabContents* contents_; + + // The unique id of the active NavigationEntry of the TabContents taht we were + // opened for. Used to help expire on navigations. + int contents_unique_id_; + + DISALLOW_COPY_AND_ASSIGN(InfoBarDelegate); }; // An interface derived from InfoBarDelegate implemented by objects wishing to @@ -69,6 +87,11 @@ class AlertInfoBarDelegate : public InfoBarDelegate { virtual bool EqualsDelegate(InfoBarDelegate* delegate) const; virtual InfoBar* CreateInfoBar(); virtual AlertInfoBarDelegate* AsAlertInfoBarDelegate() { return this; } + + protected: + explicit AlertInfoBarDelegate(TabContents* contents); + + DISALLOW_COPY_AND_ASSIGN(AlertInfoBarDelegate); }; // An interface derived from InfoBarDelegate implemented by objects wishing to @@ -101,13 +124,20 @@ class ConfirmInfoBarDelegate : public AlertInfoBarDelegate { virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate() { return this; } + + protected: + explicit ConfirmInfoBarDelegate(TabContents* contents); + + DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBarDelegate); }; // Simple implementations for common use cases --------------------------------- class SimpleAlertInfoBarDelegate : public AlertInfoBarDelegate { public: - SimpleAlertInfoBarDelegate(const std::wstring& message, SkBitmap* icon); + SimpleAlertInfoBarDelegate(TabContents* contents, + const std::wstring& message, + SkBitmap* icon); // Overridden from AlertInfoBarDelegate: virtual std::wstring GetMessageText() const; diff --git a/chrome/browser/password_manager.cc b/chrome/browser/password_manager.cc index f046773..2bd8cdf 100644 --- a/chrome/browser/password_manager.cc +++ b/chrome/browser/password_manager.cc @@ -25,15 +25,16 @@ void PasswordManager::RegisterUserPrefs(PrefService* prefs) { PasswordManager::PasswordManager(WebContents* web_contents) : web_contents_(web_contents), - current_bar_(NULL), observer_(NULL), - login_managers_deleter_(&pending_login_managers_) { + login_managers_deleter_(&pending_login_managers_), + ConfirmInfoBarDelegate(web_contents) { password_manager_enabled_.Init(prefs::kPasswordManagerEnabled, web_contents->profile()->GetPrefs(), NULL); } PasswordManager::~PasswordManager() { - CloseBars(); + // Remove any InfoBars we may be showing. + web_contents_->RemoveInfoBar(this); } void PasswordManager::ProvisionallySavePassword(PasswordForm form) { @@ -112,8 +113,7 @@ void PasswordManager::DidStopLoading() { return; if (pending_save_manager_->IsNewLogin()) { - // Transfer ownership of the pending_save_manager_ to the PasswordBar. - ReplaceInfoBar(new SavePasswordBar(pending_save_manager_.release(), this)); + web_contents_->AddInfoBar(this); } else { // If the save is not a new username entry, then we just want to save this // data (since the user already has related data saved), so don't prompt. @@ -182,45 +182,41 @@ void PasswordManager::Autofill(const PasswordForm& form_for_autofill, } } -void PasswordManager::CloseBars() { - if (current_bar_) - current_bar_->Close(); +// PasswordManager, ConfirmInfoBarDelegate implementation: --------------------- + +void PasswordManager::InfoBarClosed() { + pending_save_manager_.reset(NULL); +} + +std::wstring PasswordManager::GetMessageText() const { + return l10n_util::GetString(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT); } -void PasswordManager::ReplaceInfoBar(InfoBarItemView* bar) { - // TODO(brettw) The password manager should not have to know about info bars. - CloseBars(); - InfoBarView* view = web_contents_->view()->GetInfoBarView(); - view->AddChildView(bar); - current_bar_ = bar; +SkBitmap* PasswordManager::GetIcon() const { + return ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_INFOBAR_SAVE_PASSWORD); } -PasswordManager::SavePasswordBar - ::SavePasswordBar(PasswordFormManager* form_manager, - PasswordManager* password_manager) - : form_manager_(form_manager), - password_manager_(password_manager), - InfoBarConfirmView( - l10n_util::GetString(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT)) { - SetOKButtonLabel(l10n_util::GetString(IDS_PASSWORD_MANAGER_SAVE_BUTTON)); - SetCancelButtonLabel(l10n_util::GetString( - IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON)); - ResourceBundle &rb = ResourceBundle::GetSharedInstance(); - SetIcon(*rb.GetBitmapNamed(IDR_INFOBAR_SAVE_PASSWORD)); +int PasswordManager::GetButtons() const { + return BUTTON_OK | BUTTON_CANCEL; } -PasswordManager::SavePasswordBar::~SavePasswordBar() { - password_manager_->current_bar_ = NULL; - if (form_manager_) - delete form_manager_; +std::wstring PasswordManager::GetButtonLabel(InfoBarButton button) const { + if (button == BUTTON_OK) + return l10n_util::GetString(IDS_PASSWORD_MANAGER_SAVE_BUTTON); + if (button == BUTTON_CANCEL) + return l10n_util::GetString(IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON); + NOTREACHED(); + return std::wstring(); } -void PasswordManager::SavePasswordBar::OKButtonPressed() { - form_manager_->Save(); - BeginClose(); +void PasswordManager::Accept() { + pending_save_manager_->Save(); + web_contents_->RemoveInfoBar(this); } -void PasswordManager::SavePasswordBar::CancelButtonPressed() { - form_manager_->PermanentlyBlacklist(); - BeginClose(); +void PasswordManager::Cancel() { + pending_save_manager_->PermanentlyBlacklist(); + web_contents_->RemoveInfoBar(this); } + diff --git a/chrome/browser/password_manager.h b/chrome/browser/password_manager.h index ecdac61..584ffff 100644 --- a/chrome/browser/password_manager.h +++ b/chrome/browser/password_manager.h @@ -6,7 +6,7 @@ #define CHROME_BROWSER_PASSWORD_MANAGER_H__ #include "base/scoped_ptr.h" -#include "chrome/browser/views/info_bar_confirm_view.h" +#include "chrome/browser/infobar_delegate.h" #include "chrome/browser/password_form_manager.h" #include "chrome/browser/views/login_view.h" #include "chrome/common/pref_member.h" @@ -21,7 +21,8 @@ class WebContents; // receiving password form data from the renderer and managing the password // database through the WebDataService. The PasswordManager is a LoginModel // for purposes of supporting HTTP authentication dialogs. -class PasswordManager : public views::LoginModel { +class PasswordManager : public views::LoginModel, + public ConfirmInfoBarDelegate { public: static void RegisterUserPrefs(PrefService* prefs); @@ -34,9 +35,6 @@ class PasswordManager : public views::LoginModel { const PasswordFormMap& best_matches, const PasswordForm* const preferred_match) const; - // Closes any visible password manager UI - void CloseBars(); - // Notification that the user navigated away from the current page. // Unless this is a password form submission, for our purposes this // means we're done with the current page, so we can clean-up. @@ -63,32 +61,15 @@ class PasswordManager : public views::LoginModel { } private: - // The Info Bar UI that prompts the user to save a password. - friend class SavePasswordBar; - class SavePasswordBar : public InfoBarConfirmView { - public: - SavePasswordBar(PasswordFormManager* form_manager, - PasswordManager* password_manager); - virtual ~SavePasswordBar(); - - // InfoBarConfirmView overrides. - virtual void OKButtonPressed(); - virtual void CancelButtonPressed(); - - private: - PasswordFormManager* form_manager_; - PasswordManager* password_manager_; - - DISALLOW_EVIL_CONSTRUCTORS(SavePasswordBar); - }; - - // Replace the current InfoBar with a new one. Just adds if there is no - // visible InfoBars. - void ReplaceInfoBar(InfoBarItemView* view); - - // The currently visible InfoBar (NULL if none) - InfoBarItemView* current_bar_; - + // Overridden from ConfirmInfoBarDelegate: + virtual void InfoBarClosed(); + virtual std::wstring GetMessageText() const; + virtual SkBitmap* GetIcon() const; + virtual int GetButtons() const; + virtual std::wstring GetButtonLabel(InfoBarButton button) const; + virtual void Accept(); + virtual void Cancel(); + // When a form is "seen" on a page, a PasswordFormManager is created // and stored in this collection until user navigates away from page. typedef std::vector<PasswordFormManager*> LoginManagers; diff --git a/chrome/browser/plugin_installer.cc b/chrome/browser/plugin_installer.cc index 1d42d80..afd0314 100644 --- a/chrome/browser/plugin_installer.cc +++ b/chrome/browser/plugin_installer.cc @@ -4,9 +4,9 @@ #include "chrome/browser/plugin_installer.h" -#include "chrome/app/theme/theme_resources.h" -#include "chrome/browser/web_contents_view.h" #include "base/string_util.h" +#include "chrome/app/theme/theme_resources.h" +#include "chrome/browser/web_contents.h" #include "chrome/common/l10n_util.h" #include "chrome/common/resource_bundle.h" #include "webkit/default_plugin/default_plugin_shared.h" @@ -15,33 +15,24 @@ PluginInstaller::PluginInstaller(WebContents* web_contents) : web_contents_(web_contents), - current_bar_(NULL) { + ConfirmInfoBarDelegate(web_contents) { } PluginInstaller::~PluginInstaller() { - if (current_bar_) - current_bar_->Close(); + // Remove any InfoBars we may be showing. + web_contents_->RemoveInfoBar(this); } void PluginInstaller::OnMissingPluginStatus(int status) { switch(status) { case default_plugin::MISSING_PLUGIN_AVAILABLE: { - // Display missing plugin InfoBar if a missing plugin is available. - if (current_bar_) - return; - - // TODO(brettw) have a more general way to add to the info bar rather - // than mucking with it directly. - InfoBarView* view = web_contents_->view()->GetInfoBarView(); - current_bar_ = new PluginInstallerBar(this); - view->AddChildView(current_bar_); + web_contents_->AddInfoBar(this); break; } case default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD: { // Hide the InfoBar if user already started download/install of the // missing plugin. - if (current_bar_) - current_bar_->Close(); + web_contents_->RemoveInfoBar(this); break; } default: { @@ -51,38 +42,25 @@ void PluginInstaller::OnMissingPluginStatus(int status) { } } -void PluginInstaller::OnStartLoading() { - if (current_bar_) - current_bar_->BeginClose(); -} - -void PluginInstaller::OnBarDestroy(InfoBarConfirmView* bar) { - if (current_bar_ == bar) - current_bar_ = NULL; +std::wstring PluginInstaller::GetMessageText() const { + return l10n_util::GetString(IDS_PLUGININSTALLER_MISSINGPLUGIN_PROMPT); } -void PluginInstaller::OnOKButtonPressed() { - current_bar_->BeginClose(); - web_contents_->render_view_host()->InstallMissingPlugin(); +SkBitmap* PluginInstaller::GetIcon() const { + return ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_INFOBAR_PLUGIN_INSTALL); } -PluginInstaller::PluginInstallerBar - ::PluginInstallerBar(PluginInstaller* plugin_installer) - : plugin_installer_(plugin_installer), - InfoBarConfirmView( - l10n_util::GetString(IDS_PLUGININSTALLER_MISSINGPLUGIN_PROMPT)) { - SetOKButtonLabel( - l10n_util::GetString(IDS_PLUGININSTALLER_INSTALLPLUGIN_BUTTON)); - RemoveCancelButton(); - ResourceBundle &rb = ResourceBundle::GetSharedInstance(); - SetIcon(*rb.GetBitmapNamed(IDR_INFOBAR_PLUGIN_INSTALL)); +int PluginInstaller::GetButtons() const { + return BUTTON_OK; } -PluginInstaller::PluginInstallerBar::~PluginInstallerBar() { - plugin_installer_->OnBarDestroy(this); +std::wstring PluginInstaller::GetButtonLabel(InfoBarButton button) const { + if (button == BUTTON_OK) + return l10n_util::GetString(IDS_PLUGININSTALLER_INSTALLPLUGIN_BUTTON); + return ConfirmInfoBarDelegate::GetButtonLabel(button); } -void PluginInstaller::PluginInstallerBar::OKButtonPressed() { - plugin_installer_->OnOKButtonPressed(); +void PluginInstaller::Accept() { + web_contents_->render_view_host()->InstallMissingPlugin(); } - diff --git a/chrome/browser/plugin_installer.h b/chrome/browser/plugin_installer.h index e2d21e9..a3b479a 100644 --- a/chrome/browser/plugin_installer.h +++ b/chrome/browser/plugin_installer.h @@ -2,17 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_PLUGIN_INSTALLER_H__ -#define CHROME_BROWSER_PLUGIN_INSTALLER_H__ +#ifndef CHROME_BROWSER_PLUGIN_INSTALLER_H_ +#define CHROME_BROWSER_PLUGIN_INSTALLER_H_ -#include "base/scoped_ptr.h" -#include "chrome/browser/views/info_bar_confirm_view.h" -#include "chrome/browser/web_contents.h" -#include "chrome/browser/webdata/web_data_service.h" +#include "chrome/browser/infobar_delegate.h" + +class WebContents; // The main purpose for this class is to popup/close the infobar when there is // a missing plugin. -class PluginInstaller { +class PluginInstaller : public ConfirmInfoBarDelegate { public: explicit PluginInstaller(WebContents* web_contents); ~PluginInstaller(); @@ -20,26 +19,16 @@ class PluginInstaller { void OnMissingPluginStatus(int status); // A new page starts loading. This is the perfect time to close the info bar. void OnStartLoading(); - void OnBarDestroy(InfoBarConfirmView* bar); - void OnOKButtonPressed(); private: - class PluginInstallerBar : public InfoBarConfirmView { - public: - PluginInstallerBar(PluginInstaller* plugin_installer); - virtual ~PluginInstallerBar(); - - // InfoBarConfirmView overrides. - virtual void OKButtonPressed(); - - private: - PluginInstaller* plugin_installer_; - - DISALLOW_EVIL_CONSTRUCTORS(PluginInstallerBar); - }; + // Overridden from ConfirmInfoBarDelegate: + virtual std::wstring GetMessageText() const; + virtual SkBitmap* GetIcon() const; + virtual int GetButtons() const; + virtual std::wstring GetButtonLabel(InfoBarButton button) const; + virtual void Accept(); // The containing WebContents WebContents* web_contents_; - InfoBarItemView* current_bar_; DISALLOW_EVIL_CONSTRUCTORS(PluginInstaller); }; diff --git a/chrome/browser/session_crashed_view.cc b/chrome/browser/session_crashed_view.cc index 6fa81e3d..e69de29 100644 --- a/chrome/browser/session_crashed_view.cc +++ b/chrome/browser/session_crashed_view.cc @@ -1,39 +0,0 @@ -// Copyright (c) 2006-2008 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/session_crashed_view.h" - -#include "chrome/app/theme/theme_resources.h" -#include "chrome/browser/session_restore.h" -#include "chrome/common/l10n_util.h" -#include "chrome/common/resource_bundle.h" - -#include "chromium_strings.h" -#include "generated_resources.h" - -SessionCrashedView::SessionCrashedView(Profile* profile) - : InfoBarConfirmView( - l10n_util::GetString(IDS_SESSION_CRASHED_VIEW_MESSAGE)), - profile_(profile) { - DCHECK(profile_); - SetOKButtonLabel( - l10n_util::GetString(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON)); - RemoveCancelButton(); - ResourceBundle &rb = ResourceBundle::GetSharedInstance(); - SetIcon(*rb.GetBitmapNamed(IDR_INFOBAR_RESTORE_SESSION)); -} - -SessionCrashedView::~SessionCrashedView() { -} - -void SessionCrashedView::OKButtonPressed() { - // Restore the session. - SessionRestore::RestoreSession(profile_, NULL, false, true, false, - std::vector<GURL>()); - - // Close the info bar. - InfoBarConfirmView::OKButtonPressed(); - // NOTE: OKButtonPressed eventually results in deleting us. -} - diff --git a/chrome/browser/session_crashed_view.h b/chrome/browser/session_crashed_view.h index 3a09e86..e69de29 100644 --- a/chrome/browser/session_crashed_view.h +++ b/chrome/browser/session_crashed_view.h @@ -1,30 +0,0 @@ -// Copyright (c) 2006-2008 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. - -#ifndef CHROME_BROWSER_SESSION_CRASHED_VIEW_H__ -#define CHROME_BROWSER_SESSION_CRASHED_VIEW_H__ - -#include "chrome/browser/views/info_bar_confirm_view.h" - -class Profile; - -// SessionCrashedView is used on startup when the last session didn't exit -// cleanly. The user is given the option of restoring the last session. -class SessionCrashedView : public InfoBarConfirmView { - public: - explicit SessionCrashedView(Profile* profile); - virtual ~SessionCrashedView(); - - virtual void SessionCrashedView::OKButtonPressed(); - - private: - void Init(); - - Profile* profile_; - - DISALLOW_EVIL_CONSTRUCTORS(SessionCrashedView); -}; - -#endif // CHROME_BROWSER_SESSION_CRASHED_VIEW_H__ - diff --git a/chrome/browser/tab_contents.cc b/chrome/browser/tab_contents.cc index 510c611..9bdca3c 100644 --- a/chrome/browser/tab_contents.cc +++ b/chrome/browser/tab_contents.cc @@ -390,7 +390,7 @@ void TabContents::SetInitialFocus() { void TabContents::AddInfoBar(InfoBarDelegate* delegate) { // Look through the existing InfoBarDelegates we have for a match. If we've // already got one that matches, then we don't add the new one. - for (size_t i = 0; i < infobar_delegate_count(); ++i) { + for (int i = 0; i < infobar_delegate_count(); ++i) { if (GetInfoBarDelegateAt(i)->EqualsDelegate(delegate)) return; } @@ -415,10 +415,10 @@ void TabContents::RemoveInfoBar(InfoBarDelegate* delegate) { find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate); if (it != infobar_delegates_.end()) { InfoBarDelegate* delegate = *it; - infobar_delegates_.erase(it); NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_INFOBAR_REMOVED, Source<TabContents>(this), Details<InfoBarDelegate>(delegate)); + infobar_delegates_.erase(it); } // Remove ourselves as an observer if we are tracking no more InfoBars. @@ -590,11 +590,9 @@ void TabContents::ExpireInfoBars( if (!details.is_user_initiated_main_frame_load()) return; - for (size_t i = 0; i < infobar_delegate_count(); ++i) { + for (int i = infobar_delegate_count() - 1; i >= 0; --i) { InfoBarDelegate* delegate = GetInfoBarDelegateAt(i); - if (!TransitionIsReload(details.entry->transition_type()) && - delegate->ShouldCloseOnNavigate()) { + if (delegate->ShouldExpire(details)) RemoveInfoBar(delegate); - } } } diff --git a/chrome/browser/tab_contents.h b/chrome/browser/tab_contents.h index 6893ee1..2f78a79 100644 --- a/chrome/browser/tab_contents.h +++ b/chrome/browser/tab_contents.h @@ -393,8 +393,8 @@ class TabContents : public PageNavigator, void RemoveInfoBar(InfoBarDelegate* delegate); // Enumeration and access functions. - size_t infobar_delegate_count() const { return infobar_delegates_.size(); } - InfoBarDelegate* GetInfoBarDelegateAt(size_t index) { + int infobar_delegate_count() const { return infobar_delegates_.size(); } + InfoBarDelegate* GetInfoBarDelegateAt(int index) { return infobar_delegates_.at(index); } diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index c3b5d07..91b148c 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -636,6 +636,7 @@ void BrowserView::TabDetachedAt(TabContents* contents, int index) { // We need to reset the current tab contents to NULL before it gets // freed. This is because the focus manager performs some operations // on the selected TabContents when it is removed. + infobar_container_->ChangeTabContents(NULL); contents_container_->SetTabContents(NULL); } } diff --git a/chrome/browser/views/infobars/infobar_container.cc b/chrome/browser/views/infobars/infobar_container.cc index 2fe7a35..3a79464 100644 --- a/chrome/browser/views/infobars/infobar_container.cc +++ b/chrome/browser/views/infobars/infobar_container.cc @@ -19,6 +19,10 @@ InfoBarContainer::InfoBarContainer(BrowserView* browser_view) } InfoBarContainer::~InfoBarContainer() { + // We NULL this pointer before resetting the TabContents to prevent view + // hierarchy modifications from attempting to adjust the BrowserView, which is + // in the process of shutting down. + browser_view_ = NULL; ChangeTabContents(NULL); } @@ -31,6 +35,9 @@ void InfoBarContainer::ChangeTabContents(TabContents* contents) { this, NOTIFY_TAB_CONTENTS_INFOBAR_REMOVED, Source<TabContents>(tab_contents_)); } + // No need to delete the child views here, their removal from the view + // hierarchy does this automatically (see InfoBar::InfoBarRemoved). + RemoveAllChildViews(false); tab_contents_ = contents; if (tab_contents_) { UpdateInfoBars(); @@ -44,7 +51,8 @@ void InfoBarContainer::ChangeTabContents(TabContents* contents) { } void InfoBarContainer::InfoBarAnimated(bool completed) { - browser_view_->SelectedTabToolbarSizeChanged(!completed); + if (browser_view_) + browser_view_->SelectedTabToolbarSizeChanged(!completed); } void InfoBarContainer::RemoveDelegate(InfoBarDelegate* delegate) { @@ -76,7 +84,7 @@ void InfoBarContainer::Layout() { void InfoBarContainer::ViewHierarchyChanged(bool is_add, views::View* parent, views::View* child) { - if (parent == this && child->GetParent() == this) { + if (parent == this && child->GetParent() == this && browser_view_) { // An InfoBar child was added or removed. Tell the BrowserView it needs to // re-layout since our preferred size will have changed. browser_view_->SelectedTabToolbarSizeChanged(false); @@ -100,10 +108,7 @@ void InfoBarContainer::Observe(NotificationType type, // InfoBarContainer, private: -------------------------------------------------- void InfoBarContainer::UpdateInfoBars() { - // Clear out all the old child views. - RemoveAllChildViews(true); - - for (size_t i = 0; i < tab_contents_->infobar_delegate_count(); ++i) { + for (int i = 0; i < tab_contents_->infobar_delegate_count(); ++i) { InfoBarDelegate* delegate = tab_contents_->GetInfoBarDelegateAt(i); InfoBar* infobar = delegate->CreateInfoBar(); infobar->set_container(this); @@ -120,7 +125,7 @@ void InfoBarContainer::AddInfoBar(InfoBarDelegate* delegate) { } void InfoBarContainer::RemoveInfoBar(InfoBarDelegate* delegate) { - size_t index = 0; + int index = 0; for (; index < tab_contents_->infobar_delegate_count(); ++index) { if (tab_contents_->GetInfoBarDelegateAt(index) == delegate) break; diff --git a/chrome/browser/views/infobars/infobars.cc b/chrome/browser/views/infobars/infobars.cc index 5733d33..466a74f 100644 --- a/chrome/browser/views/infobars/infobars.cc +++ b/chrome/browser/views/infobars/infobars.cc @@ -11,8 +11,10 @@ #include "chrome/common/slide_animation.h" #include "chrome/views/background.h" #include "chrome/views/button.h" +#include "chrome/views/external_focus_tracker.h" #include "chrome/views/image_view.h" #include "chrome/views/label.h" +#include "chrome/views/widget.h" #include "generated_resources.h" @@ -66,7 +68,11 @@ class InfoBarBackground : public views::Background { InfoBar::InfoBar(InfoBarDelegate* delegate) : delegate_(delegate), - close_button_(new views::Button) { + close_button_(new views::Button), + delete_factory_(this) { + // We delete ourselves when we're removed from the view hierarchy. + SetParentOwned(false); + set_background(new InfoBarBackground); ResourceBundle& rb = ResourceBundle::GetSharedInstance(); @@ -97,14 +103,19 @@ void InfoBar::Open() { } void InfoBar::AnimateClose() { + DestroyFocusTracker(true); animation_->Hide(); } void InfoBar::Close() { GetParent()->RemoveChildView(this); - if (delegate()) - delegate()->InfoBarClosed(); - delete this; + // Note that we only tell the delegate we're closed here, and not when we're + // simply destroyed (by virtue of a tab switch or being moved from window to + // window), since this action can cause the delegate to destroy itself. + if (delegate_) { + delegate_->InfoBarClosed(); + delegate_ = NULL; + } } // InfoBar, views::View overrides: --------------------------------------------- @@ -122,6 +133,17 @@ void InfoBar::Layout() { } +void InfoBar::ViewHierarchyChanged(bool is_add, views::View* parent, + views::View* child) { + if (child == this) { + if (is_add) { + InfoBarAdded(); + } else { + InfoBarRemoved(); + } + } +} + // InfoBar, protected: --------------------------------------------------------- int InfoBar::GetAvailableWidth() const { @@ -138,14 +160,58 @@ void InfoBar::ButtonPressed(views::BaseButton* sender) { // InfoBar, AnimationDelegate implementation: ---------------------------------- void InfoBar::AnimationProgressed(const Animation* animation) { - container_->InfoBarAnimated(true); + if (container_) + container_->InfoBarAnimated(true); } void InfoBar::AnimationEnded(const Animation* animation) { - container_->InfoBarAnimated(false); + if (container_) { + container_->InfoBarAnimated(false); + + if (!animation_->IsShowing()) + Close(); + } +} + +// InfoBar, private: ----------------------------------------------------------- + +void InfoBar::InfoBarAdded() { + // The container_ pointer must be set before adding to the view hierarchy. + DCHECK(container_); + // When we're added to a view hierarchy within a widget, we create an + // external focus tracker to track what was focused in case we obtain + // focus so that we can restore focus when we're removed. + views::Widget* widget = GetWidget(); + if (widget) { + focus_tracker_.reset( + new views::ExternalFocusTracker(this, + views::FocusManager::GetFocusManager(widget->GetHWND()))); + } +} - if (!animation_->IsShowing()) - Close(); +void InfoBar::InfoBarRemoved() { + DestroyFocusTracker(false); + // NULL our container_ pointer so that if Animation::Stop results in + // AnimationEnded being called, we do not try and delete ourselves twice. + container_ = NULL; + animation_->Stop(); + // Finally, clean ourselves up when we're removed from the view hierarchy + // since no-one refers to us now. + MessageLoop::current()->PostTask(FROM_HERE, + delete_factory_.NewRunnableMethod(&InfoBar::DeleteSelf)); +} + +void InfoBar::DestroyFocusTracker(bool restore_focus) { + if (focus_tracker_.get()) { + if (restore_focus) + focus_tracker_->FocusLastFocusedExternalView(); + focus_tracker_->SetFocusManager(NULL); + focus_tracker_.reset(NULL); + } +} + +void InfoBar::DeleteSelf() { + delete this; } // AlertInfoBar, public: ------------------------------------------------------- @@ -199,6 +265,12 @@ ConfirmInfoBar::ConfirmInfoBar(ConfirmInfoBarDelegate* delegate) cancel_button_(NULL), initialized_(false), AlertInfoBar(delegate) { + ok_button_ = new views::NativeButton( + delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK)); + ok_button_->SetListener(this); + cancel_button_ = new views::NativeButton( + delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL)); + cancel_button_->SetListener(this); } ConfirmInfoBar::~ConfirmInfoBar() { @@ -214,10 +286,16 @@ void ConfirmInfoBar::Layout() { gfx::Size ok_ps = ok_button_->GetPreferredSize(); gfx::Size cancel_ps = cancel_button_->GetPreferredSize(); - if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) + if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) { ok_button_width = ok_ps.width(); - if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) - cancel_button_width = cancel_ps.width(); + } else { + ok_button_->SetVisible(false); + } + if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) { + cancel_button_width = cancel_ps.width(); + } else { + cancel_button_->SetVisible(false); + } cancel_button_->SetBounds(available_width - cancel_button_width, OffsetY(this, cancel_ps), cancel_ps.width(), @@ -225,13 +303,13 @@ void ConfirmInfoBar::Layout() { int spacing = cancel_button_width > 0 ? kButtonSpacing : 0; ok_button_->SetBounds(cancel_button_->x() - spacing - ok_button_width, OffsetY(this, ok_ps), ok_ps.width(), ok_ps.height()); - AlertInfoBar::Layout(); } void ConfirmInfoBar::ViewHierarchyChanged(bool is_add, views::View* parent, views::View* child) { + InfoBar::ViewHierarchyChanged(is_add, parent, child); if (is_add && child == this && !initialized_) { Init(); initialized_ = true; @@ -243,8 +321,10 @@ void ConfirmInfoBar::ViewHierarchyChanged(bool is_add, void ConfirmInfoBar::ButtonPressed(views::NativeButton* sender) { if (sender == ok_button_) { GetDelegate()->Accept(); + AnimateClose(); } else if (sender == cancel_button_) { GetDelegate()->Cancel(); + AnimateClose(); } else { NOTREACHED(); } @@ -267,14 +347,7 @@ ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() { } void ConfirmInfoBar::Init() { - ok_button_ = new views::NativeButton( - GetDelegate()->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK)); - ok_button_->SetListener(this); AddChildView(ok_button_); - - cancel_button_ = new views::NativeButton( - GetDelegate()->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL)); - cancel_button_->SetListener(this); AddChildView(cancel_button_); } diff --git a/chrome/browser/views/infobars/infobars.h b/chrome/browser/views/infobars/infobars.h index 1e02f96..f2ccc73 100644 --- a/chrome/browser/views/infobars/infobars.h +++ b/chrome/browser/views/infobars/infobars.h @@ -13,6 +13,7 @@ class InfoBarContainer; class SlideAnimation; namespace views { class Button; +class ExternalFocusTracker; class ImageView; class Label; } @@ -30,6 +31,8 @@ class InfoBar : public views::View, InfoBarDelegate* delegate() const { return delegate_; } + // Set a link to the parent InfoBarContainer. This must be set before the + // InfoBar is added to the view hierarchy. void set_container(InfoBarContainer* container) { container_ = container; } // Starts animating the InfoBar open. @@ -52,6 +55,11 @@ class InfoBar : public views::View, virtual void Layout(); protected: + // Overridden from views::View: + virtual void ViewHierarchyChanged(bool is_add, + views::View* parent, + views::View* child); + // Returns the available width of the View for use by child view layout, // excluding the close button. virtual int GetAvailableWidth() const; @@ -64,6 +72,20 @@ class InfoBar : public views::View, virtual void AnimationProgressed(const Animation* animation); virtual void AnimationEnded(const Animation* animation); + // Called when an InfoBar is added or removed from a view hierarchy to do + // setup and shutdown. + void InfoBarAdded(); + void InfoBarRemoved(); + + // Destroys the external focus tracker, if present. If |restore_focus| is + // true, restores focus to the view tracked by the focus tracker before doing + // so. + void DestroyFocusTracker(bool restore_focus); + + // Deletes this object (called after a return to the message loop to allow + // the stack in ViewHierarchyChanged to unwind). + void DeleteSelf(); + // The InfoBar's container InfoBarContainer* container_; @@ -76,6 +98,13 @@ class InfoBar : public views::View, // The animation that runs when the InfoBar is opened or closed. scoped_ptr<SlideAnimation> animation_; + // Tracks and stores the last focused view which is not the InfoBar or any of + // its children. Used to restore focus once the InfoBar is closed. + scoped_ptr<views::ExternalFocusTracker> focus_tracker_; + + // Used to delete this object after a return to the message loop. + ScopedRunnableMethodFactory<InfoBar> delete_factory_; + DISALLOW_COPY_AND_ASSIGN(InfoBar); }; diff --git a/chrome/browser/web_contents.cc b/chrome/browser/web_contents.cc index 60ba95b4..c3c0a9e 100644 --- a/chrome/browser/web_contents.cc +++ b/chrome/browser/web_contents.cc @@ -855,8 +855,6 @@ void WebContents::RequestMove(const gfx::Rect& new_bounds) { } void WebContents::DidStartLoading(RenderViewHost* rvh, int32 page_id) { - if (plugin_installer_ != NULL) - plugin_installer_->OnStartLoading(); SetIsLoading(true, NULL); } @@ -1339,12 +1337,13 @@ void WebContents::OnCrashedPlugin(const std::wstring& plugin_path) { plugin_name = product_name; } AddInfoBar(new SimpleAlertInfoBarDelegate( - l10n_util::GetStringF(IDS_PLUGIN_CRASHED_PROMPT, plugin_name), NULL)); + this, l10n_util::GetStringF(IDS_PLUGIN_CRASHED_PROMPT, plugin_name), + NULL)); } void WebContents::OnJSOutOfMemory() { AddInfoBar(new SimpleAlertInfoBarDelegate( - l10n_util::GetString(IDS_JS_OUT_OF_MEMORY_PROMPT), NULL)); + this, l10n_util::GetString(IDS_JS_OUT_OF_MEMORY_PROMPT), NULL)); } bool WebContents::CanBlur() const { diff --git a/chrome/common/notification_types.h b/chrome/common/notification_types.h index c748d36..d6ca458 100644 --- a/chrome/common/notification_types.h +++ b/chrome/common/notification_types.h @@ -200,18 +200,18 @@ enum NotificationType { // No details are expected. NOTIFY_WEB_CONTENTS_DISCONNECTED, - // This message is sent when a new InfoBar is added to a TabContents. The - // source is a Source<TabContents> with a pointer to the TabContents the + // This message is sent when a new InfoBar has been added to a TabContents. + // The source is a Source<TabContents> with a pointer to the TabContents the // InfoBar was added to. The details is a Details<InfoBarDelegate> with a // pointer to an object implementing the InfoBarDelegate interface for the // InfoBar that was added. NOTIFY_TAB_CONTENTS_INFOBAR_ADDED, - // This message is sent when an InfoBar is removed from a TabContents. The - // source is a Source<TabContents> with a pointer to the TabContents the - // InfoBar was removed from. The details is a Details<InfoBarDelegate> with a - // pointer to an object implementing the InfoBarDelegate interface for the - // InfoBar that was removed. + // This message is sent when an InfoBar is about to be removed from a + // TabContents. The source is a Source<TabContents> with a pointer to the + // TabContents the InfoBar was removed from. The details is a + // Details<InfoBarDelegate> with a pointer to an object implementing the + // InfoBarDelegate interface for the InfoBar that was removed. NOTIFY_TAB_CONTENTS_INFOBAR_REMOVED, // This is sent when an externally hosted tab is created. The details contain |