Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: chrome/browser/content_settings/content_settings_pref_provider.cc

Issue 670953006: Componentize HostContentSettingsMap and content settings providers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: win64 suppress warnings Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/content_settings/content_settings_pref_provider.h"
6
7 #include <map>
8 #include <string>
9 #include <utility>
10
11 #include "base/auto_reset.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/metrics/histogram.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/prefs/scoped_user_pref_update.h"
18 #include "base/strings/string_split.h"
19 #include "base/time/clock.h"
20 #include "base/time/default_clock.h"
21 #include "chrome/browser/content_settings/content_settings_utils.h"
22 #include "chrome/browser/content_settings/host_content_settings_map.h"
23 #include "chrome/common/pref_names.h"
24 #include "components/content_settings/core/browser/content_settings_rule.h"
25 #include "components/content_settings/core/common/content_settings.h"
26 #include "components/content_settings/core/common/content_settings_pattern.h"
27 #include "components/pref_registry/pref_registry_syncable.h"
28 #include "url/gurl.h"
29
30 namespace {
31
32 typedef std::pair<std::string, std::string> StringPair;
33 typedef std::map<std::string, std::string> StringMap;
34
35 const char kPerPluginPrefName[] = "per_plugin";
36 const char kAudioKey[] = "audio";
37 const char kVideoKey[] = "video";
38 const char kLastUsed[] = "last_used";
39
40 ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type,
41 ContentSetting setting) {
42 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES &&
43 setting == CONTENT_SETTING_ASK) {
44 return CONTENT_SETTING_BLOCK;
45 }
46 return setting;
47 }
48
49 // If the given content type supports resource identifiers in user preferences,
50 // returns true and sets |pref_key| to the key in the content settings
51 // dictionary under which per-resource content settings are stored.
52 // Otherwise, returns false.
53 bool GetResourceTypeName(ContentSettingsType content_type,
54 std::string* pref_key) {
55 if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS) {
56 *pref_key = kPerPluginPrefName;
57 return true;
58 }
59 return false;
60 }
61
62 } // namespace
63
64 namespace content_settings {
65
66 // ////////////////////////////////////////////////////////////////////////////
67 // PrefProvider:
68 //
69
70 // static
71 void PrefProvider::RegisterProfilePrefs(
72 user_prefs::PrefRegistrySyncable* registry) {
73 registry->RegisterIntegerPref(
74 prefs::kContentSettingsVersion,
75 ContentSettingsPattern::kContentSettingsPatternVersion,
76 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
77 registry->RegisterDictionaryPref(
78 prefs::kContentSettingsPatternPairs,
79 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
80 }
81
82 PrefProvider::PrefProvider(PrefService* prefs, bool incognito)
83 : prefs_(prefs),
84 clock_(new base::DefaultClock()),
85 is_incognito_(incognito),
86 updating_preferences_(false) {
87 DCHECK(prefs_);
88 // Verify preferences version.
89 if (!prefs_->HasPrefPath(prefs::kContentSettingsVersion)) {
90 prefs_->SetInteger(prefs::kContentSettingsVersion,
91 ContentSettingsPattern::kContentSettingsPatternVersion);
92 }
93 if (prefs_->GetInteger(prefs::kContentSettingsVersion) >
94 ContentSettingsPattern::kContentSettingsPatternVersion) {
95 return;
96 }
97
98 // Read content settings exceptions.
99 ReadContentSettingsFromPref(false);
100
101 if (!is_incognito_) {
102 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfExceptions",
103 value_map_.size());
104 }
105
106 // Migrate the obsolete media content setting exceptions to the new settings.
107 // This needs to be done after ReadContentSettingsFromPref().
108 if (!is_incognito_)
109 MigrateObsoleteMediaContentSetting();
110
111 pref_change_registrar_.Init(prefs_);
112 pref_change_registrar_.Add(
113 prefs::kContentSettingsPatternPairs,
114 base::Bind(&PrefProvider::OnContentSettingsPatternPairsChanged,
115 base::Unretained(this)));
116 }
117
118 bool PrefProvider::SetWebsiteSetting(
119 const ContentSettingsPattern& primary_pattern,
120 const ContentSettingsPattern& secondary_pattern,
121 ContentSettingsType content_type,
122 const ResourceIdentifier& resource_identifier,
123 base::Value* in_value) {
124 DCHECK(CalledOnValidThread());
125 DCHECK(prefs_);
126 // Default settings are set using a wildcard pattern for both
127 // |primary_pattern| and |secondary_pattern|. Don't store default settings in
128 // the |PrefProvider|. The |PrefProvider| handles settings for specific
129 // sites/origins defined by the |primary_pattern| and the |secondary_pattern|.
130 // Default settings are handled by the |DefaultProvider|.
131 if (primary_pattern == ContentSettingsPattern::Wildcard() &&
132 secondary_pattern == ContentSettingsPattern::Wildcard() &&
133 resource_identifier.empty()) {
134 return false;
135 }
136
137 // At this point take the ownership of the |in_value|.
138 scoped_ptr<base::Value> value(in_value);
139 // Update in memory value map.
140 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_;
141 if (!is_incognito_)
142 map_to_modify = &value_map_;
143
144 {
145 base::AutoLock auto_lock(lock_);
146 if (value.get()) {
147 map_to_modify->SetValue(
148 primary_pattern,
149 secondary_pattern,
150 content_type,
151 resource_identifier,
152 value->DeepCopy());
153 } else {
154 map_to_modify->DeleteValue(
155 primary_pattern,
156 secondary_pattern,
157 content_type,
158 resource_identifier);
159 }
160 }
161 // Update the content settings preference.
162 if (!is_incognito_) {
163 UpdatePref(primary_pattern,
164 secondary_pattern,
165 content_type,
166 resource_identifier,
167 value.get());
168 }
169
170 NotifyObservers(
171 primary_pattern, secondary_pattern, content_type, resource_identifier);
172
173 return true;
174 }
175
176 void PrefProvider::ClearAllContentSettingsRules(
177 ContentSettingsType content_type) {
178 DCHECK(CalledOnValidThread());
179 DCHECK(prefs_);
180
181 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_;
182 if (!is_incognito_)
183 map_to_modify = &value_map_;
184
185 std::vector<Rule> rules_to_delete;
186 {
187 base::AutoLock auto_lock(lock_);
188 scoped_ptr<RuleIterator> rule_iterator(
189 map_to_modify->GetRuleIterator(content_type, std::string(), NULL));
190 // Copy the rules; we cannot call |UpdatePref| while holding |lock_|.
191 while (rule_iterator->HasNext())
192 rules_to_delete.push_back(rule_iterator->Next());
193
194 map_to_modify->DeleteValues(content_type, std::string());
195 }
196
197 for (std::vector<Rule>::const_iterator it = rules_to_delete.begin();
198 it != rules_to_delete.end(); ++it) {
199 UpdatePref(it->primary_pattern,
200 it->secondary_pattern,
201 content_type,
202 std::string(),
203 NULL);
204 }
205 NotifyObservers(ContentSettingsPattern(),
206 ContentSettingsPattern(),
207 content_type,
208 std::string());
209 }
210
211 PrefProvider::~PrefProvider() {
212 DCHECK(!prefs_);
213 }
214
215 RuleIterator* PrefProvider::GetRuleIterator(
216 ContentSettingsType content_type,
217 const ResourceIdentifier& resource_identifier,
218 bool incognito) const {
219 if (incognito)
220 return incognito_value_map_.GetRuleIterator(content_type,
221 resource_identifier,
222 &lock_);
223 return value_map_.GetRuleIterator(content_type, resource_identifier, &lock_);
224 }
225
226 // ////////////////////////////////////////////////////////////////////////////
227 // Private
228
229 void PrefProvider::UpdatePref(
230 const ContentSettingsPattern& primary_pattern,
231 const ContentSettingsPattern& secondary_pattern,
232 ContentSettingsType content_type,
233 const ResourceIdentifier& resource_identifier,
234 const base::Value* value) {
235 // Ensure that |lock_| is not held by this thread, since this function will
236 // send out notifications (by |~DictionaryPrefUpdate|).
237 AssertLockNotHeld();
238
239 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
240 {
241 DictionaryPrefUpdate update(prefs_,
242 prefs::kContentSettingsPatternPairs);
243 base::DictionaryValue* pattern_pairs_settings = update.Get();
244
245 // Get settings dictionary for the given patterns.
246 std::string pattern_str(CreatePatternString(primary_pattern,
247 secondary_pattern));
248 base::DictionaryValue* settings_dictionary = NULL;
249 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion(
250 pattern_str, &settings_dictionary);
251
252 if (!found && value) {
253 settings_dictionary = new base::DictionaryValue;
254 pattern_pairs_settings->SetWithoutPathExpansion(
255 pattern_str, settings_dictionary);
256 }
257
258 if (settings_dictionary) {
259 std::string res_dictionary_path;
260 if (GetResourceTypeName(content_type, &res_dictionary_path) &&
261 !resource_identifier.empty()) {
262 base::DictionaryValue* resource_dictionary = NULL;
263 found = settings_dictionary->GetDictionary(
264 res_dictionary_path, &resource_dictionary);
265 if (!found) {
266 if (value == NULL)
267 return; // Nothing to remove. Exit early.
268 resource_dictionary = new base::DictionaryValue;
269 settings_dictionary->Set(res_dictionary_path, resource_dictionary);
270 }
271 // Update resource dictionary.
272 if (value == NULL) {
273 resource_dictionary->RemoveWithoutPathExpansion(resource_identifier,
274 NULL);
275 if (resource_dictionary->empty()) {
276 settings_dictionary->RemoveWithoutPathExpansion(
277 res_dictionary_path, NULL);
278 }
279 } else {
280 resource_dictionary->SetWithoutPathExpansion(
281 resource_identifier, value->DeepCopy());
282 }
283 } else {
284 // Update settings dictionary.
285 std::string setting_path = GetTypeName(content_type);
286 if (value == NULL) {
287 settings_dictionary->RemoveWithoutPathExpansion(setting_path,
288 NULL);
289 settings_dictionary->RemoveWithoutPathExpansion(kLastUsed, NULL);
290 } else {
291 settings_dictionary->SetWithoutPathExpansion(
292 setting_path, value->DeepCopy());
293 }
294 }
295 // Remove the settings dictionary if it is empty.
296 if (settings_dictionary->empty()) {
297 pattern_pairs_settings->RemoveWithoutPathExpansion(
298 pattern_str, NULL);
299 }
300 }
301 }
302 }
303
304
305 void PrefProvider::MigrateObsoleteMediaContentSetting() {
306 std::vector<Rule> rules_to_delete;
307 {
308 scoped_ptr<RuleIterator> rule_iterator(GetRuleIterator(
309 CONTENT_SETTINGS_TYPE_MEDIASTREAM, std::string(), false));
310 while (rule_iterator->HasNext()) {
311 // Skip default setting and rules without a value.
312 const content_settings::Rule& rule = rule_iterator->Next();
313 DCHECK(rule.primary_pattern != ContentSettingsPattern::Wildcard());
314 if (!rule.value.get())
315 continue;
316 rules_to_delete.push_back(rule);
317 }
318 }
319
320 for (std::vector<Rule>::const_iterator it = rules_to_delete.begin();
321 it != rules_to_delete.end(); ++it) {
322 const base::DictionaryValue* value_dict = NULL;
323 if (!it->value->GetAsDictionary(&value_dict) || value_dict->empty())
324 return;
325
326 std::string audio_device, video_device;
327 value_dict->GetString(kAudioKey, &audio_device);
328 value_dict->GetString(kVideoKey, &video_device);
329 // Add the exception to the new microphone content setting.
330 if (!audio_device.empty()) {
331 SetWebsiteSetting(it->primary_pattern,
332 it->secondary_pattern,
333 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
334 std::string(),
335 new base::FundamentalValue(CONTENT_SETTING_ALLOW));
336 }
337 // Add the exception to the new camera content setting.
338 if (!video_device.empty()) {
339 SetWebsiteSetting(it->primary_pattern,
340 it->secondary_pattern,
341 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
342 std::string(),
343 new base::FundamentalValue(CONTENT_SETTING_ALLOW));
344 }
345
346 // Remove the old exception in CONTENT_SETTINGS_TYPE_MEDIASTREAM.
347 SetWebsiteSetting(it->primary_pattern,
348 it->secondary_pattern,
349 CONTENT_SETTINGS_TYPE_MEDIASTREAM,
350 std::string(),
351 NULL);
352 }
353 }
354
355 void PrefProvider::ReadContentSettingsFromPref(bool overwrite) {
356 // |DictionaryPrefUpdate| sends out notifications when destructed. This
357 // construction order ensures |AutoLock| gets destroyed first and |lock_| is
358 // not held when the notifications are sent. Also, |auto_reset| must be still
359 // valid when the notifications are sent, so that |Observe| skips the
360 // notification.
361 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
362 DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs);
363 base::AutoLock auto_lock(lock_);
364
365 const base::DictionaryValue* all_settings_dictionary =
366 prefs_->GetDictionary(prefs::kContentSettingsPatternPairs);
367
368 if (overwrite)
369 value_map_.clear();
370
371 // Careful: The returned value could be NULL if the pref has never been set.
372 if (!all_settings_dictionary)
373 return;
374
375 base::DictionaryValue* mutable_settings;
376 scoped_ptr<base::DictionaryValue> mutable_settings_scope;
377
378 if (!is_incognito_) {
379 mutable_settings = update.Get();
380 } else {
381 // Create copy as we do not want to persist anything in OTR prefs.
382 mutable_settings = all_settings_dictionary->DeepCopy();
383 mutable_settings_scope.reset(mutable_settings);
384 }
385 // Convert all Unicode patterns into punycode form, then read.
386 CanonicalizeContentSettingsExceptions(mutable_settings);
387
388 size_t cookies_block_exception_count = 0;
389 size_t cookies_allow_exception_count = 0;
390 size_t cookies_session_only_exception_count = 0;
391 for (base::DictionaryValue::Iterator i(*mutable_settings); !i.IsAtEnd();
392 i.Advance()) {
393 const std::string& pattern_str(i.key());
394 std::pair<ContentSettingsPattern, ContentSettingsPattern> pattern_pair =
395 ParsePatternString(pattern_str);
396 if (!pattern_pair.first.IsValid() ||
397 !pattern_pair.second.IsValid()) {
398 // TODO: Change this to DFATAL when crbug.com/132659 is fixed.
399 LOG(ERROR) << "Invalid pattern strings: " << pattern_str;
400 continue;
401 }
402
403 // Get settings dictionary for the current pattern string, and read
404 // settings from the dictionary.
405 const base::DictionaryValue* settings_dictionary = NULL;
406 bool is_dictionary = i.value().GetAsDictionary(&settings_dictionary);
407 DCHECK(is_dictionary);
408
409 for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
410 ContentSettingsType content_type = static_cast<ContentSettingsType>(i);
411
412 std::string res_dictionary_path;
413 if (GetResourceTypeName(content_type, &res_dictionary_path)) {
414 const base::DictionaryValue* resource_dictionary = NULL;
415 if (settings_dictionary->GetDictionary(
416 res_dictionary_path, &resource_dictionary)) {
417 for (base::DictionaryValue::Iterator j(*resource_dictionary);
418 !j.IsAtEnd();
419 j.Advance()) {
420 const std::string& resource_identifier(j.key());
421 int setting = CONTENT_SETTING_DEFAULT;
422 bool is_integer = j.value().GetAsInteger(&setting);
423 DCHECK(is_integer);
424 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting);
425 value_map_.SetValue(pattern_pair.first,
426 pattern_pair.second,
427 content_type,
428 resource_identifier,
429 new base::FundamentalValue(setting));
430 }
431 }
432 }
433 base::Value* value = NULL;
434 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type)) {
435 const base::DictionaryValue* setting = NULL;
436 // TODO(xians): Handle the non-dictionary types.
437 if (settings_dictionary->GetDictionaryWithoutPathExpansion(
438 GetTypeName(ContentSettingsType(i)), &setting)) {
439 DCHECK(!setting->empty());
440 value = setting->DeepCopy();
441 }
442 } else {
443 int setting = CONTENT_SETTING_DEFAULT;
444 if (settings_dictionary->GetIntegerWithoutPathExpansion(
445 GetTypeName(ContentSettingsType(i)), &setting)) {
446 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting);
447 setting = FixObsoleteCookiePromptMode(content_type,
448 ContentSetting(setting));
449 value = new base::FundamentalValue(setting);
450 }
451 }
452
453 // |value_map_| will take the ownership of |value|.
454 if (value != NULL) {
455 value_map_.SetValue(pattern_pair.first,
456 pattern_pair.second,
457 content_type,
458 ResourceIdentifier(),
459 value);
460 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) {
461 ContentSetting s = ValueToContentSetting(value);
462 switch (s) {
463 case CONTENT_SETTING_ALLOW :
464 ++cookies_allow_exception_count;
465 break;
466 case CONTENT_SETTING_BLOCK :
467 ++cookies_block_exception_count;
468 break;
469 case CONTENT_SETTING_SESSION_ONLY :
470 ++cookies_session_only_exception_count;
471 break;
472 default:
473 NOTREACHED();
474 break;
475 }
476 }
477 }
478 }
479 }
480 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfBlockCookiesExceptions",
481 cookies_block_exception_count);
482 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfAllowCookiesExceptions",
483 cookies_allow_exception_count);
484 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfSessionOnlyCookiesExceptions",
485 cookies_session_only_exception_count);
486 }
487
488 void PrefProvider::OnContentSettingsPatternPairsChanged() {
489 DCHECK(CalledOnValidThread());
490
491 if (updating_preferences_)
492 return;
493
494 ReadContentSettingsFromPref(true);
495
496 NotifyObservers(ContentSettingsPattern(),
497 ContentSettingsPattern(),
498 CONTENT_SETTINGS_TYPE_DEFAULT,
499 std::string());
500 }
501
502 // static
503 void PrefProvider::CanonicalizeContentSettingsExceptions(
504 base::DictionaryValue* all_settings_dictionary) {
505 DCHECK(all_settings_dictionary);
506
507 std::vector<std::string> remove_items;
508 base::StringPairs move_items;
509 for (base::DictionaryValue::Iterator i(*all_settings_dictionary);
510 !i.IsAtEnd();
511 i.Advance()) {
512 const std::string& pattern_str(i.key());
513 std::pair<ContentSettingsPattern, ContentSettingsPattern> pattern_pair =
514 ParsePatternString(pattern_str);
515 if (!pattern_pair.first.IsValid() ||
516 !pattern_pair.second.IsValid()) {
517 LOG(ERROR) << "Invalid pattern strings: " << pattern_str;
518 continue;
519 }
520
521 const std::string canonicalized_pattern_str = CreatePatternString(
522 pattern_pair.first, pattern_pair.second);
523
524 if (canonicalized_pattern_str.empty() ||
525 canonicalized_pattern_str == pattern_str) {
526 continue;
527 }
528
529 // Clear old pattern if prefs already have canonicalized pattern.
530 const base::DictionaryValue* new_pattern_settings_dictionary = NULL;
531 if (all_settings_dictionary->GetDictionaryWithoutPathExpansion(
532 canonicalized_pattern_str, &new_pattern_settings_dictionary)) {
533 remove_items.push_back(pattern_str);
534 continue;
535 }
536
537 // Move old pattern to canonicalized pattern.
538 const base::DictionaryValue* old_pattern_settings_dictionary = NULL;
539 if (i.value().GetAsDictionary(&old_pattern_settings_dictionary)) {
540 move_items.push_back(
541 std::make_pair(pattern_str, canonicalized_pattern_str));
542 }
543 }
544
545 for (size_t i = 0; i < remove_items.size(); ++i) {
546 all_settings_dictionary->RemoveWithoutPathExpansion(remove_items[i], NULL);
547 }
548
549 for (size_t i = 0; i < move_items.size(); ++i) {
550 scoped_ptr<base::Value> pattern_settings_dictionary;
551 all_settings_dictionary->RemoveWithoutPathExpansion(
552 move_items[i].first, &pattern_settings_dictionary);
553 all_settings_dictionary->SetWithoutPathExpansion(
554 move_items[i].second, pattern_settings_dictionary.release());
555 }
556 }
557
558 void PrefProvider::ShutdownOnUIThread() {
559 DCHECK(CalledOnValidThread());
560 DCHECK(prefs_);
561 RemoveAllObservers();
562 pref_change_registrar_.RemoveAll();
563 prefs_ = NULL;
564 }
565
566 void PrefProvider::UpdateLastUsage(
567 const ContentSettingsPattern& primary_pattern,
568 const ContentSettingsPattern& secondary_pattern,
569 ContentSettingsType content_type) {
570 // Don't write if in incognito.
571 if (is_incognito_) {
572 return;
573 }
574
575 // Ensure that |lock_| is not held by this thread, since this function will
576 // send out notifications (by |~DictionaryPrefUpdate|).
577 AssertLockNotHeld();
578
579 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
580 {
581 DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs);
582 base::DictionaryValue* pattern_pairs_settings = update.Get();
583
584 std::string pattern_str(
585 CreatePatternString(primary_pattern, secondary_pattern));
586 base::DictionaryValue* settings_dictionary = NULL;
587 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion(
588 pattern_str, &settings_dictionary);
589
590 if (!found) {
591 settings_dictionary = new base::DictionaryValue;
592 pattern_pairs_settings->SetWithoutPathExpansion(pattern_str,
593 settings_dictionary);
594 }
595
596 base::DictionaryValue* last_used_dictionary = NULL;
597 found = settings_dictionary->GetDictionaryWithoutPathExpansion(
598 kLastUsed, &last_used_dictionary);
599
600 if (!found) {
601 last_used_dictionary = new base::DictionaryValue;
602 settings_dictionary->SetWithoutPathExpansion(kLastUsed,
603 last_used_dictionary);
604 }
605
606 std::string settings_path = GetTypeName(content_type);
607 last_used_dictionary->Set(
608 settings_path, new base::FundamentalValue(clock_->Now().ToDoubleT()));
609 }
610 }
611
612 base::Time PrefProvider::GetLastUsage(
613 const ContentSettingsPattern& primary_pattern,
614 const ContentSettingsPattern& secondary_pattern,
615 ContentSettingsType content_type) {
616 const base::DictionaryValue* pattern_pairs_settings =
617 prefs_->GetDictionary(prefs::kContentSettingsPatternPairs);
618 std::string pattern_str(
619 CreatePatternString(primary_pattern, secondary_pattern));
620
621 const base::DictionaryValue* settings_dictionary = NULL;
622 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion(
623 pattern_str, &settings_dictionary);
624
625 if (!found)
626 return base::Time();
627
628 const base::DictionaryValue* last_used_dictionary = NULL;
629 found = settings_dictionary->GetDictionaryWithoutPathExpansion(
630 kLastUsed, &last_used_dictionary);
631
632 if (!found)
633 return base::Time();
634
635 double last_used_time;
636 found = last_used_dictionary->GetDoubleWithoutPathExpansion(
637 GetTypeName(content_type), &last_used_time);
638
639 if (!found)
640 return base::Time();
641
642 return base::Time::FromDoubleT(last_used_time);
643 }
644
645 void PrefProvider::AssertLockNotHeld() const {
646 #if !defined(NDEBUG)
647 // |Lock::Acquire()| will assert if the lock is held by this thread.
648 lock_.Acquire();
649 lock_.Release();
650 #endif
651 }
652
653 void PrefProvider::SetClockForTesting(scoped_ptr<base::Clock> clock) {
654 clock_ = clock.Pass();
655 }
656
657 } // namespace content_settings
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698