// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef EXTENSIONS_BROWSER_VALUE_STORE_VALUE_STORE_H_ #define EXTENSIONS_BROWSER_VALUE_STORE_VALUE_STORE_H_ #include <string> #include <vector> #include "base/memory/scoped_ptr.h" #include "base/values.h" #include "extensions/browser/value_store/value_store_change.h" // Interface for a storage area for Value objects. class ValueStore { public: // Error codes returned from storage methods. enum ErrorCode { OK, // The failure was due to some kind of database corruption. Depending on // what is corrupted, some part of the database may be recoverable. // // For example, if the on-disk representation of leveldb is corrupted, it's // likely the whole database will need to be wiped and started again. // // If a single key has been committed with an invalid JSON representation, // just that key can be deleted without affecting the rest of the database. CORRUPTION, // The failure was due to the store being read-only (for example, policy). READ_ONLY, // The failure was due to the store running out of space. QUOTA_EXCEEDED, // Any other error. OTHER_ERROR, }; // Bundles an ErrorCode with further metadata. struct Error { Error(ErrorCode code, const std::string& message, scoped_ptr<std::string> key); ~Error(); static scoped_ptr<Error> Create(ErrorCode code, const std::string& message, scoped_ptr<std::string> key) { return make_scoped_ptr(new Error(code, message, key.Pass())); } // The error code. const ErrorCode code; // Message associated with the error. const std::string message; // The key associated with the error, if any. Use a scoped_ptr here // because empty-string is a valid key. // // TODO(kalman): add test(s) for an empty key. const scoped_ptr<std::string> key; private: DISALLOW_COPY_AND_ASSIGN(Error); }; // The result of a read operation (Get). class ReadResultType { public: explicit ReadResultType(scoped_ptr<base::DictionaryValue> settings); explicit ReadResultType(scoped_ptr<Error> error); ~ReadResultType(); bool HasError() const { return error_; } bool IsCorrupted() const { return error_.get() && error_->code == CORRUPTION; } // Gets the settings read from the storage. Note that this represents // the root object. If you request the value for key "foo", that value will // be in |settings|.|foo|. // // Must only be called if there is no error. base::DictionaryValue& settings() { return *settings_; } scoped_ptr<base::DictionaryValue> PassSettings() { return settings_.Pass(); } // Only call if HasError is true. const Error& error() const { return *error_; } scoped_ptr<Error> PassError() { return error_.Pass(); } private: scoped_ptr<base::DictionaryValue> settings_; scoped_ptr<Error> error_; DISALLOW_COPY_AND_ASSIGN(ReadResultType); }; typedef scoped_ptr<ReadResultType> ReadResult; // The result of a write operation (Set/Remove/Clear). class WriteResultType { public: explicit WriteResultType(scoped_ptr<ValueStoreChangeList> changes); explicit WriteResultType(scoped_ptr<Error> error); ~WriteResultType(); bool HasError() const { return error_; } // Gets the list of changes to the settings which resulted from the write. // Won't be present if the NO_GENERATE_CHANGES WriteOptions was given. // Only call if HasError is false. ValueStoreChangeList& changes() { return *changes_; } scoped_ptr<ValueStoreChangeList> PassChanges() { return changes_.Pass(); } // Only call if HasError is true. const Error& error() const { return *error_; } scoped_ptr<Error> PassError() { return error_.Pass(); } private: scoped_ptr<ValueStoreChangeList> changes_; scoped_ptr<Error> error_; DISALLOW_COPY_AND_ASSIGN(WriteResultType); }; typedef scoped_ptr<WriteResultType> WriteResult; // Options for write operations. enum WriteOptionsValues { // Callers should usually use this. DEFAULTS = 0, // Ignore any quota restrictions. IGNORE_QUOTA = 1<<1, // Don't generate the changes for a WriteResult. NO_GENERATE_CHANGES = 1<<2, }; typedef int WriteOptions; virtual ~ValueStore() {} // Helpers for making a Read/WriteResult. template<typename T> static ReadResult MakeReadResult(scoped_ptr<T> arg) { return ReadResult(new ReadResultType(arg.Pass())); } template<typename T> static WriteResult MakeWriteResult(scoped_ptr<T> arg) { return WriteResult(new WriteResultType(arg.Pass())); } // Gets the amount of space being used by a single value, in bytes. // Note: The GetBytesInUse methods are only used by extension settings at the // moment. If these become more generally useful, the // SettingsStorageQuotaEnforcer and WeakUnlimitedSettingsStorage classes // should be moved to the value_store directory. virtual size_t GetBytesInUse(const std::string& key) = 0; // Gets the total amount of space being used by multiple values, in bytes. virtual size_t GetBytesInUse(const std::vector<std::string>& keys) = 0; // Gets the total amount of space being used by this storage area, in bytes. virtual size_t GetBytesInUse() = 0; // Gets a single value from storage. virtual ReadResult Get(const std::string& key) = 0; // Gets multiple values from storage. virtual ReadResult Get(const std::vector<std::string>& keys) = 0; // Gets all values from storage. virtual ReadResult Get() = 0; // Sets a single key to a new value. virtual WriteResult Set(WriteOptions options, const std::string& key, const base::Value& value) = 0; // Sets multiple keys to new values. virtual WriteResult Set( WriteOptions options, const base::DictionaryValue& values) = 0; // Removes a key from the storage. virtual WriteResult Remove(const std::string& key) = 0; // Removes multiple keys from the storage. virtual WriteResult Remove(const std::vector<std::string>& keys) = 0; // Clears the storage. virtual WriteResult Clear() = 0; // In the event of corruption, the ValueStore should be able to restore // itself. This means deleting local corrupted files. If only a few keys are // corrupted, then some of the database may be saved. If the full database is // corrupted, this will erase it in its entirety. // Returns true on success, false on failure. The only way this will fail is // if we also cannot delete the database file. // Note: This method may be expensive; some implementations may need to read // the entire database to restore. Use sparingly. // Note: This method (and the following RestoreKey()) are rude, and do not // make any logs, track changes, or other generally polite things. Please do // not use these as substitutes for Clear() and Remove(). virtual bool Restore() = 0; // Similar to Restore(), but for only a particular key. If the key is corrupt, // this will forcefully remove the key. It does not look at the database on // the whole, which makes it faster, but does not guarantee there is no // additional corruption. // Returns true on success, and false on failure. If false, the next step is // probably to Restore() the whole database. virtual bool RestoreKey(const std::string& key) = 0; }; #endif // EXTENSIONS_BROWSER_VALUE_STORE_VALUE_STORE_H_