Upstream version 6.34.113.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 "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"
14
15 namespace {
16
17 namespace widget_keys = xwalk::application_widget_keys;
18
19 const char kPreferences[] = "preferences";
20 const char kPreferencesName[] = "name";
21 const char kPreferencesValue[] = "value";
22 const char kPreferencesReadonly[] = "readonly";
23
24 const base::FilePath::CharType kWidgetStorageExtension[] =
25     FILE_PATH_LITERAL(".widgetStorage");
26
27 const char kStorageTableName[] = "widget_storage";
28
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 )";
34
35 const char kClearStorageTableWithBindOp[] =
36     "DELETE FROM widget_storage WHERE read_only = ? ";
37
38 const char kInsertItemWithBindOp[] =
39     "INSERT INTO widget_storage (value, read_only, key) "
40     "VALUES(?,?,?)";
41
42 const char kUpdateItemWithBindOp[] =
43     "UPDATE widget_storage SET value = ? , read_only = ? "
44     "WHERE key = ?";
45
46 const char kRemoveItemWithBindOp[] =
47     "DELETE FROM widget_storage WHERE key = ?";
48
49 const char kSelectTableLength[] =
50     "SELECT count(*) FROM widget_storage ";
51
52 const char kSelectCountWithBindOp[] =
53     "SELECT count(*) FROM widget_storage "
54     "WHERE key = ?";
55
56 const char kSelectAllItem[] =
57     "SELECT key, value FROM widget_storage ";
58
59 const char kSelectReadOnlyWithBindOp[] =
60     "SELECT read_only FROM widget_storage "
61     "WHERE key = ?";
62 }  // namespace
63
64 namespace xwalk {
65 namespace application {
66
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);
72
73   base::FilePath name(application_->id());
74   base::FilePath::StringType storage_name =
75       name.value() + kWidgetStorageExtension;
76   data_path_ = data_dir.Append(storage_name);
77
78   if (!base::PathExists(data_dir) && !base::CreateDirectory(data_dir)) {
79     LOG(ERROR) << "Could not create widget storage path.";
80     return;
81   }
82
83   if (!Init()) {
84     LOG(ERROR) << "Initialize widget storage failed.";
85     return;
86   }
87 }
88
89 AppWidgetStorage::~AppWidgetStorage() {
90 }
91
92 bool AppWidgetStorage::Init() {
93   if (!sqlite_db_->Open(data_path_)) {
94     LOG(ERROR) << "Unable to open widget storage DB.";
95     return false;
96   }
97   sqlite_db_->Preload();
98
99   if (!InitStorageTable()) {
100      LOG(ERROR) << "Unable to init widget storage table.";
101      return false;
102   }
103   return db_initialized_;
104 }
105
106 bool AppWidgetStorage::SaveConfigInfoItem(base::DictionaryValue* dict) {
107   DCHECK(dict);
108   std::string key;
109   std::string value;
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);
115 }
116
117 bool AppWidgetStorage::SaveConfigInfoInDB() {
118   WidgetInfo* info =
119       static_cast<WidgetInfo*>(
120       application_->data()->GetManifestData(widget_keys::kWidgetKey));
121   base::DictionaryValue* widget_info = info->GetWidgetInfo();
122   if (!widget_info) {
123     LOG(ERROR) << "Fail to get parsed widget information.";
124     return false;
125   }
126
127   base::Value* pref_value;
128   widget_info->Get(kPreferences, &pref_value);
129
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);
137
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))
143         return false;
144     }
145   } else {
146     LOG(INFO) << "No widget preferences or preference type is not supported.";
147   }
148
149   return true;
150 }
151
152 bool AppWidgetStorage::InitStorageTable() {
153   if (sqlite_db_->DoesTableExist(kStorageTableName)) {
154     db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
155     return true;
156   }
157
158   sql::Transaction transaction(sqlite_db_.get());
159   transaction.Begin();
160   if (!sqlite_db_->Execute(kCreateStorageTableOp))
161     return false;
162   if (!transaction.Commit())
163     return false;
164
165   db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
166   SaveConfigInfoInDB();
167
168   return true;
169 }
170
171 bool AppWidgetStorage::EntryExists(const std::string& key) const {
172   sql::Transaction transaction(sqlite_db_.get());
173   if (!transaction.Begin())
174     return false;
175
176   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
177       kSelectCountWithBindOp));
178   stmt.BindString(0, key);
179   if (!stmt.Step()) {
180     LOG(ERROR) << "An error occured when selecting count from DB.";
181     return false;
182   }
183
184   if (!transaction.Commit())
185     return false;
186
187   int exist = stmt.ColumnInt(0);
188   return exist > 0;
189 }
190
191 bool AppWidgetStorage::IsReadOnly(const std::string& key) {
192   sql::Transaction transaction(sqlite_db_.get());
193   if (!transaction.Begin())
194     return true;
195
196   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
197       kSelectReadOnlyWithBindOp));
198   stmt.BindString(0, key);
199   if (!stmt.Step()) {
200     LOG(ERROR) << "An error occured when selecting count from DB.";
201     return true;
202   }
203
204   if (!transaction.Commit())
205     return true;
206
207   return stmt.ColumnBool(0);
208 }
209
210 bool AppWidgetStorage::AddEntry(const std::string& key,
211                                const std::string& value,
212                                bool read_only) {
213   if (!db_initialized_ && !Init())
214     return false;
215
216   std::string operation;
217   if (!EntryExists(key)) {
218     operation = kInsertItemWithBindOp;
219   } else if (!IsReadOnly(key)) {
220     operation = kUpdateItemWithBindOp;
221   } else {
222     LOG(ERROR) << "Could not set read only item " << key;
223     return false;
224   }
225
226   sql::Transaction transaction(sqlite_db_.get());
227   if (!transaction.Begin())
228     return false;
229
230   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
231     operation.c_str()));
232   stmt.BindString(0, value);
233   stmt.BindBool(1, read_only);
234   stmt.BindString(2, key);
235   if (!stmt.Run()) {
236     LOG(ERROR) << "An error occured when set item into DB.";
237     return false;
238   }
239
240   return transaction.Commit();
241 }
242
243 bool AppWidgetStorage::RemoveEntry(const std::string& key) {
244   if (!db_initialized_ && !Init())
245     return false;
246
247   if (IsReadOnly(key)) {
248     LOG(ERROR) << "Could not remove read only item " << key;
249     return false;
250   }
251
252   sql::Transaction transaction(sqlite_db_.get());
253   if (!transaction.Begin())
254     return false;
255
256   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
257       kRemoveItemWithBindOp));
258   stmt.BindString(0, key);
259
260   if (!stmt.Run()) {
261     LOG(ERROR) << "An error occured when removing item into DB.";
262     return false;
263   }
264
265   return transaction.Commit();
266 }
267
268 bool AppWidgetStorage::Clear() {
269   if (!db_initialized_ && !Init())
270     return false;
271
272   sql::Transaction transaction(sqlite_db_.get());
273   transaction.Begin();
274
275   sql::Statement stmt(sqlite_db_->GetUniqueStatement(
276       kClearStorageTableWithBindOp));
277   stmt.BindBool(0, false);
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::GetAllEntries(base::DictionaryValue* result) {
288   std::string key;
289   std::string value;
290   DCHECK(result);
291
292   if (!db_initialized_ && !Init())
293     return false;
294
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);
300   }
301
302   return true;
303 }
304
305 }  // namespace application
306 }  // namespace xwalk