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