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.
5 #include "xwalk/application/browser/application_storage_impl.h"
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"
21 namespace db_fields = xwalk::application_storage_constants;
23 namespace application {
25 const base::FilePath::CharType ApplicationStorageImpl::kDBFileName[] =
26 FILE_PATH_LITERAL("applications.db");
28 const char kEventSeparator = ';';
29 const char kPermissionSeparator = '^';
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;
37 const std::string StoredPermissionStr[] = {
43 std::string ToString(StoredPermission permission) {
44 if (permission == UNDEFINED_STORED_PERM)
45 return std::string("");
46 return StoredPermissionStr[permission];
49 StoredPermission ToPermission(const std::string& str) {
51 for (i = 0; i < UNDEFINED_STORED_PERM; ++i) {
52 if (str == StoredPermissionStr[i])
55 return static_cast<StoredPermission>(i);
58 inline const base::FilePath GetDBPath(const base::FilePath& path) {
59 return path.Append(ApplicationStorageImpl::kDBFileName);
62 // Initializes the applications table, returning true on success.
63 bool InitApplicationsTable(sql::Connection* db) {
64 sql::Transaction transaction(db);
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))
71 return transaction.Commit();
74 bool InitEventsTable(sql::Connection* db) {
75 sql::Transaction transaction(db);
77 if (!db->DoesTableExist(db_fields::kEventTableName)) {
78 if (!db->Execute(db_fields::kCreateEventTableOp))
81 return transaction.Commit();
84 // Permissions are stored like "bluetooth^ALLOW;calendar^DENY;contacts^ALLOW"
85 std::string ToString(StoredPermissionMap permissions) {
87 StoredPermissionMap::iterator iter;
88 for (iter = permissions.begin(); iter != permissions.end(); ++iter) {
91 str += (iter->first + kPermissionSeparator + ToString(iter->second));
96 StoredPermissionMap ToPermissionMap(const std::string& str) {
97 StoredPermissionMap map;
98 std::vector<std::string> vec;
99 base::SplitString(str, ';', &vec);
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?";
110 map[perm_item[0]] = ToPermission(perm_item[1]);
116 bool InitPermissionsTable(sql::Connection* db) {
117 sql::Transaction transaction(db);
119 if (!db->DoesTableExist(db_fields::kPermissionTableName)) {
120 if (!db->Execute(db_fields::kCreatePermissionTableOp))
123 return transaction.Commit();
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;
135 ApplicationStorageImpl::ApplicationStorageImpl(const base::FilePath& path)
137 db_initialized_(false) {
138 // Ensure the parent directory for database file is created before reading
140 if (!base::PathExists(path) && !base::CreateDirectory(path))
144 bool ApplicationStorageImpl::UpgradeToVersion1(const base::FilePath& v0_file) {
145 JSONFileValueSerializer serializer(v0_file);
148 base::Value* old_db = serializer.Deserialize(&error_code, &error);
150 LOG(ERROR) << "Unable to read applications information from JSON DB, "
151 "the error message is: "
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);
164 value->GetString("path", &path);
166 scoped_refptr<ApplicationData> application =
167 ApplicationData::Create(base::FilePath::FromUTF8Unsafe(path),
173 LOG(ERROR) << "Unable to migrate the information to Version 1: " << error;
178 value->GetDouble("install_time", &install_time);
179 if (!AddApplication(application, base::Time::FromDoubleT(install_time)))
182 meta_table_.SetVersionNumber(1);
187 ApplicationStorageImpl::~ApplicationStorageImpl() {
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.";
198 sqlite_db->Preload();
200 if (!meta_table_.Init(sqlite_db.get(), kVersionNumber, kVersionNumber) ||
201 meta_table_.GetVersionNumber() != kVersionNumber) {
202 LOG(ERROR) << "Unable to init the META table.";
206 if (!InitApplicationsTable(sqlite_db.get())) {
207 LOG(ERROR) << "Unable to open applications table.";
211 if (!InitEventsTable(sqlite_db.get())) {
212 LOG(ERROR) << "Unable to open registered events table.";
216 if (!InitPermissionsTable(sqlite_db.get())) {
217 LOG(ERROR) << "Unable to open registered permissions table.";
221 if (!sqlite_db->Execute("PRAGMA foreign_keys=ON")) {
222 LOG(ERROR) << "Unable to enforce foreign key contraints.";
226 sqlite_db_.reset(sqlite_db.release());
228 db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
230 base::FilePath v0_file = data_path_.Append(
231 FILE_PATH_LITERAL("applications_db"));
232 if (base::PathExists(v0_file) &&
234 if (!UpgradeToVersion1(v0_file)) {
235 LOG(ERROR) << "Unable to migrate database from JSON format to SQLite.";
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.";
246 db_initialized_ = GetInstalledApplications(applications);
248 return db_initialized_;
251 bool ApplicationStorageImpl::GetInstalledApplications(
252 ApplicationData::ApplicationDataMap& applications) {
253 if (!db_initialized_) {
254 LOG(ERROR) << "The database haven't initilized.";
258 sql::Statement smt(sqlite_db_->GetUniqueStatement(
259 db_fields::kGetAllRowsFromAppEventTableOp));
263 std::string error_msg;
265 std::string id = smt.ColumnString(0);
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)));
275 LOG(ERROR) << "An error occured when deserializing the manifest, "
276 "the error message is: "
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);
286 scoped_refptr<ApplicationData> application =
287 ApplicationData::Create(
288 base::FilePath::FromUTF8Unsafe(path),
294 LOG(ERROR) << "Load appliation error: " << error;
298 application->install_time_ = base::Time::FromDoubleT(install_time);
300 if (!events.empty()) {
301 application->events_ =
302 std::set<std::string>(events.begin(), events.end());
305 application->permission_map_ = ToPermissionMap(smt.ColumnString(5));
307 if (!Insert(application, applications)) {
308 LOG(ERROR) << "An error occurred while"
309 "initializing the application cache data.";
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.";
324 return (SetApplicationValue(
325 application, install_time, db_fields::kSetApplicationWithBindOp) &&
326 SetEvents(application->ID(), application->GetEvents()) &&
327 SetPermissions(application->ID(), application->permission_map_));
330 bool ApplicationStorageImpl::UpdateApplication(
331 ApplicationData* application, const base::Time& install_time) {
332 if (!db_initialized_) {
333 LOG(ERROR) << "The database haven't initialized.";
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;
348 bool ApplicationStorageImpl::RemoveApplication(const std::string& id) {
349 if (!db_initialized_) {
350 LOG(ERROR) << "The database haven't initialized.";
354 sql::Transaction transaction(sqlite_db_.get());
355 if (!transaction.Begin())
358 sql::Statement smt(sqlite_db_->GetUniqueStatement(
359 db_fields::kDeleteApplicationWithBindOp));
360 smt.BindString(0, id);
362 LOG(ERROR) << "Could not delete application "
363 "information from DB.";
367 return transaction.Commit();
370 bool ApplicationStorageImpl::SetApplicationValue(
371 const ApplicationData* application,
372 const base::Time& install_time,
373 const std::string& operation) {
375 LOG(ERROR) << "A value is needed when inserting/updating in DB.";
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.";
386 sql::Transaction transaction(sqlite_db_.get());
387 if (!transaction.Begin())
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.";
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());
400 LOG(ERROR) << "An error occured when inserting/updating "
401 "application info in DB.";
405 return transaction.Commit();
408 bool ApplicationStorageImpl::SetEvents(const std::string& id,
409 const std::set<std::string>& events) {
410 if (!db_initialized_)
412 return SetEventsValue(id, events, db_fields::kInsertEventsWithBindOp);
415 bool ApplicationStorageImpl::UpdateEvents(
416 const std::string &id, const std::set<std::string>& events) {
417 if (!db_initialized_)
421 return DeleteEvents(id);
423 return SetEventsValue(id, events, db_fields::kUpdateEventsWithBindOp);
426 bool ApplicationStorageImpl::DeleteEvents(const std::string& id) {
427 sql::Transaction transaction(sqlite_db_.get());
428 if (!transaction.Begin())
431 sql::Statement smt(sqlite_db_->GetUniqueStatement(
432 db_fields::kDeleteEventsWithBindOp));
433 smt.BindString(0, id);
436 LOG(ERROR) << "An error occured when deleting event information from DB.";
440 return transaction.Commit();
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));
451 if (!transaction.Begin())
454 sql::Statement smt(sqlite_db_->GetUniqueStatement(
456 smt.BindString(0, events_list);
457 smt.BindString(1, id);
459 LOG(ERROR) << "An error occured when inserting event information into DB.";
463 return transaction.Commit();
466 bool ApplicationStorageImpl::SetPermissions(const std::string& id,
467 const StoredPermissionMap& permissions) {
468 if (!db_initialized_) {
469 LOG(ERROR) << "Database is not initialized.";
472 return SetPermissionsValue(id, permissions,
473 db_fields::kInsertPermissionsWithBindOp);
476 bool ApplicationStorageImpl::UpdatePermissions(const std::string& id,
477 const StoredPermissionMap& permissions) {
478 if (!db_initialized_) {
479 LOG(ERROR) << "Database is not initialized.";
482 if (permissions.empty())
483 return RevokePermissions(id);
485 return SetPermissionsValue(id, permissions,
486 db_fields::kUpdatePermissionsWithBindOp);
489 bool ApplicationStorageImpl::RevokePermissions(const std::string& id) {
490 sql::Transaction transaction(sqlite_db_.get());
491 if (!transaction.Begin())
494 sql::Statement statement(sqlite_db_->GetUniqueStatement(
495 db_fields::kDeletePermissionsWithBindOp));
496 statement.BindString(0, id);
498 if (!statement.Run()) {
500 "An error occurred while removing permissions.";
503 return transaction.Commit();
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);
513 if (!transaction.Begin())
516 sql::Statement statement(sqlite_db_->GetUniqueStatement(
518 statement.BindString(0, permission_str);
519 statement.BindString(1, id);
520 if (!statement.Run()) {
522 "An error occurred while inserting permissions.";
525 return transaction.Commit();
528 } // namespace application