Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / browser / application_storage_impl.cc
1 // Copyright (c) 2013 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/browser/application_storage_impl.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/file_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/string_util.h"
14 #include "base/json/json_file_value_serializer.h"
15 #include "base/json/json_string_value_serializer.h"
16 #include "sql/statement.h"
17 #include "sql/transaction.h"
18 #include "xwalk/application/browser/application_storage.h"
19 #include "xwalk/application/common/application_storage_constants.h"
20
21 namespace db_fields = xwalk::application_storage_constants;
22 namespace xwalk {
23 namespace application {
24
25 const base::FilePath::CharType ApplicationStorageImpl::kDBFileName[] =
26     FILE_PATH_LITERAL("applications.db");
27
28 const char kEventSeparator = ';';
29 const char kPermissionSeparator = '^';
30
31 // Switching the JSON format DB(version 0) to SQLite backend version 1,
32 // should migrate all data from JSON DB to SQLite applications table.
33 static const int kVersionNumber = 1;
34
35 namespace {
36
37 const std::string StoredPermissionStr[] = {
38     "ALLOW",
39     "DENY",
40     "PROMPT",
41 };
42
43 std::string ToString(StoredPermission permission) {
44   if (permission == UNDEFINED_STORED_PERM)
45     return std::string("");
46   return StoredPermissionStr[permission];
47 }
48
49 StoredPermission ToPermission(const std::string& str) {
50   unsigned int i;
51   for (i = 0; i < UNDEFINED_STORED_PERM; ++i) {
52     if (str == StoredPermissionStr[i])
53       break;
54   }
55   return static_cast<StoredPermission>(i);
56 }
57
58 inline const base::FilePath GetDBPath(const base::FilePath& path) {
59   return path.Append(ApplicationStorageImpl::kDBFileName);
60 }
61
62 // Initializes the applications table, returning true on success.
63 bool InitApplicationsTable(sql::Connection* db) {
64   sql::Transaction transaction(db);
65   transaction.Begin();
66   // The table is named "applications", the primary key is "id".
67   if (!db->DoesTableExist(db_fields::kAppTableName)) {
68     if (!db->Execute(db_fields::kCreateAppTableOp))
69       return false;
70   }
71   return transaction.Commit();
72 }
73
74 bool InitEventsTable(sql::Connection* db) {
75   sql::Transaction transaction(db);
76   transaction.Begin();
77   if (!db->DoesTableExist(db_fields::kEventTableName)) {
78     if (!db->Execute(db_fields::kCreateEventTableOp))
79      return false;
80   }
81   return transaction.Commit();
82 }
83
84 // Permissions are stored like "bluetooth^ALLOW;calendar^DENY;contacts^ALLOW"
85 std::string ToString(StoredPermissionMap permissions) {
86   std::string str;
87   StoredPermissionMap::iterator iter;
88   for (iter = permissions.begin(); iter != permissions.end(); ++iter) {
89     if (!str.empty())
90       str += ";";
91     str += (iter->first + kPermissionSeparator + ToString(iter->second));
92   }
93   return str;
94 }
95
96 StoredPermissionMap ToPermissionMap(const std::string& str) {
97   StoredPermissionMap map;
98   std::vector<std::string> vec;
99   base::SplitString(str, ';', &vec);
100   if (!vec.empty()) {
101     for (std::vector<std::string>::iterator iter = vec.begin();
102         iter != vec.end(); ++iter) {
103       std::vector<std::string> perm_item;
104       base::SplitString(*iter, kPermissionSeparator, &perm_item);
105       if (perm_item.size() != 2) {
106         LOG(ERROR) << "Permission format error! Corrupted database?";
107         map.clear();
108         break;
109       }
110       map[perm_item[0]] = ToPermission(perm_item[1]);
111     }
112   }
113   return map;
114 }
115
116 bool InitPermissionsTable(sql::Connection* db) {
117   sql::Transaction transaction(db);
118   transaction.Begin();
119   if (!db->DoesTableExist(db_fields::kPermissionTableName)) {
120     if (!db->Execute(db_fields::kCreatePermissionTableOp))
121      return false;
122   }
123   return transaction.Commit();
124 }
125
126 bool Insert(scoped_refptr<ApplicationData> application,
127             ApplicationData::ApplicationDataMap& applications) {
128   return applications.insert(
129       std::pair<std::string, scoped_refptr<ApplicationData> >(
130           application->ID(), application)).second;
131 }
132
133 }  // namespace
134
135 ApplicationStorageImpl::ApplicationStorageImpl(const base::FilePath& path)
136     : data_path_(path),
137       db_initialized_(false) {
138   // Ensure the parent directory for database file is created before reading
139   // from it.
140   if (!base::PathExists(path) && !base::CreateDirectory(path))
141     return;
142 }
143
144 bool ApplicationStorageImpl::UpgradeToVersion1(const base::FilePath& v0_file) {
145   JSONFileValueSerializer serializer(v0_file);
146   int error_code;
147   std::string error;
148   base::Value* old_db = serializer.Deserialize(&error_code, &error);
149   if (!old_db) {
150     LOG(ERROR) << "Unable to read applications information from JSON DB, "
151                   "the error message is: "
152                << error;
153     return false;
154   }
155
156   scoped_ptr<base::DictionaryValue> value;
157   for (base::DictionaryValue::Iterator it(
158            *static_cast<base::DictionaryValue*>(old_db));
159        !it.IsAtEnd(); it.Advance()) {
160     value.reset(static_cast<base::DictionaryValue*>(it.value().DeepCopy()));
161     base::DictionaryValue* manifest;
162     value->GetDictionary("manifest", &manifest);
163     std::string path;
164     value->GetString("path", &path);
165     std::string error;
166     scoped_refptr<ApplicationData> application =
167         ApplicationData::Create(base::FilePath::FromUTF8Unsafe(path),
168                                 Manifest::INTERNAL,
169                                 *manifest,
170                                 it.key(),
171                                 &error);
172     if (!application) {
173       LOG(ERROR) << "Unable to migrate the information to Version 1: " << error;
174       return false;
175     }
176
177     double install_time;
178     value->GetDouble("install_time", &install_time);
179     if (!AddApplication(application, base::Time::FromDoubleT(install_time)))
180       return false;
181   }
182   meta_table_.SetVersionNumber(1);
183
184   return true;
185 }
186
187 ApplicationStorageImpl::~ApplicationStorageImpl() {
188 }
189
190 bool ApplicationStorageImpl::Init(
191     ApplicationData::ApplicationDataMap& applications) {
192   bool does_db_exist = base::PathExists(GetDBPath(data_path_));
193   scoped_ptr<sql::Connection> sqlite_db(new sql::Connection);
194   if (!sqlite_db->Open(GetDBPath(data_path_))) {
195     LOG(ERROR) << "Unable to open applications DB.";
196     return false;
197   }
198   sqlite_db->Preload();
199
200   if (!meta_table_.Init(sqlite_db.get(), kVersionNumber, kVersionNumber) ||
201       meta_table_.GetVersionNumber() != kVersionNumber) {
202     LOG(ERROR) << "Unable to init the META table.";
203     return false;
204   }
205
206   if (!InitApplicationsTable(sqlite_db.get())) {
207     LOG(ERROR) << "Unable to open applications table.";
208     return false;
209   }
210
211   if (!InitEventsTable(sqlite_db.get())) {
212     LOG(ERROR) << "Unable to open registered events table.";
213     return false;
214   }
215
216   if (!InitPermissionsTable(sqlite_db.get())) {
217     LOG(ERROR) << "Unable to open registered permissions table.";
218     return false;
219   }
220
221   if (!sqlite_db->Execute("PRAGMA foreign_keys=ON")) {
222     LOG(ERROR) << "Unable to enforce foreign key contraints.";
223     return false;
224   }
225
226   sqlite_db_.reset(sqlite_db.release());
227
228   db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
229
230   base::FilePath v0_file = data_path_.Append(
231       FILE_PATH_LITERAL("applications_db"));
232   if (base::PathExists(v0_file) &&
233       !does_db_exist) {
234     if (!UpgradeToVersion1(v0_file)) {
235       LOG(ERROR) << "Unable to migrate database from JSON format to SQLite.";
236       return false;
237     }
238     // After migrated to SQLite, delete the old JSON DB file is safe,
239     // since all information has been migrated and it will not be used anymore.
240     if (!base::DeleteFile(v0_file, false)) {
241       LOG(ERROR) << "Unalbe to delete old JSON DB file.";
242       return false;
243     }
244   }
245
246   db_initialized_ = GetInstalledApplications(applications);
247
248   return db_initialized_;
249 }
250
251 bool ApplicationStorageImpl::GetInstalledApplications(
252     ApplicationData::ApplicationDataMap& applications) {
253   if (!db_initialized_) {
254     LOG(ERROR) << "The database haven't initilized.";
255     return false;
256   }
257
258   sql::Statement smt(sqlite_db_->GetUniqueStatement(
259       db_fields::kGetAllRowsFromAppEventTableOp));
260   if (!smt.is_valid())
261     return false;
262
263   std::string error_msg;
264   while (smt.Step()) {
265     std::string id = smt.ColumnString(0);
266
267     int error_code;
268     std::string manifest_str = smt.ColumnString(1);
269     JSONStringValueSerializer serializer(&manifest_str);
270     scoped_ptr<base::DictionaryValue> manifest(
271         static_cast<base::DictionaryValue*>(
272             serializer.Deserialize(&error_code, &error_msg)));
273
274     if (!manifest) {
275       LOG(ERROR) << "An error occured when deserializing the manifest, "
276                     "the error message is: "
277                  << error_msg;
278       return false;
279     }
280     std::string path = smt.ColumnString(2);
281     double install_time = smt.ColumnDouble(3);
282     std::vector<std::string> events;
283     base::SplitString(smt.ColumnString(4), kEventSeparator, &events);
284
285     std::string error;
286     scoped_refptr<ApplicationData> application =
287         ApplicationData::Create(
288             base::FilePath::FromUTF8Unsafe(path),
289             Manifest::INTERNAL,
290             *manifest,
291             id,
292             &error);
293     if (!application) {
294       LOG(ERROR) << "Load appliation error: " << error;
295       return false;
296     }
297
298     application->install_time_ = base::Time::FromDoubleT(install_time);
299
300     if (!events.empty()) {
301       application->events_ =
302           std::set<std::string>(events.begin(), events.end());
303     }
304
305     application->permission_map_ = ToPermissionMap(smt.ColumnString(5));
306
307     if (!Insert(application, applications)) {
308       LOG(ERROR) << "An error occurred while"
309                     "initializing the application cache data.";
310       return false;
311     }
312   }
313
314   return true;
315 }
316
317 bool ApplicationStorageImpl::AddApplication(const ApplicationData* application,
318                                             const base::Time& install_time) {
319   if (!db_initialized_) {
320     LOG(ERROR) << "The database haven't initialized.";
321     return false;
322   }
323
324   return (SetApplicationValue(
325       application, install_time, db_fields::kSetApplicationWithBindOp) &&
326           SetEvents(application->ID(), application->GetEvents()) &&
327           SetPermissions(application->ID(), application->permission_map_));
328 }
329
330 bool ApplicationStorageImpl::UpdateApplication(
331     ApplicationData* application, const base::Time& install_time) {
332   if (!db_initialized_) {
333     LOG(ERROR) << "The database haven't initialized.";
334     return false;
335   }
336
337   if (SetApplicationValue(
338           application, install_time, db_fields::kUpdateApplicationWithBindOp) &&
339       UpdateEvents(application->ID(), application->GetEvents()) &&
340       UpdatePermissions(application->ID(), application->permission_map_)) {
341     application->is_dirty_ = false;
342     return true;
343   }
344
345   return false;
346 }
347
348 bool ApplicationStorageImpl::RemoveApplication(const std::string& id) {
349   if (!db_initialized_) {
350     LOG(ERROR) << "The database haven't initialized.";
351     return false;
352   }
353
354   sql::Transaction transaction(sqlite_db_.get());
355   if (!transaction.Begin())
356     return false;
357
358   sql::Statement smt(sqlite_db_->GetUniqueStatement(
359       db_fields::kDeleteApplicationWithBindOp));
360   smt.BindString(0, id);
361   if (!smt.Run()) {
362     LOG(ERROR) << "Could not delete application "
363                   "information from DB.";
364     return false;
365   }
366
367   return transaction.Commit();
368 }
369
370 bool ApplicationStorageImpl::SetApplicationValue(
371     const ApplicationData* application,
372     const base::Time& install_time,
373     const std::string& operation) {
374   if (!application) {
375     LOG(ERROR) << "A value is needed when inserting/updating in DB.";
376     return false;
377   }
378
379   std::string manifest;
380   JSONStringValueSerializer serializer(&manifest);
381   if (!serializer.Serialize(*(application->GetManifest()->value()))) {
382     LOG(ERROR) << "An error occured when serializing the manifest value.";
383     return false;
384   }
385
386   sql::Transaction transaction(sqlite_db_.get());
387   if (!transaction.Begin())
388     return false;
389
390   sql::Statement smt(sqlite_db_->GetUniqueStatement(operation.c_str()));
391   if (!smt.is_valid()) {
392     LOG(ERROR) << "Unable to insert/update application info in DB.";
393     return false;
394   }
395   smt.BindString(0, manifest);
396   smt.BindString(1, application->Path().AsUTF8Unsafe());
397   smt.BindDouble(2, install_time.ToDoubleT());
398   smt.BindString(3, application->ID());
399   if (!smt.Run()) {
400     LOG(ERROR) << "An error occured when inserting/updating "
401                   "application info in DB.";
402     return false;
403   }
404
405   return transaction.Commit();
406 }
407
408 bool ApplicationStorageImpl::SetEvents(const std::string& id,
409                                        const std::set<std::string>& events) {
410   if (!db_initialized_)
411     return false;
412   return SetEventsValue(id, events, db_fields::kInsertEventsWithBindOp);
413 }
414
415 bool ApplicationStorageImpl::UpdateEvents(
416     const std::string &id, const std::set<std::string>& events) {
417   if (!db_initialized_)
418     return false;
419
420   if (events.empty())
421     return DeleteEvents(id);
422
423   return SetEventsValue(id, events, db_fields::kUpdateEventsWithBindOp);
424 }
425
426 bool ApplicationStorageImpl::DeleteEvents(const std::string& id) {
427   sql::Transaction transaction(sqlite_db_.get());
428   if (!transaction.Begin())
429     return false;
430
431   sql::Statement smt(sqlite_db_->GetUniqueStatement(
432       db_fields::kDeleteEventsWithBindOp));
433   smt.BindString(0, id);
434
435   if (!smt.Run()) {
436     LOG(ERROR) << "An error occured when deleting event information from DB.";
437     return false;
438   }
439
440   return transaction.Commit();
441 }
442
443 bool ApplicationStorageImpl::SetEventsValue(
444     const std::string& id,
445     const std::set<std::string>& events,
446     const std::string& operation) {
447   sql::Transaction transaction(sqlite_db_.get());
448   std::string events_list(JoinString(
449       std::vector<std::string>(events.begin(), events.end()), kEventSeparator));
450
451   if (!transaction.Begin())
452     return false;
453
454   sql::Statement smt(sqlite_db_->GetUniqueStatement(
455       operation.c_str()));
456   smt.BindString(0, events_list);
457   smt.BindString(1, id);
458   if (!smt.Run()) {
459     LOG(ERROR) << "An error occured when inserting event information into DB.";
460     return false;
461   }
462
463   return transaction.Commit();
464 }
465
466 bool ApplicationStorageImpl::SetPermissions(const std::string& id,
467     const StoredPermissionMap& permissions) {
468   if (!db_initialized_) {
469     LOG(ERROR) << "Database is not initialized.";
470     return false;
471   }
472   return SetPermissionsValue(id, permissions,
473       db_fields::kInsertPermissionsWithBindOp);
474 }
475
476 bool ApplicationStorageImpl::UpdatePermissions(const std::string& id,
477     const StoredPermissionMap& permissions) {
478   if (!db_initialized_) {
479     LOG(ERROR) << "Database is not initialized.";
480     return false;
481   }
482   if (permissions.empty())
483     return RevokePermissions(id);
484
485   return SetPermissionsValue(id, permissions,
486       db_fields::kUpdatePermissionsWithBindOp);
487 }
488
489 bool ApplicationStorageImpl::RevokePermissions(const std::string& id) {
490   sql::Transaction transaction(sqlite_db_.get());
491   if (!transaction.Begin())
492     return false;
493
494   sql::Statement statement(sqlite_db_->GetUniqueStatement(
495       db_fields::kDeletePermissionsWithBindOp));
496   statement.BindString(0, id);
497
498   if (!statement.Run()) {
499     LOG(ERROR) <<
500         "An error occurred while removing permissions.";
501     return false;
502   }
503   return transaction.Commit();
504 }
505
506 bool ApplicationStorageImpl::SetPermissionsValue(
507     const std::string& id,
508     const StoredPermissionMap& permissions,
509     const std::string& operation) {
510   sql::Transaction transaction(sqlite_db_.get());
511   std::string permission_str = ToString(permissions);
512
513   if (!transaction.Begin())
514     return false;
515
516   sql::Statement statement(sqlite_db_->GetUniqueStatement(
517       operation.c_str()));
518   statement.BindString(0, permission_str);
519   statement.BindString(1, id);
520   if (!statement.Run()) {
521     LOG(ERROR) <<
522         "An error occurred while inserting permissions.";
523     return false;
524   }
525   return transaction.Commit();
526 }
527
528 }  // namespace application
529 }  // namespace xwalk