1792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project// Use of this source code is governed by a BSD-style license that can be
3792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project// found in the LICENSE file.
4792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
5792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project#include "chrome/browser/content_settings/content_settings_origin_identifier_value_map.h"
6792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
7792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project#include "base/compiler_specific.h"
8792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project#include "base/logging.h"
9792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project#include "base/memory/scoped_ptr.h"
10792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project#include "base/synchronization/lock.h"
11792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project#include "base/values.h"
12792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project#include "chrome/browser/content_settings/content_settings_rule.h"
13792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project#include "chrome/browser/content_settings/content_settings_utils.h"
14792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project#include "chrome/common/content_settings_types.h"
15792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project#include "url/gurl.h"
16792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
17792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectnamespace content_settings {
18792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
19f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissennamespace {
20f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen
21792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project// This iterator is used for iterating the rules for |content_type| and
22792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project// |resource_identifier| in the precedence order of the rules.
23792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectclass RuleIteratorImpl : public RuleIterator {
24792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project public:
253fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  // |RuleIteratorImpl| takes the ownership of |auto_lock|.
26792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  RuleIteratorImpl(
27792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project      const OriginIdentifierValueMap::Rules::const_iterator& current_rule,
28792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project      const OriginIdentifierValueMap::Rules::const_iterator& rule_end,
29792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project      base::AutoLock* auto_lock)
303fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen      : current_rule_(current_rule),
31792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        rule_end_(rule_end),
32792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        auto_lock_(auto_lock) {
33792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  }
34792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  virtual ~RuleIteratorImpl() {}
35792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
36792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  virtual bool HasNext() const OVERRIDE {
37792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    return (current_rule_ != rule_end_);
383fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  }
39792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
401968e38c437d7419ba01e5b7c1081f01ae618783Marco Nelissen  virtual Rule Next() OVERRIDE {
41792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    DCHECK(current_rule_ != rule_end_);
42792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    DCHECK(current_rule_->second.get());
43792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    Rule to_return(current_rule_->first.primary_pattern,
44792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                   current_rule_->first.secondary_pattern,
45792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                   current_rule_->second.get()->DeepCopy());
46792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    ++current_rule_;
47792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    return to_return;
48792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  }
49792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
50792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project private:
51792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  OriginIdentifierValueMap::Rules::const_iterator current_rule_;
52792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  OriginIdentifierValueMap::Rules::const_iterator rule_end_;
53792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  scoped_ptr<base::AutoLock> auto_lock_;
54792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project};
55792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
56792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project}  // namespace
573fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen
583fdd97fb21031de30e604d470fc8458b814e6587Marco NelissenOriginIdentifierValueMap::EntryMapKey::EntryMapKey(
59792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    ContentSettingsType content_type,
60792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    const ResourceIdentifier& resource_identifier)
61792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    : content_type(content_type),
62792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project      resource_identifier(resource_identifier) {
63792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project}
64792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
65792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectbool OriginIdentifierValueMap::EntryMapKey::operator<(
66792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    const OriginIdentifierValueMap::EntryMapKey& other) const {
67792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  if (content_type != other.content_type)
68792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    return content_type < other.content_type;
69792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  return (resource_identifier < other.resource_identifier);
70792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project}
71f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen
72792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source ProjectOriginIdentifierValueMap::PatternPair::PatternPair(
73792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    const ContentSettingsPattern& primary_pattern,
74792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    const ContentSettingsPattern& secondary_pattern)
75792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    : primary_pattern(primary_pattern),
76792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project      secondary_pattern(secondary_pattern) {
77792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project}
78792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
79792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectbool OriginIdentifierValueMap::PatternPair::operator<(
80792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    const OriginIdentifierValueMap::PatternPair& other) const {
81792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  // Note that this operator is the other way around than
82792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  // |ContentSettingsPattern::operator<|. It sorts patterns with higher
833fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  // precedence first.
84f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen  if (primary_pattern > other.primary_pattern)
853fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen    return true;
863fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  else if (other.primary_pattern > primary_pattern)
873fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen    return false;
883fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  return (secondary_pattern > other.secondary_pattern);
893fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen}
90792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
91792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source ProjectRuleIterator* OriginIdentifierValueMap::GetRuleIterator(
92792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    ContentSettingsType content_type,
93792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    const ResourceIdentifier& resource_identifier,
94792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    base::Lock* lock) const {
95792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  EntryMapKey key(content_type, resource_identifier);
963fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  // We access |entries_| here, so we need to lock |lock_| first. The lock must
979882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen  // be passed to the |RuleIteratorImpl| in a locked state, so that nobody can
983fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  // access |entries_| after |find()| but before the |RuleIteratorImpl| is
999882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen  // created.
1003fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  scoped_ptr<base::AutoLock> auto_lock;
1013fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  if (lock)
1023fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen    auto_lock.reset(new base::AutoLock(*lock));
1033fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  EntryMap::const_iterator it = entries_.find(key);
1043fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  if (it == entries_.end())
1053fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen    return new EmptyRuleIterator();
106bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen  return new RuleIteratorImpl(it->second.begin(),
1073fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen                              it->second.end(),
1083fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen                              auto_lock.release());
1093fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen}
1103fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen
1113fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissensize_t OriginIdentifierValueMap::size() const {
1123fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  size_t size = 0;
1133fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  EntryMap::const_iterator it;
1143fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  for (it = entries_.begin(); it != entries_.end(); ++it)
1153fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen    size += it->second.size();
1163fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  return size;
1173fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen}
1183fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen
1193fdd97fb21031de30e604d470fc8458b814e6587Marco NelissenOriginIdentifierValueMap::OriginIdentifierValueMap() {}
1203fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen
1213fdd97fb21031de30e604d470fc8458b814e6587Marco NelissenOriginIdentifierValueMap::~OriginIdentifierValueMap() {}
1223fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen
1233fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissenbase::Value* OriginIdentifierValueMap::GetValue(
1243fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen    const GURL& primary_url,
1253fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen    const GURL& secondary_url,
126792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    ContentSettingsType content_type,
127792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    const ResourceIdentifier& resource_identifier) const {
1289882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen  EntryMapKey key(content_type, resource_identifier);
1293fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  EntryMap::const_iterator it = entries_.find(key);
1309882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen  if (it == entries_.end())
1319882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen      return NULL;
1329882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen
1339882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen  // Iterate the entries in until a match is found. Since the rules are stored
1349882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen  // in the order of decreasing precedence, the most specific match is found
1359882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen  // first.
1369882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen  Rules::const_iterator entry;
1379882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen  for (entry = it->second.begin(); entry != it->second.end(); ++entry) {
1389882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen    if (entry->first.primary_pattern.Matches(primary_url) &&
1399882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen        entry->first.secondary_pattern.Matches(secondary_url)) {
1409882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen      return entry->second.get();
1419882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen    }
1429882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen  }
1439882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen  return NULL;
1449882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen}
1459882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen
1469882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissenvoid OriginIdentifierValueMap::SetValue(
1479882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen    const ContentSettingsPattern& primary_pattern,
1489882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen    const ContentSettingsPattern& secondary_pattern,
1499882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen    ContentSettingsType content_type,
1509882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen    const ResourceIdentifier& resource_identifier,
1519882f540844f6a613eeb5edf5f076d1dcc72bf9fMarco Nelissen    base::Value* value) {
152792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  DCHECK(primary_pattern.IsValid());
153792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  DCHECK(secondary_pattern.IsValid());
154792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  DCHECK(value);
155792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  EntryMapKey key(content_type, resource_identifier);
156792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  PatternPair patterns(primary_pattern, secondary_pattern);
157792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  // This will create the entry and the linked_ptr if needed.
158792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  entries_[key][patterns].reset(value);
159792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project}
160792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
161792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectvoid OriginIdentifierValueMap::DeleteValue(
162792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project      const ContentSettingsPattern& primary_pattern,
163792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project      const ContentSettingsPattern& secondary_pattern,
164792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project      ContentSettingsType content_type,
165792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project      const ResourceIdentifier& resource_identifier) {
166792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  EntryMapKey key(content_type, resource_identifier);
167792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  PatternPair patterns(primary_pattern, secondary_pattern);
168792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  entries_[key].erase(patterns);
169792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  if (entries_[key].empty()) {
170792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    entries_.erase(key);
171792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  }
172792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project}
173792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
174792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectvoid OriginIdentifierValueMap::DeleteValues(
175792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project      ContentSettingsType content_type,
176792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project      const ResourceIdentifier& resource_identifier) {
177792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  EntryMapKey key(content_type, resource_identifier);
178792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project  entries_.erase(key);
179792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project}
180792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
181792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectvoid OriginIdentifierValueMap::clear() {
1823fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  // Delete all owned value objects.
1833fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen  entries_.clear();
1843fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen}
1853fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen
1863fdd97fb21031de30e604d470fc8458b814e6587Marco Nelissen}  // namespace content_settings
187792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project