summaryrefslogtreecommitdiff
path: root/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
blob: 4ae17600381712ed3649e59cfdc08decb645a8b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_FACTORY_IMPL_H_
#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_FACTORY_IMPL_H_

#include <stddef.h>

#include <map>
#include <memory>
#include <set>

#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "content/browser/indexed_db/indexed_db_factory.h"

namespace base {
struct Feature;
}

namespace url {
class Origin;
}

namespace content {

class IndexedDBContextImpl;

CONTENT_EXPORT extern const base::Feature kIDBTombstoneStatistics;
CONTENT_EXPORT extern const base::Feature kIDBTombstoneDeletion;

class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
 public:
  // Maximum time interval between runs of the IndexedDBSweeper. Sweeping only
  // occurs after backing store close.
  // Visible for testing.
  static constexpr const base::TimeDelta kMaxEarliestGlobalSweepFromNow =
      base::TimeDelta::FromHours(2);
  // Maximum time interval between runs of the IndexedDBSweeper for a given
  // origin. Sweeping only occurs after backing store close.
  // Visible for testing.
  static constexpr const base::TimeDelta kMaxEarliestOriginSweepFromNow =
      base::TimeDelta::FromDays(7);

  IndexedDBFactoryImpl(IndexedDBContextImpl* context, base::Clock* clock);

  // content::IndexedDBFactory overrides:
  void ReleaseDatabase(const IndexedDBDatabase::Identifier& identifier,
                       bool forced_close) override;

  void GetDatabaseNames(scoped_refptr<IndexedDBCallbacks> callbacks,
                        const url::Origin& origin,
                        const base::FilePath& data_directory,
                        scoped_refptr<net::URLRequestContextGetter>
                            request_context_getter) override;
  void Open(const base::string16& name,
            std::unique_ptr<IndexedDBPendingConnection> connection,
            scoped_refptr<net::URLRequestContextGetter> request_context_getter,
            const url::Origin& origin,
            const base::FilePath& data_directory) override;

  void DeleteDatabase(
      const base::string16& name,
      scoped_refptr<net::URLRequestContextGetter> request_context_getter,
      scoped_refptr<IndexedDBCallbacks> callbacks,
      const url::Origin& origin,
      const base::FilePath& data_directory,
      bool force_close) override;

  void AbortTransactionsAndCompactDatabase(
      base::OnceCallback<void(leveldb::Status)> callback,
      const url::Origin& origin) override;
  void AbortTransactionsForDatabase(
      base::OnceCallback<void(leveldb::Status)> callback,
      const url::Origin& origin) override;

  void HandleBackingStoreFailure(const url::Origin& origin) override;
  void HandleBackingStoreCorruption(
      const url::Origin& origin,
      const IndexedDBDatabaseError& error) override;

  OriginDBs GetOpenDatabasesForOrigin(const url::Origin& origin) const override;

  void ForceClose(const url::Origin& origin) override;

  // Called by the IndexedDBContext destructor so the factory can do cleanup.
  void ContextDestroyed() override;

  // Called by the IndexedDBActiveBlobRegistry.
  void ReportOutstandingBlobs(const url::Origin& origin,
                              bool blobs_outstanding) override;

  // Called by an IndexedDBDatabase when it is actually deleted.
  void DatabaseDeleted(
      const IndexedDBDatabase::Identifier& identifier) override;

  // Called by IndexedDBBackingStore when blob files have been cleaned.
  void BlobFilesCleaned(const url::Origin& origin) override;

  size_t GetConnectionCount(const url::Origin& origin) const override;

  void NotifyIndexedDBContentChanged(
      const url::Origin& origin,
      const base::string16& database_name,
      const base::string16& object_store_name) override;

  int64_t GetInMemoryDBSize(const url::Origin& origin) const override;

  base::Time GetLastModified(const url::Origin& origin) const override;

 protected:
  ~IndexedDBFactoryImpl() override;

  scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
      const url::Origin& origin,
      const base::FilePath& data_directory,
      scoped_refptr<net::URLRequestContextGetter> request_context_getter,
      IndexedDBDataLossInfo* data_loss_info,
      bool* disk_full,
      leveldb::Status* s) override;

  scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
      const url::Origin& origin,
      const base::FilePath& data_directory,
      scoped_refptr<net::URLRequestContextGetter> request_context_getter,
      IndexedDBDataLossInfo* data_loss_info,
      bool* disk_full,
      bool first_time,
      leveldb::Status* s) override;

  void ReleaseBackingStore(const url::Origin& origin, bool immediate);
  void CloseBackingStore(const url::Origin& origin);
  IndexedDBContextImpl* context() const { return context_; }

 private:
  FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
                           BackingStoreReleasedOnForcedClose);
  FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
                           BackingStoreReleaseDelayedOnClose);
  FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, BackingStoreRunPreCloseTasks);
  FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, BackingStoreNoSweeping);
  FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, DatabaseFailedOpen);
  FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
                           DeleteDatabaseClosesBackingStore);
  FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
                           ForceCloseReleasesBackingStore);
  FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
                           GetDatabaseNamesClosesBackingStore);
  FRIEND_TEST_ALL_PREFIXES(IndexedDBTest,
                           ForceCloseOpenDatabasesOnCommitFailure);

  leveldb::Status AbortTransactions(const url::Origin& origin);

  // Called internally after a database is closed, with some delay. If this
  // factory has the last reference it will start running pre-close tasks.
  void MaybeStartPreCloseTasks(const url::Origin& origin);
  // Called internally after pre-close tasks. If this factory has the last
  // reference it will be released.
  void MaybeCloseBackingStore(const url::Origin& origin);
  bool HasLastBackingStoreReference(const url::Origin& origin) const;

  // Testing helpers, so unit tests don't need to grovel through internal state.
  bool IsDatabaseOpen(const url::Origin& origin,
                      const base::string16& name) const;
  bool IsBackingStoreOpen(const url::Origin& origin) const;
  bool IsBackingStorePendingClose(const url::Origin& origin) const;
  void RemoveDatabaseFromMaps(const IndexedDBDatabase::Identifier& identifier);

  IndexedDBContextImpl* context_;

  std::map<IndexedDBDatabase::Identifier, IndexedDBDatabase*> database_map_;
  OriginDBMap origin_dbs_;
  std::map<url::Origin, scoped_refptr<IndexedDBBackingStore>>
      backing_store_map_;

  std::set<scoped_refptr<IndexedDBBackingStore> > session_only_backing_stores_;
  std::map<url::Origin, scoped_refptr<IndexedDBBackingStore>>
      backing_stores_with_active_blobs_;
  std::set<url::Origin> backends_opened_since_boot_;

  base::Clock* clock_;
  base::Time earliest_sweep_;

  DISALLOW_COPY_AND_ASSIGN(IndexedDBFactoryImpl);
};

}  // namespace content

#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_FACTORY_IMPL_H_