summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-21 22:05:45 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-21 22:05:45 +0000
commitb78e168b1640e456e1fc5a1ca8956a4a50c7df94 (patch)
treecbadab016871c254617ec26ab2d4c6987033b1c4 /chrome
parenta66e24c34a22a4a183b91ad80d74e896a4f4db5f (diff)
downloadchromium_src-b78e168b1640e456e1fc5a1ca8956a4a50c7df94.zip
chromium_src-b78e168b1640e456e1fc5a1ca8956a4a50c7df94.tar.gz
chromium_src-b78e168b1640e456e1fc5a1ca8956a4a50c7df94.tar.bz2
Update renderer plugin cache when we load/unload extensions with plugins.
BUG=12306 TEST=Load and unload extensions that contain plugins and visit pages that use them. Also covered by tests. Review URL: http://codereview.chromium.org/201111 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26748 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-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
9 files changed, 106 insertions, 13 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>