Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2013 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 "chrome/common/extensions/manifest_handler.h"
      6 
      7 #include <map>
      8 
      9 #include "base/logging.h"
     10 #include "base/stl_util.h"
     11 #include "chrome/common/extensions/extension.h"
     12 
     13 namespace extensions {
     14 
     15 namespace {
     16 
     17 static base::LazyInstance<ManifestHandlerRegistry> g_registry =
     18     LAZY_INSTANCE_INITIALIZER;
     19 static ManifestHandlerRegistry* g_registry_override = NULL;
     20 
     21 ManifestHandlerRegistry* GetRegistry() {
     22   if (!g_registry_override)
     23     return g_registry.Pointer();
     24   return g_registry_override;
     25 }
     26 
     27 }  // namespace
     28 
     29 ManifestHandler::ManifestHandler() {
     30 }
     31 
     32 ManifestHandler::~ManifestHandler() {
     33 }
     34 
     35 bool ManifestHandler::Validate(const Extension* extension,
     36                                std::string* error,
     37                                std::vector<InstallWarning>* warnings) const {
     38   return true;
     39 }
     40 
     41 bool ManifestHandler::AlwaysParseForType(Manifest::Type type) const {
     42   return false;
     43 }
     44 
     45 bool ManifestHandler::AlwaysValidateForType(Manifest::Type type) const {
     46   return false;
     47 }
     48 
     49 const std::vector<std::string> ManifestHandler::PrerequisiteKeys() const {
     50   return std::vector<std::string>();
     51 }
     52 
     53 void ManifestHandler::Register() {
     54   linked_ptr<ManifestHandler> this_linked(this);
     55   const std::vector<std::string> keys = Keys();
     56   for (size_t i = 0; i < keys.size(); ++i)
     57     GetRegistry()->RegisterManifestHandler(keys[i], this_linked);
     58 }
     59 
     60 // static
     61 void ManifestHandler::FinalizeRegistration() {
     62   GetRegistry()->Finalize();
     63 }
     64 
     65 // static
     66 bool ManifestHandler::IsRegistrationFinalized() {
     67   return GetRegistry()->is_finalized_;
     68 }
     69 
     70 // static
     71 bool ManifestHandler::ParseExtension(Extension* extension, string16* error) {
     72   return GetRegistry()->ParseExtension(extension, error);
     73 }
     74 
     75 // static
     76 bool ManifestHandler::ValidateExtension(const Extension* extension,
     77                                         std::string* error,
     78                                         std::vector<InstallWarning>* warnings) {
     79   return GetRegistry()->ValidateExtension(extension, error, warnings);
     80 }
     81 
     82 // static
     83 const std::vector<std::string> ManifestHandler::SingleKey(
     84     const std::string& key) {
     85   return std::vector<std::string>(1, key);
     86 }
     87 
     88 ManifestHandlerRegistry::ManifestHandlerRegistry() : is_finalized_(false) {
     89 }
     90 
     91 ManifestHandlerRegistry::~ManifestHandlerRegistry() {
     92 }
     93 
     94 void ManifestHandlerRegistry::Finalize() {
     95   CHECK(!is_finalized_);
     96   SortManifestHandlers();
     97   is_finalized_ = true;
     98 }
     99 
    100 void ManifestHandlerRegistry::RegisterManifestHandler(
    101     const std::string& key, linked_ptr<ManifestHandler> handler) {
    102   CHECK(!is_finalized_);
    103   handlers_[key] = handler;
    104 }
    105 
    106 bool ManifestHandlerRegistry::ParseExtension(Extension* extension,
    107                                              string16* error) {
    108   std::map<int, ManifestHandler*> handlers_by_priority;
    109   for (ManifestHandlerMap::iterator iter = handlers_.begin();
    110        iter != handlers_.end(); ++iter) {
    111     ManifestHandler* handler = iter->second.get();
    112     if (extension->manifest()->HasPath(iter->first) ||
    113         handler->AlwaysParseForType(extension->GetType())) {
    114       handlers_by_priority[priority_map_[handler]] = handler;
    115     }
    116   }
    117   for (std::map<int, ManifestHandler*>::iterator iter =
    118            handlers_by_priority.begin();
    119        iter != handlers_by_priority.end(); ++iter) {
    120     if (!(iter->second)->Parse(extension, error))
    121       return false;
    122   }
    123   return true;
    124 }
    125 
    126 bool ManifestHandlerRegistry::ValidateExtension(
    127     const Extension* extension,
    128     std::string* error,
    129     std::vector<InstallWarning>* warnings) {
    130   std::set<ManifestHandler*> handlers;
    131   for (ManifestHandlerMap::iterator iter = handlers_.begin();
    132        iter != handlers_.end(); ++iter) {
    133     ManifestHandler* handler = iter->second.get();
    134     if (extension->manifest()->HasPath(iter->first) ||
    135         handler->AlwaysValidateForType(extension->GetType())) {
    136       handlers.insert(handler);
    137     }
    138   }
    139   for (std::set<ManifestHandler*>::iterator iter = handlers.begin();
    140        iter != handlers.end(); ++iter) {
    141     if (!(*iter)->Validate(extension, error, warnings))
    142       return false;
    143   }
    144   return true;
    145 }
    146 
    147 // static
    148 ManifestHandlerRegistry* ManifestHandlerRegistry::SetForTesting(
    149     ManifestHandlerRegistry* new_registry) {
    150   ManifestHandlerRegistry* old_registry = GetRegistry();
    151   if (new_registry != g_registry.Pointer())
    152     g_registry_override = new_registry;
    153   else
    154     g_registry_override = NULL;
    155   return old_registry;
    156 }
    157 
    158 void ManifestHandlerRegistry::SortManifestHandlers() {
    159   std::set<ManifestHandler*> unsorted_handlers;
    160   for (ManifestHandlerMap::const_iterator iter = handlers_.begin();
    161        iter != handlers_.end(); ++iter) {
    162     unsorted_handlers.insert(iter->second.get());
    163   }
    164 
    165   int priority = 0;
    166   while (true) {
    167     std::set<ManifestHandler*> next_unsorted_handlers;
    168     for (std::set<ManifestHandler*>::const_iterator iter =
    169              unsorted_handlers.begin();
    170          iter != unsorted_handlers.end(); ++iter) {
    171       ManifestHandler* handler = *iter;
    172       const std::vector<std::string>& prerequisites =
    173           handler->PrerequisiteKeys();
    174       int unsatisfied = prerequisites.size();
    175       for (size_t i = 0; i < prerequisites.size(); ++i) {
    176         ManifestHandlerMap::const_iterator prereq_iter =
    177             handlers_.find(prerequisites[i]);
    178         // If the prerequisite does not exist, crash.
    179         CHECK(prereq_iter != handlers_.end())
    180             << "Extension manifest handler depends on unrecognized key "
    181             << prerequisites[i];
    182         // Prerequisite is in our map.
    183         if (ContainsKey(priority_map_, prereq_iter->second.get()))
    184           unsatisfied--;
    185       }
    186       if (unsatisfied == 0) {
    187         priority_map_[handler] = priority;
    188         priority++;
    189       } else {
    190         // Put in the list for next time.
    191         next_unsorted_handlers.insert(handler);
    192       }
    193     }
    194     if (next_unsorted_handlers.size() == unsorted_handlers.size())
    195       break;
    196     unsorted_handlers.swap(next_unsorted_handlers);
    197   }
    198 
    199   // If there are any leftover unsorted handlers, they must have had
    200   // circular dependencies.
    201   CHECK(unsorted_handlers.size() == 0) << "Extension manifest handlers have "
    202                                        << "circular dependencies!";
    203 }
    204 
    205 }  // namespace extensions
    206