OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef WEBKIT_QUOTA_QUOTA_MANAGER_H_ | |
6 #define WEBKIT_QUOTA_QUOTA_MANAGER_H_ | |
7 | |
8 #include <deque> | |
9 #include <list> | |
10 #include <map> | |
11 #include <set> | |
12 #include <string> | |
13 #include <utility> | |
14 #include <vector> | |
15 | |
16 #include "base/basictypes.h" | |
17 #include "base/callback.h" | |
18 #include "base/files/file_path.h" | |
19 #include "base/memory/ref_counted.h" | |
20 #include "base/memory/scoped_ptr.h" | |
21 #include "base/memory/weak_ptr.h" | |
22 #include "base/sequenced_task_runner_helpers.h" | |
23 #include "webkit/quota/quota_callbacks.h" | |
24 #include "webkit/quota/quota_client.h" | |
25 #include "webkit/quota/quota_database.h" | |
26 #include "webkit/quota/quota_task.h" | |
27 #include "webkit/quota/special_storage_policy.h" | |
28 #include "webkit/storage/webkit_storage_export.h" | |
29 | |
30 namespace base { | |
31 class FilePath; | |
32 class SequencedTaskRunner; | |
33 class SingleThreadTaskRunner; | |
34 } | |
35 | |
36 namespace quota_internals { | |
37 class QuotaInternalsProxy; | |
38 } | |
39 | |
40 namespace quota { | |
41 | |
42 class MockQuotaManager; | |
43 class QuotaDatabase; | |
44 class QuotaManagerProxy; | |
45 class QuotaTemporaryStorageEvictor; | |
46 class UsageTracker; | |
47 | |
48 struct QuotaManagerDeleter; | |
49 | |
50 struct WEBKIT_STORAGE_EXPORT UsageAndQuota { | |
51 int64 usage; | |
52 int64 global_limited_usage; | |
53 int64 quota; | |
54 int64 available_disk_space; | |
55 | |
56 UsageAndQuota(); | |
57 UsageAndQuota(int64 usage, | |
58 int64 global_limited_usage, | |
59 int64 quota, | |
60 int64 available_disk_space); | |
61 }; | |
62 | |
63 // An interface called by QuotaTemporaryStorageEvictor. | |
64 class WEBKIT_STORAGE_EXPORT QuotaEvictionHandler { | |
65 public: | |
66 typedef base::Callback<void(const GURL&)> GetLRUOriginCallback; | |
67 typedef StatusCallback EvictOriginDataCallback; | |
68 typedef base::Callback<void(QuotaStatusCode status, | |
69 const UsageAndQuota& usage_and_quota)> | |
70 UsageAndQuotaCallback; | |
71 | |
72 // Returns the least recently used origin. It might return empty | |
73 // GURL when there are no evictable origins. | |
74 virtual void GetLRUOrigin( | |
75 StorageType type, | |
76 const GetLRUOriginCallback& callback) = 0; | |
77 | |
78 virtual void EvictOriginData( | |
79 const GURL& origin, | |
80 StorageType type, | |
81 const EvictOriginDataCallback& callback) = 0; | |
82 | |
83 virtual void GetUsageAndQuotaForEviction( | |
84 const UsageAndQuotaCallback& callback) = 0; | |
85 | |
86 protected: | |
87 virtual ~QuotaEvictionHandler() {} | |
88 }; | |
89 | |
90 struct UsageInfo { | |
91 UsageInfo(const std::string& host, StorageType type, int64 usage) | |
92 : host(host), | |
93 type(type), | |
94 usage(usage) {} | |
95 std::string host; | |
96 StorageType type; | |
97 int64 usage; | |
98 }; | |
99 | |
100 // The quota manager class. This class is instantiated per profile and | |
101 // held by the profile. With the exception of the constructor and the | |
102 // proxy() method, all methods should only be called on the IO thread. | |
103 class WEBKIT_STORAGE_EXPORT QuotaManager | |
104 : public QuotaTaskObserver, | |
105 public QuotaEvictionHandler, | |
106 public base::RefCountedThreadSafe<QuotaManager, QuotaManagerDeleter> { | |
107 public: | |
108 typedef base::Callback<void(QuotaStatusCode, | |
109 int64 /* usage */, | |
110 int64 /* quota */)> | |
111 GetUsageAndQuotaCallback; | |
112 | |
113 static const int64 kIncognitoDefaultQuotaLimit; | |
114 static const int64 kNoLimit; | |
115 | |
116 QuotaManager(bool is_incognito, | |
117 const base::FilePath& profile_path, | |
118 base::SingleThreadTaskRunner* io_thread, | |
119 base::SequencedTaskRunner* db_thread, | |
120 SpecialStoragePolicy* special_storage_policy); | |
121 | |
122 // Returns a proxy object that can be used on any thread. | |
123 QuotaManagerProxy* proxy() { return proxy_.get(); } | |
124 | |
125 // Called by clients or webapps. Returns usage per host. | |
126 void GetUsageInfo(const GetUsageInfoCallback& callback); | |
127 | |
128 // Called by Web Apps. | |
129 // This method is declared as virtual to allow test code to override it. | |
130 virtual void GetUsageAndQuotaForWebApps( | |
131 const GURL& origin, | |
132 StorageType type, | |
133 const GetUsageAndQuotaCallback& callback); | |
134 | |
135 // Called by StorageClients. | |
136 // This method is declared as virtual to allow test code to override it. | |
137 // | |
138 // For UnlimitedStorage origins, this version skips usage and quota handling | |
139 // to avoid extra query cost. | |
140 // Do not call this method for apps/user-facing code. | |
141 virtual void GetUsageAndQuota( | |
142 const GURL& origin, | |
143 StorageType type, | |
144 const GetUsageAndQuotaCallback& callback); | |
145 | |
146 // Called by clients via proxy. | |
147 // Client storage should call this method when storage is accessed. | |
148 // Used to maintain LRU ordering. | |
149 void NotifyStorageAccessed(QuotaClient::ID client_id, | |
150 const GURL& origin, | |
151 StorageType type); | |
152 | |
153 // Called by clients via proxy. | |
154 // Client storage must call this method whenever they have made any | |
155 // modifications that change the amount of data stored in their storage. | |
156 void NotifyStorageModified(QuotaClient::ID client_id, | |
157 const GURL& origin, | |
158 StorageType type, | |
159 int64 delta); | |
160 | |
161 // Used to avoid evicting origins with open pages. | |
162 // A call to NotifyOriginInUse must be balanced by a later call | |
163 // to NotifyOriginNoLongerInUse. | |
164 void NotifyOriginInUse(const GURL& origin); | |
165 void NotifyOriginNoLongerInUse(const GURL& origin); | |
166 bool IsOriginInUse(const GURL& origin) const { | |
167 return origins_in_use_.find(origin) != origins_in_use_.end(); | |
168 } | |
169 | |
170 void SetUsageCacheEnabled(QuotaClient::ID client_id, | |
171 const GURL& origin, | |
172 StorageType type, | |
173 bool enabled); | |
174 | |
175 // DeleteOriginData and DeleteHostData (surprisingly enough) delete data of a | |
176 // particular StorageType associated with either a specific origin or set of | |
177 // origins. Each method additionally requires a |quota_client_mask| which | |
178 // specifies the types of QuotaClients to delete from the origin. This is | |
179 // specified by the caller as a bitmask built from QuotaClient::IDs. Setting | |
180 // the mask to QuotaClient::kAllClientsMask will remove all clients from the | |
181 // origin, regardless of type. | |
182 virtual void DeleteOriginData(const GURL& origin, | |
183 StorageType type, | |
184 int quota_client_mask, | |
185 const StatusCallback& callback); | |
186 void DeleteHostData(const std::string& host, | |
187 StorageType type, | |
188 int quota_client_mask, | |
189 const StatusCallback& callback); | |
190 | |
191 // Called by UI and internal modules. | |
192 void GetAvailableSpace(const AvailableSpaceCallback& callback); | |
193 void GetTemporaryGlobalQuota(const QuotaCallback& callback); | |
194 | |
195 // Ok to call with NULL callback. | |
196 void SetTemporaryGlobalOverrideQuota(int64 new_quota, | |
197 const QuotaCallback& callback); | |
198 | |
199 void GetPersistentHostQuota(const std::string& host, | |
200 const QuotaCallback& callback); | |
201 void SetPersistentHostQuota(const std::string& host, | |
202 int64 new_quota, | |
203 const QuotaCallback& callback); | |
204 void GetGlobalUsage(StorageType type, const GlobalUsageCallback& callback); | |
205 void GetHostUsage(const std::string& host, StorageType type, | |
206 const UsageCallback& callback); | |
207 | |
208 void GetStatistics(std::map<std::string, std::string>* statistics); | |
209 | |
210 bool IsStorageUnlimited(const GURL& origin, StorageType type) const; | |
211 | |
212 bool CanQueryDiskSize(const GURL& origin) const { | |
213 return special_storage_policy_.get() && | |
214 special_storage_policy_->CanQueryDiskSize(origin); | |
215 } | |
216 | |
217 virtual void GetOriginsModifiedSince(StorageType type, | |
218 base::Time modified_since, | |
219 const GetOriginsCallback& callback); | |
220 | |
221 bool ResetUsageTracker(StorageType type); | |
222 | |
223 // Determines the portion of the temp pool that can be | |
224 // utilized by a single host (ie. 5 for 20%). | |
225 static const int kPerHostTemporaryPortion; | |
226 | |
227 static const char kDatabaseName[]; | |
228 | |
229 static const int64 kMinimumPreserveForSystem; | |
230 | |
231 static const int kThresholdOfErrorsToBeBlacklisted; | |
232 | |
233 static const int kEvictionIntervalInMilliSeconds; | |
234 | |
235 // This is kept non-const so that test code can change the value. | |
236 // TODO(kinuko): Make this a real const value and add a proper way to set | |
237 // the quota for syncable storage. (http://crbug.com/155488) | |
238 static int64 kSyncableStorageDefaultHostQuota; | |
239 | |
240 protected: | |
241 virtual ~QuotaManager(); | |
242 | |
243 private: | |
244 friend class base::DeleteHelper<QuotaManager>; | |
245 friend class base::RefCountedThreadSafe<QuotaManager, QuotaManagerDeleter>; | |
246 friend class MockQuotaManager; | |
247 friend class MockStorageClient; | |
248 friend class quota_internals::QuotaInternalsProxy; | |
249 friend class QuotaManagerProxy; | |
250 friend class QuotaManagerTest; | |
251 friend class QuotaTemporaryStorageEvictor; | |
252 friend struct QuotaManagerDeleter; | |
253 | |
254 class GetUsageInfoTask; | |
255 | |
256 class OriginDataDeleter; | |
257 class HostDataDeleter; | |
258 | |
259 class GetModifiedSinceHelper; | |
260 class DumpQuotaTableHelper; | |
261 class DumpOriginInfoTableHelper; | |
262 | |
263 typedef QuotaDatabase::QuotaTableEntry QuotaTableEntry; | |
264 typedef QuotaDatabase::OriginInfoTableEntry OriginInfoTableEntry; | |
265 typedef std::vector<QuotaTableEntry> QuotaTableEntries; | |
266 typedef std::vector<OriginInfoTableEntry> OriginInfoTableEntries; | |
267 | |
268 // Function pointer type used to store the function which returns the | |
269 // available disk space for the disk containing the given FilePath. | |
270 typedef int64 (*GetAvailableDiskSpaceFn)(const base::FilePath&); | |
271 | |
272 typedef base::Callback<void(const QuotaTableEntries&)> | |
273 DumpQuotaTableCallback; | |
274 typedef base::Callback<void(const OriginInfoTableEntries&)> | |
275 DumpOriginInfoTableCallback; | |
276 | |
277 struct EvictionContext { | |
278 EvictionContext(); | |
279 virtual ~EvictionContext(); | |
280 GURL evicted_origin; | |
281 StorageType evicted_type; | |
282 | |
283 EvictOriginDataCallback evict_origin_data_callback; | |
284 }; | |
285 | |
286 typedef QuotaEvictionHandler::UsageAndQuotaCallback | |
287 UsageAndQuotaDispatcherCallback; | |
288 | |
289 // This initialization method is lazily called on the IO thread | |
290 // when the first quota manager API is called. | |
291 // Initialize must be called after all quota clients are added to the | |
292 // manager by RegisterStorage. | |
293 void LazyInitialize(); | |
294 | |
295 // Called by clients via proxy. | |
296 // Registers a quota client to the manager. | |
297 // The client must remain valid until OnQuotaManagerDestored is called. | |
298 void RegisterClient(QuotaClient* client); | |
299 | |
300 UsageTracker* GetUsageTracker(StorageType type) const; | |
301 | |
302 // Extract cached origins list from the usage tracker. | |
303 // (Might return empty list if no origin is tracked by the tracker.) | |
304 void GetCachedOrigins(StorageType type, std::set<GURL>* origins); | |
305 | |
306 // These internal methods are separately defined mainly for testing. | |
307 void NotifyStorageAccessedInternal( | |
308 QuotaClient::ID client_id, | |
309 const GURL& origin, | |
310 StorageType type, | |
311 base::Time accessed_time); | |
312 void NotifyStorageModifiedInternal( | |
313 QuotaClient::ID client_id, | |
314 const GURL& origin, | |
315 StorageType type, | |
316 int64 delta, | |
317 base::Time modified_time); | |
318 | |
319 void DumpQuotaTable(const DumpQuotaTableCallback& callback); | |
320 void DumpOriginInfoTable(const DumpOriginInfoTableCallback& callback); | |
321 | |
322 // Methods for eviction logic. | |
323 void StartEviction(); | |
324 void DeleteOriginFromDatabase(const GURL& origin, StorageType type); | |
325 | |
326 void DidOriginDataEvicted(QuotaStatusCode status); | |
327 | |
328 void ReportHistogram(); | |
329 void DidGetTemporaryGlobalUsageForHistogram(int64 usage, | |
330 int64 unlimited_usage); | |
331 void DidGetPersistentGlobalUsageForHistogram(int64 usage, | |
332 int64 unlimited_usage); | |
333 | |
334 // QuotaEvictionHandler. | |
335 virtual void GetLRUOrigin( | |
336 StorageType type, | |
337 const GetLRUOriginCallback& callback) OVERRIDE; | |
338 virtual void EvictOriginData( | |
339 const GURL& origin, | |
340 StorageType type, | |
341 const EvictOriginDataCallback& callback) OVERRIDE; | |
342 virtual void GetUsageAndQuotaForEviction( | |
343 const UsageAndQuotaCallback& callback) OVERRIDE; | |
344 | |
345 void DidSetTemporaryGlobalOverrideQuota(const QuotaCallback& callback, | |
346 const int64* new_quota, | |
347 bool success); | |
348 void DidGetPersistentHostQuota(const std::string& host, | |
349 const int64* quota, | |
350 bool success); | |
351 void DidSetPersistentHostQuota(const std::string& host, | |
352 const QuotaCallback& callback, | |
353 const int64* new_quota, | |
354 bool success); | |
355 void DidInitialize(int64* temporary_quota_override, | |
356 int64* desired_available_space, | |
357 bool success); | |
358 void DidGetLRUOrigin(const GURL* origin, | |
359 bool success); | |
360 void DidGetInitialTemporaryGlobalQuota(QuotaStatusCode status, | |
361 int64 quota_unused); | |
362 void DidInitializeTemporaryOriginsInfo(bool success); | |
363 void DidGetAvailableSpace(int64 space); | |
364 void DidDatabaseWork(bool success); | |
365 | |
366 void DeleteOnCorrectThread() const; | |
367 | |
368 void PostTaskAndReplyWithResultForDBThread( | |
369 const tracked_objects::Location& from_here, | |
370 const base::Callback<bool(QuotaDatabase*)>& task, | |
371 const base::Callback<void(bool)>& reply); | |
372 | |
373 const bool is_incognito_; | |
374 const base::FilePath profile_path_; | |
375 | |
376 scoped_refptr<QuotaManagerProxy> proxy_; | |
377 bool db_disabled_; | |
378 bool eviction_disabled_; | |
379 scoped_refptr<base::SingleThreadTaskRunner> io_thread_; | |
380 scoped_refptr<base::SequencedTaskRunner> db_thread_; | |
381 mutable scoped_ptr<QuotaDatabase> database_; | |
382 | |
383 GetLRUOriginCallback lru_origin_callback_; | |
384 std::set<GURL> access_notified_origins_; | |
385 | |
386 QuotaClientList clients_; | |
387 | |
388 scoped_ptr<UsageTracker> temporary_usage_tracker_; | |
389 scoped_ptr<UsageTracker> persistent_usage_tracker_; | |
390 scoped_ptr<UsageTracker> syncable_usage_tracker_; | |
391 // TODO(michaeln): Need a way to clear the cache, drop and | |
392 // reinstantiate the trackers when they're not handling requests. | |
393 | |
394 scoped_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_; | |
395 EvictionContext eviction_context_; | |
396 | |
397 ClosureQueue db_initialization_callbacks_; | |
398 AvailableSpaceCallbackQueue available_space_callbacks_; | |
399 GlobalQuotaCallbackQueue temporary_global_quota_callbacks_; | |
400 HostQuotaCallbackMap persistent_host_quota_callbacks_; | |
401 | |
402 bool temporary_quota_initialized_; | |
403 int64 temporary_quota_override_; | |
404 | |
405 int64 desired_available_space_; | |
406 | |
407 // Map from origin to count. | |
408 std::map<GURL, int> origins_in_use_; | |
409 // Map from origin to error count. | |
410 std::map<GURL, int> origins_in_error_; | |
411 | |
412 scoped_refptr<SpecialStoragePolicy> special_storage_policy_; | |
413 | |
414 base::WeakPtrFactory<QuotaManager> weak_factory_; | |
415 base::RepeatingTimer<QuotaManager> histogram_timer_; | |
416 | |
417 // Pointer to the function used to get the available disk space. This is | |
418 // overwritten by QuotaManagerTest in order to attain a deterministic reported | |
419 // value. The default value points to base::SysInfo::AmountOfFreeDiskSpace. | |
420 GetAvailableDiskSpaceFn get_disk_space_fn_; | |
421 | |
422 DISALLOW_COPY_AND_ASSIGN(QuotaManager); | |
423 }; | |
424 | |
425 struct QuotaManagerDeleter { | |
426 static void Destruct(const QuotaManager* manager) { | |
427 manager->DeleteOnCorrectThread(); | |
428 } | |
429 }; | |
430 | |
431 // The proxy may be called and finally released on any thread. | |
432 class WEBKIT_STORAGE_EXPORT QuotaManagerProxy | |
433 : public base::RefCountedThreadSafe<QuotaManagerProxy> { | |
434 public: | |
435 virtual void RegisterClient(QuotaClient* client); | |
436 virtual void NotifyStorageAccessed(QuotaClient::ID client_id, | |
437 const GURL& origin, | |
438 StorageType type); | |
439 virtual void NotifyStorageModified(QuotaClient::ID client_id, | |
440 const GURL& origin, | |
441 StorageType type, | |
442 int64 delta); | |
443 virtual void NotifyOriginInUse(const GURL& origin); | |
444 virtual void NotifyOriginNoLongerInUse(const GURL& origin); | |
445 | |
446 virtual void SetUsageCacheEnabled(QuotaClient::ID client_id, | |
447 const GURL& origin, | |
448 StorageType type, | |
449 bool enabled); | |
450 | |
451 // This method may only be called on the IO thread. | |
452 // It may return NULL if the manager has already been deleted. | |
453 QuotaManager* quota_manager() const; | |
454 | |
455 protected: | |
456 friend class QuotaManager; | |
457 friend class base::RefCountedThreadSafe<QuotaManagerProxy>; | |
458 | |
459 QuotaManagerProxy(QuotaManager* manager, | |
460 base::SingleThreadTaskRunner* io_thread); | |
461 virtual ~QuotaManagerProxy(); | |
462 | |
463 QuotaManager* manager_; // only accessed on the io thread | |
464 scoped_refptr<base::SingleThreadTaskRunner> io_thread_; | |
465 | |
466 DISALLOW_COPY_AND_ASSIGN(QuotaManagerProxy); | |
467 }; | |
468 | |
469 } // namespace quota | |
470 | |
471 #endif // WEBKIT_QUOTA_QUOTA_MANAGER_H_ | |
OLD | NEW |