Upstream version 7.36.149.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/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 kSelectReadOnlyWithBindOp[] =
58     "SELECT read_only FROM widget_storage "
59     "WHERE key = ?";
60 }  // namespace
61
62 namespace xwalk {
63 namespace application {
64
65 AppWidgetStorage::AppWidgetStorage(Application* application,
66                                    const base::FilePath& data_dir)
67     : application_(application),
68       db_initialized_(false),
69       data_path_(data_dir) {
70   sqlite_db_.reset(new sql::Connection);
71
72   if (!Init()) {
73     LOG(ERROR) << "Initialize widget storage failed.";
74     return;
75   }
76 }
77
78 AppWidgetStorage::~AppWidgetStorage() {
79 }
80
81 bool AppWidgetStorage::Init() {
82   if (!sqlite_db_->Open(data_path_)) {
83     LOG(ERROR) << "Unable to open widget storage DB.";
84     return false;
85   }
86   sqlite_db_->Preload();
87
88   if (!InitStorageTable()) {
89      LOG(ERROR) << "Unable to init widget storage table.";
90      return false;
91   }
92   return db_initialized_;
93 }
94
95 bool AppWidgetStorage::SaveConfigInfoItem(base::DictionaryValue* dict) {
96   DCHECK(dict);
97   std::string key;
98   std::string value;
99   bool read_only = false;
100   dict->GetString(kPreferencesName, &key);
101   dict->GetString(kPreferencesValue, &value);
102   dict->GetBoolean(kPreferencesReadonly, &read_only);
103   return AddEntry(key, value, read_only);
104 }
105
106 bool AppWidgetStorage::SaveConfigInfoInDB() {
107   WidgetInfo* info =
108       static_cast<WidgetInfo*>(
109       application_->data()->GetManifestData(widget_keys::kWidgetKey));
110   base::DictionaryValue* widget_info = info->GetWidgetInfo();
111   if (!widget_info) {
112     LOG(ERROR) << "Fail to get parsed widget information.";
113     return false;
114   }
115
116   base::Value* pref_value = NULL;
117   widget_info->Get(kPreferences, &pref_value);
118
119   if (pref_value && pref_value->IsType(base::Value::TYPE_DICTIONARY)) {
120     base::DictionaryValue* dict;
121     pref_value->GetAsDictionary(&dict);
122     return SaveConfigInfoItem(dict);
123   } else if (pref_value && pref_value->IsType(base::Value::TYPE_LIST)) {
124     base::ListValue* list;
125     pref_value->GetAsList(&list);
126
127     for (base::ListValue::iterator it = list->begin();
128          it != list->end(); ++it) {
129       base::DictionaryValue* dict;
130       (*it)->GetAsDictionary(&dict);
131       if (!SaveConfigInfoItem(dict))
132         return false;
133     }
134   } else {
135     LOG(INFO) << "No widget preferences or preference type is not supported.";
136   }
137
138   return true;
139 }
140
141 bool AppWidgetStorage::InitStorageTable() {
142   if (sqlite_db_->DoesTableExist(kStorageTableName)) {
143     db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
144     return true;
145   }
146
147   sql::Transaction transaction(sqlite_db_.get());
148   transaction.Begin();
149   if (!sqlite_db_->Execute(kCreateStorageTableOp))
150     return false;
151   if (!transaction.Commit())
152     return false;
153
154   db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
155   SaveConfigInfoInDB();
156
157   return true;
158 }
159
160 bool AppWidgetStorage::EntryExists(const std::string& key) const {
161   sql::Transaction transaction(sqlite_db_.get());
162   if (!transaction.Begin())
163     return false;
164
165   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
166       kSelectCountWithBindOp));
167   stmt.BindString(0, key);
168   if (!stmt.Step()) {
169     LOG(ERROR) << "An error occured when selecting count from DB.";
170     return false;
171   }
172
173   if (!transaction.Commit())
174     return false;
175
176   int exist = stmt.ColumnInt(0);
177   return exist > 0;
178 }
179
180 bool AppWidgetStorage::IsReadOnly(const std::string& key) {
181   sql::Transaction transaction(sqlite_db_.get());
182   if (!transaction.Begin())
183     return true;
184
185   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
186       kSelectReadOnlyWithBindOp));
187   stmt.BindString(0, key);
188   if (!stmt.Step()) {
189     LOG(ERROR) << "An error occured when selecting count from DB.";
190     return true;
191   }
192
193   if (!transaction.Commit())
194     return true;
195
196   return stmt.ColumnBool(0);
197 }
198
199 bool AppWidgetStorage::AddEntry(const std::string& key,
200                                const std::string& value,
201                                bool read_only) {
202   if (!db_initialized_ && !Init())
203     return false;
204
205   std::string operation;
206   if (!EntryExists(key)) {
207     operation = kInsertItemWithBindOp;
208   } else if (!IsReadOnly(key)) {
209     operation = kUpdateItemWithBindOp;
210   } else {
211     LOG(ERROR) << "Could not set read only item " << key;
212     return false;
213   }
214
215   sql::Transaction transaction(sqlite_db_.get());
216   if (!transaction.Begin())
217     return false;
218
219   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
220     operation.c_str()));
221   stmt.BindString(0, value);
222   stmt.BindBool(1, read_only);
223   stmt.BindString(2, key);
224   if (!stmt.Run()) {
225     LOG(ERROR) << "An error occured when set item into DB.";
226     return false;
227   }
228
229   return transaction.Commit();
230 }
231
232 bool AppWidgetStorage::RemoveEntry(const std::string& key) {
233   if (!db_initialized_ && !Init())
234     return false;
235
236   if (IsReadOnly(key)) {
237     LOG(ERROR) << "Could not remove read only item " << key;
238     return false;
239   }
240
241   sql::Transaction transaction(sqlite_db_.get());
242   if (!transaction.Begin())
243     return false;
244
245   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
246       kRemoveItemWithBindOp));
247   stmt.BindString(0, key);
248
249   if (!stmt.Run()) {
250     LOG(ERROR) << "An error occured when removing item into DB.";
251     return false;
252   }
253
254   return transaction.Commit();
255 }
256
257 bool AppWidgetStorage::Clear() {
258   if (!db_initialized_ && !Init())
259     return false;
260
261   sql::Transaction transaction(sqlite_db_.get());
262   transaction.Begin();
263
264   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
265       kClearStorageTableWithBindOp));
266   stmt.BindBool(0, false);
267
268   if (!stmt.Run()) {
269     LOG(ERROR) << "An error occured when removing item into DB.";
270     return false;
271   }
272
273   return transaction.Commit();
274 }
275
276 bool AppWidgetStorage::GetAllEntries(base::DictionaryValue* result) {
277   std::string key;
278   std::string value;
279   DCHECK(result);
280
281   if (!db_initialized_ && !Init())
282     return false;
283
284   sql::Statement stmt(sqlite_db_->GetUniqueStatement(kSelectAllItem));
285   while (stmt.Step()) {
286     key = stmt.ColumnString(0);
287     value = stmt.ColumnString(1);
288     result->SetString(key, value);
289   }
290
291   return true;
292 }
293
294 }  // namespace application
295 }  // namespace xwalk