blob: 09d4773fea154994ba33859f294f22d83a9c44b8 [file] [log] [blame]
Ben Murdochbb1529c2013-08-08 10:24:53 +01001// Copyright 2013 The Chromium Authors. All rights reserved.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Murdochbb1529c2013-08-08 10:24:53 +01005#ifndef CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_DATABASE_H_
6#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_DATABASE_H_
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01007
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"
Ben Murdochbb1529c2013-08-08 10:24:53 +010015#include "content/common/content_export.h"
16#include "content/common/dom_storage/dom_storage_types.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010017#include "third_party/leveldatabase/src/include/leveldb/status.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010018
19class GURL;
20
21namespace leveldb {
22class DB;
23struct ReadOptions;
24class WriteBatch;
25} // namespace leveldb
26
Ben Murdochbb1529c2013-08-08 10:24:53 +010027namespace content {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010028
29// SessionStorageDatabase holds the data from multiple namespaces and multiple
Ben Murdochbb1529c2013-08-08 10:24:53 +010030// origins. All DOMStorageAreas for session storage share the same
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010031// 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.
Ben Murdochbb1529c2013-08-08 10:24:53 +010036class CONTENT_EXPORT SessionStorageDatabase :
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010037 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,
Ben Murdochbb1529c2013-08-08 10:24:53 +010047 DOMStorageValuesMap* result);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010048
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,
Ben Murdochbb1529c2013-08-08 10:24:53 +010058 const DOMStorageValuesMap& changes);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010059
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 friend class SessionStorageDatabaseTest;
78
79 ~SessionStorageDatabase();
80
81 // Opens the database at file_path_ if it exists already and creates it if
82 // |create_if_needed| is true. Returns true if the database was opened, false
83 // if the opening failed or was not necessary (the database doesn't exist and
84 // |create_if_needed| is false). The possible failures are:
85 // - leveldb cannot open the database.
86 // - The database is in an inconsistent or errored state.
87 bool LazyOpen(bool create_if_needed);
88
89 // Tries to open the database at file_path_, assigns |db| to point to the
90 // opened leveldb::DB instance.
91 leveldb::Status TryToOpen(leveldb::DB** db);
92
93 // Returns true if the database is already open, false otherwise.
94 bool IsOpen() const;
95
96 // Helpers for checking caller erros, invariants and database errors. All
97 // these return |ok|, for chaining.
98 bool CallerErrorCheck(bool ok) const;
99 bool ConsistencyCheck(bool ok);
100 bool DatabaseErrorCheck(bool ok);
101
102 // Helper functions. All return true if the operation succeeded, and false if
103 // it failed (a database error or a consistency error). If the return type is
104 // void, the operation cannot fail. If they return false, ConsistencyCheck or
105 // DatabaseErrorCheck have already been called.
106
107 // Creates a namespace for |namespace_id| and updates the next namespace id if
108 // needed. If |ok_if_exists| is false, checks that the namespace didn't exist
109 // before.
110 bool CreateNamespace(const std::string& namespace_id,
111 bool ok_if_exists,
112 leveldb::WriteBatch* batch);
113
114 // Reads the areas assoiated with |namespace_id| and puts the (origin, map_id)
115 // pairs into |areas|.
116 bool GetAreasInNamespace(const std::string& namespace_id,
117 std::map<std::string, std::string>* areas);
118
119 // Adds an association between |origin| and |map_id| into the namespace
120 // |namespace_id|.
121 void AddAreaToNamespace(const std::string& namespace_id,
122 const std::string& origin,
123 const std::string& map_id,
124 leveldb::WriteBatch* batch);
125
126 // Helpers for deleting data for |namespace_id| and |origin|.
127 bool DeleteAreaHelper(const std::string& namespace_id,
128 const std::string& origin,
129 leveldb::WriteBatch* batch);
130
131 // Retrieves the map id for |namespace_id| and |origin|. It's not an error if
132 // the map doesn't exist.
133 bool GetMapForArea(const std::string& namespace_id,
134 const std::string& origin,
135 const leveldb::ReadOptions& options,
136 bool* exists,
137 std::string* map_id);
138
139 // Creates a new map for |namespace_id| and |origin|. |map_id| will hold the
140 // id of the created map. If there is a map for |namespace_id| and |origin|,
141 // this just overwrites the map id. The caller is responsible for decreasing
142 // the ref count.
143 bool CreateMapForArea(const std::string& namespace_id,
144 const GURL& origin,
145 std::string* map_id,
146 leveldb::WriteBatch* batch);
147 // Reads the contents of the map |map_id| into |result|. If |only_keys| is
148 // true, only keys are aread from the database and the values in |result| will
149 // be empty.
150 bool ReadMap(const std::string& map_id,
151 const leveldb::ReadOptions& options,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100152 DOMStorageValuesMap* result,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100153 bool only_keys);
154 // Writes |values| into the map |map_id|.
155 void WriteValuesToMap(const std::string& map_id,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100156 const DOMStorageValuesMap& values,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100157 leveldb::WriteBatch* batch);
158
159 bool GetMapRefCount(const std::string& map_id, int64* ref_count);
160 bool IncreaseMapRefCount(const std::string& map_id,
161 leveldb::WriteBatch* batch);
162 // Decreases the ref count of a map by |decrease|. If the ref count goes to 0,
163 // deletes the map.
164 bool DecreaseMapRefCount(const std::string& map_id,
165 int decrease,
166 leveldb::WriteBatch* batch);
167
168 // Deletes all values in |map_id|.
169 bool ClearMap(const std::string& map_id, leveldb::WriteBatch* batch);
170
171 // Breaks the association between (|namespace_id|, |origin|) and |map_id| and
172 // creates a new map for (|namespace_id|, |origin|). Copies the data from the
173 // old map if |copy_data| is true.
174 bool DeepCopyArea(const std::string& namespace_id,
175 const GURL& origin,
176 bool copy_data,
177 std::string* map_id,
178 leveldb::WriteBatch* batch);
179
180 // Helper functions for creating the keys needed for the schema.
181 static std::string NamespaceStartKey(const std::string& namespace_id);
182 static std::string NamespaceKey(const std::string& namespace_id,
183 const std::string& origin);
184 static const char* NamespacePrefix();
185 static std::string MapRefCountKey(const std::string& map_id);
186 static std::string MapKey(const std::string& map_id, const std::string& key);
187 static const char* NextMapIdKey();
188
189 scoped_ptr<leveldb::DB> db_;
190 base::FilePath file_path_;
191
192 // For protecting the database opening code.
193 base::Lock db_lock_;
194
195 // True if a database error has occurred (e.g., cannot read data).
196 bool db_error_;
197 // True if the database is in an inconsistent state.
198 bool is_inconsistent_;
199
200 DISALLOW_COPY_AND_ASSIGN(SessionStorageDatabase);
201};
202
Ben Murdochbb1529c2013-08-08 10:24:53 +0100203} // namespace content
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100204
Ben Murdochbb1529c2013-08-08 10:24:53 +0100205#endif // CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_DATABASE_H_