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

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: " 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);
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 i(
458 map_to_modify->find(pattern_str));
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 requested_setting(
543 content_type, resource_identifier);
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(
553 requested_setting)->second;
554 } else {
555 setting = CONTENT_SETTING_DEFAULT;
556 }
557 } else {
558 setting = i->second.content_settings.settings[content_type];
559 }
560 if (setting != CONTENT_SETTING_DEFAULT) {
561 // Use of push_back() relies on the map iterator traversing in order of
562 // ascending keys.
563 content_setting_rules->push_back(Rule(ContentSettingsPattern(i->first),
564 ContentSettingsPattern(i->first),
565 setting));
566 }
567 }
568 }
569
570 void PrefProvider::ResetToDefaults() {
571 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
572
573 {
574 base::AutoLock auto_lock(lock_);
575 host_content_settings_.clear();
576 off_the_record_settings_.clear();
577 }
578
579 if (!is_off_the_record_) {
580 PrefService* prefs = profile_->GetPrefs();
581 updating_preferences_ = true;
582 prefs->ClearPref(prefs::kContentSettingsPatterns);
583 updating_preferences_ = false;
584 }
585 }
586
587 void PrefProvider::ClearAllContentSettingsRules(
588 ContentSettingsType content_type) {
589 DCHECK(kTypeNames[content_type] != NULL); // Don't call this for Geolocation.
590
591 PrefService* prefs = NULL;
592 DictionaryValue* all_settings_dictionary = NULL;
593 HostContentSettings* map_to_modify = &off_the_record_settings_;
594
595 if (!is_off_the_record_) {
596 prefs = profile_->GetPrefs();
597 all_settings_dictionary =
598 prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
599 map_to_modify = &host_content_settings_;
600 }
601
602 {
603 base::AutoLock auto_lock(lock_);
604 for (HostContentSettings::iterator i(map_to_modify->begin());
605 i != map_to_modify->end(); ) {
606 if (RequiresResourceIdentifier(content_type) ||
607 i->second.content_settings.settings[content_type] !=
608 CONTENT_SETTING_DEFAULT) {
609 if (RequiresResourceIdentifier(content_type))
610 i->second.content_settings_for_resources.clear();
611 i->second.content_settings.settings[content_type] =
612 CONTENT_SETTING_DEFAULT;
613 std::string host(i->first);
614 if (AllDefault(i->second)) {
615 if (all_settings_dictionary)
616 all_settings_dictionary->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 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
841 if (initializing_ || profile_ == NULL)
842 return;
843 NotificationService::current()->Notify(
844 NotificationType::CONTENT_SETTINGS_CHANGED,
845 Source<HostContentSettingsMap>(
846 profile_->GetHostContentSettingsMap()),
847 Details<const ContentSettingsDetails>(&details));
848 }
849
850 void PrefProvider::UnregisterObservers() {
851 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
852 if (!profile_)
853 return;
854 pref_change_registrar_.RemoveAll();
855 notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED,
856 Source<Profile>(profile_));
857 profile_ = NULL;
858 }
859
860 void PrefProvider::MigrateObsoletePerhostPref(PrefService* prefs) {
861 if (prefs->HasPrefPath(prefs::kPerHostContentSettings)) {
862 const DictionaryValue* all_settings_dictionary =
863 prefs->GetDictionary(prefs::kPerHostContentSettings);
864 for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
865 i != all_settings_dictionary->end_keys(); ++i) {
866 const std::string& host(*i);
867 ContentSettingsPattern pattern(
868 std::string(ContentSettingsPattern::kDomainWildcard) + host);
869 DictionaryValue* host_settings_dictionary = NULL;
870 bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
871 host, &host_settings_dictionary);
872 DCHECK(found);
873 ContentSettings settings;
874 GetSettingsFromDictionary(host_settings_dictionary, &settings);
875 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
876 if (settings.settings[j] != CONTENT_SETTING_DEFAULT &&
877 !RequiresResourceIdentifier(ContentSettingsType(j))) {
878 SetContentSetting(
879 pattern,
880 pattern,
881 ContentSettingsType(j),
882 "",
883 settings.settings[j]);
884 }
885 }
886 }
887 prefs->ClearPref(prefs::kPerHostContentSettings);
888 }
889 }
890
891 void PrefProvider::MigrateObsoletePopupsPref(PrefService* prefs) {
892 if (prefs->HasPrefPath(prefs::kPopupWhitelistedHosts)) {
893 const ListValue* whitelist_pref =
894 prefs->GetList(prefs::kPopupWhitelistedHosts);
895 for (ListValue::const_iterator i(whitelist_pref->begin());
896 i != whitelist_pref->end(); ++i) {
897 std::string host;
898 (*i)->GetAsString(&host);
899 SetContentSetting(ContentSettingsPattern(host),
900 ContentSettingsPattern(host),
901 CONTENT_SETTINGS_TYPE_POPUPS,
902 "",
903 CONTENT_SETTING_ALLOW);
904 }
905 prefs->ClearPref(prefs::kPopupWhitelistedHosts);
906 }
907 }
908
909 // ////////////////////////////////////////////////////////////////////////////
910 // LEGACY TBR
911 //
912
913 ContentSettings PrefProvider::GetNonDefaultContentSettings(
914 const GURL& url) const {
915 base::AutoLock auto_lock(lock_);
916
917 const std::string host(net::GetHostOrSpecFromURL(url));
918 ContentSettings output;
919 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j)
920 output.settings[j] = CONTENT_SETTING_DEFAULT;
921
922 // Check for exact matches first.
923 HostContentSettings::const_iterator i(host_content_settings_.find(host));
924 if (i != host_content_settings_.end())
925 output = i->second.content_settings;
926
927 // If this map is not for an off-the-record profile, these searches will never
928 // match. The additional off-the-record exceptions always overwrite the
929 // regular ones.
930 i = off_the_record_settings_.find(host);
931 if (i != off_the_record_settings_.end()) {
932 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j)
933 if (i->second.content_settings.settings[j] != CONTENT_SETTING_DEFAULT)
934 output.settings[j] = i->second.content_settings.settings[j];
935 }
936
937 // Match patterns starting with the most concrete pattern match.
938 for (std::string key =
939 std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) {
940 HostContentSettings::const_iterator i(off_the_record_settings_.find(key));
941 if (i != off_the_record_settings_.end()) {
942 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
943 if (output.settings[j] == CONTENT_SETTING_DEFAULT)
944 output.settings[j] = i->second.content_settings.settings[j];
945 }
946 }
947 i = host_content_settings_.find(key);
948 if (i != host_content_settings_.end()) {
949 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
950 if (output.settings[j] == CONTENT_SETTING_DEFAULT)
951 output.settings[j] = i->second.content_settings.settings[j];
952 }
953 }
954 const size_t next_dot =
955 key.find('.', ContentSettingsPattern::kDomainWildcardLength);
956 if (next_dot == std::string::npos)
957 break;
958 key.erase(ContentSettingsPattern::kDomainWildcardLength,
959 next_dot - ContentSettingsPattern::kDomainWildcardLength + 1);
960 }
961
962 return output;
963 }
964
264 } // namespace content_settings 965 } // namespace content_settings
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698