blob: 5fe45ed8ffe90debcb6c21d81581c2cd797491d6 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "storage/browser/quota/storage_policy_observer.h"
#include <utility>
#include "base/task/post_task.h"
#include "url/origin.h"
namespace storage {
// A helper class that lives on the IO thread and registers with
// SpecialStoragePolicy. It bounces back any OnPolicyChanged messages
// to the StoragePolicyObserver on the provided `reply_task_runner`.
class StoragePolicyObserverIOThread
: public storage::SpecialStoragePolicy::Observer {
public:
StoragePolicyObserverIOThread(
scoped_refptr<base::SequencedTaskRunner> reply_task_runner,
scoped_refptr<storage::SpecialStoragePolicy> storage_policy,
base::WeakPtr<StoragePolicyObserver> observer)
: reply_task_runner_(std::move(reply_task_runner)),
storage_policy_(std::move(storage_policy)),
observer_(std::move(observer)) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
storage_policy_->AddObserver(this);
}
~StoragePolicyObserverIOThread() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
storage_policy_->RemoveObserver(this);
}
// storage::SpecialStoragePolicy::Observer implementation:
void OnPolicyChanged() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
reply_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&StoragePolicyObserver::OnPolicyChanged, observer_));
}
private:
scoped_refptr<base::SequencedTaskRunner> reply_task_runner_;
scoped_refptr<storage::SpecialStoragePolicy> storage_policy_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtr<StoragePolicyObserver> observer_;
};
StoragePolicyObserver::StoragePolicyObserver(
ApplyPolicyUpdatesCallback callback,
scoped_refptr<base::SequencedTaskRunner> io_task_runner,
scoped_refptr<storage::SpecialStoragePolicy> storage_policy)
: callback_(callback), storage_policy_(std::move(storage_policy)) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!storage_policy_)
return;
storage_policy_observer_ = base::SequenceBound<StoragePolicyObserverIOThread>(
std::move(io_task_runner), base::SequencedTaskRunnerHandle::Get(),
storage_policy_, weak_factory_.GetWeakPtr());
}
StoragePolicyObserver::~StoragePolicyObserver() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void StoragePolicyObserver::StartTrackingOrigin(const url::Origin& origin) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// If the origin exists, emplace fails, and its state is unchanged.
const GURL origin_url = GURL(origin.Serialize());
origin_state_.emplace(origin_url, OriginState());
OnPolicyChanged();
}
void StoragePolicyObserver::StartTrackingOrigins(
const std::vector<url::Origin>& origins) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (const auto& origin : origins) {
// If the origin exists, emplace fails, and its state is unchanged.
GURL origin_url = GURL(origin.Serialize());
origin_state_.emplace(std::move(origin_url), OriginState());
}
OnPolicyChanged();
}
void StoragePolicyObserver::StopTrackingOrigin(const url::Origin& origin) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const GURL origin_url = GURL(origin.Serialize());
origin_state_.erase(origin_url);
}
void StoragePolicyObserver::OnPolicyChanged() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::vector<storage::mojom::StoragePolicyUpdatePtr> policy_updates;
for (auto& entry : origin_state_) {
const GURL& origin = entry.first;
OriginState& state = entry.second;
state.should_purge_on_shutdown = ShouldPurgeOnShutdown(origin);
if (state.should_purge_on_shutdown != state.will_purge_on_shutdown) {
state.will_purge_on_shutdown = state.should_purge_on_shutdown;
policy_updates.emplace_back(storage::mojom::StoragePolicyUpdate::New(
url::Origin::Create(origin), state.should_purge_on_shutdown));
}
}
if (policy_updates.empty())
return;
callback_.Run(std::move(policy_updates));
}
bool StoragePolicyObserver::ShouldPurgeOnShutdownForTesting(
const url::Origin& origin) {
const GURL origin_url = GURL(origin.Serialize());
return ShouldPurgeOnShutdown(origin_url);
}
bool StoragePolicyObserver::ShouldPurgeOnShutdown(const GURL& origin) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!storage_policy_)
return false;
if (!storage_policy_->IsStorageSessionOnly(origin))
return false;
if (storage_policy_->IsStorageProtected(origin))
return false;
return true;
}
} // namespace storage