1// Copyright 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_DOM_STORAGE_SESSION_STORAGE_DATABASE_H_ 6#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_DATABASE_H_ 7 8#include <map> 9#include <string> 10 11#include "base/files/file_path.h" 12#include "base/memory/ref_counted.h" 13#include "base/memory/scoped_ptr.h" 14#include "base/synchronization/lock.h" 15#include "content/common/content_export.h" 16#include "content/common/dom_storage/dom_storage_types.h" 17#include "third_party/leveldatabase/src/include/leveldb/status.h" 18 19class GURL; 20 21namespace leveldb { 22class DB; 23struct ReadOptions; 24class WriteBatch; 25} // namespace leveldb 26 27namespace content { 28 29// SessionStorageDatabase holds the data from multiple namespaces and multiple 30// origins. All DOMStorageAreas for session storage share the same 31// SessionStorageDatabase. 32 33// Only one thread is allowed to call the public functions other than 34// ReadAreaValues and ReadNamespacesAndOrigins. Other threads are allowed to 35// call ReadAreaValues and ReadNamespacesAndOrigins. 36class CONTENT_EXPORT SessionStorageDatabase : 37 public base::RefCountedThreadSafe<SessionStorageDatabase> { 38 public: 39 explicit SessionStorageDatabase(const base::FilePath& file_path); 40 41 // Reads the (key, value) pairs for |namespace_id| and |origin|. |result| is 42 // assumed to be empty and any duplicate keys will be overwritten. If the 43 // database exists on disk then it will be opened. If it does not exist then 44 // it will not be created and |result| will be unmodified. 45 void ReadAreaValues(const std::string& namespace_id, 46 const GURL& origin, 47 DOMStorageValuesMap* result); 48 49 // Updates the data for |namespace_id| and |origin|. Will remove all keys 50 // before updating the database if |clear_all_first| is set. Then all entries 51 // in |changes| will be examined - keys mapped to a null NullableString16 will 52 // be removed and all others will be inserted/updated as appropriate. It is 53 // allowed to write data into a shallow copy created by CloneNamespace, and in 54 // that case the copy will be made deep before writing the values. 55 bool CommitAreaChanges(const std::string& namespace_id, 56 const GURL& origin, 57 bool clear_all_first, 58 const DOMStorageValuesMap& changes); 59 60 // Creates shallow copies of the areas for |namespace_id| and associates them 61 // with |new_namespace_id|. 62 bool CloneNamespace(const std::string& namespace_id, 63 const std::string& new_namespace_id); 64 65 // Deletes the data for |namespace_id| and |origin|. 66 bool DeleteArea(const std::string& namespace_id, const GURL& origin); 67 68 // Deletes the data for |namespace_id|. 69 bool DeleteNamespace(const std::string& namespace_id); 70 71 // Reads the namespace IDs and origins present in the database. 72 bool ReadNamespacesAndOrigins( 73 std::map<std::string, std::vector<GURL> >* namespaces_and_origins); 74 75 private: 76 friend class base::RefCountedThreadSafe<SessionStorageDatabase>; 77 class DBOperation; 78 friend class SessionStorageDatabase::DBOperation; 79 friend class SessionStorageDatabaseTest; 80 81 ~SessionStorageDatabase(); 82 83 // Opens the database at file_path_ if it exists already and creates it if 84 // |create_if_needed| is true. Returns true if the database was opened, false 85 // if the opening failed or was not necessary (the database doesn't exist and 86 // |create_if_needed| is false). The possible failures are: 87 // - leveldb cannot open the database. 88 // - The database is in an inconsistent or errored state. 89 bool LazyOpen(bool create_if_needed); 90 91 // Tries to open the database at file_path_, assigns |db| to point to the 92 // opened leveldb::DB instance. 93 leveldb::Status TryToOpen(leveldb::DB** db); 94 95 // Returns true if the database is already open, false otherwise. 96 bool IsOpen() const; 97 98 // Helpers for checking caller erros, invariants and database errors. All 99 // these return |ok|, for chaining. 100 bool CallerErrorCheck(bool ok) const; 101 bool ConsistencyCheck(bool ok); 102 bool DatabaseErrorCheck(bool ok); 103 104 // Helper functions. All return true if the operation succeeded, and false if 105 // it failed (a database error or a consistency error). If the return type is 106 // void, the operation cannot fail. If they return false, ConsistencyCheck or 107 // DatabaseErrorCheck have already been called. 108 109 // Creates a namespace for |namespace_id| and updates the next namespace id if 110 // needed. If |ok_if_exists| is false, checks that the namespace didn't exist 111 // before. 112 bool CreateNamespace(const std::string& namespace_id, 113 bool ok_if_exists, 114 leveldb::WriteBatch* batch); 115 116 // Reads the areas assoiated with |namespace_id| and puts the (origin, map_id) 117 // pairs into |areas|. 118 bool GetAreasInNamespace(const std::string& namespace_id, 119 std::map<std::string, std::string>* areas); 120 121 // Adds an association between |origin| and |map_id| into the namespace 122 // |namespace_id|. 123 void AddAreaToNamespace(const std::string& namespace_id, 124 const std::string& origin, 125 const std::string& map_id, 126 leveldb::WriteBatch* batch); 127 128 // Helpers for deleting data for |namespace_id| and |origin|. 129 bool DeleteAreaHelper(const std::string& namespace_id, 130 const std::string& origin, 131 leveldb::WriteBatch* batch); 132 133 // Retrieves the map id for |namespace_id| and |origin|. It's not an error if 134 // the map doesn't exist. 135 bool GetMapForArea(const std::string& namespace_id, 136 const std::string& origin, 137 const leveldb::ReadOptions& options, 138 bool* exists, 139 std::string* map_id); 140 141 // Creates a new map for |namespace_id| and |origin|. |map_id| will hold the 142 // id of the created map. If there is a map for |namespace_id| and |origin|, 143 // this just overwrites the map id. The caller is responsible for decreasing 144 // the ref count. 145 bool CreateMapForArea(const std::string& namespace_id, 146 const GURL& origin, 147 std::string* map_id, 148 leveldb::WriteBatch* batch); 149 // Reads the contents of the map |map_id| into |result|. If |only_keys| is 150 // true, only keys are aread from the database and the values in |result| will 151 // be empty. 152 bool ReadMap(const std::string& map_id, 153 const leveldb::ReadOptions& options, 154 DOMStorageValuesMap* result, 155 bool only_keys); 156 // Writes |values| into the map |map_id|. 157 void WriteValuesToMap(const std::string& map_id, 158 const DOMStorageValuesMap& values, 159 leveldb::WriteBatch* batch); 160 161 bool GetMapRefCount(const std::string& map_id, int64* ref_count); 162 bool IncreaseMapRefCount(const std::string& map_id, 163 leveldb::WriteBatch* batch); 164 // Decreases the ref count of a map by |decrease|. If the ref count goes to 0, 165 // deletes the map. 166 bool DecreaseMapRefCount(const std::string& map_id, 167 int decrease, 168 leveldb::WriteBatch* batch); 169 170 // Deletes all values in |map_id|. 171 bool ClearMap(const std::string& map_id, leveldb::WriteBatch* batch); 172 173 // Breaks the association between (|namespace_id|, |origin|) and |map_id| and 174 // creates a new map for (|namespace_id|, |origin|). Copies the data from the 175 // old map if |copy_data| is true. 176 bool DeepCopyArea(const std::string& namespace_id, 177 const GURL& origin, 178 bool copy_data, 179 std::string* map_id, 180 leveldb::WriteBatch* batch); 181 182 // Helper functions for creating the keys needed for the schema. 183 static std::string NamespaceStartKey(const std::string& namespace_id); 184 static std::string NamespaceKey(const std::string& namespace_id, 185 const std::string& origin); 186 static const char* NamespacePrefix(); 187 static std::string MapRefCountKey(const std::string& map_id); 188 static std::string MapKey(const std::string& map_id, const std::string& key); 189 static const char* NextMapIdKey(); 190 191 scoped_ptr<leveldb::DB> db_; 192 base::FilePath file_path_; 193 194 // For protecting the database opening code. Also guards the variables below. 195 base::Lock db_lock_; 196 197 // True if a database error has occurred (e.g., cannot read data). 198 bool db_error_; 199 // True if the database is in an inconsistent state. 200 bool is_inconsistent_; 201 // True if the database is in a failed or inconsistent state, and we have 202 // already deleted it (as an attempt to recover later). 203 bool invalid_db_deleted_; 204 205 // The number of database operations in progress. We need this so that we can 206 // delete an inconsistent database at the right moment. 207 int operation_count_; 208 209 DISALLOW_COPY_AND_ASSIGN(SessionStorageDatabase); 210}; 211 212} // namespace content 213 214#endif // CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_DATABASE_H_ 215