Fix emulator build error
[platform/framework/web/chromium-efl.git] / components / permissions / permission_actions_history.cc
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 #include "components/permissions/permission_actions_history.h"
5
6 #include "base/containers/adapters.h"
7 #include "base/json/values_util.h"
8 #include "base/ranges/algorithm.h"
9 #include "base/strings/string_piece.h"
10 #include "base/values.h"
11 #include "build/build_config.h"
12 #include "components/keyed_service/content/browser_context_dependency_manager.h"
13 #include "components/permissions/permission_util.h"
14 #include "components/permissions/pref_names.h"
15 #include "components/permissions/request_type.h"
16 #include "components/prefs/pref_service.h"
17 #include "components/prefs/scoped_user_pref_update.h"
18 #include "third_party/abseil-cpp/absl/types/optional.h"
19
20 #include <vector>
21
22 namespace permissions {
23 namespace {
24
25 // Inner structure of |prefs::kPermissionActions| containing a history of past
26 // permission actions. It is a dictionary of JSON lists keyed on the result of
27 // PermissionUtil::GetPermissionString (lower-cased for backwards compatibility)
28 // and has the following format:
29 //
30 //   "profile.content_settings.permission_actions": {
31 //      "notifications": [
32 //       { "time": "1333333333337", "action": 1, "prompt_disposition": 2 },
33 //       { "time": "1567957177000", "action": 3, "prompt_disposition": 4 },
34 //     ],
35 //     "geolocation": [...],
36 //     ...
37 //   }
38 // The "prompt_disposition" key was added in M96. Any older entry will be
39 // missing that key. The value is backed by the PermissionPromptDisposition
40 // enum.
41 constexpr char kPermissionActionEntryActionKey[] = "action";
42 constexpr char kPermissionActionEntryTimestampKey[] = "time";
43 constexpr char kPermissionActionEntryPromptDispositionKey[] =
44     "prompt_disposition";
45
46 // Entries in permission actions expire after they become this old.
47 constexpr base::TimeDelta kPermissionActionMaxAge = base::Days(90);
48
49 }  // namespace
50
51 std::vector<PermissionActionsHistory::Entry>
52 PermissionActionsHistory::GetHistory(const base::Time& begin,
53                                      EntryFilter entry_filter) {
54   const base::Value::Dict& dictionary =
55       pref_service_->GetDict(prefs::kPermissionActions);
56
57   std::vector<PermissionActionsHistory::Entry> matching_actions;
58   for (auto permission_entry : dictionary) {
59     const auto permission_actions =
60         GetHistoryInternal(begin, permission_entry.first, entry_filter);
61
62     matching_actions.insert(matching_actions.end(), permission_actions.begin(),
63                             permission_actions.end());
64   }
65
66   base::ranges::sort(
67       matching_actions, {},
68       [](const PermissionActionsHistory::Entry& entry) { return entry.time; });
69   return matching_actions;
70 }
71
72 std::vector<PermissionActionsHistory::Entry>
73 PermissionActionsHistory::GetHistory(const base::Time& begin,
74                                      RequestType type,
75                                      EntryFilter entry_filter) {
76   return GetHistoryInternal(begin, PermissionKeyForRequestType(type),
77                             entry_filter);
78 }
79
80 void PermissionActionsHistory::RecordAction(
81     PermissionAction action,
82     RequestType type,
83     PermissionPromptDisposition prompt_disposition) {
84   ScopedDictPrefUpdate update(pref_service_, prefs::kPermissionActions);
85   base::Value::Dict& update_dict = update.Get();
86
87   const base::StringPiece permission_path(PermissionKeyForRequestType(type));
88
89   if (!update_dict.FindListByDottedPath(permission_path)) {
90     update_dict.SetByDottedPath(permission_path, base::Value::List());
91   }
92
93   base::Value::List* permission_actions =
94       update_dict.FindListByDottedPath(permission_path);
95   CHECK(permission_actions);
96
97   // Discard permission actions older than |kPermissionActionMaxAge|.
98   const base::Time cutoff = base::Time::Now() - kPermissionActionMaxAge;
99   permission_actions->EraseIf([cutoff](const base::Value& entry) {
100     const absl::optional<base::Time> timestamp = base::ValueToTime(
101         entry.GetDict().Find(kPermissionActionEntryTimestampKey));
102     return !timestamp || *timestamp < cutoff;
103   });
104
105   // Record the new permission action.
106   base::Value::Dict new_action_attributes;
107   new_action_attributes.Set(kPermissionActionEntryTimestampKey,
108                             base::TimeToValue(base::Time::Now()));
109   new_action_attributes.Set(kPermissionActionEntryActionKey,
110                             static_cast<int>(action));
111   new_action_attributes.Set(kPermissionActionEntryPromptDispositionKey,
112                             static_cast<int>(prompt_disposition));
113   permission_actions->Append(std::move(new_action_attributes));
114 }
115
116 void PermissionActionsHistory::ClearHistory(const base::Time& delete_begin,
117                                             const base::Time& delete_end) {
118   DCHECK(!delete_end.is_null());
119   if (delete_begin.is_null() && delete_end.is_max()) {
120     pref_service_->ClearPref(prefs::kPermissionActions);
121     return;
122   }
123
124   ScopedDictPrefUpdate update(pref_service_, prefs::kPermissionActions);
125
126   for (auto permission_entry : update.Get()) {
127     permission_entry.second.GetList().EraseIf([delete_begin,
128                                                delete_end](const auto& entry) {
129       const absl::optional<base::Time> timestamp = base::ValueToTime(
130           entry.GetDict().Find(kPermissionActionEntryTimestampKey));
131       return (!timestamp ||
132               (*timestamp >= delete_begin && *timestamp < delete_end));
133     });
134   }
135 }
136
137 PermissionActionsHistory::PermissionActionsHistory(PrefService* pref_service)
138     : pref_service_(pref_service) {}
139
140 std::vector<PermissionActionsHistory::Entry>
141 PermissionActionsHistory::GetHistoryInternal(const base::Time& begin,
142                                              const std::string& key,
143                                              EntryFilter entry_filter) {
144   const base::Value::List* permission_actions =
145       pref_service_->GetDict(prefs::kPermissionActions).FindList(key);
146
147   if (!permission_actions)
148     return {};
149
150   std::vector<Entry> matching_actions;
151
152   for (const auto& entry : *permission_actions) {
153     const base::Value::Dict& entry_dict = entry.GetDict();
154     const absl::optional<base::Time> timestamp =
155         base::ValueToTime(entry_dict.Find(kPermissionActionEntryTimestampKey));
156
157     if (timestamp < begin)
158       continue;
159
160     if (entry_filter != EntryFilter::WANT_ALL_PROMPTS) {
161       // If we want either the Loud or Quiet UI actions but don't have this
162       // info due to legacy reasons we ignore the entry.
163       const absl::optional<int> prompt_disposition_int =
164           entry_dict.FindInt(kPermissionActionEntryPromptDispositionKey);
165       if (!prompt_disposition_int)
166         continue;
167
168       const PermissionPromptDisposition prompt_disposition =
169           static_cast<PermissionPromptDisposition>(*prompt_disposition_int);
170
171       if (entry_filter == EntryFilter::WANT_LOUD_PROMPTS_ONLY &&
172           !PermissionUmaUtil::IsPromptDispositionLoud(prompt_disposition)) {
173         continue;
174       }
175
176       if (entry_filter == EntryFilter::WANT_QUIET_PROMPTS_ONLY &&
177           !PermissionUmaUtil::IsPromptDispositionQuiet(prompt_disposition)) {
178         continue;
179       }
180     }
181     const PermissionAction past_action = static_cast<PermissionAction>(
182         *(entry_dict.FindInt(kPermissionActionEntryActionKey)));
183     matching_actions.emplace_back(
184         PermissionActionsHistory::Entry{past_action, timestamp.value()});
185   }
186   return matching_actions;
187 }
188
189 PrefService* PermissionActionsHistory::GetPrefServiceForTesting() {
190   return pref_service_;
191 }
192
193 // static
194 void PermissionActionsHistory::FillInActionCounts(
195     PredictionRequestFeatures::ActionCounts* counts,
196     const std::vector<PermissionActionsHistory::Entry>& actions) {
197   for (const auto& entry : actions) {
198     switch (entry.action) {
199       case PermissionAction::DENIED:
200         counts->denies++;
201         break;
202       case PermissionAction::GRANTED:
203       case PermissionAction::GRANTED_ONCE:
204         counts->grants++;
205         break;
206       case PermissionAction::DISMISSED:
207         counts->dismissals++;
208         break;
209       case PermissionAction::IGNORED:
210         counts->ignores++;
211         break;
212       default:
213         // Anything else is ignored.
214         break;
215     }
216   }
217 }
218
219 // static
220 void PermissionActionsHistory::RegisterProfilePrefs(
221     user_prefs::PrefRegistrySyncable* registry) {
222   registry->RegisterDictionaryPref(prefs::kPermissionActions,
223                                    PrefRegistry::LOSSY_PREF);
224 }
225
226 }  // namespace permissions