summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/extension_browsertests_misc.cc51
-rw-r--r--chrome/browser/plugin_service.cc32
-rw-r--r--chrome/common/render_messages_internal.h6
-rw-r--r--chrome/renderer/render_thread.cc4
-rw-r--r--chrome/renderer/render_thread.h2
-rw-r--r--chrome/test/data/extensions/uitest/plugins/README2
-rw-r--r--chrome/test/data/extensions/uitest/plugins/manifest.json6
-rwxr-xr-xchrome/test/data/extensions/uitest/plugins/plugin.dllbin0 -> 92160 bytes
-rw-r--r--chrome/test/data/extensions/uitest/plugins/test.html16
-rw-r--r--webkit/api/public/WebKit.h5
-rw-r--r--webkit/api/src/WebKit.cpp4
-rw-r--r--webkit/glue/plugins/plugin_list.cc9
-rw-r--r--webkit/glue/plugins/plugin_list.h5
13 files changed, 123 insertions, 19 deletions
diff --git a/chrome/browser/extensions/extension_browsertests_misc.cc b/chrome/browser/extensions/extension_browsertests_misc.cc
index 490ef9c..153d0a1 100644
--- a/chrome/browser/extensions/extension_browsertests_misc.cc
+++ b/chrome/browser/extensions/extension_browsertests_misc.cc
@@ -627,3 +627,54 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, WindowOpenNoPrivileges) {
newtab->render_view_host(), L"", L"testExtensionApi()", &result);
EXPECT_FALSE(result);
}
+
+// Tests that a renderer's plugin list is properly updated when we load and
+// unload an extension that contains a plugin.
+// TODO(mpcomplete): need cross platform plugin support.
+#if defined(OS_WIN)
+IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, PluginLoadUnload) {
+ FilePath extension_dir =
+ test_data_dir_.AppendASCII("uitest").AppendASCII("plugins");
+
+ ui_test_utils::NavigateToURL(browser(),
+ net::FilePathToFileURL(extension_dir.AppendASCII("test.html")));
+ TabContents* tab = browser()->GetSelectedTabContents();
+
+ // With no extensions, the plugin should not be loaded.
+ bool result = false;
+ ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ tab->render_view_host(), L"", L"testPluginWorks()", &result);
+ EXPECT_FALSE(result);
+
+ ExtensionsService* service = browser()->profile()->GetExtensionsService();
+ ASSERT_TRUE(LoadExtension(extension_dir));
+ EXPECT_EQ(1u, service->extensions()->size());
+ // Now the plugin should be in the cache, but we have to reload the page for
+ // it to work.
+ ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ tab->render_view_host(), L"", L"testPluginWorks()", &result);
+ EXPECT_FALSE(result);
+ browser()->Reload();
+ ui_test_utils::WaitForNavigationInCurrentTab(browser());
+ ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ tab->render_view_host(), L"", L"testPluginWorks()", &result);
+ EXPECT_TRUE(result);
+
+ EXPECT_EQ(1u, service->extensions()->size());
+ UnloadExtension(service->extensions()->at(0)->id());
+ EXPECT_EQ(0u, service->extensions()->size());
+
+ // Now the plugin should be out of the cache again, but existing pages will
+ // still work until we reload them.
+
+ ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ tab->render_view_host(), L"", L"testPluginWorks()", &result);
+ EXPECT_TRUE(result);
+ browser()->Reload();
+ ui_test_utils::WaitForNavigationInCurrentTab(browser());
+
+ ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ tab->render_view_host(), L"", L"testPluginWorks()", &result);
+ EXPECT_FALSE(result);
+}
+#endif
diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc
index 1d767bd..42a67e9 100644
--- a/chrome/browser/plugin_service.cc
+++ b/chrome/browser/plugin_service.cc
@@ -178,6 +178,13 @@ FilePath PluginService::GetPluginPath(const GURL& url,
return FilePath();
}
+static void PurgePluginListCache(bool reload_pages) {
+ for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
+ !it.IsAtEnd(); it.Advance()) {
+ it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
+ }
+}
+
void PluginService::OnWaitableEventSignaled(
base::WaitableEvent* waitable_event) {
#if defined(OS_WIN)
@@ -188,11 +195,7 @@ void PluginService::OnWaitableEventSignaled(
}
NPAPI::PluginList::Singleton()->ResetPluginsLoaded();
-
- for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
- !it.IsAtEnd(); it.Advance()) {
- it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache());
- }
+ PurgePluginListCache(true);
#endif // defined(OS_WIN)
}
@@ -206,20 +209,33 @@ void PluginService::Observe(NotificationType type,
// have a stale version by the time extensions are loaded.
// See: http://code.google.com/p/chromium/issues/detail?id=12306
Extension* extension = Details<Extension>(details).ptr();
+ bool plugins_changed = false;
for (size_t i = 0; i < extension->plugins().size(); ++i ) {
const Extension::PluginInfo& plugin = extension->plugins()[i];
NPAPI::PluginList::Singleton()->ResetPluginsLoaded();
NPAPI::PluginList::Singleton()->AddExtraPluginPath(plugin.path);
+ plugins_changed = true;
if (!plugin.is_public)
private_plugins_[plugin.path] = extension->url();
}
+ if (plugins_changed)
+ PurgePluginListCache(false);
break;
}
case NotificationType::EXTENSION_UNLOADED: {
- // TODO(aa): Implement this. Also, will it be possible to delete the
- // extension folder if this isn't unloaded?
- // See: http://code.google.com/p/chromium/issues/detail?id=12306
+ Extension* extension = Details<Extension>(details).ptr();
+ bool plugins_changed = false;
+ for (size_t i = 0; i < extension->plugins().size(); ++i ) {
+ const Extension::PluginInfo& plugin = extension->plugins()[i];
+ NPAPI::PluginList::Singleton()->ResetPluginsLoaded();
+ NPAPI::PluginList::Singleton()->RemoveExtraPluginPath(plugin.path);
+ plugins_changed = true;
+ if (!plugin.is_public)
+ private_plugins_.erase(plugin.path);
+ }
+ if (plugins_changed)
+ PurgePluginListCache(false);
break;
}
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 700f3a1..9cfdf77 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -455,8 +455,10 @@ IPC_BEGIN_MESSAGES(View)
// Install the first missing pluign.
IPC_MESSAGE_ROUTED0(ViewMsg_InstallMissingPlugin)
- // Tells the renderer to empty its plugin list cache.
- IPC_MESSAGE_CONTROL0(ViewMsg_PurgePluginListCache)
+ // Tells the renderer to empty its plugin list cache, optional reloading
+ // pages containing plugins.
+ IPC_MESSAGE_CONTROL1(ViewMsg_PurgePluginListCache,
+ bool /* reload_pages */)
IPC_MESSAGE_ROUTED1(ViewMsg_RunFileChooserResponse,
std::vector<FilePath> /* selected files */)
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index e7c04ed..788b852 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -490,12 +490,12 @@ void RenderThread::OnExtensionMessageInvoke(const std::string& function_name,
RendererExtensionBindings::Invoke(function_name, args, NULL);
}
-void RenderThread::OnPurgePluginListCache() {
+void RenderThread::OnPurgePluginListCache(bool reload_pages) {
// The call below will cause a GetPlugins call with refresh=true, but at this
// point we already know that the browser has refreshed its list, so disable
// refresh temporarily to prevent each renderer process causing the list to be
// regenerated.
plugin_refresh_allowed_ = false;
- WebKit::resetPluginCache();
+ WebKit::resetPluginCache(reload_pages);
plugin_refresh_allowed_ = true;
}
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index 007bac4..ab9a0b2 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -162,7 +162,7 @@ class RenderThread : public RenderThreadBase,
void OnExtensionMessageInvoke(const std::string& function_name,
const ListValue& args);
- void OnPurgePluginListCache();
+ void OnPurgePluginListCache(bool reload_pages);
// Gather usage statistics from the in-memory cache and inform our host.
// These functions should be call periodically so that the host can make
diff --git a/chrome/test/data/extensions/uitest/plugins/README b/chrome/test/data/extensions/uitest/plugins/README
new file mode 100644
index 0000000..469bb0d
--- /dev/null
+++ b/chrome/test/data/extensions/uitest/plugins/README
@@ -0,0 +1,2 @@
+Note: plugin.dll is a Release build of npapi_layout_test_plugin with the mime
+type changed, so it doesn't conflict with the original DLL.
diff --git a/chrome/test/data/extensions/uitest/plugins/manifest.json b/chrome/test/data/extensions/uitest/plugins/manifest.json
new file mode 100644
index 0000000..94fb7b6
--- /dev/null
+++ b/chrome/test/data/extensions/uitest/plugins/manifest.json
@@ -0,0 +1,6 @@
+{
+ "version": "1.0.0.0",
+ "name": "NPAPI plugin test",
+ "description": "An extension for an extension UITest.",
+ "plugins": [{"path": "plugin.dll", "public": true}]
+}
diff --git a/chrome/test/data/extensions/uitest/plugins/plugin.dll b/chrome/test/data/extensions/uitest/plugins/plugin.dll
new file mode 100755
index 0000000..928e62a
--- /dev/null
+++ b/chrome/test/data/extensions/uitest/plugins/plugin.dll
Binary files differ
diff --git a/chrome/test/data/extensions/uitest/plugins/test.html b/chrome/test/data/extensions/uitest/plugins/test.html
new file mode 100644
index 0000000..6226916
--- /dev/null
+++ b/chrome/test/data/extensions/uitest/plugins/test.html
@@ -0,0 +1,16 @@
+<embed id="plugin"
+ type="application/x-extension-test"
+ style="width:100; height:100">
+</embed>
+<script>
+ function testPluginWorks() {
+ var plug = document.getElementById("plugin");
+ var success = false;
+ if (plug && plug.testInvokeDefault) {
+ plug.testInvokeDefault(function(str) {
+ success = true;
+ });
+ }
+ window.domAutomationController.send(success);
+ }
+</script>
diff --git a/webkit/api/public/WebKit.h b/webkit/api/public/WebKit.h
index e0fc2b7..93c8625 100644
--- a/webkit/api/public/WebKit.h
+++ b/webkit/api/public/WebKit.h
@@ -95,8 +95,9 @@ namespace WebKit {
// Enables HTML5 media support.
WEBKIT_API void enableMediaPlayer();
- // Purge the plugin list cache.
- WEBKIT_API void resetPluginCache();
+ // Purge the plugin list cache. If |reloadPages| is true, any pages
+ // containing plugins will be reloaded after refreshing the plugin list.
+ WEBKIT_API void resetPluginCache(bool reloadPages);
// Enables HTML5 database support.
WEBKIT_API void enableDatabases();
diff --git a/webkit/api/src/WebKit.cpp b/webkit/api/src/WebKit.cpp
index 8bdf2a8..877e5c9 100644
--- a/webkit/api/src/WebKit.cpp
+++ b/webkit/api/src/WebKit.cpp
@@ -135,9 +135,9 @@ void enableMediaPlayer()
#endif
}
-void resetPluginCache()
+void resetPluginCache(bool reloadPages)
{
- WebCore::Page::refreshPlugins(true);
+ WebCore::Page::refreshPlugins(reloadPages);
}
void enableDatabases()
diff --git a/webkit/glue/plugins/plugin_list.cc b/webkit/glue/plugins/plugin_list.cc
index 467f68e..338b1f0 100644
--- a/webkit/glue/plugins/plugin_list.cc
+++ b/webkit/glue/plugins/plugin_list.cc
@@ -39,6 +39,15 @@ void PluginList::AddExtraPluginPath(const FilePath& plugin_path) {
extra_plugin_paths_.push_back(plugin_path);
}
+void PluginList::RemoveExtraPluginPath(const FilePath& plugin_path) {
+ AutoLock lock(lock_);
+ std::vector<FilePath>::iterator it =
+ std::find(extra_plugin_paths_.begin(), extra_plugin_paths_.end(),
+ plugin_path);
+ if (it != extra_plugin_paths_.end())
+ extra_plugin_paths_.erase(it);
+}
+
void PluginList::AddExtraPluginDir(const FilePath& plugin_dir) {
AutoLock lock(lock_);
extra_plugin_dirs_.push_back(plugin_dir);
diff --git a/webkit/glue/plugins/plugin_list.h b/webkit/glue/plugins/plugin_list.h
index 7fc2b58..ddb30cf 100644
--- a/webkit/glue/plugins/plugin_list.h
+++ b/webkit/glue/plugins/plugin_list.h
@@ -80,9 +80,10 @@ class PluginList {
// plugins.
void ResetPluginsLoaded();
- // Add an extra plugin to load when we actually do the loading. Must be
- // called before the plugins have been loaded.
+ // Add/Remove an extra plugin to load when we actually do the loading. Must
+ // be called before the plugins have been loaded.
void AddExtraPluginPath(const FilePath& plugin_path);
+ void RemoveExtraPluginPath(const FilePath& plugin_path);
// Same as above, but specifies a directory in which to search for plugins.
void AddExtraPluginDir(const FilePath& plugin_dir);