diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-21 22:05:45 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-21 22:05:45 +0000 |
commit | b78e168b1640e456e1fc5a1ca8956a4a50c7df94 (patch) | |
tree | cbadab016871c254617ec26ab2d4c6987033b1c4 /chrome | |
parent | a66e24c34a22a4a183b91ad80d74e896a4f4db5f (diff) | |
download | chromium_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.cc | 51 | ||||
-rw-r--r-- | chrome/browser/plugin_service.cc | 32 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 6 | ||||
-rw-r--r-- | chrome/renderer/render_thread.cc | 4 | ||||
-rw-r--r-- | chrome/renderer/render_thread.h | 2 | ||||
-rw-r--r-- | chrome/test/data/extensions/uitest/plugins/README | 2 | ||||
-rw-r--r-- | chrome/test/data/extensions/uitest/plugins/manifest.json | 6 | ||||
-rwxr-xr-x | chrome/test/data/extensions/uitest/plugins/plugin.dll | bin | 0 -> 92160 bytes | |||
-rw-r--r-- | chrome/test/data/extensions/uitest/plugins/test.html | 16 |
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 Binary files differnew file mode 100755 index 0000000..928e62a --- /dev/null +++ b/chrome/test/data/extensions/uitest/plugins/plugin.dll 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> |