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/file_util.h"
10 #include "sql/statement.h"
11 #include "sql/transaction.h"
12 #include "xwalk/application/common/application_manifest_constants.h"
13 #include "xwalk/application/common/manifest_handlers/widget_handler.h"
17 namespace widget_keys = xwalk::application_widget_keys;
19 const char kPreferences[] = "preferences";
20 const char kPreferencesName[] = "name";
21 const char kPreferencesValue[] = "value";
22 const char kPreferencesReadonly[] = "readonly";
24 const base::FilePath::CharType kWidgetStorageExtension[] =
25 FILE_PATH_LITERAL(".widgetStorage");
27 const char kStorageTableName[] = "widget_storage";
29 const char kCreateStorageTableOp[] =
30 "CREATE TABLE widget_storage ("
31 "key TEXT NOT NULL UNIQUE PRIMARY KEY,"
32 "value TEXT NOT NULL,"
33 "read_only INTEGER )";
35 const char kClearStorageTableWithBindOp[] =
36 "DELETE FROM widget_storage WHERE read_only = ? ";
38 const char kInsertItemWithBindOp[] =
39 "INSERT INTO widget_storage (value, read_only, key) "
42 const char kUpdateItemWithBindOp[] =
43 "UPDATE widget_storage SET value = ? , read_only = ? "
46 const char kRemoveItemWithBindOp[] =
47 "DELETE FROM widget_storage WHERE key = ?";
49 const char kSelectTableLength[] =
50 "SELECT count(*) FROM widget_storage ";
52 const char kSelectCountWithBindOp[] =
53 "SELECT count(*) FROM widget_storage "
56 const char kSelectAllItem[] =
57 "SELECT key, value FROM widget_storage ";
59 const char kSelectReadOnlyWithBindOp[] =
60 "SELECT read_only FROM widget_storage "
65 namespace application {
67 AppWidgetStorage::AppWidgetStorage(Application* application,
68 const base::FilePath& data_dir)
69 : application_(application),
70 db_initialized_(false) {
71 sqlite_db_.reset(new sql::Connection);
73 base::FilePath name(application_->id());
74 base::FilePath::StringType storage_name =
75 name.value() + kWidgetStorageExtension;
76 data_path_ = data_dir.Append(storage_name);
78 if (!base::PathExists(data_dir) && !base::CreateDirectory(data_dir)) {
79 LOG(ERROR) << "Could not create widget storage path.";
84 LOG(ERROR) << "Initialize widget storage failed.";
89 AppWidgetStorage::~AppWidgetStorage() {
92 bool AppWidgetStorage::Init() {
93 if (!sqlite_db_->Open(data_path_)) {
94 LOG(ERROR) << "Unable to open widget storage DB.";
97 sqlite_db_->Preload();
99 if (!InitStorageTable()) {
100 LOG(ERROR) << "Unable to init widget storage table.";
103 return db_initialized_;
106 bool AppWidgetStorage::SaveConfigInfoItem(base::DictionaryValue* dict) {
110 bool read_only = false;
111 dict->GetString(kPreferencesName, &key);
112 dict->GetString(kPreferencesValue, &value);
113 dict->GetBoolean(kPreferencesReadonly, &read_only);
114 return AddEntry(key, value, read_only);
117 bool AppWidgetStorage::SaveConfigInfoInDB() {
119 static_cast<WidgetInfo*>(
120 application_->data()->GetManifestData(widget_keys::kWidgetKey));
121 base::DictionaryValue* widget_info = info->GetWidgetInfo();
123 LOG(ERROR) << "Fail to get parsed widget information.";
127 base::Value* pref_value;
128 widget_info->Get(kPreferences, &pref_value);
130 if (pref_value && pref_value->IsType(base::Value::TYPE_DICTIONARY)) {
131 base::DictionaryValue* dict;
132 pref_value->GetAsDictionary(&dict);
133 return SaveConfigInfoItem(dict);
134 } else if (pref_value && pref_value->IsType(base::Value::TYPE_LIST)) {
135 base::ListValue* list;
136 pref_value->GetAsList(&list);
138 for (base::ListValue::iterator it = list->begin();
139 it != list->end(); ++it) {
140 base::DictionaryValue* dict;
141 (*it)->GetAsDictionary(&dict);
142 if (!SaveConfigInfoItem(dict))
146 LOG(INFO) << "No widget preferences or preference type is not supported.";
152 bool AppWidgetStorage::InitStorageTable() {
153 if (sqlite_db_->DoesTableExist(kStorageTableName)) {
154 db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
158 sql::Transaction transaction(sqlite_db_.get());
160 if (!sqlite_db_->Execute(kCreateStorageTableOp))
162 if (!transaction.Commit())
165 db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
166 SaveConfigInfoInDB();
171 bool AppWidgetStorage::EntryExists(const std::string& key) const {
172 sql::Transaction transaction(sqlite_db_.get());
173 if (!transaction.Begin())
176 sql::Statement stmt(sqlite_db_->GetUniqueStatement(
177 kSelectCountWithBindOp));
178 stmt.BindString(0, key);
180 LOG(ERROR) << "An error occured when selecting count from DB.";
184 if (!transaction.Commit())
187 int exist = stmt.ColumnInt(0);
191 bool AppWidgetStorage::IsReadOnly(const std::string& key) {
192 sql::Transaction transaction(sqlite_db_.get());
193 if (!transaction.Begin())
196 sql::Statement stmt(sqlite_db_->GetUniqueStatement(
197 kSelectReadOnlyWithBindOp));
198 stmt.BindString(0, key);
200 LOG(ERROR) << "An error occured when selecting count from DB.";
204 if (!transaction.Commit())
207 return stmt.ColumnBool(0);
210 bool AppWidgetStorage::AddEntry(const std::string& key,
211 const std::string& value,
213 if (!db_initialized_ && !Init())
216 std::string operation;
217 if (!EntryExists(key)) {
218 operation = kInsertItemWithBindOp;
219 } else if (!IsReadOnly(key)) {
220 operation = kUpdateItemWithBindOp;
222 LOG(ERROR) << "Could not set read only item " << key;
226 sql::Transaction transaction(sqlite_db_.get());
227 if (!transaction.Begin())
230 sql::Statement stmt(sqlite_db_->GetUniqueStatement(
232 stmt.BindString(0, value);
233 stmt.BindBool(1, read_only);
234 stmt.BindString(2, key);
236 LOG(ERROR) << "An error occured when set item into DB.";
240 return transaction.Commit();
243 bool AppWidgetStorage::RemoveEntry(const std::string& key) {
244 if (!db_initialized_ && !Init())
247 if (IsReadOnly(key)) {
248 LOG(ERROR) << "Could not remove read only item " << key;
252 sql::Transaction transaction(sqlite_db_.get());
253 if (!transaction.Begin())
256 sql::Statement stmt(sqlite_db_->GetUniqueStatement(
257 kRemoveItemWithBindOp));
258 stmt.BindString(0, key);
261 LOG(ERROR) << "An error occured when removing item into DB.";
265 return transaction.Commit();
268 bool AppWidgetStorage::Clear() {
269 if (!db_initialized_ && !Init())
272 sql::Transaction transaction(sqlite_db_.get());
275 sql::Statement stmt(sqlite_db_->GetUniqueStatement(
276 kClearStorageTableWithBindOp));
277 stmt.BindBool(0, false);
280 LOG(ERROR) << "An error occured when removing item into DB.";
284 return transaction.Commit();
287 bool AppWidgetStorage::GetAllEntries(base::DictionaryValue* result) {
292 if (!db_initialized_ && !Init())
295 sql::Statement stmt(sqlite_db_->GetUniqueStatement(kSelectAllItem));
296 while (stmt.Step()) {
297 key = stmt.ColumnString(0);
298 value = stmt.ColumnString(1);
299 result->SetString(key, value);
305 } // namespace application