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

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 first round of comments. 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 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 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
88 has_network_connectivity_ = !net::NetworkChangeNotifier::IsOffline();
mmenke 2015/01/16 21:28:34 Think it's worth a comment why this shouldn't be i
engedy 2015/01/19 18:13:11 Done.
89 }
90
91 AffiliationFetchThrottler::~AffiliationFetchThrottler() {
92 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
93 }
94
95 void AffiliationFetchThrottler::SignalNetworkRequestNeeded() {
96 if (state_ != IDLE)
mmenke 2015/01/16 21:28:35 Should we DCHECK on this? I assume one class will
engedy 2015/01/19 18:13:10 Being able to call this multiple times allows the
97 return;
98
99 state_ = FETCH_NEEDED;
mmenke 2015/01/16 21:28:35 Does the delegate have to be able to handle a call
mmenke 2015/01/16 21:49:54 Hrm...Was thinking there was a case where that cou
engedy 2015/01/19 18:13:11 Yes, I believe this can never happen. I have added
100 if (has_network_connectivity_)
101 EnsureCallbackIsScheduled();
102 }
103
104 void AffiliationFetchThrottler::InformOfNetworkRequestComplete(bool success) {
105 DCHECK_EQ(state_, FETCH_IN_FLIGHT);
mmenke 2015/01/16 21:28:34 Suggest making expected value the first argument (
engedy 2015/01/19 18:13:11 I'd prefer to keep it this way. As opposed to EXPE
106 state_ = IDLE;
107 exponential_backoff_->InformOfRequest(success);
mmenke 2015/01/16 21:31:28 It's up to the consumer to tell us if/when they wa
engedy 2015/01/19 18:13:11 Done. PTAL at the class comment.
108 }
109
110 void AffiliationFetchThrottler::EnsureCallbackIsScheduled() {
111 DCHECK_EQ(state_, FETCH_NEEDED);
mmenke 2015/01/16 21:49:54 DCHECK(has_network_connectivity_)?
engedy 2015/01/19 18:13:11 Done.
112 if (is_fetch_scheduled_)
113 return;
114
115 is_fetch_scheduled_ = true;
mmenke 2015/01/16 21:28:34 Suggest using a OneShotTimer instead, it keeps tra
engedy 2015/01/19 18:13:11 I wanted to use that, but it does not allow time t
mmenke 2015/01/21 17:18:52 Ah, I wasn't aware we had a task runner class with
116 task_runner_->PostDelayedTask(
117 FROM_HERE,
118 base::Bind(&AffiliationFetchThrottler::OnBackoffDelayExpiredCallback,
119 weak_ptr_factory_.GetWeakPtr()),
120 exponential_backoff_->GetTimeUntilRelease());
mmenke 2015/01/16 21:49:54 Also, do we need async behavior here? Seems like
engedy 2015/01/19 18:13:11 While we could certainly do that, do you think put
mmenke 2015/01/21 17:18:52 ScheduleCallbackIfNeeded? (Could even have the st
engedy 2015/01/23 22:09:43 I would like to keep always async behavior. On tha
121 }
122
123 void AffiliationFetchThrottler::OnBackoffDelayExpiredCallback() {
124 DCHECK_EQ(state_, FETCH_NEEDED);
125 DCHECK(is_fetch_scheduled_);
126 is_fetch_scheduled_ = false;
127
128 // Do nothing if network connectivity was lost while this callback was in the
129 // task queue. The callback will be posted in the OnConnectionTypeChanged
130 // handler once again.
131 if (!has_network_connectivity_)
132 return;
133
134 // The release time might have been increased if network connectivity was lost
135 // and restored while this callback was in the task queue. If so, reschedule.
136 if (exponential_backoff_->ShouldRejectRequest())
137 EnsureCallbackIsScheduled();
138 else
139 state_ = delegate_->OnCanSendNetworkRequest() ? FETCH_IN_FLIGHT : IDLE;
140 }
141
142 void AffiliationFetchThrottler::OnConnectionTypeChanged(
143 net::NetworkChangeNotifier::ConnectionType type) {
144 bool old_has_network_connectivity = has_network_connectivity_;
145 has_network_connectivity_ =
146 (type != net::NetworkChangeNotifier::CONNECTION_NONE);
147
148 // Only react when network connectivity has been reestablished.
149 if (!has_network_connectivity_ || old_has_network_connectivity)
150 return;
151
152 double grace_ms =
153 kGracePeriodAfterNetworkRestoredInMs *
154 (1 - base::RandDouble() * kAffiliationBackoffParameters.jitter_factor);
155 base::TimeTicks release_time = std::max(
156 exponential_backoff_->GetReleaseTime(),
157 tick_clock_->NowTicks() + base::TimeDelta::FromMillisecondsD(grace_ms));
158 // Note that SetCustomReleaseTime() takes the maximum of the current release
159 // time and the supplied |release_time|.
160 exponential_backoff_->SetCustomReleaseTime(release_time);
161
162 if (state_ == FETCH_NEEDED)
163 EnsureCallbackIsScheduled();
164 }
165
166 } // namespace password_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698