1 // Copyright 2023 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.
5 #include "components/media_device_salt/media_device_salt_service.h"
9 #include "base/containers/cxx20_erase_vector.h"
10 #include "base/feature_list.h"
11 #include "base/functional/bind.h"
12 #include "base/system/system_monitor.h"
13 #include "base/task/sequenced_task_runner.h"
14 #include "base/task/task_traits.h"
15 #include "base/task/thread_pool.h"
16 #include "base/threading/sequence_bound.h"
17 #include "base/time/time.h"
18 #include "base/unguessable_token.h"
19 #include "components/media_device_salt/media_device_id_salt.h"
20 #include "components/media_device_salt/media_device_salt_database.h"
21 #include "third_party/blink/public/common/storage_key/storage_key.h"
23 namespace media_device_salt {
25 BASE_FEATURE(kMediaDeviceIdPartitioning,
26 "MediaDeviceIdPartitioning",
27 base::FEATURE_ENABLED_BY_DEFAULT);
28 BASE_FEATURE(kMediaDeviceIdRandomSaltsPerStorageKey,
29 "MediaDeviceIdRandomSaltsPerStorageKey",
30 base::FEATURE_ENABLED_BY_DEFAULT);
34 scoped_refptr<base::SequencedTaskRunner> CreateDatabaseTaskRunner() {
35 // We use a SequencedTaskRunner so that there is a global ordering to a
36 // storage key's directory operations.
37 return base::ThreadPool::CreateSequencedTaskRunner({
38 base::MayBlock(), // For File I/O
39 base::TaskPriority::USER_VISIBLE,
40 base::TaskShutdownBehavior::BLOCK_SHUTDOWN, // To allow clean shutdown
46 MediaDeviceSaltService::MediaDeviceSaltService(PrefService* pref_service,
47 const base::FilePath& path)
48 : fallback_salt_(CreateRandomSalt()),
49 fallback_salt_creation_time_(base::Time::Now()),
50 media_device_id_salt_(
51 base::MakeRefCounted<MediaDeviceIDSalt>(pref_service)),
52 pref_service_(pref_service),
53 db_(base::FeatureList::IsEnabled(kMediaDeviceIdPartitioning)
54 ? base::SequenceBound<MediaDeviceSaltDatabase>(
55 CreateDatabaseTaskRunner(),
57 : base::SequenceBound<MediaDeviceSaltDatabase>()) {}
59 MediaDeviceSaltService::~MediaDeviceSaltService() = default;
61 void MediaDeviceSaltService::GetSalt(
62 const blink::StorageKey& storage_key,
63 base::OnceCallback<void(const std::string&)> callback) {
64 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
65 if (!base::FeatureList::IsEnabled(kMediaDeviceIdPartitioning)) {
66 std::move(callback).Run(GetGlobalSalt());
70 if (storage_key.origin().opaque()) {
71 std::move(callback).Run(fallback_salt_);
75 absl::optional<std::string> candidate_salt;
76 if (!base::FeatureList::IsEnabled(kMediaDeviceIdRandomSaltsPerStorageKey)) {
77 candidate_salt = GetGlobalSalt();
80 db_.AsyncCall(&MediaDeviceSaltDatabase::GetOrInsertSalt)
81 .WithArgs(storage_key, candidate_salt)
82 .Then(base::BindOnce(&MediaDeviceSaltService::FinalizeGetSalt,
83 weak_factory_.GetWeakPtr(), std::move(callback)));
86 void MediaDeviceSaltService::FinalizeGetSalt(
87 base::OnceCallback<void(const std::string&)> callback,
88 absl::optional<std::string> salt) {
89 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
90 std::move(callback).Run(salt.has_value() ? *salt : fallback_salt_);
93 void MediaDeviceSaltService::DeleteSalts(
94 base::Time delete_begin,
95 base::Time delete_end,
96 content::StoragePartition::StorageKeyMatcherFunction matcher,
97 base::OnceClosure done_closure) {
98 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
100 if (!base::FeatureList::IsEnabled(kMediaDeviceIdPartitioning)) {
101 std::move(done_closure).Run();
105 if (!base::FeatureList::IsEnabled(kMediaDeviceIdRandomSaltsPerStorageKey) ||
106 !base::FeatureList::IsEnabled(kMediaDeviceIdPartitioning)) {
109 if (!base::FeatureList::IsEnabled(kMediaDeviceIdPartitioning)) {
110 FinalizeDeleteSalts(std::move(done_closure));
114 // Reset the fallback key if the deletion period includes its creation time.
115 if (delete_begin <= fallback_salt_creation_time_ &&
116 fallback_salt_creation_time_ <= delete_end) {
117 fallback_salt_ = CreateRandomSalt();
118 fallback_salt_creation_time_ = base::Time::Now();
122 db_.AsyncCall(&MediaDeviceSaltDatabase::DeleteEntries)
123 .WithArgs(delete_begin, delete_end, std::move(matcher))
124 .Then(base::BindOnce(&MediaDeviceSaltService::FinalizeDeleteSalts,
125 weak_factory_.GetWeakPtr(),
126 std::move(done_closure)));
129 void MediaDeviceSaltService::FinalizeDeleteSalts(
130 base::OnceClosure done_closure) {
131 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
132 // Propagate device change notifications, for anything currently using devices
133 // which will now have new IDs.
134 if (base::SystemMonitor* monitor = base::SystemMonitor::Get()) {
135 monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
136 monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO);
138 std::move(done_closure).Run();
141 void MediaDeviceSaltService::DeleteSalt(const blink::StorageKey& storage_key,
142 base::OnceClosure done_closure) {
143 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
144 if (!base::FeatureList::IsEnabled(kMediaDeviceIdPartitioning)) {
145 std::move(done_closure).Run();
148 db_.AsyncCall(&MediaDeviceSaltDatabase::DeleteEntry)
149 .WithArgs(storage_key)
150 .Then(base::BindOnce(&MediaDeviceSaltService::FinalizeDeleteSalts,
151 weak_factory_.GetWeakPtr(),
152 std::move(done_closure)));
155 void MediaDeviceSaltService::GetAllStorageKeys(
156 base::OnceCallback<void(std::vector<blink::StorageKey>)> callback) {
157 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
158 if (!base::FeatureList::IsEnabled(kMediaDeviceIdPartitioning)) {
159 std::move(callback).Run({});
162 db_.AsyncCall(&MediaDeviceSaltDatabase::GetAllStorageKeys)
163 .Then(base::BindOnce(&MediaDeviceSaltService::FinalizeGetAllStorageKeys,
164 weak_factory_.GetWeakPtr(), std::move(callback)));
167 void MediaDeviceSaltService::FinalizeGetAllStorageKeys(
168 base::OnceCallback<void(std::vector<blink::StorageKey>)> callback,
169 std::vector<blink::StorageKey> storage_keys) {
170 std::move(callback).Run(std::move(storage_keys));
173 std::string MediaDeviceSaltService::GetGlobalSalt() {
174 return media_device_id_salt_->GetSalt();
177 void MediaDeviceSaltService::ResetGlobalSalt() {
178 MediaDeviceIDSalt::Reset(pref_service_);
181 } // namespace media_device_salt