1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/content_settings/core/browser/content_settings_ephemeral_provider.h"
6 
7 #include "base/stl_util.h"
8 #include "base/time/default_clock.h"
9 #include "components/content_settings/core/browser/content_settings_registry.h"
10 #include "components/content_settings/core/browser/website_settings_info.h"
11 #include "components/content_settings/core/browser/website_settings_registry.h"
12 #include "components/content_settings/core/common/content_settings.h"
13 #include "components/content_settings/core/common/content_settings_pattern.h"
14 
15 namespace content_settings {
16 
17 // ////////////////////////////////////////////////////////////////////////////
18 // EphemeralProvider:
19 //
20 
EphemeralProvider(bool store_last_modified)21 EphemeralProvider::EphemeralProvider(bool store_last_modified)
22     : store_last_modified_(store_last_modified),
23       clock_(base::DefaultClock::GetInstance()) {
24   ContentSettingsRegistry* content_settings =
25       ContentSettingsRegistry::GetInstance();
26   WebsiteSettingsRegistry* website_settings =
27       WebsiteSettingsRegistry::GetInstance();
28   for (const WebsiteSettingsInfo* info : *website_settings) {
29     const ContentSettingsInfo* content_type_info =
30         content_settings->Get(info->type());
31     // If this is an ephemeral content setting, handle it in this class.
32     if (content_type_info && content_type_info->storage_behavior() ==
33                                  ContentSettingsInfo::EPHEMERAL) {
34       supported_types_.insert(info->type());
35     }
36   }
37 }
38 
~EphemeralProvider()39 EphemeralProvider::~EphemeralProvider() {}
40 
GetRuleIterator(ContentSettingsType content_type,const ResourceIdentifier & resource_identifier,bool incognito) const41 std::unique_ptr<RuleIterator> EphemeralProvider::GetRuleIterator(
42     ContentSettingsType content_type,
43     const ResourceIdentifier& resource_identifier,
44     bool incognito) const {
45   return content_settings_rules_.GetRuleIterator(content_type,
46                                                  resource_identifier, nullptr);
47 }
48 
SetWebsiteSetting(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const ResourceIdentifier & resource_identifier,std::unique_ptr<base::Value> && in_value)49 bool EphemeralProvider::SetWebsiteSetting(
50     const ContentSettingsPattern& primary_pattern,
51     const ContentSettingsPattern& secondary_pattern,
52     ContentSettingsType content_type,
53     const ResourceIdentifier& resource_identifier,
54     std::unique_ptr<base::Value>&& in_value) {
55   DCHECK(CalledOnValidThread());
56 
57   if (!base::Contains(supported_types_, content_type))
58     return false;
59 
60   // Default settings are set using a wildcard pattern for both
61   // |primary_pattern| and |secondary_pattern|. Don't store default settings in
62   // the EphemeralProvider. The EphemeralProvider handles settings for
63   // specific sites/origins defined by the |primary_pattern| and the
64   // |secondary_pattern|. Default settings are handled by the DefaultProvider.
65   if (primary_pattern == ContentSettingsPattern::Wildcard() &&
66       secondary_pattern == ContentSettingsPattern::Wildcard() &&
67       resource_identifier.empty()) {
68     return false;
69   }
70 
71   std::unique_ptr<base::Value> value(std::move(in_value));
72   if (value) {
73     content_settings_rules_.SetValue(
74         primary_pattern, secondary_pattern, content_type, resource_identifier,
75         store_last_modified_ ? clock_->Now() : base::Time(), std::move(*value));
76     NotifyObservers(primary_pattern, secondary_pattern, content_type,
77                     resource_identifier);
78   } else {
79     // If the value exists, delete it.
80     if (content_settings_rules_.GetLastModified(
81             primary_pattern, secondary_pattern, content_type,
82             resource_identifier) != base::Time()) {
83       content_settings_rules_.DeleteValue(primary_pattern, secondary_pattern,
84                                           content_type, resource_identifier);
85       NotifyObservers(primary_pattern, secondary_pattern, content_type,
86                       resource_identifier);
87     }
88   }
89   return true;
90 }
91 
GetWebsiteSettingLastModified(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const ResourceIdentifier & resource_identifier)92 base::Time EphemeralProvider::GetWebsiteSettingLastModified(
93     const ContentSettingsPattern& primary_pattern,
94     const ContentSettingsPattern& secondary_pattern,
95     ContentSettingsType content_type,
96     const ResourceIdentifier& resource_identifier) {
97   DCHECK(CalledOnValidThread());
98 
99   return content_settings_rules_.GetLastModified(
100       primary_pattern, secondary_pattern, content_type, resource_identifier);
101 }
102 
ClearAllContentSettingsRules(ContentSettingsType content_type)103 void EphemeralProvider::ClearAllContentSettingsRules(
104     ContentSettingsType content_type) {
105   DCHECK(CalledOnValidThread());
106 
107   // Get all resource identifiers for this |content_type|.
108   std::set<ResourceIdentifier> resource_identifiers;
109   for (OriginIdentifierValueMap::EntryMap::const_iterator entry =
110            content_settings_rules_.begin();
111        entry != content_settings_rules_.end(); entry++) {
112     if (entry->first.content_type == content_type)
113       resource_identifiers.insert(entry->first.resource_identifier);
114   }
115 
116   for (const ResourceIdentifier& resource_identifier : resource_identifiers)
117     content_settings_rules_.DeleteValues(content_type, resource_identifier);
118 
119   if (!resource_identifiers.empty()) {
120     NotifyObservers(ContentSettingsPattern(), ContentSettingsPattern(),
121                     content_type, ResourceIdentifier());
122   }
123 }
124 
ShutdownOnUIThread()125 void EphemeralProvider::ShutdownOnUIThread() {
126   DCHECK(CalledOnValidThread());
127   RemoveAllObservers();
128 }
129 
SetClockForTesting(base::Clock * clock)130 void EphemeralProvider::SetClockForTesting(base::Clock* clock) {
131   clock_ = clock;
132 }
133 
134 }  // namespace content_settings
135