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

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: Nit Created 5 years, 11 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 #include "net/base/backoff_entry.h"
16
17 namespace password_manager {
18
19 namespace {
20
21 const net::BackoffEntry::Policy kAffiliationBackoffParameters = {
22 // Number of initial errors (in sequence) to ignore before going into
23 // exponential backoff.
24 0,
25
26 // Initial delay (in ms) once backoff starts.
27 10 * 1000, // 10 seconds
28
29 // Factor by which the delay will be multiplied on each subsequent failure.
30 4,
31
32 // Fuzzing percentage: 50% will spread delays randomly between 50%--100% of
33 // the nominal time.
34 .5, // 50%
35
36 // Maximum delay (in ms) during exponential backoff.
37 6 * 3600 * 1000, // 6 hours
38
39 // Time to keep an entry from being discarded even when it has no
40 // significant state, -1 to never discard. (Not applicable.)
41 -1,
42
43 // False means that initial_delay_ms is the first delay once we start
44 // exponential backoff, i.e., there is no delay after subsequent successful
45 // requests.
46 false,
47 };
48
49 // Grace period before the first request is sent after network connectivity is
50 // restored. The fuzzing factor from above applies.
51 const int64_t kGracePeriodAfterNetworkRestoredInMs = 10 * 1000; // 10 seconds
52
53 // Implementation of net::BackoffEntry that allows mocking its tick source.
54 class BackoffEntryImpl : public net::BackoffEntry {
55 public:
56 explicit BackoffEntryImpl(base::TickClock* tick_clock)
57 : BackoffEntry(&kAffiliationBackoffParameters), tick_clock_(tick_clock) {}
58 ~BackoffEntryImpl() override {}
59
60 private:
61 // net::BackoffEntry:
62 base::TimeTicks ImplGetTimeNow() const override {
63 return tick_clock_->NowTicks();
64 }
65
66 // Must outlive this instance.
67 base::TickClock* tick_clock_;
68
69 DISALLOW_COPY_AND_ASSIGN(BackoffEntryImpl);
70 };
71
72 } // namespace
73
74 AffiliationFetchThrottler::AffiliationFetchThrottler(
75 AffiliationFetchThrottlerDelegate* delegate,
76 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
77 scoped_ptr<base::TickClock> tick_clock)
78 : delegate_(delegate),
79 task_runner_(task_runner),
80 state_(IDLE),
81 has_network_connectivity_(false),
82 is_fetch_scheduled_(false),
83 tick_clock_(tick_clock.Pass()),
84 exponential_backoff_(new BackoffEntryImpl(tick_clock_.get())),
85 weak_ptr_factory_(this) {
86 DCHECK(delegate);
87 // Start observing before querying the current connectivity state, so that if
88 // the state changes concurrently in-between, it will not go unnoticed.
89 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
90 has_network_connectivity_ = !net::NetworkChangeNotifier::IsOffline();
91 }
92
93 AffiliationFetchThrottler::~AffiliationFetchThrottler() {
94 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
95 }
96
97 void AffiliationFetchThrottler::SignalNetworkRequestNeeded() {
98 if (state_ != IDLE)
99 return;
100
101 state_ = FETCH_NEEDED;
102 if (has_network_connectivity_)
103 EnsureCallbackIsScheduled();
104 }
105
106 void AffiliationFetchThrottler::InformOfNetworkRequestComplete(bool success) {
107 DCHECK_EQ(state_, FETCH_IN_FLIGHT);
108 state_ = IDLE;
109 exponential_backoff_->InformOfRequest(success);
110 }
111
112 void AffiliationFetchThrottler::EnsureCallbackIsScheduled() {
113 DCHECK_EQ(state_, FETCH_NEEDED);
114 DCHECK(has_network_connectivity_);
115
116 if (is_fetch_scheduled_)
117 return;
118
119 is_fetch_scheduled_ = true;
120 task_runner_->PostDelayedTask(
121 FROM_HERE,
122 base::Bind(&AffiliationFetchThrottler::OnBackoffDelayExpiredCallback,
123 weak_ptr_factory_.GetWeakPtr()),
mmenke 2015/01/21 17:18:52 Don't think we have any test that fails if this us
engedy 2015/01/23 22:09:43 Done.
124 exponential_backoff_->GetTimeUntilRelease());
125 }
126
127 void AffiliationFetchThrottler::OnBackoffDelayExpiredCallback() {
128 DCHECK_EQ(state_, FETCH_NEEDED);
129 DCHECK(is_fetch_scheduled_);
130 is_fetch_scheduled_ = false;
131
132 // Do nothing if network connectivity was lost while this callback was in the
133 // task queue. The callback will be posted in the OnConnectionTypeChanged
134 // handler once again.
135 if (!has_network_connectivity_)
136 return;
137
138 // The release time might have been increased if network connectivity was lost
139 // and restored while this callback was in the task queue. If so, reschedule.
140 if (exponential_backoff_->ShouldRejectRequest())
141 EnsureCallbackIsScheduled();
142 else
143 state_ = delegate_->OnCanSendNetworkRequest() ? FETCH_IN_FLIGHT : IDLE;
144 }
145
146 void AffiliationFetchThrottler::OnConnectionTypeChanged(
147 net::NetworkChangeNotifier::ConnectionType type) {
148 bool old_has_network_connectivity = has_network_connectivity_;
149 has_network_connectivity_ =
150 (type != net::NetworkChangeNotifier::CONNECTION_NONE);
151
152 // Only react when network connectivity has been reestablished.
153 if (!has_network_connectivity_ || old_has_network_connectivity)
154 return;
155
156 double grace_ms =
157 kGracePeriodAfterNetworkRestoredInMs *
158 (1 - base::RandDouble() * kAffiliationBackoffParameters.jitter_factor);
159 base::TimeTicks release_time = std::max(
160 exponential_backoff_->GetReleaseTime(),
161 tick_clock_->NowTicks() + base::TimeDelta::FromMillisecondsD(grace_ms));
162 // Note that SetCustomReleaseTime() takes the maximum of the current release
163 // time and the supplied |release_time|.
164 exponential_backoff_->SetCustomReleaseTime(release_time);
165
166 if (state_ == FETCH_NEEDED)
167 EnsureCallbackIsScheduled();
168 }
169
170 } // namespace password_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698