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 16namespace content_settings { 17 18namespace { 19 20// This iterator is used for iterating the rules for |content_type| and 21// |resource_identifier| in the precedence order of the rules. 22class 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 57OriginIdentifierValueMap::EntryMapKey::EntryMapKey( 58 ContentSettingsType content_type, 59 const ResourceIdentifier& resource_identifier) 60 : content_type(content_type), 61 resource_identifier(resource_identifier) { 62} 63 64bool 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 71OriginIdentifierValueMap::PatternPair::PatternPair( 72 const ContentSettingsPattern& primary_pattern, 73 const ContentSettingsPattern& secondary_pattern) 74 : primary_pattern(primary_pattern), 75 secondary_pattern(secondary_pattern) { 76} 77 78bool 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 90RuleIterator* 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 110size_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 118OriginIdentifierValueMap::OriginIdentifierValueMap() {} 119 120OriginIdentifierValueMap::~OriginIdentifierValueMap() {} 121 122base::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 145void 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 160void 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 173void OriginIdentifierValueMap::DeleteValues( 174 ContentSettingsType content_type, 175 const ResourceIdentifier& resource_identifier) { 176 EntryMapKey key(content_type, resource_identifier); 177 entries_.erase(key); 178} 179 180void OriginIdentifierValueMap::clear() { 181 // Delete all owned value objects. 182 entries_.clear(); 183} 184 185} // namespace content_settings 186