diff options
author | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-26 17:00:33 +0000 |
---|---|---|
committer | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-26 17:00:33 +0000 |
commit | 3240d2502106b171635231826c72b0f440fba9c9 (patch) | |
tree | cd4efdddffd712446f042c3b86e77cc4d645ba12 /chrome/browser | |
parent | 1efa8696f8388ca66491c68508f0c75d69d6f1d0 (diff) | |
download | chromium_src-3240d2502106b171635231826c72b0f440fba9c9.zip chromium_src-3240d2502106b171635231826c72b0f440fba9c9.tar.gz chromium_src-3240d2502106b171635231826c72b0f440fba9c9.tar.bz2 |
Keep infobar visible during plug-in installation and show installation state.
Instead of dismissing the infobar when the user accepts it, it's now dismissed when the last missing plug-in placeholder is gone (because we loaded the actual plug-in).
BUG=110701
TEST=none
Review URL: http://codereview.chromium.org/9269007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@119246 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/plugin_installer.cc | 21 | ||||
-rw-r--r-- | chrome/browser/plugin_installer.h | 9 | ||||
-rw-r--r-- | chrome/browser/plugin_installer_infobar_delegate.cc | 70 | ||||
-rw-r--r-- | chrome/browser/plugin_installer_infobar_delegate.h | 34 | ||||
-rw-r--r-- | chrome/browser/plugin_installer_observer.cc | 18 | ||||
-rw-r--r-- | chrome/browser/plugin_installer_observer.h | 16 | ||||
-rw-r--r-- | chrome/browser/plugin_observer.cc | 43 | ||||
-rw-r--r-- | chrome/browser/plugin_observer.h | 9 |
8 files changed, 172 insertions, 48 deletions
diff --git a/chrome/browser/plugin_installer.cc b/chrome/browser/plugin_installer.cc index 0316412..e812282 100644 --- a/chrome/browser/plugin_installer.cc +++ b/chrome/browser/plugin_installer.cc @@ -33,6 +33,19 @@ void PluginInstaller::AddObserver(PluginInstallerObserver* observer) { void PluginInstaller::RemoveObserver(PluginInstallerObserver* observer) { observers_.RemoveObserver(observer); + if (observers_.size() == weak_observers_.size()) { + FOR_EACH_OBSERVER(WeakPluginInstallerObserver, weak_observers_, + OnlyWeakObserversLeft()); + } +} + +void PluginInstaller::AddWeakObserver(WeakPluginInstallerObserver* observer) { + weak_observers_.AddObserver(observer); +} + +void PluginInstaller::RemoveWeakObserver( + WeakPluginInstallerObserver* observer) { + weak_observers_.RemoveObserver(observer); } void PluginInstaller::StartInstalling( @@ -50,6 +63,12 @@ void PluginInstaller::StartInstalling( base::Bind(&PluginInstaller::DownloadError, base::Unretained(this))); } +void PluginInstaller::DidOpenDownloadURL() { + DCHECK(state_ == kStateIdle); + DCHECK(url_for_display_); + FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DidFinishDownload()); +} + void PluginInstaller::DidFinishDownload(const FilePath& downloaded_file) { DCHECK(state_ == kStateDownloading); state_ = kStateIdle; @@ -59,5 +78,7 @@ void PluginInstaller::DidFinishDownload(const FilePath& downloaded_file) { } void PluginInstaller::DownloadError(const std::string& msg) { + DCHECK(state_ == kStateDownloading); + state_ = kStateIdle; FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadError(msg)); } diff --git a/chrome/browser/plugin_installer.h b/chrome/browser/plugin_installer.h index 514d919..6f76967 100644 --- a/chrome/browser/plugin_installer.h +++ b/chrome/browser/plugin_installer.h @@ -12,6 +12,7 @@ class FilePath; class PluginInstallerObserver; +class WeakPluginInstallerObserver; namespace net { class URLRequestContextGetter; @@ -34,6 +35,9 @@ class PluginInstaller { void AddObserver(PluginInstallerObserver* observer); void RemoveObserver(PluginInstallerObserver* observer); + void AddWeakObserver(WeakPluginInstallerObserver* observer); + void RemoveWeakObserver(WeakPluginInstallerObserver* observer); + State state() const { return state_; } // Unique identifier for the plug-in. Should be kept in sync with the @@ -55,12 +59,17 @@ class PluginInstaller { void StartInstalling(net::URLRequestContextGetter* request_context); + // Called when the browser opened the download URL in a new tab, to notify + // observers. + void DidOpenDownloadURL(); + private: void DidFinishDownload(const FilePath& downloaded_file); void DownloadError(const std::string& msg); State state_; ObserverList<PluginInstallerObserver> observers_; + ObserverList<WeakPluginInstallerObserver> weak_observers_; std::string identifier_; GURL plugin_url_; diff --git a/chrome/browser/plugin_installer_infobar_delegate.cc b/chrome/browser/plugin_installer_infobar_delegate.cc index 5945760..4716e40 100644 --- a/chrome/browser/plugin_installer_infobar_delegate.cc +++ b/chrome/browser/plugin_installer_infobar_delegate.cc @@ -4,8 +4,10 @@ #include "chrome/browser/plugin_installer_infobar_delegate.h" +#include "base/utf_string_conversions.h" #include "chrome/browser/google/google_util.h" #include "chrome/browser/infobars/infobar_tab_helper.h" +#include "chrome/browser/plugin_installer.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/public/browser/web_contents.h" #include "grit/generated_resources.h" @@ -18,33 +20,48 @@ using content::OpenURLParams; using content::Referrer; PluginInstallerInfoBarDelegate::PluginInstallerInfoBarDelegate( - PluginInstaller* installer, InfoBarTabHelper* infobar_helper, - const string16& plugin_name, - const GURL& learn_more_url, - const base::Closure& callback) + PluginInstaller* installer, + const base::Closure& callback, + const string16& message) : ConfirmInfoBarDelegate(infobar_helper), - PluginInstallerObserver(installer), - plugin_name_(plugin_name), - learn_more_url_(learn_more_url), - callback_(callback) { + WeakPluginInstallerObserver(installer), + callback_(callback), + message_(message) { } PluginInstallerInfoBarDelegate::~PluginInstallerInfoBarDelegate() { } +InfoBarDelegate* PluginInstallerInfoBarDelegate::Create( + InfoBarTabHelper* infobar_helper, + PluginInstaller* installer, + const base::Closure& callback) { + string16 message; + switch (installer->state()) { + case PluginInstaller::kStateIdle: + message = l10n_util::GetStringFUTF16( + IDS_PLUGININSTALLER_INSTALLPLUGIN_PROMPT, installer->name()); + break; + case PluginInstaller::kStateDownloading: + message = l10n_util::GetStringUTF16(IDS_PLUGIN_DOWNLOADING); + break; + } + return new PluginInstallerInfoBarDelegate( + infobar_helper, installer, callback, message); +} + gfx::Image* PluginInstallerInfoBarDelegate::GetIcon() const { return &ResourceBundle::GetSharedInstance().GetNativeImageNamed( IDR_INFOBAR_PLUGIN_INSTALL); } string16 PluginInstallerInfoBarDelegate::GetMessageText() const { - return l10n_util::GetStringFUTF16(IDS_PLUGININSTALLER_INSTALLPLUGIN_PROMPT, - plugin_name_); + return message_; } int PluginInstallerInfoBarDelegate::GetButtons() const { - return BUTTON_OK; + return callback_.is_null() ? BUTTON_NONE : BUTTON_OK; } string16 PluginInstallerInfoBarDelegate::GetButtonLabel( @@ -55,7 +72,7 @@ string16 PluginInstallerInfoBarDelegate::GetButtonLabel( bool PluginInstallerInfoBarDelegate::Accept() { callback_.Run(); - return true; + return false; } string16 PluginInstallerInfoBarDelegate::GetLinkText() const { @@ -64,7 +81,7 @@ string16 PluginInstallerInfoBarDelegate::GetLinkText() const { bool PluginInstallerInfoBarDelegate::LinkClicked( WindowOpenDisposition disposition) { - GURL url(learn_more_url_); + GURL url(installer()->help_url()); if (url.is_empty()) { url = google_util::AppendGoogleLocaleParam(GURL( "https://www.google.com/support/chrome/bin/answer.py?answer=142064")); @@ -79,6 +96,33 @@ bool PluginInstallerInfoBarDelegate::LinkClicked( } void PluginInstallerInfoBarDelegate::DidStartDownload() { + ReplaceWithInfoBar(l10n_util::GetStringUTF16(IDS_PLUGIN_DOWNLOADING)); +} + +void PluginInstallerInfoBarDelegate::DidFinishDownload() { + ReplaceWithInfoBar(l10n_util::GetStringUTF16(IDS_PLUGIN_INSTALLING)); +} + +void PluginInstallerInfoBarDelegate::DownloadError(const std::string& message) { + ReplaceWithInfoBar( + l10n_util::GetStringUTF16(IDS_PLUGIN_DOWNLOAD_ERROR_SHORT)); +} + +void PluginInstallerInfoBarDelegate::OnlyWeakObserversLeft() { if (owner()) owner()->RemoveInfoBar(this); } + +void PluginInstallerInfoBarDelegate::ReplaceWithInfoBar( + const string16& message) { + // Return early if the message doesn't change. This is important in case the + // PluginInstaller is still iterating over its observers (otherwise we would + // keep replacing infobar delegates infinitely). + if (message_ == message) + return; + if (!owner()) + return; + InfoBarDelegate* delegate = new PluginInstallerInfoBarDelegate( + owner(), installer(), base::Closure(), message); + owner()->ReplaceInfoBar(this, delegate); +} diff --git a/chrome/browser/plugin_installer_infobar_delegate.h b/chrome/browser/plugin_installer_infobar_delegate.h index b43b623..5dad51e 100644 --- a/chrome/browser/plugin_installer_infobar_delegate.h +++ b/chrome/browser/plugin_installer_infobar_delegate.h @@ -9,24 +9,27 @@ #include "base/callback.h" #include "chrome/browser/plugin_installer_observer.h" #include "chrome/browser/tab_contents/confirm_infobar_delegate.h" +#include "chrome/browser/tab_contents/link_infobar_delegate.h" #include "googleurl/src/gurl.h" // The main purpose for this class is to popup/close the infobar when there is // a missing plugin. class PluginInstallerInfoBarDelegate : public ConfirmInfoBarDelegate, - public PluginInstallerObserver { + public WeakPluginInstallerObserver { public: - // Shows an infobar asking whether to install the plugin with the name - // |plugin_name|. When the user accepts, |callback| is called. - // If |installer| is not NULL, registers itself as its observer, to dismiss - // the infobar if it's accepted in another tab. - PluginInstallerInfoBarDelegate(PluginInstaller* installer, - InfoBarTabHelper* infobar_helper, - const string16& plugin_name, - const GURL& learn_more_url, + // Shows an infobar asking whether to install the plugin represented by + // |installer|. When the user accepts, |callback| is called. + // During installation of the plug-in, the infobar will change to reflect the + // installation state. + static InfoBarDelegate* Create(InfoBarTabHelper* infobar_helper, + PluginInstaller* installer, const base::Closure& callback); private: + PluginInstallerInfoBarDelegate(InfoBarTabHelper* infobar_helper, + PluginInstaller* installer, + const base::Closure& callback, + const string16& message); virtual ~PluginInstallerInfoBarDelegate(); // ConfirmInfoBarDelegate: @@ -40,11 +43,20 @@ class PluginInstallerInfoBarDelegate : public ConfirmInfoBarDelegate, // PluginInstallerObserver: virtual void DidStartDownload() OVERRIDE; + virtual void DidFinishDownload() OVERRIDE; + virtual void DownloadError(const std::string& message) OVERRIDE; + + // WeakPluginInstallerObserver: + virtual void OnlyWeakObserversLeft() OVERRIDE; + + // Replaces this infobar with one showing |message|. The new infobar will + // not have any buttons (and not call the callback). + void ReplaceWithInfoBar(const string16& message); - string16 plugin_name_; - GURL learn_more_url_; base::Closure callback_; + string16 message_; + DISALLOW_COPY_AND_ASSIGN(PluginInstallerInfoBarDelegate); }; diff --git a/chrome/browser/plugin_installer_observer.cc b/chrome/browser/plugin_installer_observer.cc index 72284c7..419f60e 100644 --- a/chrome/browser/plugin_installer_observer.cc +++ b/chrome/browser/plugin_installer_observer.cc @@ -8,13 +8,11 @@ PluginInstallerObserver::PluginInstallerObserver(PluginInstaller* installer) : installer_(installer) { - if (installer) - installer->AddObserver(this); + installer->AddObserver(this); } PluginInstallerObserver::~PluginInstallerObserver() { - if (installer_) - installer_->RemoveObserver(this); + installer_->RemoveObserver(this); } void PluginInstallerObserver::DidStartDownload() { @@ -25,3 +23,15 @@ void PluginInstallerObserver::DidFinishDownload() { void PluginInstallerObserver::DownloadError(const std::string& message) { } + +WeakPluginInstallerObserver::WeakPluginInstallerObserver( + PluginInstaller* installer) : PluginInstallerObserver(installer) { + installer->AddWeakObserver(this); +} + +WeakPluginInstallerObserver::~WeakPluginInstallerObserver() { + installer()->RemoveWeakObserver(this); +} + +void WeakPluginInstallerObserver::OnlyWeakObserversLeft() { +} diff --git a/chrome/browser/plugin_installer_observer.h b/chrome/browser/plugin_installer_observer.h index 1d95afd..b9b228a 100644 --- a/chrome/browser/plugin_installer_observer.h +++ b/chrome/browser/plugin_installer_observer.h @@ -16,7 +16,7 @@ class PluginInstallerObserver { virtual ~PluginInstallerObserver(); protected: - PluginInstaller* installer() { return installer_; } + PluginInstaller* installer() const { return installer_; } private: friend class PluginInstaller; @@ -29,4 +29,18 @@ class PluginInstallerObserver { PluginInstaller* installer_; }; +// A WeakPluginInstallerObserver is like a weak pointer to the installer, in the +// sense that if only weak observers are left, we don't need to show +// installation UI anymore. +class WeakPluginInstallerObserver : public PluginInstallerObserver { + public: + explicit WeakPluginInstallerObserver(PluginInstaller* installer); + virtual ~WeakPluginInstallerObserver(); + + private: + friend class PluginInstaller; + + virtual void OnlyWeakObserversLeft(); +}; + #endif // CHROME_BROWSER_PLUGIN_INSTALLER_OBSERVER_H_ diff --git a/chrome/browser/plugin_observer.cc b/chrome/browser/plugin_observer.cc index eb85064..975b369 100644 --- a/chrome/browser/plugin_observer.cc +++ b/chrome/browser/plugin_observer.cc @@ -6,6 +6,7 @@ #include "base/auto_reset.h" #include "base/bind.h" +#include "base/stl_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/content_settings/host_content_settings_map.h" @@ -300,7 +301,7 @@ bool OutdatedPluginInfoBarDelegate::LinkClicked( #if defined(ENABLE_PLUGIN_INSTALLATION) class ConfirmInstallDialogDelegate : public TabModalConfirmDialogDelegate, - public PluginInstallerObserver { + public WeakPluginInstallerObserver { public: ConfirmInstallDialogDelegate(WebContents* web_contents, PluginInstaller* installer); @@ -314,6 +315,7 @@ class ConfirmInstallDialogDelegate : public TabModalConfirmDialogDelegate, // PluginInstallerObserver methods: virtual void DidStartDownload() OVERRIDE; + virtual void OnlyWeakObserversLeft() OVERRIDE; private: net::URLRequestContextGetter* request_context_; @@ -323,7 +325,7 @@ ConfirmInstallDialogDelegate::ConfirmInstallDialogDelegate( WebContents* web_contents, PluginInstaller* installer) : TabModalConfirmDialogDelegate(web_contents), - PluginInstallerObserver(installer), + WeakPluginInstallerObserver(installer), request_context_(web_contents->GetBrowserContext()->GetRequestContext()) { } @@ -352,6 +354,10 @@ void ConfirmInstallDialogDelegate::OnCanceled() { void ConfirmInstallDialogDelegate::DidStartDownload() { Cancel(); } + +void ConfirmInstallDialogDelegate::OnlyWeakObserversLeft() { + Cancel(); +} #endif // defined(ENABLE_PLUGIN_INSTALLATION) } // namespace @@ -371,7 +377,6 @@ class PluginObserver::MissingPluginHost : public PluginInstallerObserver { case PluginInstaller::kStateIdle: { observer->Send(new ChromeViewMsg_FoundMissingPlugin(routing_id_, installer->name())); - observer->ShowPluginInstallationInfoBar(installer); break; } case PluginInstaller::kStateDownloading: { @@ -409,6 +414,7 @@ PluginObserver::PluginObserver(TabContentsWrapper* tab_contents) } PluginObserver::~PluginObserver() { + STLDeleteValues(&missing_plugins_); } bool PluginObserver::OnMessageReceived(const IPC::Message& message) { @@ -418,6 +424,8 @@ bool PluginObserver::OnMessageReceived(const IPC::Message& message) { #if defined(ENABLE_PLUGIN_INSTALLATION) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FindMissingPlugin, OnFindMissingPlugin) + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RemoveMissingPluginHost, + OnRemoveMissingPluginHost) #endif IPC_MESSAGE_HANDLER(ChromeViewHostMsg_OpenAboutPlugins, OnOpenAboutPlugins) @@ -455,19 +463,14 @@ void PluginObserver::OnFindMissingPlugin(int placeholder_id, void PluginObserver::FoundMissingPlugin(int placeholder_id, const std::string& mime_type, PluginInstaller* installer) { - missing_plugins_.push_back( - new MissingPluginHost(this, placeholder_id, installer)); -} - -void PluginObserver::ShowPluginInstallationInfoBar(PluginInstaller* installer) { + missing_plugins_[placeholder_id] = + new MissingPluginHost(this, placeholder_id, installer); InfoBarTabHelper* infobar_helper = tab_contents_->infobar_tab_helper(); - infobar_helper->AddInfoBar(new PluginInstallerInfoBarDelegate( - installer, - infobar_helper, - installer->name(), - installer->help_url(), + InfoBarDelegate* delegate = PluginInstallerInfoBarDelegate::Create( + infobar_helper, installer, base::Bind(&PluginObserver::InstallMissingPlugin, - weak_ptr_factory_.GetWeakPtr(), installer))); + weak_ptr_factory_.GetWeakPtr(), installer)); + infobar_helper->AddInfoBar(delegate); } void PluginObserver::DidNotFindMissingPlugin(int placeholder_id) { @@ -481,12 +484,24 @@ void PluginObserver::InstallMissingPlugin(PluginInstaller* installer) { content::Referrer(web_contents()->GetURL(), WebKit::WebReferrerPolicyDefault), NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_TYPED, false)); + installer->DidOpenDownloadURL(); } else { browser::ShowTabModalConfirmDialog( new ConfirmInstallDialogDelegate(web_contents(), installer), tab_contents_); } } + +void PluginObserver::OnRemoveMissingPluginHost(int placeholder_id) { + std::map<int, MissingPluginHost*>::iterator it = + missing_plugins_.find(placeholder_id); + if (it == missing_plugins_.end()) { + NOTREACHED(); + return; + } + delete it->second; + missing_plugins_.erase(it); +} #endif // defined(ENABLE_PLUGIN_INSTALLATION) void PluginObserver::OnOpenAboutPlugins() { diff --git a/chrome/browser/plugin_observer.h b/chrome/browser/plugin_observer.h index e8b8fdd..58f3e11 100644 --- a/chrome/browser/plugin_observer.h +++ b/chrome/browser/plugin_observer.h @@ -10,7 +10,7 @@ #include "content/public/browser/web_contents_observer.h" #if defined(ENABLE_PLUGIN_INSTALLATION) -#include "base/memory/scoped_vector.h" +#include <map> #endif class GURL; @@ -30,9 +30,6 @@ class PluginObserver : public content::WebContentsObserver { // content::WebContentsObserver implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - // Shows the infobar that offers to install a missing plug-in. - void ShowPluginInstallationInfoBar(PluginInstaller* installer); - private: #if defined(ENABLE_PLUGIN_INSTALLATION) class MissingPluginHost; @@ -49,13 +46,15 @@ class PluginObserver : public content::WebContentsObserver { void InstallMissingPlugin(PluginInstaller* installer); #endif void OnOpenAboutPlugins(); + void OnRemoveMissingPluginHost(int placeholder_id); base::WeakPtrFactory<PluginObserver> weak_ptr_factory_; TabContentsWrapper* tab_contents_; #if defined(ENABLE_PLUGIN_INSTALLATION) - ScopedVector<MissingPluginHost> missing_plugins_; + // Stores all MissingPluginHosts, keyed by their routing ID.ß + std::map<int, MissingPluginHost*> missing_plugins_; #endif DISALLOW_COPY_AND_ASSIGN(PluginObserver); |