|  | // Copyright 2017 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 EXTENSIONS_BROWSER_API_FEEDBACK_PRIVATE_ACCESS_RATE_LIMITER_H_ | 
|  | #define EXTENSIONS_BROWSER_API_FEEDBACK_PRIVATE_ACCESS_RATE_LIMITER_H_ | 
|  |  | 
|  | #include <algorithm> | 
|  | #include <memory> | 
|  |  | 
|  | #include "base/macros.h" | 
|  | #include "base/time/default_tick_clock.h" | 
|  | #include "base/time/tick_clock.h" | 
|  | #include "base/time/time.h" | 
|  |  | 
|  | namespace extensions { | 
|  |  | 
|  | // Keeps track of how frequently a resource may be accessed. Uses a rechargeable | 
|  | // time counter to keep track. Each time an access is attempted, if the counter | 
|  | // has more than |recharge_period_|, it will be a successful access, and then | 
|  | // |recharge_period_| is deducted from it. If the counter has less than | 
|  | // |recharge_period_|, it will not be a successful access. | 
|  | // | 
|  | // The counter is automatically charged as time goes on. It is updated based on | 
|  | // the current time right before each access attempt. The counter maxes out at | 
|  | // |recharge_period_ * max_num_accesses|. | 
|  | // | 
|  | // The counter starts off at the max level, so that at the beginning, the number | 
|  | // of successful accesses that can be immediately attempted is | 
|  | // |max_num_accesses|. | 
|  | // | 
|  | // For example, suppose max_num_accesses=3 and recharge_period=100 ms. The | 
|  | // following sequence of events could happen: | 
|  | // - AttemptAccess() immediately gets called 3 times. It returns true 3 times. | 
|  | // - Any further access within the next 100 ms will return false. | 
|  | // - After 100 ms, call AttemptAccess() again. It will return true. | 
|  | // - Any further access within the next 100 ms will return false. | 
|  | // - After 200 ms, call AttemptAccess() again. It will return true. It can be | 
|  | //   called successfully one more time at this point, but we won't call it yet. | 
|  | // - After 100 ms, call AttemptAccess() twice. It will return true both times, | 
|  | //   because the meter will have charged enough for two more accessess. | 
|  | // | 
|  | // The counter can be charged partially. e.g. it can accrue 50 ms from one | 
|  | // attempted access and 50 ms from the next, to get a full 100 ms and thus one | 
|  | // more successful access. | 
|  | // | 
|  | // See the unit tests for more info about the behavior. | 
|  | class AccessRateLimiter { | 
|  | public: | 
|  | AccessRateLimiter(size_t max_num_accesses, | 
|  | const base::TimeDelta& recharge_period, | 
|  | const base::TickClock* tick_clock); | 
|  | ~AccessRateLimiter(); | 
|  |  | 
|  | // Attempt to access a resource. Will update |counter_| based on how much time | 
|  | // has elapsed since the last access attempt. | 
|  | // - Deducts |recharge_period_| from |counter_| if possible and returns true | 
|  | //   to indicate a successful access attempt. | 
|  | // - If |counter_| < |recharge_period_|, returns false to indicate a failed | 
|  | //   access attempt. | 
|  | bool AttemptAccess(); | 
|  |  | 
|  | private: | 
|  | // Can only accrue up to this many available accesses. | 
|  | const size_t max_num_accesses_; | 
|  |  | 
|  | // Time when AttemptAccess() was last called. | 
|  | base::TimeTicks last_access_time_; | 
|  |  | 
|  | // The time it takes to accumulate one extra available access. If this is set | 
|  | // 0, accesses is allowed. | 
|  | const base::TimeDelta recharge_period_; | 
|  |  | 
|  | // Keeps track of how many available accesses there are. There is one for each | 
|  | // unit of |recharge_period_|. | 
|  | base::TimeDelta counter_; | 
|  |  | 
|  | // Points to a timer clock implementation for keeping track of access times. | 
|  | const base::TickClock* tick_clock_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(AccessRateLimiter); | 
|  | }; | 
|  |  | 
|  | }  // namespace extensions | 
|  |  | 
|  | #endif  // EXTENSIONS_BROWSER_API_FEEDBACK_PRIVATE_ACCESS_RATE_LIMITER_H_ |