diff options
Diffstat (limited to 'chromium/components/content_settings')
20 files changed, 431 insertions, 206 deletions
diff --git a/chromium/components/content_settings/core/browser/BUILD.gn b/chromium/components/content_settings/core/browser/BUILD.gn index 3e4fa6688f5..44e44e36352 100644 --- a/chromium/components/content_settings/core/browser/BUILD.gn +++ b/chromium/components/content_settings/core/browser/BUILD.gn @@ -54,6 +54,7 @@ static_library("browser") { "//components/url_formatter", "//extensions/features", "//net", + "//services/preferences/public/cpp", "//url", ] diff --git a/chromium/components/content_settings/core/browser/DEPS b/chromium/components/content_settings/core/browser/DEPS index eddae7bcb63..01dbe2ae6df 100644 --- a/chromium/components/content_settings/core/browser/DEPS +++ b/chromium/components/content_settings/core/browser/DEPS @@ -8,4 +8,5 @@ include_rules = [ "+extensions/features", "+net/base", "+net/cookies", + "+services/preferences/public", ] diff --git a/chromium/components/content_settings/core/browser/content_settings_default_provider.cc b/chromium/components/content_settings/core/browser/content_settings_default_provider.cc index 261fedb9d6b..ffa75aa7da7 100644 --- a/chromium/components/content_settings/core/browser/content_settings_default_provider.cc +++ b/chromium/components/content_settings/core/browser/content_settings_default_provider.cc @@ -11,6 +11,8 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" +#include "components/content_settings/core/browser/content_settings_info.h" +#include "components/content_settings/core/browser/content_settings_registry.h" #include "components/content_settings/core/browser/content_settings_rule.h" #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/browser/website_settings_info.h" @@ -186,6 +188,10 @@ DefaultProvider::DefaultProvider(PrefService* prefs, bool incognito) IntToContentSetting(prefs_->GetInteger( GetPrefName(CONTENT_SETTINGS_TYPE_AUTOPLAY))), CONTENT_SETTING_NUM_SETTINGS); + UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultSubresourceFilterSetting", + IntToContentSetting(prefs_->GetInteger(GetPrefName( + CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER))), + CONTENT_SETTING_NUM_SETTINGS); #endif pref_change_registrar_.Init(prefs_); PrefChangeRegistrar::NamedChangeCallback callback = base::Bind( @@ -296,6 +302,10 @@ bool DefaultProvider::IsValueEmptyOrDefault(ContentSettingsType content_type, void DefaultProvider::ChangeSetting(ContentSettingsType content_type, base::Value* value) { + const ContentSettingsInfo* info = + ContentSettingsRegistry::GetInstance()->Get(content_type); + DCHECK(!info || !value || + info->IsDefaultSettingValid(ValueToContentSetting(value))); default_settings_[content_type] = value ? base::WrapUnique(value->DeepCopy()) : ContentSettingToValue(GetDefaultValue(content_type)); @@ -363,6 +373,8 @@ std::unique_ptr<base::Value> DefaultProvider::ReadFromPref( } void DefaultProvider::DiscardObsoletePreferences() { + if (is_incognito_) + return; // These prefs were never stored on iOS/Android so they don't need to be // deleted. #if !defined(OS_IOS) diff --git a/chromium/components/content_settings/core/browser/content_settings_info.cc b/chromium/components/content_settings/core/browser/content_settings_info.cc index c111944e286..41fd1375bb0 100644 --- a/chromium/components/content_settings/core/browser/content_settings_info.cc +++ b/chromium/components/content_settings/core/browser/content_settings_info.cc @@ -5,6 +5,7 @@ #include "components/content_settings/core/browser/content_settings_info.h" #include "base/stl_util.h" +#include "components/content_settings/core/browser/website_settings_info.h" namespace content_settings { @@ -24,4 +25,26 @@ bool ContentSettingsInfo::IsSettingValid(ContentSetting setting) const { return base::ContainsKey(valid_settings_, setting); } +// TODO(raymes): Find a better way to deal with the special-casing in +// IsDefaultSettingValid. +bool ContentSettingsInfo::IsDefaultSettingValid(ContentSetting setting) const { + ContentSettingsType type = website_settings_info_->type(); +#if defined(OS_ANDROID) || defined(OS_CHROMEOS) + // Don't support ALLOW for protected media default setting until migration. + if (type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER && + setting == CONTENT_SETTING_ALLOW) { + return false; + } +#endif + + // Don't support ALLOW for the default media settings. + if ((type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA || + type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) && + setting == CONTENT_SETTING_ALLOW) { + return false; + } + + return base::ContainsKey(valid_settings_, setting); +} + } // namespace content_settings diff --git a/chromium/components/content_settings/core/browser/content_settings_info.h b/chromium/components/content_settings/core/browser/content_settings_info.h index d1eb3a58248..07a176741aa 100644 --- a/chromium/components/content_settings/core/browser/content_settings_info.h +++ b/chromium/components/content_settings/core/browser/content_settings_info.h @@ -46,6 +46,7 @@ class ContentSettingsInfo { } bool IsSettingValid(ContentSetting setting) const; + bool IsDefaultSettingValid(ContentSetting setting) const; IncognitoBehavior incognito_behavior() const { return incognito_behavior_; } diff --git a/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc b/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc index 3f6133b67a8..8bb2f98613c 100644 --- a/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc +++ b/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc @@ -38,10 +38,10 @@ class RuleIteratorImpl : public RuleIterator { Rule Next() override { DCHECK(HasNext()); - DCHECK(current_rule_->second.get()); + DCHECK(current_rule_->second.value.get()); Rule to_return(current_rule_->first.primary_pattern, current_rule_->first.secondary_pattern, - current_rule_->second.get()->DeepCopy()); + current_rule_->second.value.get()->DeepCopy()); ++current_rule_; return to_return; } @@ -83,6 +83,10 @@ bool OriginIdentifierValueMap::PatternPair::operator<( std::tie(other.primary_pattern, other.secondary_pattern); } +OriginIdentifierValueMap::ValueEntry::ValueEntry() : last_modified(), value(){}; + +OriginIdentifierValueMap::ValueEntry::~ValueEntry(){}; + std::unique_ptr<RuleIterator> OriginIdentifierValueMap::GetRuleIterator( ContentSettingsType content_type, const ResourceIdentifier& resource_identifier, @@ -129,17 +133,37 @@ base::Value* OriginIdentifierValueMap::GetValue( for (const auto& entry : it->second) { if (entry.first.primary_pattern.Matches(primary_url) && entry.first.secondary_pattern.Matches(secondary_url)) { - return entry.second.get(); + return entry.second.value.get(); } } return nullptr; } +base::Time OriginIdentifierValueMap::GetLastModified( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier) const { + DCHECK(primary_pattern.IsValid()); + DCHECK(secondary_pattern.IsValid()); + + EntryMapKey key(content_type, resource_identifier); + PatternPair patterns(primary_pattern, secondary_pattern); + EntryMap::const_iterator it = entries_.find(key); + if (it == entries_.end()) + return base::Time(); + Rules::const_iterator r = it->second.find(patterns); + if (r == it->second.end()) + return base::Time(); + return r->second.last_modified; +} + void OriginIdentifierValueMap::SetValue( const ContentSettingsPattern& primary_pattern, const ContentSettingsPattern& secondary_pattern, ContentSettingsType content_type, const ResourceIdentifier& resource_identifier, + base::Time last_modified, base::Value* value) { DCHECK(primary_pattern.IsValid()); DCHECK(secondary_pattern.IsValid()); @@ -150,7 +174,9 @@ void OriginIdentifierValueMap::SetValue( EntryMapKey key(content_type, resource_identifier); PatternPair patterns(primary_pattern, secondary_pattern); // This will create the entry and the linked_ptr if needed. - entries_[key][patterns].reset(value); + ValueEntry* entry = &entries_[key][patterns]; + entry->value.reset(value); + entry->last_modified = last_modified; } void OriginIdentifierValueMap::DeleteValue( diff --git a/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h b/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h index 1ac2fe56bed..f27816b6574 100644 --- a/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h +++ b/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h @@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/memory/linked_ptr.h" +#include "base/time/time.h" #include "components/content_settings/core/common/content_settings.h" class GURL; @@ -44,7 +45,14 @@ class OriginIdentifierValueMap { bool operator<(const OriginIdentifierValueMap::PatternPair& other) const; }; - typedef std::map<PatternPair, linked_ptr<base::Value> > Rules; + struct ValueEntry { + base::Time last_modified; + linked_ptr<base::Value> value; + ValueEntry(); + ~ValueEntry(); + }; + + typedef std::map<PatternPair, ValueEntry> Rules; typedef std::map<EntryMapKey, Rules> EntryMap; EntryMap::iterator begin() { @@ -92,15 +100,22 @@ class OriginIdentifierValueMap { ContentSettingsType content_type, const ResourceIdentifier& resource_identifier) const; - // Sets the |value| for the given |primary_pattern|, |secondary_pattern|, - // |content_type|, |resource_identifier| tuple. The method takes the ownership - // of the passed |value|. - void SetValue( + base::Time GetLastModified( const ContentSettingsPattern& primary_pattern, const ContentSettingsPattern& secondary_pattern, ContentSettingsType content_type, - const ResourceIdentifier& resource_identifier, - base::Value* value); + const ResourceIdentifier& resource_identifier) const; + + // Sets the |value| for the given |primary_pattern|, |secondary_pattern|, + // |content_type|, |resource_identifier| tuple. The method takes the ownership + // of the passed |value|. The caller can also store a |last_modified| date + // for each value. + void SetValue(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + base::Time last_modified, + base::Value* value); // Deletes the map entry for the given |primary_pattern|, // |secondary_pattern|, |content_type|, |resource_identifier| tuple. diff --git a/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc b/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc index c2967aa41a6..d9b8cfa9806 100644 --- a/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc +++ b/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc @@ -13,6 +13,8 @@ #include "base/json/json_reader.h" #include "base/macros.h" #include "base/values.h" +#include "components/content_settings/core/browser/content_settings_info.h" +#include "components/content_settings/core/browser/content_settings_registry.h" #include "components/content_settings/core/browser/content_settings_rule.h" #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/common/content_settings_pattern.h" @@ -235,9 +237,10 @@ void PolicyProvider::GetContentSettingsFromPreferences( VLOG_IF(2, !pattern_pair.second.IsValid()) << "Replacing invalid secondary pattern '" << pattern_pair.second.ToString() << "' with wildcard"; + // Don't set a timestamp for policy settings. value_map->SetValue( pattern_pair.first, secondary_pattern, content_type, - ResourceIdentifier(), + ResourceIdentifier(), base::Time(), new base::Value(kPrefsForManagedContentSettingsMap[i].setting)); } } @@ -319,11 +322,10 @@ void PolicyProvider::GetAutoSelectCertificateSettingsFromPreferences( // Don't pass removed values from |value|, because base::Values read with // JSONReader use a shared string buffer. Instead, DeepCopy here. - value_map->SetValue(pattern, - ContentSettingsPattern::Wildcard(), + // Don't set a timestamp for policy settings. + value_map->SetValue(pattern, ContentSettingsPattern::Wildcard(), CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, - std::string(), - cert_filter->DeepCopy()); + std::string(), base::Time(), cert_filter->DeepCopy()); } } @@ -334,6 +336,13 @@ void PolicyProvider::ReadManagedDefaultSettings() { void PolicyProvider::UpdateManagedDefaultSetting( const PrefsForManagedDefaultMapEntry& entry) { + // Not all managed default types are registered on every platform. If they're + // not registered, don't update them. + const ContentSettingsInfo* info = + ContentSettingsRegistry::GetInstance()->Get(entry.content_type); + if (!info) + return; + // If a pref to manage a default-content-setting was not set (NOTICE: // "HasPrefPath" returns false if no value was set for a registered pref) then // the default value of the preference is used. The default value of a @@ -355,10 +364,11 @@ void PolicyProvider::UpdateManagedDefaultSetting( value_map_.DeleteValue(ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(), entry.content_type, std::string()); - } else { + } else if (info->IsSettingValid(IntToContentSetting(setting))) { + // Don't set a timestamp for policy settings. value_map_.SetValue(ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(), entry.content_type, - std::string(), new base::Value(setting)); + std::string(), base::Time(), new base::Value(setting)); } } diff --git a/chromium/components/content_settings/core/browser/content_settings_pref.cc b/chromium/components/content_settings/core/browser/content_settings_pref.cc index f32e3018b4c..99e132b8151 100644 --- a/chromium/components/content_settings/core/browser/content_settings_pref.cc +++ b/chromium/components/content_settings/core/browser/content_settings_pref.cc @@ -8,7 +8,9 @@ #include "base/auto_reset.h" #include "base/bind.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "components/content_settings/core/browser/content_settings_info.h" #include "components/content_settings/core/browser/content_settings_registry.h" @@ -19,11 +21,14 @@ #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/pref_names.h" #include "components/prefs/scoped_user_pref_update.h" +#include "services/preferences/public/cpp/dictionary_value_update.h" +#include "services/preferences/public/cpp/scoped_pref_update.h" #include "url/gurl.h" namespace { const char kSettingPath[] = "setting"; +const char kLastModifiedPath[] = "last_modified"; const char kPerResourceIdentifierPrefName[] = "per_resource"; // If the given content type supports resource identifiers in user preferences, @@ -51,6 +56,17 @@ bool IsValueAllowedForType(const base::Value* value, ContentSettingsType type) { return value->GetType() == base::Value::Type::DICTIONARY; } +// Extract a timestamp from |dictionary[kLastModifiedPath]|. +// Will return base::Time() if no timestamp exists. +base::Time GetTimeStamp(const base::DictionaryValue* dictionary) { + std::string timestamp_str; + dictionary->GetStringWithoutPathExpansion(kLastModifiedPath, ×tamp_str); + int64_t timestamp = 0; + base::StringToInt64(timestamp_str, ×tamp); + base::Time last_modified = base::Time::FromInternalValue(timestamp); + return last_modified; +} + } // namespace namespace content_settings { @@ -95,6 +111,7 @@ bool ContentSettingsPref::SetWebsiteSetting( const ContentSettingsPattern& primary_pattern, const ContentSettingsPattern& secondary_pattern, const ResourceIdentifier& resource_identifier, + base::Time modified_time, base::Value* in_value) { DCHECK(!in_value || IsValueAllowedForType(in_value, content_type_)); DCHECK(thread_checker_.CalledOnValidThread()); @@ -114,12 +131,9 @@ bool ContentSettingsPref::SetWebsiteSetting( { base::AutoLock auto_lock(lock_); if (value.get()) { - map_to_modify->SetValue( - primary_pattern, - secondary_pattern, - content_type_, - resource_identifier, - value->DeepCopy()); + map_to_modify->SetValue(primary_pattern, secondary_pattern, content_type_, + resource_identifier, modified_time, + value->DeepCopy()); } else { map_to_modify->DeleteValue( primary_pattern, @@ -130,10 +144,8 @@ bool ContentSettingsPref::SetWebsiteSetting( } // Update the content settings preference. if (!is_incognito_) { - UpdatePref(primary_pattern, - secondary_pattern, - resource_identifier, - value.get()); + UpdatePref(primary_pattern, secondary_pattern, resource_identifier, + modified_time, value.get()); } notify_callback_.Run( @@ -142,6 +154,19 @@ bool ContentSettingsPref::SetWebsiteSetting( return true; } +base::Time ContentSettingsPref::GetWebsiteSettingLastModified( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + const ResourceIdentifier& resource_identifier) { + OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; + if (!is_incognito_) + map_to_modify = &value_map_; + + base::Time last_modified = map_to_modify->GetLastModified( + primary_pattern, secondary_pattern, content_type_, resource_identifier); + return last_modified; +} + void ContentSettingsPref::ClearPref() { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(prefs_); @@ -153,9 +178,8 @@ void ContentSettingsPref::ClearPref() { { base::AutoReset<bool> auto_reset(&updating_preferences_, true); - DictionaryPrefUpdate update(prefs_, pref_name_); - base::DictionaryValue* pattern_pairs_settings = update.Get(); - pattern_pairs_settings->Clear(); + prefs::ScopedDictionaryPrefUpdate update(prefs_, pref_name_); + update->Clear(); } } @@ -188,13 +212,13 @@ bool ContentSettingsPref::TryLockForTesting() const { } void ContentSettingsPref::ReadContentSettingsFromPref() { - // |DictionaryPrefUpdate| sends out notifications when destructed. This + // |ScopedDictionaryPrefUpdate| sends out notifications when destructed. This // construction order ensures |AutoLock| gets destroyed first and |lock_| is // not held when the notifications are sent. Also, |auto_reset| must be still // valid when the notifications are sent, so that |Observe| skips the // notification. base::AutoReset<bool> auto_reset(&updating_preferences_, true); - DictionaryPrefUpdate update(prefs_, pref_name_); + prefs::ScopedDictionaryPrefUpdate update(prefs_, pref_name_); base::AutoLock auto_lock(lock_); const base::DictionaryValue* all_settings_dictionary = @@ -202,27 +226,31 @@ void ContentSettingsPref::ReadContentSettingsFromPref() { value_map_.clear(); - // Careful: The returned value could be NULL if the pref has never been set. + // Careful: The returned value could be nullptr if the pref has never been + // set. if (!all_settings_dictionary) return; - base::DictionaryValue* mutable_settings; - std::unique_ptr<base::DictionaryValue> mutable_settings_scope; + const base::DictionaryValue* settings; if (!is_incognito_) { - mutable_settings = update.Get(); + // Convert all Unicode patterns into punycode form, then read. + auto mutable_settings = update.Get(); + CanonicalizeContentSettingsExceptions(mutable_settings.get()); + settings = mutable_settings->AsConstDictionary(); } else { - // Create copy as we do not want to persist anything in incognito prefs. - mutable_settings = all_settings_dictionary->DeepCopy(); - mutable_settings_scope.reset(mutable_settings); + // Canonicalization is unnecessary when |is_incognito_|. Both incognito and + // non-incognito read from the same pref and non-incognito reads occur + // before incognito reads. Thus, by the time the incognito call to + // ReadContentSettingsFromPref() occurs, the non-incognito call will have + // canonicalized the stored pref data. + settings = all_settings_dictionary; } - // Convert all Unicode patterns into punycode form, then read. - CanonicalizeContentSettingsExceptions(mutable_settings); size_t cookies_block_exception_count = 0; size_t cookies_allow_exception_count = 0; size_t cookies_session_only_exception_count = 0; - for (base::DictionaryValue::Iterator i(*mutable_settings); !i.IsAtEnd(); + for (base::DictionaryValue::Iterator i(*settings); !i.IsAtEnd(); i.Advance()) { const std::string& pattern_str(i.key()); std::pair<ContentSettingsPattern, ContentSettingsPattern> pattern_pair = @@ -236,14 +264,15 @@ void ContentSettingsPref::ReadContentSettingsFromPref() { // Get settings dictionary for the current pattern string, and read // settings from the dictionary. - const base::DictionaryValue* settings_dictionary = NULL; + const base::DictionaryValue* settings_dictionary = nullptr; bool is_dictionary = i.value().GetAsDictionary(&settings_dictionary); DCHECK(is_dictionary); if (SupportsResourceIdentifiers(content_type_)) { - const base::DictionaryValue* resource_dictionary = NULL; + const base::DictionaryValue* resource_dictionary = nullptr; if (settings_dictionary->GetDictionary( kPerResourceIdentifierPrefName, &resource_dictionary)) { + base::Time last_modified = GetTimeStamp(settings_dictionary); for (base::DictionaryValue::Iterator j(*resource_dictionary); !j.IsAtEnd(); j.Advance()) { @@ -253,10 +282,10 @@ void ContentSettingsPref::ReadContentSettingsFromPref() { DCHECK(is_integer); DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); std::unique_ptr<base::Value> setting_ptr(new base::Value(setting)); - value_map_.SetValue(pattern_pair.first, - pattern_pair.second, - content_type_, - resource_identifier, + DCHECK(IsValueAllowedForType(setting_ptr.get(), content_type_)); + // Per resource settings store a single timestamps for all resources. + value_map_.SetValue(pattern_pair.first, pattern_pair.second, + content_type_, resource_identifier, last_modified, setting_ptr->DeepCopy()); } } @@ -264,13 +293,11 @@ void ContentSettingsPref::ReadContentSettingsFromPref() { const base::Value* value = nullptr; settings_dictionary->GetWithoutPathExpansion(kSettingPath, &value); - if (value) { + base::Time last_modified = GetTimeStamp(settings_dictionary); DCHECK(IsValueAllowedForType(value, content_type_)); - value_map_.SetValue(pattern_pair.first, - pattern_pair.second, - content_type_, - ResourceIdentifier(), + value_map_.SetValue(pattern_pair.first, pattern_pair.second, + content_type_, ResourceIdentifier(), last_modified, value->DeepCopy()); if (content_type_ == CONTENT_SETTINGS_TYPE_COOKIES) { ContentSetting s = ValueToContentSetting(value); @@ -321,67 +348,82 @@ void ContentSettingsPref::UpdatePref( const ContentSettingsPattern& primary_pattern, const ContentSettingsPattern& secondary_pattern, const ResourceIdentifier& resource_identifier, + const base::Time last_modified, const base::Value* value) { // Ensure that |lock_| is not held by this thread, since this function will - // send out notifications (by |~DictionaryPrefUpdate|). + // send out notifications (by |~ScopedDictionaryPrefUpdate|). AssertLockNotHeld(); base::AutoReset<bool> auto_reset(&updating_preferences_, true); { - DictionaryPrefUpdate update(prefs_, pref_name_); - base::DictionaryValue* pattern_pairs_settings = update.Get(); + prefs::ScopedDictionaryPrefUpdate update(prefs_, pref_name_); + std::unique_ptr<prefs::DictionaryValueUpdate> pattern_pairs_settings = + update.Get(); // Get settings dictionary for the given patterns. std::string pattern_str(CreatePatternString(primary_pattern, secondary_pattern)); - base::DictionaryValue* settings_dictionary = NULL; + std::unique_ptr<prefs::DictionaryValueUpdate> settings_dictionary; bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( pattern_str, &settings_dictionary); if (!found && value) { - settings_dictionary = new base::DictionaryValue; - pattern_pairs_settings->SetWithoutPathExpansion( - pattern_str, settings_dictionary); + settings_dictionary = + pattern_pairs_settings->SetDictionaryWithoutPathExpansion( + pattern_str, base::MakeUnique<base::DictionaryValue>()); } if (settings_dictionary) { if (SupportsResourceIdentifiers(content_type_) && !resource_identifier.empty()) { - base::DictionaryValue* resource_dictionary = NULL; + std::unique_ptr<prefs::DictionaryValueUpdate> resource_dictionary; found = settings_dictionary->GetDictionary( kPerResourceIdentifierPrefName, &resource_dictionary); if (!found) { - if (value == NULL) + if (value == nullptr) return; // Nothing to remove. Exit early. - resource_dictionary = new base::DictionaryValue; - settings_dictionary->Set( - kPerResourceIdentifierPrefName, resource_dictionary); + resource_dictionary = + settings_dictionary->SetDictionaryWithoutPathExpansion( + kPerResourceIdentifierPrefName, + base::MakeUnique<base::DictionaryValue>()); } // Update resource dictionary. - if (value == NULL) { + if (value == nullptr) { resource_dictionary->RemoveWithoutPathExpansion(resource_identifier, - NULL); + nullptr); if (resource_dictionary->empty()) { settings_dictionary->RemoveWithoutPathExpansion( - kPerResourceIdentifierPrefName, NULL); + kPerResourceIdentifierPrefName, nullptr); + settings_dictionary->RemoveWithoutPathExpansion(kLastModifiedPath, + nullptr); } } else { - resource_dictionary->SetWithoutPathExpansion( - resource_identifier, value->DeepCopy()); + resource_dictionary->SetWithoutPathExpansion(resource_identifier, + value->CreateDeepCopy()); + // Update timestamp for whole resource dictionary. + settings_dictionary->SetStringWithoutPathExpansion( + kLastModifiedPath, + base::Int64ToString(last_modified.ToInternalValue())); } } else { // Update settings dictionary. - if (value == NULL) { - settings_dictionary->RemoveWithoutPathExpansion(kSettingPath, NULL); + if (value == nullptr) { + settings_dictionary->RemoveWithoutPathExpansion(kSettingPath, + nullptr); + settings_dictionary->RemoveWithoutPathExpansion(kLastModifiedPath, + nullptr); } else { - settings_dictionary->SetWithoutPathExpansion( - kSettingPath, value->DeepCopy()); + settings_dictionary->SetWithoutPathExpansion(kSettingPath, + value->CreateDeepCopy()); + settings_dictionary->SetStringWithoutPathExpansion( + kLastModifiedPath, + base::Int64ToString(last_modified.ToInternalValue())); } } // Remove the settings dictionary if it is empty. if (settings_dictionary->empty()) { - pattern_pairs_settings->RemoveWithoutPathExpansion( - pattern_str, NULL); + pattern_pairs_settings->RemoveWithoutPathExpansion(pattern_str, + nullptr); } } } @@ -389,14 +431,14 @@ void ContentSettingsPref::UpdatePref( // static void ContentSettingsPref::CanonicalizeContentSettingsExceptions( - base::DictionaryValue* all_settings_dictionary) { + prefs::DictionaryValueUpdate* all_settings_dictionary) { DCHECK(all_settings_dictionary); std::vector<std::string> remove_items; base::StringPairs move_items; - for (base::DictionaryValue::Iterator i(*all_settings_dictionary); - !i.IsAtEnd(); - i.Advance()) { + for (base::DictionaryValue::Iterator i( + *all_settings_dictionary->AsConstDictionary()); + !i.IsAtEnd(); i.Advance()) { const std::string& pattern_str(i.key()); std::pair<ContentSettingsPattern, ContentSettingsPattern> pattern_pair = ParsePatternString(pattern_str); @@ -415,7 +457,7 @@ void ContentSettingsPref::CanonicalizeContentSettingsExceptions( } // Clear old pattern if prefs already have canonicalized pattern. - const base::DictionaryValue* new_pattern_settings_dictionary = NULL; + const base::DictionaryValue* new_pattern_settings_dictionary = nullptr; if (all_settings_dictionary->GetDictionaryWithoutPathExpansion( canonicalized_pattern_str, &new_pattern_settings_dictionary)) { remove_items.push_back(pattern_str); @@ -423,7 +465,7 @@ void ContentSettingsPref::CanonicalizeContentSettingsExceptions( } // Move old pattern to canonicalized pattern. - const base::DictionaryValue* old_pattern_settings_dictionary = NULL; + const base::DictionaryValue* old_pattern_settings_dictionary = nullptr; if (i.value().GetAsDictionary(&old_pattern_settings_dictionary)) { move_items.push_back( std::make_pair(pattern_str, canonicalized_pattern_str)); @@ -431,7 +473,8 @@ void ContentSettingsPref::CanonicalizeContentSettingsExceptions( } for (size_t i = 0; i < remove_items.size(); ++i) { - all_settings_dictionary->RemoveWithoutPathExpansion(remove_items[i], NULL); + all_settings_dictionary->RemoveWithoutPathExpansion(remove_items[i], + nullptr); } for (size_t i = 0; i < move_items.size(); ++i) { @@ -439,7 +482,7 @@ void ContentSettingsPref::CanonicalizeContentSettingsExceptions( all_settings_dictionary->RemoveWithoutPathExpansion( move_items[i].first, &pattern_settings_dictionary); all_settings_dictionary->SetWithoutPathExpansion( - move_items[i].second, pattern_settings_dictionary.release()); + move_items[i].second, std::move(pattern_settings_dictionary)); } } diff --git a/chromium/components/content_settings/core/browser/content_settings_pref.h b/chromium/components/content_settings/core/browser/content_settings_pref.h index 77c6d031fb1..3139fc4aecb 100644 --- a/chromium/components/content_settings/core/browser/content_settings_pref.h +++ b/chromium/components/content_settings/core/browser/content_settings_pref.h @@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" +#include "base/time/time.h" #include "base/values.h" #include "components/content_settings/core/browser/content_settings_origin_identifier_value_map.h" #include "components/content_settings/core/browser/content_settings_provider.h" @@ -22,8 +23,8 @@ class PrefService; class PrefChangeRegistrar; -namespace base { -class DictionaryValue; +namespace prefs { +class DictionaryValueUpdate; } namespace content_settings { @@ -54,8 +55,15 @@ class ContentSettingsPref { bool SetWebsiteSetting(const ContentSettingsPattern& primary_pattern, const ContentSettingsPattern& secondary_pattern, const ResourceIdentifier& resource_identifier, + base::Time modified_time, base::Value* value); + // Returns the |last_modified| date of a setting. + base::Time GetWebsiteSettingLastModified( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + const ResourceIdentifier& resource_identifier); + void ClearPref(); void ClearAllContentSettingsRules(); @@ -77,14 +85,14 @@ class ContentSettingsPref { // value to the obsolete preference. When calling this function, |lock_| // should not be held, since this function will send out notifications of // preference changes. - void UpdatePref( - const ContentSettingsPattern& primary_pattern, - const ContentSettingsPattern& secondary_pattern, - const ResourceIdentifier& resource_identifier, - const base::Value* value); + void UpdatePref(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + const ResourceIdentifier& resource_identifier, + const base::Time last_modified, + const base::Value* value); static void CanonicalizeContentSettingsExceptions( - base::DictionaryValue* all_settings_dictionary); + prefs::DictionaryValueUpdate* all_settings_dictionary); // In the debug mode, asserts that |lock_| is not held by this thread. It's // ok if some other thread holds |lock_|, as long as it will eventually diff --git a/chromium/components/content_settings/core/browser/content_settings_pref_provider.cc b/chromium/components/content_settings/core/browser/content_settings_pref_provider.cc index 3bd173ebe0a..fc1d59bb35c 100644 --- a/chromium/components/content_settings/core/browser/content_settings_pref_provider.cc +++ b/chromium/components/content_settings/core/browser/content_settings_pref_provider.cc @@ -15,6 +15,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" +#include "base/time/default_clock.h" #include "components/content_settings/core/browser/content_settings_pref.h" #include "components/content_settings/core/browser/content_settings_rule.h" #include "components/content_settings/core/browser/content_settings_utils.h" @@ -28,6 +29,8 @@ #include "components/prefs/pref_registry.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" +#include "services/preferences/public/cpp/dictionary_value_update.h" +#include "services/preferences/public/cpp/scoped_pref_update.h" namespace content_settings { @@ -80,9 +83,13 @@ void PrefProvider::RegisterProfilePrefs( #endif // !defined(OS_IOS) } -PrefProvider::PrefProvider(PrefService* prefs, bool incognito) +PrefProvider::PrefProvider(PrefService* prefs, + bool incognito, + bool store_last_modified) : prefs_(prefs), - is_incognito_(incognito) { + is_incognito_(incognito), + store_last_modified_(store_last_modified), + clock_(new base::DefaultClock) { DCHECK(prefs_); // Verify preferences version. if (!prefs_->HasPrefPath(prefs::kContentSettingsVersion)) { @@ -150,9 +157,25 @@ bool PrefProvider::SetWebsiteSetting( return false; } + base::Time modified_time = + store_last_modified_ ? clock_->Now() : base::Time(); + return GetPref(content_type) ->SetWebsiteSetting(primary_pattern, secondary_pattern, - resource_identifier, in_value); + resource_identifier, modified_time, in_value); +} + +base::Time PrefProvider::GetWebsiteSettingLastModified( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier) { + DCHECK(CalledOnValidThread()); + DCHECK(prefs_); + + return GetPref(content_type) + ->GetWebsiteSettingLastModified(primary_pattern, secondary_pattern, + resource_identifier); } void PrefProvider::ClearAllContentSettingsRules( @@ -197,6 +220,8 @@ void PrefProvider::Notify( } void PrefProvider::DiscardObsoletePreferences() { + if (is_incognito_) + return; // These prefs were never stored on iOS/Android so they don't need to be // deleted. #if !defined(OS_IOS) @@ -236,11 +261,11 @@ void PrefProvider::DiscardObsoletePreferences() { if (!prefs_->GetDictionary(info->pref_name())) continue; - DictionaryPrefUpdate update(prefs_, info->pref_name()); - base::DictionaryValue* all_settings = update.Get(); + prefs::ScopedDictionaryPrefUpdate update(prefs_, info->pref_name()); + auto all_settings = update.Get(); std::vector<std::string> values_to_clean; - for (base::DictionaryValue::Iterator i(*all_settings); !i.IsAtEnd(); - i.Advance()) { + for (base::DictionaryValue::Iterator i(*all_settings->AsConstDictionary()); + !i.IsAtEnd(); i.Advance()) { const base::DictionaryValue* pattern_settings = nullptr; bool is_dictionary = i.value().GetAsDictionary(&pattern_settings); DCHECK(is_dictionary); @@ -249,7 +274,7 @@ void PrefProvider::DiscardObsoletePreferences() { } for (const std::string& key : values_to_clean) { - base::DictionaryValue* pattern_settings = nullptr; + std::unique_ptr<prefs::DictionaryValueUpdate> pattern_settings; all_settings->GetDictionaryWithoutPathExpansion(key, &pattern_settings); pattern_settings->RemoveWithoutPathExpansion(kObsoleteLastUsed, nullptr); if (pattern_settings->empty()) @@ -258,4 +283,8 @@ void PrefProvider::DiscardObsoletePreferences() { } } +void PrefProvider::SetClockForTesting(std::unique_ptr<base::Clock> clock) { + clock_ = std::move(clock); +} + } // namespace content_settings diff --git a/chromium/components/content_settings/core/browser/content_settings_pref_provider.h b/chromium/components/content_settings/core/browser/content_settings_pref_provider.h index 9f33e158f6e..124ac9b840f 100644 --- a/chromium/components/content_settings/core/browser/content_settings_pref_provider.h +++ b/chromium/components/content_settings/core/browser/content_settings_pref_provider.h @@ -18,6 +18,10 @@ class PrefService; +namespace base { +class Clock; +} + namespace user_prefs { class PrefRegistrySyncable; } @@ -32,7 +36,7 @@ class PrefProvider : public ObservableProvider { public: static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); - PrefProvider(PrefService* prefs, bool incognito); + PrefProvider(PrefService* prefs, bool incognito, bool store_last_modified); ~PrefProvider() override; // ProviderInterface implementations. @@ -47,6 +51,13 @@ class PrefProvider : public ObservableProvider { const ResourceIdentifier& resource_identifier, base::Value* value) override; + // Returns the |last_modified| date of a setting. + base::Time GetWebsiteSettingLastModified( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier); + void ClearAllContentSettingsRules(ContentSettingsType content_type) override; void ShutdownOnUIThread() override; @@ -55,6 +66,8 @@ class PrefProvider : public ObservableProvider { ContentSettingsPref* GetPref(ContentSettingsType type) const; + void SetClockForTesting(std::unique_ptr<base::Clock> clock); + private: friend class DeadlockCheckerObserver; // For testing. @@ -71,6 +84,8 @@ class PrefProvider : public ObservableProvider { const bool is_incognito_; + bool store_last_modified_; + PrefChangeRegistrar pref_change_registrar_; std::map<ContentSettingsType, std::unique_ptr<ContentSettingsPref>> @@ -78,6 +93,8 @@ class PrefProvider : public ObservableProvider { base::ThreadChecker thread_checker_; + std::unique_ptr<base::Clock> clock_; + DISALLOW_COPY_AND_ASSIGN(PrefProvider); }; diff --git a/chromium/components/content_settings/core/browser/content_settings_registry.cc b/chromium/components/content_settings/core/browser/content_settings_registry.cc index b782ec64617..6b18f449543 100644 --- a/chromium/components/content_settings/core/browser/content_settings_registry.cc +++ b/chromium/components/content_settings/core/browser/content_settings_registry.cc @@ -250,7 +250,8 @@ void ContentSettingsRegistry::Init() { Register(CONTENT_SETTINGS_TYPE_DURABLE_STORAGE, "durable-storage", CONTENT_SETTING_ASK, WebsiteSettingsInfo::UNSYNCABLE, WhitelistedSchemes(), - ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK), + ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, + CONTENT_SETTING_ASK), WebsiteSettingsInfo::REQUESTING_ORIGIN_ONLY_SCOPE, WebsiteSettingsRegistry::DESKTOP | WebsiteSettingsRegistry::PLATFORM_ANDROID, @@ -274,8 +275,8 @@ void ContentSettingsRegistry::Init() { ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE); Register(CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER, "subresource-filter", - CONTENT_SETTING_ALLOW, - WebsiteSettingsInfo::UNSYNCABLE, WhitelistedSchemes(), + CONTENT_SETTING_BLOCK, WebsiteSettingsInfo::UNSYNCABLE, + WhitelistedSchemes(), ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK), WebsiteSettingsInfo::REQUESTING_ORIGIN_ONLY_SCOPE, WebsiteSettingsRegistry::DESKTOP | diff --git a/chromium/components/content_settings/core/browser/content_settings_registry_unittest.cc b/chromium/components/content_settings/core/browser/content_settings_registry_unittest.cc index d63d180e0bf..db419b6e434 100644 --- a/chromium/components/content_settings/core/browser/content_settings_registry_unittest.cc +++ b/chromium/components/content_settings/core/browser/content_settings_registry_unittest.cc @@ -124,4 +124,23 @@ TEST_F(ContentSettingsRegistryTest, Iteration) { EXPECT_TRUE(cookies_found); } +TEST_F(ContentSettingsRegistryTest, IsDefaultSettingValid) { + const ContentSettingsInfo* info = + registry()->Get(CONTENT_SETTINGS_TYPE_COOKIES); + EXPECT_TRUE(info->IsDefaultSettingValid(CONTENT_SETTING_ALLOW)); + +#if !defined(OS_IOS) + info = registry()->Get(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); + EXPECT_FALSE(info->IsDefaultSettingValid(CONTENT_SETTING_ALLOW)); + + info = registry()->Get(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); + EXPECT_FALSE(info->IsDefaultSettingValid(CONTENT_SETTING_ALLOW)); +#endif + +#if defined(OS_ANDROID) || defined(OS_CHROMEOS) + info = registry()->Get(CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER); + EXPECT_FALSE(info->IsDefaultSettingValid(CONTENT_SETTING_ALLOW)); +#endif +} + } // namespace content_settings diff --git a/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc b/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc index 1d16b2fec5f..f606004be5e 100644 --- a/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc +++ b/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc @@ -31,7 +31,8 @@ class CookieSettingsTest : public testing::Test { CookieSettings::RegisterProfilePrefs(prefs_.registry()); HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry()); settings_map_ = new HostContentSettingsMap( - &prefs_, false /* incognito_profile */, false /* guest_profile */); + &prefs_, false /* incognito_profile */, false /* guest_profile */, + false /* store_last_modified */); cookie_settings_ = new CookieSettings(settings_map_.get(), &prefs_, "chrome-extension"); } diff --git a/chromium/components/content_settings/core/browser/host_content_settings_map.cc b/chromium/components/content_settings/core/browser/host_content_settings_map.cc index 3879f3096c0..52a6708ea74 100644 --- a/chromium/components/content_settings/core/browser/host_content_settings_map.cc +++ b/chromium/components/content_settings/core/browser/host_content_settings_map.cc @@ -178,13 +178,15 @@ content_settings::PatternPair GetPatternsForContentSettingsType( HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs, bool is_incognito_profile, - bool is_guest_profile) + bool is_guest_profile, + bool store_last_modified) : RefcountedKeyedService(base::ThreadTaskRunnerHandle::Get()), #ifndef NDEBUG used_from_thread_id_(base::PlatformThread::CurrentId()), #endif prefs_(prefs), is_incognito_(is_incognito_profile || is_guest_profile), + store_last_modified_(store_last_modified), weak_ptr_factory_(this) { DCHECK(!(is_incognito_profile && is_guest_profile)); @@ -194,8 +196,8 @@ HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs, base::WrapUnique(policy_provider); policy_provider->AddObserver(this); - pref_provider_ = - new content_settings::PrefProvider(prefs_, is_incognito_); + pref_provider_ = new content_settings::PrefProvider(prefs_, is_incognito_, + store_last_modified_); content_settings_providers_[PREF_PROVIDER] = base::WrapUnique(pref_provider_); pref_provider_->AddObserver(this); @@ -347,7 +349,9 @@ void HostContentSettingsMap::SetDefaultContentSetting( std::unique_ptr<base::Value> value; // A value of CONTENT_SETTING_DEFAULT implies deleting the content setting. if (setting != CONTENT_SETTING_DEFAULT) { - DCHECK(IsDefaultSettingAllowedForType(setting, content_type)); + DCHECK(content_settings::ContentSettingsRegistry::GetInstance() + ->Get(content_type) + ->IsDefaultSettingValid(setting)); value.reset(new base::Value(setting)); } SetWebsiteSettingCustomScope(ContentSettingsPattern::Wildcard(), @@ -656,57 +660,41 @@ void HostContentSettingsMap::ClearSettingsForOneType( FlushLossyWebsiteSettings(); } +base::Time HostContentSettingsMap::GetSettingLastModifiedDate( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type) const { + return pref_provider_->GetWebsiteSettingLastModified( + primary_pattern, secondary_pattern, content_type, std::string()); +} + void HostContentSettingsMap::ClearSettingsForOneTypeWithPredicate( ContentSettingsType content_type, - const base::Callback<bool(const ContentSettingsPattern& primary_pattern, - const ContentSettingsPattern& secondary_pattern)>& - pattern_predicate) { - if (pattern_predicate.is_null()) { + base::Time begin_time, + const PatternSourcePredicate& pattern_predicate) { + if (pattern_predicate.is_null() && begin_time.is_null()) { ClearSettingsForOneType(content_type); return; } - + UsedContentSettingsProviders(); ContentSettingsForOneType settings; GetSettingsForOneType(content_type, std::string(), &settings); for (const ContentSettingPatternSource& setting : settings) { - if (pattern_predicate.Run(setting.primary_pattern, + if (pattern_predicate.is_null() || + pattern_predicate.Run(setting.primary_pattern, setting.secondary_pattern)) { - SetWebsiteSettingCustomScope(setting.primary_pattern, - setting.secondary_pattern, content_type, - std::string(), nullptr); + base::Time last_modified = pref_provider_->GetWebsiteSettingLastModified( + setting.primary_pattern, setting.secondary_pattern, content_type, + std::string()); + if (last_modified >= begin_time) { + pref_provider_->SetWebsiteSetting(setting.primary_pattern, + setting.secondary_pattern, + content_type, std::string(), nullptr); + } } } } -// TODO(raymes): Remove this function. Consider making it a property of -// ContentSettingsInfo or removing it altogether (it's unclear whether we should -// be restricting allowed default values at this layer). -// static -bool HostContentSettingsMap::IsDefaultSettingAllowedForType( - ContentSetting setting, - ContentSettingsType content_type) { -#if defined(OS_ANDROID) || defined(OS_CHROMEOS) - // Don't support ALLOW for protected media default setting until migration. - if (content_type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER && - setting == CONTENT_SETTING_ALLOW) { - return false; - } -#endif - - // Don't support ALLOW for the default media settings. - if ((content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA || - content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) && - setting == CONTENT_SETTING_ALLOW) { - return false; - } - - const content_settings::ContentSettingsInfo* info = - content_settings::ContentSettingsRegistry::GetInstance()->Get( - content_type); - DCHECK(info); - return info->IsSettingValid(setting); -} - void HostContentSettingsMap::OnContentSettingChanged( const ContentSettingsPattern& primary_pattern, const ContentSettingsPattern& secondary_pattern, @@ -806,11 +794,8 @@ std::unique_ptr<base::Value> HostContentSettingsMap::GetWebsiteSetting( } } - return GetWebsiteSettingInternal(primary_url, - secondary_url, - content_type, - resource_identifier, - info); + return GetWebsiteSettingInternal(primary_url, secondary_url, content_type, + resource_identifier, info); } // static @@ -921,3 +906,8 @@ HostContentSettingsMap::GetContentSettingValueAndPatterns( } return std::unique_ptr<base::Value>(); } + +void HostContentSettingsMap::SetClockForTesting( + std::unique_ptr<base::Clock> clock) { + pref_provider_->SetClockForTesting(std::move(clock)); +}
\ No newline at end of file diff --git a/chromium/components/content_settings/core/browser/host_content_settings_map.h b/chromium/components/content_settings/core/browser/host_content_settings_map.h index eadf365cfbd..b5c7798b02f 100644 --- a/chromium/components/content_settings/core/browser/host_content_settings_map.h +++ b/chromium/components/content_settings/core/browser/host_content_settings_map.h @@ -31,6 +31,7 @@ class PrefService; namespace base { class Value; +class Clock; } namespace content_settings { @@ -66,7 +67,8 @@ class HostContentSettingsMap : public content_settings::Observer, // |is_incognito_profile| and |is_guest_profile| should be true. HostContentSettingsMap(PrefService* prefs, bool is_incognito_profile, - bool is_guest_profile); + bool is_guest_profile, + bool store_last_modified); static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); @@ -217,16 +219,27 @@ class HostContentSettingsMap : public content_settings::Observer, // This should only be called on the UI thread. void ClearSettingsForOneType(ContentSettingsType content_type); + // Return the |last_modified| date of a content setting. This will only return + // valid values for settings from the PreferenceProvider. Settings from other + // providers will return base::Time(). + // + // This may be called on any thread. + base::Time GetSettingLastModifiedDate( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type) const; + + using PatternSourcePredicate = + base::Callback<bool(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern)>; + // If |pattern_predicate| is null, this method is equivalent to the above. - // Otherwise, it only deletes exceptions matched by |pattern_predicate|. + // Otherwise, it only deletes exceptions matched by |pattern_predicate| that + // were modified at or after |begin_time|. void ClearSettingsForOneTypeWithPredicate( ContentSettingsType content_type, - const base::Callback<bool( - const ContentSettingsPattern& primary_pattern, - const ContentSettingsPattern& secondary_pattern)>& pattern_predicate); - - static bool IsDefaultSettingAllowedForType(ContentSetting setting, - ContentSettingsType content_type); + base::Time begin_time, + const PatternSourcePredicate& pattern_predicate); // RefcountedKeyedService implementation. void ShutdownOnUIThread() override; @@ -267,6 +280,10 @@ class HostContentSettingsMap : public content_settings::Observer, base::WeakPtr<HostContentSettingsMap> GetWeakPtr(); + // Injects a clock into the PrefProvider to allow control over the + // |last_modified| timestamp. + void SetClockForTesting(std::unique_ptr<base::Clock> clock); + private: friend class base::RefCountedThreadSafe<HostContentSettingsMap>; @@ -358,6 +375,10 @@ class HostContentSettingsMap : public content_settings::Observer, // Whether this settings map is for an incognito session. bool is_incognito_; + // Whether ContentSettings in the PrefProvider will store a last_modified + // timestamp. + bool store_last_modified_; + // Content setting providers. This is only modified at construction // time and by RegisterExtensionService, both of which should happen // before any other uses of it. diff --git a/chromium/components/content_settings/core/browser/website_settings_registry.cc b/chromium/components/content_settings/core/browser/website_settings_registry.cc index 1cfb5441383..4d49cef938c 100644 --- a/chromium/components/content_settings/core/browser/website_settings_registry.cc +++ b/chromium/components/content_settings/core/browser/website_settings_registry.cc @@ -165,6 +165,14 @@ void WebsiteSettingsRegistry::Init() { WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY, WebsiteSettingsInfo::REQUESTING_ORIGIN_ONLY_SCOPE, DESKTOP | PLATFORM_ANDROID, WebsiteSettingsInfo::INHERIT_IN_INCOGNITO); + // Set when an origin is activated for subresource filtering and the + // associated UI is shown to the user. Cleared when a site is de-activated or + // the first URL matching the origin is removed from history. + Register( + CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER_DATA, "subresource-filter-data", + nullptr, WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY, + WebsiteSettingsInfo::REQUESTING_ORIGIN_ONLY_SCOPE, + DESKTOP | PLATFORM_ANDROID, WebsiteSettingsInfo::INHERIT_IN_INCOGNITO); } } // namespace content_settings diff --git a/chromium/components/content_settings/core/common/content_settings.cc b/chromium/components/content_settings/core/common/content_settings.cc index ec1621532d9..4cf2d132898 100644 --- a/chromium/components/content_settings/core/common/content_settings.cc +++ b/chromium/components/content_settings/core/common/content_settings.cc @@ -16,50 +16,47 @@ ContentSetting IntToContentSetting(int content_setting) { CONTENT_SETTING_DEFAULT : static_cast<ContentSetting>(content_setting); } -// WARNING: This array should not be reordered or removed as it is used for -// histogram values. If a ContentSettingsType value has been removed, the entry -// must be replaced by a placeholder. It should correspond directly to the -// ContentType enum in histograms.xml. +struct HistogramValue { + ContentSettingsType type; + int value; +}; + +// WARNING: The value specified here for a type should match exactly the value +// specified in the ContentType enum in histograms.xml. Since these values are +// used for histograms, please do not reuse the same value for a different +// content setting. Always append to the end and increment. // TODO(raymes): We should use a sparse histogram here on the hash of the // content settings type name instead. -ContentSettingsType kHistogramOrder[] = { - CONTENT_SETTINGS_TYPE_COOKIES, - CONTENT_SETTINGS_TYPE_IMAGES, - CONTENT_SETTINGS_TYPE_JAVASCRIPT, - CONTENT_SETTINGS_TYPE_PLUGINS, - CONTENT_SETTINGS_TYPE_POPUPS, - CONTENT_SETTINGS_TYPE_GEOLOCATION, - CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, - CONTENT_SETTINGS_TYPE_DEFAULT, // FULLSCREEN (removed). - CONTENT_SETTINGS_TYPE_DEFAULT, // MOUSELOCK (removed). - CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, - CONTENT_SETTINGS_TYPE_DEFAULT, // MEDIASTREAM (removed). - CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, - CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, - CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, - CONTENT_SETTINGS_TYPE_PPAPI_BROKER, - CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, - CONTENT_SETTINGS_TYPE_MIDI_SYSEX, - CONTENT_SETTINGS_TYPE_DEFAULT, // PUSH_MESSAGING (removed). - CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, - CONTENT_SETTINGS_TYPE_DEFAULT, // METRO_SWITCH_TO_DESKTOP (removed). +HistogramValue kHistogramValue[] = { + {CONTENT_SETTINGS_TYPE_COOKIES, 0}, + {CONTENT_SETTINGS_TYPE_IMAGES, 1}, + {CONTENT_SETTINGS_TYPE_JAVASCRIPT, 2}, + {CONTENT_SETTINGS_TYPE_PLUGINS, 3}, + {CONTENT_SETTINGS_TYPE_POPUPS, 4}, + {CONTENT_SETTINGS_TYPE_GEOLOCATION, 5}, + {CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 6}, + {CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, 7}, + {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, 10}, + {CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, 12}, + {CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, 13}, + {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, 14}, + {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, 15}, + {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, 16}, + {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, 17}, + {CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, 19}, #if defined(OS_ANDROID) || defined(OS_CHROMEOS) - CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, -#else - CONTENT_SETTINGS_TYPE_DEFAULT, // PROTECTED_MEDIA_IDENTIFIER (mobile only). + {CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, 21}, #endif - CONTENT_SETTINGS_TYPE_APP_BANNER, - CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, - CONTENT_SETTINGS_TYPE_DURABLE_STORAGE, - CONTENT_SETTINGS_TYPE_DEFAULT, // KEYGEN (removed). - CONTENT_SETTINGS_TYPE_BLUETOOTH_GUARD, - CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC, - CONTENT_SETTINGS_TYPE_AUTOPLAY, - CONTENT_SETTINGS_TYPE_DEFAULT, // PROMPT_NO_DECISION_COUNT (migrated). - CONTENT_SETTINGS_TYPE_IMPORTANT_SITE_INFO, - CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, - CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER, + {CONTENT_SETTINGS_TYPE_APP_BANNER, 22}, + {CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, 23}, + {CONTENT_SETTINGS_TYPE_DURABLE_STORAGE, 24}, + {CONTENT_SETTINGS_TYPE_BLUETOOTH_GUARD, 26}, + {CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC, 27}, + {CONTENT_SETTINGS_TYPE_AUTOPLAY, 28}, + {CONTENT_SETTINGS_TYPE_IMPORTANT_SITE_INFO, 30}, + {CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, 31}, + {CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER, 32}, + {CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER_DATA, 33}, }; int ContentSettingTypeToHistogramValue(ContentSettingsType content_setting, @@ -68,14 +65,12 @@ int ContentSettingTypeToHistogramValue(ContentSettingsType content_setting, typedef base::hash_map<int, int> Map; CR_DEFINE_STATIC_LOCAL(Map, kMap, ()); if (kMap.empty()) { - for (size_t i = 0; i < arraysize(kHistogramOrder); ++i) { - if (kHistogramOrder[i] != CONTENT_SETTINGS_TYPE_DEFAULT) - kMap[kHistogramOrder[i]] = static_cast<int>(i); - } + for (const HistogramValue& histogram_value : kHistogramValue) + kMap[histogram_value.type] = histogram_value.value; } DCHECK(base::ContainsKey(kMap, content_setting)); - *num_values = arraysize(kHistogramOrder); + *num_values = arraysize(kHistogramValue); return kMap[content_setting]; } diff --git a/chromium/components/content_settings/core/common/content_settings_types.h b/chromium/components/content_settings/core/common/content_settings_types.h index d7584141be5..580a94ac8c6 100644 --- a/chromium/components/content_settings/core/common/content_settings_types.h +++ b/chromium/components/content_settings/core/common/content_settings_types.h @@ -50,6 +50,10 @@ enum ContentSettingsType { CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER, + // Website setting which stores metadata for the subresource filter to aid in + // decisions for whether or not to show the UI. + CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER_DATA, + // This is special-cased in the permissions layer to always allow, and as // such doesn't have associated prefs data. CONTENT_SETTINGS_TYPE_MIDI, |