Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / extension / application_widget_storage.cc
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.
4
5 #include "xwalk/application/extension/application_widget_storage.h"
6
7 #include <string>
8
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"
15
16 namespace {
17
18 namespace widget_keys = xwalk::application_widget_keys;
19
20 const char kPreferences[] = "preferences";
21 const char kPreferencesName[] = "name";
22 const char kPreferencesValue[] = "value";
23 const char kPreferencesReadonly[] = "readonly";
24
25 const char kStorageTableName[] = "widget_storage";
26
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 )";
32
33 const char kClearStorageTableWithBindOp[] =
34     "DELETE FROM widget_storage WHERE read_only = ? ";
35
36 const char kInsertItemWithBindOp[] =
37     "INSERT INTO widget_storage (value, read_only, key) "
38     "VALUES(?,?,?)";
39
40 const char kUpdateItemWithBindOp[] =
41     "UPDATE widget_storage SET value = ? , read_only = ? "
42     "WHERE key = ?";
43
44 const char kRemoveItemWithBindOp[] =
45     "DELETE FROM widget_storage WHERE key = ?";
46
47 const char kSelectTableLength[] =
48     "SELECT count(*) FROM widget_storage ";
49
50 const char kSelectCountWithBindOp[] =
51     "SELECT count(*) FROM widget_storage "
52     "WHERE key = ?";
53
54 const char kSelectAllItem[] =
55     "SELECT key, value FROM widget_storage ";
56
57 const char kSelectValueWithBindOp[] =
58     "SELECT value FROM widget_storage "
59     "WHERE key = ?";
60
61 const char kSelectReadOnlyWithBindOp[] =
62     "SELECT read_only FROM widget_storage "
63     "WHERE key = ?";
64 }  // namespace
65
66 namespace xwalk {
67 namespace application {
68
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);
75
76   if (!Init()) {
77     LOG(ERROR) << "Initialize widget storage failed.";
78     return;
79   }
80 }
81
82 AppWidgetStorage::~AppWidgetStorage() {
83 }
84
85 bool AppWidgetStorage::Init() {
86   if (!sqlite_db_->Open(data_path_)) {
87     LOG(ERROR) << "Unable to open widget storage DB.";
88     return false;
89   }
90   sqlite_db_->Preload();
91
92   if (!InitStorageTable()) {
93      LOG(ERROR) << "Unable to init widget storage table.";
94      return false;
95   }
96   return db_initialized_;
97 }
98
99 bool AppWidgetStorage::SaveConfigInfoItem(base::DictionaryValue* dict) {
100   DCHECK(dict);
101   std::string key;
102   std::string value;
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);
108   return false;
109 }
110
111 bool AppWidgetStorage::SaveConfigInfoInDB() {
112   WidgetInfo* info =
113       static_cast<WidgetInfo*>(
114       application_->data()->GetManifestData(widget_keys::kWidgetKey));
115   base::DictionaryValue* widget_info = info->GetWidgetInfo();
116   if (!widget_info) {
117     LOG(ERROR) << "Fail to get parsed widget information.";
118     return false;
119   }
120
121   base::Value* pref_value = NULL;
122   widget_info->Get(kPreferences, &pref_value);
123
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);
131
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))
137         return false;
138     }
139   } else {
140     LOG(INFO) << "No widget preferences or preference type is not supported.";
141   }
142
143   return true;
144 }
145
146 bool AppWidgetStorage::InitStorageTable() {
147   if (sqlite_db_->DoesTableExist(kStorageTableName)) {
148     db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
149     return true;
150   }
151
152   sql::Transaction transaction(sqlite_db_.get());
153   if (!transaction.Begin())
154     return false;
155   if (!sqlite_db_->Execute(kCreateStorageTableOp))
156     return false;
157   if (!transaction.Commit())
158     return false;
159
160   db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
161   SaveConfigInfoInDB();
162
163   return true;
164 }
165
166 bool AppWidgetStorage::EntryExists(const std::string& key) const {
167   sql::Transaction transaction(sqlite_db_.get());
168   if (!transaction.Begin())
169     return false;
170
171   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
172       kSelectCountWithBindOp));
173   stmt.BindString(0, key);
174   if (!stmt.Step()) {
175     LOG(ERROR) << "There is no item in current DB.";
176     return false;
177   }
178
179   if (!transaction.Commit())
180     return false;
181
182   int exist = stmt.ColumnInt(0);
183   return exist > 0;
184 }
185
186 bool AppWidgetStorage::IsReadOnly(const std::string& key) {
187   sql::Transaction transaction(sqlite_db_.get());
188   if (!transaction.Begin())
189     return false;
190
191   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
192       kSelectReadOnlyWithBindOp));
193   stmt.BindString(0, key);
194   if (!stmt.Step()) {
195     LOG(WARNING) << "The key doesn't exist or there is an error in current DB.";
196     return false;
197   }
198
199   if (!transaction.Commit())
200     return false;
201
202   return stmt.ColumnBool(0);
203 }
204
205 bool AppWidgetStorage::AddEntry(const std::string& key,
206                                const std::string& value,
207                                bool read_only) {
208   if (!db_initialized_ && !Init())
209     return false;
210
211   std::string operation;
212   if (!EntryExists(key)) {
213     operation = kInsertItemWithBindOp;
214   } else if (!IsReadOnly(key)) {
215     operation = kUpdateItemWithBindOp;
216   } else {
217     LOG(ERROR) << "Could not set read only item " << key;
218     return false;
219   }
220
221   sql::Transaction transaction(sqlite_db_.get());
222   if (!transaction.Begin())
223     return false;
224
225   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
226     operation.c_str()));
227   stmt.BindString(0, value);
228   stmt.BindBool(1, read_only);
229   stmt.BindString(2, key);
230   if (!stmt.Run()) {
231     LOG(ERROR) << "An error occured when set item into DB.";
232     return false;
233   }
234
235   return transaction.Commit();
236 }
237
238 bool AppWidgetStorage::GetValueByKey(const std::string& key,
239                                      std::string* value) {
240   if (!db_initialized_ && !Init())
241     return false;
242
243   sql::Transaction transaction(sqlite_db_.get());
244   if (!transaction.Begin())
245     return false;
246
247   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
248       kSelectValueWithBindOp));
249   stmt.BindString(0, key);
250   if (!stmt.Step()) {
251     LOG(WARNING) << "The key doesn't exit or there is an error in current DB.";
252     return false;
253   }
254
255   if (!transaction.Commit())
256     return false;
257
258   *value = stmt.ColumnString(0);
259   return true;
260 }
261
262 bool AppWidgetStorage::RemoveEntry(const std::string& key) {
263   if (!db_initialized_ && !Init())
264     return false;
265
266   if (IsReadOnly(key)) {
267     LOG(ERROR) << "The key is readonly or it doesn't exist." << key;
268     return false;
269   }
270
271   sql::Transaction transaction(sqlite_db_.get());
272   if (!transaction.Begin())
273     return false;
274
275   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
276       kRemoveItemWithBindOp));
277   stmt.BindString(0, key);
278
279   if (!stmt.Run()) {
280     LOG(ERROR) << "An error occured when removing item into DB.";
281     return false;
282   }
283
284   return transaction.Commit();
285 }
286
287 bool AppWidgetStorage::Clear() {
288   if (!db_initialized_ && !Init())
289     return false;
290
291   sql::Transaction transaction(sqlite_db_.get());
292   if (!transaction.Begin())
293     return false;
294
295   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
296       kClearStorageTableWithBindOp));
297   stmt.BindBool(0, false);
298
299   if (!stmt.Run()) {
300     LOG(ERROR) << "An error occured when removing item into DB.";
301     return false;
302   }
303
304   return transaction.Commit();
305 }
306
307 bool AppWidgetStorage::GetAllEntries(base::DictionaryValue* result) {
308   std::string key;
309   std::string value;
310   DCHECK(result);
311
312   if (!db_initialized_ && !Init())
313     return false;
314
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);
320   }
321
322   return true;
323 }
324
325 }  // namespace application
326 }  // namespace xwalk