1// Copyright (c) 2011 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_BROWSER_APPCACHE_APPCACHE_STORAGE_IMPL_H_
6#define WEBKIT_BROWSER_APPCACHE_APPCACHE_STORAGE_IMPL_H_
7
8#include <deque>
9#include <map>
10#include <set>
11#include <utility>
12#include <vector>
13
14#include "base/callback.h"
15#include "base/files/file_path.h"
16#include "base/memory/weak_ptr.h"
17#include "base/message_loop/message_loop_proxy.h"
18#include "webkit/browser/appcache/appcache_database.h"
19#include "webkit/browser/appcache/appcache_disk_cache.h"
20#include "webkit/browser/appcache/appcache_storage.h"
21#include "webkit/browser/webkit_storage_browser_export.h"
22
23namespace content {
24class ChromeAppCacheServiceTest;
25}
26
27namespace appcache {
28
29class AppCacheStorageImpl : public AppCacheStorage {
30 public:
31  explicit AppCacheStorageImpl(AppCacheService* service);
32  virtual ~AppCacheStorageImpl();
33
34  void Initialize(const base::FilePath& cache_directory,
35                  base::MessageLoopProxy* db_thread,
36                  base::MessageLoopProxy* cache_thread);
37  void Disable();
38  bool is_disabled() const { return is_disabled_; }
39
40  // AppCacheStorage methods, see the base class for doc comments.
41  virtual void GetAllInfo(Delegate* delegate) OVERRIDE;
42  virtual void LoadCache(int64 id, Delegate* delegate) OVERRIDE;
43  virtual void LoadOrCreateGroup(const GURL& manifest_url,
44                                 Delegate* delegate) OVERRIDE;
45  virtual void StoreGroupAndNewestCache(AppCacheGroup* group,
46                                        AppCache* newest_cache,
47                                        Delegate* delegate) OVERRIDE;
48  virtual void FindResponseForMainRequest(const GURL& url,
49                                          const GURL& preferred_manifest_url,
50                                          Delegate* delegate) OVERRIDE;
51  virtual void FindResponseForSubRequest(
52      AppCache* cache, const GURL& url,
53      AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
54      bool* found_network_namespace) OVERRIDE;
55  virtual void MarkEntryAsForeign(const GURL& entry_url,
56                                  int64 cache_id) OVERRIDE;
57  virtual void MakeGroupObsolete(AppCacheGroup* group,
58                                 Delegate* delegate) OVERRIDE;
59  virtual AppCacheResponseReader* CreateResponseReader(
60      const GURL& manifest_url, int64 group_id, int64 response_id) OVERRIDE;
61  virtual AppCacheResponseWriter* CreateResponseWriter(
62      const GURL& manifest_url, int64 group_id) OVERRIDE;
63  virtual void DoomResponses(const GURL& manifest_url,
64                             const std::vector<int64>& response_ids) OVERRIDE;
65  virtual void DeleteResponses(const GURL& manifest_url,
66                               const std::vector<int64>& response_ids) OVERRIDE;
67  virtual void PurgeMemory() OVERRIDE;
68
69 private:
70  friend class AppCacheStorageImplTest;
71
72  // The AppCacheStorageImpl class methods and datamembers may only be
73  // accessed on the IO thread. This class manufactures seperate DatabaseTasks
74  // which access the DB on a seperate background thread.
75  class DatabaseTask;
76  class InitTask;
77  class CloseConnectionTask;
78  class DisableDatabaseTask;
79  class GetAllInfoTask;
80  class StoreOrLoadTask;
81  class CacheLoadTask;
82  class GroupLoadTask;
83  class StoreGroupAndCacheTask;
84  class FindMainResponseTask;
85  class MarkEntryAsForeignTask;
86  class MakeGroupObsoleteTask;
87  class GetDeletableResponseIdsTask;
88  class InsertDeletableResponseIdsTask;
89  class DeleteDeletableResponseIdsTask;
90  class UpdateGroupLastAccessTimeTask;
91
92  typedef std::deque<DatabaseTask*> DatabaseTaskQueue;
93  typedef std::map<int64, CacheLoadTask*> PendingCacheLoads;
94  typedef std::map<GURL, GroupLoadTask*> PendingGroupLoads;
95  typedef std::deque<std::pair<GURL, int64> > PendingForeignMarkings;
96  typedef std::set<StoreGroupAndCacheTask*> PendingQuotaQueries;
97
98  bool IsInitTaskComplete() {
99    return last_cache_id_ != AppCacheStorage::kUnitializedId;
100  }
101
102  CacheLoadTask* GetPendingCacheLoadTask(int64 cache_id);
103  GroupLoadTask* GetPendingGroupLoadTask(const GURL& manifest_url);
104  void GetPendingForeignMarkingsForCache(
105      int64 cache_id, std::vector<GURL>* urls);
106
107  void ScheduleSimpleTask(const base::Closure& task);
108  void RunOnePendingSimpleTask();
109
110  void DelayedStartDeletingUnusedResponses();
111  void StartDeletingResponses(const std::vector<int64>& response_ids);
112  void ScheduleDeleteOneResponse();
113  void DeleteOneResponse();
114
115  void OnDeletedOneResponse(int rv);
116  void OnDiskCacheInitialized(int rv);
117  void CallReinitialize();
118
119  // Sometimes we can respond without having to query the database.
120  bool FindResponseForMainRequestInGroup(
121      AppCacheGroup* group,  const GURL& url, Delegate* delegate);
122  void DeliverShortCircuitedFindMainResponse(
123      const GURL& url,
124      const AppCacheEntry& found_entry,
125      scoped_refptr<AppCacheGroup> group,
126      scoped_refptr<AppCache> newest_cache,
127      scoped_refptr<DelegateReference> delegate_ref);
128
129  void CallOnMainResponseFound(
130      DelegateReferenceVector* delegates,
131      const GURL& url, const AppCacheEntry& entry,
132      const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry,
133      int64 cache_id, int64 group_id, const GURL& manifest_url);
134
135  WEBKIT_STORAGE_BROWSER_EXPORT AppCacheDiskCache* disk_cache();
136
137  // The directory in which we place files in the file system.
138  base::FilePath cache_directory_;
139  bool is_incognito_;
140
141  // This class operates primarily on the IO thread, but schedules
142  // its DatabaseTasks on the db thread. Separately, the disk_cache uses
143  // the cache_thread.
144  scoped_refptr<base::MessageLoopProxy> db_thread_;
145  scoped_refptr<base::MessageLoopProxy> cache_thread_;
146
147  // Structures to keep track of DatabaseTasks that are in-flight.
148  DatabaseTaskQueue scheduled_database_tasks_;
149  PendingCacheLoads pending_cache_loads_;
150  PendingGroupLoads pending_group_loads_;
151  PendingForeignMarkings pending_foreign_markings_;
152  PendingQuotaQueries pending_quota_queries_;
153
154  // Structures to keep track of lazy response deletion.
155  std::deque<int64> deletable_response_ids_;
156  std::vector<int64> deleted_response_ids_;
157  bool is_response_deletion_scheduled_;
158  bool did_start_deleting_responses_;
159  int64 last_deletable_response_rowid_;
160
161  // Created on the IO thread, but only used on the DB thread.
162  AppCacheDatabase* database_;
163
164  // Set if we discover a fatal error like a corrupt SQL database or
165  // disk cache and cannot continue.
166  bool is_disabled_;
167
168  scoped_ptr<AppCacheDiskCache> disk_cache_;
169
170  // Used to short-circuit certain operations without having to schedule
171  // any tasks on the background database thread.
172  std::deque<base::Closure> pending_simple_tasks_;
173  base::WeakPtrFactory<AppCacheStorageImpl> weak_factory_;
174
175  friend class content::ChromeAppCacheServiceTest;
176};
177
178}  // namespace appcache
179
180#endif  // WEBKIT_BROWSER_APPCACHE_APPCACHE_STORAGE_IMPL_H_
181