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/extensions/api/content_settings/content_settings_store.h" 6 7#include "base/memory/scoped_ptr.h" 8#include "chrome/browser/content_settings/content_settings_utils.h" 9#include "components/content_settings/core/browser/content_settings_rule.h" 10#include "testing/gmock/include/gmock/gmock.h" 11#include "testing/gtest/include/gtest/gtest.h" 12#include "url/gurl.h" 13 14using ::testing::Mock; 15 16namespace extensions { 17 18namespace { 19 20void CheckRule(const content_settings::Rule& rule, 21 const ContentSettingsPattern& primary_pattern, 22 const ContentSettingsPattern& secondary_pattern, 23 ContentSetting setting) { 24 EXPECT_EQ(primary_pattern.ToString(), rule.primary_pattern.ToString()); 25 EXPECT_EQ(secondary_pattern.ToString(), rule.secondary_pattern.ToString()); 26 EXPECT_EQ(setting, content_settings::ValueToContentSetting(rule.value.get())); 27} 28 29// Helper class which returns monotonically-increasing base::Time objects. 30class FakeTimer { 31 public: 32 FakeTimer() : internal_(0) {} 33 34 base::Time GetNext() { 35 return base::Time::FromInternalValue(++internal_); 36 } 37 38 private: 39 int64 internal_; 40}; 41 42class MockContentSettingsStoreObserver 43 : public ContentSettingsStore::Observer { 44 public: 45 MOCK_METHOD2(OnContentSettingChanged, 46 void(const std::string& extension_id, bool incognito)); 47}; 48 49ContentSetting GetContentSettingFromStore( 50 const ContentSettingsStore* store, 51 const GURL& primary_url, const GURL& secondary_url, 52 ContentSettingsType content_type, 53 const std::string& resource_identifier, 54 bool incognito) { 55 scoped_ptr<content_settings::RuleIterator> rule_iterator( 56 store->GetRuleIterator(content_type, resource_identifier, incognito)); 57 scoped_ptr<base::Value> setting( 58 content_settings::GetContentSettingValueAndPatterns( 59 rule_iterator.get(), primary_url, secondary_url, NULL, NULL)); 60 return content_settings::ValueToContentSetting(setting.get()); 61} 62 63void GetSettingsForOneTypeFromStore( 64 const ContentSettingsStore* store, 65 ContentSettingsType content_type, 66 const std::string& resource_identifier, 67 bool incognito, 68 std::vector<content_settings::Rule>* rules) { 69 rules->clear(); 70 scoped_ptr<content_settings::RuleIterator> rule_iterator( 71 store->GetRuleIterator(content_type, resource_identifier, incognito)); 72 while (rule_iterator->HasNext()) 73 rules->push_back(rule_iterator->Next()); 74} 75 76} // namespace 77 78class ContentSettingsStoreTest : public ::testing::Test { 79 public: 80 ContentSettingsStoreTest() : 81 store_(new ContentSettingsStore()) { 82 } 83 84 protected: 85 void RegisterExtension(const std::string& ext_id) { 86 store_->RegisterExtension(ext_id, timer_.GetNext(), true); 87 } 88 89 ContentSettingsStore* store() { 90 return store_.get(); 91 } 92 93 private: 94 FakeTimer timer_; 95 scoped_refptr<ContentSettingsStore> store_; 96}; 97 98TEST_F(ContentSettingsStoreTest, RegisterUnregister) { 99 ::testing::StrictMock<MockContentSettingsStoreObserver> observer; 100 store()->AddObserver(&observer); 101 102 GURL url("http://www.youtube.com"); 103 104 EXPECT_EQ(CONTENT_SETTING_DEFAULT, 105 GetContentSettingFromStore(store(), 106 url, 107 url, 108 CONTENT_SETTINGS_TYPE_COOKIES, 109 std::string(), 110 false)); 111 112 // Register first extension 113 std::string ext_id("my_extension"); 114 RegisterExtension(ext_id); 115 116 EXPECT_EQ(CONTENT_SETTING_DEFAULT, 117 GetContentSettingFromStore(store(), 118 url, 119 url, 120 CONTENT_SETTINGS_TYPE_COOKIES, 121 std::string(), 122 false)); 123 124 // Set setting 125 ContentSettingsPattern pattern = 126 ContentSettingsPattern::FromURL(GURL("http://www.youtube.com")); 127 EXPECT_CALL(observer, OnContentSettingChanged(ext_id, false)); 128 store()->SetExtensionContentSetting(ext_id, 129 pattern, 130 pattern, 131 CONTENT_SETTINGS_TYPE_COOKIES, 132 std::string(), 133 CONTENT_SETTING_ALLOW, 134 kExtensionPrefsScopeRegular); 135 Mock::VerifyAndClear(&observer); 136 137 EXPECT_EQ(CONTENT_SETTING_ALLOW, 138 GetContentSettingFromStore(store(), 139 url, 140 url, 141 CONTENT_SETTINGS_TYPE_COOKIES, 142 std::string(), 143 false)); 144 145 // Register second extension. 146 std::string ext_id_2("my_second_extension"); 147 RegisterExtension(ext_id_2); 148 EXPECT_CALL(observer, OnContentSettingChanged(ext_id_2, false)); 149 store()->SetExtensionContentSetting(ext_id_2, 150 pattern, 151 pattern, 152 CONTENT_SETTINGS_TYPE_COOKIES, 153 std::string(), 154 CONTENT_SETTING_BLOCK, 155 kExtensionPrefsScopeRegular); 156 157 EXPECT_EQ(CONTENT_SETTING_BLOCK, 158 GetContentSettingFromStore(store(), 159 url, 160 url, 161 CONTENT_SETTINGS_TYPE_COOKIES, 162 std::string(), 163 false)); 164 165 // Unregister first extension. This shouldn't change the setting. 166 EXPECT_CALL(observer, OnContentSettingChanged(ext_id, false)); 167 store()->UnregisterExtension(ext_id); 168 EXPECT_EQ(CONTENT_SETTING_BLOCK, 169 GetContentSettingFromStore(store(), 170 url, 171 url, 172 CONTENT_SETTINGS_TYPE_COOKIES, 173 std::string(), 174 false)); 175 Mock::VerifyAndClear(&observer); 176 177 // Unregister second extension. This should reset the setting to its default 178 // value. 179 EXPECT_CALL(observer, OnContentSettingChanged(ext_id_2, false)); 180 store()->UnregisterExtension(ext_id_2); 181 EXPECT_EQ(CONTENT_SETTING_DEFAULT, 182 GetContentSettingFromStore(store(), 183 url, 184 url, 185 CONTENT_SETTINGS_TYPE_COOKIES, 186 std::string(), 187 false)); 188 189 store()->RemoveObserver(&observer); 190} 191 192TEST_F(ContentSettingsStoreTest, GetAllSettings) { 193 bool incognito = false; 194 std::vector<content_settings::Rule> rules; 195 GetSettingsForOneTypeFromStore( 196 store(), CONTENT_SETTINGS_TYPE_COOKIES, std::string(), incognito, &rules); 197 ASSERT_EQ(0u, rules.size()); 198 199 // Register first extension. 200 std::string ext_id("my_extension"); 201 RegisterExtension(ext_id); 202 ContentSettingsPattern pattern = 203 ContentSettingsPattern::FromURL(GURL("http://www.youtube.com")); 204 store()->SetExtensionContentSetting(ext_id, 205 pattern, 206 pattern, 207 CONTENT_SETTINGS_TYPE_COOKIES, 208 std::string(), 209 CONTENT_SETTING_ALLOW, 210 kExtensionPrefsScopeRegular); 211 212 GetSettingsForOneTypeFromStore( 213 store(), CONTENT_SETTINGS_TYPE_COOKIES, std::string(), incognito, &rules); 214 ASSERT_EQ(1u, rules.size()); 215 CheckRule(rules[0], pattern, pattern, CONTENT_SETTING_ALLOW); 216 217 // Register second extension. 218 std::string ext_id_2("my_second_extension"); 219 RegisterExtension(ext_id_2); 220 ContentSettingsPattern pattern_2 = 221 ContentSettingsPattern::FromURL(GURL("http://www.example.com")); 222 store()->SetExtensionContentSetting(ext_id_2, 223 pattern_2, 224 pattern_2, 225 CONTENT_SETTINGS_TYPE_COOKIES, 226 std::string(), 227 CONTENT_SETTING_BLOCK, 228 kExtensionPrefsScopeRegular); 229 230 GetSettingsForOneTypeFromStore( 231 store(), CONTENT_SETTINGS_TYPE_COOKIES, std::string(), incognito, &rules); 232 ASSERT_EQ(2u, rules.size()); 233 // Rules appear in the reverse installation order of the extensions. 234 CheckRule(rules[0], pattern_2, pattern_2, CONTENT_SETTING_BLOCK); 235 CheckRule(rules[1], pattern, pattern, CONTENT_SETTING_ALLOW); 236 237 // Disable first extension. 238 store()->SetExtensionState(ext_id, false); 239 240 GetSettingsForOneTypeFromStore( 241 store(), CONTENT_SETTINGS_TYPE_COOKIES, std::string(), incognito, &rules); 242 ASSERT_EQ(1u, rules.size()); 243 CheckRule(rules[0], pattern_2, pattern_2, CONTENT_SETTING_BLOCK); 244 245 // Uninstall second extension. 246 store()->UnregisterExtension(ext_id_2); 247 248 GetSettingsForOneTypeFromStore( 249 store(), CONTENT_SETTINGS_TYPE_COOKIES, std::string(), incognito, &rules); 250 ASSERT_EQ(0u, rules.size()); 251} 252 253} // namespace extensions 254