1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// The QuotaService uses heuristics to limit abusive requests
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// made by extensions.  In this model 'items' (e.g individual bookmarks) are
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// represented by a 'Bucket' that holds state for that item for one single
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// interval of time.  The interval of time is defined as 'how long we need to
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// watch an item (for a particular heuristic) before making a decision about
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// quota violations'.  A heuristic is two functions: one mapping input
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// arguments to a unique Bucket (the BucketMapper), and another to determine
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if a new request involving such an item at a given time is a violation.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#ifndef EXTENSIONS_BROWSER_QUOTA_SERVICE_H_
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#define EXTENSIONS_BROWSER_QUOTA_SERVICE_H_
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/containers/hash_tables.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/non_thread_safe.h"
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionFunction;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class QuotaLimitHeuristic;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)typedef std::list<QuotaLimitHeuristic*> QuotaLimitHeuristics;
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// The QuotaService takes care that calls to certain extension
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functions do not exceed predefined quotas.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The QuotaService needs to live entirely on one thread, i.e. be created,
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// called and destroyed on the same thread, due to its use of a RepeatingTimer.
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// It is not a KeyedService because instances exist on both the UI
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// and IO threads.
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class QuotaService : public base::NonThreadSafe {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some concrete heuristics (declared below) that ExtensionFunctions can
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use to help the service make decisions about quota violations.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class TimedLimit;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class SustainedLimit;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  QuotaService();
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~QuotaService();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Decide whether the invocation of |function| with argument |args| by the
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension specified by |extension_id| results in a quota limit violation.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns an error message representing the failure if quota was exceeded,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or empty-string if the request is fine and can proceed.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string Assess(const std::string& extension_id,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     ExtensionFunction* function,
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     const base::ListValue* args,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const base::TimeTicks& event_time);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::string ExtensionId;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::string FunctionName;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All QuotaLimitHeuristic instances in this map are owned by us.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<FunctionName, QuotaLimitHeuristics> FunctionHeuristicsMap;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Purge resets all accumulated data (except |violation_errors_|) as if the
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // service was just created. Called periodically so we don't consume an
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unbounded amount of memory while tracking quota.  Yes, this could mean an
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension gets away with murder if it is timed right, but the extensions
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we are trying to limit are ones that consistently violate, so we'll
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // converge to the correct set.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Purge();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PurgeFunctionHeuristicsMap(FunctionHeuristicsMap* map);
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::RepeatingTimer<QuotaService> purge_timer_;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Our quota tracking state for extensions that have invoked quota limited
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // functions.  Each extension is treated separately, so extension ids are the
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // key for the mapping.  As an extension invokes functions, the map keeps
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // track of which functions it has invoked and the heuristics for each one.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Each heuristic will be evaluated and ANDed together to get a final answer.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<ExtensionId, FunctionHeuristicsMap> function_heuristics_;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For now, as soon as an extension violates quota, we don't allow it to
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // make any more requests to quota limited functions.  This provides a quick
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // lookup for these extensions that is only stored in memory.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<std::string, std::string> ViolationErrorMap;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ViolationErrorMap violation_errors_;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(QuotaService);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A QuotaLimitHeuristic is two things: 1, A heuristic to map extension
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function arguments to corresponding Buckets for each input arg, and 2) a
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// heuristic for determining if a new event involving a particular item
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (represented by its Bucket) constitutes a quota violation.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class QuotaLimitHeuristic {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parameters to configure the amount of tokens allotted to individual
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Bucket objects (see Below) and how often they are replenished.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Config {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The maximum number of tokens a bucket can contain, and is refilled to
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // every epoch.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 refill_token_count;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Specifies how frequently the bucket is logically refilled with tokens.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta refill_interval;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A Bucket is how the heuristic portrays an individual item (since quota
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // limits are per item) and all associated state for an item that needs to
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // carry through multiple calls to Apply.  It "holds" tokens, which are
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // debited and credited in response to new events involving the item being
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // being represented.  For convenience, instead of actually periodically
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // refilling buckets they are just 'Reset' on-demand (e.g. when new events
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // come in). So, a bucket has an expiration to denote it has becomes stale.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Bucket {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Bucket() : num_tokens_(0) {}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Removes a token from this bucket, and returns true if the bucket had
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // any tokens in the first place.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool DeductToken() { return num_tokens_-- > 0; }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Returns true if this bucket has tokens to deduct.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool has_tokens() const { return num_tokens_ > 0; }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reset this bucket to specification (from internal configuration), to be
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // valid from |start| until the first refill interval elapses and it needs
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to be reset again.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void Reset(const Config& config, const base::TimeTicks& start);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The time at which the token count and next expiration should be reset,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // via a call to Reset.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::TimeTicks& expiration() { return expiration_; }
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeTicks expiration_;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 num_tokens_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(Bucket);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::list<Bucket*> BucketList;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A helper interface to retrieve the bucket corresponding to |args| from
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the set of buckets (which is typically stored in the BucketMapper itself)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for this QuotaLimitHeuristic.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class BucketMapper {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~BucketMapper() {}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In most cases, this should simply extract item IDs from the arguments
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (e.g for bookmark operations involving an existing item). If a problem
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // occurs while parsing |args|, the function aborts - buckets may be non-
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // empty). The expectation is that invalid args and associated errors are
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // handled by the ExtensionFunction itself so we don't concern ourselves.
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    virtual void GetBucketsForArgs(const base::ListValue* args,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   BucketList* buckets) = 0;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maps all calls to the same bucket, regardless of |args|, for this
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // QuotaLimitHeuristic.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class SingletonBucketMapper : public BucketMapper {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SingletonBucketMapper() {}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~SingletonBucketMapper() {}
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    virtual void GetBucketsForArgs(const base::ListValue* args,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   BucketList* buckets) OVERRIDE;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Bucket bucket_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(SingletonBucketMapper);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ownership of |map| is given to the new QuotaLimitHeuristic.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuotaLimitHeuristic(const Config& config,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      BucketMapper* map,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const std::string& name);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~QuotaLimitHeuristic();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determines if sufficient quota exists (according to the Apply
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // implementation of a derived class) to perform an operation with |args|,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // based on the history of similar operations with similar arguments (which
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is retrieved using the BucketMapper).
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool ApplyToArgs(const base::ListValue* args,
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                   const base::TimeTicks& event_time);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns an error formatted according to this heuristic.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetError() const;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Config& config() { return config_; }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine if the new event occurring at |event_time| involving |bucket|
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // constitutes a quota violation according to this heuristic.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Apply(Bucket* bucket, const base::TimeTicks& event_time) = 0;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class QuotaLimitHeuristicTest;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Config config_;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The mapper used in Map. Cannot be NULL.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BucketMapper> bucket_mapper_;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The name of the heuristic for formatting error messages.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name_;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(QuotaLimitHeuristic);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A simple per-item heuristic to limit the number of events that can occur in
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a given period of time; e.g "no more than 100 events in an hour".
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class QuotaService::TimedLimit : public QuotaLimitHeuristic {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimedLimit(const Config& config, BucketMapper* map, const std::string& name)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : QuotaLimitHeuristic(config, map, name) {}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Apply(Bucket* bucket,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const base::TimeTicks& event_time) OVERRIDE;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A per-item heuristic to limit the number of events that can occur in a
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// period of time over a sustained longer interval. E.g "no more than two
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// events per minute, sustained over 10 minutes".
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class QuotaService::SustainedLimit : public QuotaLimitHeuristic {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SustainedLimit(const base::TimeDelta& sustain,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const Config& config,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 BucketMapper* map,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const std::string& name);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Apply(Bucket* bucket,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const base::TimeTicks& event_time) OVERRIDE;
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Specifies how long exhaustion of buckets is allowed to continue before
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // denying requests.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int64 repeat_exhaustion_allowance_;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 num_available_repeat_exhaustions_;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace extensions
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif  // EXTENSIONS_BROWSER_QUOTA_SERVICE_H_
242