1 // Copyright (c) 2020 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 "content/browser/indexed_db/indexed_db_control_wrapper.h"
6
7 #include "base/task/post_task.h"
8 #include "content/public/browser/browser_task_traits.h"
9 #include "content/public/browser/browser_thread.h"
10
11 namespace content {
12
13 // Observer for the SpecialStoragePolicy on the IO thread.
14 class IndexedDBControlWrapper::StoragePolicyObserver
15 : public storage::SpecialStoragePolicy::Observer {
16 public:
StoragePolicyObserver(scoped_refptr<base::SequencedTaskRunner> reply_task_runner,scoped_refptr<storage::SpecialStoragePolicy> storage_policy,base::WeakPtr<IndexedDBControlWrapper> control_wrapper)17 explicit StoragePolicyObserver(
18 scoped_refptr<base::SequencedTaskRunner> reply_task_runner,
19 scoped_refptr<storage::SpecialStoragePolicy> storage_policy,
20 base::WeakPtr<IndexedDBControlWrapper> control_wrapper)
21 : reply_task_runner_(std::move(reply_task_runner)),
22 storage_policy_(std::move(storage_policy)),
23 control_wrapper_(std::move(control_wrapper)) {
24 storage_policy_->AddObserver(this);
25 }
26
~StoragePolicyObserver()27 ~StoragePolicyObserver() override { storage_policy_->RemoveObserver(this); }
28
29 // storage::SpecialStoragePolicy::Observer implementation:
OnPolicyChanged()30 void OnPolicyChanged() override {
31 reply_task_runner_->PostTask(
32 FROM_HERE,
33 base::BindOnce(&IndexedDBControlWrapper::OnSpecialStoragePolicyChanged,
34 control_wrapper_));
35 }
36
37 private:
38 scoped_refptr<base::SequencedTaskRunner> reply_task_runner_;
39 scoped_refptr<storage::SpecialStoragePolicy> storage_policy_;
40
41 // control_wrapper_ is bound to the reply_task_runner sequence,
42 // so should not be checked other than on that sequence.
43 base::WeakPtr<IndexedDBControlWrapper> control_wrapper_;
44 };
45
IndexedDBControlWrapper(const base::FilePath & data_path,scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,base::Clock * clock,mojo::PendingRemote<storage::mojom::BlobStorageContext> blob_storage_context,mojo::PendingRemote<storage::mojom::NativeFileSystemContext> native_file_system_context,scoped_refptr<base::SequencedTaskRunner> io_task_runner,scoped_refptr<base::SequencedTaskRunner> custom_task_runner)46 IndexedDBControlWrapper::IndexedDBControlWrapper(
47 const base::FilePath& data_path,
48 scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
49 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
50 base::Clock* clock,
51 mojo::PendingRemote<storage::mojom::BlobStorageContext>
52 blob_storage_context,
53 mojo::PendingRemote<storage::mojom::NativeFileSystemContext>
54 native_file_system_context,
55 scoped_refptr<base::SequencedTaskRunner> io_task_runner,
56 scoped_refptr<base::SequencedTaskRunner> custom_task_runner)
57 : special_storage_policy_(std::move(special_storage_policy)) {
58 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
59 context_ = base::MakeRefCounted<IndexedDBContextImpl>(
60 data_path, std::move(quota_manager_proxy), clock,
61 std::move(blob_storage_context), std::move(native_file_system_context),
62 io_task_runner, std::move(custom_task_runner));
63
64 if (special_storage_policy_) {
65 storage_policy_observer_ = base::SequenceBound<StoragePolicyObserver>(
66 io_task_runner, base::SequencedTaskRunnerHandle::Get(),
67 special_storage_policy_, weak_factory_.GetWeakPtr());
68 }
69 }
70
~IndexedDBControlWrapper()71 IndexedDBControlWrapper::~IndexedDBControlWrapper() {
72 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
73 }
74
BindIndexedDB(const url::Origin & origin,mojo::PendingReceiver<blink::mojom::IDBFactory> receiver)75 void IndexedDBControlWrapper::BindIndexedDB(
76 const url::Origin& origin,
77 mojo::PendingReceiver<blink::mojom::IDBFactory> receiver) {
78 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
79 BindRemoteIfNeeded();
80 TrackOriginPolicyState(origin);
81 indexed_db_control_->BindIndexedDB(origin, std::move(receiver));
82 }
83
GetUsage(GetUsageCallback usage_callback)84 void IndexedDBControlWrapper::GetUsage(GetUsageCallback usage_callback) {
85 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
86 BindRemoteIfNeeded();
87 indexed_db_control_->GetUsage(std::move(usage_callback));
88 }
89
DeleteForOrigin(const url::Origin & origin,DeleteForOriginCallback callback)90 void IndexedDBControlWrapper::DeleteForOrigin(
91 const url::Origin& origin,
92 DeleteForOriginCallback callback) {
93 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
94 BindRemoteIfNeeded();
95 indexed_db_control_->DeleteForOrigin(origin, std::move(callback));
96 }
97
ForceClose(const url::Origin & origin,storage::mojom::ForceCloseReason reason,base::OnceClosure callback)98 void IndexedDBControlWrapper::ForceClose(
99 const url::Origin& origin,
100 storage::mojom::ForceCloseReason reason,
101 base::OnceClosure callback) {
102 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
103 BindRemoteIfNeeded();
104 indexed_db_control_->ForceClose(origin, reason, std::move(callback));
105 }
106
GetConnectionCount(const url::Origin & origin,GetConnectionCountCallback callback)107 void IndexedDBControlWrapper::GetConnectionCount(
108 const url::Origin& origin,
109 GetConnectionCountCallback callback) {
110 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
111 BindRemoteIfNeeded();
112 indexed_db_control_->GetConnectionCount(origin, std::move(callback));
113 }
114
DownloadOriginData(const url::Origin & origin,DownloadOriginDataCallback callback)115 void IndexedDBControlWrapper::DownloadOriginData(
116 const url::Origin& origin,
117 DownloadOriginDataCallback callback) {
118 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
119 BindRemoteIfNeeded();
120 indexed_db_control_->DownloadOriginData(origin, std::move(callback));
121 }
122
GetAllOriginsDetails(GetAllOriginsDetailsCallback callback)123 void IndexedDBControlWrapper::GetAllOriginsDetails(
124 GetAllOriginsDetailsCallback callback) {
125 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
126 BindRemoteIfNeeded();
127 indexed_db_control_->GetAllOriginsDetails(std::move(callback));
128 }
129
SetForceKeepSessionState()130 void IndexedDBControlWrapper::SetForceKeepSessionState() {
131 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
132 BindRemoteIfNeeded();
133 indexed_db_control_->SetForceKeepSessionState();
134 }
135
ApplyPolicyUpdates(std::vector<storage::mojom::IndexedDBStoragePolicyUpdatePtr> policy_updates)136 void IndexedDBControlWrapper::ApplyPolicyUpdates(
137 std::vector<storage::mojom::IndexedDBStoragePolicyUpdatePtr>
138 policy_updates) {
139 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
140 BindRemoteIfNeeded();
141 indexed_db_control_->ApplyPolicyUpdates(std::move(policy_updates));
142 }
143
BindTestInterface(mojo::PendingReceiver<storage::mojom::IndexedDBControlTest> receiver)144 void IndexedDBControlWrapper::BindTestInterface(
145 mojo::PendingReceiver<storage::mojom::IndexedDBControlTest> receiver) {
146 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
147 BindRemoteIfNeeded();
148 indexed_db_control_->BindTestInterface(std::move(receiver));
149 }
150
AddObserver(mojo::PendingRemote<storage::mojom::IndexedDBObserver> observer)151 void IndexedDBControlWrapper::AddObserver(
152 mojo::PendingRemote<storage::mojom::IndexedDBObserver> observer) {
153 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
154 BindRemoteIfNeeded();
155 indexed_db_control_->AddObserver(std::move(observer));
156 }
157
OnSpecialStoragePolicyChanged()158 void IndexedDBControlWrapper::OnSpecialStoragePolicyChanged() {
159 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
160 BindRemoteIfNeeded();
161
162 std::vector<storage::mojom::IndexedDBStoragePolicyUpdatePtr> policy_updates;
163 for (auto& entry : origin_state_) {
164 const GURL& origin = entry.first;
165 OriginState& state = entry.second;
166 state.should_purge_on_shutdown = ShouldPurgeOnShutdown(origin);
167
168 if (state.should_purge_on_shutdown != state.will_purge_on_shutdown) {
169 state.will_purge_on_shutdown = state.should_purge_on_shutdown;
170 policy_updates.push_back(
171 storage::mojom::IndexedDBStoragePolicyUpdate::New(
172 url::Origin::Create(origin), state.should_purge_on_shutdown));
173 }
174 }
175 if (!policy_updates.empty())
176 ApplyPolicyUpdates(std::move(policy_updates));
177 }
178
TrackOriginPolicyState(const url::Origin & origin)179 void IndexedDBControlWrapper::TrackOriginPolicyState(
180 const url::Origin& origin) {
181 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
182 const GURL origin_url = GURL(origin.Serialize());
183 auto it = origin_state_.find(origin_url);
184 if (it == origin_state_.end())
185 origin_state_[origin_url] = {};
186 OnSpecialStoragePolicyChanged();
187 }
188
ShouldPurgeOnShutdown(const GURL & origin)189 bool IndexedDBControlWrapper::ShouldPurgeOnShutdown(const GURL& origin) {
190 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
191 if (!special_storage_policy_)
192 return false;
193 if (!special_storage_policy_->IsStorageSessionOnly(origin))
194 return false;
195 if (special_storage_policy_->IsStorageProtected(origin))
196 return false;
197 return true;
198 }
199
BindRemoteIfNeeded()200 void IndexedDBControlWrapper::BindRemoteIfNeeded() {
201 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
202 DCHECK(
203 !(indexed_db_control_.is_bound() && !indexed_db_control_.is_connected()))
204 << "Rebinding is not supported yet.";
205
206 if (indexed_db_control_.is_bound())
207 return;
208 IndexedDBContextImpl* idb_context = GetIndexedDBContextInternal();
209 idb_context->IDBTaskRunner()->PostTask(
210 FROM_HERE,
211 base::BindOnce(&IndexedDBContextImpl::Bind,
212 base::WrapRefCounted(idb_context),
213 indexed_db_control_.BindNewPipeAndPassReceiver()));
214 }
215
216 } // namespace content
217