Home | History | Annotate | Download | only in database
      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 
     60   const std::string& GetOriginIdentifier() const { return origin_identifier_; }
     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:
    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 
    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.
    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 
    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:
    197     CachedOriginInfo() : OriginInfo(std::string(), 0) {}
    198     void SetOriginIdentifier(const std::string& origin_identifier) {
    199       origin_identifier_ = origin_identifier;
    200     }
    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     }
    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);
    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);
    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