summaryrefslogtreecommitdiff
path: root/chromium/content/browser/quota/quota_change_dispatcher.h
blob: e226b23dfa10cf031536c0a0c4aea5456fe6c84e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 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"

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_