OLD | NEW |
---|---|
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 Loading... | |
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 |
OLD | NEW |