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

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

Issue 6410022: Add content_settings::PrefProvider to HostContentSettingsMap. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Worked on comments Created 9 years, 10 months 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/browser/content_settings/pref_content_settings_provider.h" 5 #include "chrome/browser/content_settings/pref_content_settings_provider.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector>
9 #include <utility>
8 10
9 #include "base/command_line.h" 11 #include "base/command_line.h"
10 #include "chrome/browser/browser_thread.h" 12 #include "chrome/browser/browser_thread.h"
11 #include "chrome/browser/content_settings/content_settings_details.h" 13 #include "chrome/browser/content_settings/content_settings_details.h"
12 #include "chrome/browser/content_settings/content_settings_pattern.h" 14 #include "chrome/browser/content_settings/content_settings_pattern.h"
13 #include "chrome/browser/prefs/pref_service.h" 15 #include "chrome/browser/prefs/pref_service.h"
14 #include "chrome/browser/prefs/scoped_pref_update.h" 16 #include "chrome/browser/prefs/scoped_pref_update.h"
15 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/chrome_switches.h" 18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/content_settings.h"
17 #include "chrome/common/notification_details.h" 20 #include "chrome/common/notification_details.h"
18 #include "chrome/common/notification_service.h" 21 #include "chrome/common/notification_service.h"
19 #include "chrome/common/notification_source.h" 22 #include "chrome/common/notification_source.h"
20 #include "chrome/common/pref_names.h" 23 #include "chrome/common/pref_names.h"
24 #include "googleurl/src/gurl.h"
25 #include "net/base/net_util.h"
21 26
22 namespace { 27 namespace {
23 28
29 // The preference keys where resource identifiers are stored for
30 // ContentSettingsType values that support resource identifiers.
31 const char* kResourceTypeNames[CONTENT_SETTINGS_NUM_TYPES] = {
32 NULL,
33 NULL,
34 NULL,
35 "per_plugin",
36 NULL,
37 NULL, // Not used for Geolocation
38 NULL, // Not used for Notifications
39 };
40
24 // The default setting for each content type. 41 // The default setting for each content type.
25 const ContentSetting kDefaultSettings[CONTENT_SETTINGS_NUM_TYPES] = { 42 const ContentSetting kDefaultSettings[CONTENT_SETTINGS_NUM_TYPES] = {
26 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_COOKIES 43 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_COOKIES
27 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_IMAGES 44 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_IMAGES
28 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_JAVASCRIPT 45 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_JAVASCRIPT
29 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_PLUGINS 46 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_PLUGINS
30 CONTENT_SETTING_BLOCK, // CONTENT_SETTINGS_TYPE_POPUPS 47 CONTENT_SETTING_BLOCK, // CONTENT_SETTINGS_TYPE_POPUPS
31 CONTENT_SETTING_ASK, // Not used for Geolocation 48 CONTENT_SETTING_ASK, // Not used for Geolocation
32 CONTENT_SETTING_ASK, // Not used for Notifications 49 CONTENT_SETTING_ASK, // Not used for Notifications
33 }; 50 };
34 51
35 // The names of the ContentSettingsType values, for use with dictionary prefs. 52 // The names of the ContentSettingsType values, for use with dictionary prefs.
36 const char* kTypeNames[CONTENT_SETTINGS_NUM_TYPES] = { 53 const char* kTypeNames[CONTENT_SETTINGS_NUM_TYPES] = {
37 "cookies", 54 "cookies",
38 "images", 55 "images",
39 "javascript", 56 "javascript",
40 "plugins", 57 "plugins",
41 "popups", 58 "popups",
42 NULL, // Not used for Geolocation 59 NULL, // Not used for Geolocation
43 NULL, // Not used for Notifications 60 NULL, // Not used for Notifications
44 }; 61 };
45 62
63 // True if a given content settings type requires additional resource
64 // identifiers.
65 const bool kRequiresResourceIdentifier[CONTENT_SETTINGS_NUM_TYPES] = {
66 false, // CONTENT_SETTINGS_TYPE_COOKIES
67 false, // CONTENT_SETTINGS_TYPE_IMAGES
68 false, // CONTET_SETTINGS_TYPE_JAVASCRIPT
69 true, // CONTENT_SETTINGS_TYPE_PLUGINS
70 false, // CONTENT_SETTINGS_TYPE_POPUPS
71 false, // Not used for Geolocation
72 false, // Not used for Notifications
73 };
46 74
47 // Map ASK for the plugins content type to BLOCK if click-to-play is 75 // Map ASK for the plugins content type to BLOCK if click-to-play is
48 // not enabled. 76 // not enabled.
49 ContentSetting ClickToPlayFixup(ContentSettingsType content_type, 77 ContentSetting ClickToPlayFixup(ContentSettingsType content_type,
50 ContentSetting setting) { 78 ContentSetting setting) {
51 if (setting == CONTENT_SETTING_ASK && 79 if (setting == CONTENT_SETTING_ASK &&
52 content_type == CONTENT_SETTINGS_TYPE_PLUGINS && 80 content_type == CONTENT_SETTINGS_TYPE_PLUGINS &&
53 !CommandLine::ForCurrentProcess()->HasSwitch( 81 !CommandLine::ForCurrentProcess()->HasSwitch(
54 switches::kEnableClickToPlay)) { 82 switches::kEnableClickToPlay)) {
55 return CONTENT_SETTING_BLOCK; 83 return CONTENT_SETTING_BLOCK;
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap()), 282 Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap()),
255 Details<const ContentSettingsDetails>(&details)); 283 Details<const ContentSettingsDetails>(&details));
256 } 284 }
257 285
258 286
259 // static 287 // static
260 void PrefDefaultProvider::RegisterUserPrefs(PrefService* prefs) { 288 void PrefDefaultProvider::RegisterUserPrefs(PrefService* prefs) {
261 prefs->RegisterDictionaryPref(prefs::kDefaultContentSettings); 289 prefs->RegisterDictionaryPref(prefs::kDefaultContentSettings);
262 } 290 }
263 291
292 // ////////////////////////////////////////////////////////////////////////////
293 // PrefProvider::
294 //
295
296 // static
297 void PrefProvider::RegisterUserPrefs(PrefService* prefs) {
298 prefs->RegisterIntegerPref(prefs::kContentSettingsVersion,
299 ContentSettingsPattern::kContentSettingsPatternVersion);
300 prefs->RegisterDictionaryPref(prefs::kContentSettingsPatterns);
301
302 // Obsolete prefs, for migration:
303 prefs->RegisterListPref(prefs::kPopupWhitelistedHosts);
304 prefs->RegisterDictionaryPref(prefs::kPerHostContentSettings);
305 }
306
307 PrefProvider::PrefProvider(Profile* profile)
308 : profile_(profile),
309 is_off_the_record_(profile_->IsOffTheRecord()),
310 updating_preferences_(false) {
311 initializing_ = true;
312 PrefService* prefs = profile_->GetPrefs();
313
314 // Migrate obsolete preferences.
315 MigrateObsoletePerhostPref(prefs);
316 MigrateObsoletePopupsPref(prefs);
317
318 // Verify preferences version.
319 if (!prefs->HasPrefPath(prefs::kContentSettingsVersion)) {
320 prefs->SetInteger(prefs::kContentSettingsVersion,
321 ContentSettingsPattern::kContentSettingsPatternVersion);
322 }
323 if (prefs->GetInteger(prefs::kContentSettingsVersion) >
324 ContentSettingsPattern::kContentSettingsPatternVersion) {
325 LOG(ERROR) << "Unknown content settings version in preferences.";
326 return;
327 }
328
329 // Read exceptions.
330 ReadExceptions(false);
331
332 pref_change_registrar_.Init(prefs);
333 pref_change_registrar_.Add(prefs::kContentSettingsPatterns, this);
334
335 notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
336 Source<Profile>(profile_));
337 initializing_ = false;
338 }
339
340 bool PrefProvider::ContentSettingsTypeIsManaged(
341 ContentSettingsType content_type) {
342 return false;
343 }
344
345 ContentSetting PrefProvider::GetContentSetting(
346 const GURL& requesting_url,
347 const GURL& embedding_url,
348 ContentSettingsType content_type,
349 const ResourceIdentifier& resource_identifier) const {
350 // Support for embedding_patterns is not implemented yet.
351 DCHECK(requesting_url == embedding_url);
352
353 if (!RequiresResourceIdentifier(content_type))
354 return GetNonDefaultContentSettings(requesting_url).settings[content_type];
355
356 if (RequiresResourceIdentifier(content_type) && resource_identifier.empty())
357 return CONTENT_SETTING_DEFAULT;
358
359 if (CommandLine::ForCurrentProcess()->HasSwitch(
360 switches::kEnableResourceContentSettings)) {
361 DCHECK(!resource_identifier.empty());
362 }
363
364 base::AutoLock auto_lock(lock_);
365
366 const std::string host(net::GetHostOrSpecFromURL(requesting_url));
367 ContentSettingsTypeResourceIdentifierPair
368 requested_setting(content_type, resource_identifier);
369
370 // Check for exact matches first.
371 HostContentSettings::const_iterator i(host_content_settings_.find(host));
372 if (i != host_content_settings_.end() &&
373 i->second.content_settings_for_resources.find(requested_setting) !=
374 i->second.content_settings_for_resources.end()) {
375 return i->second.content_settings_for_resources.find(
376 requested_setting)->second;
377 }
378
379 // If this map is not for an off-the-record profile, these searches will never
380 // match. The additional off-the-record exceptions always overwrite the
381 // regular ones.
382 i = off_the_record_settings_.find(host);
383 if (i != off_the_record_settings_.end() &&
384 i->second.content_settings_for_resources.find(requested_setting) !=
385 i->second.content_settings_for_resources.end()) {
386 return i->second.content_settings_for_resources.find(
387 requested_setting)->second;
388 }
389
390 // Match patterns starting with the most concrete pattern match.
391 for (std::string key =
392 std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) {
393 HostContentSettings::const_iterator i(off_the_record_settings_.find(key));
394 if (i != off_the_record_settings_.end() &&
395 i->second.content_settings_for_resources.find(requested_setting) !=
396 i->second.content_settings_for_resources.end()) {
397 return i->second.content_settings_for_resources.find(
398 requested_setting)->second;
399 }
400
401 i = host_content_settings_.find(key);
402 if (i != host_content_settings_.end() &&
403 i->second.content_settings_for_resources.find(requested_setting) !=
404 i->second.content_settings_for_resources.end()) {
405 return i->second.content_settings_for_resources.find(
406 requested_setting)->second;
407 }
408
409 const size_t next_dot =
410 key.find('.', ContentSettingsPattern::kDomainWildcardLength);
411 if (next_dot == std::string::npos)
412 break;
413 key.erase(ContentSettingsPattern::kDomainWildcardLength,
414 next_dot - ContentSettingsPattern::kDomainWildcardLength + 1);
415 }
416
417 return CONTENT_SETTING_DEFAULT;
418 }
419
420 void PrefProvider::SetContentSetting(
421 const ContentSettingsPattern& requesting_pattern,
422 const ContentSettingsPattern& embedding_pattern,
423 ContentSettingsType content_type,
424 const ResourceIdentifier& resource_identifier,
425 ContentSetting setting) {
426 // Support for embedding_patterns is not implemented yet.
427 DCHECK(requesting_pattern == embedding_pattern);
428
429 DCHECK(kTypeNames[content_type] != NULL); // Don't call this for Geolocation.
430 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
431 DCHECK_NE(RequiresResourceIdentifier(content_type),
432 resource_identifier.empty());
433 DCHECK(content_type != CONTENT_SETTINGS_TYPE_PLUGINS ||
434 setting != CONTENT_SETTING_ASK ||
435 CommandLine::ForCurrentProcess()->HasSwitch(
436 switches::kEnableClickToPlay));
437
438 const ContentSettingsPattern pattern(
439 requesting_pattern.CanonicalizePattern());
440
441 bool early_exit = false;
442 std::string pattern_str(pattern.AsString());
443 PrefService* prefs = NULL;
444 DictionaryValue* all_settings_dictionary = NULL;
445 HostContentSettings* map_to_modify = &off_the_record_settings_;
446 if (!is_off_the_record_) {
447 prefs = profile_->GetPrefs();
448 all_settings_dictionary =
449 prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
Bernhard Bauer 2011/02/07 09:46:46 Nit: indent two more spaces.
markusheintz_ 2011/02/07 15:57:10 Done.
450 map_to_modify = &host_content_settings_;
451 }
452
453 {
454 base::AutoLock auto_lock(lock_);
455 if (!map_to_modify->count(pattern_str))
456 (*map_to_modify)[pattern_str].content_settings = ContentSettings();
457 HostContentSettings::iterator
458 i(map_to_modify->find(pattern_str));
Bernhard Bauer 2011/02/07 09:46:46 Nit: break after `i(' ?
markusheintz_ 2011/02/07 15:57:10 Done.
459 ContentSettings& settings = i->second.content_settings;
460 if (RequiresResourceIdentifier(content_type)) {
461 settings.settings[content_type] = CONTENT_SETTING_DEFAULT;
462 if (setting != CONTENT_SETTING_DEFAULT) {
463 i->second.content_settings_for_resources[
464 ContentSettingsTypeResourceIdentifierPair(content_type,
465 resource_identifier)] = setting;
466 } else {
467 i->second.content_settings_for_resources.erase(
468 ContentSettingsTypeResourceIdentifierPair(content_type,
469 resource_identifier));
470 }
471 } else {
472 settings.settings[content_type] = setting;
473 }
474 if (AllDefault(i->second)) {
475 map_to_modify->erase(i);
476 if (all_settings_dictionary)
477 all_settings_dictionary->RemoveWithoutPathExpansion(pattern_str, NULL);
478
479 // We can't just return because |NotifyObservers()| needs to be called,
480 // without |lock_| being held.
481 early_exit = true;
482 }
483 }
484
485 if (!early_exit && all_settings_dictionary) {
486 DictionaryValue* host_settings_dictionary = NULL;
487 bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
488 pattern_str, &host_settings_dictionary);
489 if (!found) {
490 host_settings_dictionary = new DictionaryValue;
491 all_settings_dictionary->SetWithoutPathExpansion(
492 pattern_str, host_settings_dictionary);
493 DCHECK_NE(setting, CONTENT_SETTING_DEFAULT);
494 }
495 if (RequiresResourceIdentifier(content_type)) {
496 std::string dictionary_path(kResourceTypeNames[content_type]);
497 DictionaryValue* resource_dictionary = NULL;
498 found = host_settings_dictionary->GetDictionary(
499 dictionary_path, &resource_dictionary);
500 if (!found) {
501 resource_dictionary = new DictionaryValue;
502 host_settings_dictionary->Set(dictionary_path, resource_dictionary);
503 }
504 if (setting == CONTENT_SETTING_DEFAULT) {
505 resource_dictionary->RemoveWithoutPathExpansion(resource_identifier,
506 NULL);
507 } else {
508 resource_dictionary->SetWithoutPathExpansion(
509 resource_identifier, Value::CreateIntegerValue(setting));
510 }
511 } else {
512 std::string dictionary_path(kTypeNames[content_type]);
513 if (setting == CONTENT_SETTING_DEFAULT) {
514 host_settings_dictionary->RemoveWithoutPathExpansion(dictionary_path,
515 NULL);
516 } else {
517 host_settings_dictionary->SetWithoutPathExpansion(
518 dictionary_path, Value::CreateIntegerValue(setting));
519 }
520 }
521 }
522
523 updating_preferences_ = true;
524 if (!is_off_the_record_)
525 ScopedPrefUpdate update(prefs, prefs::kContentSettingsPatterns);
526 updating_preferences_ = false;
527
528 NotifyObservers(ContentSettingsDetails(pattern, content_type, ""));
529 }
530
531 void PrefProvider::GetAllContentSettingsRules(
532 ContentSettingsType content_type,
533 const ResourceIdentifier& resource_identifier,
534 Rules* content_setting_rules) const {
535 DCHECK(RequiresResourceIdentifier(content_type) !=
536 resource_identifier.empty());
537 DCHECK(content_setting_rules);
538 content_setting_rules->clear();
539
540 const HostContentSettings* map_to_return =
541 is_off_the_record_ ? &off_the_record_settings_ : &host_content_settings_;
542 ContentSettingsTypeResourceIdentifierPair
543 requested_setting(content_type, resource_identifier);
Bernhard Bauer 2011/02/07 09:46:46 Nit: break after `requested_setting(' if it fits.
markusheintz_ 2011/02/07 15:57:10 Done.
544
545 base::AutoLock auto_lock(lock_);
546 for (HostContentSettings::const_iterator i(map_to_return->begin());
547 i != map_to_return->end(); ++i) {
548 ContentSetting setting;
549 if (RequiresResourceIdentifier(content_type)) {
550 if (i->second.content_settings_for_resources.find(requested_setting) !=
551 i->second.content_settings_for_resources.end())
552 setting = i->second.content_settings_for_resources.find(
Bernhard Bauer 2011/02/07 09:46:46 Nit: Please add braces for the two branches.
markusheintz_ 2011/02/07 15:57:10 Done.
553 requested_setting)->second;
554 else
555 setting = CONTENT_SETTING_DEFAULT;
556 } else {
557 setting = i->second.content_settings.settings[content_type];
558 }
559 if (setting != CONTENT_SETTING_DEFAULT) {
560 // Use of push_back() relies on the map iterator traversing in order of
561 // ascending keys.
562 content_setting_rules->push_back(Rule(ContentSettingsPattern(i->first),
563 ContentSettingsPattern(i->first),
564 setting));
565 }
566 }
567 }
568
569 void PrefProvider::ResetToDefaults() {
570 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
571
572 {
573 base::AutoLock auto_lock(lock_);
574 host_content_settings_.clear();
575 off_the_record_settings_.clear();
576 }
577
578 if (!is_off_the_record_) {
579 PrefService* prefs = profile_->GetPrefs();
580 updating_preferences_ = true;
581 prefs->ClearPref(prefs::kContentSettingsPatterns);
582 updating_preferences_ = false;
583 }
584 }
585
586 void PrefProvider::ClearAllContentSettingsRules(
587 ContentSettingsType content_type) {
588 DCHECK(kTypeNames[content_type] != NULL); // Don't call this for Geolocation.
589
590 PrefService* prefs = NULL;
591 DictionaryValue* all_settings_dictionary = NULL;
592 HostContentSettings* map_to_modify = &off_the_record_settings_;
593
594 if (!is_off_the_record_) {
595 prefs = profile_->GetPrefs();
596 all_settings_dictionary =
597 prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
Bernhard Bauer 2011/02/07 09:46:46 Nit: indent two more spaces.
markusheintz_ 2011/02/07 15:57:10 Done.
598 map_to_modify = &host_content_settings_;
599 }
600
601 {
602 base::AutoLock auto_lock(lock_);
603 for (HostContentSettings::iterator i(map_to_modify->begin());
604 i != map_to_modify->end(); ) {
605 if (RequiresResourceIdentifier(content_type) ||
606 i->second.content_settings.settings[content_type] !=
607 CONTENT_SETTING_DEFAULT) {
608 if (RequiresResourceIdentifier(content_type))
609 i->second.content_settings_for_resources.clear();
610 i->second.content_settings.settings[content_type] =
611 CONTENT_SETTING_DEFAULT;
612 std::string host(i->first);
613 if (AllDefault(i->second)) {
614 if (all_settings_dictionary)
615 all_settings_dictionary->
Bernhard Bauer 2011/02/07 09:46:46 Nit: braces.
markusheintz_ 2011/02/07 15:57:10 Put everything in one line.
616 RemoveWithoutPathExpansion(host, NULL);
617 map_to_modify->erase(i++);
618 } else if (all_settings_dictionary) {
619 DictionaryValue* host_settings_dictionary;
620 bool found =
621 all_settings_dictionary->GetDictionaryWithoutPathExpansion(
622 host, &host_settings_dictionary);
623 DCHECK(found);
624 host_settings_dictionary->RemoveWithoutPathExpansion(
625 kTypeNames[content_type], NULL);
626 ++i;
627 }
628 } else {
629 ++i;
630 }
631 }
632 }
633
634 updating_preferences_ = true;
635 if (!is_off_the_record_)
636 ScopedPrefUpdate update(prefs, prefs::kContentSettingsPatterns);
637 updating_preferences_ = false;
638
639 NotifyObservers(
640 ContentSettingsDetails(ContentSettingsPattern(), content_type, ""));
641 }
642
643 void PrefProvider::Observe(
644 NotificationType type,
645 const NotificationSource& source,
646 const NotificationDetails& details) {
647 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
648
649 if (type == NotificationType::PREF_CHANGED) {
650 DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr());
651 if (updating_preferences_)
652 return;
653
654 std::string* name = Details<std::string>(details).ptr();
655 if (*name == prefs::kContentSettingsPatterns) {
656 ReadExceptions(true);
657 } else {
658 NOTREACHED() << "Unexpected preference observed";
659 return;
660 }
661
662 if (!is_off_the_record_) {
663 NotifyObservers(ContentSettingsDetails(ContentSettingsPattern(),
664 CONTENT_SETTINGS_TYPE_DEFAULT,
665 ""));
666 }
667 } else if (type == NotificationType::PROFILE_DESTROYED) {
668 DCHECK_EQ(profile_, Source<Profile>(source).ptr());
669 UnregisterObservers();
670 } else {
671 NOTREACHED() << "Unexpected notification";
672 }
673 }
674
675 PrefProvider::~PrefProvider() {
676 UnregisterObservers();
677 }
678
679 // ////////////////////////////////////////////////////////////////////////////
680 // Private
681
682 bool PrefProvider::RequiresResourceIdentifier(
683 ContentSettingsType content_type) const {
684 if (CommandLine::ForCurrentProcess()->HasSwitch(
685 switches::kEnableResourceContentSettings)) {
686 return kRequiresResourceIdentifier[content_type];
687 } else {
688 return false;
689 }
690 }
691
692 bool PrefProvider::AllDefault(
693 const ExtendedContentSettings& settings) const {
694 for (size_t i = 0; i < arraysize(settings.content_settings.settings); ++i) {
695 if (settings.content_settings.settings[i] != CONTENT_SETTING_DEFAULT)
696 return false;
697 }
698 return settings.content_settings_for_resources.empty();
699 }
700
701 void PrefProvider::ReadExceptions(bool overwrite) {
702 base::AutoLock lock(lock_);
703
704 PrefService* prefs = profile_->GetPrefs();
705 DictionaryValue* all_settings_dictionary =
706 prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
707
708 if (overwrite)
709 host_content_settings_.clear();
710
711 // Careful: The returned value could be NULL if the pref has never been set.
712 if (all_settings_dictionary != NULL) {
713 // Convert all Unicode patterns into punycode form, then read.
714 CanonicalizeContentSettingsExceptions(all_settings_dictionary);
715
716 for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
717 i != all_settings_dictionary->end_keys(); ++i) {
718 const std::string& pattern(*i);
719 if (!ContentSettingsPattern(pattern).IsValid())
720 LOG(WARNING) << "Invalid pattern stored in content settings";
721 DictionaryValue* pattern_settings_dictionary = NULL;
722 bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
723 pattern, &pattern_settings_dictionary);
724 DCHECK(found);
725 ContentSettings settings;
726 GetSettingsFromDictionary(pattern_settings_dictionary, &settings);
727 host_content_settings_[pattern].content_settings = settings;
728 GetResourceSettingsFromDictionary(
729 pattern_settings_dictionary,
730 &host_content_settings_[pattern].content_settings_for_resources);
731 }
732 }
733 }
734
735 void PrefProvider::CanonicalizeContentSettingsExceptions(
736 DictionaryValue* all_settings_dictionary) {
737 DCHECK(all_settings_dictionary);
738
739 std::vector<std::string> remove_items;
740 std::vector<std::pair<std::string, std::string> > move_items;
741 for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
742 i != all_settings_dictionary->end_keys(); ++i) {
743 const std::string& pattern(*i);
744 const std::string canonicalized_pattern =
745 ContentSettingsPattern(pattern).CanonicalizePattern();
746
747 if (canonicalized_pattern.empty() || canonicalized_pattern == pattern)
748 continue;
749
750 // Clear old pattern if prefs already have canonicalized pattern.
751 DictionaryValue* new_pattern_settings_dictionary = NULL;
752 if (all_settings_dictionary->GetDictionaryWithoutPathExpansion(
753 canonicalized_pattern, &new_pattern_settings_dictionary)) {
754 remove_items.push_back(pattern);
755 continue;
756 }
757
758 // Move old pattern to canonicalized pattern.
759 DictionaryValue* old_pattern_settings_dictionary = NULL;
760 if (all_settings_dictionary->GetDictionaryWithoutPathExpansion(
761 pattern, &old_pattern_settings_dictionary)) {
762 move_items.push_back(std::make_pair(pattern, canonicalized_pattern));
763 }
764 }
765
766 for (size_t i = 0; i < remove_items.size(); ++i) {
767 all_settings_dictionary->RemoveWithoutPathExpansion(remove_items[i], NULL);
768 }
769
770 for (size_t i = 0; i < move_items.size(); ++i) {
771 Value* pattern_settings_dictionary = NULL;
772 all_settings_dictionary->RemoveWithoutPathExpansion(
773 move_items[i].first, &pattern_settings_dictionary);
774 all_settings_dictionary->SetWithoutPathExpansion(
775 move_items[i].second, pattern_settings_dictionary);
776 }
777 }
778
779 void PrefProvider::GetSettingsFromDictionary(
780 const DictionaryValue* dictionary,
781 ContentSettings* settings) {
782 for (DictionaryValue::key_iterator i(dictionary->begin_keys());
783 i != dictionary->end_keys(); ++i) {
784 const std::string& content_type(*i);
785 for (size_t type = 0; type < arraysize(kTypeNames); ++type) {
786 if ((kTypeNames[type] != NULL) && (kTypeNames[type] == content_type)) {
787 int setting = CONTENT_SETTING_DEFAULT;
788 bool found = dictionary->GetIntegerWithoutPathExpansion(content_type,
789 &setting);
790 DCHECK(found);
791 settings->settings[type] = IntToContentSetting(setting);
792 break;
793 }
794 }
795 }
796 // Migrate obsolete cookie prompt mode.
797 if (settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] ==
798 CONTENT_SETTING_ASK)
799 settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] = CONTENT_SETTING_BLOCK;
800
801 settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS] =
802 ClickToPlayFixup(CONTENT_SETTINGS_TYPE_PLUGINS,
803 settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS]);
804 }
805
806 void PrefProvider::GetResourceSettingsFromDictionary(
807 const DictionaryValue* dictionary,
808 ResourceContentSettings* settings) {
809 for (DictionaryValue::key_iterator i(dictionary->begin_keys());
810 i != dictionary->end_keys(); ++i) {
811 const std::string& content_type(*i);
812 for (size_t type = 0; type < arraysize(kResourceTypeNames); ++type) {
813 if ((kResourceTypeNames[type] != NULL) &&
814 (kResourceTypeNames[type] == content_type)) {
815 DictionaryValue* resource_dictionary = NULL;
816 bool found = dictionary->GetDictionary(content_type,
817 &resource_dictionary);
818 DCHECK(found);
819 for (DictionaryValue::key_iterator j(resource_dictionary->begin_keys());
820 j != resource_dictionary->end_keys(); ++j) {
821 const std::string& resource_identifier(*j);
822 int setting = CONTENT_SETTING_DEFAULT;
823 bool found = resource_dictionary->GetIntegerWithoutPathExpansion(
824 resource_identifier, &setting);
825 DCHECK(found);
826 (*settings)[ContentSettingsTypeResourceIdentifierPair(
827 ContentSettingsType(type), resource_identifier)] =
828 ClickToPlayFixup(ContentSettingsType(type),
829 ContentSetting(setting));
830 }
831
832 break;
833 }
834 }
835 }
836 }
837
838 void PrefProvider::NotifyObservers(
839 const ContentSettingsDetails& details) {
840 if (initializing_)
841 return;
842 NotificationService::current()->Notify(
843 NotificationType::CONTENT_SETTINGS_CHANGED,
844 Source<HostContentSettingsMap>(
845 profile_->GetHostContentSettingsMap()),
846 Details<const ContentSettingsDetails>(&details));
847 }
848
849 void PrefProvider::UnregisterObservers() {
850 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
851 if (!profile_)
852 return;
853 pref_change_registrar_.RemoveAll();
854 notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED,
855 Source<Profile>(profile_));
856 profile_ = NULL;
857 }
858
859 void PrefProvider::MigrateObsoletePerhostPref(PrefService* prefs) {
860 if (prefs->HasPrefPath(prefs::kPerHostContentSettings)) {
861 const DictionaryValue* all_settings_dictionary =
862 prefs->GetDictionary(prefs::kPerHostContentSettings);
863 for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
864 i != all_settings_dictionary->end_keys(); ++i) {
865 const std::string& host(*i);
866 ContentSettingsPattern pattern(
867 std::string(ContentSettingsPattern::kDomainWildcard) + host);
868 DictionaryValue* host_settings_dictionary = NULL;
869 bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
870 host, &host_settings_dictionary);
871 DCHECK(found);
872 ContentSettings settings;
873 GetSettingsFromDictionary(host_settings_dictionary, &settings);
874 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
875 if (settings.settings[j] != CONTENT_SETTING_DEFAULT &&
876 !RequiresResourceIdentifier(ContentSettingsType(j)))
Bernhard Bauer 2011/02/07 09:46:46 Nit: Braces.
markusheintz_ 2011/02/07 15:57:10 Done.
877 SetContentSetting(
878 pattern,
879 pattern,
880 ContentSettingsType(j),
881 "",
882 settings.settings[j]);
883 }
884 }
885 prefs->ClearPref(prefs::kPerHostContentSettings);
886 }
887 }
888
889 void PrefProvider::MigrateObsoletePopupsPref(PrefService* prefs) {
890 if (prefs->HasPrefPath(prefs::kPopupWhitelistedHosts)) {
891 const ListValue* whitelist_pref =
892 prefs->GetList(prefs::kPopupWhitelistedHosts);
893 for (ListValue::const_iterator i(whitelist_pref->begin());
894 i != whitelist_pref->end(); ++i) {
895 std::string host;
896 (*i)->GetAsString(&host);
897 SetContentSetting(ContentSettingsPattern(host),
898 ContentSettingsPattern(host),
899 CONTENT_SETTINGS_TYPE_POPUPS,
900 "",
901 CONTENT_SETTING_ALLOW);
902 }
903 prefs->ClearPref(prefs::kPopupWhitelistedHosts);
904 }
905 }
906
907 // ////////////////////////////////////////////////////////////////////////////
908 // LEGACY TBR
909 //
910
911 ContentSettings PrefProvider::GetNonDefaultContentSettings(
912 const GURL& url) const {
913 base::AutoLock auto_lock(lock_);
914
915 const std::string host(net::GetHostOrSpecFromURL(url));
916 ContentSettings output;
917 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j)
918 output.settings[j] = CONTENT_SETTING_DEFAULT;
919
920 // Check for exact matches first.
921 HostContentSettings::const_iterator i(host_content_settings_.find(host));
922 if (i != host_content_settings_.end())
923 output = i->second.content_settings;
924
925 // If this map is not for an off-the-record profile, these searches will never
926 // match. The additional off-the-record exceptions always overwrite the
927 // regular ones.
928 i = off_the_record_settings_.find(host);
929 if (i != off_the_record_settings_.end()) {
930 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j)
931 if (i->second.content_settings.settings[j] != CONTENT_SETTING_DEFAULT)
932 output.settings[j] = i->second.content_settings.settings[j];
933 }
934
935 // Match patterns starting with the most concrete pattern match.
936 for (std::string key =
937 std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) {
938 HostContentSettings::const_iterator i(off_the_record_settings_.find(key));
939 if (i != off_the_record_settings_.end()) {
940 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
941 if (output.settings[j] == CONTENT_SETTING_DEFAULT)
942 output.settings[j] = i->second.content_settings.settings[j];
943 }
944 }
945 i = host_content_settings_.find(key);
946 if (i != host_content_settings_.end()) {
947 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
948 if (output.settings[j] == CONTENT_SETTING_DEFAULT)
949 output.settings[j] = i->second.content_settings.settings[j];
950 }
951 }
952 const size_t next_dot =
953 key.find('.', ContentSettingsPattern::kDomainWildcardLength);
954 if (next_dot == std::string::npos)
955 break;
956 key.erase(ContentSettingsPattern::kDomainWildcardLength,
957 next_dot - ContentSettingsPattern::kDomainWildcardLength + 1);
958 }
959
960 return output;
961 }
962
264 } // namespace content_settings 963 } // namespace content_settings
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698