1 // Copyright 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 #include "content/browser/indexed_db/indexed_db_class_factory.h"
6 
7 #include <utility>
8 
9 #include "base/memory/ptr_util.h"
10 #include "base/no_destructor.h"
11 #include "components/services/storage/indexed_db/leveldb/leveldb_factory.h"
12 #include "components/services/storage/indexed_db/scopes/leveldb_scope.h"
13 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h"
14 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_factory.h"
15 #include "content/browser/indexed_db/indexed_db_factory.h"
16 #include "content/browser/indexed_db/indexed_db_leveldb_env.h"
17 #include "content/browser/indexed_db/indexed_db_leveldb_operations.h"
18 #include "content/browser/indexed_db/indexed_db_metadata_coding.h"
19 #include "content/browser/indexed_db/indexed_db_reporting.h"
20 #include "content/browser/indexed_db/indexed_db_transaction.h"
21 #include "third_party/leveldatabase/leveldb_chrome.h"
22 #include "third_party/leveldatabase/src/include/leveldb/filter_policy.h"
23 
24 namespace content {
25 namespace {
GetDefaultLevelDBFactory()26 DefaultLevelDBFactory* GetDefaultLevelDBFactory() {
27   static base::NoDestructor<DefaultLevelDBFactory> leveldb_factory(
28       IndexedDBClassFactory::GetLevelDBOptions(), "indexed-db");
29   return leveldb_factory.get();
30 }
GetDefaultTransactionalLevelDBFactory()31 DefaultTransactionalLevelDBFactory* GetDefaultTransactionalLevelDBFactory() {
32   static base::NoDestructor<DefaultTransactionalLevelDBFactory>
33       transactional_leveldb_factory;
34   return transactional_leveldb_factory.get();
35 }
36 }  // namespace
37 static IndexedDBClassFactory::GetterCallback* s_factory_getter;
38 static ::base::LazyInstance<IndexedDBClassFactory>::Leaky s_factory =
39     LAZY_INSTANCE_INITIALIZER;
40 
SetIndexedDBClassFactoryGetter(GetterCallback * cb)41 void IndexedDBClassFactory::SetIndexedDBClassFactoryGetter(GetterCallback* cb) {
42   s_factory_getter = cb;
43 }
44 
45 // static
Get()46 IndexedDBClassFactory* IndexedDBClassFactory::Get() {
47   if (s_factory_getter)
48     return (*s_factory_getter)();
49   else
50     return s_factory.Pointer();
51 }
52 
53 // static
GetLevelDBOptions()54 leveldb_env::Options IndexedDBClassFactory::GetLevelDBOptions() {
55   static const leveldb::FilterPolicy* kIDBFilterPolicy =
56       leveldb::NewBloomFilterPolicy(10);
57   leveldb_env::Options options;
58   options.comparator = indexed_db::GetDefaultLevelDBComparator();
59   options.paranoid_checks = true;
60   options.filter_policy = kIDBFilterPolicy;
61   options.compression = leveldb::kSnappyCompression;
62   // For info about the troubles we've run into with this parameter, see:
63   // https://crbug.com/227313#c11
64   options.max_open_files = 80;
65   options.env = IndexedDBLevelDBEnv::Get();
66   options.block_cache = leveldb_chrome::GetSharedWebBlockCache();
67   options.on_get_error = base::BindRepeating(
68       indexed_db::ReportLevelDBError, "WebCore.IndexedDB.LevelDBReadErrors");
69   options.on_write_error = base::BindRepeating(
70       indexed_db::ReportLevelDBError, "WebCore.IndexedDB.LevelDBWriteErrors");
71   return options;
72 }
73 
IndexedDBClassFactory()74 IndexedDBClassFactory::IndexedDBClassFactory()
75     : IndexedDBClassFactory(GetDefaultLevelDBFactory(),
76                             GetDefaultTransactionalLevelDBFactory()) {}
77 
IndexedDBClassFactory(LevelDBFactory * leveldb_factory,TransactionalLevelDBFactory * transactional_leveldb_factory)78 IndexedDBClassFactory::IndexedDBClassFactory(
79     LevelDBFactory* leveldb_factory,
80     TransactionalLevelDBFactory* transactional_leveldb_factory)
81     : leveldb_factory_(leveldb_factory),
82       transactional_leveldb_factory_(transactional_leveldb_factory) {}
83 
leveldb_factory()84 LevelDBFactory& IndexedDBClassFactory::leveldb_factory() {
85   return *leveldb_factory_;
86 }
87 TransactionalLevelDBFactory&
transactional_leveldb_factory()88 IndexedDBClassFactory::transactional_leveldb_factory() {
89   return *transactional_leveldb_factory_;
90 }
91 
92 std::pair<std::unique_ptr<IndexedDBDatabase>, leveldb::Status>
CreateIndexedDBDatabase(const base::string16 & name,IndexedDBBackingStore * backing_store,IndexedDBFactory * factory,TasksAvailableCallback tasks_available_callback,std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,const IndexedDBDatabase::Identifier & unique_identifier,ScopesLockManager * transaction_lock_manager)93 IndexedDBClassFactory::CreateIndexedDBDatabase(
94     const base::string16& name,
95     IndexedDBBackingStore* backing_store,
96     IndexedDBFactory* factory,
97     TasksAvailableCallback tasks_available_callback,
98     std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
99     const IndexedDBDatabase::Identifier& unique_identifier,
100     ScopesLockManager* transaction_lock_manager) {
101   DCHECK(backing_store);
102   DCHECK(factory);
103   std::unique_ptr<IndexedDBDatabase> database =
104       base::WrapUnique(new IndexedDBDatabase(
105           name, backing_store, factory, this,
106           std::move(tasks_available_callback), std::move(metadata_coding),
107           unique_identifier, transaction_lock_manager));
108   leveldb::Status s = database->OpenInternal();
109   if (!s.ok())
110     database = nullptr;
111   return {std::move(database), s};
112 }
113 
114 std::unique_ptr<IndexedDBTransaction>
CreateIndexedDBTransaction(int64_t id,IndexedDBConnection * connection,const std::set<int64_t> & scope,blink::mojom::IDBTransactionMode mode,TasksAvailableCallback tasks_available_callback,IndexedDBTransaction::TearDownCallback tear_down_callback,IndexedDBBackingStore::Transaction * backing_store_transaction)115 IndexedDBClassFactory::CreateIndexedDBTransaction(
116     int64_t id,
117     IndexedDBConnection* connection,
118     const std::set<int64_t>& scope,
119     blink::mojom::IDBTransactionMode mode,
120     TasksAvailableCallback tasks_available_callback,
121     IndexedDBTransaction::TearDownCallback tear_down_callback,
122     IndexedDBBackingStore::Transaction* backing_store_transaction) {
123   return base::WrapUnique(new IndexedDBTransaction(
124       id, connection, scope, mode, std::move(tasks_available_callback),
125       std::move(tear_down_callback), backing_store_transaction));
126 }
127 
SetLevelDBFactoryForTesting(LevelDBFactory * leveldb_factory)128 void IndexedDBClassFactory::SetLevelDBFactoryForTesting(
129     LevelDBFactory* leveldb_factory) {
130   if (leveldb_factory)
131     leveldb_factory_ = leveldb_factory;
132   else
133     leveldb_factory_ = GetDefaultLevelDBFactory();
134 }
135 
136 }  // namespace content
137