Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / content / browser / dom_storage / session_storage_database.h
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
19 class GURL;
20
21 namespace leveldb {
22 class DB;
23 struct ReadOptions;
24 class WriteBatch;
25 }  // namespace leveldb
26
27 namespace 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.
36 class 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_