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

Side by Side Diff: chrome/browser/extensions/extensions_quota_service.h

Issue 10871034: Make all quota-exceeding messages in the storage API explain what the failure (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: update... the other error message Created 8 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // The ExtensionsQuotaService uses heuristics to limit abusive requests 5 // The ExtensionsQuotaService uses heuristics to limit abusive requests
6 // made by extensions. In this model 'items' (e.g individual bookmarks) are 6 // made by extensions. In this model 'items' (e.g individual bookmarks) are
7 // represented by a 'Bucket' that holds state for that item for one single 7 // represented by a 'Bucket' that holds state for that item for one single
8 // interval of time. The interval of time is defined as 'how long we need to 8 // interval of time. The interval of time is defined as 'how long we need to
9 // watch an item (for a particular heuristic) before making a decision about 9 // watch an item (for a particular heuristic) before making a decision about
10 // quota violations'. A heuristic is two functions: one mapping input 10 // quota violations'. A heuristic is two functions: one mapping input
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 // Some concrete heuristics (declared below) that ExtensionFunctions can 45 // Some concrete heuristics (declared below) that ExtensionFunctions can
46 // use to help the service make decisions about quota violations. 46 // use to help the service make decisions about quota violations.
47 class TimedLimit; 47 class TimedLimit;
48 class SustainedLimit; 48 class SustainedLimit;
49 49
50 ExtensionsQuotaService(); 50 ExtensionsQuotaService();
51 virtual ~ExtensionsQuotaService(); 51 virtual ~ExtensionsQuotaService();
52 52
53 // Decide whether the invocation of |function| with argument |args| by the 53 // Decide whether the invocation of |function| with argument |args| by the
54 // extension specified by |extension_id| results in a quota limit violation. 54 // extension specified by |extension_id| results in a quota limit violation.
55 // Returns true if the request is fine and can proceed, false if the request 55 // Returns an error message representing the failure if quota was exceeded,
56 // should be throttled and an error returned to the extension. 56 // or empty-string if the request is fine and can proceed.
57 bool Assess(const std::string& extension_id, ExtensionFunction* function, 57 std::string Assess(const std::string& extension_id,
58 const ListValue* args, const base::TimeTicks& event_time); 58 ExtensionFunction* function,
59 const ListValue* args,
60 const base::TimeTicks& event_time);
61
59 private: 62 private:
60 friend class extensions::TestResetQuotaFunction; 63 friend class extensions::TestResetQuotaFunction;
61 typedef std::string ExtensionId; 64 typedef std::string ExtensionId;
62 typedef std::string FunctionName; 65 typedef std::string FunctionName;
63 // All QuotaLimitHeuristic instances in this map are owned by us. 66 // All QuotaLimitHeuristic instances in this map are owned by us.
64 typedef std::map<FunctionName, QuotaLimitHeuristics> FunctionHeuristicsMap; 67 typedef std::map<FunctionName, QuotaLimitHeuristics> FunctionHeuristicsMap;
65 68
66 // Purge resets all accumulated data (except |violators_|) as if the service 69 // Purge resets all accumulated data (except |violation_errors_|) as if the
67 // was just created. Called periodically so we don't consume an unbounded 70 // service was just created. Called periodically so we don't consume an
68 // amount of memory while tracking quota. Yes, this could mean an extension 71 // unbounded amount of memory while tracking quota. Yes, this could mean an
69 // gets away with murder if it is timed right, but the extensions we are 72 // extension gets away with murder if it is timed right, but the extensions
70 // trying to limit are ones that consistently violate, so we'll converge 73 // we are trying to limit are ones that consistently violate, so we'll
71 // to the correct set. 74 // converge to the correct set.
72 void Purge(); 75 void Purge();
73 void PurgeFunctionHeuristicsMap(FunctionHeuristicsMap* map); 76 void PurgeFunctionHeuristicsMap(FunctionHeuristicsMap* map);
74 base::RepeatingTimer<ExtensionsQuotaService> purge_timer_; 77 base::RepeatingTimer<ExtensionsQuotaService> purge_timer_;
75 78
76 // Our quota tracking state for extensions that have invoked quota limited 79 // Our quota tracking state for extensions that have invoked quota limited
77 // functions. Each extension is treated separately, so extension ids are the 80 // functions. Each extension is treated separately, so extension ids are the
78 // key for the mapping. As an extension invokes functions, the map keeps 81 // key for the mapping. As an extension invokes functions, the map keeps
79 // track of which functions it has invoked and the heuristics for each one. 82 // track of which functions it has invoked and the heuristics for each one.
80 // Each heuristic will be evaluated and ANDed together to get a final answer. 83 // Each heuristic will be evaluated and ANDed together to get a final answer.
81 std::map<ExtensionId, FunctionHeuristicsMap> function_heuristics_; 84 std::map<ExtensionId, FunctionHeuristicsMap> function_heuristics_;
82 85
83 // For now, as soon as an extension violates quota, we don't allow it to 86 // For now, as soon as an extension violates quota, we don't allow it to
84 // make any more requests to quota limited functions. This provides a quick 87 // make any more requests to quota limited functions. This provides a quick
85 // lookup for these extensions that is only stored in memory. 88 // lookup for these extensions that is only stored in memory.
86 base::hash_set<std::string> violators_; 89 typedef std::map<std::string, std::string> ViolationErrorMap;
90 ViolationErrorMap violation_errors_;
87 91
88 DISALLOW_COPY_AND_ASSIGN(ExtensionsQuotaService); 92 DISALLOW_COPY_AND_ASSIGN(ExtensionsQuotaService);
89 }; 93 };
90 94
91 // A QuotaLimitHeuristic is two things: 1, A heuristic to map extension 95 // A QuotaLimitHeuristic is two things: 1, A heuristic to map extension
92 // function arguments to corresponding Buckets for each input arg, and 2) a 96 // function arguments to corresponding Buckets for each input arg, and 2) a
93 // heuristic for determining if a new event involving a particular item 97 // heuristic for determining if a new event involving a particular item
94 // (represented by its Bucket) constitutes a quota violation. 98 // (represented by its Bucket) constitutes a quota violation.
95 class QuotaLimitHeuristic { 99 class QuotaLimitHeuristic {
96 public: 100 public:
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 // The time at which the token count and next expiration should be reset, 134 // The time at which the token count and next expiration should be reset,
131 // via a call to Reset. 135 // via a call to Reset.
132 const base::TimeTicks& expiration() { return expiration_; } 136 const base::TimeTicks& expiration() { return expiration_; }
133 private: 137 private:
134 base::TimeTicks expiration_; 138 base::TimeTicks expiration_;
135 int64 num_tokens_; 139 int64 num_tokens_;
136 DISALLOW_COPY_AND_ASSIGN(Bucket); 140 DISALLOW_COPY_AND_ASSIGN(Bucket);
137 }; 141 };
138 typedef std::list<Bucket*> BucketList; 142 typedef std::list<Bucket*> BucketList;
139 143
140 // A generic error message for quota violating requests.
141 static const char kGenericOverQuotaError[];
142
143 // A helper interface to retrieve the bucket corresponding to |args| from 144 // A helper interface to retrieve the bucket corresponding to |args| from
144 // the set of buckets (which is typically stored in the BucketMapper itself) 145 // the set of buckets (which is typically stored in the BucketMapper itself)
145 // for this QuotaLimitHeuristic. 146 // for this QuotaLimitHeuristic.
146 class BucketMapper { 147 class BucketMapper {
147 public: 148 public:
148 virtual ~BucketMapper() {} 149 virtual ~BucketMapper() {}
149 // In most cases, this should simply extract item IDs from the arguments 150 // In most cases, this should simply extract item IDs from the arguments
150 // (e.g for bookmark operations involving an existing item). If a problem 151 // (e.g for bookmark operations involving an existing item). If a problem
151 // occurs while parsing |args|, the function aborts - buckets may be non- 152 // occurs while parsing |args|, the function aborts - buckets may be non-
152 // empty). The expectation is that invalid args and associated errors are 153 // empty). The expectation is that invalid args and associated errors are
153 // handled by the ExtensionFunction itself so we don't concern ourselves. 154 // handled by the ExtensionFunction itself so we don't concern ourselves.
154 virtual void GetBucketsForArgs(const ListValue* args, 155 virtual void GetBucketsForArgs(const ListValue* args,
155 BucketList* buckets) = 0; 156 BucketList* buckets) = 0;
156 }; 157 };
157 158
158 // Maps all calls to the same bucket, regardless of |args|, for this 159 // Maps all calls to the same bucket, regardless of |args|, for this
159 // QuotaLimitHeuristic. 160 // QuotaLimitHeuristic.
160 class SingletonBucketMapper : public BucketMapper { 161 class SingletonBucketMapper : public BucketMapper {
161 public: 162 public:
162 SingletonBucketMapper() {} 163 SingletonBucketMapper() {}
163 virtual ~SingletonBucketMapper() {} 164 virtual ~SingletonBucketMapper() {}
164 virtual void GetBucketsForArgs(const ListValue* args, 165 virtual void GetBucketsForArgs(const ListValue* args,
165 BucketList* buckets) OVERRIDE; 166 BucketList* buckets) OVERRIDE;
166 167
167 private: 168 private:
168 Bucket bucket_; 169 Bucket bucket_;
169 DISALLOW_COPY_AND_ASSIGN(SingletonBucketMapper); 170 DISALLOW_COPY_AND_ASSIGN(SingletonBucketMapper);
170 }; 171 };
171 172
172 // Ownership of |mapper| is given to the new QuotaLimitHeuristic. 173 // Ownership of |map| is given to the new QuotaLimitHeuristic.
173 QuotaLimitHeuristic(const Config& config, BucketMapper* map); 174 QuotaLimitHeuristic(const Config& config,
175 BucketMapper* map,
176 const std::string& name);
174 virtual ~QuotaLimitHeuristic(); 177 virtual ~QuotaLimitHeuristic();
175 178
176 // Determines if sufficient quota exists (according to the Apply 179 // Determines if sufficient quota exists (according to the Apply
177 // implementation of a derived class) to perform an operation with |args|, 180 // implementation of a derived class) to perform an operation with |args|,
178 // based on the history of similar operations with similar arguments (which 181 // based on the history of similar operations with similar arguments (which
179 // is retrieved using the BucketMapper). 182 // is retrieved using the BucketMapper).
180 bool ApplyToArgs(const ListValue* args, const base::TimeTicks& event_time); 183 bool ApplyToArgs(const ListValue* args, const base::TimeTicks& event_time);
181 184
185 // Returns an error formatted according to this heuristic.
186 std::string GetError() const;
187
182 protected: 188 protected:
183 const Config& config() { return config_; } 189 const Config& config() { return config_; }
184 190
185 // Determine if the new event occurring at |event_time| involving |bucket| 191 // Determine if the new event occurring at |event_time| involving |bucket|
186 // constitutes a quota violation according to this heuristic. 192 // constitutes a quota violation according to this heuristic.
187 virtual bool Apply(Bucket* bucket, const base::TimeTicks& event_time) = 0; 193 virtual bool Apply(Bucket* bucket, const base::TimeTicks& event_time) = 0;
188 194
189 private: 195 private:
190 friend class QuotaLimitHeuristicTest; 196 friend class QuotaLimitHeuristicTest;
191 197
192 const Config config_; 198 const Config config_;
193 199
194 // The mapper used in Map. Cannot be NULL. 200 // The mapper used in Map. Cannot be NULL.
195 scoped_ptr<BucketMapper> bucket_mapper_; 201 scoped_ptr<BucketMapper> bucket_mapper_;
196 202
203 // The name of the heuristic for formatting error messages.
204 std::string name_;
205
197 DISALLOW_COPY_AND_ASSIGN(QuotaLimitHeuristic); 206 DISALLOW_COPY_AND_ASSIGN(QuotaLimitHeuristic);
198 }; 207 };
199 208
200 // A simple per-item heuristic to limit the number of events that can occur in 209 // A simple per-item heuristic to limit the number of events that can occur in
201 // a given period of time; e.g "no more than 100 events in an hour". 210 // a given period of time; e.g "no more than 100 events in an hour".
202 class ExtensionsQuotaService::TimedLimit : public QuotaLimitHeuristic { 211 class ExtensionsQuotaService::TimedLimit : public QuotaLimitHeuristic {
203 public: 212 public:
204 TimedLimit(const Config& config, BucketMapper* map) 213 TimedLimit(const Config& config, BucketMapper* map, const std::string& name)
205 : QuotaLimitHeuristic(config, map) {} 214 : QuotaLimitHeuristic(config, map, name) {}
206 virtual bool Apply(Bucket* bucket, 215 virtual bool Apply(Bucket* bucket,
207 const base::TimeTicks& event_time) OVERRIDE; 216 const base::TimeTicks& event_time) OVERRIDE;
208 }; 217 };
209 218
210 // A per-item heuristic to limit the number of events that can occur in a 219 // A per-item heuristic to limit the number of events that can occur in a
211 // period of time over a sustained longer interval. E.g "no more than two 220 // period of time over a sustained longer interval. E.g "no more than two
212 // events per minute, sustained over 10 minutes". 221 // events per minute, sustained over 10 minutes".
213 class ExtensionsQuotaService::SustainedLimit : public QuotaLimitHeuristic { 222 class ExtensionsQuotaService::SustainedLimit : public QuotaLimitHeuristic {
214 public: 223 public:
215 SustainedLimit(const base::TimeDelta& sustain, 224 SustainedLimit(const base::TimeDelta& sustain,
216 const Config& config, 225 const Config& config,
217 BucketMapper* map); 226 BucketMapper* map,
227 const std::string& name);
218 virtual bool Apply(Bucket* bucket, 228 virtual bool Apply(Bucket* bucket,
219 const base::TimeTicks& event_time) OVERRIDE; 229 const base::TimeTicks& event_time) OVERRIDE;
220 private: 230 private:
221 // Specifies how long exhaustion of buckets is allowed to continue before 231 // Specifies how long exhaustion of buckets is allowed to continue before
222 // denying requests. 232 // denying requests.
223 const int64 repeat_exhaustion_allowance_; 233 const int64 repeat_exhaustion_allowance_;
224 int64 num_available_repeat_exhaustions_; 234 int64 num_available_repeat_exhaustions_;
225 }; 235 };
226 236
227 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSIONS_QUOTA_SERVICE_H_ 237 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSIONS_QUOTA_SERVICE_H_
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_function_dispatcher.cc ('k') | chrome/browser/extensions/extensions_quota_service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698