• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 STORAGE_BROWSER_DATABASE_DATABASE_TRACKER_H_
6 #define STORAGE_BROWSER_DATABASE_DATABASE_TRACKER_H_
7 
8 #include <map>
9 #include <set>
10 #include <utility>
11 
12 #include "base/files/file.h"
13 #include "base/files/file_path.h"
14 #include "base/gtest_prod_util.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/observer_list.h"
18 #include "base/strings/string16.h"
19 #include "base/strings/string_util.h"
20 #include "base/time/time.h"
21 #include "net/base/completion_callback.h"
22 #include "storage/browser/storage_browser_export.h"
23 #include "storage/common/database/database_connections.h"
24 
25 namespace base {
26 class MessageLoopProxy;
27 }
28 
29 namespace content {
30 class DatabaseTracker_TestHelper_Test;
31 class MockDatabaseTracker;
32 }
33 
34 namespace sql {
35 class Connection;
36 class MetaTable;
37 }
38 
39 namespace storage {
40 class QuotaManagerProxy;
41 class SpecialStoragePolicy;
42 }
43 
44 namespace storage {
45 
46 STORAGE_EXPORT extern const base::FilePath::CharType
47     kDatabaseDirectoryName[];
48 STORAGE_EXPORT extern const base::FilePath::CharType
49     kTrackerDatabaseFileName[];
50 
51 class DatabasesTable;
52 
53 // This class is used to store information about all databases in an origin.
54 class STORAGE_EXPORT OriginInfo {
55  public:
56   OriginInfo();
57   OriginInfo(const OriginInfo& origin_info);
58   ~OriginInfo();
59 
GetOriginIdentifier()60   const std::string& GetOriginIdentifier() const { return origin_identifier_; }
TotalSize()61   int64 TotalSize() const { return total_size_; }
62   void GetAllDatabaseNames(std::vector<base::string16>* databases) const;
63   int64 GetDatabaseSize(const base::string16& database_name) const;
64   base::string16 GetDatabaseDescription(
65       const base::string16& database_name) const;
66 
67  protected:
68   typedef std::map<base::string16, std::pair<int64, base::string16> >
69       DatabaseInfoMap;
70 
71   OriginInfo(const std::string& origin_identifier, int64 total_size);
72 
73   std::string origin_identifier_;
74   int64 total_size_;
75   DatabaseInfoMap database_info_;
76 };
77 
78 // This class manages the main database and keeps track of open databases.
79 //
80 // The data in this class is not thread-safe, so all methods of this class
81 // should be called on the same thread. The only exceptions are the ctor(),
82 // the dtor() and the database_directory() and quota_manager_proxy() getters.
83 //
84 // Furthermore, some methods of this class have to read/write data from/to
85 // the disk. Therefore, in a multi-threaded application, all methods of this
86 // class should be called on the thread dedicated to file operations (file
87 // thread in the browser process, for example), if such a thread exists.
88 class STORAGE_EXPORT DatabaseTracker
89     : public base::RefCountedThreadSafe<DatabaseTracker> {
90  public:
91   class Observer {
92    public:
93     virtual void OnDatabaseSizeChanged(const std::string& origin_identifier,
94                                        const base::string16& database_name,
95                                        int64 database_size) = 0;
96     virtual void OnDatabaseScheduledForDeletion(
97         const std::string& origin_identifier,
98         const base::string16& database_name) = 0;
99 
100    protected:
~Observer()101     virtual ~Observer() {}
102   };
103 
104   DatabaseTracker(const base::FilePath& profile_path,
105                   bool is_incognito,
106                   storage::SpecialStoragePolicy* special_storage_policy,
107                   storage::QuotaManagerProxy* quota_manager_proxy,
108                   base::MessageLoopProxy* db_tracker_thread);
109 
110   void DatabaseOpened(const std::string& origin_identifier,
111                       const base::string16& database_name,
112                       const base::string16& database_details,
113                       int64 estimated_size,
114                       int64* database_size);
115   void DatabaseModified(const std::string& origin_identifier,
116                         const base::string16& database_name);
117   void DatabaseClosed(const std::string& origin_identifier,
118                       const base::string16& database_name);
119   void HandleSqliteError(const std::string& origin_identifier,
120                          const base::string16& database_name,
121                          int error);
122 
123   void CloseDatabases(const DatabaseConnections& connections);
124 
125   void AddObserver(Observer* observer);
126   void RemoveObserver(Observer* observer);
127 
128   void CloseTrackerDatabaseAndClearCaches();
129 
DatabaseDirectory()130   const base::FilePath& DatabaseDirectory() const { return db_dir_; }
131   base::FilePath GetFullDBFilePath(const std::string& origin_identifier,
132                                    const base::string16& database_name);
133 
134   // virtual for unit-testing only
135   virtual bool GetOriginInfo(const std::string& origin_id, OriginInfo* info);
136   virtual bool GetAllOriginIdentifiers(std::vector<std::string>* origin_ids);
137   virtual bool GetAllOriginsInfo(std::vector<OriginInfo>* origins_info);
138 
139   // Safe to call on any thread.
quota_manager_proxy()140   storage::QuotaManagerProxy* quota_manager_proxy() const {
141     return quota_manager_proxy_.get();
142   }
143 
144   bool IsDatabaseScheduledForDeletion(const std::string& origin_identifier,
145                                       const base::string16& database_name);
146 
147   // Deletes a single database. Returns net::OK on success, net::FAILED on
148   // failure, or net::ERR_IO_PENDING and |callback| is invoked upon completion,
149   // if non-NULL.
150   int DeleteDatabase(const std::string& origin_identifier,
151                      const base::string16& database_name,
152                      const net::CompletionCallback& callback);
153 
154   // Delete any databases that have been touched since the cutoff date that's
155   // supplied, omitting any that match IDs within |protected_origins|.
156   // Returns net::OK on success, net::FAILED if not all databases could be
157   // deleted, and net::ERR_IO_PENDING and |callback| is invoked upon completion,
158   // if non-NULL. Protected origins, according the the SpecialStoragePolicy,
159   // are not deleted by this method.
160   int DeleteDataModifiedSince(const base::Time& cutoff,
161                               const net::CompletionCallback& callback);
162 
163   // Delete all databases that belong to the given origin. Returns net::OK on
164   // success, net::FAILED if not all databases could be deleted, and
165   // net::ERR_IO_PENDING and |callback| is invoked upon completion, if non-NULL.
166   // virtual for unit testing only
167   virtual int DeleteDataForOrigin(const std::string& origin_identifier,
168                                   const net::CompletionCallback& callback);
169 
IsIncognitoProfile()170   bool IsIncognitoProfile() const { return is_incognito_; }
171 
172   const base::File* GetIncognitoFile(const base::string16& vfs_file_path) const;
173   const base::File* SaveIncognitoFile(const base::string16& vfs_file_path,
174                                       base::File file);
175   void CloseIncognitoFileHandle(const base::string16& vfs_file_path);
176   bool HasSavedIncognitoFileHandle(const base::string16& vfs_file_path) const;
177 
178   // Shutdown the database tracker, deleting database files if the tracker is
179   // used for an incognito profile.
180   void Shutdown();
181   // Disables the exit-time deletion of session-only data.
182   void SetForceKeepSessionState();
183 
184  private:
185   friend class base::RefCountedThreadSafe<DatabaseTracker>;
186   friend class content::DatabaseTracker_TestHelper_Test;
187   friend class content::MockDatabaseTracker; // for testing
188 
189   typedef std::map<std::string, std::set<base::string16> > DatabaseSet;
190   typedef std::vector<std::pair<net::CompletionCallback, DatabaseSet> >
191       PendingDeletionCallbacks;
192   typedef std::map<base::string16, base::File*> FileHandlesMap;
193   typedef std::map<std::string, base::string16> OriginDirectoriesMap;
194 
195   class CachedOriginInfo : public OriginInfo {
196    public:
CachedOriginInfo()197     CachedOriginInfo() : OriginInfo(std::string(), 0) {}
SetOriginIdentifier(const std::string & origin_identifier)198     void SetOriginIdentifier(const std::string& origin_identifier) {
199       origin_identifier_ = origin_identifier;
200     }
SetDatabaseSize(const base::string16 & database_name,int64 new_size)201     void SetDatabaseSize(const base::string16& database_name, int64 new_size) {
202       int64 old_size = 0;
203       if (database_info_.find(database_name) != database_info_.end())
204         old_size = database_info_[database_name].first;
205       database_info_[database_name].first = new_size;
206       if (new_size != old_size)
207         total_size_ += new_size - old_size;
208     }
SetDatabaseDescription(const base::string16 & database_name,const base::string16 & description)209     void SetDatabaseDescription(const base::string16& database_name,
210                                 const base::string16& description) {
211       database_info_[database_name].second = description;
212     }
213   };
214 
215   // virtual for unit-testing only.
216   virtual ~DatabaseTracker();
217 
218   // Deletes the directory that stores all DBs in incognito mode, if it exists.
219   void DeleteIncognitoDBDirectory();
220 
221   // Deletes session-only databases. Blocks databases from being created/opened.
222   void ClearSessionOnlyOrigins();
223 
224   bool DeleteClosedDatabase(const std::string& origin_identifier,
225                             const base::string16& database_name);
226 
227   // Delete all files belonging to the given origin given that no database
228   // connections within this origin are open, or if |force| is true, delete
229   // the meta data and rename the associated directory.
230   bool DeleteOrigin(const std::string& origin_identifier, bool force);
231   void DeleteDatabaseIfNeeded(const std::string& origin_identifier,
232                               const base::string16& database_name);
233 
234   bool LazyInit();
235   bool UpgradeToCurrentVersion();
236   void InsertOrUpdateDatabaseDetails(const std::string& origin_identifier,
237                                      const base::string16& database_name,
238                                      const base::string16& database_details,
239                                      int64 estimated_size);
240 
241   void ClearAllCachedOriginInfo();
242   CachedOriginInfo* MaybeGetCachedOriginInfo(
243       const std::string& origin_identifier,
244       bool create_if_needed);
GetCachedOriginInfo(const std::string & origin_identifier)245   CachedOriginInfo* GetCachedOriginInfo(
246       const std::string& origin_identifier) {
247     return MaybeGetCachedOriginInfo(origin_identifier, true);
248   }
249 
250   int64 GetDBFileSize(const std::string& origin_identifier,
251                       const base::string16& database_name);
252   int64 SeedOpenDatabaseInfo(const std::string& origin_identifier,
253                              const base::string16& database_name,
254                              const base::string16& description);
255   int64 UpdateOpenDatabaseInfoAndNotify(const std::string& origin_identifier,
256                                         const base::string16& database_name,
257                                         const base::string16* opt_description);
UpdateOpenDatabaseSizeAndNotify(const std::string & origin_identifier,const base::string16 & database_name)258   int64 UpdateOpenDatabaseSizeAndNotify(const std::string& origin_identifier,
259                                         const base::string16& database_name) {
260     return UpdateOpenDatabaseInfoAndNotify(
261         origin_identifier, database_name, NULL);
262   }
263 
264 
265   void ScheduleDatabaseForDeletion(const std::string& origin_identifier,
266                                    const base::string16& database_name);
267   // Schedule a set of open databases for deletion. If non-null, callback is
268   // invoked upon completion.
269   void ScheduleDatabasesForDeletion(const DatabaseSet& databases,
270                                     const net::CompletionCallback& callback);
271 
272   // Returns the directory where all DB files for the given origin are stored.
273   base::string16 GetOriginDirectory(const std::string& origin_identifier);
274 
275   bool is_initialized_;
276   const bool is_incognito_;
277   bool force_keep_session_state_;
278   bool shutting_down_;
279   const base::FilePath profile_path_;
280   const base::FilePath db_dir_;
281   scoped_ptr<sql::Connection> db_;
282   scoped_ptr<DatabasesTable> databases_table_;
283   scoped_ptr<sql::MetaTable> meta_table_;
284   ObserverList<Observer, true> observers_;
285   std::map<std::string, CachedOriginInfo> origins_info_map_;
286   DatabaseConnections database_connections_;
287 
288   // The set of databases that should be deleted but are still opened
289   DatabaseSet dbs_to_be_deleted_;
290   PendingDeletionCallbacks deletion_callbacks_;
291 
292   // Apps and Extensions can have special rights.
293   scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
294 
295   scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
296 
297   // The database tracker thread we're supposed to run file IO on.
298   scoped_refptr<base::MessageLoopProxy> db_tracker_thread_;
299 
300   // When in incognito mode, store a DELETE_ON_CLOSE handle to each
301   // main DB and journal file that was accessed. When the incognito profile
302   // goes away (or when the browser crashes), all these handles will be
303   // closed, and the files will be deleted.
304   FileHandlesMap incognito_file_handles_;
305 
306   // In a non-incognito profile, all DBs in an origin are stored in a directory
307   // named after the origin. In an incognito profile though, we do not want the
308   // directory structure to reveal the origins visited by the user (in case the
309   // browser process crashes and those directories are not deleted). So we use
310   // this map to assign directory names that do not reveal this information.
311   OriginDirectoriesMap incognito_origin_directories_;
312   int incognito_origin_directories_generator_;
313 
314   FRIEND_TEST_ALL_PREFIXES(DatabaseTracker, TestHelper);
315 };
316 
317 }  // namespace storage
318 
319 #endif  // STORAGE_BROWSER_DATABASE_DATABASE_TRACKER_H_
320