1 // Copyright (c) 2014 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_INDEXED_DB_INDEXED_DB_FACTORY_IMPL_H_ 6 #define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_FACTORY_IMPL_H_ 7 8 #include <stddef.h> 9 10 #include <memory> 11 #include <set> 12 #include <tuple> 13 #include <utility> 14 #include <vector> 15 16 #include "base/callback.h" 17 #include "base/containers/flat_map.h" 18 #include "base/gtest_prod_util.h" 19 #include "base/macros.h" 20 #include "base/memory/weak_ptr.h" 21 #include "base/sequence_checker.h" 22 #include "base/strings/string16.h" 23 #include "base/time/clock.h" 24 #include "base/time/time.h" 25 #include "base/trace_event/memory_dump_provider.h" 26 #include "components/services/storage/indexed_db/scopes/leveldb_scopes_factory.h" 27 #include "components/services/storage/public/mojom/native_file_system_context.mojom-forward.h" 28 #include "content/browser/indexed_db/indexed_db_backing_store.h" 29 #include "content/browser/indexed_db/indexed_db_data_loss_info.h" 30 #include "content/browser/indexed_db/indexed_db_database_error.h" 31 #include "content/browser/indexed_db/indexed_db_factory.h" 32 #include "content/browser/indexed_db/indexed_db_origin_state_handle.h" 33 #include "content/browser/indexed_db/indexed_db_task_helper.h" 34 #include "storage/browser/blob/mojom/blob_storage_context.mojom-forward.h" 35 #include "third_party/leveldatabase/src/include/leveldb/status.h" 36 #include "url/origin.h" 37 38 namespace base { 39 class FilePath; 40 class SequencedTaskRunner; 41 } 42 namespace url { 43 class Origin; 44 } 45 46 namespace content { 47 class TransactionalLevelDBFactory; 48 class TransactionalLevelDBDatabase; 49 class IndexedDBClassFactory; 50 class IndexedDBContextImpl; 51 class IndexedDBFactoryImpl; 52 class IndexedDBOriginState; 53 54 class CONTENT_EXPORT IndexedDBFactoryImpl 55 : public IndexedDBFactory, 56 base::trace_event::MemoryDumpProvider { 57 public: 58 IndexedDBFactoryImpl(IndexedDBContextImpl* context, 59 IndexedDBClassFactory* indexed_db_class_factory, 60 base::Clock* clock); 61 ~IndexedDBFactoryImpl() override; 62 63 // content::IndexedDBFactory overrides: 64 void GetDatabaseInfo(scoped_refptr<IndexedDBCallbacks> callbacks, 65 const url::Origin& origin, 66 const base::FilePath& data_directory) override; 67 void GetDatabaseNames(scoped_refptr<IndexedDBCallbacks> callbacks, 68 const url::Origin& origin, 69 const base::FilePath& data_directory) override; 70 void Open(const base::string16& name, 71 std::unique_ptr<IndexedDBPendingConnection> connection, 72 const url::Origin& origin, 73 const base::FilePath& data_directory) override; 74 75 void DeleteDatabase(const base::string16& name, 76 scoped_refptr<IndexedDBCallbacks> callbacks, 77 const url::Origin& origin, 78 const base::FilePath& data_directory, 79 bool force_close) override; 80 81 void AbortTransactionsAndCompactDatabase( 82 base::OnceCallback<void(leveldb::Status)> callback, 83 const url::Origin& origin) override; 84 void AbortTransactionsForDatabase( 85 base::OnceCallback<void(leveldb::Status)> callback, 86 const url::Origin& origin) override; 87 88 void HandleBackingStoreFailure(const url::Origin& origin) override; 89 void HandleBackingStoreCorruption( 90 const url::Origin& origin, 91 const IndexedDBDatabaseError& error) override; 92 93 std::vector<IndexedDBDatabase*> GetOpenDatabasesForOrigin( 94 const url::Origin& origin) const override; 95 96 // TODO(dmurph): This eventually needs to be async, to support scopes 97 // multithreading. 98 void ForceClose(const url::Origin& origin, 99 bool delete_in_memory_store) override; 100 101 void ForceSchemaDowngrade(const url::Origin& origin) override; 102 V2SchemaCorruptionStatus HasV2SchemaCorruption( 103 const url::Origin& origin) override; 104 105 // Called by the IndexedDBContext destructor so the factory can do cleanup. 106 void ContextDestroyed() override; 107 108 // Called by the IndexedDBActiveBlobRegistry. 109 void ReportOutstandingBlobs(const url::Origin& origin, 110 bool blobs_outstanding) override; 111 112 // Called by IndexedDBBackingStore when blob files have been cleaned. 113 void BlobFilesCleaned(const url::Origin& origin) override; 114 115 size_t GetConnectionCount(const url::Origin& origin) const override; 116 117 void NotifyIndexedDBContentChanged( 118 const url::Origin& origin, 119 const base::string16& database_name, 120 const base::string16& object_store_name) override; 121 122 int64_t GetInMemoryDBSize(const url::Origin& origin) const override; 123 124 base::Time GetLastModified(const url::Origin& origin) const override; 125 126 std::vector<url::Origin> GetOpenOrigins() const; 127 128 IndexedDBOriginState* GetOriginFactory(const url::Origin& origin) const; 129 130 // On an OK status, the factory handle is populated. Otherwise (when status is 131 // not OK), the |IndexedDBDatabaseError| will be populated. If the status was 132 // corruption, the |IndexedDBDataLossInfo| will also be populated. 133 std::tuple<IndexedDBOriginStateHandle, 134 leveldb::Status, 135 IndexedDBDatabaseError, 136 IndexedDBDataLossInfo, 137 /*was_cold_open=*/bool> 138 GetOrOpenOriginFactory(const url::Origin& origin, 139 const base::FilePath& data_directory, 140 bool create_if_missing); 141 142 void OnDatabaseError(const url::Origin& origin, 143 leveldb::Status s, 144 const char* message); 145 146 protected: 147 // Used by unittests to allow subclassing of IndexedDBBackingStore. 148 virtual std::unique_ptr<IndexedDBBackingStore> CreateBackingStore( 149 IndexedDBBackingStore::Mode backing_store_mode, 150 TransactionalLevelDBFactory* leveldb_factory, 151 const url::Origin& origin, 152 const base::FilePath& blob_path, 153 std::unique_ptr<TransactionalLevelDBDatabase> db, 154 storage::mojom::BlobStorageContext* blob_storage_context, 155 storage::mojom::NativeFileSystemContext* native_file_system_context, 156 IndexedDBBackingStore::BlobFilesCleanedCallback blob_files_cleaned, 157 IndexedDBBackingStore::ReportOutstandingBlobsCallback 158 report_outstanding_blobs, 159 scoped_refptr<base::SequencedTaskRunner> idb_task_runner, 160 scoped_refptr<base::SequencedTaskRunner> io_task_runner); 161 context()162 IndexedDBContextImpl* context() const { return context_; } 163 164 private: 165 friend class IndexedDBBrowserTest; 166 friend class IndexedDBOriginState; 167 168 FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, 169 BackingStoreReleasedOnForcedClose); 170 FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, 171 BackingStoreReleaseDelayedOnClose); 172 FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, BackingStoreRunPreCloseTasks); 173 FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, 174 BackingStoreCloseImmediatelySwitch); 175 FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, BackingStoreNoSweeping); 176 FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, DatabaseFailedOpen); 177 FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, 178 DeleteDatabaseClosesBackingStore); 179 FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, 180 ForceCloseReleasesBackingStore); 181 FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, 182 GetDatabaseNamesClosesBackingStore); 183 FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, 184 ForceCloseOpenDatabasesOnCommitFailure); 185 186 // |path_base| is the directory that will contain the database directory, the 187 // blob directory, and any data loss info. |database_path| is the directory 188 // for the leveldb database, and |blob_path| is the directory to store blob 189 // files. If |path_base| is empty, then an in-memory database is opened. 190 std::tuple<std::unique_ptr<IndexedDBBackingStore>, 191 leveldb::Status, 192 IndexedDBDataLossInfo, 193 bool /* is_disk_full */> 194 OpenAndVerifyIndexedDBBackingStore(const url::Origin& origin, 195 base::FilePath data_directory, 196 base::FilePath database_path, 197 base::FilePath blob_path, 198 LevelDBScopesOptions scopes_options, 199 LevelDBScopesFactory* scopes_factory, 200 bool is_first_attempt, 201 bool create_if_missing); 202 203 void RemoveOriginState(const url::Origin& origin); 204 205 // Called when the database has been deleted on disk. 206 void OnDatabaseDeleted(const url::Origin& origin); 207 208 void MaybeRunTasksForOrigin(const url::Origin& origin); 209 void RunTasksForOrigin(base::WeakPtr<IndexedDBOriginState> origin_state); 210 211 // Testing helpers, so unit tests don't need to grovel through internal 212 // state. 213 bool IsDatabaseOpen(const url::Origin& origin, 214 const base::string16& name) const; 215 bool IsBackingStoreOpen(const url::Origin& origin) const; 216 bool IsBackingStorePendingClose(const url::Origin& origin) const; 217 218 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, 219 base::trace_event::ProcessMemoryDump* pmd) override; 220 221 SEQUENCE_CHECKER(sequence_checker_); 222 // Raw pointer is safe because IndexedDBContextImpl owns this object. 223 IndexedDBContextImpl* context_; 224 IndexedDBClassFactory* const class_factory_; 225 base::Clock* const clock_; 226 base::Time earliest_sweep_; 227 228 base::flat_map<url::Origin, std::unique_ptr<IndexedDBOriginState>> 229 factories_per_origin_; 230 231 std::set<url::Origin> backends_opened_since_startup_; 232 233 // Weak pointers from this factory are used to bind the RemoveOriginState() 234 // function, which deletes the IndexedDBOriginState object. This allows those 235 // weak pointers to be invalidated during force close & shutdown to prevent 236 // re-entry (see ContextDestroyed()). 237 base::WeakPtrFactory<IndexedDBFactoryImpl> 238 origin_state_destruction_weak_factory_{this}; 239 base::WeakPtrFactory<IndexedDBFactoryImpl> weak_factory_{this}; 240 DISALLOW_COPY_AND_ASSIGN(IndexedDBFactoryImpl); 241 }; 242 243 } // namespace content 244 245 #endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_FACTORY_IMPL_H_ 246