Chromium Code Reviews| Index: components/content_settings/core/browser/content_settings_pref.cc |
| diff --git a/components/content_settings/core/browser/content_settings_pref.cc b/components/content_settings/core/browser/content_settings_pref.cc |
| index f32e3018b4cc0828d4b5b7efa7a596d5f022d82b..05c777a012ef6930a628d049d9209b6d9e0bd769 100644 |
| --- a/components/content_settings/core/browser/content_settings_pref.cc |
| +++ b/components/content_settings/core/browser/content_settings_pref.cc |
| @@ -9,6 +9,7 @@ |
| #include "base/auto_reset.h" |
| #include "base/bind.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" |
| @@ -24,6 +25,7 @@ |
| 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 +53,18 @@ bool IsValueAllowedForType(const base::Value* value, ContentSettingsType type) { |
| return value->GetType() == base::Value::Type::DICTIONARY; |
| } |
| +// Extract a timestamp from |dictionary[path]|. Will return base::Time() if no |
| +// timestamp exists. |
| +base::Time GetTimeStamp(const base::DictionaryValue* dictionary, |
| + const std::string& path) { |
|
raymes
2017/04/24 03:20:22
Do we need to pass this in if it's always kLastMod
dullweber
2017/04/25 10:50:44
Done.
|
| + std::string timestamp_str; |
| + dictionary->GetStringWithoutPathExpansion(path, ×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 { |
| @@ -61,12 +75,14 @@ ContentSettingsPref::ContentSettingsPref( |
| PrefChangeRegistrar* registrar, |
| const std::string& pref_name, |
| bool incognito, |
| + bool store_last_modified, |
| NotifyObserversCallback notify_callback) |
| : content_type_(content_type), |
| prefs_(prefs), |
| registrar_(registrar), |
| pref_name_(pref_name), |
| is_incognito_(incognito), |
| + store_last_modified_(store_last_modified), |
| updating_preferences_(false), |
| notify_callback_(notify_callback) { |
| DCHECK(prefs_); |
| @@ -111,15 +127,15 @@ bool ContentSettingsPref::SetWebsiteSetting( |
| if (!is_incognito_) |
| map_to_modify = &value_map_; |
| + base::Time modified_time = |
| + store_last_modified_ ? base::Time::Now() : base::Time(); |
| + |
| { |
| 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 +146,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 +156,22 @@ bool ContentSettingsPref::SetWebsiteSetting( |
| return true; |
| } |
| +void ContentSettingsPref::DeleteWebsiteSetting( |
| + const ContentSettingsPattern& primary_pattern, |
| + const ContentSettingsPattern& secondary_pattern, |
| + base::Time begin_time) { |
| + 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_, ResourceIdentifier()); |
| + if (begin_time <= last_modified) { |
| + SetWebsiteSetting(primary_pattern, secondary_pattern, ResourceIdentifier(), |
| + nullptr); |
| + } |
| +} |
| + |
| void ContentSettingsPref::ClearPref() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK(prefs_); |
| @@ -253,10 +283,9 @@ 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, |
| + // Per resource settings don't support last_modified timestamps. |
| + value_map_.SetValue(pattern_pair.first, pattern_pair.second, |
| + content_type_, resource_identifier, base::Time(), |
| setting_ptr->DeepCopy()); |
| } |
| } |
| @@ -264,13 +293,12 @@ void ContentSettingsPref::ReadContentSettingsFromPref() { |
| const base::Value* value = nullptr; |
| settings_dictionary->GetWithoutPathExpansion(kSettingPath, &value); |
| - |
| if (value) { |
| + base::Time last_modified = |
| + GetTimeStamp(settings_dictionary, kLastModifiedPath); |
| 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,6 +349,7 @@ 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|). |
| @@ -353,7 +382,7 @@ void ContentSettingsPref::UpdatePref( |
| if (!found) { |
| if (value == NULL) |
| return; // Nothing to remove. Exit early. |
| - resource_dictionary = new base::DictionaryValue; |
| + resource_dictionary = new base::DictionaryValue(); |
|
raymes
2017/04/24 03:20:22
nit: () isn't needed
dullweber
2017/04/25 10:50:44
Done.
|
| settings_dictionary->Set( |
| kPerResourceIdentifierPrefName, resource_dictionary); |
| } |
| @@ -373,9 +402,14 @@ void ContentSettingsPref::UpdatePref( |
| // Update settings dictionary. |
| if (value == NULL) { |
| settings_dictionary->RemoveWithoutPathExpansion(kSettingPath, NULL); |
| + settings_dictionary->RemoveWithoutPathExpansion(kLastModifiedPath, |
| + NULL); |
|
raymes
2017/04/24 03:20:22
nullptr
dullweber
2017/04/25 10:50:44
Done, I replaced all NULLs in this file with nullp
|
| } else { |
| settings_dictionary->SetWithoutPathExpansion( |
| kSettingPath, value->DeepCopy()); |
| + settings_dictionary->SetStringWithoutPathExpansion( |
| + kLastModifiedPath, |
| + base::Int64ToString(last_modified.ToInternalValue())); |
| } |
| } |
| // Remove the settings dictionary if it is empty. |