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.
5 #include "content/renderer/pepper/pepper_plugin_registry.h"
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"
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
21 registry
= new PepperPluginRegistry
;
22 registry
->Initialize();
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
];
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
38 PepperPluginInfo plugin
;
39 if (!MakePepperPluginInfo(info
, &plugin
))
42 plugin_list_
.push_back(plugin
);
43 return &plugin_list_
[plugin_list_
.size() - 1];
46 PluginModule
* PepperPluginRegistry::GetLiveModule(const base::FilePath
& path
) {
47 NonOwningModuleMap::iterator module_iter
= live_modules_
.find(path
);
48 if (module_iter
== live_modules_
.end())
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();
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
;
62 PluginModule::PluginInstanceSet::const_iterator instance_iter
=
64 while (instance_iter
!= instance_set
.end()) {
65 if (!(*instance_iter
)->is_deleted())
66 return module_iter
->second
;
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
;
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.
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();
87 if (i
->second
== dead_module
) {
88 live_modules_
.erase(i
);
92 // Can occur in tests.
95 PepperPluginRegistry::~PepperPluginRegistry() {
96 // Explicitly clear all preloaded modules first. This will cause callbacks
97 // to erase these modules from the live_modules_ list, and we don't want
98 // that to happen implicitly out-of-order.
99 preloaded_modules_
.clear();
101 DCHECK(live_modules_
.empty());
104 PepperPluginRegistry::PepperPluginRegistry() {}
106 void PepperPluginRegistry::Initialize() {
107 ComputePepperPluginList(&plugin_list_
);
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
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.
118 scoped_refptr
<PluginModule
> module
=
119 new PluginModule(current
.name
,
122 ppapi::PpapiPermissions(current
.permissions
));
123 AddLiveModule(current
.path
, module
.get());
124 if (current
.is_internal
) {
125 if (!module
->InitAsInternalPlugin(current
.internal_entry_points
)) {
126 DVLOG(1) << "Failed to load pepper module: " << current
.path
.value();
130 // Preload all external plugins we're not running out of process.
131 if (!module
->InitAsLibrary(current
.path
)) {
132 DVLOG(1) << "Failed to load pepper module: " << current
.path
.value();
136 preloaded_modules_
[current
.path
] = module
;
140 } // namespace content