blob: 672878be4a386e54a861457fcd075be8aac9cec0 [file] [log] [blame]
Jay Harris4e710722019-11-26 05:40:481// Copyright 2019 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
Song Fangzhencda4af62021-09-09 05:24:025#include "chrome/browser/web_applications/web_app_prefs_utils.h"
Jay Harris4e710722019-11-26 05:40:486
Phillis Tang1565f1f2020-11-12 03:07:517#include <memory>
8
Albert J. Wongf60c8d22021-07-27 07:25:269#include "base/json/values_util.h"
Phillis Tang4379e292020-11-18 00:12:3310#include "base/numerics/safe_conversions.h"
David Sandersc89b9b42022-02-19 16:34:4111#include "base/strings/string_piece.h"
Phillis Tang1565f1f2020-11-12 03:07:5112#include "base/time/time.h"
Jay Harris4e710722019-11-26 05:40:4813#include "base/values.h"
Song Fangzhencda4af62021-09-09 05:24:0214#include "chrome/browser/web_applications/web_app_constants.h"
Jay Harris4e710722019-11-26 05:40:4815#include "chrome/common/pref_names.h"
16#include "components/pref_registry/pref_registry_syncable.h"
17#include "components/prefs/pref_service.h"
Nancy Wang071f6e22021-09-27 06:45:3418#include "components/webapps/browser/installable/installable_metrics.h"
Jay Harris4e710722019-11-26 05:40:4819#include "content/public/browser/browser_thread.h"
20#include "services/preferences/public/cpp/dictionary_value_update.h"
Phillis Tang4379e292020-11-18 00:12:3321#include "services/preferences/public/cpp/scoped_pref_update.h"
Jay Harris4e710722019-11-26 05:40:4822
23namespace web_app {
24
25namespace {
26
Evan Stadeda2a3172022-02-04 02:01:3527const char kLatestWebAppInstallSource[] = "latest_web_app_install_source";
28
Roland Bock6d4b6c62022-08-02 18:50:0029const base::Value::Dict* GetWebAppDictionary(const PrefService* pref_service,
30 const AppId& app_id) {
Jay Harris4e710722019-11-26 05:40:4831 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
Roland Bock6d4b6c62022-08-02 18:50:0032 const base::Value::Dict& web_apps_prefs =
33 pref_service->GetValueDict(prefs::kWebAppsPreferences);
Jay Harris4e710722019-11-26 05:40:4834
Roland Bock6d4b6c62022-08-02 18:50:0035 return web_apps_prefs.FindDict(app_id);
Jay Harris4e710722019-11-26 05:40:4836}
37
38std::unique_ptr<prefs::DictionaryValueUpdate> UpdateWebAppDictionary(
39 std::unique_ptr<prefs::DictionaryValueUpdate> web_apps_prefs_update,
40 const AppId& app_id) {
41 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
42 std::unique_ptr<prefs::DictionaryValueUpdate> web_app_prefs_update;
43 if (!web_apps_prefs_update->GetDictionaryWithoutPathExpansion(
44 app_id, &web_app_prefs_update)) {
45 web_app_prefs_update =
46 web_apps_prefs_update->SetDictionaryWithoutPathExpansion(
47 app_id, std::make_unique<base::DictionaryValue>());
48 }
49 return web_app_prefs_update;
50}
51
Phillis Tang4379e292020-11-18 00:12:3352// Returns whether the time occurred within X days.
Anton Bikineev46bbb972021-05-15 17:53:5353bool TimeOccurredWithinDays(absl::optional<base::Time> time, int days) {
Phillis Tang4379e292020-11-18 00:12:3354 return time && (base::Time::Now() - time.value()).InDays() < days;
55}
56
Evan Stadeda2a3172022-02-04 02:01:3557// Removes all the empty app ID dictionaries from the `web_app_ids` dictionary.
58// That is, this dictionary:
59//
60// "web_app_ids": {
61// "<app_id_1>": {},
62// "<app_id_2>": { "foo": true }
63// }
64//
65// will become this dictionary:
66//
67// "web_app_ids": {
68// "<app_id_2>": { "foo": true }
69// }
70void RemoveEmptyWebAppPrefs(PrefService* pref_service) {
71 prefs::ScopedDictionaryPrefUpdate update(pref_service,
72 prefs::kWebAppsPreferences);
73
74 std::vector<AppId> apps_to_remove;
Anders Hartvoll Ruud1951f1f12022-07-28 10:34:0275 for (const auto [app_id, dict] : *update.Get()->AsDict()) {
Evan Stadeda2a3172022-02-04 02:01:3576 if (dict.is_dict() && dict.DictEmpty())
77 apps_to_remove.push_back(app_id);
78 }
79
80 for (const AppId& app_id : apps_to_remove)
81 update.Get()->Remove(app_id);
82}
83
Jay Harris4e710722019-11-26 05:40:4884} // namespace
85
86// The stored preferences look like:
Jay Harris4e710722019-11-26 05:40:4887// "web_app_ids": {
88// "<app_id_1>": {
89// "was_external_app_uninstalled_by_user": true,
Jay Harris46b47a6c2020-01-28 04:17:2690// A double representing the number of seconds since epoch, in local time.
91// Convert from/to using base::Time::FromDoubleT() and
92// base::Time::ToDoubleT().
Phillis Tang4379e292020-11-18 00:12:3393// "IPH_num_of_consecutive_ignore": 2,
94// A string-flavored base::value representing the int64_t number of
Albert J. Wongf60c8d22021-07-27 07:25:2695// microseconds since the Windows epoch, using base::TimeToValue().
Phillis Tang4379e292020-11-18 00:12:3396// "IPH_last_ignore_time": "13249617864945580",
Jay Harris4e710722019-11-26 05:40:4897// },
Phillis Tang4379e292020-11-18 00:12:3398// },
99// "app_agnostic_iph_state": {
100// "IPH_num_of_consecutive_ignore": 3,
101// A string-flavored base::Value representing int64_t number of microseconds
Albert J. Wongf60c8d22021-07-27 07:25:26102// since the Windows epoch, using base::TimeToValue().
Phillis Tang4379e292020-11-18 00:12:33103// "IPH_last_ignore_time": "13249617864945500",
104// },
Robbie McElrathebc64b72021-06-04 01:39:48105// isolation_state is managed by isolation_prefs_utils
106// "isolation_state": {
107// "<origin>": {
108// "storage_isolation_key": "abc123",
109// },
Evan Stadeda2a3172022-02-04 02:01:35110// }
Jay Harris4e710722019-11-26 05:40:48111//
Jay Harris4e710722019-11-26 05:40:48112
Phillis Tang1565f1f2020-11-12 03:07:51113const char kIphIgnoreCount[] = "IPH_num_of_consecutive_ignore";
114
115const char kIphLastIgnoreTime[] = "IPH_last_ignore_time";
116
Jay Harris4e710722019-11-26 05:40:48117void WebAppPrefsUtilsRegisterProfilePrefs(
118 user_prefs::PrefRegistrySyncable* registry) {
119 registry->RegisterDictionaryPref(::prefs::kWebAppsPreferences);
Phillis Tang4379e292020-11-18 00:12:33120 registry->RegisterDictionaryPref(::prefs::kWebAppsAppAgnosticIphState);
Jay Harris4e710722019-11-26 05:40:48121}
122
123bool GetBoolWebAppPref(const PrefService* pref_service,
124 const AppId& app_id,
125 base::StringPiece path) {
Roland Bock6d4b6c62022-08-02 18:50:00126 if (const base::Value::Dict* web_app_prefs =
Carlos Caballerof5e79fb2021-11-24 04:08:32127 GetWebAppDictionary(pref_service, app_id)) {
Roland Bock6d4b6c62022-08-02 18:50:00128 return web_app_prefs->FindBoolByDottedPath(path).value_or(false);
Carlos Caballerof5e79fb2021-11-24 04:08:32129 }
130 return false;
Jay Harris4e710722019-11-26 05:40:48131}
132
133void UpdateBoolWebAppPref(PrefService* pref_service,
134 const AppId& app_id,
135 base::StringPiece path,
136 bool value) {
137 prefs::ScopedDictionaryPrefUpdate update(pref_service,
138 prefs::kWebAppsPreferences);
139
140 std::unique_ptr<prefs::DictionaryValueUpdate> web_app_prefs =
141 UpdateWebAppDictionary(update.Get(), app_id);
142 web_app_prefs->SetBoolean(path, value);
143}
144
Anton Bikineev46bbb972021-05-15 17:53:53145absl::optional<int> GetIntWebAppPref(const PrefService* pref_service,
Glen Robertson24f339c2020-04-08 04:50:40