OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/content_settings/core/browser/content_settings_pref.h" | 5 #include "components/content_settings/core/browser/content_settings_pref.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
11 #include "base/prefs/scoped_user_pref_update.h" | 11 #include "base/prefs/scoped_user_pref_update.h" |
12 #include "base/strings/string_split.h" | 12 #include "base/strings/string_split.h" |
13 #include "base/time/clock.h" | 13 #include "base/time/clock.h" |
14 #include "components/content_settings/core/browser/content_settings_rule.h" | 14 #include "components/content_settings/core/browser/content_settings_rule.h" |
15 #include "components/content_settings/core/browser/content_settings_utils.h" | 15 #include "components/content_settings/core/browser/content_settings_utils.h" |
16 #include "components/content_settings/core/browser/host_content_settings_map.h" | 16 #include "components/content_settings/core/browser/host_content_settings_map.h" |
17 #include "components/content_settings/core/common/content_settings.h" | 17 #include "components/content_settings/core/common/content_settings.h" |
18 #include "components/content_settings/core/common/content_settings_pattern.h" | 18 #include "components/content_settings/core/common/content_settings_pattern.h" |
19 #include "components/content_settings/core/common/pref_names.h" | 19 #include "components/content_settings/core/common/pref_names.h" |
20 #include "url/gurl.h" | 20 #include "url/gurl.h" |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
24 typedef std::pair<std::string, std::string> StringPair; | 24 const char kSettingPath[] = "setting"; |
25 | 25 const char kPerResourceIdentifierPrefName[] = "per_resource"; |
26 const char kPerPluginPrefName[] = "per_plugin"; | 26 const char kPerPluginPrefName[] = "per_plugin"; |
27 const char kLastUsed[] = "last_used"; | 27 const char kLastUsed[] = "last_used"; |
28 | 28 |
29 ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type, | 29 ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type, |
30 ContentSetting setting) { | 30 ContentSetting setting) { |
31 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES && | 31 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES && |
32 setting == CONTENT_SETTING_ASK) { | 32 setting == CONTENT_SETTING_ASK) { |
33 return CONTENT_SETTING_BLOCK; | 33 return CONTENT_SETTING_BLOCK; |
34 } | 34 } |
35 return setting; | 35 return setting; |
36 } | 36 } |
37 | 37 |
38 // If the given content type supports resource identifiers in user preferences, | 38 // If the given content type supports resource identifiers in user preferences, |
39 // returns true and sets |pref_key| to the key in the content settings | 39 // returns true and sets |pref_key| to the key in the content settings |
40 // dictionary under which per-resource content settings are stored. | 40 // dictionary under which per-resource content settings are stored. |
41 // Otherwise, returns false. | 41 // Otherwise, returns false. |
42 bool GetResourceTypeName(ContentSettingsType content_type, | 42 bool SupportsResourceIdentifiers(ContentSettingsType content_type) { |
43 std::string* pref_key) { | 43 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS; |
44 if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS) { | |
45 *pref_key = kPerPluginPrefName; | |
46 return true; | |
47 } | |
48 return false; | |
49 } | 44 } |
50 | 45 |
51 } // namespace | 46 } // namespace |
52 | 47 |
53 namespace content_settings { | 48 namespace content_settings { |
54 | 49 |
55 ContentSettingsPref::ContentSettingsPref( | 50 ContentSettingsPref::ContentSettingsPref( |
| 51 ContentSettingsType content_type, |
56 PrefService* prefs, | 52 PrefService* prefs, |
57 PrefChangeRegistrar* registrar, | 53 PrefChangeRegistrar* registrar, |
58 base::Clock* clock, | 54 const char* pref_name, |
59 bool incognito, | 55 bool incognito, |
| 56 bool* updating_old_preferences_flag, |
60 NotifyObserversCallback notify_callback) | 57 NotifyObserversCallback notify_callback) |
61 : prefs_(prefs), | 58 : content_type_(content_type), |
62 clock_(clock), | 59 prefs_(prefs), |
63 registrar_(registrar), | 60 registrar_(registrar), |
| 61 pref_name_(pref_name), |
64 is_incognito_(incognito), | 62 is_incognito_(incognito), |
65 updating_preferences_(false), | 63 updating_preferences_(false), |
| 64 updating_old_preferences_(updating_old_preferences_flag), |
66 notify_callback_(notify_callback) { | 65 notify_callback_(notify_callback) { |
67 DCHECK(prefs_); | 66 DCHECK(prefs_); |
68 | 67 |
69 // Read content settings exceptions. | 68 ReadContentSettingsFromPrefAndWriteToOldPref(); |
70 ReadContentSettingsFromPref(); | |
71 | 69 |
72 registrar->Add( | 70 registrar_->Add( |
73 prefs::kContentSettingsPatternPairs, | 71 pref_name_, |
74 base::Bind(&ContentSettingsPref::OnContentSettingsPatternPairsChanged, | 72 base::Bind(&ContentSettingsPref::OnPrefChanged, base::Unretained(this))); |
75 base::Unretained(this))); | |
76 } | 73 } |
77 | 74 |
78 ContentSettingsPref::~ContentSettingsPref() { | 75 ContentSettingsPref::~ContentSettingsPref() { |
79 } | 76 } |
80 | 77 |
81 RuleIterator* ContentSettingsPref::GetRuleIterator( | 78 RuleIterator* ContentSettingsPref::GetRuleIterator( |
82 ContentSettingsType content_type, | |
83 const ResourceIdentifier& resource_identifier, | 79 const ResourceIdentifier& resource_identifier, |
84 bool incognito) const { | 80 bool incognito) const { |
85 if (incognito) | 81 if (incognito) |
86 return incognito_value_map_.GetRuleIterator(content_type, | 82 return incognito_value_map_.GetRuleIterator(content_type_, |
87 resource_identifier, | 83 resource_identifier, |
88 &lock_); | 84 &lock_); |
89 return value_map_.GetRuleIterator(content_type, resource_identifier, &lock_); | 85 return value_map_.GetRuleIterator(content_type_, resource_identifier, &lock_); |
90 } | 86 } |
91 | 87 |
92 bool ContentSettingsPref::SetWebsiteSetting( | 88 bool ContentSettingsPref::SetWebsiteSetting( |
93 const ContentSettingsPattern& primary_pattern, | 89 const ContentSettingsPattern& primary_pattern, |
94 const ContentSettingsPattern& secondary_pattern, | 90 const ContentSettingsPattern& secondary_pattern, |
95 ContentSettingsType content_type, | |
96 const ResourceIdentifier& resource_identifier, | 91 const ResourceIdentifier& resource_identifier, |
97 base::Value* in_value) { | 92 base::Value* in_value) { |
98 DCHECK(thread_checker_.CalledOnValidThread()); | 93 DCHECK(thread_checker_.CalledOnValidThread()); |
99 DCHECK(prefs_); | 94 DCHECK(prefs_); |
100 | 95 DCHECK(primary_pattern != ContentSettingsPattern::Wildcard() || |
101 // Default settings are set using a wildcard pattern for both | 96 secondary_pattern != ContentSettingsPattern::Wildcard() || |
102 // |primary_pattern| and |secondary_pattern|. Don't store default settings in | 97 !resource_identifier.empty()); |
103 // the |PrefProvider|. The |PrefProvider| handles settings for specific | |
104 // sites/origins defined by the |primary_pattern| and the |secondary_pattern|. | |
105 // Default settings are handled by the |DefaultProvider|. | |
106 if (primary_pattern == ContentSettingsPattern::Wildcard() && | |
107 secondary_pattern == ContentSettingsPattern::Wildcard() && | |
108 resource_identifier.empty()) { | |
109 return false; | |
110 } | |
111 | 98 |
112 // At this point take the ownership of the |in_value|. | 99 // At this point take the ownership of the |in_value|. |
113 scoped_ptr<base::Value> value(in_value); | 100 scoped_ptr<base::Value> value(in_value); |
| 101 |
114 // Update in memory value map. | 102 // Update in memory value map. |
115 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; | 103 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; |
116 if (!is_incognito_) | 104 if (!is_incognito_) |
117 map_to_modify = &value_map_; | 105 map_to_modify = &value_map_; |
118 | 106 |
119 { | 107 { |
120 base::AutoLock auto_lock(lock_); | 108 base::AutoLock auto_lock(lock_); |
121 if (value.get()) { | 109 if (value.get()) { |
122 map_to_modify->SetValue( | 110 map_to_modify->SetValue( |
123 primary_pattern, | 111 primary_pattern, |
124 secondary_pattern, | 112 secondary_pattern, |
125 content_type, | 113 content_type_, |
126 resource_identifier, | 114 resource_identifier, |
127 value->DeepCopy()); | 115 value->DeepCopy()); |
128 } else { | 116 } else { |
129 map_to_modify->DeleteValue( | 117 map_to_modify->DeleteValue( |
130 primary_pattern, | 118 primary_pattern, |
131 secondary_pattern, | 119 secondary_pattern, |
132 content_type, | 120 content_type_, |
133 resource_identifier); | 121 resource_identifier); |
134 } | 122 } |
135 } | 123 } |
136 // Update the content settings preference. | 124 // Update the content settings preference. |
137 if (!is_incognito_) { | 125 if (!is_incognito_) { |
138 UpdatePref(primary_pattern, | 126 UpdatePref(primary_pattern, |
139 secondary_pattern, | 127 secondary_pattern, |
140 content_type, | |
141 resource_identifier, | 128 resource_identifier, |
142 value.get()); | 129 value.get()); |
| 130 if (IsContentSettingsTypeSyncable(content_type_)) { |
| 131 UpdateOldPref(primary_pattern, |
| 132 secondary_pattern, |
| 133 resource_identifier, |
| 134 value.get()); |
| 135 } |
143 } | 136 } |
144 | 137 |
145 notify_callback_.Run( | 138 notify_callback_.Run( |
146 primary_pattern, secondary_pattern, content_type, resource_identifier); | 139 primary_pattern, secondary_pattern, content_type_, resource_identifier); |
147 | 140 |
148 return true; | 141 return true; |
149 } | 142 } |
150 | 143 |
151 void ContentSettingsPref::ClearAllContentSettingsRules( | 144 void ContentSettingsPref::ClearAllContentSettingsRules() { |
152 ContentSettingsType content_type) { | |
153 DCHECK(thread_checker_.CalledOnValidThread()); | 145 DCHECK(thread_checker_.CalledOnValidThread()); |
154 DCHECK(prefs_); | 146 DCHECK(prefs_); |
155 | 147 |
156 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; | 148 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; |
157 if (!is_incognito_) | 149 if (!is_incognito_) |
158 map_to_modify = &value_map_; | 150 map_to_modify = &value_map_; |
159 | 151 |
160 std::vector<Rule> rules_to_delete; | 152 std::vector<Rule> rules_to_delete; |
161 { | 153 { |
162 base::AutoLock auto_lock(lock_); | 154 base::AutoLock auto_lock(lock_); |
163 scoped_ptr<RuleIterator> rule_iterator( | 155 scoped_ptr<RuleIterator> rule_iterator( |
164 map_to_modify->GetRuleIterator(content_type, std::string(), NULL)); | 156 map_to_modify->GetRuleIterator(content_type_, std::string(), NULL)); |
165 // Copy the rules; we cannot call |UpdatePref| while holding |lock_|. | 157 // Copy the rules; we cannot call |UpdatePref| while holding |lock_|. |
166 while (rule_iterator->HasNext()) | 158 while (rule_iterator->HasNext()) |
167 rules_to_delete.push_back(rule_iterator->Next()); | 159 rules_to_delete.push_back(rule_iterator->Next()); |
168 | 160 |
169 map_to_modify->DeleteValues(content_type, std::string()); | 161 map_to_modify->DeleteValues(content_type_, std::string()); |
170 } | 162 } |
171 | 163 |
172 for (std::vector<Rule>::const_iterator it = rules_to_delete.begin(); | 164 for (std::vector<Rule>::const_iterator it = rules_to_delete.begin(); |
173 it != rules_to_delete.end(); ++it) { | 165 it != rules_to_delete.end(); ++it) { |
174 UpdatePref(it->primary_pattern, | 166 UpdatePref(it->primary_pattern, |
175 it->secondary_pattern, | 167 it->secondary_pattern, |
176 content_type, | |
177 std::string(), | 168 std::string(), |
178 NULL); | 169 NULL); |
| 170 if (IsContentSettingsTypeSyncable(content_type_)) { |
| 171 UpdateOldPref(it->primary_pattern, |
| 172 it->secondary_pattern, |
| 173 std::string(), |
| 174 NULL); |
| 175 } |
179 } | 176 } |
180 notify_callback_.Run(ContentSettingsPattern(), | 177 notify_callback_.Run(ContentSettingsPattern(), |
181 ContentSettingsPattern(), | 178 ContentSettingsPattern(), |
182 content_type, | 179 content_type_, |
183 std::string()); | 180 std::string()); |
184 } | 181 } |
185 | 182 |
186 void ContentSettingsPref::UpdateLastUsage( | 183 void ContentSettingsPref::UpdateLastUsage( |
187 const ContentSettingsPattern& primary_pattern, | 184 const ContentSettingsPattern& primary_pattern, |
188 const ContentSettingsPattern& secondary_pattern, | 185 const ContentSettingsPattern& secondary_pattern, |
189 ContentSettingsType content_type) { | 186 base::Clock* clock) { |
190 // Don't write if in incognito. | 187 // Don't write if in incognito. |
191 if (is_incognito_) { | 188 if (is_incognito_) { |
192 return; | 189 return; |
193 } | 190 } |
194 | 191 |
195 // Ensure that |lock_| is not held by this thread, since this function will | 192 // Ensure that |lock_| is not held by this thread, since this function will |
196 // send out notifications (by |~DictionaryPrefUpdate|). | 193 // send out notifications (by |~DictionaryPrefUpdate|). |
197 AssertLockNotHeld(); | 194 AssertLockNotHeld(); |
198 | 195 |
199 base::AutoReset<bool> auto_reset(&updating_preferences_, true); | 196 base::AutoReset<bool> auto_reset(&updating_preferences_, true); |
200 { | 197 { |
201 DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs); | 198 DictionaryPrefUpdate update(prefs_, pref_name_); |
202 base::DictionaryValue* pattern_pairs_settings = update.Get(); | 199 base::DictionaryValue* pattern_pairs_settings = update.Get(); |
203 | 200 |
204 std::string pattern_str( | 201 std::string pattern_str( |
205 CreatePatternString(primary_pattern, secondary_pattern)); | 202 CreatePatternString(primary_pattern, secondary_pattern)); |
206 base::DictionaryValue* settings_dictionary = NULL; | 203 base::DictionaryValue* settings_dictionary = NULL; |
207 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( | 204 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( |
208 pattern_str, &settings_dictionary); | 205 pattern_str, &settings_dictionary); |
209 | 206 |
210 if (!found) { | 207 if (!found) { |
211 settings_dictionary = new base::DictionaryValue; | 208 settings_dictionary = new base::DictionaryValue; |
212 pattern_pairs_settings->SetWithoutPathExpansion(pattern_str, | 209 pattern_pairs_settings->SetWithoutPathExpansion(pattern_str, |
213 settings_dictionary); | 210 settings_dictionary); |
214 } | 211 } |
215 | 212 |
216 base::DictionaryValue* last_used_dictionary = NULL; | 213 settings_dictionary->SetWithoutPathExpansion( |
217 found = settings_dictionary->GetDictionaryWithoutPathExpansion( | 214 kLastUsed, new base::FundamentalValue(clock->Now().ToDoubleT())); |
218 kLastUsed, &last_used_dictionary); | |
219 | |
220 if (!found) { | |
221 last_used_dictionary = new base::DictionaryValue; | |
222 settings_dictionary->SetWithoutPathExpansion(kLastUsed, | |
223 last_used_dictionary); | |
224 } | |
225 | |
226 std::string settings_path = GetTypeName(content_type); | |
227 last_used_dictionary->Set( | |
228 settings_path, new base::FundamentalValue(clock_->Now().ToDoubleT())); | |
229 } | 215 } |
230 } | 216 } |
231 | 217 |
232 base::Time ContentSettingsPref::GetLastUsage( | 218 base::Time ContentSettingsPref::GetLastUsage( |
233 const ContentSettingsPattern& primary_pattern, | 219 const ContentSettingsPattern& primary_pattern, |
234 const ContentSettingsPattern& secondary_pattern, | 220 const ContentSettingsPattern& secondary_pattern) { |
235 ContentSettingsType content_type) { | |
236 const base::DictionaryValue* pattern_pairs_settings = | 221 const base::DictionaryValue* pattern_pairs_settings = |
237 prefs_->GetDictionary(prefs::kContentSettingsPatternPairs); | 222 prefs_->GetDictionary(pref_name_); |
238 std::string pattern_str( | 223 std::string pattern_str( |
239 CreatePatternString(primary_pattern, secondary_pattern)); | 224 CreatePatternString(primary_pattern, secondary_pattern)); |
240 | 225 |
241 const base::DictionaryValue* settings_dictionary = NULL; | 226 const base::DictionaryValue* settings_dictionary = NULL; |
242 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( | 227 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( |
243 pattern_str, &settings_dictionary); | 228 pattern_str, &settings_dictionary); |
244 | 229 |
245 if (!found) | 230 if (!found) |
246 return base::Time(); | 231 return base::Time(); |
247 | 232 |
248 const base::DictionaryValue* last_used_dictionary = NULL; | |
249 found = settings_dictionary->GetDictionaryWithoutPathExpansion( | |
250 kLastUsed, &last_used_dictionary); | |
251 | |
252 if (!found) | |
253 return base::Time(); | |
254 | |
255 double last_used_time; | 233 double last_used_time; |
256 found = last_used_dictionary->GetDoubleWithoutPathExpansion( | 234 found = settings_dictionary->GetDoubleWithoutPathExpansion( |
257 GetTypeName(content_type), &last_used_time); | 235 kLastUsed, &last_used_time); |
258 | 236 |
259 if (!found) | 237 if (!found) |
260 return base::Time(); | 238 return base::Time(); |
261 | 239 |
262 return base::Time::FromDoubleT(last_used_time); | 240 return base::Time::FromDoubleT(last_used_time); |
263 } | 241 } |
264 | 242 |
265 size_t ContentSettingsPref::GetNumExceptions() { | 243 size_t ContentSettingsPref::GetNumExceptions() { |
266 return value_map_.size(); | 244 return value_map_.size(); |
267 } | 245 } |
268 | 246 |
269 void ContentSettingsPref::SetClockForTesting(base::Clock* clock) { | 247 void ContentSettingsPref::ReadContentSettingsFromPrefAndWriteToOldPref() { |
270 clock_ = clock; | |
271 } | |
272 | |
273 void ContentSettingsPref::ReadContentSettingsFromPref() { | |
274 // |DictionaryPrefUpdate| sends out notifications when destructed. This | 248 // |DictionaryPrefUpdate| sends out notifications when destructed. This |
275 // construction order ensures |AutoLock| gets destroyed first and |lock_| is | 249 // construction order ensures |AutoLock| gets destroyed first and |lock_| is |
276 // not held when the notifications are sent. Also, |auto_reset| must be still | 250 // not held when the notifications are sent. Also, |auto_reset| must be still |
277 // valid when the notifications are sent, so that |Observe| skips the | 251 // valid when the notifications are sent, so that |Observe| skips the |
278 // notification. | 252 // notification. |
279 base::AutoReset<bool> auto_reset(&updating_preferences_, true); | 253 base::AutoReset<bool> auto_reset(&updating_preferences_, true); |
280 DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs); | 254 DictionaryPrefUpdate update(prefs_, pref_name_); |
281 base::AutoLock auto_lock(lock_); | 255 base::AutoLock auto_lock(lock_); |
282 | 256 |
283 const base::DictionaryValue* all_settings_dictionary = | 257 const base::DictionaryValue* all_settings_dictionary = |
284 prefs_->GetDictionary(prefs::kContentSettingsPatternPairs); | 258 prefs_->GetDictionary(pref_name_); |
285 | 259 |
286 value_map_.clear(); | 260 value_map_.clear(); |
| 261 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_)) |
| 262 ClearOldPreference(); |
287 | 263 |
288 // Careful: The returned value could be NULL if the pref has never been set. | 264 // Careful: The returned value could be NULL if the pref has never been set. |
289 if (!all_settings_dictionary) | 265 if (!all_settings_dictionary) |
290 return; | 266 return; |
291 | 267 |
292 base::DictionaryValue* mutable_settings; | 268 base::DictionaryValue* mutable_settings; |
293 scoped_ptr<base::DictionaryValue> mutable_settings_scope; | 269 scoped_ptr<base::DictionaryValue> mutable_settings_scope; |
294 | 270 |
295 if (!is_incognito_) { | 271 if (!is_incognito_) { |
296 mutable_settings = update.Get(); | 272 mutable_settings = update.Get(); |
(...skipping 19 matching lines...) Expand all Loading... |
316 LOG(ERROR) << "Invalid pattern strings: " << pattern_str; | 292 LOG(ERROR) << "Invalid pattern strings: " << pattern_str; |
317 continue; | 293 continue; |
318 } | 294 } |
319 | 295 |
320 // Get settings dictionary for the current pattern string, and read | 296 // Get settings dictionary for the current pattern string, and read |
321 // settings from the dictionary. | 297 // settings from the dictionary. |
322 const base::DictionaryValue* settings_dictionary = NULL; | 298 const base::DictionaryValue* settings_dictionary = NULL; |
323 bool is_dictionary = i.value().GetAsDictionary(&settings_dictionary); | 299 bool is_dictionary = i.value().GetAsDictionary(&settings_dictionary); |
324 DCHECK(is_dictionary); | 300 DCHECK(is_dictionary); |
325 | 301 |
326 for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { | 302 if (SupportsResourceIdentifiers(content_type_)) { |
327 ContentSettingsType content_type = static_cast<ContentSettingsType>(i); | 303 const base::DictionaryValue* resource_dictionary = NULL; |
328 | 304 if (settings_dictionary->GetDictionary( |
329 std::string res_dictionary_path; | 305 kPerResourceIdentifierPrefName, &resource_dictionary)) { |
330 if (GetResourceTypeName(content_type, &res_dictionary_path)) { | 306 for (base::DictionaryValue::Iterator j(*resource_dictionary); |
331 const base::DictionaryValue* resource_dictionary = NULL; | 307 !j.IsAtEnd(); |
332 if (settings_dictionary->GetDictionary( | 308 j.Advance()) { |
333 res_dictionary_path, &resource_dictionary)) { | 309 const std::string& resource_identifier(j.key()); |
334 for (base::DictionaryValue::Iterator j(*resource_dictionary); | 310 int setting = CONTENT_SETTING_DEFAULT; |
335 !j.IsAtEnd(); | 311 bool is_integer = j.value().GetAsInteger(&setting); |
336 j.Advance()) { | 312 DCHECK(is_integer); |
337 const std::string& resource_identifier(j.key()); | |
338 int setting = CONTENT_SETTING_DEFAULT; | |
339 bool is_integer = j.value().GetAsInteger(&setting); | |
340 DCHECK(is_integer); | |
341 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); | |
342 value_map_.SetValue(pattern_pair.first, | |
343 pattern_pair.second, | |
344 content_type, | |
345 resource_identifier, | |
346 new base::FundamentalValue(setting)); | |
347 } | |
348 } | |
349 } | |
350 base::Value* value = NULL; | |
351 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type)) { | |
352 const base::DictionaryValue* setting = NULL; | |
353 // TODO(xians): Handle the non-dictionary types. | |
354 if (settings_dictionary->GetDictionaryWithoutPathExpansion( | |
355 GetTypeName(ContentSettingsType(i)), &setting)) { | |
356 DCHECK(!setting->empty()); | |
357 value = setting->DeepCopy(); | |
358 } | |
359 } else { | |
360 int setting = CONTENT_SETTING_DEFAULT; | |
361 if (settings_dictionary->GetIntegerWithoutPathExpansion( | |
362 GetTypeName(ContentSettingsType(i)), &setting)) { | |
363 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); | 313 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); |
364 setting = FixObsoleteCookiePromptMode(content_type, | 314 scoped_ptr<base::Value> setting_ptr( |
365 ContentSetting(setting)); | 315 new base::FundamentalValue(setting)); |
366 value = new base::FundamentalValue(setting); | 316 value_map_.SetValue(pattern_pair.first, |
367 } | 317 pattern_pair.second, |
368 } | 318 content_type_, |
369 | 319 resource_identifier, |
370 // |value_map_| will take the ownership of |value|. | 320 setting_ptr->DeepCopy()); |
371 if (value != NULL) { | 321 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_)) { |
372 value_map_.SetValue(pattern_pair.first, | 322 UpdateOldPref(pattern_pair.first, |
373 pattern_pair.second, | 323 pattern_pair.second, |
374 content_type, | 324 resource_identifier, |
375 ResourceIdentifier(), | 325 setting_ptr.get()); |
376 value); | |
377 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) { | |
378 ContentSetting s = ValueToContentSetting(value); | |
379 switch (s) { | |
380 case CONTENT_SETTING_ALLOW : | |
381 ++cookies_allow_exception_count; | |
382 break; | |
383 case CONTENT_SETTING_BLOCK : | |
384 ++cookies_block_exception_count; | |
385 break; | |
386 case CONTENT_SETTING_SESSION_ONLY : | |
387 ++cookies_session_only_exception_count; | |
388 break; | |
389 default: | |
390 NOTREACHED(); | |
391 break; | |
392 } | 326 } |
393 } | 327 } |
394 } | 328 } |
395 } | 329 } |
| 330 base::Value* value = NULL; |
| 331 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type_)) { |
| 332 const base::DictionaryValue* setting = NULL; |
| 333 // TODO(xians): Handle the non-dictionary types. |
| 334 if (settings_dictionary->GetDictionaryWithoutPathExpansion( |
| 335 kSettingPath, &setting)) { |
| 336 DCHECK(!setting->empty()); |
| 337 value = setting->DeepCopy(); |
| 338 } |
| 339 } else { |
| 340 int setting = CONTENT_SETTING_DEFAULT; |
| 341 if (settings_dictionary->GetIntegerWithoutPathExpansion( |
| 342 kSettingPath, &setting)) { |
| 343 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); |
| 344 setting = FixObsoleteCookiePromptMode(content_type_, |
| 345 ContentSetting(setting)); |
| 346 value = new base::FundamentalValue(setting); |
| 347 } |
| 348 } |
| 349 |
| 350 if (value != NULL) { |
| 351 scoped_ptr<base::Value> value_ptr(value); |
| 352 value_map_.SetValue(pattern_pair.first, |
| 353 pattern_pair.second, |
| 354 content_type_, |
| 355 ResourceIdentifier(), |
| 356 value->DeepCopy()); |
| 357 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_)) { |
| 358 UpdateOldPref(pattern_pair.first, |
| 359 pattern_pair.second, |
| 360 ResourceIdentifier(), |
| 361 value_ptr.get()); |
| 362 } |
| 363 if (content_type_ == CONTENT_SETTINGS_TYPE_COOKIES) { |
| 364 ContentSetting s = ValueToContentSetting(value); |
| 365 switch (s) { |
| 366 case CONTENT_SETTING_ALLOW : |
| 367 ++cookies_allow_exception_count; |
| 368 break; |
| 369 case CONTENT_SETTING_BLOCK : |
| 370 ++cookies_block_exception_count; |
| 371 break; |
| 372 case CONTENT_SETTING_SESSION_ONLY : |
| 373 ++cookies_session_only_exception_count; |
| 374 break; |
| 375 default: |
| 376 NOTREACHED(); |
| 377 break; |
| 378 } |
| 379 } |
| 380 } |
| 381 |
396 } | 382 } |
397 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfBlockCookiesExceptions", | 383 |
398 cookies_block_exception_count); | 384 if (content_type_ == CONTENT_SETTINGS_TYPE_COOKIES) { |
399 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfAllowCookiesExceptions", | 385 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfBlockCookiesExceptions", |
400 cookies_allow_exception_count); | 386 cookies_block_exception_count); |
401 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfSessionOnlyCookiesExceptions", | 387 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfAllowCookiesExceptions", |
402 cookies_session_only_exception_count); | 388 cookies_allow_exception_count); |
| 389 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfSessionOnlyCookiesExceptions", |
| 390 cookies_session_only_exception_count); |
| 391 } |
403 } | 392 } |
404 | 393 |
405 void ContentSettingsPref::OnContentSettingsPatternPairsChanged() { | 394 void ContentSettingsPref::OnPrefChanged() { |
406 DCHECK(thread_checker_.CalledOnValidThread()); | 395 DCHECK(thread_checker_.CalledOnValidThread()); |
407 | 396 |
408 if (updating_preferences_) | 397 if (updating_preferences_) |
409 return; | 398 return; |
410 | 399 |
411 ReadContentSettingsFromPref(); | 400 ReadContentSettingsFromPrefAndWriteToOldPref(); |
412 | 401 |
413 notify_callback_.Run(ContentSettingsPattern(), | 402 notify_callback_.Run(ContentSettingsPattern(), |
414 ContentSettingsPattern(), | 403 ContentSettingsPattern(), |
415 CONTENT_SETTINGS_TYPE_DEFAULT, | 404 content_type_, |
416 std::string()); | 405 std::string()); |
417 } | 406 } |
418 | 407 |
419 void ContentSettingsPref::UpdatePref( | 408 void ContentSettingsPref::UpdatePref( |
420 const ContentSettingsPattern& primary_pattern, | 409 const ContentSettingsPattern& primary_pattern, |
421 const ContentSettingsPattern& secondary_pattern, | 410 const ContentSettingsPattern& secondary_pattern, |
422 ContentSettingsType content_type, | |
423 const ResourceIdentifier& resource_identifier, | 411 const ResourceIdentifier& resource_identifier, |
424 const base::Value* value) { | 412 const base::Value* value) { |
425 // Ensure that |lock_| is not held by this thread, since this function will | 413 // Ensure that |lock_| is not held by this thread, since this function will |
426 // send out notifications (by |~DictionaryPrefUpdate|). | 414 // send out notifications (by |~DictionaryPrefUpdate|). |
427 AssertLockNotHeld(); | 415 AssertLockNotHeld(); |
428 | 416 |
429 base::AutoReset<bool> auto_reset(&updating_preferences_, true); | 417 base::AutoReset<bool> auto_reset(&updating_preferences_, true); |
430 { | 418 { |
| 419 DictionaryPrefUpdate update(prefs_, pref_name_); |
| 420 base::DictionaryValue* pattern_pairs_settings = update.Get(); |
| 421 |
| 422 // Get settings dictionary for the given patterns. |
| 423 std::string pattern_str(CreatePatternString(primary_pattern, |
| 424 secondary_pattern)); |
| 425 base::DictionaryValue* settings_dictionary = NULL; |
| 426 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( |
| 427 pattern_str, &settings_dictionary); |
| 428 |
| 429 if (!found && value) { |
| 430 settings_dictionary = new base::DictionaryValue; |
| 431 pattern_pairs_settings->SetWithoutPathExpansion( |
| 432 pattern_str, settings_dictionary); |
| 433 } |
| 434 |
| 435 if (settings_dictionary) { |
| 436 if (SupportsResourceIdentifiers(content_type_) && |
| 437 !resource_identifier.empty()) { |
| 438 base::DictionaryValue* resource_dictionary = NULL; |
| 439 found = settings_dictionary->GetDictionary( |
| 440 kPerResourceIdentifierPrefName, &resource_dictionary); |
| 441 if (!found) { |
| 442 if (value == NULL) |
| 443 return; // Nothing to remove. Exit early. |
| 444 resource_dictionary = new base::DictionaryValue; |
| 445 settings_dictionary->Set( |
| 446 kPerResourceIdentifierPrefName, resource_dictionary); |
| 447 } |
| 448 // Update resource dictionary. |
| 449 if (value == NULL) { |
| 450 resource_dictionary->RemoveWithoutPathExpansion(resource_identifier, |
| 451 NULL); |
| 452 if (resource_dictionary->empty()) { |
| 453 settings_dictionary->RemoveWithoutPathExpansion( |
| 454 kPerResourceIdentifierPrefName, NULL); |
| 455 } |
| 456 } else { |
| 457 resource_dictionary->SetWithoutPathExpansion( |
| 458 resource_identifier, value->DeepCopy()); |
| 459 } |
| 460 } else { |
| 461 // Update settings dictionary. |
| 462 if (value == NULL) { |
| 463 settings_dictionary->RemoveWithoutPathExpansion(kSettingPath, NULL); |
| 464 settings_dictionary->RemoveWithoutPathExpansion(kLastUsed, NULL); |
| 465 } else { |
| 466 settings_dictionary->SetWithoutPathExpansion( |
| 467 kSettingPath, value->DeepCopy()); |
| 468 } |
| 469 } |
| 470 // Remove the settings dictionary if it is empty. |
| 471 if (settings_dictionary->empty()) { |
| 472 pattern_pairs_settings->RemoveWithoutPathExpansion( |
| 473 pattern_str, NULL); |
| 474 } |
| 475 } |
| 476 } |
| 477 } |
| 478 |
| 479 void ContentSettingsPref::UpdateOldPref( |
| 480 const ContentSettingsPattern& primary_pattern, |
| 481 const ContentSettingsPattern& secondary_pattern, |
| 482 const ResourceIdentifier& resource_identifier, |
| 483 const base::Value* value) { |
| 484 DCHECK(IsContentSettingsTypeSyncable(content_type_)); |
| 485 |
| 486 // The incognito provider cannot write the settings to avoid echo effect: |
| 487 // New preference -> PrefProvider -> Old preference -> |
| 488 // -> Incognito PrefProvider -> New preference -> etc. |
| 489 DCHECK(!is_incognito_); |
| 490 |
| 491 if (*updating_old_preferences_) |
| 492 return; |
| 493 |
| 494 base::AutoReset<bool> auto_reset(updating_old_preferences_, true); |
| 495 { |
431 DictionaryPrefUpdate update(prefs_, | 496 DictionaryPrefUpdate update(prefs_, |
432 prefs::kContentSettingsPatternPairs); | 497 prefs::kContentSettingsPatternPairs); |
433 base::DictionaryValue* pattern_pairs_settings = update.Get(); | 498 base::DictionaryValue* pattern_pairs_settings = update.Get(); |
434 | 499 |
435 // Get settings dictionary for the given patterns. | 500 // Get settings dictionary for the given patterns. |
436 std::string pattern_str(CreatePatternString(primary_pattern, | 501 std::string pattern_str(CreatePatternString(primary_pattern, |
437 secondary_pattern)); | 502 secondary_pattern)); |
438 base::DictionaryValue* settings_dictionary = NULL; | 503 base::DictionaryValue* settings_dictionary = NULL; |
439 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( | 504 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( |
440 pattern_str, &settings_dictionary); | 505 pattern_str, &settings_dictionary); |
441 | 506 |
442 if (!found && value) { | 507 if (!found && value) { |
443 settings_dictionary = new base::DictionaryValue; | 508 settings_dictionary = new base::DictionaryValue; |
444 pattern_pairs_settings->SetWithoutPathExpansion( | 509 pattern_pairs_settings->SetWithoutPathExpansion( |
445 pattern_str, settings_dictionary); | 510 pattern_str, settings_dictionary); |
446 } | 511 } |
447 | 512 |
448 if (settings_dictionary) { | 513 if (settings_dictionary) { |
449 std::string res_dictionary_path; | 514 if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS && |
450 if (GetResourceTypeName(content_type, &res_dictionary_path) && | |
451 !resource_identifier.empty()) { | 515 !resource_identifier.empty()) { |
452 base::DictionaryValue* resource_dictionary = NULL; | 516 base::DictionaryValue* resource_dictionary = NULL; |
453 found = settings_dictionary->GetDictionary( | 517 found = settings_dictionary->GetDictionary( |
454 res_dictionary_path, &resource_dictionary); | 518 kPerPluginPrefName, &resource_dictionary); |
455 if (!found) { | 519 if (!found) { |
456 if (value == NULL) | 520 if (value == NULL) |
457 return; // Nothing to remove. Exit early. | 521 return; // Nothing to remove. Exit early. |
458 resource_dictionary = new base::DictionaryValue; | 522 resource_dictionary = new base::DictionaryValue; |
459 settings_dictionary->Set(res_dictionary_path, resource_dictionary); | 523 settings_dictionary->Set(kPerPluginPrefName, resource_dictionary); |
460 } | 524 } |
461 // Update resource dictionary. | 525 // Update resource dictionary. |
462 if (value == NULL) { | 526 if (value == NULL) { |
463 resource_dictionary->RemoveWithoutPathExpansion(resource_identifier, | 527 resource_dictionary->RemoveWithoutPathExpansion(resource_identifier, |
464 NULL); | 528 NULL); |
465 if (resource_dictionary->empty()) { | 529 if (resource_dictionary->empty()) { |
466 settings_dictionary->RemoveWithoutPathExpansion( | 530 settings_dictionary->RemoveWithoutPathExpansion( |
467 res_dictionary_path, NULL); | 531 kPerPluginPrefName, NULL); |
468 } | 532 } |
469 } else { | 533 } else { |
470 resource_dictionary->SetWithoutPathExpansion( | 534 resource_dictionary->SetWithoutPathExpansion( |
471 resource_identifier, value->DeepCopy()); | 535 resource_identifier, value->DeepCopy()); |
472 } | 536 } |
473 } else { | 537 } else { |
474 // Update settings dictionary. | 538 // Update settings dictionary. |
475 std::string setting_path = GetTypeName(content_type); | 539 std::string setting_path = GetTypeName(content_type_); |
476 if (value == NULL) { | 540 if (value == NULL) { |
477 settings_dictionary->RemoveWithoutPathExpansion(setting_path, | 541 settings_dictionary->RemoveWithoutPathExpansion(setting_path, |
478 NULL); | 542 NULL); |
479 settings_dictionary->RemoveWithoutPathExpansion(kLastUsed, NULL); | 543 settings_dictionary->RemoveWithoutPathExpansion(kLastUsed, NULL); |
480 } else { | 544 } else { |
481 settings_dictionary->SetWithoutPathExpansion( | 545 settings_dictionary->SetWithoutPathExpansion( |
482 setting_path, value->DeepCopy()); | 546 setting_path, value->DeepCopy()); |
483 } | 547 } |
484 } | 548 } |
485 // Remove the settings dictionary if it is empty. | 549 // Remove the settings dictionary if it is empty. |
486 if (settings_dictionary->empty()) { | 550 if (settings_dictionary->empty()) { |
487 pattern_pairs_settings->RemoveWithoutPathExpansion( | 551 pattern_pairs_settings->RemoveWithoutPathExpansion( |
488 pattern_str, NULL); | 552 pattern_str, NULL); |
489 } | 553 } |
490 } | 554 } |
491 } | 555 } |
492 } | 556 } |
493 | 557 |
| 558 void ContentSettingsPref::ClearOldPreference() { |
| 559 DCHECK(IsContentSettingsTypeSyncable(content_type_)); |
| 560 |
| 561 if (*updating_old_preferences_) |
| 562 return; |
| 563 |
| 564 std::vector<std::string> keys; |
| 565 |
| 566 base::AutoReset<bool> auto_reset(updating_old_preferences_, true); |
| 567 DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs); |
| 568 base::DictionaryValue* old_dictionary = update.Get(); |
| 569 |
| 570 for (base::DictionaryValue::Iterator it(*old_dictionary); |
| 571 !it.IsAtEnd(); it.Advance()) { |
| 572 keys.push_back(it.key()); |
| 573 } |
| 574 |
| 575 for (const std::string key : keys) { |
| 576 base::DictionaryValue* exception; |
| 577 bool is_dictionary = |
| 578 old_dictionary->GetDictionaryWithoutPathExpansion(key, &exception); |
| 579 DCHECK(is_dictionary); |
| 580 |
| 581 exception->RemoveWithoutPathExpansion(GetTypeName(content_type_), NULL); |
| 582 |
| 583 base::DictionaryValue* last_used; |
| 584 if (exception->GetDictionaryWithoutPathExpansion(kLastUsed, &last_used)) { |
| 585 last_used->RemoveWithoutPathExpansion(GetTypeName(content_type_), NULL); |
| 586 |
| 587 if (last_used->empty()) |
| 588 exception->RemoveWithoutPathExpansion(kLastUsed, NULL); |
| 589 } |
| 590 |
| 591 if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS) |
| 592 exception->RemoveWithoutPathExpansion(kPerPluginPrefName, NULL); |
| 593 |
| 594 if (exception->empty()) |
| 595 old_dictionary->RemoveWithoutPathExpansion(key, NULL); |
| 596 } |
| 597 |
| 598 } |
| 599 |
494 // static | 600 // static |
495 void ContentSettingsPref::CanonicalizeContentSettingsExceptions( | 601 void ContentSettingsPref::CanonicalizeContentSettingsExceptions( |
496 base::DictionaryValue* all_settings_dictionary) { | 602 base::DictionaryValue* all_settings_dictionary) { |
497 DCHECK(all_settings_dictionary); | 603 DCHECK(all_settings_dictionary); |
498 | 604 |
499 std::vector<std::string> remove_items; | 605 std::vector<std::string> remove_items; |
500 base::StringPairs move_items; | 606 base::StringPairs move_items; |
501 for (base::DictionaryValue::Iterator i(*all_settings_dictionary); | 607 for (base::DictionaryValue::Iterator i(*all_settings_dictionary); |
502 !i.IsAtEnd(); | 608 !i.IsAtEnd(); |
503 i.Advance()) { | 609 i.Advance()) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 | 655 |
550 void ContentSettingsPref::AssertLockNotHeld() const { | 656 void ContentSettingsPref::AssertLockNotHeld() const { |
551 #if !defined(NDEBUG) | 657 #if !defined(NDEBUG) |
552 // |Lock::Acquire()| will assert if the lock is held by this thread. | 658 // |Lock::Acquire()| will assert if the lock is held by this thread. |
553 lock_.Acquire(); | 659 lock_.Acquire(); |
554 lock_.Release(); | 660 lock_.Release(); |
555 #endif | 661 #endif |
556 } | 662 } |
557 | 663 |
558 } // namespace content_settings | 664 } // namespace content_settings |
OLD | NEW |