In memory map to store |Value| objects for
(origin pattern, origin pattern, content type, resource) identifier) tuples.

This is supposed to replace the content_settings::BaseProvider.

BUG=63656
TEST=origin_identifier_value_map_unittest.cc,
     content_settings_pref_provider_unittest.cc,
     host_content_settings_map_unittest.cc

Review URL: http://codereview.chromium.org/7049007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@88522 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/content_settings/content_settings_origin_identifier_value_map.cc b/chrome/browser/content_settings/content_settings_origin_identifier_value_map.cc
new file mode 100644
index 0000000..1d30d90f
--- /dev/null
+++ b/chrome/browser/content_settings/content_settings_origin_identifier_value_map.cc
@@ -0,0 +1,131 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/content_settings/content_settings_origin_identifier_value_map.h"
+
+#include "base/logging.h"
+#include "base/values.h"
+#include "googleurl/src/gurl.h"
+
+namespace content_settings {
+
+OriginIdentifierValueMap::OriginIdentifierValueMap() {}
+
+OriginIdentifierValueMap::~OriginIdentifierValueMap() {
+  Clear();
+}
+
+bool operator>(const OriginIdentifierValueMap::Entry& first,
+               const OriginIdentifierValueMap::Entry& second) {
+  // Compare item patterns.
+  if (first.item_pattern > second.item_pattern)
+    return true;
+  if (first.item_pattern < second.item_pattern)
+    return false;
+
+  // Compare top_level_frame patterns.
+  if (first.top_level_frame_pattern > second.top_level_frame_pattern)
+    return true;
+  return false;
+}
+
+Value* OriginIdentifierValueMap::GetValue(
+    const GURL& item_url,
+    const GURL& top_level_frame_url,
+    ContentSettingsType content_type,
+    const ResourceIdentifier& resource_identifier) const {
+  // Find best matching list entry.
+  OriginIdentifierValueMap::const_iterator best_match = entries_.end();
+  for (OriginIdentifierValueMap::const_iterator entry = entries_.begin();
+       entry != entries_.end();
+       ++entry) {
+    if (entry->item_pattern.Matches(item_url) &&
+        entry->top_level_frame_pattern.Matches(top_level_frame_url) &&
+        entry->content_type == content_type &&
+        entry->identifier == resource_identifier) {
+      if (best_match == entries_.end() || *entry > *best_match) {
+        best_match = entry;
+      }
+    }
+  }
+  if (best_match != entries_.end())
+    return best_match->value.get();
+  return NULL;
+}
+
+void OriginIdentifierValueMap::SetValue(
+    const ContentSettingsPattern& item_pattern,
+    const ContentSettingsPattern& top_level_frame_pattern,
+    ContentSettingsType content_type,
+    const ResourceIdentifier& resource_identifier,
+    Value* value) {
+  OriginIdentifierValueMap::iterator list_entry =
+      FindEntry(item_pattern,
+                top_level_frame_pattern,
+                content_type,
+                resource_identifier);
+  if (list_entry == entries_.end()) {
+    // No matching list entry found. Add a new entry to the list.
+    entries_.insert(list_entry, Entry(item_pattern,
+                                      top_level_frame_pattern,
+                                      content_type,
+                                      resource_identifier,
+                                      value));
+  } else {
+    // Update the list entry.
+    list_entry->value.reset(value);
+  }
+}
+
+void OriginIdentifierValueMap::DeleteValue(
+      const ContentSettingsPattern& item_pattern,
+      const ContentSettingsPattern& top_level_frame_pattern,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier) {
+  OriginIdentifierValueMap::iterator entry_to_delete =
+      FindEntry(item_pattern,
+                top_level_frame_pattern,
+                content_type,
+                resource_identifier);
+  if (entry_to_delete != entries_.end()) {
+    entries_.erase(entry_to_delete);
+  }
+}
+
+void OriginIdentifierValueMap::Clear() {
+  // Delete all owned value objects.
+  /*
+  for (OriginIdentifierValueMap::iterator entry = entries_.begin();
+       entry != entries_.end();
+       ++entry) {
+    delete entry->value;
+  }
+  */
+  entries_.clear();
+}
+
+OriginIdentifierValueMap::iterator OriginIdentifierValueMap::DeleteValue(
+    OriginIdentifierValueMap::iterator entry) {
+  return entries_.erase(entry);
+}
+
+OriginIdentifierValueMap::iterator OriginIdentifierValueMap::FindEntry(
+      const ContentSettingsPattern& item_pattern,
+      const ContentSettingsPattern& top_level_frame_pattern,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier) {
+  for (OriginIdentifierValueMap::iterator entry = entries_.begin();
+       entry != entries_.end();
+       ++entry) {
+    if (item_pattern == entry->item_pattern &&
+        top_level_frame_pattern == entry->top_level_frame_pattern &&
+        content_type == entry->content_type &&
+        resource_identifier == entry->identifier) {
+      return entry;
+    }
+  }
+  return entries_.end();
+}
+
+}  // namespace content_settings
diff --git a/chrome/browser/content_settings/content_settings_origin_identifier_value_map.h b/chrome/browser/content_settings/content_settings_origin_identifier_value_map.h
new file mode 100644
index 0000000..70c9f88
--- /dev/null
+++ b/chrome/browser/content_settings/content_settings_origin_identifier_value_map.h
@@ -0,0 +1,133 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_ORIGIN_IDENTIFIER_VALUE_MAP_H_
+#define CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_ORIGIN_IDENTIFIER_VALUE_MAP_H_
+
+#include <list>
+#include <map>
+#include <string>
+
+#include "base/tuple.h"
+#include "base/memory/linked_ptr.h"
+#include "chrome/browser/content_settings/content_settings_pattern.h"
+#include "chrome/common/content_settings_types.h"
+
+class GURL;
+class Value;
+
+namespace content_settings {
+
+class OriginIdentifierValueMap {
+ public:
+  typedef std::string ResourceIdentifier;
+
+  struct Entry {
+    Entry(ContentSettingsPattern item_pattern,
+          ContentSettingsPattern top_level_frame_pattern,
+          ContentSettingsType content_type,
+          ResourceIdentifier identifier,
+          Value* value)
+          : item_pattern(item_pattern),
+            top_level_frame_pattern(top_level_frame_pattern),
+            content_type(content_type),
+            identifier(identifier),
+            value(value) {
+    }
+
+    ContentSettingsPattern item_pattern;
+    ContentSettingsPattern top_level_frame_pattern;
+    ContentSettingsType content_type;
+    ResourceIdentifier identifier;
+    linked_ptr<Value> value;
+  };
+
+  typedef std::list<Entry> EntryList;
+
+  typedef EntryList::const_iterator const_iterator;
+
+  typedef EntryList::iterator iterator;
+
+  EntryList::iterator begin() {
+    return entries_.begin();
+  }
+
+  EntryList::iterator end() {
+    return entries_.end();
+  }
+
+  EntryList::const_iterator begin() const {
+    return entries_.begin();
+  }
+
+  EntryList::const_iterator end() const {
+    return entries_.end();
+  }
+
+  size_t size() const {
+    return entries_.size();
+  }
+
+  OriginIdentifierValueMap();
+  ~OriginIdentifierValueMap();
+
+  // Returns a weak pointer to the value for the given |item_pattern|,
+  // |top_level_frame_pattern|, |content_type|, |resource_identifier| tuple. If
+  // no value is stored for the passed parameter |NULL| is returned.
+  Value* GetValue(
+      const GURL& item_url,
+      const GURL& top_level_frame_url,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier) const;
+
+  // Sets the |value| for the given |item_pattern|, |top_level_frame_pattern|,
+  // |content_type|, |resource_identifier| tuple. The method takes the ownership
+  // of the passed |value|.
+  void SetValue(
+      const ContentSettingsPattern& item_pattern,
+      const ContentSettingsPattern& top_level_frame_pattern,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier,
+      Value* value);
+
+  // Deletes the map entry for the given |item_pattern|,
+  // |top_level_frame_pattern|, |content_type|, |resource_identifier| tuple.
+  void DeleteValue(
+      const ContentSettingsPattern& item_pattern,
+      const ContentSettingsPattern& top_level_frame_pattern,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier);
+
+  // Deletes the map entry at the passed position. The method returns the
+  // position of the next entry in the map.
+  EntryList::iterator DeleteValue(EntryList::iterator entry);
+
+  // Clears all map entries.
+  void Clear();
+
+ private:
+  // Finds the list entry for the given |item_pattern|,
+  // |top_level_frame_pattern|, |content_type|, |resource_identifier| tuple and
+  // returns the iterator of the list entry. If no entry is found for the passed
+  // parameters then the end of list iterator is returned.
+  EntryList::iterator FindEntry(
+      const ContentSettingsPattern& item_pattern,
+      const ContentSettingsPattern& top_level_frame_pattern,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier);
+
+  EntryList entries_;
+
+  DISALLOW_COPY_AND_ASSIGN(OriginIdentifierValueMap);
+};
+
+// Compares two origin value map entries and tests if the item, top-level-frame
+// pattern pair of the first entry has a higher precedences then the pattern
+// pair of the second entry.
+bool operator>(const OriginIdentifierValueMap::Entry& first,
+               const OriginIdentifierValueMap::Entry& second);
+
+}  // namespace content_settings
+
+#endif  // CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_ORIGIN_IDENTIFIER_VALUE_MAP_H_
diff --git a/chrome/browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc b/chrome/browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc
new file mode 100644
index 0000000..f028524
--- /dev/null
+++ b/chrome/browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc
@@ -0,0 +1,172 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/content_settings/content_settings_origin_identifier_value_map.h"
+
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(OriginIdentifierValueMapTest, SetGetValue) {
+  content_settings::OriginIdentifierValueMap map;
+
+  EXPECT_EQ(NULL, map.GetValue(GURL("http://www.google.com"),
+                               GURL("http://www.google.com"),
+                               CONTENT_SETTINGS_TYPE_COOKIES,
+                               ""));
+  map.SetValue(
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      CONTENT_SETTINGS_TYPE_COOKIES,
+      "",
+      Value::CreateIntegerValue(1));
+
+  scoped_ptr<Value> expected_value(Value::CreateIntegerValue(1));
+  EXPECT_TRUE(expected_value->Equals(
+      map.GetValue(GURL("http://www.google.com"),
+                   GURL("http://www.google.com"),
+                   CONTENT_SETTINGS_TYPE_COOKIES,
+                   "")));
+
+  EXPECT_EQ(NULL, map.GetValue(GURL("http://www.google.com"),
+                               GURL("http://www.youtube.com"),
+                               CONTENT_SETTINGS_TYPE_COOKIES,
+                               ""));
+
+  EXPECT_EQ(NULL, map.GetValue(GURL("http://www.youtube.com"),
+                               GURL("http://www.google.com"),
+                               CONTENT_SETTINGS_TYPE_COOKIES,
+                               ""));
+
+  EXPECT_EQ(NULL, map.GetValue(GURL("http://www.google.com"),
+                               GURL("http://www.google.com"),
+                               CONTENT_SETTINGS_TYPE_POPUPS,
+                               ""));
+
+  EXPECT_EQ(NULL, map.GetValue(GURL("http://www.google.com"),
+                               GURL("http://www.google.com"),
+                               CONTENT_SETTINGS_TYPE_COOKIES,
+                               "resource_id"));
+}
+
+TEST(OriginIdentifierValueMapTest, SetDeleteValue) {
+  content_settings::OriginIdentifierValueMap map;
+
+  EXPECT_EQ(NULL, map.GetValue(GURL("http://www.google.com"),
+                               GURL("http://www.google.com"),
+                               CONTENT_SETTINGS_TYPE_PLUGINS,
+                               "java-plugin"));
+
+  // Set sample values.
+  map.SetValue(
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      CONTENT_SETTINGS_TYPE_PLUGINS,
+      "java-plugin",
+      Value::CreateIntegerValue(1));
+
+  int actual_value;
+  EXPECT_TRUE(map.GetValue(GURL("http://www.google.com"),
+                           GURL("http://www.google.com"),
+                           CONTENT_SETTINGS_TYPE_PLUGINS,
+                           "java-plugin")->GetAsInteger(&actual_value));
+  EXPECT_EQ(1, actual_value);
+  EXPECT_EQ(NULL, map.GetValue(GURL("http://www.google.com"),
+                               GURL("http://www.google.com"),
+                               CONTENT_SETTINGS_TYPE_PLUGINS,
+                               "flash-plugin"));
+  // Delete non-existing value.
+  map.DeleteValue(
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      CONTENT_SETTINGS_TYPE_PLUGINS,
+      "flash-plugin");
+  EXPECT_EQ(NULL, map.GetValue(GURL("http://www.google.com"),
+                               GURL("http://www.google.com"),
+                               CONTENT_SETTINGS_TYPE_PLUGINS,
+                               "flash-plugin"));
+  EXPECT_TRUE(map.GetValue(GURL("http://www.google.com"),
+                           GURL("http://www.google.com"),
+                           CONTENT_SETTINGS_TYPE_PLUGINS,
+                           "java-plugin")->GetAsInteger(&actual_value));
+  EXPECT_EQ(1, actual_value);
+
+  // Delete existing value.
+  map.DeleteValue(
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      CONTENT_SETTINGS_TYPE_PLUGINS,
+      "java-plugin");
+
+  EXPECT_EQ(NULL, map.GetValue(GURL("http://www.google.com"),
+                               GURL("http://www.google.com"),
+                               CONTENT_SETTINGS_TYPE_PLUGINS,
+                               "java-plugin"));
+}
+
+TEST(OriginIdentifierValueMapTest, Clear) {
+  content_settings::OriginIdentifierValueMap map;
+  EXPECT_EQ(map.begin(), map.end());
+
+  // Set two values.
+  map.SetValue(
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      CONTENT_SETTINGS_TYPE_PLUGINS,
+      "java-plugin",
+      Value::CreateIntegerValue(1));
+  map.SetValue(
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      CONTENT_SETTINGS_TYPE_COOKIES,
+      "",
+      Value::CreateIntegerValue(1));
+  EXPECT_NE(map.begin(), map.end());
+  int actual_value;
+  EXPECT_TRUE(map.GetValue(GURL("http://www.google.com"),
+                           GURL("http://www.google.com"),
+                           CONTENT_SETTINGS_TYPE_PLUGINS,
+                           "java-plugin")->GetAsInteger(&actual_value));
+  EXPECT_EQ(1, actual_value);
+
+  // Clear the map.
+  map.Clear();
+  EXPECT_EQ(map.begin(), map.end());
+  EXPECT_EQ(NULL, map.GetValue(GURL("http://www.google.com"),
+                               GURL("http://www.google.com"),
+                               CONTENT_SETTINGS_TYPE_PLUGINS,
+                               "java-plugin"));
+}
+
+TEST(OriginIdentifierValueMapTest, ListEntryPrecedences) {
+  content_settings::OriginIdentifierValueMap map;
+
+  map.SetValue(
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      CONTENT_SETTINGS_TYPE_COOKIES,
+      "",
+      Value::CreateIntegerValue(1));
+
+  map.SetValue(
+      ContentSettingsPattern::FromString("www.google.com"),
+      ContentSettingsPattern::FromString("[*.]google.com"),
+      CONTENT_SETTINGS_TYPE_COOKIES,
+      "",
+      Value::CreateIntegerValue(2));
+
+  int actual_value;
+  EXPECT_TRUE(map.GetValue(GURL("http://mail.google.com"),
+                           GURL("http://www.google.com"),
+                           CONTENT_SETTINGS_TYPE_COOKIES,
+                           "")->GetAsInteger(&actual_value));
+  EXPECT_EQ(1, actual_value);
+
+  EXPECT_TRUE(map.GetValue(GURL("http://www.google.com"),
+                           GURL("http://www.google.com"),
+                           CONTENT_SETTINGS_TYPE_COOKIES,
+                           "")->GetAsInteger(&actual_value));
+  EXPECT_EQ(2, actual_value);
+}
diff --git a/chrome/browser/content_settings/content_settings_pattern.cc b/chrome/browser/content_settings/content_settings_pattern.cc
index 4721573..70cc42e 100644
--- a/chrome/browser/content_settings/content_settings_pattern.cc
+++ b/chrome/browser/content_settings/content_settings_pattern.cc
@@ -310,35 +310,6 @@
 }
 
 // static
-ContentSettingsPattern ContentSettingsPattern::LegacyFromURL(
-    const GURL& url) {
-  scoped_ptr<ContentSettingsPattern::BuilderInterface> builder(
-      ContentSettingsPattern::CreateBuilder(true));
-
-  if (url.SchemeIsFile()) {
-    builder->WithScheme(url.scheme())->WithPath(url.path());
-  } else {
-    // Please keep the order of the ifs below as URLs with an IP as host can
-    // also have a "http" scheme.
-    // TODO(markusheintz): For HTTPS we will create scheme specific patterns as
-    // soon as the pattern matching code in the HostContentSettingsMap is
-    // replaced.
-    if (url.HostIsIPAddress()) {
-      builder->WithSchemeWildcard()->WithHost(url.host());
-    } else if (url.SchemeIs(chrome::kHttpScheme)) {
-      builder->WithSchemeWildcard()->WithDomainWildcard()->WithHost(url.host());
-    } else if (url.SchemeIs(chrome::kHttpsScheme)) {
-      builder->WithSchemeWildcard()->WithDomainWildcard()->WithHost(
-          url.host());
-    } else {
-      // Unsupported scheme
-    }
-    builder->WithPortWildcard();
-  }
-  return builder->Build();
-}
-
-// static
 ContentSettingsPattern ContentSettingsPattern::FromURLNoWildcard(
     const GURL& url) {
   scoped_ptr<ContentSettingsPattern::BuilderInterface> builder(
@@ -358,21 +329,6 @@
 }
 
 // static
-ContentSettingsPattern ContentSettingsPattern::LegacyFromURLNoWildcard(
-    const GURL& url) {
-  scoped_ptr<ContentSettingsPattern::BuilderInterface> builder(
-      ContentSettingsPattern::CreateBuilder(true));
-
-  if (url.SchemeIsFile()) {
-    builder->WithScheme(url.scheme())->WithPath(url.path());
-  } else {
-    builder->WithSchemeWildcard()->WithHost(url.host());
-  }
-  builder->WithPortWildcard();
-  return builder->Build();
-}
-
-// static
 ContentSettingsPattern ContentSettingsPattern::FromString(
     const std::string& pattern_spec) {
   scoped_ptr<ContentSettingsPattern::BuilderInterface> builder(
diff --git a/chrome/browser/content_settings/content_settings_pattern.h b/chrome/browser/content_settings/content_settings_pattern.h
index 7525089..7f8d7cf 100644
--- a/chrome/browser/content_settings/content_settings_pattern.h
+++ b/chrome/browser/content_settings/content_settings_pattern.h
@@ -99,13 +99,9 @@
   // all subdomains and ports.
   static ContentSettingsPattern FromURL(const GURL& url);
 
-  static ContentSettingsPattern LegacyFromURL(const GURL& url);
-
   // Returns a pattern that matches exactly this URL.
   static ContentSettingsPattern FromURLNoWildcard(const GURL& url);
 
-  static ContentSettingsPattern LegacyFromURLNoWildcard(const GURL& url);
-
   // Returns a pattern that matches the given pattern specification.
   // Valid patterns specifications are:
   //   - [*.]domain.tld (matches domain.tld and all sub-domains)
diff --git a/chrome/browser/content_settings/content_settings_pref_provider.cc b/chrome/browser/content_settings/content_settings_pref_provider.cc
index d487b73..072dbb6 100644
--- a/chrome/browser/content_settings/content_settings_pref_provider.cc
+++ b/chrome/browser/content_settings/content_settings_pref_provider.cc
@@ -85,6 +85,43 @@
   }
 }
 
+std::string CreatePatternString(
+    const ContentSettingsPattern& requesting_pattern,
+    const ContentSettingsPattern& embedding_pattern) {
+  DCHECK(requesting_pattern == embedding_pattern);
+  return requesting_pattern.ToString();
+}
+
+ContentSetting ValueToContentSetting(Value* value) {
+  int int_value;
+  value->GetAsInteger(&int_value);
+  return IntToContentSetting(int_value);
+}
+
+ContentSettingsType StringToContentSettingsType(
+    const std::string& content_type_str) {
+  for (size_t type = 0; type < arraysize(kTypeNames); ++type) {
+    if ((kTypeNames[type] != NULL) && (kTypeNames[type] == content_type_str))
+      return ContentSettingsType(type);
+  }
+  for (size_t type = 0; type < arraysize(kResourceTypeNames); ++type) {
+    if ((kResourceTypeNames[type] != NULL) &&
+        (kResourceTypeNames[type] == content_type_str)) {
+      return ContentSettingsType(type);
+    }
+  }
+  return CONTENT_SETTINGS_TYPE_DEFAULT;
+}
+
+ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type,
+                                           ContentSetting setting) {
+  if (content_type == CONTENT_SETTINGS_TYPE_COOKIES &&
+      setting == CONTENT_SETTING_ASK) {
+    return CONTENT_SETTING_BLOCK;
+  }
+  return setting;
+}
+
 }  // namespace
 
 namespace content_settings {
@@ -344,8 +381,8 @@
 }
 
 PrefProvider::PrefProvider(Profile* profile)
-  : BaseProvider(profile->IsOffTheRecord()),
-    profile_(profile),
+  : profile_(profile),
+    is_incognito_(profile_->IsOffTheRecord()),
     updating_preferences_(false) {
   Init();
 }
@@ -372,9 +409,9 @@
   // Read exceptions.
   ReadExceptions(false);
 
-  if (!is_incognito()) {
+  if (!is_incognito_) {
     UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfExceptions",
-                         host_content_settings()->size());
+                         value_map_.size());
   }
 
   pref_change_registrar_.Init(prefs);
@@ -385,6 +422,66 @@
   initializing_ = false;
 }
 
+ContentSetting PrefProvider::GetContentSetting(
+      const GURL& requesting_url,
+      const GURL& embedding_url,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier) const {
+  // Support for item, top-level-frame URLs are not enabled yet.
+  DCHECK(requesting_url == embedding_url);
+
+  // For a |PrefProvider| used in a |HostContentSettingsMap| of a non incognito
+  // profile, this will always return NULL.
+  // TODO(markusheintz): I don't like this. I'd like to have an
+  // IncognitoProviderWrapper that wrapps the pref provider for a host content
+  // settings map of an incognito profile.
+  Value* incognito_value = incognito_value_map_.GetValue(
+      requesting_url,
+      embedding_url,
+      content_type,
+      resource_identifier);
+  if (incognito_value)
+    return ValueToContentSetting(incognito_value);
+
+  Value* value = value_map_.GetValue(
+      requesting_url,
+      embedding_url,
+      content_type,
+      resource_identifier);
+  if (value)
+    return ValueToContentSetting(value);
+
+  return CONTENT_SETTING_DEFAULT;
+}
+
+void PrefProvider::GetAllContentSettingsRules(
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier,
+      Rules* content_setting_rules) const {
+  DCHECK_NE(RequiresResourceIdentifier(content_type),
+            resource_identifier.empty());
+  DCHECK(content_setting_rules);
+  content_setting_rules->clear();
+
+  const OriginIdentifierValueMap* map_to_return =
+      is_incognito_ ? &incognito_value_map_ : &value_map_;
+
+  base::AutoLock auto_lock(lock_);
+  for (OriginIdentifierValueMap::const_iterator entry = map_to_return->begin();
+       entry != map_to_return->end();
+       ++entry) {
+    if (entry->content_type == content_type &&
+        entry->identifier == resource_identifier) {
+      ContentSetting setting = ValueToContentSetting(entry->value.get());
+      DCHECK(setting != CONTENT_SETTING_DEFAULT);
+      Rule new_rule(entry->item_pattern,
+                    entry->top_level_frame_pattern,
+                    setting);
+      content_setting_rules->push_back(new_rule);
+    }
+  }
+}
+
 void PrefProvider::SetContentSetting(
     const ContentSettingsPattern& requesting_pattern,
     const ContentSettingsPattern& embedding_pattern,
@@ -403,97 +500,96 @@
          CommandLine::ForCurrentProcess()->HasSwitch(
             switches::kEnableClickToPlay));
 
-  bool early_exit = false;
-  std::string pattern_str(requesting_pattern.ToString());
-  DictionaryValue* all_settings_dictionary = NULL;
-
   updating_preferences_ = true;
   {
-    // Begin scope of update.
-    // profile_ may be NULL in unit tests.
     DictionaryPrefUpdate update(profile_ ? profile_->GetPrefs() : NULL,
                                 prefs::kContentSettingsPatterns);
+    DictionaryValue* all_settings_dictionary = NULL;
 
-    // Select content-settings-map to write to.
-    HostContentSettings* map_to_modify = incognito_settings();
-    if (!is_incognito()) {
+    OriginIdentifierValueMap* map_to_modify = &incognito_value_map_;
+    if (!is_incognito_) {
+      map_to_modify = &value_map_;
       all_settings_dictionary = update.Get();
-
-      map_to_modify = host_content_settings();
     }
 
-    // Update content-settings-map.
+    // Update in memory value map.
     {
-      base::AutoLock auto_lock(lock());
-      if (!map_to_modify->count(pattern_str))
-        (*map_to_modify)[pattern_str].content_settings = ContentSettings();
-      HostContentSettings::iterator i(map_to_modify->find(pattern_str));
-      ContentSettings& settings = i->second.content_settings;
-      if (RequiresResourceIdentifier(content_type)) {
-        settings.settings[content_type] = CONTENT_SETTING_DEFAULT;
-        if (setting != CONTENT_SETTING_DEFAULT) {
-          i->second.content_settings_for_resources[
-              ContentSettingsTypeResourceIdentifierPair(content_type,
-              resource_identifier)] = setting;
-        } else {
-          i->second.content_settings_for_resources.erase(
-              ContentSettingsTypeResourceIdentifierPair(content_type,
-              resource_identifier));
-        }
+      base::AutoLock auto_lock(lock_);
+      if (setting == CONTENT_SETTING_DEFAULT) {
+        map_to_modify->DeleteValue(
+            requesting_pattern,
+            embedding_pattern,
+            content_type,
+            resource_identifier);
       } else {
-        settings.settings[content_type] = setting;
+        map_to_modify->SetValue(
+            requesting_pattern,
+            embedding_pattern,
+            content_type,
+            resource_identifier,
+            Value::CreateIntegerValue(setting));
       }
-      if (AllDefault(i->second)) {
-        map_to_modify->erase(i);
-        if (all_settings_dictionary)
+    }
+
+    // Update the content settings preference.
+    std::string pattern_str(CreatePatternString(requesting_pattern,
+                                                embedding_pattern));
+    if (all_settings_dictionary) {
+      // Get settings dictionary for the pattern string (key).
+      DictionaryValue* settings_dictionary = NULL;
+      bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+          pattern_str, &settings_dictionary);
+
+      if (!found && (setting != CONTENT_SETTING_DEFAULT)) {
+        settings_dictionary = new DictionaryValue;
+        all_settings_dictionary->SetWithoutPathExpansion(
+            pattern_str, settings_dictionary);
+      }
+
+      if (settings_dictionary) {
+        if (RequiresResourceIdentifier(content_type)) {
+          // Get resource dictionary.
+          std::string res_dictionary_path(kResourceTypeNames[content_type]);
+          DictionaryValue* resource_dictionary = NULL;
+          found = settings_dictionary->GetDictionary(
+              res_dictionary_path, &resource_dictionary);
+          if (!found) {
+            if (setting == CONTENT_SETTING_DEFAULT)
+              return;  // Nothing to remove. Exit early.
+            resource_dictionary = new DictionaryValue;
+            settings_dictionary->Set(res_dictionary_path, resource_dictionary);
+          }
+          // Update resource dictionary.
+          if (setting == CONTENT_SETTING_DEFAULT) {
+            resource_dictionary->RemoveWithoutPathExpansion(resource_identifier,
+                                                            NULL);
+            if (resource_dictionary->empty()) {
+              settings_dictionary->RemoveWithoutPathExpansion(
+                  res_dictionary_path, NULL);
+            }
+          } else {
+            resource_dictionary->SetWithoutPathExpansion(
+                resource_identifier, Value::CreateIntegerValue(setting));
+          }
+        } else {
+          // Update settings dictionary.
+          std::string setting_path(kTypeNames[content_type]);
+          if (setting == CONTENT_SETTING_DEFAULT) {
+            settings_dictionary->RemoveWithoutPathExpansion(setting_path,
+                                                            NULL);
+          } else {
+            settings_dictionary->SetWithoutPathExpansion(
+                setting_path, Value::CreateIntegerValue(setting));
+          }
+        }
+        // Remove the settings dictionary if it is empty.
+        if (settings_dictionary->empty()) {
           all_settings_dictionary->RemoveWithoutPathExpansion(
               pattern_str, NULL);
-
-        // We can't just return because |NotifyObservers()| needs to be called,
-        // without lock() being held.
-        early_exit = true;
-      }
-    }
-
-    // Update the content_settings preference.
-    if (!early_exit && all_settings_dictionary) {
-      DictionaryValue* host_settings_dictionary = NULL;
-      bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
-          pattern_str, &host_settings_dictionary);
-      if (!found) {
-        host_settings_dictionary = new DictionaryValue;
-        all_settings_dictionary->SetWithoutPathExpansion(
-            pattern_str, host_settings_dictionary);
-        DCHECK_NE(setting, CONTENT_SETTING_DEFAULT);
-      }
-      if (RequiresResourceIdentifier(content_type)) {
-        std::string dictionary_path(kResourceTypeNames[content_type]);
-        DictionaryValue* resource_dictionary = NULL;
-        found = host_settings_dictionary->GetDictionary(
-            dictionary_path, &resource_dictionary);
-        if (!found) {
-          resource_dictionary = new DictionaryValue;
-          host_settings_dictionary->Set(dictionary_path, resource_dictionary);
-        }
-        if (setting == CONTENT_SETTING_DEFAULT) {
-          resource_dictionary->RemoveWithoutPathExpansion(resource_identifier,
-                                                          NULL);
-        } else {
-          resource_dictionary->SetWithoutPathExpansion(
-              resource_identifier, Value::CreateIntegerValue(setting));
-        }
-      } else {
-        std::string dictionary_path(kTypeNames[content_type]);
-        if (setting == CONTENT_SETTING_DEFAULT) {
-          host_settings_dictionary->RemoveWithoutPathExpansion(dictionary_path,
-                                                               NULL);
-        } else {
-          host_settings_dictionary->SetWithoutPathExpansion(
-              dictionary_path, Value::CreateIntegerValue(setting));
         }
       }
     }
-  }  // End scope of update.
+  }
   updating_preferences_ = false;
 
   ContentSettingsDetails details(
@@ -505,12 +601,12 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   {
-    base::AutoLock auto_lock(lock());
-    host_content_settings()->clear();
-    incognito_settings()->clear();
+    base::AutoLock auto_lock(lock_);
+    value_map_.Clear();
+    incognito_value_map_.Clear();
   }
 
-  if (!is_incognito()) {
+  if (!is_incognito_) {
     PrefService* prefs = profile_->GetPrefs();
     updating_preferences_ = true;
     prefs->ClearPref(prefs::kContentSettingsPatterns);
@@ -522,47 +618,47 @@
     ContentSettingsType content_type) {
   DCHECK(kTypeNames[content_type] != NULL);  // Don't call this for Geolocation.
 
-  DictionaryValue* all_settings_dictionary = NULL;
-  HostContentSettings* map_to_modify = incognito_settings();
-
   updating_preferences_ = true;
   {  // Begin scope of update.
     DictionaryPrefUpdate update(profile_->GetPrefs(),
                                 prefs::kContentSettingsPatterns);
 
-    if (!is_incognito()) {
+    DictionaryValue* all_settings_dictionary = NULL;
+    OriginIdentifierValueMap* map_to_modify = &incognito_value_map_;
+    if (!is_incognito_) {
       all_settings_dictionary = update.Get();
-      map_to_modify = host_content_settings();
+      map_to_modify = &value_map_;
     }
 
     {
-      base::AutoLock auto_lock(lock());
-      for (HostContentSettings::iterator i(map_to_modify->begin());
-           i != map_to_modify->end(); ) {
-        if (RequiresResourceIdentifier(content_type) ||
-            i->second.content_settings.settings[content_type] !=
-                CONTENT_SETTING_DEFAULT) {
-          if (RequiresResourceIdentifier(content_type))
-            i->second.content_settings_for_resources.clear();
-          i->second.content_settings.settings[content_type] =
-              CONTENT_SETTING_DEFAULT;
-          std::string host(i->first);
-          if (AllDefault(i->second)) {
-            if (all_settings_dictionary)
-              all_settings_dictionary->RemoveWithoutPathExpansion(host, NULL);
-            map_to_modify->erase(i++);
-          } else if (all_settings_dictionary) {
-            DictionaryValue* host_settings_dictionary;
+      base::AutoLock auto_lock(lock_);
+
+      OriginIdentifierValueMap::iterator entry(map_to_modify->begin());
+      while (entry != map_to_modify->end()) {
+        if (entry->content_type == content_type) {
+          std::string pattern_str = CreatePatternString(
+              entry->item_pattern, entry->top_level_frame_pattern);
+          // Delete current |entry| and set |entry| to the next value map entry.
+          entry = map_to_modify->DeleteValue(entry);
+
+          // Update the content settings preference.
+          if (all_settings_dictionary) {
+            // Update the settings dictionary.
+            DictionaryValue* settings_dictionary;
             bool found =
                 all_settings_dictionary->GetDictionaryWithoutPathExpansion(
-                    host, &host_settings_dictionary);
+                    pattern_str, &settings_dictionary);
             DCHECK(found);
-            host_settings_dictionary->RemoveWithoutPathExpansion(
+            settings_dictionary->RemoveWithoutPathExpansion(
                 kTypeNames[content_type], NULL);
-            ++i;
+            // Remove empty dictionaries.
+            if (settings_dictionary->empty())
+              all_settings_dictionary->RemoveWithoutPathExpansion(pattern_str,
+                                                                  NULL);
           }
         } else {
-          ++i;
+          // No action is required, so move to the next value map entry.
+          ++entry;
         }
       }
     }
@@ -593,7 +689,7 @@
       return;
     }
 
-    if (!is_incognito()) {
+    if (!is_incognito_) {
       ContentSettingsDetails details(ContentSettingsPattern(),
                                      CONTENT_SETTINGS_TYPE_DEFAULT,
                                      std::string());
@@ -615,52 +711,98 @@
 // Private
 
 void PrefProvider::ReadExceptions(bool overwrite) {
-  base::AutoLock auto_lock(lock());
+  base::AutoLock auto_lock(lock_);
 
   PrefService* prefs = profile_->GetPrefs();
   const DictionaryValue* all_settings_dictionary =
       prefs->GetDictionary(prefs::kContentSettingsPatterns);
 
   if (overwrite)
-    host_content_settings()->clear();
+    value_map_.Clear();
 
   updating_preferences_ = true;
-
   // Careful: The returned value could be NULL if the pref has never been set.
   if (all_settings_dictionary != NULL) {
     DictionaryPrefUpdate update(prefs, prefs::kContentSettingsPatterns);
     DictionaryValue* mutable_settings;
     scoped_ptr<DictionaryValue> mutable_settings_scope;
 
-    if (!is_incognito()) {
+    if (!is_incognito_) {
       mutable_settings = update.Get();
     } else {
       // Create copy as we do not want to persist anything in OTR prefs.
       mutable_settings = all_settings_dictionary->DeepCopy();
       mutable_settings_scope.reset(mutable_settings);
     }
-
     // Convert all Unicode patterns into punycode form, then read.
     CanonicalizeContentSettingsExceptions(mutable_settings);
 
     for (DictionaryValue::key_iterator i(mutable_settings->begin_keys());
          i != mutable_settings->end_keys(); ++i) {
-      const std::string& pattern(*i);
-      if (!ContentSettingsPattern::LegacyFromString(pattern).IsValid())
+      const std::string& pattern_str(*i);
+      ContentSettingsPattern pattern =
+          ContentSettingsPattern::FromString(pattern_str);
+      if (!pattern.IsValid())
         LOG(WARNING) << "Invalid pattern stored in content settings";
-      DictionaryValue* pattern_settings_dictionary = NULL;
+
+      // Get settings dictionary for the current pattern string, and read
+      // settings from the dictionary.
+      DictionaryValue* settings_dictionary = NULL;
       bool found = mutable_settings->GetDictionaryWithoutPathExpansion(
-          pattern, &pattern_settings_dictionary);
+          pattern_str, &settings_dictionary);
       DCHECK(found);
 
-      ExtendedContentSettings extended_settings;
-      GetSettingsFromDictionary(pattern_settings_dictionary,
-                                &extended_settings.content_settings);
-      GetResourceSettingsFromDictionary(
-          pattern_settings_dictionary,
-          &extended_settings.content_settings_for_resources);
+      for (DictionaryValue::key_iterator i(settings_dictionary->begin_keys());
+           i != settings_dictionary->end_keys();
+           ++i) {
+        const std::string& content_type_str(*i);
+        ContentSettingsType content_type = StringToContentSettingsType(
+            content_type_str);
+        if (content_type == CONTENT_SETTINGS_TYPE_DEFAULT) {
+          NOTREACHED();
+          LOG(WARNING) << "Skip settings for invalid content settings type '"
+                       << content_type_str << "'";
+          continue;
+        }
 
-      (*host_content_settings())[pattern] = extended_settings;
+        if (RequiresResourceIdentifier(content_type)) {
+          DictionaryValue* resource_dictionary = NULL;
+          bool found = settings_dictionary->GetDictionary(
+              content_type_str, &resource_dictionary);
+          DCHECK(found);
+          for (DictionaryValue::key_iterator j(
+                   resource_dictionary->begin_keys());
+               j != resource_dictionary->end_keys();
+               ++j) {
+            const std::string& resource_identifier(*j);
+            int setting = CONTENT_SETTING_DEFAULT;
+            found = resource_dictionary->GetIntegerWithoutPathExpansion(
+                resource_identifier, &setting);
+            DCHECK(found);
+            setting = ClickToPlayFixup(content_type,
+                                       ContentSetting(setting));
+            value_map_.SetValue(pattern,
+                                pattern,
+                                content_type,
+                                resource_identifier,
+                                Value::CreateIntegerValue(setting));
+          }
+        } else {
+          int setting = CONTENT_SETTING_DEFAULT;
+          bool found = settings_dictionary->GetIntegerWithoutPathExpansion(
+              content_type_str, &setting);
+          DCHECK(found);
+          setting = FixObsoleteCookiePromptMode(content_type,
+                                                ContentSetting(setting));
+          setting = ClickToPlayFixup(content_type,
+                                     ContentSetting(setting));
+          value_map_.SetValue(pattern,
+                              pattern,
+                              content_type,
+                              ResourceIdentifier(""),
+                              Value::CreateIntegerValue(setting));
+        }
+      }
     }
   }
   updating_preferences_ = false;
@@ -676,7 +818,7 @@
        i != all_settings_dictionary->end_keys(); ++i) {
     const std::string& pattern(*i);
     const std::string canonicalized_pattern =
-        ContentSettingsPattern::LegacyFromString(pattern).ToString();
+        ContentSettingsPattern::FromString(pattern).ToString();
 
     if (canonicalized_pattern.empty() || canonicalized_pattern == pattern)
       continue;
@@ -710,65 +852,6 @@
   }
 }
 
-void PrefProvider::GetSettingsFromDictionary(
-    const DictionaryValue* dictionary,
-    ContentSettings* settings) {
-  for (DictionaryValue::key_iterator i(dictionary->begin_keys());
-       i != dictionary->end_keys(); ++i) {
-    const std::string& content_type(*i);
-    for (size_t type = 0; type < arraysize(kTypeNames); ++type) {
-      if ((kTypeNames[type] != NULL) && (kTypeNames[type] == content_type)) {
-        int setting = CONTENT_SETTING_DEFAULT;
-        bool found = dictionary->GetIntegerWithoutPathExpansion(content_type,
-                                                                &setting);
-        DCHECK(found);
-        settings->settings[type] = IntToContentSetting(setting);
-        break;
-      }
-    }
-  }
-  // Migrate obsolete cookie prompt mode.
-  if (settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] ==
-      CONTENT_SETTING_ASK)
-    settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] = CONTENT_SETTING_BLOCK;
-
-  settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS] =
-      ClickToPlayFixup(CONTENT_SETTINGS_TYPE_PLUGINS,
-                       settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS]);
-}
-
-void PrefProvider::GetResourceSettingsFromDictionary(
-    const DictionaryValue* dictionary,
-    ResourceContentSettings* settings) {
-  for (DictionaryValue::key_iterator i(dictionary->begin_keys());
-       i != dictionary->end_keys(); ++i) {
-    const std::string& content_type(*i);
-    for (size_t type = 0; type < arraysize(kResourceTypeNames); ++type) {
-      if ((kResourceTypeNames[type] != NULL) &&
-          (kResourceTypeNames[type] == content_type)) {
-        DictionaryValue* resource_dictionary = NULL;
-        bool found = dictionary->GetDictionary(content_type,
-                                               &resource_dictionary);
-        DCHECK(found);
-        for (DictionaryValue::key_iterator j(resource_dictionary->begin_keys());
-             j != resource_dictionary->end_keys(); ++j) {
-          const std::string& resource_identifier(*j);
-          int setting = CONTENT_SETTING_DEFAULT;
-          bool found = resource_dictionary->GetIntegerWithoutPathExpansion(
-              resource_identifier, &setting);
-          DCHECK(found);
-          (*settings)[ContentSettingsTypeResourceIdentifierPair(
-              ContentSettingsType(type), resource_identifier)] =
-                  ClickToPlayFixup(ContentSettingsType(type),
-                                   ContentSetting(setting));
-        }
-
-        break;
-      }
-    }
-  }
-}
-
 void PrefProvider::NotifyObservers(
     const ContentSettingsDetails& details) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -801,23 +884,48 @@
          i != all_settings_dictionary->end_keys(); ++i) {
       const std::string& host(*i);
       ContentSettingsPattern pattern =
-          ContentSettingsPattern::LegacyFromString(
+          ContentSettingsPattern::FromString(
               std::string(ContentSettingsPattern::kDomainWildcard) + host);
       DictionaryValue* host_settings_dictionary = NULL;
       bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
           host, &host_settings_dictionary);
       DCHECK(found);
-      ContentSettings settings;
-      GetSettingsFromDictionary(host_settings_dictionary, &settings);
-      for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
-        if (settings.settings[j] != CONTENT_SETTING_DEFAULT &&
-            !RequiresResourceIdentifier(ContentSettingsType(j))) {
-          SetContentSetting(
-              pattern,
-              pattern,
-              ContentSettingsType(j),
-              "",
-              settings.settings[j]);
+
+      for (DictionaryValue::key_iterator i(
+               host_settings_dictionary->begin_keys());
+           i != host_settings_dictionary->end_keys();
+           ++i) {
+        const std::string& content_type_str(*i);
+        ContentSettingsType content_type =
+            StringToContentSettingsType(content_type_str);
+
+        if (content_type == CONTENT_SETTINGS_TYPE_DEFAULT) {
+          NOTREACHED();
+          LOG(DFATAL) << "Skip settings for invalid content settings type '"
+                      << content_type_str << "'";
+          continue;
+        }
+
+        if (!RequiresResourceIdentifier(content_type)) {
+          int setting_int_value = CONTENT_SETTING_DEFAULT;
+          bool found =
+              host_settings_dictionary->GetIntegerWithoutPathExpansion(
+                  content_type_str, &setting_int_value);
+          DCHECK(found);
+          ContentSetting setting = IntToContentSetting(setting_int_value);
+
+          setting = FixObsoleteCookiePromptMode(content_type, setting);
+          setting = ClickToPlayFixup(content_type, setting);
+
+          // TODO(markusheintz): Maybe this check can be removed.
+          if (setting != CONTENT_SETTING_DEFAULT) {
+            SetContentSetting(
+                pattern,
+                pattern,
+                content_type,
+                "",
+                setting);
+          }
         }
       }
     }
@@ -833,8 +941,8 @@
          i != whitelist_pref->end(); ++i) {
       std::string host;
       (*i)->GetAsString(&host);
-      SetContentSetting(ContentSettingsPattern::LegacyFromString(host),
-                        ContentSettingsPattern::LegacyFromString(host),
+      SetContentSetting(ContentSettingsPattern::FromString(host),
+                        ContentSettingsPattern::FromString(host),
                         CONTENT_SETTINGS_TYPE_POPUPS,
                         "",
                         CONTENT_SETTING_ALLOW);
diff --git a/chrome/browser/content_settings/content_settings_pref_provider.h b/chrome/browser/content_settings/content_settings_pref_provider.h
index 479ddd1..4e00ae51 100644
--- a/chrome/browser/content_settings/content_settings_pref_provider.h
+++ b/chrome/browser/content_settings/content_settings_pref_provider.h
@@ -14,8 +14,9 @@
 
 #include "base/basictypes.h"
 #include "base/synchronization/lock.h"
-#include "chrome/browser/content_settings/content_settings_base_provider.h"
+#include "chrome/browser/content_settings/content_settings_origin_identifier_value_map.h"
 #include "chrome/browser/content_settings/content_settings_provider.h"
+#include "chrome/browser/content_settings/content_settings_utils.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
 #include "content/common/notification_observer.h"
 #include "content/common/notification_registrar.h"
@@ -99,7 +100,7 @@
 
 // Content settings provider that provides content settings from the user
 // preference.
-class PrefProvider : public BaseProvider,
+class PrefProvider : public ProviderInterface,
                      public NotificationObserver {
  public:
   static void RegisterUserPrefs(PrefService* prefs);
@@ -107,6 +108,7 @@
   explicit PrefProvider(Profile* profile);
   virtual ~PrefProvider();
 
+  // ProviderInterface implementations.
   virtual void SetContentSetting(
       const ContentSettingsPattern& requesting_pattern,
       const ContentSettingsPattern& embedding_pattern,
@@ -114,20 +116,30 @@
       const ResourceIdentifier& resource_identifier,
       ContentSetting content_setting);
 
+  virtual ContentSetting GetContentSetting(
+      const GURL& requesting_url,
+      const GURL& embedding_url,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier) const;
+
+  virtual void GetAllContentSettingsRules(
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier,
+      Rules* content_setting_rules) const;
+
   virtual void ClearAllContentSettingsRules(
       ContentSettingsType content_type);
 
   virtual void ResetToDefaults();
 
-  // BaseProvider implementations.
-  virtual void Init();
-
   // NotificationObserver implementation.
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
                        const NotificationDetails& details);
 
  private:
+  void Init();
+
   void ReadExceptions(bool overwrite);
 
   // Various migration methods (old cookie, popup and per-host data gets
@@ -138,20 +150,14 @@
   void CanonicalizeContentSettingsExceptions(
       DictionaryValue* all_settings_dictionary);
 
-  void GetSettingsFromDictionary(
-      const DictionaryValue* dictionary,
-      ContentSettings* settings);
-
-  void GetResourceSettingsFromDictionary(
-      const DictionaryValue* dictionary,
-      ResourceContentSettings* settings);
-
   void NotifyObservers(const ContentSettingsDetails& details);
 
   void UnregisterObservers();
 
   Profile* profile_;
 
+  bool is_incognito_;
+
   PrefChangeRegistrar pref_change_registrar_;
   NotificationRegistrar notification_registrar_;
 
@@ -162,6 +168,14 @@
   // Do not fire any Notifications as long as we are in the constructor.
   bool initializing_;
 
+  OriginIdentifierValueMap value_map_;
+
+  OriginIdentifierValueMap incognito_value_map_;
+
+  // Used around accesses to the value map objects to guarantee
+  // thread safety.
+  mutable base::Lock lock_;
+
   DISALLOW_COPY_AND_ASSIGN(PrefProvider);
 };
 
diff --git a/chrome/browser/content_settings/host_content_settings_map.cc b/chrome/browser/content_settings/host_content_settings_map.cc
index e2b95c4..b226a6e8 100644
--- a/chrome/browser/content_settings/host_content_settings_map.cc
+++ b/chrome/browser/content_settings/host_content_settings_map.cc
@@ -260,34 +260,33 @@
     const std::string& resource_identifier,
     SettingsForOneType* settings) const {
   DCHECK(settings);
-  settings->clear();
-
   // Collect content_settings::Rules for the given content_type and
   // resource_identifier from the content settings providers.
-  Rules content_settings_rules;
+  std::map<std::string, PatternSettingPair>
+      pattern_str_pattern_setting_pair_map;
   for (ConstProviderIterator provider = content_settings_providers_.begin();
-       provider != content_settings_providers_.end();
-       ++provider) {
-    // TODO(markusheintz): Only the rules that are applied should be collected.
-    // Merge rules.
-    // TODO(markusheintz): GetAllContentSettingsRules should maybe not clear the
-    // passed vector in case rule sets are just unified.
+     provider != content_settings_providers_.end();
+     ++provider) {
     Rules rules;
     (*provider)->GetAllContentSettingsRules(
         content_type, resource_identifier, &rules);
-    content_settings_rules.insert(content_settings_rules.end(),
-                                  rules.begin(),
-                                  rules.end());
+    // TODO(markusheintz): Only the rules that are applied should be collected.
+    for (Rules::iterator rule = rules.begin();
+         rule != rules.end();
+         ++rule) {
+      const ContentSettingsPattern& pattern(rule->requesting_url_pattern);
+      pattern_str_pattern_setting_pair_map[pattern.ToString()] =
+          PatternSettingPair(pattern, rule->content_setting);
+    }
   }
 
-  // convert Rules to SettingsForOneType
-  for (const_rules_iterator rule_iterator =
-           content_settings_rules.begin();
-       rule_iterator != content_settings_rules.end();
-       ++rule_iterator) {
-    settings->push_back(std::make_pair(ContentSettingsPattern(
-        rule_iterator->requesting_url_pattern),
-        rule_iterator->content_setting));
+  settings->clear();
+  // Rely on the maps iterator to sort the rules.
+  for (std::map<std::string, PatternSettingPair>::iterator i(
+           pattern_str_pattern_setting_pair_map.begin());
+       i != pattern_str_pattern_setting_pair_map.end();
+       ++i) {
+    settings->push_back(i->second);
   }
 }
 
@@ -321,11 +320,11 @@
     ContentSetting setting) {
   // Make sure there is no entry that would override the pattern we are about
   // to insert for exactly this URL.
-  SetContentSetting(ContentSettingsPattern::LegacyFromURLNoWildcard(url),
+  SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(url),
                     content_type,
                     resource_identifier,
                     CONTENT_SETTING_DEFAULT);
-  SetContentSetting(ContentSettingsPattern::LegacyFromURL(url),
+  SetContentSetting(ContentSettingsPattern::FromURL(url),
                     content_type,
                     resource_identifier,
                     setting);
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
index 1320096..fcf5818 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
@@ -111,6 +111,10 @@
   HostContentSettingsMap* map = profile_->GetHostContentSettingsMap();
   std::string fooPlugin = "foo";
   std::string barPlugin = "bar";
+
+  // Navigating to some sample url prevents the GetURL method from returning an
+  // invalid empty URL.
+  contents()->NavigateAndCommit(GURL("http://www.example.com"));
   GURL url = contents()->GetURL();
   map->AddExceptionForURL(url,
                           CONTENT_SETTINGS_TYPE_PLUGINS,
diff --git a/chrome/browser/ui/webui/options/content_settings_handler.cc b/chrome/browser/ui/webui/options/content_settings_handler.cc
index a135bd6..68b4716 100644
--- a/chrome/browser/ui/webui/options/content_settings_handler.cc
+++ b/chrome/browser/ui/webui/options/content_settings_handler.cc
@@ -662,7 +662,7 @@
     // got destroyed before we received this message.
     if (settings_map) {
       settings_map->SetContentSetting(
-          ContentSettingsPattern::LegacyFromString(pattern),
+          ContentSettingsPattern::FromString(pattern),
           ContentSettingsTypeFromGroupName(type_string),
           "",
           CONTENT_SETTING_DEFAULT);
@@ -697,7 +697,7 @@
   if (!settings_map)
     return;
 
-  settings_map->SetContentSetting(ContentSettingsPattern::LegacyFromString(
+  settings_map->SetContentSetting(ContentSettingsPattern::FromString(
                                       pattern),
                                   type,
                                   "",
@@ -715,7 +715,7 @@
   CHECK(args->GetString(arg_i++, &pattern_string));
 
   ContentSettingsPattern pattern =
-      ContentSettingsPattern::LegacyFromString(pattern_string);
+      ContentSettingsPattern::FromString(pattern_string);
 
   scoped_ptr<Value> mode_value(Value::CreateStringValue(mode_string));
   scoped_ptr<Value> pattern_value(Value::CreateStringValue(pattern_string));
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index bf4c2ce..90e9c388 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -761,6 +761,8 @@
         'browser/content_settings/content_settings_extension_provider.h',
         'browser/content_settings/content_settings_notification_provider.cc',
         'browser/content_settings/content_settings_notification_provider.h',
+        'browser/content_settings/content_settings_origin_identifier_value_map.cc',
+        'browser/content_settings/content_settings_origin_identifier_value.h',
         'browser/content_settings/content_settings_pattern.cc',
         'browser/content_settings/content_settings_pattern.h',
         'browser/content_settings/content_settings_pattern_parser.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index e7cd17d..4c633ae 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1351,6 +1351,7 @@
         'browser/command_updater_unittest.cc',
         'browser/content_settings/content_settings_mock_provider.cc',
         'browser/content_settings/content_settings_mock_provider.h',
+        'browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc',
         'browser/content_settings/content_settings_pattern_unittest.cc',
         'browser/content_settings/content_settings_pattern_parser_unittest.cc',
         'browser/content_settings/content_settings_policy_provider_unittest.cc',