Home | History | Annotate | Download | only in pepper
      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