Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: components/password_manager/core/browser/affiliation_fetch_throttler.cc

Issue 807503002: Implement throttling logic for fetching affiliation information. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@aff_database
Patch Set: Addressed more comments. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 "components/password_manager/core/browser/affiliation_fetch_throttler.h "
6
7 #include <stdint.h>
8
9 #include "base/logging.h"
10 #include "base/rand_util.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/time/tick_clock.h"
13 #include "base/time/time.h"
14 #include "components/password_manager/core/browser/affiliation_fetch_throttler_d elegate.h"
15
16 namespace password_manager {
17
18 namespace {
19
20 // Implementation of net::BackoffEntry that allows mocking its tick source.
21 class BackoffEntryImpl : public net::BackoffEntry {
22 public:
23 // |tick_clock| must outlive this instance.
24 explicit BackoffEntryImpl(const net::BackoffEntry::Policy* const policy,
25 base::TickClock* tick_clock)
26 : BackoffEntry(policy), tick_clock_(tick_clock) {}
27 ~BackoffEntryImpl() override {}
28
29 private:
30 // net::BackoffEntry:
31 base::TimeTicks ImplGetTimeNow() const override {
32 return tick_clock_->NowTicks();
33 }
34
35 base::TickClock* tick_clock_;
36
37 DISALLOW_COPY_AND_ASSIGN(BackoffEntryImpl);
38 };
39
40 } // namespace
41
42 // static
43 const net::BackoffEntry::Policy AffiliationFetchThrottler::kBackoffPolicy = {
44 // Number of initial errors (in sequence) to ignore before going into
45 // exponential backoff.
46 0,
47
48 // Initial delay (in ms) once backoff starts.
49 10 * 1000, // 10 seconds
50
51 // Factor by which the delay will be multiplied on each subsequent
52 // failure.
53 4,
54
55 // Fuzzing percentage: 50% will spread delays randomly between 50%--100%
56 // of
57 // the nominal time.
58 .5, // 50%
59
60 // Maximum delay (in ms) during exponential backoff.
61 6 * 3600 * 1000, // 6 hours
62
63 // Time to keep an entry from being discarded even when it has no
64 // significant state, -1 to never discard. (Not applicable.)
65 -1,
66
67 // False means that initial_delay_ms is the first delay once we start
68 // exponential backoff, i.e., there is no delay after subsequent
69 // successful
70 // requests.
71 false,
72 };
73
74 // static
75 const int64_t AffiliationFetchThrottler::kGracePeriodAfterReconnectMs =
76 10 * 1000; // 10 seconds
77
78 AffiliationFetchThrottler::AffiliationFetchThrottler(
79 AffiliationFetchThrottlerDelegate* delegate,
80 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
81 scoped_ptr<base::TickClock> tick_clock)
82 : delegate_(delegate),
83 task_runner_(task_runner),
84 state_(IDLE),
85 has_network_connectivity_(false),
86 is_fetch_scheduled_(false),
87 tick_clock_(tick_clock.Pass()),
88 exponential_backoff_(
89 new BackoffEntryImpl(&kBackoffPolicy, tick_clock_.get())),
90 weak_ptr_factory_(this) {
91 DCHECK(delegate);
92 // Start observing before querying the current connectivity state, so that if
93 // the state changes concurrently in-between, it will not go unnoticed.
94 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
95 has_network_connectivity_ = !net::NetworkChangeNotifier::IsOffline();
96 }
97
98 AffiliationFetchThrottler::~AffiliationFetchThrottler() {
99 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
100 }
101
102 void AffiliationFetchThrottler::SignalNetworkRequestNeeded() {
103 if (state_ != IDLE)
104 return;
105
106 state_ = FETCH_NEEDED;
107 if (has_network_connectivity_)
108 EnsureCallbackIsScheduled();
109 }
110
111 void AffiliationFetchThrottler::InformOfNetworkRequestComplete(bool success) {
112 DCHECK_EQ(state_, FETCH_IN_FLIGHT);
113 state_ = IDLE;
114 exponential_backoff_->InformOfRequest(success);
115 }
116
117 void AffiliationFetchThrottler::EnsureCallbackIsScheduled() {
118 DCHECK_EQ(state_, FETCH_NEEDED);
119 DCHECK(has_network_connectivity_);
120
121 if (is_fetch_scheduled_)
122 return;
123
124 is_fetch_scheduled_ = true;
125 task_runner_->PostDelayedTask(
126 FROM_HERE,
127 base::Bind(&AffiliationFetchThrottler::OnBackoffDelayExpiredCallback,
128 weak_ptr_factory_.GetWeakPtr()),
129 exponential_backoff_->GetTimeUntilRelease());
130 }
131
132 void AffiliationFetchThrottler::OnBackoffDelayExpiredCallback() {
133 DCHECK_EQ(state_, FETCH_NEEDED);
134 DCHECK(is_fetch_scheduled_);
135 is_fetch_scheduled_ = false;
136
137 // Do nothing if network connectivity was lost while this callback was in the
138 // task queue. The callback will be posted in the OnConnectionTypeChanged
139 // handler once again.
140 if (!has_network_connectivity_)
141 return;
142
143 // The release time might have been increased if network connectivity was lost
144 // and restored while this callback was in the task queue. If so, reschedule.
145 if (exponential_backoff_->ShouldRejectRequest())
146 EnsureCallbackIsScheduled();
147 else
148 state_ = delegate_->OnCanSendNetworkRequest() ? FETCH_IN_FLIGHT : IDLE;
149 }
150
151 void AffiliationFetchThrottler::OnConnectionTypeChanged(
152 net::NetworkChangeNotifier::ConnectionType type) {
153 bool old_has_network_connectivity = has_network_connectivity_;
154 has_network_connectivity_ =
155 (type != net::NetworkChangeNotifier::CONNECTION_NONE);
156
157 // Only react when network connectivity has been reestablished.
158 if (!has_network_connectivity_ || old_has_network_connectivity)
159 return;
160
161 double grace_ms = kGracePeriodAfterReconnectMs *
162 (1 - base::RandDouble() * kBackoffPolicy.jitter_factor);
163 exponential_backoff_->SetCustomReleaseTime(std::max(
164 exponential_backoff_->GetReleaseTime(),
165 tick_clock_->NowTicks() + base::TimeDelta::FromMillisecondsD(grace_ms)));
166
167 if (state_ == FETCH_NEEDED)
168 EnsureCallbackIsScheduled();
169 }
170
171 } // namespace password_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698