1 // Copyright 2016 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 COMPONENTS_SERVICES_STORAGE_DOM_STORAGE_LOCAL_STORAGE_IMPL_H_ 6 #define COMPONENTS_SERVICES_STORAGE_DOM_STORAGE_LOCAL_STORAGE_IMPL_H_ 7 8 #include <stdint.h> 9 #include <map> 10 #include <memory> 11 #include <set> 12 #include <string> 13 #include <vector> 14 15 #include "base/callback_forward.h" 16 #include "base/files/file_path.h" 17 #include "base/memory/ref_counted.h" 18 #include "base/sequenced_task_runner.h" 19 #include "base/threading/sequence_bound.h" 20 #include "base/trace_event/memory_allocator_dump.h" 21 #include "base/trace_event/memory_dump_provider.h" 22 #include "components/services/storage/dom_storage/async_dom_storage_database.h" 23 #include "components/services/storage/dom_storage/dom_storage_database.h" 24 #include "components/services/storage/public/mojom/local_storage_control.mojom.h" 25 #include "mojo/public/cpp/bindings/pending_receiver.h" 26 #include "mojo/public/cpp/bindings/receiver.h" 27 #include "mojo/public/cpp/bindings/remote.h" 28 #include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h" 29 #include "url/origin.h" 30 31 namespace storage { 32 33 // The Local Storage implementation. An instance of this class exists for each 34 // storage partition using Local Storage, managing storage for all origins 35 // within the partition. 36 class LocalStorageImpl : public base::trace_event::MemoryDumpProvider, 37 public mojom::LocalStorageControl { 38 public: 39 static base::FilePath LegacyDatabaseFileNameFromOrigin( 40 const url::Origin& origin); 41 static url::Origin OriginFromLegacyDatabaseFileName( 42 const base::FilePath& file_name); 43 44 // Constructs a Local Storage implementation which will create its root 45 // "Local Storage" directory in |storage_root| if non-empty. |task_runner| 46 // run tasks on the same sequence as the one which constructs this object. 47 // |legacy_task_runner| must support blocking operations and its tasks must 48 // be able to block shutdown. If valid, |receiver| will be bound to this 49 // object to allow for remote control via the LocalStorageControl interface. 50 LocalStorageImpl(const base::FilePath& storage_root, 51 scoped_refptr<base::SequencedTaskRunner> task_runner, 52 scoped_refptr<base::SequencedTaskRunner> legacy_task_runner, 53 mojo::PendingReceiver<mojom::LocalStorageControl> receiver); 54 55 void FlushOriginForTesting(const url::Origin& origin); 56 57 // Used by content settings to alter the behavior around 58 // what data to keep and what data to discard at shutdown. 59 // The policy is not so straight forward to describe, see 60 // the implementation for details. SetForceKeepSessionState()61 void SetForceKeepSessionState() { force_keep_session_state_ = true; } 62 63 // Called when the owning BrowserContext is ending. 64 // Schedules the commit of any unsaved changes and will delete 65 // and keep data on disk per the content settings and special storage 66 // policies. 67 void ShutdownAndDelete(); 68 69 // Clears unused storage areas, when thresholds are reached. 70 void PurgeUnusedAreasIfNeeded(); 71 72 // mojom::LocalStorageControl implementation: 73 void BindStorageArea( 74 const url::Origin& origin, 75 mojo::PendingReceiver<blink::mojom::StorageArea> receiver) override; 76 void GetUsage(GetUsageCallback callback) override; 77 void DeleteStorage(const url::Origin& origin, 78 DeleteStorageCallback callback) override; 79 void CleanUpStorage(CleanUpStorageCallback callback) override; 80 void Flush(FlushCallback callback) override; 81 void PurgeMemory() override; 82 void ApplyPolicyUpdates( 83 std::vector<mojom::LocalStoragePolicyUpdatePtr> policy_updates) override; 84 void ForceKeepSessionState() override; 85 86 // base::trace_event::MemoryDumpProvider implementation. 87 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, 88 base::trace_event::ProcessMemoryDump* pmd) override; 89 90 // Converts a string from the old storage format to the new storage format. 91 static std::vector<uint8_t> MigrateString(const base::string16& input); 92 93 // Access the underlying DomStorageDatabase. May be null if the database is 94 // not yet open. GetDatabaseForTesting()95 const base::SequenceBound<DomStorageDatabase>& GetDatabaseForTesting() const { 96 return database_->database(); 97 } 98 99 // Wait for the database to be opened, or for opening to fail. If the database 100 // is already opened, |callback| is invoked immediately. 101 void SetDatabaseOpenCallbackForTesting(base::OnceClosure callback); 102 103 private: 104 friend class DOMStorageBrowserTest; 105 106 class StorageAreaHolder; 107 108 ~LocalStorageImpl() override; 109 110 // Runs |callback| immediately if already connected to a database, otherwise 111 // delays running |callback| untill after a connection has been established. 112 // Initiates connecting to the database if no connection is in progres yet. 113 void RunWhenConnected(base::OnceClosure callback); 114 115 // Part of our asynchronous directory opening called from RunWhenConnected(). 116 void InitiateConnection(bool in_memory_only = false); 117 void OnDatabaseOpened(leveldb::Status status); 118 void OnGotDatabaseVersion(leveldb::Status status, 119 const std::vector<uint8_t>& value); 120 void OnConnectionFinished(); 121 void DeleteAndRecreateDatabase(const char* histogram_name); 122 void OnDBDestroyed(bool recreate_in_memory, leveldb::Status status); 123 124 StorageAreaHolder* GetOrCreateStorageArea(const url::Origin& origin); 125 126 // The (possibly delayed) implementation of GetUsage(). Can be called directly 127 // from that function, or through |on_database_open_callbacks_|. 128 void RetrieveStorageUsage(GetUsageCallback callback); 129 void OnGotMetaData(GetUsageCallback callback, 130 std::vector<DomStorageDatabase::KeyValuePair> data); 131 132 void OnGotStorageUsageForShutdown( 133 std::vector<mojom::LocalStorageUsageInfoPtr> usage); 134 void OnShutdownComplete(leveldb::Status status); 135 136 void GetStatistics(size_t* total_cache_size, size_t* unused_area_count); 137 void OnCommitResult(leveldb::Status status); 138 139 // These values are written to logs. New enum values can be added, but 140 // existing enums must never be renumbered or deleted and reused. 141 enum class OpenResult { 142 DIRECTORY_OPEN_FAILED = 0, 143 DATABASE_OPEN_FAILED = 1, 144 INVALID_VERSION = 2, 145 VERSION_READ_ERROR = 3, 146 SUCCESS = 4, 147 MAX 148 }; 149 150 void LogDatabaseOpenResult(OpenResult result); 151 152 const base::FilePath directory_; 153 154 enum ConnectionState { 155 NO_CONNECTION, 156 CONNECTION_IN_PROGRESS, 157 CONNECTION_FINISHED, 158 CONNECTION_SHUTDOWN 159 } connection_state_ = NO_CONNECTION; 160 bool database_initialized_ = false; 161 162 bool force_keep_session_state_ = false; 163 164 const scoped_refptr<base::SequencedTaskRunner> leveldb_task_runner_; 165 166 base::trace_event::MemoryAllocatorDumpGuid memory_dump_id_; 167 168 std::unique_ptr<AsyncDomStorageDatabase> database_; 169 bool tried_to_recreate_during_open_ = false; 170 bool in_memory_ = false; 171 172 std::vector<base::OnceClosure> on_database_opened_callbacks_; 173 174 // Maps between an origin and its prefixed LevelDB view. 175 std::map<url::Origin, std::unique_ptr<StorageAreaHolder>> areas_; 176 177 // Used to access old data for migration. 178 scoped_refptr<base::SequencedTaskRunner> legacy_task_runner_; 179 180 bool is_low_end_device_; 181 // Counts consecutive commit errors. If this number reaches a threshold, the 182 // whole database is thrown away. 183 int commit_error_count_ = 0; 184 bool tried_to_recover_from_commit_errors_ = false; 185 186 // The set of (origin) URLs whose storage should be cleared on shutdown. 187 std::set<GURL> origins_to_purge_on_shutdown_; 188 189 // Name of an extra histogram to log open results to, if not null. 190 const char* open_result_histogram_ = nullptr; 191 192 mojo::Receiver<mojom::LocalStorageControl> control_receiver_{this}; 193 194 base::WeakPtrFactory<LocalStorageImpl> weak_ptr_factory_{this}; 195 }; 196 197 } // namespace storage 198 199 #endif // COMPONENTS_SERVICES_STORAGE_DOM_STORAGE_LOCAL_STORAGE_IMPL_H_ 200