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