• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/pepper_plugin_instance_impl.h"
10 #include "content/renderer/pepper/plugin_module.h"
11 #include "ppapi/shared_impl/ppapi_permissions.h"
12 
13 namespace content {
14 
15 // static
GetInstance()16 PepperPluginRegistry* PepperPluginRegistry::GetInstance() {
17   static PepperPluginRegistry* registry = NULL;
18   // This object leaks.  It is a temporary hack to work around a crash.
19   // http://code.google.com/p/chromium/issues/detail?id=63234
20   if (!registry) {
21     registry = new PepperPluginRegistry;
22     registry->Initialize();
23   }
24   return registry;
25 }
26 
GetInfoForPlugin(const WebPluginInfo & info)27 const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin(
28     const WebPluginInfo& info) {
29   for (size_t i = 0; i < plugin_list_.size(); ++i) {
30     if (info.path == plugin_list_[i].path)
31       return &plugin_list_[i];
32   }
33   // We did not find the plugin in our list. But wait! the plugin can also
34   // be a latecomer, as it happens with pepper flash. This information
35   // is actually in |info| and we can use it to construct it and add it to
36   // the list. This same deal needs to be done in the browser side in
37   // PluginService.
38   PepperPluginInfo plugin;
39   if (!MakePepperPluginInfo(info, &plugin))
40     return NULL;
41 
42   plugin_list_.push_back(plugin);
43   return &plugin_list_[plugin_list_.size() - 1];
44 }
45 
GetLiveModule(const base::FilePath & path)46 PluginModule* PepperPluginRegistry::GetLiveModule(const base::FilePath& path) {
47   NonOwningModuleMap::iterator module_iter = live_modules_.find(path);
48   if (module_iter == live_modules_.end())
49     return NULL;
50 
51   // Check the instances for the module to see if they've all been Delete()d.
52   // We don't want to return a PluginModule in that case, since the plugin may
53   // have exited already.
54   const PluginModule::PluginInstanceSet& instance_set =
55       module_iter->second->GetAllInstances();
56 
57   // If instance_set is empty, InstanceCreated() hasn't been called yet, so
58   // it's safe to return the PluginModule.
59   if (instance_set.empty())
60     return module_iter->second;
61 
62   PluginModule::PluginInstanceSet::const_iterator instance_iter =
63       instance_set.begin();
64   while (instance_iter != instance_set.end()) {
65     if (!(*instance_iter)->is_deleted())
66       return module_iter->second;
67     ++instance_iter;
68   }
69   return NULL;
70 }
71 
AddLiveModule(const base::FilePath & path,PluginModule * module)72 void PepperPluginRegistry::AddLiveModule(const base::FilePath& path,
73                                          PluginModule* module) {
74   DCHECK(live_modules_.find(path) == live_modules_.end());
75   live_modules_[path] = module;
76 }
77 
PluginModuleDead(PluginModule * dead_module)78 void PepperPluginRegistry::PluginModuleDead(PluginModule* dead_module) {
79   // DANGER: Don't dereference the dead_module pointer! It may be in the
80   // process of being deleted.
81 
82   // Modules aren't destroyed very often and there are normally at most a
83   // couple of them. So for now we just do a brute-force search.
84   for (NonOwningModuleMap::iterator i = live_modules_.begin();
85        i != live_modules_.end(); ++i) {
86     if (i->second == dead_module) {
87       live_modules_.erase(i);
88       return;
89     }
90   }
91   // Can occur in tests.
92 }
93 
~PepperPluginRegistry()94 PepperPluginRegistry::~PepperPluginRegistry() {
95   // Explicitly clear all preloaded modules first. This will cause callbacks
96   // to erase these modules from the live_modules_ list, and we don't want
97   // that to happen implicitly out-of-order.
98   preloaded_modules_.clear();
99 
100   DCHECK(live_modules_.empty());
101 }
102 
PepperPluginRegistry()103 PepperPluginRegistry::PepperPluginRegistry() {
104 }
105 
Initialize()106 void PepperPluginRegistry::Initialize() {
107   ComputePepperPluginList(&plugin_list_);
108 
109   // Note that in each case, AddLiveModule must be called before completing
110   // initialization. If we bail out (in the continue clauses) before saving
111   // the initialized module, it will still try to unregister itself in its
112   // destructor.
113   for (size_t i = 0; i < plugin_list_.size(); i++) {
114     const PepperPluginInfo& current = plugin_list_[i];
115     if (current.is_out_of_process)
116       continue;  // Out of process plugins need no special pre-initialization.
117 
118     scoped_refptr<PluginModule> module = new PluginModule(
119         current.name, current.path,
120         ppapi::PpapiPermissions(current.permissions));
121     AddLiveModule(current.path, module.get());
122     if (current.is_internal) {
123       if (!module->InitAsInternalPlugin(current.internal_entry_points)) {
124         DLOG(ERROR) << "Failed to load pepper module: " << current.path.value();
125         continue;
126       }
127     } else {
128       // Preload all external plugins we're not running out of process.
129       if (!module->InitAsLibrary(current.path)) {
130         DLOG(ERROR) << "Failed to load pepper module: " << current.path.value();
131         continue;
132       }
133     }
134     preloaded_modules_[current.path] = module;
135   }
136 }
137 
138 }  // namespace content
139