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

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: Fix ambiguity with pow() on Android. 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 failure.
52 4,
53
54 // Fuzzing percentage: 50% will spread delays randomly between 50%--100% of
55 // the nominal time.
56 .5, // 50%
57
58 // Maximum delay (in ms) during exponential backoff.
59 6 * 3600 * 1000, // 6 hours
60
61 // Time to keep an entry from being discarded even when it has no
62 // significant state, -1 to never discard. (Not applicable.)
63 -1,
64
65 // False means that initial_delay_ms is the first delay once we start
66 // exponential backoff, i.e., there is no delay after subsequent successful
67 // requests.
68 false,
69 };
70
71 // static
72 const int64_t AffiliationFetchThrottler::kGracePeriodAfterReconnectMs =
73 10 * 1000; // 10 seconds
74
75 AffiliationFetchThrottler::AffiliationFetchThrottler(
76 AffiliationFetchThrottlerDelegate* delegate,
77 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
78 scoped_ptr<base::TickClock> tick_clock)
79 : delegate_(delegate),
80 task_runner_(task_runner),
81 state_(IDLE),
82 has_network_connectivity_(false),
83 is_fetch_scheduled_(false),
84 tick_clock_(tick_clock.Pass()),
85 exponential_backoff_(
86 new BackoffEntryImpl(&kBackoffPolicy, tick_clock_.get())),
87 weak_ptr_factory_(this) {
88 DCHECK(delegate);
89 // Start observing before querying the current connectivity state, so that if
90 // the state changes concurrently in-between, it will not go unnoticed.
91 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
92 has_network_connectivity_ = !net::NetworkChangeNotifier::IsOffline();
93 }
94
95 AffiliationFetchThrottler::~AffiliationFetchThrottler() {
96 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
97 }
98
99 void AffiliationFetchThrottler::SignalNetworkRequestNeeded() {
100 if (state_ != IDLE)
101 return;
102
103 state_ = FETCH_NEEDED;
104 if (has_network_connectivity_)
105 EnsureCallbackIsScheduled();
106 }
107
108 void AffiliationFetchThrottler::InformOfNetworkRequestComplete(bool success) {
109 DCHECK_EQ(state_, FETCH_IN_FLIGHT);
110 state_ = IDLE;
111 exponential_backoff_->InformOfRequest(success);
112 }
113
114 void AffiliationFetchThrottler::EnsureCallbackIsScheduled() {
115 DCHECK_EQ(state_, FETCH_NEEDED);
116 DCHECK(has_network_connectivity_);
117
118 if (is_fetch_scheduled_)
119 return;
120
121 is_fetch_scheduled_ = true;
122 task_runner_->PostDelayedTask(
123 FROM_HERE,
124 base::Bind(&AffiliationFetchThrottler::OnBackoffDelayExpiredCallback,
125 weak_ptr_factory_.GetWeakPtr()),
126 exponential_backoff_->GetTimeUntilRelease());
127 }
128
129 void AffiliationFetchThrottler::OnBackoffDelayExpiredCallback() {
130 DCHECK_EQ(state_, FETCH_NEEDED);
131 DCHECK(is_fetch_scheduled_);
132 is_fetch_scheduled_ = false;
133
134 // Do nothing if network connectivity was lost while this callback was in the
135 // task queue. The callback will be posted in the OnConnectionTypeChanged
136 // handler once again.
137 if (!has_network_connectivity_)
138 return;
139
140 // The release time might have been increased if network connectivity was lost
141 // and restored while this callback was in the task queue. If so, reschedule.
142 if (exponential_backoff_->ShouldRejectRequest())
143 EnsureCallbackIsScheduled();
144 else
145 state_ = delegate_->OnCanSendNetworkRequest() ? FETCH_IN_FLIGHT : IDLE;
146 }
147
148 void AffiliationFetchThrottler::OnConnectionTypeChanged(
149 net::NetworkChangeNotifier::ConnectionType type) {
150 bool old_has_network_connectivity = has_network_connectivity_;
151 has_network_connectivity_ =
152 (type != net::NetworkChangeNotifier::CONNECTION_NONE);
153
154 // Only react when network connectivity has been reestablished.
155 if (!has_network_connectivity_ || old_has_network_connectivity)
156 return;
157
158 double grace_ms = kGracePeriodAfterReconnectMs *
159 (1 - base::RandDouble() * kBackoffPolicy.jitter_factor);
160 exponential_backoff_->SetCustomReleaseTime(std::max(
161 exponential_backoff_->GetReleaseTime(),
162 tick_clock_->NowTicks() + base::TimeDelta::FromMillisecondsD(grace_ms)));
163
164 if (state_ == FETCH_NEEDED)
165 EnsureCallbackIsScheduled();
166 }
167
168 } // namespace password_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698