Home | History | Annotate | Download | only in declarative
      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 "chrome/browser/extensions/api/declarative/initializing_rules_registry.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/strings/stringprintf.h"
      9 #include "base/values.h"
     10 
     11 namespace {
     12 std::string ToId(int identifier) {
     13   return base::StringPrintf("_%d_", identifier);
     14 }
     15 }  // namespace
     16 
     17 namespace extensions {
     18 
     19 InitializingRulesRegistry::InitializingRulesRegistry(
     20     scoped_refptr<RulesRegistry> delegate)
     21     : RulesRegistry(delegate->owner_thread(), delegate->event_name()),
     22       delegate_(delegate),
     23       last_generated_rule_identifier_id_(0) {}
     24 
     25 std::string InitializingRulesRegistry::AddRules(
     26     const std::string& extension_id,
     27     const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) {
     28   std::string error = CheckAndFillInOptionalRules(extension_id, rules);
     29   if (!error.empty())
     30     return error;
     31   FillInOptionalPriorities(rules);
     32   return delegate_->AddRules(extension_id, rules);
     33 }
     34 
     35 std::string InitializingRulesRegistry::RemoveRules(
     36     const std::string& extension_id,
     37     const std::vector<std::string>& rule_identifiers) {
     38   std::string error = delegate_->RemoveRules(extension_id, rule_identifiers);
     39   if (!error.empty())
     40     return error;
     41   RemoveUsedRuleIdentifiers(extension_id, rule_identifiers);
     42   return std::string();
     43 }
     44 
     45 std::string InitializingRulesRegistry::RemoveAllRules(
     46     const std::string& extension_id) {
     47   std::string error = delegate_->RemoveAllRules(extension_id);
     48   if (!error.empty())
     49     return error;
     50   RemoveAllUsedRuleIdentifiers(extension_id);
     51   return std::string();
     52 }
     53 
     54 std::string InitializingRulesRegistry::GetRules(
     55     const std::string& extension_id,
     56     const std::vector<std::string>& rule_identifiers,
     57     std::vector<linked_ptr<RulesRegistry::Rule> >* out) {
     58   return delegate_->GetRules(extension_id, rule_identifiers, out);
     59 }
     60 
     61 std::string InitializingRulesRegistry::GetAllRules(
     62     const std::string& extension_id,
     63     std::vector<linked_ptr<RulesRegistry::Rule> >* out) {
     64   return delegate_->GetAllRules(extension_id, out);
     65 }
     66 
     67 void InitializingRulesRegistry::OnExtensionUnloaded(
     68     const std::string& extension_id) {
     69   delegate_->OnExtensionUnloaded(extension_id);
     70   used_rule_identifiers_.erase(extension_id);
     71 }
     72 
     73 size_t
     74 InitializingRulesRegistry::GetNumberOfUsedRuleIdentifiersForTesting() const {
     75   size_t entry_count = 0u;
     76   for (RuleIdentifiersMap::const_iterator extension =
     77            used_rule_identifiers_.begin();
     78        extension != used_rule_identifiers_.end();
     79        ++extension) {
     80     // Each extension is counted as 1 just for being there. Otherwise we miss
     81     // keys with empty values.
     82     entry_count += 1u + extension->second.size();
     83   }
     84   return entry_count;
     85 }
     86 
     87 InitializingRulesRegistry::~InitializingRulesRegistry() {}
     88 
     89 bool InitializingRulesRegistry::IsUniqueId(
     90     const std::string& extension_id,
     91     const std::string& rule_id) const {
     92   RuleIdentifiersMap::const_iterator identifiers =
     93       used_rule_identifiers_.find(extension_id);
     94   if (identifiers == used_rule_identifiers_.end())
     95     return true;
     96   return identifiers->second.find(rule_id) == identifiers->second.end();
     97 }
     98 
     99 std::string InitializingRulesRegistry::GenerateUniqueId(
    100     const std::string& extension_id) {
    101   while (!IsUniqueId(extension_id, ToId(last_generated_rule_identifier_id_)))
    102     ++last_generated_rule_identifier_id_;
    103   return ToId(last_generated_rule_identifier_id_);
    104 }
    105 
    106 std::string InitializingRulesRegistry::CheckAndFillInOptionalRules(
    107     const std::string& extension_id,
    108     const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) {
    109   // IDs we have inserted, in case we need to rollback this operation.
    110   std::vector<std::string> rollback_log;
    111 
    112   // First we insert all rules with existing identifier, so that generated
    113   // identifiers cannot collide with identifiers passed by the caller.
    114   for (std::vector<linked_ptr<RulesRegistry::Rule> >::const_iterator i =
    115       rules.begin(); i != rules.end(); ++i) {
    116     RulesRegistry::Rule* rule = i->get();
    117     if (rule->id.get()) {
    118       std::string id = *(rule->id);
    119       if (!IsUniqueId(extension_id, id)) {
    120         RemoveUsedRuleIdentifiers(extension_id, rollback_log);
    121         return "Id " + id + " was used multiple times.";
    122       }
    123       used_rule_identifiers_[extension_id].insert(id);
    124     }
    125   }
    126   // Now we generate IDs in case they were not specificed in the rules. This
    127   // cannot fail so we do not need to keep track of a rollback log.
    128   for (std::vector<linked_ptr<RulesRegistry::Rule> >::const_iterator i =
    129       rules.begin(); i != rules.end(); ++i) {
    130     RulesRegistry::Rule* rule = i->get();
    131     if (!rule->id.get()) {
    132       rule->id.reset(new std::string(GenerateUniqueId(extension_id)));
    133       used_rule_identifiers_[extension_id].insert(*(rule->id));
    134     }
    135   }
    136   return std::string();
    137 }
    138 
    139 void InitializingRulesRegistry::FillInOptionalPriorities(
    140     const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) {
    141   std::vector<linked_ptr<RulesRegistry::Rule> >::const_iterator i;
    142   for (i = rules.begin(); i != rules.end(); ++i) {
    143     if (!(*i)->priority.get())
    144       (*i)->priority.reset(new int(DEFAULT_PRIORITY));
    145   }
    146 }
    147 
    148 void InitializingRulesRegistry::RemoveUsedRuleIdentifiers(
    149     const std::string& extension_id,
    150     const std::vector<std::string>& identifiers) {
    151   std::vector<std::string>::const_iterator i;
    152   for (i = identifiers.begin(); i != identifiers.end(); ++i)
    153     used_rule_identifiers_[extension_id].erase(*i);
    154 }
    155 
    156 void InitializingRulesRegistry::RemoveAllUsedRuleIdentifiers(
    157     const std::string& extension_id) {
    158   used_rule_identifiers_.erase(extension_id);
    159 }
    160 
    161 }  // namespace extensions
    162