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