1 // Copyright 2019 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_ORIGIN_STATE_H_ 6 #define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_ORIGIN_STATE_H_ 7 8 #include <stdint.h> 9 #include <memory> 10 11 #include "base/callback.h" 12 #include "base/containers/flat_map.h" 13 #include "base/feature_list.h" 14 #include "base/gtest_prod_util.h" 15 #include "base/sequence_checker.h" 16 #include "base/strings/string16.h" 17 #include "base/time/clock.h" 18 #include "base/timer/timer.h" 19 #include "components/services/storage/indexed_db/scopes/disjoint_range_lock_manager.h" 20 #include "content/browser/indexed_db/indexed_db_origin_state_handle.h" 21 #include "content/browser/indexed_db/indexed_db_task_helper.h" 22 #include "content/common/content_export.h" 23 #include "third_party/leveldatabase/src/include/leveldb/status.h" 24 #include "url/origin.h" 25 26 namespace content { 27 class IndexedDBBackingStore; 28 class IndexedDBDatabase; 29 class IndexedDBFactoryImpl; 30 class IndexedDBPreCloseTaskQueue; 31 class TransactionalLevelDBFactory; 32 33 constexpr const char kIDBCloseImmediatelySwitch[] = "idb-close-immediately"; 34 35 // This is an emergency kill switch to use with Finch if the feature needs to be 36 // shut off. 37 CONTENT_EXPORT extern const base::Feature kCompactIDBOnClose; 38 39 // IndexedDBOriginState manages the per-origin IndexedDB state, and contains the 40 // backing store for the origin. 41 // 42 // This class is expected to manage its own lifetime by using the 43 // |destruct_myself_| closure, which is expected to destroy this object in the 44 // parent IndexedDBFactoryImpl (and remove it from any collections, etc). 45 // However, IndexedDBOriginState should still handle destruction without the use 46 // of that closure when the storage partition is destructed. 47 // 48 // IndexedDBOriginState will keep itself alive while: 49 // * There are handles referencing the factory, 50 // * There are outstanding blob references to this database's blob files, and 51 // * The factory is in an incognito profile. 52 class CONTENT_EXPORT IndexedDBOriginState { 53 public: 54 using TearDownCallback = base::RepeatingCallback<void(leveldb::Status)>; 55 using OriginDBMap = 56 base::flat_map<base::string16, std::unique_ptr<IndexedDBDatabase>>; 57 58 // Maximum time interval between runs of the IndexedDBSweeper. Sweeping only 59 // occurs after backing store close. 60 // Visible for testing. 61 static constexpr const base::TimeDelta kMaxEarliestGlobalSweepFromNow = 62 base::TimeDelta::FromHours(1); 63 // Maximum time interval between runs of the IndexedDBSweeper for a given 64 // origin. Sweeping only occurs after backing store close. 65 // Visible for testing. 66 static constexpr const base::TimeDelta kMaxEarliestOriginSweepFromNow = 67 base::TimeDelta::FromDays(3); 68 69 enum class ClosingState { 70 // IndexedDBOriginState isn't closing. 71 kNotClosing, 72 // IndexedDBOriginState is pausing for kBackingStoreGracePeriodSeconds 73 // to 74 // allow new references to open before closing the backing store. 75 kPreCloseGracePeriod, 76 // The |pre_close_task_queue| is running any pre-close tasks. 77 kRunningPreCloseTasks, 78 kClosed, 79 }; 80 81 // Calling |destruct_myself| should destruct this object. 82 // |earliest_global_sweep_time| is expected to outlive this object. 83 IndexedDBOriginState( 84 url::Origin origin, 85 bool persist_for_incognito, 86 base::Clock* clock, 87 TransactionalLevelDBFactory* transactional_leveldb_factory, 88 base::Time* earliest_global_sweep_time, 89 std::unique_ptr<DisjointRangeLockManager> lock_manager, 90 TasksAvailableCallback notify_tasks_callback, 91 TearDownCallback tear_down_callback, 92 std::unique_ptr<IndexedDBBackingStore> backing_store); 93 ~IndexedDBOriginState(); 94 95 void AbortAllTransactions(bool compact); 96 97 void ForceClose(); 98 IsClosing()99 bool IsClosing() const { 100 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 101 return closing_stage_ != ClosingState::kNotClosing; 102 } 103 closing_stage()104 ClosingState closing_stage() const { 105 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 106 return closing_stage_; 107 } 108 109 void ReportOutstandingBlobs(bool blobs_outstanding); 110 111 void StopPersistingForIncognito(); 112 origin()113 const url::Origin& origin() { return origin_; } backing_store()114 IndexedDBBackingStore* backing_store() { 115 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 116 return backing_store_.get(); 117 } databases()118 const OriginDBMap& databases() const { 119 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 120 return databases_; 121 } lock_manager()122 DisjointRangeLockManager* lock_manager() { 123 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 124 return lock_manager_.get(); 125 } pre_close_task_queue()126 IndexedDBPreCloseTaskQueue* pre_close_task_queue() const { 127 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 128 return pre_close_task_queue_.get(); 129 } notify_tasks_callback()130 TasksAvailableCallback notify_tasks_callback() { 131 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 132 return notify_tasks_callback_; 133 } 134 135 // Note: calling this callback will destroy the IndexedDBOriginState. tear_down_callback()136 const TearDownCallback& tear_down_callback() { return tear_down_callback_; } 137 is_running_tasks()138 bool is_running_tasks() const { return running_tasks_; } is_task_run_scheduled()139 bool is_task_run_scheduled() const { return task_run_scheduled_; } set_task_run_scheduled()140 void set_task_run_scheduled() { task_run_scheduled_ = true; } 141 close_timer()142 base::OneShotTimer* close_timer() { 143 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 144 return &close_timer_; 145 } 146 147 enum class RunTasksResult { kDone, kError, kCanBeDestroyed }; 148 std::tuple<RunTasksResult, leveldb::Status> RunTasks(); 149 AsWeakPtr()150 base::WeakPtr<IndexedDBOriginState> AsWeakPtr() { 151 return weak_factory_.GetWeakPtr(); 152 } 153 154 private: 155 friend IndexedDBFactoryImpl; 156 friend IndexedDBOriginStateHandle; 157 158 // Test needs access to ShouldRunTombstoneSweeper. 159 FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTestWithMockTime, 160 TombstoneSweeperTiming); 161 162 // Test needs access to CompactionKillSwitchWorks. 163 FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, CompactionKillSwitchWorks); 164 165 IndexedDBDatabase* AddDatabase(const base::string16& name, 166 std::unique_ptr<IndexedDBDatabase> database); 167 168 // Returns a new handle to this factory. If this object was in its closing 169 // sequence, then that sequence will be halted by this call. 170 IndexedDBOriginStateHandle CreateHandle() WARN_UNUSED_RESULT; 171 172 void OnHandleDestruction(); 173 174 // Returns true if this factory can be closed (no references, no blobs, and 175 // not persisting for incognito). 176 bool CanCloseFactory(); 177 178 void MaybeStartClosing(); 179 void StartClosing(); 180 void StartPreCloseTasks(); 181 182 // Executes database operations, and if |true| is returned by this function, 183 // then the current time will be written to the database as the last sweep 184 // time. 185 bool ShouldRunTombstoneSweeper(); 186 187 bool ShouldRunCompaction(); 188 189 SEQUENCE_CHECKER(sequence_checker_); 190 191 url::Origin origin_; 192 193 // True if this factory should be remain alive due to the storage partition 194 // being for incognito mode, and our backing store being in-memory. This is 195 // used as closing criteria for this object, see CanCloseFactory. 196 bool persist_for_incognito_; 197 // True if there are blobs referencing this backing store that are still 198 // alive. This is used as closing criteria for this object, see 199 // CanCloseFactory. 200 bool has_blobs_outstanding_ = false; 201 bool skip_closing_sequence_ = false; 202 base::Clock* const clock_; 203 TransactionalLevelDBFactory* const transactional_leveldb_factory_; 204 205 bool running_tasks_ = false; 206 bool task_run_scheduled_ = false; 207 208 // This is safe because it is owned by IndexedDBFactoryImpl, which owns this 209 // object. 210 base::Time* earliest_global_sweep_time_; 211 ClosingState closing_stage_ = ClosingState::kNotClosing; 212 base::OneShotTimer close_timer_; 213 const std::unique_ptr<DisjointRangeLockManager> lock_manager_; 214 std::unique_ptr<IndexedDBBackingStore> backing_store_; 215 216 OriginDBMap databases_; 217 // This is the refcount for the number of IndexedDBOriginStateHandle's given 218 // out for this factory using OpenReference. This is used as closing 219 // criteria for this object, see CanCloseFactory. 220 int64_t open_handles_ = 0; 221 222 std::unique_ptr<IndexedDBPreCloseTaskQueue> pre_close_task_queue_; 223 224 TasksAvailableCallback notify_tasks_callback_; 225 TearDownCallback tear_down_callback_; 226 227 base::WeakPtrFactory<IndexedDBOriginState> weak_factory_{this}; 228 229 DISALLOW_COPY_AND_ASSIGN(IndexedDBOriginState); 230 }; 231 232 } // namespace content 233 234 #endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_ORIGIN_STATE_H_ 235