blob: 38969e084dbc29d13821ff9f193b97433bf9f025 [file] [log] [blame]
// Copyright 2020 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.
#ifndef CONTENT_BROWSER_QUOTA_QUOTA_CHANGE_DISPATCHER_H_
#define CONTENT_BROWSER_QUOTA_QUOTA_CHANGE_DISPATCHER_H_
#include <map>
#include <utility>
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "third_party/blink/public/mojom/quota/quota_manager_host.mojom.h"
#include "url/origin.h"
class TimeDelta;
namespace content {
// Dispatches a storage pressure event to listeners across multiple origins.
//
// This class handles dispatching the event with randomized delays,
// to avoid creating a cross-origin user identifier.
//
// There is one instance per QuotaContext instance. All methods must
// be called on the same sequence.
class CONTENT_EXPORT QuotaChangeDispatcher
: public base::RefCountedDeleteOnSequence<QuotaChangeDispatcher> {
public:
explicit QuotaChangeDispatcher(
scoped_refptr<base::SequencedTaskRunner> io_thread);
QuotaChangeDispatcher(const QuotaChangeDispatcher&) = delete;
QuotaChangeDispatcher& operator=(const QuotaChangeDispatcher&) = delete;
// Dispatch OnQuotaChange for every origin and its corresponding listeners.
void MaybeDispatchEvents();
void DispatchEventsForOrigin(const url::Origin& origin);
void AddChangeListener(
const url::Origin& origin,
mojo::PendingRemote<blink::mojom::QuotaChangeListener> mojo_listener);
void OnRemoteDisconnect(const url::Origin& origin,
mojo::RemoteSetElementId id);
private:
friend class QuotaChangeDispatcherTest;
friend class QuotaContext;
friend class RefCountedDeleteOnSequence<QuotaChangeDispatcher>;
friend class base::DeleteHelper<QuotaChangeDispatcher>;
~QuotaChangeDispatcher();
const base::TimeDelta GetQuotaChangeEventInterval();
struct DelayedOriginListener {
DelayedOriginListener();
~DelayedOriginListener();
// This delay is used to introduce noise to the event, to prevent
// bad actors from using the event to determine cross-origin
// resource size or to correlate and identify users across origins/profiles.
base::TimeDelta delay;
mojo::RemoteSet<blink::mojom::QuotaChangeListener> listeners;
};
// Stores all of the listeners associated with a unique origin
// corresponding to a randomized delay for that origin.
std::map<url::Origin, DelayedOriginListener> listeners_by_origin_;
// Keeps track of last time events were dispatched for debouncing events.
base::TimeTicks last_event_dispatched_at_;
// Cache the event interval to avoid checking command line switches
// each time the interval is checked. See kDefaultQuotaChangeIntervalSeconds
// for the default value. See switches::kQuotaChangeEventInterval for a
// command-line override.
base::TimeDelta quota_change_event_interval_;
bool is_quota_change_interval_cached_ = false;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<QuotaChangeDispatcher> weak_ptr_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_QUOTA_QUOTA_CHANGE_DISPATCHER_H_