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