1 // Copyright (c) 2014 Intel Corporation. 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.
5 #include "xwalk/application/extension/application_widget_storage.h"
9 #include "base/files/file_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "sql/statement.h"
12 #include "sql/transaction.h"
13 #include "xwalk/application/common/application_manifest_constants.h"
14 #include "xwalk/application/common/manifest_handlers/widget_handler.h"
18 namespace widget_keys = xwalk::application_widget_keys;
20 const char kPreferences[] = "preferences";
21 const char kPreferencesName[] = "name";
22 const char kPreferencesValue[] = "value";
23 const char kPreferencesReadonly[] = "readonly";
25 const char kStorageTableName[] = "widget_storage";
27 const char kCreateStorageTableOp[] =
28 "CREATE TABLE widget_storage ("
29 "key TEXT NOT NULL UNIQUE PRIMARY KEY,"
30 "value TEXT NOT NULL,"
31 "read_only INTEGER )";
33 const char kClearStorageTableWithBindOp[] =
34 "DELETE FROM widget_storage WHERE read_only = ? ";
36 const char kInsertItemWithBindOp[] =
37 "INSERT INTO widget_storage (value, read_only, key) "
40 const char kUpdateItemWithBindOp[] =
41 "UPDATE widget_storage SET value = ? , read_only = ? "
44 const char kRemoveItemWithBindOp[] =
45 "DELETE FROM widget_storage WHERE key = ?";
47 const char kSelectTableLength[] =
48 "SELECT count(*) FROM widget_storage ";
50 const char kSelectCountWithBindOp[] =
51 "SELECT count(*) FROM widget_storage "
54 const char kSelectAllItem[] =
55 "SELECT key, value FROM widget_storage ";
57 const char kSelectValueWithBindOp[] =
58 "SELECT value FROM widget_storage "
61 const char kSelectReadOnlyWithBindOp[] =
62 "SELECT read_only FROM widget_storage "
67 namespace application {
69 AppWidgetStorage::AppWidgetStorage(Application* application,
70 const base::FilePath& data_dir)
71 : application_(application),
72 db_initialized_(false),
73 data_path_(data_dir) {
74 sqlite_db_.reset(new sql::Connection);
77 LOG(ERROR) << "Initialize widget storage failed.";
82 AppWidgetStorage::~AppWidgetStorage() {
85 bool AppWidgetStorage::Init() {
86 if (!sqlite_db_->Open(data_path_)) {
87 LOG(ERROR) << "Unable to open widget storage DB.";
90 sqlite_db_->Preload();
92 if (!InitStorageTable()) {
93 LOG(ERROR) << "Unable to init widget storage table.";
96 return db_initialized_;
99 bool AppWidgetStorage::SaveConfigInfoItem(base::DictionaryValue* dict) {
103 bool read_only = false;
104 if (dict->GetString(kPreferencesName, &key) &&
105 dict->GetString(kPreferencesValue, &value) &&
106 dict->GetBoolean(kPreferencesReadonly, &read_only))
107 return AddEntry(key, value, read_only);
111 bool AppWidgetStorage::SaveConfigInfoInDB() {
113 static_cast<WidgetInfo*>(
114 application_->data()->GetManifestData(widget_keys::kWidgetKey));
115 base::DictionaryValue* widget_info = info->GetWidgetInfo();
117 LOG(ERROR) << "Fail to get parsed widget information.";
121 base::Value* pref_value = NULL;
122 widget_info->Get(kPreferences, &pref_value);
124 if (pref_value && pref_value->IsType(base::Value::TYPE_DICTIONARY)) {
125 base::DictionaryValue* dict;
126 pref_value->GetAsDictionary(&dict);
127 return SaveConfigInfoItem(dict);
128 } else if (pref_value && pref_value->IsType(base::Value::TYPE_LIST)) {
129 base::ListValue* list;
130 pref_value->GetAsList(&list);
132 for (base::ListValue::iterator it = list->begin();
133 it != list->end(); ++it) {
134 base::DictionaryValue* dict;
135 (*it)->GetAsDictionary(&dict);
136 if (!SaveConfigInfoItem(dict))
140 LOG(INFO) << "No widget preferences or preference type is not supported.";
146 bool AppWidgetStorage::InitStorageTable() {
147 if (sqlite_db_->DoesTableExist(kStorageTableName)) {
148 db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
152 sql::Transaction transaction(sqlite_db_.get());
153 if (!transaction.Begin())
155 if (!sqlite_db_->Execute(kCreateStorageTableOp))
157 if (!transaction.Commit())
160 db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
161 SaveConfigInfoInDB();
166 bool AppWidgetStorage::EntryExists(const std::string& key) const {
167 sql::Transaction transaction(sqlite_db_.get());
168 if (!transaction.Begin())
171 sql::Statement stmt(sqlite_db_->GetUniqueStatement(
172 kSelectCountWithBindOp));
173 stmt.BindString(0, key);
175 LOG(ERROR) << "There is no item in current DB.";
179 if (!transaction.Commit())
182 int exist = stmt.ColumnInt(0);
186 bool AppWidgetStorage::IsReadOnly(const std::string& key) {
187 sql::Transaction transaction(sqlite_db_.get());
188 if (!transaction.Begin())
191 sql::Statement stmt(sqlite_db_->GetUniqueStatement(
192 kSelectReadOnlyWithBindOp));
193 stmt.BindString(0, key);
195 LOG(WARNING) << "The key doesn't exist or there is an error in current DB.";
199 if (!transaction.Commit())
202 return stmt.ColumnBool(0);
205 bool AppWidgetStorage::AddEntry(const std::string& key,
206 const std::string& value,
208 if (!db_initialized_ && !Init())
211 std::string operation;
212 if (!EntryExists(key)) {
213 operation = kInsertItemWithBindOp;
214 } else if (!IsReadOnly(key)) {
215 operation = kUpdateItemWithBindOp;
217 LOG(ERROR) << "Could not set read only item " << key;
221 sql::Transaction transaction(sqlite_db_.get());
222 if (!transaction.Begin())
225 sql::Statement stmt(sqlite_db_->GetUniqueStatement(
227 stmt.BindString(0, value);
228 stmt.BindBool(1, read_only);
229 stmt.BindString(2, key);
231 LOG(ERROR) << "An error occured when set item into DB.";
235 return transaction.Commit();
238 bool AppWidgetStorage::GetValueByKey(const std::string& key,
239 std::string* value) {
240 if (!db_initialized_ && !Init())
243 sql::Transaction transaction(sqlite_db_.get());
244 if (!transaction.Begin())
247 sql::Statement stmt(sqlite_db_->GetUniqueStatement(
248 kSelectValueWithBindOp));
249 stmt.BindString(0, key);
251 LOG(WARNING) << "The key doesn't exit or there is an error in current DB.";
255 if (!transaction.Commit())
258 *value = stmt.ColumnString(0);
262 bool AppWidgetStorage::RemoveEntry(const std::string& key) {
263 if (!db_initialized_ && !Init())
266 if (IsReadOnly(key)) {
267 LOG(ERROR) << "The key is readonly or it doesn't exist." << key;
271 sql::Transaction transaction(sqlite_db_.get());
272 if (!transaction.Begin())
275 sql::Statement stmt(sqlite_db_->GetUniqueStatement(
276 kRemoveItemWithBindOp));
277 stmt.BindString(0, key);
280 LOG(ERROR) << "An error occured when removing item into DB.";
284 return transaction.Commit();
287 bool AppWidgetStorage::Clear() {
288 if (!db_initialized_ && !Init())
291 sql::Transaction transaction(sqlite_db_.get());
292 if (!transaction.Begin())
295 sql::Statement stmt(sqlite_db_->GetUniqueStatement(
296 kClearStorageTableWithBindOp));
297 stmt.BindBool(0, false);
300 LOG(ERROR) << "An error occured when removing item into DB.";
304 return transaction.Commit();
307 bool AppWidgetStorage::GetAllEntries(base::DictionaryValue* result) {
312 if (!db_initialized_ && !Init())
315 sql::Statement stmt(sqlite_db_->GetUniqueStatement(kSelectAllItem));
316 while (stmt.Step()) {
317 key = stmt.ColumnString(0);
318 value = stmt.ColumnString(1);
319 result->SetString(key, value);
325 } // namespace application