diff options
-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 | ||||
-rw-r--r-- | webkit/api/public/WebKit.h | 5 | ||||
-rw-r--r-- | webkit/api/src/WebKit.cpp | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_list.cc | 9 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_list.h | 5 |
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 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> 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); |