PluginFinder returns copies of PluginMetadata and PluginInstaller no more aggregate PluginMetadata


BUG=124396


Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=159068

Reverted: https://codereview.chromium.org/10981069

Review URL: https://chromiumcodereview.appspot.com/10958071

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159691 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_api.cc b/chrome/browser/extensions/api/content_settings/content_settings_api.cc
index 5c6e02f4..ce001ca 100644
--- a/chrome/browser/extensions/api/content_settings/content_settings_api.cc
+++ b/chrome/browser/extensions/api/content_settings/content_settings_api.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/values.h"
 #include "chrome/browser/content_settings/cookie_settings.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
@@ -273,7 +274,7 @@
   ListValue* list = new ListValue();
   for (std::vector<webkit::WebPluginInfo>::const_iterator it = plugins.begin();
        it != plugins.end(); ++it) {
-    PluginMetadata* plugin_metadata = finder->GetPluginMetadata(*it);
+    scoped_ptr<PluginMetadata> plugin_metadata(finder->GetPluginMetadata(*it));
     const std::string& group_identifier = plugin_metadata->identifier();
     if (group_identifiers.find(group_identifier) != group_identifiers.end())
       continue;
diff --git a/chrome/browser/pepper_broker_observer.cc b/chrome/browser/pepper_broker_observer.cc
index caffb57e..c78bf09 100644
--- a/chrome/browser/pepper_broker_observer.cc
+++ b/chrome/browser/pepper_broker_observer.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/pepper_broker_observer.h"
 
+#include "base/memory/scoped_ptr.h"
 #include "chrome/browser/api/infobars/confirm_infobar_delegate.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
 #include "chrome/browser/infobars/infobar_tab_helper.h"
@@ -101,8 +102,8 @@
   webkit::WebPluginInfo plugin;
   bool success = plugin_service->GetPluginInfoByPath(plugin_path_, &plugin);
   DCHECK(success);
-  PluginMetadata* plugin_metadata =
-      PluginFinder::GetInstance()->GetPluginMetadata(plugin);
+  scoped_ptr<PluginMetadata> plugin_metadata(
+      PluginFinder::GetInstance()->GetPluginMetadata(plugin));
   return l10n_util::GetStringFUTF16(IDS_PEPPER_BROKER_MESSAGE,
                                     plugin_metadata->name(),
                                     net::FormatUrl(url_.GetOrigin(),
diff --git a/chrome/browser/plugins/plugin_finder.cc b/chrome/browser/plugins/plugin_finder.cc
index be73b16db..aded8b6 100644
--- a/chrome/browser/plugins/plugin_finder.cc
+++ b/chrome/browser/plugins/plugin_finder.cc
@@ -84,7 +84,7 @@
       identifier_plugin_[identifier] = metadata;
 
 #if defined(ENABLE_PLUGIN_INSTALLATION)
-      installers_[identifier] = new PluginInstaller(metadata);
+      installers_[identifier] = new PluginInstaller();
 #endif
     }
   }
@@ -122,10 +122,13 @@
 }
 
 #if defined(ENABLE_PLUGIN_INSTALLATION)
-PluginInstaller* PluginFinder::FindPlugin(const std::string& mime_type,
-                                          const std::string& language) {
+bool PluginFinder::FindPlugin(
+    const std::string& mime_type,
+    const std::string& language,
+    PluginInstaller** installer,
+    scoped_ptr<PluginMetadata>* plugin_metadata) {
   if (g_browser_process->local_state()->GetBoolean(prefs::kDisablePluginFinder))
-    return NULL;
+    return false;
   for (DictionaryValue::Iterator plugin_it(*plugin_list_);
        plugin_it.HasNext(); plugin_it.Advance()) {
     const DictionaryValue* plugin = NULL;
@@ -149,26 +152,40 @@
         std::string identifier = plugin_it.key();
         {
           base::AutoLock lock(mutex_);
-          std::map<std::string, PluginInstaller*>::const_iterator installer =
+          std::map<std::string, PluginMetadata*>::const_iterator metadata_it =
+              identifier_plugin_.find(identifier);
+          DCHECK(metadata_it != identifier_plugin_.end());
+          *plugin_metadata = metadata_it->second->Clone();
+
+          std::map<std::string, PluginInstaller*>::const_iterator installer_it =
               installers_.find(identifier);
-          DCHECK(installer != installers_.end());
-          return installer->second;
+          DCHECK(installer_it != installers_.end());
+          *installer = installer_it->second;
+          return true;
         }
       }
     }
   }
-  return NULL;
+  return false;
 }
 
-PluginInstaller* PluginFinder::FindPluginWithIdentifier(
-    const std::string& identifier) {
+bool PluginFinder::FindPluginWithIdentifier(
+    const std::string& identifier,
+    PluginInstaller** installer,
+    scoped_ptr<PluginMetadata>* plugin_metadata) {
   base::AutoLock lock(mutex_);
   std::map<std::string, PluginInstaller*>::const_iterator it =
       installers_.find(identifier);
-  if (it != installers_.end())
-    return it->second;
+  if (it != installers_.end()) {
+    *installer = it->second;
+    std::map<std::string, PluginMetadata*>::const_iterator metadata_it =
+        identifier_plugin_.find(identifier);
+    DCHECK(metadata_it != identifier_plugin_.end());
+    *plugin_metadata = metadata_it->second->Clone();
+    return true;
+  }
 
-  return NULL;
+  return false;
 }
 #endif
 
@@ -233,11 +250,11 @@
   return plugin;
 }
 
-PluginMetadata* PluginFinder::GetPluginMetadata(
+scoped_ptr<PluginMetadata> PluginFinder::GetPluginMetadata(
     const webkit::WebPluginInfo& plugin) {
   base::AutoLock lock(mutex_);
   if (name_plugin_.find(plugin.name) != name_plugin_.end())
-    return name_plugin_[plugin.name];
+    return name_plugin_[plugin.name]->Clone();
 
   // Use the group name matcher to find the plug-in metadata we want.
   for (std::map<std::string, PluginMetadata*>::const_iterator it =
@@ -246,7 +263,7 @@
       continue;
 
     name_plugin_[plugin.name] = it->second;
-    return it->second;
+    return it->second->Clone();
   }
 
   // The plug-in metadata was not found, create a dummy one holding
@@ -259,5 +276,5 @@
 
   name_plugin_[plugin.name] = metadata;
   identifier_plugin_[identifier] = metadata;
-  return metadata;
+  return metadata->Clone();
 }
diff --git a/chrome/browser/plugins/plugin_finder.h b/chrome/browser/plugins/plugin_finder.h
index b681e50..dacecb4 100644
--- a/chrome/browser/plugins/plugin_finder.h
+++ b/chrome/browser/plugins/plugin_finder.h
@@ -39,20 +39,28 @@
 
 #if defined(ENABLE_PLUGIN_INSTALLATION)
   // Finds a plug-in for the given MIME type and language (specified as an IETF
-  // language tag, i.e. en-US) and returns the PluginInstaller for the plug-in,
-  // or NULL if no plug-in is found.
-  PluginInstaller* FindPlugin(const std::string& mime_type,
-                              const std::string& language);
+  // language tag, i.e. en-US). If found, sets |installer| to the
+  // corresponding PluginInstaller and |plugin_metadata| to a copy of the
+  // corresponding PluginMetadata.
+  bool FindPlugin(const std::string& mime_type,
+                  const std::string& language,
+                  PluginInstaller** installer,
+                  scoped_ptr<PluginMetadata>* plugin_metadata);
 
-  // Returns the plug-in with the given identifier.
-  PluginInstaller* FindPluginWithIdentifier(const std::string& identifier);
+  // Finds the plug-in with the given identifier. If found, sets |installer|
+  // to the corresponding PluginInstaller and |plugin_metadata| to a copy
+  // of the corresponding PluginMetadata.
+  bool FindPluginWithIdentifier(const std::string& identifier,
+                                PluginInstaller** installer,
+                                scoped_ptr<PluginMetadata>* plugin_metadata);
 #endif
 
   // Returns the plug-in name with the given identifier.
   string16 FindPluginNameWithIdentifier(const std::string& identifier);
 
   // Gets plug-in metadata using |plugin|.
-  PluginMetadata* GetPluginMetadata(const webkit::WebPluginInfo& plugin);
+  scoped_ptr<PluginMetadata> GetPluginMetadata(
+      const webkit::WebPluginInfo& plugin);
 
  private:
   friend struct DefaultSingletonTraits<PluginFinder>;
diff --git a/chrome/browser/plugins/plugin_infobar_delegates.cc b/chrome/browser/plugins/plugin_infobar_delegates.cc
index 0d5e7fd..78607fc 100644
--- a/chrome/browser/plugins/plugin_infobar_delegates.cc
+++ b/chrome/browser/plugins/plugin_infobar_delegates.cc
@@ -155,35 +155,38 @@
 
 InfoBarDelegate* OutdatedPluginInfoBarDelegate::Create(
     content::WebContents* web_contents,
-    PluginInstaller* installer) {
+    PluginInstaller* installer,
+    scoped_ptr<PluginMetadata> plugin_metadata) {
   string16 message;
   switch (installer->state()) {
     case PluginInstaller::INSTALLER_STATE_IDLE:
       message = l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED_PROMPT,
-                                           installer->name());
+                                           plugin_metadata->name());
       break;
     case PluginInstaller::INSTALLER_STATE_DOWNLOADING:
       message = l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
-                                           installer->name());
+                                           plugin_metadata->name());
       break;
   }
   return new OutdatedPluginInfoBarDelegate(
-      web_contents, installer, message);
+      web_contents, installer, plugin_metadata.Pass(), message);
 }
 
 OutdatedPluginInfoBarDelegate::OutdatedPluginInfoBarDelegate(
     content::WebContents* web_contents,
     PluginInstaller* installer,
+    scoped_ptr<PluginMetadata> plugin_metadata,
     const string16& message)
     : PluginInfoBarDelegate(
           InfoBarService::FromTabContents(
               TabContents::FromWebContents(web_contents)),
-          installer->name(),
-          installer->identifier()),
+          plugin_metadata->name(),
+          plugin_metadata->identifier()),
       WeakPluginInstallerObserver(installer),
+      plugin_metadata_(plugin_metadata.Pass()),
       message_(message) {
   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Shown"));
-  std::string name = UTF16ToUTF8(installer->name());
+  std::string name = UTF16ToUTF8(plugin_metadata_->name());
   if (name == PluginMetadata::kJavaGroupName)
     content::RecordAction(
         UserMetricsAction("OutdatedPluginInfobar.Shown.Java"));
@@ -230,10 +233,14 @@
   }
 
   content::WebContents* web_contents = owner()->GetWebContents();
-  if (installer()->url_for_display()) {
-    installer()->OpenDownloadURL(web_contents);
+  if (plugin_metadata_->url_for_display()) {
+    installer()->OpenDownloadURL(plugin_metadata_->url_for_display(),
+                                 plugin_metadata_->plugin_url(),
+                                 web_contents);
   } else {
     installer()->StartInstalling(
+        plugin_metadata_->url_for_display(),
+        plugin_metadata_->plugin_url(),
         TabContents::FromWebContents(web_contents));
   }
   return false;
@@ -260,23 +267,23 @@
 
 void OutdatedPluginInfoBarDelegate::DownloadStarted() {
   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
-                                                installer()->name()));
+                                                plugin_metadata_->name()));
 }
 
 void OutdatedPluginInfoBarDelegate::DownloadError(const std::string& message) {
   ReplaceWithInfoBar(
       l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR_SHORT,
-                                 installer()->name()));
+                                 plugin_metadata_->name()));
 }
 
 void OutdatedPluginInfoBarDelegate::DownloadCancelled() {
   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED,
-                                                installer()->name()));
+                                                plugin_metadata_->name()));
 }
 
 void OutdatedPluginInfoBarDelegate::DownloadFinished() {
   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_UPDATING,
-                                                installer()->name()));
+                                                plugin_metadata_->name()));
 }
 
 void OutdatedPluginInfoBarDelegate::OnlyWeakObserversLeft() {
@@ -294,7 +301,8 @@
   if (!owner())
     return;
   InfoBarDelegate* delegate = new PluginInstallerInfoBarDelegate(
-      owner(), installer(), base::Closure(), false, message);
+      owner(), installer(), plugin_metadata_->Clone(),
+      base::Closure(), false, message);
   owner()->ReplaceInfoBar(this, delegate);
 }
 
@@ -303,11 +311,13 @@
 PluginInstallerInfoBarDelegate::PluginInstallerInfoBarDelegate(
     InfoBarService* infobar_service,
     PluginInstaller* installer,
+    scoped_ptr<PluginMetadata> plugin_metadata,
     const base::Closure& callback,
     bool new_install,
     const string16& message)
     : ConfirmInfoBarDelegate(infobar_service),
       WeakPluginInstallerObserver(installer),
+      plugin_metadata_(plugin_metadata.Pass()),
       callback_(callback),
       new_install_(new_install),
       message_(message) {
@@ -319,20 +329,22 @@
 InfoBarDelegate* PluginInstallerInfoBarDelegate::Create(
     InfoBarService* infobar_service,
     PluginInstaller* installer,
+    scoped_ptr<PluginMetadata> plugin_metadata,
     const base::Closure& callback) {
   string16 message;
-  const string16& plugin_name = installer->name();
   switch (installer->state()) {
     case PluginInstaller::INSTALLER_STATE_IDLE:
       message = l10n_util::GetStringFUTF16(
-          IDS_PLUGININSTALLER_INSTALLPLUGIN_PROMPT, plugin_name);
+          IDS_PLUGININSTALLER_INSTALLPLUGIN_PROMPT, plugin_metadata->name());
       break;
     case PluginInstaller::INSTALLER_STATE_DOWNLOADING:
-      message = l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING, plugin_name);
+      message = l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
+                                           plugin_metadata->name());
       break;
   }
   return new PluginInstallerInfoBarDelegate(
-      infobar_service, installer, callback, true, message);
+      infobar_service, installer, plugin_metadata.Pass(),
+      callback, true, message);
 }
 
 gfx::Image* PluginInstallerInfoBarDelegate::GetIcon() const {
@@ -367,7 +379,7 @@
 
 bool PluginInstallerInfoBarDelegate::LinkClicked(
     WindowOpenDisposition disposition) {
-  GURL url(installer()->help_url());
+  GURL url(plugin_metadata_->help_url());
   if (url.is_empty()) {
     url = google_util::AppendGoogleLocaleParam(GURL(
       "https://www.google.com/support/chrome/bin/answer.py?answer=142064"));
@@ -383,24 +395,24 @@
 
 void PluginInstallerInfoBarDelegate::DownloadStarted() {
   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
-                                                installer()->name()));
+                                                plugin_metadata_->name()));
 }
 
 void PluginInstallerInfoBarDelegate::DownloadCancelled() {
   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED,
-                                                installer()->name()));
+                                                plugin_metadata_->name()));
 }
 
 void PluginInstallerInfoBarDelegate::DownloadError(const std::string& message) {
   ReplaceWithInfoBar(
       l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR_SHORT,
-                                 installer()->name()));
+                                 plugin_metadata_->name()));
 }
 
 void PluginInstallerInfoBarDelegate::DownloadFinished() {
   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(
       new_install_ ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING,
-      installer()->name()));
+          plugin_metadata_->name()));
 }
 
 void PluginInstallerInfoBarDelegate::OnlyWeakObserversLeft() {
@@ -418,7 +430,8 @@
   if (!owner())
     return;
   InfoBarDelegate* delegate = new PluginInstallerInfoBarDelegate(
-      owner(), installer(), base::Closure(), new_install_, message);
+      owner(), installer(), plugin_metadata_->Clone(),
+      base::Closure(), new_install_, message);
   owner()->ReplaceInfoBar(this, delegate);
 }
 
diff --git a/chrome/browser/plugins/plugin_infobar_delegates.h b/chrome/browser/plugins/plugin_infobar_delegates.h
index 08937d7..85fa159 100644
--- a/chrome/browser/plugins/plugin_infobar_delegates.h
+++ b/chrome/browser/plugins/plugin_infobar_delegates.h
@@ -15,6 +15,7 @@
 
 class InfoBarService;
 class HostContentSettingsMap;
+class PluginMetadata;
 
 namespace content {
 class WebContents;
@@ -80,11 +81,13 @@
                                       public WeakPluginInstallerObserver {
  public:
   static InfoBarDelegate* Create(content::WebContents* web_contents,
-                                 PluginInstaller* installer);
+                                 PluginInstaller* installer,
+                                 scoped_ptr<PluginMetadata> metadata);
 
  private:
   OutdatedPluginInfoBarDelegate(content::WebContents* web_contents,
                                 PluginInstaller* installer,
+                                scoped_ptr<PluginMetadata> metadata,
                                 const string16& message);
   virtual ~OutdatedPluginInfoBarDelegate();
 
@@ -110,6 +113,8 @@
   // not have any buttons (and not call the callback).
   void ReplaceWithInfoBar(const string16& message);
 
+  scoped_ptr<PluginMetadata> plugin_metadata_;
+
   string16 message_;
 
   DISALLOW_COPY_AND_ASSIGN(OutdatedPluginInfoBarDelegate);
@@ -126,6 +131,7 @@
   // installation state.
   static InfoBarDelegate* Create(InfoBarService* infobar_service,
                                  PluginInstaller* installer,
+                                 scoped_ptr<PluginMetadata> plugin_metadata,
                                  const base::Closure& callback);
 
  private:
@@ -133,6 +139,7 @@
 
   PluginInstallerInfoBarDelegate(InfoBarService* infobar_service,
                                  PluginInstaller* installer,
+                                 scoped_ptr<PluginMetadata> plugin_metadata,
                                  const base::Closure& callback,
                                  bool new_install,
                                  const string16& message);
@@ -160,6 +167,8 @@
   // not have any buttons (and not call the callback).
   void ReplaceWithInfoBar(const string16& message);
 
+  scoped_ptr<PluginMetadata> plugin_metadata_;
+
   base::Closure callback_;
 
   // True iff the plug-in isn't installed yet.
diff --git a/chrome/browser/plugins/plugin_installer.cc b/chrome/browser/plugins/plugin_installer.cc
index 2c5a582..678addd 100644
--- a/chrome/browser/plugins/plugin_installer.cc
+++ b/chrome/browser/plugins/plugin_installer.cc
@@ -66,10 +66,8 @@
 
 }  // namespace
 
-PluginInstaller::PluginInstaller(PluginMetadata* plugin)
-    : plugin_(plugin),
-      state_(INSTALLER_STATE_IDLE) {
-  DCHECK(plugin_);
+PluginInstaller::PluginInstaller()
+    : state_(INSTALLER_STATE_IDLE) {
 }
 
 PluginInstaller::~PluginInstaller() {
@@ -131,9 +129,11 @@
   weak_observers_.RemoveObserver(observer);
 }
 
-void PluginInstaller::StartInstalling(TabContents* tab_contents) {
+void PluginInstaller::StartInstalling(bool url_for_display,
+                                      const GURL& plugin_url,
+                                      TabContents* tab_contents) {
   DCHECK_EQ(INSTALLER_STATE_IDLE, state_);
-  DCHECK(!plugin_->url_for_display());
+  DCHECK(url_for_display);
   state_ = INSTALLER_STATE_DOWNLOADING;
   FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadStarted());
   content::WebContents* web_contents = tab_contents->web_contents();
@@ -144,7 +144,7 @@
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::Bind(&BeginDownload,
-                 plugin_->plugin_url(),
+                 plugin_url,
                  tab_contents->profile()->GetResourceContext(),
                  web_contents->GetRenderProcessHost()->GetID(),
                  web_contents->GetRenderViewHost()->GetRoutingID(),
@@ -174,11 +174,13 @@
   download_item->AddObserver(this);
 }
 
-void PluginInstaller::OpenDownloadURL(content::WebContents* web_contents) {
+void PluginInstaller::OpenDownloadURL(bool url_for_display,
+                                      const GURL& plugin_url,
+                                      content::WebContents* web_contents) {
   DCHECK_EQ(INSTALLER_STATE_IDLE, state_);
-  DCHECK(plugin_->url_for_display());
+  DCHECK(url_for_display);
   web_contents->OpenURL(content::OpenURLParams(
-      plugin_->plugin_url(),
+      plugin_url,
       content::Referrer(web_contents->GetURL(),
                         WebKit::WebReferrerPolicyDefault),
       NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_TYPED, false));
diff --git a/chrome/browser/plugins/plugin_installer.h b/chrome/browser/plugins/plugin_installer.h
index 322ef06..8dca3fd7 100644
--- a/chrome/browser/plugins/plugin_installer.h
+++ b/chrome/browser/plugins/plugin_installer.h
@@ -34,7 +34,7 @@
     INSTALLER_STATE_DOWNLOADING,
   };
 
-  explicit PluginInstaller(PluginMetadata* plugin);
+  PluginInstaller();
   virtual ~PluginInstaller();
 
   virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE;
@@ -46,32 +46,20 @@
   void AddWeakObserver(WeakPluginInstallerObserver* observer);
   void RemoveWeakObserver(WeakPluginInstallerObserver* observer);
 
-  // Unique identifier for the plug-in.
-  const std::string& identifier() const { return plugin_->identifier(); }
-
-  // Human-readable name of the plug-in.
-  const string16& name() const { return plugin_->name(); }
-
-  // If |url_for_display| is false, |plugin_url| is the URL of the download page
-  // for the plug-in, which should be opened in a new tab. If it is true,
-  // |plugin_url| is the URL of the plug-in installer binary, which can be
-  // directly downloaded.
-  bool url_for_display() const { return plugin_->url_for_display(); }
-  const GURL& plugin_url() const { return plugin_->plugin_url(); }
-
-  // URL to open when the user clicks on the "Problems installing?" link.
-  const GURL& help_url() const { return plugin_->help_url(); }
-
   InstallerState state() const { return state_; }
 
   // Opens the download URL in a new tab. This method should only be called if
   // |url_for_display| returns true.
-  void OpenDownloadURL(content::WebContents* web_contents);
+  void OpenDownloadURL(bool url_for_display,
+                       const GURL& plugin_url,
+                       content::WebContents* web_contents);
 
   // Starts downloading the download URL and opens the downloaded file
   // when finished. This method should only be called if |url_for_display|
   // returns false.
-  void StartInstalling(TabContents* tab_contents);
+  void StartInstalling(bool url_for_display,
+                       const GURL& plugin_url,
+                       TabContents* tab_contents);
 
  private:
   void DownloadStarted(scoped_refptr<content::DownloadManager> dlm,
@@ -80,9 +68,6 @@
   void DownloadError(const std::string& msg);
   void DownloadCancelled();
 
-  // Can't be NULL. It is owned by PluginFinder.
-  PluginMetadata* plugin_;
-
   InstallerState state_;
   ObserverList<PluginInstallerObserver> observers_;
   ObserverList<WeakPluginInstallerObserver> weak_observers_;
diff --git a/chrome/browser/plugins/plugin_metadata.cc b/chrome/browser/plugins/plugin_metadata.cc
index 3062f6fb..5013c7f1 100644
--- a/chrome/browser/plugins/plugin_metadata.cc
+++ b/chrome/browser/plugins/plugin_metadata.cc
@@ -93,3 +93,14 @@
   // Keep versions ordered by newest (biggest) first.
   return lhs.CompareTo(rhs) > 0;
 }
+
+scoped_ptr<PluginMetadata> PluginMetadata::Clone() const {
+  PluginMetadata* copy = new PluginMetadata(identifier_,
+                                            name_,
+                                            url_for_display_,
+                                            plugin_url_,
+                                            help_url_,
+                                            group_name_matcher_);
+  copy->versions_ = versions_;
+  return make_scoped_ptr(copy);
+}
diff --git a/chrome/browser/plugins/plugin_metadata.h b/chrome/browser/plugins/plugin_metadata.h
index 0f63ac4..b8ca5e0 100644
--- a/chrome/browser/plugins/plugin_metadata.h
+++ b/chrome/browser/plugins/plugin_metadata.h
@@ -7,6 +7,7 @@
 
 #include <map>
 
+#include "base/memory/scoped_ptr.h"
 #include "base/string16.h"
 #include "base/version.h"
 #include "googleurl/src/gurl.h"
@@ -73,6 +74,8 @@
   // considered out-of-date, etc.)
   SecurityStatus GetSecurityStatus(const webkit::WebPluginInfo& plugin) const;
 
+  scoped_ptr<PluginMetadata> Clone() const;
+
  private:
   struct VersionComparator {
     bool operator() (const Version& lhs, const Version& rhs) const;
@@ -85,6 +88,8 @@
   GURL plugin_url_;
   GURL help_url_;
   std::map<Version, SecurityStatus, VersionComparator> versions_;
+
+  DISALLOW_COPY_AND_ASSIGN(PluginMetadata);
 };
 
 #endif  // CHROME_BROWSER_PLUGINS_PLUGIN_METADATA_H_
diff --git a/chrome/browser/plugins/plugin_observer.cc b/chrome/browser/plugins/plugin_observer.cc
index c0b3948..28637c2 100644
--- a/chrome/browser/plugins/plugin_observer.cc
+++ b/chrome/browser/plugins/plugin_observer.cc
@@ -58,7 +58,8 @@
                                      public WeakPluginInstallerObserver {
  public:
   ConfirmInstallDialogDelegate(content::WebContents* web_contents,
-                               PluginInstaller* installer);
+                               PluginInstaller* installer,
+                               scoped_ptr<PluginMetadata> plugin_metadata);
 
   // TabModalConfirmDialogDelegate methods:
   virtual string16 GetTitle() OVERRIDE;
@@ -73,24 +74,27 @@
 
  private:
   content::WebContents* web_contents_;
+  scoped_ptr<PluginMetadata> plugin_metadata_;
 };
 
 ConfirmInstallDialogDelegate::ConfirmInstallDialogDelegate(
     content::WebContents* web_contents,
-    PluginInstaller* installer)
+    PluginInstaller* installer,
+    scoped_ptr<PluginMetadata> plugin_metadata)
     : TabModalConfirmDialogDelegate(web_contents),
       WeakPluginInstallerObserver(installer),
-      web_contents_(web_contents) {
+      web_contents_(web_contents),
+      plugin_metadata_(plugin_metadata.Pass()) {
 }
 
 string16 ConfirmInstallDialogDelegate::GetTitle() {
   return l10n_util::GetStringFUTF16(
-      IDS_PLUGIN_CONFIRM_INSTALL_DIALOG_TITLE, installer()->name());
+      IDS_PLUGIN_CONFIRM_INSTALL_DIALOG_TITLE, plugin_metadata_->name());
 }
 
 string16 ConfirmInstallDialogDelegate::GetMessage() {
   return l10n_util::GetStringFUTF16(IDS_PLUGIN_CONFIRM_INSTALL_DIALOG_MSG,
-                                    installer()->name());
+                                    plugin_metadata_->name());
 }
 
 string16 ConfirmInstallDialogDelegate::GetAcceptButtonTitle() {
@@ -99,7 +103,9 @@
 }
 
 void ConfirmInstallDialogDelegate::OnAccepted() {
-  installer()->StartInstalling(TabContents::FromWebContents(web_contents_));
+  installer()->StartInstalling(plugin_metadata_->url_for_display(),
+                               plugin_metadata_->plugin_url(),
+                               TabContents::FromWebContents(web_contents_));
 }
 
 void ConfirmInstallDialogDelegate::OnCanceled() {
@@ -123,6 +129,7 @@
  public:
   PluginPlaceholderHost(PluginObserver* observer,
                         int routing_id,
+                        string16 plugin_name,
                         PluginInstaller* installer)
       : PluginInstallerObserver(installer),
         observer_(observer),
@@ -131,7 +138,7 @@
     switch (installer->state()) {
       case PluginInstaller::INSTALLER_STATE_IDLE: {
         observer->Send(new ChromeViewMsg_FoundMissingPlugin(routing_id_,
-                                                            installer->name()));
+                                                            plugin_name));
         break;
       }
       case PluginInstaller::INSTALLER_STATE_DOWNLOADING: {
@@ -232,17 +239,23 @@
 void PluginObserver::OnBlockedOutdatedPlugin(int placeholder_id,
                                              const std::string& identifier) {
 #if defined(ENABLE_PLUGIN_INSTALLATION)
+  PluginFinder* finder = PluginFinder::GetInstance();
   // Find plugin to update.
-  PluginInstaller* installer =
-      PluginFinder::GetInstance()->FindPluginWithIdentifier(identifier);
-  DCHECK(installer) << "Couldn't find PluginInstaller for identifier "
-                    << identifier;
+  PluginInstaller* installer = NULL;
+  scoped_ptr<PluginMetadata> plugin;
+  if (!finder->FindPluginWithIdentifier(identifier, &installer, &plugin)) {
+    NOTREACHED();
+    return;
+  }
+
   plugin_placeholders_[placeholder_id] =
-      new PluginPlaceholderHost(this, placeholder_id, installer);
+      new PluginPlaceholderHost(this, placeholder_id,
+                                plugin->name(), installer);
   TabContents* tab_contents = TabContents::FromWebContents(web_contents());
   InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper();
   infobar_helper->AddInfoBar(
-      OutdatedPluginInfoBarDelegate::Create(web_contents(), installer));
+      OutdatedPluginInfoBarDelegate::Create(web_contents(),
+                                            installer, plugin.Pass()));
 #else
   // If we don't support third-party plug-in installation, we shouldn't have
   // outdated plug-ins.
@@ -254,42 +267,57 @@
 void PluginObserver::OnFindMissingPlugin(int placeholder_id,
                                          const std::string& mime_type) {
   std::string lang = "en-US";  // Oh yes.
-  PluginInstaller* installer =
-      PluginFinder::GetInstance()->FindPlugin(mime_type, lang);
-  if (!installer) {
+  scoped_ptr<PluginMetadata> plugin_metadata;
+  PluginInstaller* installer = NULL;
+  bool found_plugin = PluginFinder::GetInstance()->FindPlugin(
+      mime_type, lang, &installer, &plugin_metadata);
+  if (!found_plugin) {
     Send(new ChromeViewMsg_DidNotFindMissingPlugin(placeholder_id));
     return;
   }
+  DCHECK(installer);
+  DCHECK(plugin_metadata.get());
 
   plugin_placeholders_[placeholder_id] =
-      new PluginPlaceholderHost(this, placeholder_id, installer);
+      new PluginPlaceholderHost(this, placeholder_id,
+                                plugin_metadata->name(),
+                                installer);
   TabContents* tab_contents = TabContents::FromWebContents(web_contents());
   InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper();
+  base::Closure callback =  base::Bind(&PluginObserver::InstallMissingPlugin,
+                                       weak_ptr_factory_.GetWeakPtr(),
+                                       installer,
+                                       base::Passed(plugin_metadata->Clone()));
   InfoBarDelegate* delegate;
 #if !defined(OS_WIN)
   delegate = PluginInstallerInfoBarDelegate::Create(
       infobar_helper, installer,
-      base::Bind(&PluginObserver::InstallMissingPlugin,
-                 weak_ptr_factory_.GetWeakPtr(), installer));
+      plugin_metadata.Pass(),
+      callback);
 #else
   delegate = base::win::IsMetroProcess() ?
       PluginMetroModeInfoBarDelegate::Create(
-          infobar_helper, installer->name()) :
+          infobar_helper, plugin_metadata->name()) :
       PluginInstallerInfoBarDelegate::Create(
           infobar_helper, installer,
-          base::Bind(&PluginObserver::InstallMissingPlugin,
-              weak_ptr_factory_.GetWeakPtr(), installer));
+          plugin_metadata.Pass(),
+          callback);
 #endif
   infobar_helper->AddInfoBar(delegate);
 }
 
-void PluginObserver::InstallMissingPlugin(PluginInstaller* installer) {
-  if (installer->url_for_display()) {
-    installer->OpenDownloadURL(web_contents());
+void PluginObserver::InstallMissingPlugin(
+    PluginInstaller* installer,
+    scoped_ptr<PluginMetadata> plugin_metadata) {
+  if (plugin_metadata->url_for_display()) {
+    installer->OpenDownloadURL(plugin_metadata->url_for_display(),
+                               plugin_metadata->plugin_url(),
+                               web_contents());
   } else {
     TabModalConfirmDialog::Create(
-        new ConfirmInstallDialogDelegate(web_contents(), installer),
-        TabContents::FromWebContents(web_contents()));
+        new ConfirmInstallDialogDelegate(
+            web_contents(), installer, plugin_metadata.Pass()),
+            TabContents::FromWebContents(web_contents()));
   }
 }
 
diff --git a/chrome/browser/plugins/plugin_observer.h b/chrome/browser/plugins/plugin_observer.h
index 569304d..cba27cf6 100644
--- a/chrome/browser/plugins/plugin_observer.h
+++ b/chrome/browser/plugins/plugin_observer.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_PLUGINS_PLUGIN_OBSERVER_H_
 #define CHROME_BROWSER_PLUGINS_PLUGIN_OBSERVER_H_
 
+#include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/common/web_contents_user_data.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -16,6 +17,8 @@
 class GURL;
 class InfoBarDelegate;
 class PluginFinder;
+class PluginMetadata;
+class TabContents;
 
 #if defined(ENABLE_PLUGIN_INSTALLATION)
 class PluginInstaller;
@@ -42,7 +45,8 @@
   class PluginPlaceholderHost;
 
 #if defined(ENABLE_PLUGIN_INSTALLATION)
-  void InstallMissingPlugin(PluginInstaller* installer);
+  void InstallMissingPlugin(PluginInstaller* installer,
+                            scoped_ptr<PluginMetadata> plugin_metadata);
 #endif
 
   // Message handlers:
diff --git a/chrome/browser/plugins/plugin_prefs.cc b/chrome/browser/plugins/plugin_prefs.cc
index 54f3ba8..45a49cd 100644
--- a/chrome/browser/plugins/plugin_prefs.cc
+++ b/chrome/browser/plugins/plugin_prefs.cc
@@ -129,7 +129,7 @@
 
   // Update the state for all plug-ins in the group.
   for (size_t i = 0; i < plugins.size(); ++i) {
-    PluginMetadata* plugin = finder->GetPluginMetadata(plugins[i]);
+    scoped_ptr<PluginMetadata> plugin(finder->GetPluginMetadata(plugins[i]));
     if (group_name != plugin->name())
       continue;
     plugin_state_.Set(plugins[i].path, enabled);
@@ -148,7 +148,8 @@
   webkit::WebPluginInfo plugin;
   bool can_enable = true;
   if (PluginService::GetInstance()->GetPluginInfoByPath(path, &plugin)) {
-    PluginMetadata* plugin_metadata = finder->GetPluginMetadata(plugin);
+    scoped_ptr<PluginMetadata> plugin_metadata(
+        finder->GetPluginMetadata(plugin));
     PolicyStatus plugin_status =
         PolicyStatusForPlugin(plugin.name, plugin.version);
     PolicyStatus group_status =
@@ -191,8 +192,8 @@
   string16 group_name;
   for (size_t i = 0; i < plugins.size(); ++i) {
     if (plugins[i].path == path) {
-      PluginMetadata* plugin_metadata =
-          plugin_finder->GetPluginMetadata(plugins[i]);
+      scoped_ptr<PluginMetadata> plugin_metadata(
+          plugin_finder->GetPluginMetadata(plugins[i]));
       // set the group name for this plug-in.
       group_name = plugin_metadata->name();
       DCHECK_EQ(enabled, IsPluginEnabled(plugins[i]));
@@ -202,8 +203,8 @@
 
   bool all_disabled = true;
   for (size_t i = 0; i < plugins.size(); ++i) {
-    PluginMetadata* plugin_metadata =
-        plugin_finder->GetPluginMetadata(plugins[i]);
+    scoped_ptr<PluginMetadata> plugin_metadata(
+        plugin_finder->GetPluginMetadata(plugins[i]));
     DCHECK(!plugin_metadata->name().empty());
     if (group_name == plugin_metadata->name()) {
       all_disabled = all_disabled && !IsPluginEnabled(plugins[i]);
@@ -265,8 +266,9 @@
 }
 
 bool PluginPrefs::IsPluginEnabled(const webkit::WebPluginInfo& plugin) const {
-  PluginFinder* finder = PluginFinder::GetInstance();
-  string16 group_name = finder->GetPluginMetadata(plugin)->name();
+  scoped_ptr<PluginMetadata> plugin_metadata(
+      PluginFinder::GetInstance()->GetPluginMetadata(plugin));
+  string16 group_name = plugin_metadata->name();
 
   PolicyStatus plugin_status =
       PolicyStatusForPlugin(plugin.name, plugin.version);
@@ -689,7 +691,8 @@
     summary->SetBoolean("enabled", enabled);
     plugins_list->Append(summary);
 
-    PluginMetadata* plugin_metadata = finder->GetPluginMetadata(plugins[i]);
+    scoped_ptr<PluginMetadata> plugin_metadata(
+        finder->GetPluginMetadata(plugins[i]));
     // Insert into a set of all group names.
     group_names.insert(plugin_metadata->name());
   }
diff --git a/chrome/browser/renderer_host/plugin_info_message_filter.cc b/chrome/browser/renderer_host/plugin_info_message_filter.cc
index 70893da..3054e49 100644
--- a/chrome/browser/renderer_host/plugin_info_message_filter.cc
+++ b/chrome/browser/renderer_host/plugin_info_message_filter.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/renderer_host/plugin_info_message_filter.h"
 
 #include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/metrics/histogram.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/content_settings/content_settings_utils.h"
@@ -129,8 +130,8 @@
     ChromeViewHostMsg_GetPluginInfo_Status* status,
     std::string* group_identifier,
     string16* group_name) const {
-  PluginMetadata* plugin_metadata =
-      PluginFinder::GetInstance()->GetPluginMetadata(plugin);
+  scoped_ptr<PluginMetadata> plugin_metadata(
+      PluginFinder::GetInstance()->GetPluginMetadata(plugin));
   *group_name = plugin_metadata->name();
   *group_identifier = plugin_metadata->identifier();
 
diff --git a/chrome/browser/ui/pdf/pdf_unsupported_feature.cc b/chrome/browser/ui/pdf/pdf_unsupported_feature.cc
index 98c5a82a..e50ebe9 100644
--- a/chrome/browser/ui/pdf/pdf_unsupported_feature.cc
+++ b/chrome/browser/ui/pdf/pdf_unsupported_feature.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/pdf/pdf_unsupported_feature.h"
 
 #include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "base/version.h"
@@ -284,8 +285,8 @@
   reader_webplugininfo_ = *reader;
 
 #if defined(ENABLE_PLUGIN_INSTALLATION)
-  PluginMetadata* plugin_metadata =
-      plugin_finder->GetPluginMetadata(reader_webplugininfo_);
+  scoped_ptr<PluginMetadata> plugin_metadata(
+      plugin_finder->GetPluginMetadata(reader_webplugininfo_));
 
   reader_vulnerable_ = plugin_metadata->GetSecurityStatus(*reader) !=
                        PluginMetadata::SECURITY_STATUS_UP_TO_DATE;
@@ -372,8 +373,8 @@
   const webkit::WebPluginInfo* reader = NULL;
   PluginFinder* plugin_finder = PluginFinder::GetInstance();
   for (size_t i = 0; i < plugins.size(); ++i) {
-    PluginMetadata* plugin_metadata =
-        plugin_finder->GetPluginMetadata(plugins[i]);
+    scoped_ptr<PluginMetadata> plugin_metadata(
+        plugin_finder->GetPluginMetadata(plugins[i]));
     if (plugin_metadata->identifier() != kAdobeReaderIdentifier)
       continue;
 
diff --git a/chrome/browser/ui/webui/plugins_ui.cc b/chrome/browser/ui/webui/plugins_ui.cc
index 8a8b062..a39d46cd 100644
--- a/chrome/browser/ui/webui/plugins_ui.cc
+++ b/chrome/browser/ui/webui/plugins_ui.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/memory/singleton.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop.h"
@@ -339,7 +340,8 @@
   // the plug-ins in UI in a grouped fashion.
   PluginGroups groups;
   for (size_t i = 0; i < plugins.size(); ++i) {
-    PluginMetadata* plugin = plugin_finder->GetPluginMetadata(plugins[i]);
+    scoped_ptr<PluginMetadata> plugin(
+        plugin_finder->GetPluginMetadata(plugins[i]));
     groups[plugin->identifier()].push_back(&plugins[i]);
   }
 
@@ -349,8 +351,8 @@
       it != groups.end(); ++it) {
     const std::vector<const WebPluginInfo*>& group_plugins = it->second;
     ListValue* plugin_files = new ListValue();
-    PluginMetadata* plugin_metadata =
-        plugin_finder->GetPluginMetadata(*group_plugins[0]);
+    scoped_ptr<PluginMetadata> plugin_metadata(
+        plugin_finder->GetPluginMetadata(*group_plugins[0]));
     string16 group_name = plugin_metadata->name();
     std::string group_identifier = plugin_metadata->identifier();
     bool group_enabled = false;