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 CONTENT_BROWSER_APPCACHE_APPCACHE_STORAGE_IMPL_H_
6#define CONTENT_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/ref_counted.h"
17#include "base/memory/weak_ptr.h"
18#include "content/browser/appcache/appcache_database.h"
19#include "content/browser/appcache/appcache_disk_cache.h"
20#include "content/browser/appcache/appcache_storage.h"
21#include "content/common/content_export.h"
22
23namespace base {
24class SingleThreadTaskRunner;
25}  // namespace base
26
27namespace content {
28class AppCacheStorageImplTest;
29class ChromeAppCacheServiceTest;
30
31class AppCacheStorageImpl : public AppCacheStorage {
32 public:
33  explicit AppCacheStorageImpl(AppCacheServiceImpl* service);
34  virtual ~AppCacheStorageImpl();
35
36  void Initialize(
37      const base::FilePath& cache_directory,
38      const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
39      const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread);
40  void Disable();
41  bool is_disabled() const { return is_disabled_; }
42
43  // AppCacheStorage methods, see the base class for doc comments.
44  virtual void GetAllInfo(Delegate* delegate) OVERRIDE;
45  virtual void LoadCache(int64 id, Delegate* delegate) OVERRIDE;
46  virtual void LoadOrCreateGroup(const GURL& manifest_url,
47                                 Delegate* delegate) OVERRIDE;
48  virtual void StoreGroupAndNewestCache(AppCacheGroup* group,
49                                        AppCache* newest_cache,
50                                        Delegate* delegate) OVERRIDE;
51  virtual void FindResponseForMainRequest(const GURL& url,
52                                          const GURL& preferred_manifest_url,
53                                          Delegate* delegate) OVERRIDE;
54  virtual void FindResponseForSubRequest(
55      AppCache* cache, const GURL& url,
56      AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
57      bool* found_network_namespace) OVERRIDE;
58  virtual void MarkEntryAsForeign(const GURL& entry_url,
59                                  int64 cache_id) OVERRIDE;
60  virtual void MakeGroupObsolete(AppCacheGroup* group,
61                                 Delegate* delegate,
62                                 int response_code) OVERRIDE;
63  virtual AppCacheResponseReader* CreateResponseReader(
64      const GURL& manifest_url, int64 group_id, int64 response_id) OVERRIDE;
65  virtual AppCacheResponseWriter* CreateResponseWriter(
66      const GURL& manifest_url, int64 group_id) OVERRIDE;
67  virtual void DoomResponses(const GURL& manifest_url,
68                             const std::vector<int64>& response_ids) OVERRIDE;
69  virtual void DeleteResponses(const GURL& manifest_url,
70                               const std::vector<int64>& response_ids) OVERRIDE;
71
72 private:
73  // The AppCacheStorageImpl class methods and datamembers may only be
74  // accessed on the IO thread. This class manufactures seperate DatabaseTasks
75  // which access the DB on a seperate background thread.
76  class DatabaseTask;
77  class InitTask;
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 DeleteAndStartOver();
118  void DeleteAndStartOverPart2();
119  void CallScheduleReinitialize();
120
121  // Sometimes we can respond without having to query the database.
122  bool FindResponseForMainRequestInGroup(
123      AppCacheGroup* group,  const GURL& url, Delegate* delegate);
124  void DeliverShortCircuitedFindMainResponse(
125      const GURL& url,
126      const AppCacheEntry& found_entry,
127      scoped_refptr<AppCacheGroup> group,
128      scoped_refptr<AppCache> newest_cache,
129      scoped_refptr<DelegateReference> delegate_ref);
130
131  void CallOnMainResponseFound(
132      DelegateReferenceVector* delegates,
133      const GURL& url, const AppCacheEntry& entry,
134      const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry,
135      int64 cache_id, int64 group_id, const GURL& manifest_url);
136
137  CONTENT_EXPORT AppCacheDiskCache* disk_cache();
138
139  // The directory in which we place files in the file system.
140  base::FilePath cache_directory_;
141  bool is_incognito_;
142
143  // This class operates primarily on the IO thread, but schedules
144  // its DatabaseTasks on the db thread. Separately, the disk_cache uses
145  // the cache thread.
146  scoped_refptr<base::SingleThreadTaskRunner> db_thread_;
147  scoped_refptr<base::SingleThreadTaskRunner> cache_thread_;
148
149  // Structures to keep track of DatabaseTasks that are in-flight.
150  DatabaseTaskQueue scheduled_database_tasks_;
151  PendingCacheLoads pending_cache_loads_;
152  PendingGroupLoads pending_group_loads_;
153  PendingForeignMarkings pending_foreign_markings_;
154  PendingQuotaQueries pending_quota_queries_;
155
156  // Structures to keep track of lazy response deletion.
157  std::deque<int64> deletable_response_ids_;
158  std::vector<int64> deleted_response_ids_;
159  bool is_response_deletion_scheduled_;
160  bool did_start_deleting_responses_;
161  int64 last_deletable_response_rowid_;
162
163  // Created on the IO thread, but only used on the DB thread.
164  AppCacheDatabase* database_;
165
166  // Set if we discover a fatal error like a corrupt SQL database or
167  // disk cache and cannot continue.
168  bool is_disabled_;
169
170  scoped_ptr<AppCacheDiskCache> disk_cache_;
171
172  // Used to short-circuit certain operations without having to schedule
173  // any tasks on the background database thread.
174  std::deque<base::Closure> pending_simple_tasks_;
175  base::WeakPtrFactory<AppCacheStorageImpl> weak_factory_;
176
177  friend class content::AppCacheStorageImplTest;
178  friend class content::ChromeAppCacheServiceTest;
179};
180
181}  // namespace content
182
183#endif  // CONTENT_BROWSER_APPCACHE_APPCACHE_STORAGE_IMPL_H_
184