1 // Copyright (c) 2013 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_DATABASE_H_
6 #define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_DATABASE_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <list>
12 #include <map>
13 #include <memory>
14 #include <string>
15 #include <tuple>
16 #include <utility>
17 #include <vector>
18 
19 #include "base/callback.h"
20 #include "base/containers/queue.h"
21 #include "base/gtest_prod_util.h"
22 #include "base/macros.h"
23 #include "base/memory/ref_counted.h"
24 #include "base/memory/weak_ptr.h"
25 #include "base/strings/string16.h"
26 #include "components/services/storage/indexed_db/scopes/scopes_lock_manager.h"
27 #include "content/browser/indexed_db/indexed_db.h"
28 #include "content/browser/indexed_db/indexed_db_backing_store.h"
29 #include "content/browser/indexed_db/indexed_db_callbacks.h"
30 #include "content/browser/indexed_db/indexed_db_connection_coordinator.h"
31 #include "content/browser/indexed_db/indexed_db_observer.h"
32 #include "content/browser/indexed_db/indexed_db_origin_state_handle.h"
33 #include "content/browser/indexed_db/indexed_db_pending_connection.h"
34 #include "content/browser/indexed_db/indexed_db_task_helper.h"
35 #include "content/browser/indexed_db/indexed_db_value.h"
36 #include "content/browser/indexed_db/list_set.h"
37 #include "content/common/content_export.h"
38 #include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
39 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
40 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-forward.h"
41 
42 namespace blink {
43 class IndexedDBKeyPath;
44 class IndexedDBKeyRange;
45 struct IndexedDBDatabaseMetadata;
46 struct IndexedDBIndexMetadata;
47 struct IndexedDBObjectStoreMetadata;
48 }  // namespace blink
49 
50 namespace url {
51 class Origin;
52 }
53 
54 namespace content {
55 class IndexedDBClassFactory;
56 class IndexedDBConnection;
57 class IndexedDBDatabaseCallbacks;
58 class IndexedDBFactory;
59 class IndexedDBMetadataCoding;
60 class IndexedDBOriginStateHandle;
61 class IndexedDBTransaction;
62 struct IndexedDBValue;
63 
64 class CONTENT_EXPORT IndexedDBDatabase {
65  public:
66   // Identifier is pair of (origin, database name).
67   using Identifier = std::pair<url::Origin, base::string16>;
68   // Used to report irrecoverable backend errors. The second argument can be
69   // null.
70   using ErrorCallback =
71       base::RepeatingCallback<void(leveldb::Status, const char*)>;
72 
73   static const int64_t kInvalidId = 0;
74   static const int64_t kMinimumIndexId = 30;
75 
76   virtual ~IndexedDBDatabase();
77 
identifier()78   const Identifier& identifier() const { return identifier_; }
backing_store()79   IndexedDBBackingStore* backing_store() { return backing_store_; }
80 
id()81   int64_t id() const { return metadata_.id; }
name()82   const base::string16& name() const { return metadata_.name; }
origin()83   const url::Origin& origin() const { return identifier_.first; }
metadata()84   const blink::IndexedDBDatabaseMetadata& metadata() const { return metadata_; }
85 
transaction_lock_manager()86   ScopesLockManager* transaction_lock_manager() { return lock_manager_; }
transaction_lock_manager()87   const ScopesLockManager* transaction_lock_manager() const {
88     return lock_manager_;
89   }
90 
connections()91   const list_set<IndexedDBConnection*>& connections() const {
92     return connections_;
93   }
tasks_available_callback()94   TasksAvailableCallback tasks_available_callback() {
95     return tasks_available_callback_;
96   }
97 
98   // TODO(dmurph): Remove this method and have transactions be directly
99   // scheduled using the lock manager.
100 
101   enum class RunTasksResult { kDone, kError, kCanBeDestroyed };
102   std::tuple<RunTasksResult, leveldb::Status> RunTasks();
103   void RegisterAndScheduleTransaction(IndexedDBTransaction* transaction);
104 
105   // The database object (this object) must be kept alive for the duration of
106   // this call. This means the caller should own an IndexedDBOriginStateHandle
107   // while caling this methods.
108   leveldb::Status ForceCloseAndRunTasks();
109 
110   void Commit(IndexedDBTransaction* transaction);
111 
112   void TransactionCreated();
113   void TransactionFinished(blink::mojom::IDBTransactionMode mode,
114                            bool committed);
115 
116   void AddPendingObserver(IndexedDBTransaction* transaction,
117                           int32_t observer_id,
118                           const IndexedDBObserver::Options& options);
119 
120   // |value| can be null for delete and clear operations.
121   void FilterObservation(IndexedDBTransaction*,
122                          int64_t object_store_id,
123                          blink::mojom::IDBOperationType type,
124                          const blink::IndexedDBKeyRange& key_range,
125                          const IndexedDBValue* value);
126   void SendObservations(
127       std::map<int32_t, blink::mojom::IDBObserverChangesPtr> change_map);
128 
129   void ScheduleOpenConnection(
130       IndexedDBOriginStateHandle origin_state_handle,
131       std::unique_ptr<IndexedDBPendingConnection> connection);
132   void ScheduleDeleteDatabase(IndexedDBOriginStateHandle origin_state_handle,
133                               scoped_refptr<IndexedDBCallbacks> callbacks,
134                               base::OnceClosure on_deletion_complete);
135 
136   void AddObjectStoreToMetadata(blink::IndexedDBObjectStoreMetadata metadata,
137                                 int64_t new_max_object_store_id);
138   blink::IndexedDBObjectStoreMetadata RemoveObjectStoreFromMetadata(
139       int64_t object_store_id);
140   void AddIndexToMetadata(int64_t object_store_id,
141                           blink::IndexedDBIndexMetadata metadata,
142                           int64_t new_max_index_id);
143   blink::IndexedDBIndexMetadata RemoveIndexFromMetadata(int64_t object_store_id,
144                                                         int64_t index_id);
145 
146   // The following methods all schedule a task on the transaction & modify the
147   // database:
148 
149   // Number of connections that have progressed passed initial open call.
ConnectionCount()150   size_t ConnectionCount() const { return connections_.size(); }
151 
152   // Number of active open/delete calls (running or blocked on other
153   // connections).
ActiveOpenDeleteCount()154   size_t ActiveOpenDeleteCount() const {
155     return connection_coordinator_.ActiveOpenDeleteCount();
156   }
157 
158   // Number of open/delete calls that are waiting their turn.
PendingOpenDeleteCount()159   size_t PendingOpenDeleteCount() const {
160     return connection_coordinator_.PendingOpenDeleteCount();
161   }
162 
163   // The following methods are all of the ones actually scheduled asynchronously
164   // within transctions:
165 
166   leveldb::Status CreateObjectStoreOperation(
167       int64_t object_store_id,
168       const base::string16& name,
169       const blink::IndexedDBKeyPath& key_path,
170       bool auto_increment,
171       IndexedDBTransaction* transaction);
172   void CreateObjectStoreAbortOperation(int64_t object_store_id);
173 
174   leveldb::Status DeleteObjectStoreOperation(int64_t object_store_id,
175                                              IndexedDBTransaction* transaction);
176   void DeleteObjectStoreAbortOperation(
177       blink::IndexedDBObjectStoreMetadata object_store_metadata);
178 
179   leveldb::Status RenameObjectStoreOperation(int64_t object_store_id,
180                                              const base::string16& new_name,
181                                              IndexedDBTransaction* transaction);
182   void RenameObjectStoreAbortOperation(int64_t object_store_id,
183                                        base::string16 old_name);
184 
185   leveldb::Status VersionChangeOperation(
186       int64_t version,
187       scoped_refptr<IndexedDBCallbacks> callbacks,
188       IndexedDBTransaction* transaction);
189   void VersionChangeAbortOperation(int64_t previous_version);
190 
191   leveldb::Status CreateIndexOperation(int64_t object_store_id,
192                                        int64_t index_id,
193                                        const base::string16& name,
194                                        const blink::IndexedDBKeyPath& key_path,
195                                        bool unique,
196                                        bool multi_entry,
197                                        IndexedDBTransaction* transaction);
198   void CreateIndexAbortOperation(int64_t object_store_id, int64_t index_id);
199 
200   leveldb::Status DeleteIndexOperation(int64_t object_store_id,
201                                        int64_t index_id,
202                                        IndexedDBTransaction* transaction);
203   void DeleteIndexAbortOperation(int64_t object_store_id,
204                                  blink::IndexedDBIndexMetadata index_metadata);
205 
206   leveldb::Status RenameIndexOperation(int64_t object_store_id,
207                                        int64_t index_id,
208                                        const base::string16& new_name,
209                                        IndexedDBTransaction* transaction);
210   void RenameIndexAbortOperation(int64_t object_store_id,
211                                  int64_t index_id,
212                                  base::string16 old_name);
213 
214   leveldb::Status GetOperation(
215       base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
216       int64_t object_store_id,
217       int64_t index_id,
218       std::unique_ptr<blink::IndexedDBKeyRange> key_range,
219       indexed_db::CursorType cursor_type,
220       blink::mojom::IDBDatabase::GetCallback callback,
221       IndexedDBTransaction* transaction);
222 
223   leveldb::Status GetAllOperation(
224       base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
225       int64_t object_store_id,
226       int64_t index_id,
227       std::unique_ptr<blink::IndexedDBKeyRange> key_range,
228       indexed_db::CursorType cursor_type,
229       int64_t max_count,
230       blink::mojom::IDBDatabase::GetAllCallback callback,
231       IndexedDBTransaction* transaction);
232 
233   struct CONTENT_EXPORT PutOperationParams {
234     PutOperationParams();
235     ~PutOperationParams();
236     int64_t object_store_id;
237     IndexedDBValue value;
238     std::unique_ptr<blink::IndexedDBKey> key;
239     blink::mojom::IDBPutMode put_mode;
240     blink::mojom::IDBTransaction::PutCallback callback;
241     std::vector<blink::IndexedDBIndexKeys> index_keys;
242 
243    private:
244     DISALLOW_COPY_AND_ASSIGN(PutOperationParams);
245   };
246   leveldb::Status PutOperation(std::unique_ptr<PutOperationParams> params,
247                                IndexedDBTransaction* transaction);
248 
249   struct CONTENT_EXPORT PutAllOperationParams {
250     PutAllOperationParams();
251     ~PutAllOperationParams();
252     IndexedDBValue value;
253     std::unique_ptr<blink::IndexedDBKey> key;
254     std::vector<blink::IndexedDBIndexKeys> index_keys;
255 
256    private:
257     DISALLOW_COPY_AND_ASSIGN(PutAllOperationParams);
258   };
259   leveldb::Status PutAllOperation(
260       int64_t object_store_id,
261       std::vector<std::unique_ptr<PutAllOperationParams>> params,
262       blink::mojom::IDBTransaction::PutAllCallback callback,
263       IndexedDBTransaction* transaction);
264 
265   leveldb::Status SetIndexKeysOperation(
266       int64_t object_store_id,
267       std::unique_ptr<blink::IndexedDBKey> primary_key,
268       const std::vector<blink::IndexedDBIndexKeys>& index_keys,
269       IndexedDBTransaction* transaction);
270 
271   leveldb::Status SetIndexesReadyOperation(size_t index_count,
272                                            IndexedDBTransaction* transaction);
273 
274   struct OpenCursorOperationParams {
275     OpenCursorOperationParams();
276     ~OpenCursorOperationParams();
277     int64_t object_store_id;
278     int64_t index_id;
279     std::unique_ptr<blink::IndexedDBKeyRange> key_range;
280     blink::mojom::IDBCursorDirection direction;
281     indexed_db::CursorType cursor_type;
282     blink::mojom::IDBTaskType task_type;
283     blink::mojom::IDBDatabase::OpenCursorCallback callback;
284 
285    private:
286     DISALLOW_COPY_AND_ASSIGN(OpenCursorOperationParams);
287   };
288   leveldb::Status OpenCursorOperation(
289       std::unique_ptr<OpenCursorOperationParams> params,
290       const url::Origin& origin,
291       base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
292       IndexedDBTransaction* transaction);
293 
294   leveldb::Status CountOperation(
295       int64_t object_store_id,
296       int64_t index_id,
297       std::unique_ptr<blink::IndexedDBKeyRange> key_range,
298       scoped_refptr<IndexedDBCallbacks> callbacks,
299       IndexedDBTransaction* transaction);
300 
301   leveldb::Status DeleteRangeOperation(
302       int64_t object_store_id,
303       std::unique_ptr<blink::IndexedDBKeyRange> key_range,
304       scoped_refptr<IndexedDBCallbacks> callbacks,
305       IndexedDBTransaction* transaction);
306 
307   leveldb::Status GetKeyGeneratorCurrentNumberOperation(
308       int64_t object_store_id,
309       scoped_refptr<IndexedDBCallbacks> callbacks,
310       IndexedDBTransaction* transaction);
311 
312   leveldb::Status ClearOperation(int64_t object_store_id,
313                                  scoped_refptr<IndexedDBCallbacks> callbacks,
314                                  IndexedDBTransaction* transaction);
315 
316   bool IsObjectStoreIdInMetadata(int64_t object_store_id) const;
317   bool IsObjectStoreIdAndIndexIdInMetadata(int64_t object_store_id,
318                                            int64_t index_id) const;
319   bool IsObjectStoreIdAndMaybeIndexIdInMetadata(int64_t object_store_id,
320                                                 int64_t index_id) const;
321   bool IsObjectStoreIdInMetadataAndIndexNotInMetadata(int64_t object_store_id,
322                                                       int64_t index_id) const;
323 
AsWeakPtr()324   base::WeakPtr<IndexedDBDatabase> AsWeakPtr() {
325     return weak_factory_.GetWeakPtr();
326   }
327 
AddConnectionForTesting(IndexedDBConnection * connection)328   void AddConnectionForTesting(IndexedDBConnection* connection) {
329     connections_.insert(connection);
330   }
331 
332  protected:
333   friend class IndexedDBTransaction;
334   friend class IndexedDBConnectionCoordinator;
335   friend class IndexedDBConnectionCoordinator::ConnectionRequest;
336   friend class IndexedDBConnectionCoordinator::OpenRequest;
337   friend class IndexedDBConnectionCoordinator::DeleteRequest;
338 
339   IndexedDBDatabase(const base::string16& name,
340                     IndexedDBBackingStore* backing_store,
341                     IndexedDBFactory* factory,
342                     IndexedDBClassFactory* class_factory,
343                     TasksAvailableCallback tasks_available_callback,
344                     std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
345                     const Identifier& unique_identifier,
346                     ScopesLockManager* transaction_lock_manager);
347 
348   // May be overridden in tests.
349   virtual size_t GetUsableMessageSizeInBytes() const;
350 
351  private:
352   friend class MockBrowserTestIndexedDBClassFactory;
353   friend class IndexedDBClassFactory;
354 
355   FRIEND_TEST_ALL_PREFIXES(IndexedDBDatabaseTest, OpenDeleteClear);
356 
357   void CallUpgradeTransactionStartedForTesting(int64_t old_version);
358 
359   class ConnectionRequest;
360   class OpenRequest;
361   class DeleteRequest;
362 
363   leveldb::Status OpenInternal();
364 
365   // If there is no active request, grab a new one from the pending queue and
366   // start it. Afterwards, possibly release the database by calling
367   // MaybeReleaseDatabase().
368   void ProcessRequestQueueAndMaybeRelease();
369 
370   // If there are no connections, pending requests, or an active request, then
371   // this function will call |destroy_me_|, which can destruct this object.
372   void MaybeReleaseDatabase();
373 
374   std::unique_ptr<IndexedDBConnection> CreateConnection(
375       IndexedDBOriginStateHandle origin_state_handle,
376       scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks);
377 
378   // Ack that one of the connections notified with a "versionchange" event did
379   // not promptly close. Therefore a "blocked" event should be fired at the
380   // pending connection.
381   void VersionChangeIgnored();
382 
383   bool HasNoConnections() const;
384 
385   void SendVersionChangeToAllConnections(int64_t old_version,
386                                          int64_t new_version);
387 
388   // This can only be called when the given connection is closed and no longer
389   // has any transaction objects.
390   void ConnectionClosed(IndexedDBConnection* connection);
391 
392   bool CanBeDestroyed();
393 
394   // Safe because the IndexedDBBackingStore is owned by the same object which
395   // owns us, the IndexedDBPerOriginFactory.
396   IndexedDBBackingStore* backing_store_;
397   blink::IndexedDBDatabaseMetadata metadata_;
398 
399   const Identifier identifier_;
400   // TODO(dmurph): Remove the need for this to be here (and then remove it).
401   IndexedDBFactory* factory_;
402   IndexedDBClassFactory* const class_factory_;
403   std::unique_ptr<IndexedDBMetadataCoding> metadata_coding_;
404 
405   ScopesLockManager* lock_manager_;
406   int64_t transaction_count_ = 0;
407 
408   list_set<IndexedDBConnection*> connections_;
409 
410   TasksAvailableCallback tasks_available_callback_;
411 
412   bool force_closing_ = false;
413 
414   IndexedDBConnectionCoordinator connection_coordinator_;
415 
416   // |weak_factory_| is used for all callback uses.
417   base::WeakPtrFactory<IndexedDBDatabase> weak_factory_{this};
418 
419   DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabase);
420 };
421 
422 }  // namespace content
423 
424 #endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_DATABASE_H_
425