1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/renderer/pepper/pepper_plugin_registry.h" 6 7 #include "base/logging.h" 8 #include "content/common/pepper_plugin_list.h" 9 #include "content/renderer/pepper/plugin_module.h" 10 #include "ppapi/shared_impl/ppapi_permissions.h" 11 12 namespace content { 13 14 // static 15 PepperPluginRegistry* PepperPluginRegistry::GetInstance() { 16 static PepperPluginRegistry* registry = NULL; 17 // This object leaks. It is a temporary hack to work around a crash. 18 // http://code.google.com/p/chromium/issues/detail?id=63234 19 if (!registry) 20 registry = new PepperPluginRegistry; 21 return registry; 22 } 23 24 const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin( 25 const WebPluginInfo& info) { 26 for (size_t i = 0; i < plugin_list_.size(); ++i) { 27 if (info.path == plugin_list_[i].path) 28 return &plugin_list_[i]; 29 } 30 // We did not find the plugin in our list. But wait! the plugin can also 31 // be a latecomer, as it happens with pepper flash. This information 32 // is actually in |info| and we can use it to construct it and add it to 33 // the list. This same deal needs to be done in the browser side in 34 // PluginService. 35 PepperPluginInfo plugin; 36 if (!MakePepperPluginInfo(info, &plugin)) 37 return NULL; 38 39 plugin_list_.push_back(plugin); 40 return &plugin_list_[plugin_list_.size() - 1]; 41 } 42 43 PluginModule* PepperPluginRegistry::GetLiveModule(const base::FilePath& path) { 44 NonOwningModuleMap::iterator it = live_modules_.find(path); 45 if (it == live_modules_.end()) 46 return NULL; 47 return it->second; 48 } 49 50 void PepperPluginRegistry::AddLiveModule(const base::FilePath& path, 51 PluginModule* module) { 52 DCHECK(live_modules_.find(path) == live_modules_.end()); 53 live_modules_[path] = module; 54 } 55 56 void PepperPluginRegistry::PluginModuleDead(PluginModule* dead_module) { 57 // DANGER: Don't dereference the dead_module pointer! It may be in the 58 // process of being deleted. 59 60 // Modules aren't destroyed very often and there are normally at most a 61 // couple of them. So for now we just do a brute-force search. 62 for (NonOwningModuleMap::iterator i = live_modules_.begin(); 63 i != live_modules_.end(); ++i) { 64 if (i->second == dead_module) { 65 live_modules_.erase(i); 66 return; 67 } 68 } 69 // Can occur in tests. 70 } 71 72 PepperPluginRegistry::~PepperPluginRegistry() { 73 // Explicitly clear all preloaded modules first. This will cause callbacks 74 // to erase these modules from the live_modules_ list, and we don't want 75 // that to happen implicitly out-of-order. 76 preloaded_modules_.clear(); 77 78 DCHECK(live_modules_.empty()); 79 } 80 81 PepperPluginRegistry::PepperPluginRegistry() { 82 ComputePepperPluginList(&plugin_list_); 83 84 // Note that in each case, AddLiveModule must be called before completing 85 // initialization. If we bail out (in the continue clauses) before saving 86 // the initialized module, it will still try to unregister itself in its 87 // destructor. 88 for (size_t i = 0; i < plugin_list_.size(); i++) { 89 const PepperPluginInfo& current = plugin_list_[i]; 90 if (current.is_out_of_process) 91 continue; // Out of process plugins need no special pre-initialization. 92 93 scoped_refptr<PluginModule> module = new PluginModule( 94 current.name, current.path, 95 ppapi::PpapiPermissions(current.permissions)); 96 AddLiveModule(current.path, module.get()); 97 if (current.is_internal) { 98 if (!module->InitAsInternalPlugin(current.internal_entry_points)) { 99 DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); 100 continue; 101 } 102 } else { 103 // Preload all external plugins we're not running out of process. 104 if (!module->InitAsLibrary(current.path)) { 105 DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); 106 continue; 107 } 108 } 109 preloaded_modules_[current.path] = module; 110 } 111 } 112 113 } // namespace content 114