15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/child/npapi/plugin_lib.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_counters.h"
117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/child/npapi/plugin_host.h"
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/child/npapi/plugin_instance.h"
14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/common/plugin_list.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace content {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPluginLibrariesLoadedCounter[] = "PluginLibrariesLoaded";
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPluginInstancesActiveCounter[] = "PluginInstancesActive";
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A list of all the instantiated plugins.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static std::vector<scoped_refptr<PluginLib> >* g_loaded_libs;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PluginLib* PluginLib::CreatePluginLib(const base::FilePath& filename) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We can only have one PluginLib object per plugin as it controls the per
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instance function calls (i.e. NP_Initialize and NP_Shutdown).  So we keep
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a map of PluginLib objects.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_loaded_libs)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_loaded_libs = new std::vector<scoped_refptr<PluginLib> >;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < g_loaded_libs->size(); ++i) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*g_loaded_libs)[i]->plugin_info().path == filename)
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return (*g_loaded_libs)[i].get();
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  WebPluginInfo info;
37ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!PluginList::Singleton()->ReadPluginInfo(filename, &info))
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return new PluginLib(info);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginLib::UnloadAllPlugins() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_loaded_libs) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // PluginLib::Unload() can remove items from the list and even delete
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the list when it removes the last item, so we must work with a copy
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of the list so that we don't get the carpet removed under our feet.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<scoped_refptr<PluginLib> > loaded_libs(*g_loaded_libs);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < loaded_libs.size(); ++i)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loaded_libs[i]->Unload();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (g_loaded_libs && g_loaded_libs->empty()) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete g_loaded_libs;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_loaded_libs = NULL;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginLib::ShutdownAllPlugins() {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_loaded_libs) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < g_loaded_libs->size(); ++i)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*g_loaded_libs)[i]->Shutdown();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochPluginLib::PluginLib(const WebPluginInfo& info)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : web_plugin_info_(info),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      library_(NULL),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initialized_(false),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      saved_data_(0),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_count_(0),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      skip_unload_(false),
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      defer_unload_(false) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StatsCounter(kPluginLibrariesLoadedCounter).Increment();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(static_cast<void*>(&plugin_funcs_), 0, sizeof(plugin_funcs_));
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_loaded_libs->push_back(make_scoped_refptr(this));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  memset(&entry_points_, 0, sizeof(entry_points_));
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginLib::~PluginLib() {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StatsCounter(kPluginLibrariesLoadedCounter).Decrement();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (saved_data_ != 0) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO - delete the savedData object here
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPPluginFuncs* PluginLib::functions() {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &plugin_funcs_;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPError PluginLib::NP_Initialize() {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(ERROR, PluginList::DebugPluginLoading())
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value()
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "): initialized=" << initialized_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (initialized_)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NPERR_NO_ERROR;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Load())
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NPERR_MODULE_LOAD_FAILED_ERROR;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginHost* host = PluginHost::Singleton();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host == 0)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NPERR_GENERIC_ERROR;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPError rv = entry_points_.np_initialize(host->host_functions(),
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           &plugin_funcs_);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPError rv = entry_points_.np_initialize(host->host_functions());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On the Mac, we need to get entry points after calling np_initialize to
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // match the behavior of other browsers.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == NPERR_NO_ERROR) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = entry_points_.np_getentrypoints(&plugin_funcs_);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_MACOSX
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(ERROR, PluginList::DebugPluginLoading())
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value()
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "): result=" << rv;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialized_ = (rv == NPERR_NO_ERROR);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginLib::NP_Shutdown(void) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry_points_.np_shutdown();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPError PluginLib::NP_ClearSiteData(const char* site,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    uint64 flags,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    uint64 max_age) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (plugin_funcs_.clearsitedata)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return plugin_funcs_.clearsitedata(site, flags, max_age);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NPERR_INVALID_FUNCTABLE_ERROR;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char** PluginLib::NP_GetSitesWithData() {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (plugin_funcs_.getsiteswithdata)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return plugin_funcs_.getsiteswithdata();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginLib::PreventLibraryUnload() {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  skip_unload_ = true;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginInstance* PluginLib::CreateInstance(const std::string& mime_type) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginInstance* new_instance = new PluginInstance(this, mime_type);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_count_++;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StatsCounter(kPluginInstancesActiveCounter).Increment();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(static_cast<PluginInstance*>(NULL), new_instance);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new_instance;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginLib::CloseInstance() {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StatsCounter(kPluginInstancesActiveCounter).Decrement();
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_count_--;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If a plugin is running in its own process it will get unloaded on process
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shutdown.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((instance_count_ == 0) && !defer_unload_)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Unload();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginLib::Load() {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (library_)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool rv = false;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::NativeLibrary library = 0;
174effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::NativeLibraryLoadError error;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // This is to work around a bug in the Real player recorder plugin which
178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // intercepts LoadLibrary calls from chrome.dll and wraps NPAPI functions
179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // provided by the plugin. It crashes if the media player plugin is being
180ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // loaded. Workaround is to load the dll dynamically by getting the
181ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // LoadLibrary API address from kernel32.dll which bypasses the recorder
182ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // plugin.
183ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (web_plugin_info_.name.find(L"Windows Media Player") !=
184ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      std::wstring::npos) {
185ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    library = base::LoadNativeLibraryDynamically(web_plugin_info_.path);
186ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  } else {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    library = base::LoadNativeLibrary(web_plugin_info_.path, &error);
188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#else
190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  library = base::LoadNativeLibrary(web_plugin_info_.path, &error);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!library) {
194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG_IF(ERROR, PluginList::DebugPluginLoading())
195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        << "Couldn't load plugin " << web_plugin_info_.path.value() << " "
196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        << error.ToString();
197ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return rv;
198ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // According to the WebKit source, QuickTime at least requires us to call
202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // UseResFile on the plugin resources before loading.
203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (library->bundle_resource_ref != -1)
204ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    UseResFile(library->bundle_resource_ref);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  rv = true;  // assume success now
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
209ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  entry_points_.np_initialize =
210ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      (NP_InitializeFunc)base::GetFunctionPointerFromNativeLibrary(library,
211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          "NP_Initialize");
212ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (entry_points_.np_initialize == 0)
213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    rv = false;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) || defined(OS_MACOSX)
216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  entry_points_.np_getentrypoints =
217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      (NP_GetEntryPointsFunc)base::GetFunctionPointerFromNativeLibrary(
218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          library, "NP_GetEntryPoints");
219ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (entry_points_.np_getentrypoints == 0)
220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    rv = false;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  entry_points_.np_shutdown =
224ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      (NP_ShutdownFunc)base::GetFunctionPointerFromNativeLibrary(library,
225ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          "NP_Shutdown");
226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (entry_points_.np_shutdown == 0)
227ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    rv = false;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_funcs_.size = sizeof(plugin_funcs_);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_funcs_.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_POSIX)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry_points_.np_getentrypoints(&plugin_funcs_) != NPERR_NO_ERROR)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = false;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On Linux and Mac, we get the plugin entry points during NP_Initialize.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
240ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (rv) {
241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG_IF(ERROR, PluginList::DebugPluginLoading())
242ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        << "Plugin " << web_plugin_info_.path.value()
243ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        << " loaded successfully.";
244ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    library_ = library;
245ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  } else {
246ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG_IF(ERROR, PluginList::DebugPluginLoading())
247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        << "Plugin " << web_plugin_info_.path.value()
248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        << " failed to load, unloading.";
249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    base::UnloadNativeLibrary(library);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a helper to help perform a delayed NP_Shutdown and FreeLibrary on the
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// plugin dll.
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FreePluginLibraryHelper(const base::FilePath& path,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base::NativeLibrary library,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             NP_ShutdownFunc shutdown_func) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shutdown_func) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't call NP_Shutdown if the library has been reloaded since this task
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // was posted.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool reloaded = false;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (g_loaded_libs) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < g_loaded_libs->size(); ++i) {
2662385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        if ((*g_loaded_libs)[i]->plugin_info().path == path) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reloaded = true;
2682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          break;
2692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!reloaded)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shutdown_func();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (library) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Always call base::UnloadNativeLibrary so that the system reference
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // count is decremented.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::UnloadNativeLibrary(library);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginLib::Unload() {
284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (library_) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In case of single process mode, a plugin can delete itself
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // by executing a script. So delay the unloading of the library
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so that the plugin will have a chance to unwind.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* TODO(dglazkov): Revisit when re-enabling the JSC build.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if USE(JSC)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The plugin NPAPI instances may still be around. Delay the
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NP_Shutdown and FreeLibrary calls at least till the next
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // peek message.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defer_unload = true;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!defer_unload_) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG_IF(ERROR, PluginList::DebugPluginLoading())
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "Scheduling delayed unload for plugin "
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << web_plugin_info_.path.value();
300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::MessageLoop::current()->PostTask(
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&FreePluginLibraryHelper,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     web_plugin_info_.path,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     skip_unload_ ? NULL : library_,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     entry_points_.np_shutdown));
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Shutdown();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!skip_unload_) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG_IF(ERROR, PluginList::DebugPluginLoading())
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "Unloading plugin " << web_plugin_info_.path.value();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::UnloadNativeLibrary(library_);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    library_ = NULL;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < g_loaded_libs->size(); ++i) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*g_loaded_libs)[i].get() == this) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_loaded_libs->erase(g_loaded_libs->begin() + i);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_loaded_libs->empty()) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete g_loaded_libs;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_loaded_libs = NULL;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginLib::Shutdown() {
331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (initialized_) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NP_Shutdown();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    initialized_ = false;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
337ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}  // namespace content
338