diff options
Diffstat (limited to 'webkit/glue/plugins/plugin_lib.cc')
-rw-r--r-- | webkit/glue/plugins/plugin_lib.cc | 349 |
1 files changed, 0 insertions, 349 deletions
diff --git a/webkit/glue/plugins/plugin_lib.cc b/webkit/glue/plugins/plugin_lib.cc deleted file mode 100644 index 4ae4da4..0000000 --- a/webkit/glue/plugins/plugin_lib.cc +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright (c) 2010 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 "webkit/glue/plugins/plugin_lib.h" - -#include "base/logging.h" -#include "base/message_loop.h" -#include "base/metrics/stats_counters.h" -#include "base/string_util.h" -#include "webkit/glue/webkit_glue.h" -#include "webkit/glue/plugins/plugin_instance.h" -#include "webkit/glue/plugins/plugin_host.h" -#include "webkit/glue/plugins/plugin_list.h" - -namespace NPAPI { - -const char kPluginLibrariesLoadedCounter[] = "PluginLibrariesLoaded"; -const char kPluginInstancesActiveCounter[] = "PluginInstancesActive"; - -// A list of all the instantiated plugins. -static std::vector<scoped_refptr<PluginLib> >* g_loaded_libs; - -PluginLib* PluginLib::CreatePluginLib(const FilePath& filename) { - // We can only have one PluginLib object per plugin as it controls the per - // instance function calls (i.e. NP_Initialize and NP_Shutdown). So we keep - // a map of PluginLib objects. - if (!g_loaded_libs) - g_loaded_libs = new std::vector<scoped_refptr<PluginLib> >; - - for (size_t i = 0; i < g_loaded_libs->size(); ++i) { - if ((*g_loaded_libs)[i]->plugin_info().path == filename) - return (*g_loaded_libs)[i]; - } - - WebPluginInfo info; - const PluginEntryPoints* entry_points = NULL; - if (!PluginList::Singleton()->ReadPluginInfo(filename, &info, &entry_points)) - return NULL; - - return new PluginLib(info, entry_points); -} - -void PluginLib::UnloadAllPlugins() { - if (g_loaded_libs) { - // PluginLib::Unload() can remove items from the list and even delete - // the list when it removes the last item, so we must work with a copy - // of the list so that we don't get the carpet removed under our feet. - std::vector<scoped_refptr<PluginLib> > loaded_libs(*g_loaded_libs); - for (size_t i = 0; i < loaded_libs.size(); ++i) - loaded_libs[i]->Unload(); - - if (g_loaded_libs && g_loaded_libs->empty()) { - delete g_loaded_libs; - g_loaded_libs = NULL; - } - } -} - -void PluginLib::ShutdownAllPlugins() { - if (g_loaded_libs) { - for (size_t i = 0; i < g_loaded_libs->size(); ++i) - (*g_loaded_libs)[i]->Shutdown(); - } -} - -PluginLib::PluginLib(const WebPluginInfo& info, - const PluginEntryPoints* entry_points) - : web_plugin_info_(info), - library_(NULL), - initialized_(false), - saved_data_(0), - instance_count_(0), - skip_unload_(false) { - base::StatsCounter(kPluginLibrariesLoadedCounter).Increment(); - memset(static_cast<void*>(&plugin_funcs_), 0, sizeof(plugin_funcs_)); - g_loaded_libs->push_back(make_scoped_refptr(this)); - - if (entry_points) { - internal_ = true; - entry_points_ = *entry_points; - } else { - internal_ = false; - // We will read the entry points from the plugin directly. - memset(&entry_points_, 0, sizeof(entry_points_)); - } -} - -PluginLib::~PluginLib() { - base::StatsCounter(kPluginLibrariesLoadedCounter).Decrement(); - if (saved_data_ != 0) { - // TODO - delete the savedData object here - } -} - -NPPluginFuncs* PluginLib::functions() { - return &plugin_funcs_; -} - -NPError PluginLib::NP_Initialize() { - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value() - << "): initialized=" << initialized_; - if (initialized_) - return NPERR_NO_ERROR; - - if (!Load()) - return NPERR_MODULE_LOAD_FAILED_ERROR; - - PluginHost* host = PluginHost::Singleton(); - if (host == 0) - return NPERR_GENERIC_ERROR; - -#if defined(OS_POSIX) && !defined(OS_MACOSX) - NPError rv = entry_points_.np_initialize(host->host_functions(), - &plugin_funcs_); -#else - NPError rv = entry_points_.np_initialize(host->host_functions()); -#if defined(OS_MACOSX) - // On the Mac, we need to get entry points after calling np_initialize to - // match the behavior of other browsers. - if (rv == NPERR_NO_ERROR) { - rv = entry_points_.np_getentrypoints(&plugin_funcs_); - } -#endif // OS_MACOSX -#endif - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value() - << "): result=" << rv; - initialized_ = (rv == NPERR_NO_ERROR); - return rv; -} - -void PluginLib::NP_Shutdown(void) { - DCHECK(initialized_); - entry_points_.np_shutdown(); -} - -void PluginLib::PreventLibraryUnload() { - skip_unload_ = true; -} - -PluginInstance* PluginLib::CreateInstance(const std::string& mime_type) { - PluginInstance* new_instance = new PluginInstance(this, mime_type); - instance_count_++; - base::StatsCounter(kPluginInstancesActiveCounter).Increment(); - DCHECK_NE(static_cast<PluginInstance*>(NULL), new_instance); - return new_instance; -} - -void PluginLib::CloseInstance() { - base::StatsCounter(kPluginInstancesActiveCounter).Decrement(); - instance_count_--; - // If a plugin is running in its own process it will get unloaded on process - // shutdown. - if ((instance_count_ == 0) && webkit_glue::IsPluginRunningInRendererProcess()) - Unload(); -} - -bool PluginLib::Load() { - if (library_) - return true; - - bool rv = false; - base::NativeLibrary library = 0; - - if (!internal_) { -#if defined(OS_WIN) - // This is to work around a bug in the Real player recorder plugin which - // intercepts LoadLibrary calls from chrome.dll and wraps NPAPI functions - // provided by the plugin. It crashes if the media player plugin is being - // loaded. Workaround is to load the dll dynamically by getting the - // LoadLibrary API address from kernel32.dll which bypasses the recorder - // plugin. - if (web_plugin_info_.name.find(L"Windows Media Player") != - std::wstring::npos) { - library = base::LoadNativeLibraryDynamically(web_plugin_info_.path); - } else { - library = base::LoadNativeLibrary(web_plugin_info_.path); - } -#else // OS_WIN - library = base::LoadNativeLibrary(web_plugin_info_.path); -#endif // OS_WIN - if (library == 0) { - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "Couldn't load plugin " << web_plugin_info_.path.value(); - return rv; - } - -#if defined(OS_MACOSX) - // According to the WebKit source, QuickTime at least requires us to call - // UseResFile on the plugin resources before loading. - if (library->bundle_resource_ref != -1) - UseResFile(library->bundle_resource_ref); -#endif - - rv = true; // assume success now - - entry_points_.np_initialize = - (NP_InitializeFunc)base::GetFunctionPointerFromNativeLibrary(library, - "NP_Initialize"); - if (entry_points_.np_initialize == 0) - rv = false; - -#if defined(OS_WIN) || defined(OS_MACOSX) - entry_points_.np_getentrypoints = - (NP_GetEntryPointsFunc)base::GetFunctionPointerFromNativeLibrary( - library, "NP_GetEntryPoints"); - if (entry_points_.np_getentrypoints == 0) - rv = false; -#endif - - entry_points_.np_shutdown = - (NP_ShutdownFunc)base::GetFunctionPointerFromNativeLibrary(library, - "NP_Shutdown"); - if (entry_points_.np_shutdown == 0) - rv = false; - } else { - rv = true; - } - - if (rv) { - plugin_funcs_.size = sizeof(plugin_funcs_); - plugin_funcs_.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; -#if !defined(OS_POSIX) - if (entry_points_.np_getentrypoints(&plugin_funcs_) != NPERR_NO_ERROR) - rv = false; -#else - // On Linux and Mac, we get the plugin entry points during NP_Initialize. -#endif - } - - if (!internal_) { - if (rv) { - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "Plugin " << web_plugin_info_.path.value() - << " loaded successfully."; - library_ = library; - } else { - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "Plugin " << web_plugin_info_.path.value() - << " failed to load, unloading."; - base::UnloadNativeLibrary(library); - } - } - - return rv; -} - -// This class implements delayed NP_Shutdown and FreeLibrary on the plugin dll. -class FreePluginLibraryTask : public Task { - public: - FreePluginLibraryTask(const FilePath& path, - base::NativeLibrary library, - NP_ShutdownFunc shutdown_func) - : path_(path), - library_(library), - NP_Shutdown_(shutdown_func) { - } - - ~FreePluginLibraryTask() {} - - void Run() { - if (NP_Shutdown_) { - // Don't call NP_Shutdown if the library has been reloaded since this task - // was posted. - bool reloaded = false; - if (g_loaded_libs) { - for (size_t i = 0; i < g_loaded_libs->size(); ++i) { - if ((*g_loaded_libs)[i]->plugin_info().path == path_) - reloaded = true; - } - } - if (!reloaded) - NP_Shutdown_(); - } - - if (library_) { - // Always call base::UnloadNativeLibrary so that the system reference - // count is decremented. - base::UnloadNativeLibrary(library_); - library_ = NULL; - } - } - - private: - FilePath path_; - base::NativeLibrary library_; - NP_ShutdownFunc NP_Shutdown_; - DISALLOW_COPY_AND_ASSIGN(FreePluginLibraryTask); -}; - -void PluginLib::Unload() { - if (!internal_ && library_) { - // In case of single process mode, a plugin can delete itself - // by executing a script. So delay the unloading of the library - // so that the plugin will have a chance to unwind. - bool defer_unload = webkit_glue::IsPluginRunningInRendererProcess(); - -/* TODO(dglazkov): Revisit when re-enabling the JSC build. -#if USE(JSC) - // The plugin NPAPI instances may still be around. Delay the - // NP_Shutdown and FreeLibrary calls at least till the next - // peek message. - defer_unload = true; -#endif -*/ - - if (defer_unload) { - FreePluginLibraryTask* free_library_task = - new FreePluginLibraryTask(web_plugin_info_.path, - skip_unload_ ? NULL : library_, - entry_points_.np_shutdown); - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "Scheduling delayed unload for plugin " - << web_plugin_info_.path.value(); - MessageLoop::current()->PostTask(FROM_HERE, free_library_task); - } else { - Shutdown(); - if (!skip_unload_) { - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "Unloading plugin " << web_plugin_info_.path.value(); - base::UnloadNativeLibrary(library_); - } - } - - library_ = NULL; - } - - for (size_t i = 0; i < g_loaded_libs->size(); ++i) { - if ((*g_loaded_libs)[i].get() == this) { - g_loaded_libs->erase(g_loaded_libs->begin() + i); - break; - } - } - if (g_loaded_libs->empty()) { - delete g_loaded_libs; - g_loaded_libs = NULL; - } -} - -void PluginLib::Shutdown() { - if (initialized_ && !internal_) { - NP_Shutdown(); - initialized_ = false; - } -} - -} // namespace NPAPI |