summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-28 11:57:51 +0000
committerbauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-28 11:57:51 +0000
commit1d697f38d70b8edaca243a49f790b525c1c95a9d (patch)
treed865f1e7f9984aea144a889c51ddd6fff443ad05
parent2f606239c901c6c464ae0323a9eb577401cdaacc (diff)
downloadchromium_src-1d697f38d70b8edaca243a49f790b525c1c95a9d.zip
chromium_src-1d697f38d70b8edaca243a49f790b525c1c95a9d.tar.gz
chromium_src-1d697f38d70b8edaca243a49f790b525c1c95a9d.tar.bz2
Show infobar for missing plug-ins on Mac.
TBR=arv@chromium.org BUG=62079 TEST=none Review URL: http://codereview.chromium.org/8578009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111693 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/generated_resources.grd25
-rw-r--r--chrome/browser/browser_resources.grd6
-rw-r--r--chrome/browser/chrome_plugin_message_filter.cc19
-rw-r--r--chrome/browser/chrome_plugin_message_filter.h3
-rw-r--r--chrome/browser/plugin_finder.cc101
-rw-r--r--chrome/browser/plugin_finder.h54
-rw-r--r--chrome/browser/plugin_installer_infobar_delegate.cc35
-rw-r--r--chrome/browser/plugin_installer_infobar_delegate.h13
-rw-r--r--chrome/browser/plugin_observer.cc49
-rw-r--r--chrome/browser/plugin_observer.h13
-rw-r--r--chrome/browser/resources/plugins_mac.json173
-rw-r--r--chrome/browser/resources/plugins_win.json166
-rw-r--r--chrome/chrome_browser.gypi4
-rw-r--r--chrome/common/render_messages.h15
-rw-r--r--chrome/renderer/plugins/missing_plugin.cc64
-rw-r--r--chrome/renderer/plugins/missing_plugin.h21
-rw-r--r--chrome/renderer/plugins/plugin_placeholder.cc3
-rw-r--r--chrome/renderer/plugins/plugin_placeholder.h1
-rw-r--r--chrome/renderer/resources/blocked_plugin.html5
-rw-r--r--webkit/plugins/webview_plugin.cc5
-rw-r--r--webkit/plugins/webview_plugin.h5
21 files changed, 745 insertions, 35 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 1e1fd1c..549867c9 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -539,10 +539,13 @@ are declared in build/common.gypi.
Input &amp;methods
</message>
<message name="IDS_CONTENT_CONTEXT_PLUGIN_RUN" desc="The name of the Run command on the blocked plugin context menu">
- Run this plugin
+ Run this plug-in
</message>
<message name="IDS_CONTENT_CONTEXT_PLUGIN_HIDE" desc="The name of the Hide command on the blocked plugin context menu">
- Hide this plugin
+ Hide this plug-in
+ </message>
+ <message name="IDS_CONTENT_CONTEXT_PLUGIN_INSTALL" desc="The name of the Install command on the missing plugin context menu">
+ Install missing plug-in
</message>
<message name="IDS_CONTENT_CONTEXT_SPEECH_INPUT_MENU" desc="The name of the Speech input options submenu in the content area context menu">
Voice recognition options
@@ -754,10 +757,13 @@ are declared in build/common.gypi.
Input &amp;Methods
</message>
<message name="IDS_CONTENT_CONTEXT_PLUGIN_RUN" desc="In Title Case: The name of the Run command on the blocked plugin context menu">
- Run This Plugin
+ Run This Plug-in
</message>
<message name="IDS_CONTENT_CONTEXT_PLUGIN_HIDE" desc="In Title Case: The name of the Hide command on the blocked plugin context menu">
- Hide This Plugin
+ Hide This Plug-in
+ </message>
+ <message name="IDS_CONTENT_CONTEXT_PLUGIN_INSTALL" desc="The name of the Install command on the missing plugin context menu">
+ Install Missing Plug-in
</message>
<message name="IDS_CONTENT_CONTEXT_SPEECH_INPUT_MENU" desc="In Title Case: The name of the Speech input options submenu in the content area context menu">
Voice Recognition Options
@@ -5032,9 +5038,15 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_PLUGIN_NOT_AUTHORIZED" desc="The placeholder text for a plug-in that requires user permission to run.">
The <ph name="PLUGIN_NAME">$1<ex>Java</ex></ph> plug-in needs your permission to run.
</message>
- <message name="IDS_PLUGIN_NOT_FOUND" desc="The placeholder text for a plug-in that is not installed.">
+ <message name="IDS_PLUGIN_NOT_FOUND" desc="The placeholder text for an unknown plug-in that is not installed.">
No plug-in available to display this content.
</message>
+ <message name="IDS_PLUGIN_SEARCHING" desc="The placeholder text when searching for a missing plug-in.">
+ Looking for plug-in...
+ </message>
+ <message name="IDS_PLUGIN_FOUND" desc="The placeholder text for a known plug-in that is not installed.">
+ The <ph name="PLUGIN_NAME">$1<ex>Quicktime</ex></ph> plug-in is required to display this content.
+ </message>
<message name="IDS_PLUGIN_DISABLED" desc="The placeholder text for a disabled plug-in.">
The <ph name="PLUGIN_NAME">$1<ex>Flash</ex></ph> plug-in has been disabled. To re-enable it, please go to <ph name="CHROME_PLUGINS_LINK">chrome://plugins</ph>.
</message>
@@ -9393,6 +9405,9 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_PLUGININSTALLER_MISSINGPLUGIN_PROMPT" desc="Info Bar message to prompt installing missing plugin">
An additional plug-in is required to display some elements on this page.
</message>
+ <message name="IDS_PLUGININSTALLER_INSTALLPLUGIN_PROMPT" desc="Info Bar message to prompt installing missing plugin">
+ The <ph name="PLUGIN_NAME">$1<ex>Quicktime</ex></ph> plug-in is required to display some elements on this page.
+ </message>
<message name="IDS_PLUGININSTALLER_INSTALLPLUGIN_BUTTON" desc="Info Bar button to install missing plugin">
Install plug-in...
</message>
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 630f21a..fa9a07c 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -86,6 +86,12 @@
<include name="IDR_NOTIFICATION_ICON_HTML" file="resources\notification_icon.html" type="BINDATA" />
<include name="IDR_PLUGINS_HTML" file="resources\plugins.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_PLUGINS_JS" file="resources\plugins.js" type="BINDATA" />
+ <if expr="is_win">
+ <include name="IDR_PLUGIN_DB_JSON" file="resources\plugins_win.json" type="BINDATA" />
+ </if>
+ <if expr="is_macosx">
+ <include name="IDR_PLUGIN_DB_JSON" file="resources\plugins_mac.json" type="BINDATA" />
+ </if>
<include name="IDR_POLICY_CSS" file="resources\policy.css" type="BINDATA"/>
<include name="IDR_POLICY_HTML" file="resources\policy.html" flattenhtml="true" allowexternalscript="true" type="BINDATA"/>
<include name="IDR_POLICY_JS" file="resources\policy.js" type="BINDATA"/>
diff --git a/chrome/browser/chrome_plugin_message_filter.cc b/chrome/browser/chrome_plugin_message_filter.cc
index fee4c01..9d9677b 100644
--- a/chrome/browser/chrome_plugin_message_filter.cc
+++ b/chrome/browser/chrome_plugin_message_filter.cc
@@ -93,7 +93,6 @@ void ChromePluginMessageFilter::OnDownloadUrlOnFileThread(
context,
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
}
-
#endif
void ChromePluginMessageFilter::OnGetPluginFinderUrl(
@@ -136,8 +135,10 @@ void ChromePluginMessageFilter::HandleMissingPluginStatus(
InfoBarTabHelper* infobar_helper = tcw->infobar_tab_helper();
if (status == webkit::npapi::default_plugin::MISSING_PLUGIN_AVAILABLE) {
- infobar_helper->AddInfoBar(
- new PluginInstallerInfoBarDelegate(infobar_helper, window));
+ infobar_helper->AddInfoBar(new PluginInstallerInfoBarDelegate(
+ infobar_helper, string16(), GURL(),
+ base::Bind(&ChromePluginMessageFilter::InstallMissingPlugin,
+ base::Unretained(window))));
return;
}
@@ -157,3 +158,15 @@ void ChromePluginMessageFilter::HandleMissingPluginStatus(
NOTIMPLEMENTED();
#endif // OS_WIN
}
+
+// static
+void ChromePluginMessageFilter::InstallMissingPlugin(gfx::NativeWindow window) {
+#if defined(OS_WIN)
+ ::PostMessage(window,
+ webkit::npapi::default_plugin::kInstallMissingPluginMessage,
+ 0,
+ 0);
+#else
+ NOTIMPLEMENTED();
+#endif // OS_WIN
+}
diff --git a/chrome/browser/chrome_plugin_message_filter.h b/chrome/browser/chrome_plugin_message_filter.h
index 08bc147..67642ca 100644
--- a/chrome/browser/chrome_plugin_message_filter.h
+++ b/chrome/browser/chrome_plugin_message_filter.h
@@ -52,12 +52,13 @@ class ChromePluginMessageFilter : public IPC::ChannelProxy::MessageFilter,
int render_view_id,
gfx::NativeWindow window);
- // static
static void HandleMissingPluginStatus(int status,
int render_process_id,
int render_view_id,
gfx::NativeWindow window);
+ static void InstallMissingPlugin(gfx::NativeWindow window);
+
PluginProcessHost* process_;
DISALLOW_COPY_AND_ASSIGN(ChromePluginMessageFilter);
diff --git a/chrome/browser/plugin_finder.cc b/chrome/browser/plugin_finder.cc
new file mode 100644
index 0000000..eee7757
--- /dev/null
+++ b/chrome/browser/plugin_finder.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2011 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/plugin_finder.h"
+
+#include "base/bind.h"
+#include "base/json/json_reader.h"
+#include "base/message_loop.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/browser_thread.h"
+#include "googleurl/src/gurl.h"
+#include "grit/browser_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+
+PluginFinder* PluginFinder::GetInstance() {
+ return Singleton<PluginFinder>::get();
+}
+
+PluginFinder::PluginFinder() {
+#if defined(OS_WIN) || defined(OS_MACOSX)
+ base::StringPiece json_resource(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_PLUGIN_DB_JSON));
+ bool allow_trailing_comma = false;
+ std::string error_str;
+ scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
+ json_resource.as_string(),
+ allow_trailing_comma,
+ NULL,
+ &error_str));
+ DLOG_IF(ERROR, !value.get()) << error_str;
+ if (value->IsType(base::Value::TYPE_DICTIONARY)) {
+ base::DictionaryValue* dict =
+ static_cast<base::DictionaryValue*>(value.get());
+ base::ListValue* list = NULL;
+ dict->GetList("plugins", &list);
+ plugin_list_.reset(list->DeepCopy());
+ }
+ DCHECK(plugin_list_.get());
+#endif
+ if (!plugin_list_.get())
+ plugin_list_.reset(new base::ListValue());
+}
+
+PluginFinder::~PluginFinder() {
+}
+
+void PluginFinder::FindPlugin(
+ const std::string& mime_type,
+ const std::string& language,
+ const FindPluginCallback& found_callback,
+ const base::Closure& not_found_callback) {
+ if (g_browser_process->local_state()->GetBoolean(
+ prefs::kDisablePluginFinder)) {
+ MessageLoop::current()->PostTask(FROM_HERE, not_found_callback);
+ return;
+ }
+ for (ListValue::const_iterator plugin_it = plugin_list_->begin();
+ plugin_it != plugin_list_->end(); ++plugin_it) {
+ if (!(*plugin_it)->IsType(base::Value::TYPE_DICTIONARY)) {
+ NOTREACHED();
+ continue;
+ }
+ const base::DictionaryValue* plugin =
+ static_cast<const base::DictionaryValue*>(*plugin_it);
+ std::string language_str;
+ bool success = plugin->GetString("lang", &language_str);
+ DCHECK(success);
+ if (language_str != language)
+ continue;
+ ListValue* mime_types = NULL;
+ success = plugin->GetList("mime_types", &mime_types);
+ DCHECK(success);
+ for (ListValue::const_iterator mime_type_it = mime_types->begin();
+ mime_type_it != mime_types->end(); ++mime_type_it) {
+ std::string mime_type_str;
+ success = (*mime_type_it)->GetAsString(&mime_type_str);
+ DCHECK(success);
+ if (mime_type_str == mime_type) {
+ std::string url;
+ success = plugin->GetString("url", &url);
+ DCHECK(success);
+ string16 name;
+ success = plugin->GetString("name", &name);
+ DCHECK(success);
+ bool display_url = false;
+ plugin->GetBoolean("displayurl", &display_url);
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(found_callback, GURL(url), name, display_url));
+ return;
+ }
+ }
+ }
+ MessageLoop::current()->PostTask(FROM_HERE, not_found_callback);
+}
+
diff --git a/chrome/browser/plugin_finder.h b/chrome/browser/plugin_finder.h
new file mode 100644
index 0000000..e9b18d0
--- /dev/null
+++ b/chrome/browser/plugin_finder.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2011 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_PLUGIN_FINDER_H_
+#define CHROME_BROWSER_PLUGIN_FINDER_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/singleton.h"
+#include "base/string16.h"
+
+namespace base {
+class ListValue;
+}
+
+class GURL;
+
+class PluginFinder {
+ public:
+ // If |display_url| 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.
+ typedef base::Callback<void(GURL /* plugin_url */,
+ string16 /* name */,
+ bool /* display_url */)> FindPluginCallback;
+
+ static PluginFinder* GetInstance();
+
+ // Finds a plug-in for the given MIME type and language (specified as an IETF
+ // language tag, i.e. en-US) and calls one of the two passed in callbacks,
+ // depending on whether a plug-in is found.
+ void FindPlugin(const std::string& mime_type,
+ const std::string& language,
+ const FindPluginCallback& found_callback,
+ const base::Closure& not_found_callback);
+
+ private:
+ friend struct DefaultSingletonTraits<PluginFinder>;
+
+ PluginFinder();
+ ~PluginFinder();
+
+ scoped_ptr<base::ListValue> plugin_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginFinder);
+};
+
+#endif // CHROME_BROWSER_PLUGIN_FINDER_H_
diff --git a/chrome/browser/plugin_installer_infobar_delegate.cc b/chrome/browser/plugin_installer_infobar_delegate.cc
index 02b8f2d..01f054b 100644
--- a/chrome/browser/plugin_installer_infobar_delegate.cc
+++ b/chrome/browser/plugin_installer_infobar_delegate.cc
@@ -13,12 +13,16 @@
#include "grit/theme_resources_standard.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
-#include "webkit/plugins/npapi/default_plugin_shared.h"
PluginInstallerInfoBarDelegate::PluginInstallerInfoBarDelegate(
- InfoBarTabHelper* infobar_helper, gfx::NativeWindow window)
+ InfoBarTabHelper* infobar_helper,
+ const string16& plugin_name,
+ const GURL& learn_more_url,
+ const base::Closure& callback)
: ConfirmInfoBarDelegate(infobar_helper),
- window_(window) {
+ plugin_name_(plugin_name),
+ learn_more_url_(learn_more_url),
+ callback_(callback) {
}
PluginInstallerInfoBarDelegate::~PluginInstallerInfoBarDelegate() {
@@ -35,7 +39,11 @@ PluginInstallerInfoBarDelegate*
}
string16 PluginInstallerInfoBarDelegate::GetMessageText() const {
- return l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_MISSINGPLUGIN_PROMPT);
+ // TODO(bauerb): Remove this check when removing the default plug-in.
+ return plugin_name_.empty() ?
+ l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_MISSINGPLUGIN_PROMPT) :
+ l10n_util::GetStringFUTF16(IDS_PLUGININSTALLER_INSTALLPLUGIN_PROMPT,
+ plugin_name_);
}
int PluginInstallerInfoBarDelegate::GetButtons() const {
@@ -49,13 +57,7 @@ string16 PluginInstallerInfoBarDelegate::GetButtonLabel(
}
bool PluginInstallerInfoBarDelegate::Accept() {
- // TODO(PORT) for other platforms.
-#if defined(OS_WIN)
- ::PostMessage(window_,
- webkit::npapi::default_plugin::kInstallMissingPluginMessage,
- 0,
- 0);
-#endif
+ callback_.Run();
return true;
}
@@ -65,9 +67,14 @@ string16 PluginInstallerInfoBarDelegate::GetLinkText() const {
bool PluginInstallerInfoBarDelegate::LinkClicked(
WindowOpenDisposition disposition) {
- owner()->tab_contents()->OpenURL(google_util::AppendGoogleLocaleParam(GURL(
- "https://www.google.com/support/chrome/bin/answer.py?answer=142064")),
- GURL(),
+ GURL url(learn_more_url_);
+ // TODO(bauerb): Remove this check when removing the default plug-in.
+ if (url.is_empty()) {
+ url = google_util::AppendGoogleLocaleParam(GURL(
+ "https://www.google.com/support/chrome/bin/answer.py?answer=142064"));
+ }
+ owner()->tab_contents()->OpenURL(
+ url, GURL(),
(disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
content::PAGE_TRANSITION_LINK);
return false;
diff --git a/chrome/browser/plugin_installer_infobar_delegate.h b/chrome/browser/plugin_installer_infobar_delegate.h
index 519b73a..3d2f68f 100644
--- a/chrome/browser/plugin_installer_infobar_delegate.h
+++ b/chrome/browser/plugin_installer_infobar_delegate.h
@@ -6,15 +6,20 @@
#define CHROME_BROWSER_PLUGIN_INSTALLER_INFOBAR_DELEGATE_H_
#pragma once
+#include "base/callback.h"
#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
-#include "ui/gfx/native_widget_types.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:
+ // Shows an infobar asking whether to install the plugin with the name
+ // |plugin_name|. When the user accepts, |callback| is called.
PluginInstallerInfoBarDelegate(InfoBarTabHelper* infobar_helper,
- gfx::NativeWindow window);
+ const string16& plugin_name,
+ const GURL& learn_more_url,
+ const base::Closure& callback);
private:
virtual ~PluginInstallerInfoBarDelegate();
@@ -30,7 +35,9 @@ class PluginInstallerInfoBarDelegate : public ConfirmInfoBarDelegate {
virtual string16 GetLinkText() const OVERRIDE;
virtual bool LinkClicked(WindowOpenDisposition disposition) OVERRIDE;
- gfx::NativeWindow window_;
+ string16 plugin_name_;
+ GURL learn_more_url_;
+ base::Closure callback_;
DISALLOW_COPY_AND_ASSIGN(PluginInstallerInfoBarDelegate);
};
diff --git a/chrome/browser/plugin_observer.cc b/chrome/browser/plugin_observer.cc
index 8c78fcb..73d9a75 100644
--- a/chrome/browser/plugin_observer.cc
+++ b/chrome/browser/plugin_observer.cc
@@ -4,10 +4,14 @@
#include "chrome/browser/plugin_observer.h"
+#include "base/bind.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
+#include "chrome/browser/plugin_finder.h"
+#include "chrome/browser/plugin_installer_infobar_delegate.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
@@ -282,6 +286,7 @@ bool OutdatedPluginInfoBarDelegate::LinkClicked(
PluginObserver::PluginObserver(TabContentsWrapper* tab_contents)
: TabContentsObserver(tab_contents->tab_contents()),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
tab_contents_(tab_contents) {
}
@@ -292,6 +297,8 @@ bool PluginObserver::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(PluginObserver, message)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedOutdatedPlugin,
OnBlockedOutdatedPlugin)
+ IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FindMissingPlugin,
+ OnFindMissingPlugin)
IPC_MESSAGE_UNHANDLED(return false)
IPC_END_MESSAGE_MAP()
@@ -308,3 +315,45 @@ void PluginObserver::OnBlockedOutdatedPlugin(const string16& name,
name)) :
new OutdatedPluginInfoBarDelegate(infobar_helper, name, update_url));
}
+
+void PluginObserver::OnFindMissingPlugin(int placeholder_id,
+ const std::string& mime_type) {
+ PluginFinder* plugin_finder = PluginFinder::GetInstance();
+ std::string lang = "en-US"; // Oh yes.
+ plugin_finder->FindPlugin(
+ mime_type, lang,
+ base::Bind(&PluginObserver::FoundMissingPlugin,
+ weak_ptr_factory_.GetWeakPtr(), placeholder_id, mime_type),
+ base::Bind(&PluginObserver::DidNotFindMissingPlugin,
+ weak_ptr_factory_.GetWeakPtr(), placeholder_id, mime_type));
+}
+
+void PluginObserver::FoundMissingPlugin(int placeholder_id,
+ const std::string& mime_type,
+ const GURL& url,
+ const string16& name,
+ bool display_url) {
+ Send(new ChromeViewMsg_FoundMissingPlugin(placeholder_id, name));
+ InfoBarTabHelper* infobar_helper = tab_contents_->infobar_tab_helper();
+ infobar_helper->AddInfoBar(new PluginInstallerInfoBarDelegate(
+ infobar_helper,
+ name,
+ GURL(), // TODO(bauerb): Get URL from JSON file.
+ base::Bind(&PluginObserver::InstallMissingPlugin,
+ weak_ptr_factory_.GetWeakPtr(), url, display_url)));
+}
+
+void PluginObserver::DidNotFindMissingPlugin(int placeholder_id,
+ const std::string& mime_type) {
+ Send(new ChromeViewMsg_DidNotFindMissingPlugin(placeholder_id));
+}
+
+void PluginObserver::InstallMissingPlugin(const GURL& url,
+ bool display_url) {
+ if (display_url) {
+ tab_contents()->OpenURL(url, tab_contents()->GetURL(), NEW_FOREGROUND_TAB,
+ content::PAGE_TRANSITION_TYPED);
+ } else {
+ NOTIMPLEMENTED();
+ }
+}
diff --git a/chrome/browser/plugin_observer.h b/chrome/browser/plugin_observer.h
index 082a180..a8a2706 100644
--- a/chrome/browser/plugin_observer.h
+++ b/chrome/browser/plugin_observer.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_PLUGIN_OBSERVER_H_
#pragma once
+#include "base/memory/weak_ptr.h"
#include "content/browser/tab_contents/tab_contents_observer.h"
class GURL;
@@ -22,6 +23,18 @@ class PluginObserver : public TabContentsObserver {
private:
void OnBlockedOutdatedPlugin(const string16& name, const GURL& update_url);
+ void OnFindMissingPlugin(int placeholder_id, const std::string& mime_type);
+
+ void FoundMissingPlugin(int placeholder_id,
+ const std::string& mime_type,
+ const GURL& url,
+ const string16& name,
+ bool display_url);
+ void DidNotFindMissingPlugin(int placeholder_id,
+ const std::string& mime_type);
+ void InstallMissingPlugin(const GURL& url, bool display_url);
+
+ base::WeakPtrFactory<PluginObserver> weak_ptr_factory_;
TabContentsWrapper* tab_contents_;
scoped_ptr<InfoBarDelegate> plugin_installer_; // Lazily created.
diff --git a/chrome/browser/resources/plugins_mac.json b/chrome/browser/resources/plugins_mac.json
new file mode 100644
index 0000000..1f0a456
--- /dev/null
+++ b/chrome/browser/resources/plugins_mac.json
@@ -0,0 +1,173 @@
+{
+ "plugins": [
+ {
+ "mime_types": [
+ "application/x-java-applet",
+ "application/x-java-applet,version=1.1",
+ "application/x-java-applet,version=1.1.1",
+ "application/x-java-applet,version=1.1.2",
+ "application/x-java-applet,version=1.1.3",
+ "application/x-java-applet,version=1.2",
+ "application/x-java-applet,version=1.2.1",
+ "application/x-java-applet,version=1.2.2",
+ "application/x-java-applet,version=1.3",
+ "application/x-java-applet,version=1.3.1",
+ "application/x-java-applet,version=1.4",
+ "application/x-java-applet,version=1.4.1",
+ "application/x-java-applet,version=1.4.2",
+ "application/x-java-applet,version=1.5",
+ "application/x-java-applet,version=1.6",
+ "application/x-java-bean",
+ "application/x-java-bean,version=1.1",
+ "application/x-java-bean,version=1.1.1",
+ "application/x-java-bean,version=1.1.2",
+ "application/x-java-bean,version=1.1.3",
+ "application/x-java-bean,version=1.2",
+ "application/x-java-bean,version=1.2.1",
+ "application/x-java-bean,version=1.2.2",
+ "application/x-java-bean,version=1.3",
+ "application/x-java-bean,version=1.3.1",
+ "application/x-java-bean,version=1.4",
+ "application/x-java-bean,version=1.4.1",
+ "application/x-java-bean,version=1.4.2",
+ "application/x-java-bean,version=1.5",
+ "application/x-java-bean,version=1.6",
+ "application/x-java-vm"
+ ],
+ "lang": "en-US",
+ "name": "Java(TM)",
+ "url": "http://java.com/en/download/apple_manual.jsp",
+ "displayurl": true
+ },
+ {
+ "mime_types": [
+ "audio/vnd.rn-realaudio",
+ "video/vnd.rn-realvideo",
+ "audio/x-pn-realaudio-plugin",
+ "audio/x-pn-realaudio"
+ ],
+ "lang": "en-US",
+ "name": "RealPlayer",
+ "url": "http://www.real.com/realplayer/download",
+ "displayurl": true
+ },
+ {
+ "mime_types": [
+ "application/futuresplash",
+ "application/x-shockwave-flash"
+ ],
+ "lang": "en-US",
+ "name": "Adobe Flash Player",
+ "url": "http://get.adobe.com/flashplayer/",
+ "displayurl": true
+ },
+ {
+ "mime_types": [
+ "application/x-director"
+ ],
+ "lang": "en-US",
+ "name": "Adobe Shockwave Player",
+ "url": "http://www.adobe.com/shockwave/download/",
+ "displayurl": true
+ },
+ {
+ "mime_types": [
+ "application/pdf",
+ "application/vnd.adobe.x-mars",
+ "application/vnd.adobe.xdp+xml",
+ "application/vnd.adobe.xfd+xml",
+ "application/vnd.adobe.xfdf",
+ "application/vnd.fdf"
+ ],
+ "lang": "en-US",
+ "name": "Adobe Reader",
+ "url": "http://get.adobe.com/reader/",
+ "displayurl": true
+ },
+ {
+ "mime_types": [
+ "application/sdp",
+ "application/x-mpeg",
+ "application/x-rtsp",
+ "application/x-sdp",
+ "audio/3ggp",
+ "audio/3ggp2",
+ "audio/aac",
+ "audio/ac3",
+ "audio/aiff",
+ "audio/amr",
+ "audio/basic",
+ "audio/mid",
+ "audio/midi",
+ "audio/mp4",
+ "audio/mpeg",
+ "audio/vnd.qcelp",
+ "audio/wav",
+ "audio/x-aac",
+ "audio/x-ac3",
+ "audio/x-aiff",
+ "audio/x-caf",
+ "audio/x-gsm",
+ "audio/x-m4a",
+ "audio/x-m4b",
+ "audio/x-m4p",
+ "audio/x-midi",
+ "audio/x-mpeg",
+ "audio/x-wav",
+ "image/jp2",
+ "image/jpeg2000",
+ "image/jpeg2000-image",
+ "image/pict",
+ "image/png",
+ "image/x-jpeg2000-image",
+ "image/x-macpaint",
+ "image/x-pict",
+ "image/x-png",
+ "image/x-quicktime",
+ "image/x-sgi",
+ "image/x-targa",
+ "video/3ggp",
+ "video/3ggp2",
+ "video/flc",
+ "video/mp4",
+ "video/mpeg",
+ "video/quicktime",
+ "video/sd-video",
+ "video/x-m4v",
+ "video/x-mpeg"
+ ],
+ "lang": "en-US",
+ "name": "QuickTime Player",
+ "url": "http://www.apple.com/quicktime/download/",
+ "displayurl": true
+ },
+ {
+ "mime_types": [
+ "application/asx",
+ "application/x-mplayer2",
+ "application/x-ms-wmp",
+ "audio/x-ms-wax",
+ "audio/x-ms-wma",
+ "video/x-ms-asf",
+ "video/x-ms-asf-plugin",
+ "video/x-ms-wm",
+ "video/x-ms-wmv",
+ "video/x-ms-wvx"
+ ],
+ "lang": "en-US",
+ "name": "Flip4Mac",
+ "url": "http://www.telestream.net/flip4mac-wmv/overview.htm",
+ "displayurl": true
+ },
+ {
+ "mime_types": [
+ "video/divx",
+ "video/x-matroska"
+ ],
+ "lang": "en-US",
+ "name": "DivX Web Player",
+ "url": "http://www.divx.com/en/downloads/divx/mac",
+ "displayurl": true
+ }
+ ]
+} \ No newline at end of file
diff --git a/chrome/browser/resources/plugins_win.json b/chrome/browser/resources/plugins_win.json
new file mode 100644
index 0000000..0549c6c
--- /dev/null
+++ b/chrome/browser/resources/plugins_win.json
@@ -0,0 +1,166 @@
+{
+ "plugins": [
+ {
+ "mime_types": [
+ "application/x-java-applet",
+ "application/x-java-applet,version=1.1",
+ "application/x-java-applet,version=1.1.1",
+ "application/x-java-applet,version=1.1.2",
+ "application/x-java-applet,version=1.1.3",
+ "application/x-java-applet,version=1.2",
+ "application/x-java-applet,version=1.2.1",
+ "application/x-java-applet,version=1.2.2",
+ "application/x-java-applet,version=1.3",
+ "application/x-java-applet,version=1.3.1",
+ "application/x-java-applet,version=1.4",
+ "application/x-java-applet,version=1.4.1",
+ "application/x-java-applet,version=1.4.2",
+ "application/x-java-applet,version=1.5",
+ "application/x-java-applet,version=1.6",
+ "application/x-java-bean",
+ "application/x-java-bean,version=1.1",
+ "application/x-java-bean,version=1.1.1",
+ "application/x-java-bean,version=1.1.2",
+ "application/x-java-bean,version=1.1.3",
+ "application/x-java-bean,version=1.2",
+ "application/x-java-bean,version=1.2.1",
+ "application/x-java-bean,version=1.2.2",
+ "application/x-java-bean,version=1.3",
+ "application/x-java-bean,version=1.3.1",
+ "application/x-java-bean,version=1.4",
+ "application/x-java-bean,version=1.4.1",
+ "application/x-java-bean,version=1.4.2",
+ "application/x-java-bean,version=1.5",
+ "application/x-java-bean,version=1.6",
+ "application/x-java-vm"
+ ],
+ "lang": "en-US",
+ "name": "Java(TM)",
+ "url": "http://java.com/download",
+ "displayurl": true
+ },
+ {
+ "mime_types": [
+ "audio/vnd.rn-realaudio",
+ "video/vnd.rn-realvideo",
+ "audio/x-pn-realaudio-plugin",
+ "audio/x-pn-realaudio"
+ ],
+ "lang": "en-US",
+ "name": "RealPlayer",
+ "url": "http://forms.real.com/real/realone/download.html?type=rpsp_us"
+ },
+ {
+ "mime_types": [
+ "application/futuresplash",
+ "application/x-shockwave-flash"
+ ],
+ "lang": "en-US",
+ "name": "Adobe Flash Player",
+ "url": "http://fpdownload.adobe.com/get/flashplayer/current/install_flash_player.exe"
+ },
+ {
+ "mime_types": [
+ "application/x-director"
+ ],
+ "lang": "en-US",
+ "name": "Adobe Shockwave Player",
+ "url": "http://fpdownload.macromedia.com/get/shockwave/default/english/win95nt/latest/Shockwave_Installer_Slim.exe"
+ },
+ {
+ "mime_types": [
+ "application/pdf",
+ "application/vnd.adobe.x-mars",
+ "application/vnd.adobe.xdp+xml",
+ "application/vnd.adobe.xfd+xml",
+ "application/vnd.adobe.xfdf",
+ "application/vnd.fdf"
+ ],
+ "lang": "en-US",
+ "name": "Adobe Reader",
+ "url": "http://ardownload.adobe.com/pub/adobe/reader/win/9.x/9.1/enu/AdbeRdr910_en_US.exe"
+ },
+ {
+ "mime_types": [
+ "application/sdp",
+ "application/x-mpeg",
+ "application/x-rtsp",
+ "application/x-sdp",
+ "audio/3ggp",
+ "audio/3ggp2",
+ "audio/aac",
+ "audio/ac3",
+ "audio/aiff",
+ "audio/amr",
+ "audio/basic",
+ "audio/mid",
+ "audio/midi",
+ "audio/mp4",
+ "audio/mpeg",
+ "audio/vnd.qcelp",
+ "audio/wav",
+ "audio/x-aac",
+ "audio/x-ac3",
+ "audio/x-aiff",
+ "audio/x-caf",
+ "audio/x-gsm",
+ "audio/x-m4a",
+ "audio/x-m4b",
+ "audio/x-m4p",
+ "audio/x-midi",
+ "audio/x-mpeg",
+ "audio/x-wav",
+ "image/jp2",
+ "image/jpeg2000",
+ "image/jpeg2000-image",
+ "image/pict",
+ "image/png",
+ "image/x-jpeg2000-image",
+ "image/x-macpaint",
+ "image/x-pict",
+ "image/x-png",
+ "image/x-quicktime",
+ "image/x-sgi",
+ "image/x-targa",
+ "video/3ggp",
+ "video/3ggp2",
+ "video/flc",
+ "video/mp4",
+ "video/mpeg",
+ "video/quicktime",
+ "video/sd-video",
+ "video/x-m4v",
+ "video/x-mpeg"
+ ],
+ "lang": "en-US",
+ "name": "QuickTime Player",
+ "url": "http://appldnld.apple.com.edgesuite.net/content.info.apple.com/QuickTime/061-6118.20090601.Pq3V9/QuickTimeInstaller.exe"
+ },
+ {
+ "mime_types": [
+ "application/asx",
+ "application/x-mplayer2",
+ "application/x-ms-wmp",
+ "audio/x-ms-wax",
+ "audio/x-ms-wma",
+ "video/x-ms-asf",
+ "video/x-ms-asf-plugin",
+ "video/x-ms-wm",
+ "video/x-ms-wmv",
+ "video/x-ms-wvx"
+ ],
+ "lang": "en-US",
+ "name": "Windows Media Player",
+ "url": "http://port25.technet.com/videos/downloads/wmpfirefoxplugin.exe"
+ },
+ {
+ "mime_types": [
+ "video/divx",
+ "video/x-matroska"
+ ],
+ "lang": "en-US",
+ "name": "DivX Web Player",
+ "url": "http://download.divx.com/player/divxdotcom/DivXWebPlayerInstaller.exe"
+ }
+ ]
+} \ No newline at end of file
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 5f298da..8e6f2a0 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1725,6 +1725,8 @@
'browser/plugin_data_remover_helper.h',
'browser/plugin_download_helper.cc',
'browser/plugin_download_helper.h',
+ 'browser/plugin_finder.cc',
+ 'browser/plugin_finder.h',
'browser/plugin_installer_infobar_delegate.cc',
'browser/plugin_installer_infobar_delegate.h',
'browser/plugin_observer.cc',
@@ -4173,8 +4175,6 @@
['exclude', '^browser/platform_util_win.cc'],
['exclude', '^browser/plugin_download_helper.cc'],
['exclude', '^browser/plugin_download_helper.h'],
- ['exclude', '^browser/plugin_installer_infobar_delegate.cc'],
- ['exclude', '^browser/plugin_installer_infobar_delegate.h'],
['exclude', '^browser/renderer_host/render_widget_host_view_views*'],
['exclude', '^browser/tab_contents/web_drag_source_win.cc'],
['exclude', '^browser/tab_contents/web_drag_source_win.h'],
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index a4e5bea..cdaa14d 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -423,6 +423,21 @@ IPC_SYNC_MESSAGE_CONTROL4_3(ChromeViewHostMsg_GetPluginInfo,
webkit::WebPluginInfo /* plugin */,
std::string /* actual_mime_type */)
+// Tells the browser to search for a plug-in that can handle the given MIME
+// type. The result will be sent asynchronously to the routing ID
+// |placeholder_id|.
+IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_FindMissingPlugin,
+ int /* placeholder_id */,
+ std::string /* mime_type */)
+
+// Notifies a missing plug-in placeholder that a plug-in with name |plugin_name|
+// has been found.
+IPC_MESSAGE_ROUTED1(ChromeViewMsg_FoundMissingPlugin,
+ string16 /* plugin_name */)
+
+// Notifies a missing plug-in placeholder that no plug-in has been found.
+IPC_MESSAGE_ROUTED0(ChromeViewMsg_DidNotFindMissingPlugin)
+
// Specifies the URL as the first parameter (a wstring) and thumbnail as
// binary data as the second parameter.
IPC_MESSAGE_ROUTED3(ChromeViewHostMsg_Thumbnail,
diff --git a/chrome/renderer/plugins/missing_plugin.cc b/chrome/renderer/plugins/missing_plugin.cc
index 9773414..6b8acf9 100644
--- a/chrome/renderer/plugins/missing_plugin.cc
+++ b/chrome/renderer/plugins/missing_plugin.cc
@@ -4,20 +4,26 @@
#include "chrome/renderer/plugins/missing_plugin.h"
+#include "base/json/string_escape.h"
#include "base/string_piece.h"
#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/jstemplate_builder.h"
+#include "chrome/common/render_messages.h"
#include "chrome/renderer/custom_menu_commands.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
#include "grit/generated_resources.h"
#include "grit/renderer_resources.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebMenuItemInfo.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "webkit/plugins/npapi/plugin_group.h"
@@ -28,9 +34,11 @@ using WebKit::WebMenuItemInfo;
using WebKit::WebPlugin;
using WebKit::WebPluginParams;
using WebKit::WebPoint;
+using WebKit::WebScriptSource;
using WebKit::WebString;
using WebKit::WebVector;
using content::RenderThread;
+using content::RenderView;
using webkit::WebViewPlugin;
namespace {
@@ -38,7 +46,7 @@ const MissingPlugin* g_last_active_menu = NULL;
}
// static
-WebViewPlugin* MissingPlugin::Create(content::RenderView* render_view,
+WebViewPlugin* MissingPlugin::Create(RenderView* render_view,
WebFrame* frame,
const WebPluginParams& params) {
const base::StringPiece template_html(
@@ -46,27 +54,32 @@ WebViewPlugin* MissingPlugin::Create(content::RenderView* render_view,
IDR_BLOCKED_PLUGIN_HTML));
DictionaryValue values;
- values.SetString("message", l10n_util::GetStringUTF8(IDS_PLUGIN_NOT_FOUND));
+ values.SetString("message", l10n_util::GetStringUTF8(IDS_PLUGIN_SEARCHING));
// "t" is the id of the templates root node.
std::string html_data =
jstemplate_builder::GetI18nTemplateHtml(template_html, &values);
// |missing_plugin| will destroy itself when its WebViewPlugin is going away.
- MissingPlugin* missing_plugin = new MissingPlugin(render_view, frame, params,
- html_data);
+ MissingPlugin* missing_plugin = new MissingPlugin(
+ render_view, frame, params, html_data);
return missing_plugin->plugin();
}
-MissingPlugin::MissingPlugin(content::RenderView* render_view,
+MissingPlugin::MissingPlugin(RenderView* render_view,
WebFrame* frame,
const WebPluginParams& params,
const std::string& html_data)
: PluginPlaceholder(render_view, frame, params, html_data),
- mime_type_(params.mimeType) {
+ mime_type_(params.mimeType),
+ placeholder_routing_id_(RenderThread::Get()->GenerateRoutingID()) {
+ RenderThread::Get()->AddRoute(placeholder_routing_id_, this);
+ RenderThread::Get()->Send(new ChromeViewHostMsg_FindMissingPlugin(
+ routing_id(), placeholder_routing_id_, mime_type_.utf8()));
}
MissingPlugin::~MissingPlugin() {
+ RenderThread::Get()->RemoveRoute(placeholder_routing_id_);
}
void MissingPlugin::BindWebFrame(WebFrame* frame) {
@@ -111,6 +124,41 @@ void MissingPlugin::ShowContextMenu(const WebKit::WebMouseEvent& event) {
g_last_active_menu = this;
}
+bool MissingPlugin::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(MissingPlugin, message)
+ IPC_MESSAGE_HANDLER(ChromeViewMsg_FoundMissingPlugin,
+ OnFoundMissingPlugin)
+ IPC_MESSAGE_HANDLER(ChromeViewMsg_DidNotFindMissingPlugin,
+ OnDidNotFindMissingPlugin)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void MissingPlugin::OnFoundMissingPlugin(const string16& plugin_name) {
+ SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_FOUND, plugin_name));
+}
+
+void MissingPlugin::OnDidNotFindMissingPlugin() {
+ SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_FOUND));
+}
+
+void MissingPlugin::SetMessage(const string16& message) {
+ message_ = message;
+ if (!plugin()->web_view()->mainFrame()->isLoading())
+ UpdateMessage();
+}
+
+void MissingPlugin::UpdateMessage() {
+ DCHECK(!plugin()->web_view()->mainFrame()->isLoading());
+ std::string script = "window.setMessage(" +
+ base::GetDoubleQuotedJson(message_) + ")";
+ plugin()->web_view()->mainFrame()->executeScript(
+ WebScriptSource(ASCIIToUTF16(script)));
+}
+
void MissingPlugin::ContextMenuAction(unsigned id) {
if (g_last_active_menu != this)
return;
@@ -122,3 +170,7 @@ void MissingPlugin::ContextMenuAction(unsigned id) {
}
}
+void MissingPlugin::DidFinishLoading() {
+ if (message_.length() > 0)
+ UpdateMessage();
+}
diff --git a/chrome/renderer/plugins/missing_plugin.h b/chrome/renderer/plugins/missing_plugin.h
index 7b3351f..399cfbd 100644
--- a/chrome/renderer/plugins/missing_plugin.h
+++ b/chrome/renderer/plugins/missing_plugin.h
@@ -6,9 +6,14 @@
#define CHROME_RENDERER_PLUGINS_MISSING_PLUGIN_H_
#pragma once
+#include "base/string16.h"
#include "chrome/renderer/plugins/plugin_placeholder.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+namespace content {
+class RenderThread;
+}
+
class MissingPlugin : public PluginPlaceholder {
public:
// Creates a new WebViewPlugin with a MissingPlugin as a delegate.
@@ -27,14 +32,30 @@ class MissingPlugin : public PluginPlaceholder {
// WebViewPlugin::Delegate methods:
virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE;
virtual void ShowContextMenu(const WebKit::WebMouseEvent&) OVERRIDE;
+ virtual void DidFinishLoading() OVERRIDE;
+
+ // IPC::Channel::Listener methods:
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
// content::RenderViewObserver methods:
virtual void ContextMenuAction(unsigned id) OVERRIDE;
void HideCallback(const CppArgumentList& args, CppVariant* result);
+ void OnFoundMissingPlugin(const string16& plugin_name);
+ void OnDidNotFindMissingPlugin();
+
+ void SetMessage(const string16& message);
+ void UpdateMessage();
+
WebKit::WebString mime_type_;
+ // |routing_id()| is the routing ID of our associated RenderView, but we have
+ // a separate routing ID for messages specific to this placeholder.
+ int32 placeholder_routing_id_;
+
+ string16 message_;
+
DISALLOW_COPY_AND_ASSIGN(MissingPlugin);
};
diff --git a/chrome/renderer/plugins/plugin_placeholder.cc b/chrome/renderer/plugins/plugin_placeholder.cc
index 4bc97a6..ffc9523 100644
--- a/chrome/renderer/plugins/plugin_placeholder.cc
+++ b/chrome/renderer/plugins/plugin_placeholder.cc
@@ -124,3 +124,6 @@ void PluginPlaceholder::WillDestroyPlugin() {
void PluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) {
}
+
+void PluginPlaceholder::DidFinishLoading() {
+}
diff --git a/chrome/renderer/plugins/plugin_placeholder.h b/chrome/renderer/plugins/plugin_placeholder.h
index 009d300..fde0c47 100644
--- a/chrome/renderer/plugins/plugin_placeholder.h
+++ b/chrome/renderer/plugins/plugin_placeholder.h
@@ -44,6 +44,7 @@ class PluginPlaceholder : public content::RenderViewObserver,
virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE;
virtual void WillDestroyPlugin() OVERRIDE;
virtual void ShowContextMenu(const WebKit::WebMouseEvent& event) OVERRIDE;
+ virtual void DidFinishLoading() OVERRIDE;
private:
WebKit::WebFrame* frame_;
diff --git a/chrome/renderer/resources/blocked_plugin.html b/chrome/renderer/resources/blocked_plugin.html
index 6f8e8620..92fe9d0 100644
--- a/chrome/renderer/resources/blocked_plugin.html
+++ b/chrome/renderer/resources/blocked_plugin.html
@@ -5,6 +5,9 @@
function debug(msg) {
document.getElementById('debug').textContent = msg;
}
+function setMessage(msg) {
+ document.getElementById('message').textContent = msg;
+}
</script>
<style>
body {
@@ -76,7 +79,7 @@ p {
<div i18n-values="title:name" id="outer">
<div id="inner">
<div><img id="plugin_icon" src="plugin_blocked.png" /></div>
-<h1 i18n-content="message">PLUGIN_BLOCKED</h1>
+<h1 id="message" i18n-content="message"></h1>
<p id="debug"> </p>
</div>
<div id="close" i18n-values="title:hide" onclick="plugin.hide();" />
diff --git a/webkit/plugins/webview_plugin.cc b/webkit/plugins/webview_plugin.cc
index f43fc2c..5098564 100644
--- a/webkit/plugins/webview_plugin.cc
+++ b/webkit/plugins/webview_plugin.cc
@@ -243,6 +243,11 @@ WebURLError WebViewPlugin::cancelledError(WebFrame* frame,
return error;
}
+void WebViewPlugin::didFinishLoad(WebFrame* frame) {
+ if (delegate_)
+ delegate_->DidFinishLoading();
+}
+
void WebViewPlugin::didReceiveResponse(WebFrame* frame,
unsigned identifier,
const WebURLResponse& response) {
diff --git a/webkit/plugins/webview_plugin.h b/webkit/plugins/webview_plugin.h
index 1d2a35d..7146d98 100644
--- a/webkit/plugins/webview_plugin.h
+++ b/webkit/plugins/webview_plugin.h
@@ -46,6 +46,9 @@ class WebViewPlugin: public WebKit::WebPlugin, public WebKit::WebViewClient,
// Called upon a context menu event.
virtual void ShowContextMenu(const WebKit::WebMouseEvent&) = 0;
+
+ // Called when the WebFrame finished loading.
+ virtual void DidFinishLoading() = 0;
};
explicit WebViewPlugin(Delegate* delegate);
@@ -126,6 +129,8 @@ class WebViewPlugin: public WebKit::WebPlugin, public WebKit::WebViewClient,
virtual WebKit::WebURLError cancelledError(
WebKit::WebFrame* frame, const WebKit::WebURLRequest& request);
+ virtual void didFinishLoad(WebKit::WebFrame*);
+
// This method is defined in WebPlugin as well as in WebFrameClient, but with
// different parameters. We only care about implementing the WebPlugin
// version, so we implement this method and call the default in WebFrameClient