1// Copyright 2014 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 EXTENSIONS_BROWSER_VALUE_STORE_VALUE_STORE_H_
6#define EXTENSIONS_BROWSER_VALUE_STORE_VALUE_STORE_H_
7
8#include <string>
9#include <vector>
10
11#include "base/memory/scoped_ptr.h"
12#include "base/values.h"
13#include "extensions/browser/value_store/value_store_change.h"
14
15// Interface for a storage area for Value objects.
16class ValueStore {
17 public:
18  // Error codes returned from storage methods.
19  enum ErrorCode {
20    OK,
21
22    // The failure was due to some kind of database corruption. Depending on
23    // what is corrupted, some part of the database may be recoverable.
24    //
25    // For example, if the on-disk representation of leveldb is corrupted, it's
26    // likely the whole database will need to be wiped and started again.
27    //
28    // If a single key has been committed with an invalid JSON representation,
29    // just that key can be deleted without affecting the rest of the database.
30    CORRUPTION,
31
32    // The failure was due to the store being read-only (for example, policy).
33    READ_ONLY,
34
35    // The failure was due to the store running out of space.
36    QUOTA_EXCEEDED,
37
38    // Any other error.
39    OTHER_ERROR,
40  };
41
42  // Bundles an ErrorCode with further metadata.
43  struct Error {
44    Error(ErrorCode code,
45          const std::string& message,
46          scoped_ptr<std::string> key);
47    ~Error();
48
49    static scoped_ptr<Error> Create(ErrorCode code,
50                                    const std::string& message,
51                                    scoped_ptr<std::string> key) {
52      return make_scoped_ptr(new Error(code, message, key.Pass()));
53    }
54
55    // The error code.
56    const ErrorCode code;
57
58    // Message associated with the error.
59    const std::string message;
60
61    // The key associated with the error, if any. Use a scoped_ptr here
62    // because empty-string is a valid key.
63    //
64    // TODO(kalman): add test(s) for an empty key.
65    const scoped_ptr<std::string> key;
66
67   private:
68    DISALLOW_COPY_AND_ASSIGN(Error);
69  };
70
71  // The result of a read operation (Get).
72  class ReadResultType {
73   public:
74    explicit ReadResultType(scoped_ptr<base::DictionaryValue> settings);
75    explicit ReadResultType(scoped_ptr<Error> error);
76    ~ReadResultType();
77
78    bool HasError() const { return error_; }
79
80    bool IsCorrupted() const {
81      return error_.get() && error_->code == CORRUPTION;
82    }
83
84    // Gets the settings read from the storage. Note that this represents
85    // the root object. If you request the value for key "foo", that value will
86    // be in |settings|.|foo|.
87    //
88    // Must only be called if there is no error.
89    base::DictionaryValue& settings() { return *settings_; }
90    scoped_ptr<base::DictionaryValue> PassSettings() {
91      return settings_.Pass();
92    }
93
94    // Only call if HasError is true.
95    const Error& error() const { return *error_; }
96    scoped_ptr<Error> PassError() { return error_.Pass(); }
97
98   private:
99    scoped_ptr<base::DictionaryValue> settings_;
100    scoped_ptr<Error> error_;
101
102    DISALLOW_COPY_AND_ASSIGN(ReadResultType);
103  };
104  typedef scoped_ptr<ReadResultType> ReadResult;
105
106  // The result of a write operation (Set/Remove/Clear).
107  class WriteResultType {
108   public:
109    explicit WriteResultType(scoped_ptr<ValueStoreChangeList> changes);
110    explicit WriteResultType(scoped_ptr<Error> error);
111    ~WriteResultType();
112
113    bool HasError() const { return error_; }
114
115    // Gets the list of changes to the settings which resulted from the write.
116    // Won't be present if the NO_GENERATE_CHANGES WriteOptions was given.
117    // Only call if HasError is false.
118    ValueStoreChangeList& changes() { return *changes_; }
119    scoped_ptr<ValueStoreChangeList> PassChanges() { return changes_.Pass(); }
120
121    // Only call if HasError is true.
122    const Error& error() const { return *error_; }
123    scoped_ptr<Error> PassError() { return error_.Pass(); }
124
125   private:
126    scoped_ptr<ValueStoreChangeList> changes_;
127    scoped_ptr<Error> error_;
128
129    DISALLOW_COPY_AND_ASSIGN(WriteResultType);
130  };
131  typedef scoped_ptr<WriteResultType> WriteResult;
132
133  // Options for write operations.
134  enum WriteOptionsValues {
135    // Callers should usually use this.
136    DEFAULTS = 0,
137
138    // Ignore any quota restrictions.
139    IGNORE_QUOTA = 1<<1,
140
141    // Don't generate the changes for a WriteResult.
142    NO_GENERATE_CHANGES = 1<<2,
143  };
144  typedef int WriteOptions;
145
146  virtual ~ValueStore() {}
147
148  // Helpers for making a Read/WriteResult.
149  template<typename T>
150  static ReadResult MakeReadResult(scoped_ptr<T> arg) {
151    return ReadResult(new ReadResultType(arg.Pass()));
152  }
153
154  template<typename T>
155  static WriteResult MakeWriteResult(scoped_ptr<T> arg) {
156    return WriteResult(new WriteResultType(arg.Pass()));
157  }
158
159  // Gets the amount of space being used by a single value, in bytes.
160  // Note: The GetBytesInUse methods are only used by extension settings at the
161  // moment. If these become more generally useful, the
162  // SettingsStorageQuotaEnforcer and WeakUnlimitedSettingsStorage classes
163  // should be moved to the value_store directory.
164  virtual size_t GetBytesInUse(const std::string& key) = 0;
165
166  // Gets the total amount of space being used by multiple values, in bytes.
167  virtual size_t GetBytesInUse(const std::vector<std::string>& keys) = 0;
168
169  // Gets the total amount of space being used by this storage area, in bytes.
170  virtual size_t GetBytesInUse() = 0;
171
172  // Gets a single value from storage.
173  virtual ReadResult Get(const std::string& key) = 0;
174
175  // Gets multiple values from storage.
176  virtual ReadResult Get(const std::vector<std::string>& keys) = 0;
177
178  // Gets all values from storage.
179  virtual ReadResult Get() = 0;
180
181  // Sets a single key to a new value.
182  virtual WriteResult Set(WriteOptions options,
183                          const std::string& key,
184                          const base::Value& value) = 0;
185
186  // Sets multiple keys to new values.
187  virtual WriteResult Set(
188      WriteOptions options, const base::DictionaryValue& values) = 0;
189
190  // Removes a key from the storage.
191  virtual WriteResult Remove(const std::string& key) = 0;
192
193  // Removes multiple keys from the storage.
194  virtual WriteResult Remove(const std::vector<std::string>& keys) = 0;
195
196  // Clears the storage.
197  virtual WriteResult Clear() = 0;
198
199  // In the event of corruption, the ValueStore should be able to restore
200  // itself. This means deleting local corrupted files. If only a few keys are
201  // corrupted, then some of the database may be saved. If the full database is
202  // corrupted, this will erase it in its entirety.
203  // Returns true on success, false on failure. The only way this will fail is
204  // if we also cannot delete the database file.
205  // Note: This method may be expensive; some implementations may need to read
206  // the entire database to restore. Use sparingly.
207  // Note: This method (and the following RestoreKey()) are rude, and do not
208  // make any logs, track changes, or other generally polite things. Please do
209  // not use these as substitutes for Clear() and Remove().
210  virtual bool Restore() = 0;
211
212  // Similar to Restore(), but for only a particular key. If the key is corrupt,
213  // this will forcefully remove the key. It does not look at the database on
214  // the whole, which makes it faster, but does not guarantee there is no
215  // additional corruption.
216  // Returns true on success, and false on failure. If false, the next step is
217  // probably to Restore() the whole database.
218  virtual bool RestoreKey(const std::string& key) = 0;
219};
220
221#endif  // EXTENSIONS_BROWSER_VALUE_STORE_VALUE_STORE_H_
222