Home | History | Annotate | Download | only in browser
      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 "components/content_settings/core/browser/content_settings_origin_identifier_value_map.h"
      6 
      7 #include "base/compiler_specific.h"
      8 #include "base/logging.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/synchronization/lock.h"
     11 #include "base/values.h"
     12 #include "components/content_settings/core/browser/content_settings_rule.h"
     13 #include "components/content_settings/core/common/content_settings_types.h"
     14 #include "url/gurl.h"
     15 
     16 namespace content_settings {
     17 
     18 namespace {
     19 
     20 // This iterator is used for iterating the rules for |content_type| and
     21 // |resource_identifier| in the precedence order of the rules.
     22 class RuleIteratorImpl : public RuleIterator {
     23  public:
     24   // |RuleIteratorImpl| takes the ownership of |auto_lock|.
     25   RuleIteratorImpl(
     26       const OriginIdentifierValueMap::Rules::const_iterator& current_rule,
     27       const OriginIdentifierValueMap::Rules::const_iterator& rule_end,
     28       base::AutoLock* auto_lock)
     29       : current_rule_(current_rule),
     30         rule_end_(rule_end),
     31         auto_lock_(auto_lock) {
     32   }
     33   virtual ~RuleIteratorImpl() {}
     34 
     35   virtual bool HasNext() const OVERRIDE {
     36     return (current_rule_ != rule_end_);
     37   }
     38 
     39   virtual Rule Next() OVERRIDE {
     40     DCHECK(current_rule_ != rule_end_);
     41     DCHECK(current_rule_->second.get());
     42     Rule to_return(current_rule_->first.primary_pattern,
     43                    current_rule_->first.secondary_pattern,
     44                    current_rule_->second.get()->DeepCopy());
     45     ++current_rule_;
     46     return to_return;
     47   }
     48 
     49  private:
     50   OriginIdentifierValueMap::Rules::const_iterator current_rule_;
     51   OriginIdentifierValueMap::Rules::const_iterator rule_end_;
     52   scoped_ptr<base::AutoLock> auto_lock_;
     53 };
     54 
     55 }  // namespace
     56 
     57 OriginIdentifierValueMap::EntryMapKey::EntryMapKey(
     58     ContentSettingsType content_type,
     59     const ResourceIdentifier& resource_identifier)
     60     : content_type(content_type),
     61       resource_identifier(resource_identifier) {
     62 }
     63 
     64 bool OriginIdentifierValueMap::EntryMapKey::operator<(
     65     const OriginIdentifierValueMap::EntryMapKey& other) const {
     66   if (content_type != other.content_type)
     67     return content_type < other.content_type;
     68   return (resource_identifier < other.resource_identifier);
     69 }
     70 
     71 OriginIdentifierValueMap::PatternPair::PatternPair(
     72     const ContentSettingsPattern& primary_pattern,
     73     const ContentSettingsPattern& secondary_pattern)
     74     : primary_pattern(primary_pattern),
     75       secondary_pattern(secondary_pattern) {
     76 }
     77 
     78 bool OriginIdentifierValueMap::PatternPair::operator<(
     79     const OriginIdentifierValueMap::PatternPair& other) const {
     80   // Note that this operator is the other way around than
     81   // |ContentSettingsPattern::operator<|. It sorts patterns with higher
     82   // precedence first.
     83   if (primary_pattern > other.primary_pattern)
     84     return true;
     85   else if (other.primary_pattern > primary_pattern)
     86     return false;
     87   return (secondary_pattern > other.secondary_pattern);
     88 }
     89 
     90 RuleIterator* OriginIdentifierValueMap::GetRuleIterator(
     91     ContentSettingsType content_type,
     92     const ResourceIdentifier& resource_identifier,
     93     base::Lock* lock) const {
     94   EntryMapKey key(content_type, resource_identifier);
     95   // We access |entries_| here, so we need to lock |lock_| first. The lock must
     96   // be passed to the |RuleIteratorImpl| in a locked state, so that nobody can
     97   // access |entries_| after |find()| but before the |RuleIteratorImpl| is
     98   // created.
     99   scoped_ptr<base::AutoLock> auto_lock;
    100   if (lock)
    101     auto_lock.reset(new base::AutoLock(*lock));
    102   EntryMap::const_iterator it = entries_.find(key);
    103   if (it == entries_.end())
    104     return new EmptyRuleIterator();
    105   return new RuleIteratorImpl(it->second.begin(),
    106                               it->second.end(),
    107                               auto_lock.release());
    108 }
    109 
    110 size_t OriginIdentifierValueMap::size() const {
    111   size_t size = 0;
    112   EntryMap::const_iterator it;
    113   for (it = entries_.begin(); it != entries_.end(); ++it)
    114     size += it->second.size();
    115   return size;
    116 }
    117 
    118 OriginIdentifierValueMap::OriginIdentifierValueMap() {}
    119 
    120 OriginIdentifierValueMap::~OriginIdentifierValueMap() {}
    121 
    122 base::Value* OriginIdentifierValueMap::GetValue(
    123     const GURL& primary_url,
    124     const GURL& secondary_url,
    125     ContentSettingsType content_type,
    126     const ResourceIdentifier& resource_identifier) const {
    127   EntryMapKey key(content_type, resource_identifier);
    128   EntryMap::const_iterator it = entries_.find(key);
    129   if (it == entries_.end())
    130       return NULL;
    131 
    132   // Iterate the entries in until a match is found. Since the rules are stored
    133   // in the order of decreasing precedence, the most specific match is found
    134   // first.
    135   Rules::const_iterator entry;
    136   for (entry = it->second.begin(); entry != it->second.end(); ++entry) {
    137     if (entry->first.primary_pattern.Matches(primary_url) &&
    138         entry->first.secondary_pattern.Matches(secondary_url)) {
    139       return entry->second.get();
    140     }
    141   }
    142   return NULL;
    143 }
    144 
    145 void OriginIdentifierValueMap::SetValue(
    146     const ContentSettingsPattern& primary_pattern,
    147     const ContentSettingsPattern& secondary_pattern,
    148     ContentSettingsType content_type,
    149     const ResourceIdentifier& resource_identifier,
    150     base::Value* value) {
    151   DCHECK(primary_pattern.IsValid());
    152   DCHECK(secondary_pattern.IsValid());
    153   DCHECK(value);
    154   EntryMapKey key(content_type, resource_identifier);
    155   PatternPair patterns(primary_pattern, secondary_pattern);
    156   // This will create the entry and the linked_ptr if needed.
    157   entries_[key][patterns].reset(value);
    158 }
    159 
    160 void OriginIdentifierValueMap::DeleteValue(
    161       const ContentSettingsPattern& primary_pattern,
    162       const ContentSettingsPattern& secondary_pattern,
    163       ContentSettingsType content_type,
    164       const ResourceIdentifier& resource_identifier) {
    165   EntryMapKey key(content_type, resource_identifier);
    166   PatternPair patterns(primary_pattern, secondary_pattern);
    167   entries_[key].erase(patterns);
    168   if (entries_[key].empty()) {
    169     entries_.erase(key);
    170   }
    171 }
    172 
    173 void OriginIdentifierValueMap::DeleteValues(
    174       ContentSettingsType content_type,
    175       const ResourceIdentifier& resource_identifier) {
    176   EntryMapKey key(content_type, resource_identifier);
    177   entries_.erase(key);
    178 }
    179 
    180 void OriginIdentifierValueMap::clear() {
    181   // Delete all owned value objects.
    182   entries_.clear();
    183 }
    184 
    185 }  // namespace content_settings
    186