This source file includes following definitions.
- CreatePluginLib
- UnloadAllPlugins
- ShutdownAllPlugins
- defer_unload_
- NP_Initialize
- NP_Shutdown
- NP_ClearSiteData
- NP_GetSitesWithData
- PreventLibraryUnload
- CreateInstance
- CloseInstance
- Load
- FreePluginLibraryHelper
- Unload
- Shutdown
#include "content/child/npapi/plugin_lib.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/stats_counters.h"
#include "base/strings/string_util.h"
#include "content/child/npapi/plugin_host.h"
#include "content/child/npapi/plugin_instance.h"
#include "content/common/plugin_list.h"
namespace content {
const char kPluginLibrariesLoadedCounter[] = "PluginLibrariesLoaded";
const char kPluginInstancesActiveCounter[] = "PluginInstancesActive";
static std::vector<scoped_refptr<PluginLib> >* g_loaded_libs;
PluginLib* PluginLib::CreatePluginLib(const base::FilePath& filename) {
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].get();
}
WebPluginInfo info;
if (!PluginList::Singleton()->ReadPluginInfo(filename, &info))
return NULL;
return new PluginLib(info);
}
void PluginLib::UnloadAllPlugins() {
if (g_loaded_libs) {
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)
: web_plugin_info_(info),
library_(NULL),
initialized_(false),
saved_data_(0),
instance_count_(0),
skip_unload_(false),
defer_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));
memset(&entry_points_, 0, sizeof(entry_points_));
}
PluginLib::~PluginLib() {
base::StatsCounter(kPluginLibrariesLoadedCounter).Decrement();
if (saved_data_ != 0) {
}
}
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)
if (rv == NPERR_NO_ERROR) {
rv = entry_points_.np_getentrypoints(&plugin_funcs_);
}
#endif
#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();
}
NPError PluginLib::NP_ClearSiteData(const char* site,
uint64 flags,
uint64 max_age) {
DCHECK(initialized_);
if (plugin_funcs_.clearsitedata)
return plugin_funcs_.clearsitedata(site, flags, max_age);
return NPERR_INVALID_FUNCTABLE_ERROR;
}
char** PluginLib::NP_GetSitesWithData() {
DCHECK(initialized_);
if (plugin_funcs_.getsiteswithdata)
return plugin_funcs_.getsiteswithdata();
return NULL;
}
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 ((instance_count_ == 0) && !defer_unload_)
Unload();
}
bool PluginLib::Load() {
if (library_)
return true;
bool rv = false;
base::NativeLibrary library = 0;
base::NativeLibraryLoadError error;
#if defined(OS_WIN)
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, &error);
}
#else
library = base::LoadNativeLibrary(web_plugin_info_.path, &error);
#endif
if (!library) {
LOG_IF(ERROR, PluginList::DebugPluginLoading())
<< "Couldn't load plugin " << web_plugin_info_.path.value() << " "
<< error.ToString();
return rv;
}
#if defined(OS_MACOSX)
if (library->bundle_resource_ref != -1)
UseResFile(library->bundle_resource_ref);
#endif
rv = true;
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;
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
#endif
}
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;
}
void FreePluginLibraryHelper(const base::FilePath& path,
base::NativeLibrary library,
NP_ShutdownFunc shutdown_func) {
if (shutdown_func) {
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;
break;
}
}
}
if (!reloaded)
shutdown_func();
}
if (library) {
base::UnloadNativeLibrary(library);
}
}
void PluginLib::Unload() {
if (library_) {
if (!defer_unload_) {
LOG_IF(ERROR, PluginList::DebugPluginLoading())
<< "Scheduling delayed unload for plugin "
<< web_plugin_info_.path.value();
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&FreePluginLibraryHelper,
web_plugin_info_.path,
skip_unload_ ? NULL : library_,
entry_points_.np_shutdown));
} 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_) {
NP_Shutdown();
initialized_ = false;
}
}
}