Implement privilege for usermedia permission
[framework/web/wrt-commons.git] / modules / security_origin_dao / dao / security_origin_dao.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file    security_origin_dao.cpp
18  * @author  Jihoon Chung (jihoon.chung@samsung.com)
19  * @version 1.0
20  * @brief    This file contains the definition of security origin dao class.
21  */
22
23 #include <wrt-commons/security-origin-dao/security_origin_database.h>
24 #include <wrt-commons/security-origin-dao/security_origin_dao.h>
25 #include <wrt-commons/security-origin-dao/security_origin_dao_types.h>
26 #include <orm_generator_security_origin.h>
27 #include <dpl/foreach.h>
28 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
29 #include <dpl/wrt-dao-ro/WrtDatabase.h>
30 #include <dpl/wrt-dao-ro/widget_config.h>
31 #include <dpl/wrt-dao-ro/global_config.h>
32 #include <dpl/wrt-dao-ro/common_dao_types.h>
33 #include <sys/stat.h>
34 #include <fstream>
35
36 using namespace DPL::DB::ORM;
37 using namespace DPL::DB::ORM::security_origin;
38
39 namespace SecurityOriginDB {
40 #define SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN          Try
41
42 #define SQL_CONNECTION_EXCEPTION_HANDLER_END(message)   \
43     Catch(DPL::DB::SqlConnection::Exception::Base) {       \
44         LogError(message);                              \
45         ReThrowMsg(SecurityOriginDAO::Exception::DatabaseError, \
46                    message);                            \
47     }
48
49 namespace {
50 DPL::DB::SqlConnection::Flag::Option SECURITY_ORIGIN_DB_OPTION =
51     DPL::DB::SqlConnection::Flag::RW;
52 DPL::DB::SqlConnection::Flag::Type SECURITY_ORIGIN_DB_TYPE =
53     DPL::DB::SqlConnection::Flag::UseLucene;
54 const char* const SECURITY_ORIGIN_DB_NAME = ".security_origin.db";
55 const char* const SECURITY_ORIGIN_DB_SQL_PATH =
56     "/usr/share/wrt-engine/security_origin_db.sql";
57 const char* const SECURITY_DATABASE_JOURNAL_FILENAME = "-journal";
58
59 const int WEB_APPLICATION_UID = 5000;
60 const int WEB_APPLICATION_GUID = 5000;
61
62 std::string createDatabasePath(const WrtDB::WidgetPkgName &pkgName)
63 {
64     std::stringstream filename;
65
66     filename << WrtDB::WidgetConfig::GetWidgetPersistentStoragePath(pkgName)
67              << "/"
68              << SECURITY_ORIGIN_DB_NAME;
69     return filename.str();
70 }
71
72 std::string createDatabasePath(int widgetHandle)
73 {
74     using namespace DPL::DB::ORM;
75     using namespace WrtDB::WidgetConfig;
76     using namespace WrtDB::GlobalConfig;
77
78     WrtDB::TizenAppId appid;
79
80     Try
81     {
82         appid = WrtDB::WidgetDAOReadOnly::getTzAppId(widgetHandle);
83     }
84     Catch(DPL::DB::SqlConnection::Exception::Base) {
85         LogError("Failed to get database Path");
86     }
87     return createDatabasePath(appid);
88 }
89
90 void checkDatabase(std::string databasePath)
91 {
92     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
93     {
94         if (databasePath.empty()) {
95             ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
96                      "Wrong database Path is passed");
97         }
98
99         struct stat buffer;
100         if (stat(databasePath.c_str(), &buffer) != 0) {
101             //Create fresh database
102             LogInfo("Creating database " << databasePath);
103
104             std::fstream file;
105             file.open(SECURITY_ORIGIN_DB_SQL_PATH, std::ios_base::in);
106             if (!file) {
107                 ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
108                          "Fail to get database Path");
109             }
110
111             std::stringstream ssBuffer;
112             ssBuffer << file.rdbuf();
113
114             file.close();
115
116             DPL::DB::SqlConnection con(databasePath,
117                                        SECURITY_ORIGIN_DB_TYPE,
118                                        SECURITY_ORIGIN_DB_OPTION);
119             con.ExecCommand(ssBuffer.str().c_str());
120         }
121
122         if(chown(databasePath.c_str(),
123                  WEB_APPLICATION_UID,
124                  WEB_APPLICATION_GUID) != 0)
125         {
126             ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
127                  "Fail to change uid/guid");
128         }
129         std::string databaseJournal =
130             databasePath + SECURITY_DATABASE_JOURNAL_FILENAME;
131         if(chown(databaseJournal.c_str(),
132                  WEB_APPLICATION_UID,
133                  WEB_APPLICATION_GUID) != 0)
134         {
135             ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
136                  "Fail to change uid/guid");
137         }
138     }
139     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to get database Path")
140 }
141 }
142
143 SecurityOriginDAO::SecurityOriginDAO(int handle) :
144     m_securityOriginDBPath(createDatabasePath(handle)),
145     m_securityOriginDBInterface(m_securityOriginDBPath, SECURITY_ORIGIN_DB_TYPE)
146 {
147     checkDatabase(m_securityOriginDBPath);
148     m_securityOriginDBInterface.AttachToThread(SECURITY_ORIGIN_DB_OPTION);
149 }
150
151 SecurityOriginDAO::SecurityOriginDAO(const WrtDB::WidgetPkgName &pkgName) :
152     m_securityOriginDBPath(createDatabasePath(pkgName)),
153     m_securityOriginDBInterface(m_securityOriginDBPath, SECURITY_ORIGIN_DB_TYPE)
154 {
155     checkDatabase(m_securityOriginDBPath);
156     m_securityOriginDBInterface.AttachToThread(SECURITY_ORIGIN_DB_OPTION);
157 }
158
159 SecurityOriginDAO::~SecurityOriginDAO()
160 {
161     m_securityOriginDBInterface.DetachFromThread();
162 }
163
164 SecurityOriginDataList SecurityOriginDAO::getSecurityOriginDataList(void)
165 {
166     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
167     {
168         SecurityOriginDataList list;
169         SECURITY_ORIGIN_DB_SELECT(select,
170                                   SecurityOriginInfo,
171                                   &m_securityOriginDBInterface);
172         typedef std::list<SecurityOriginInfo::Row> RowList;
173         RowList rowList = select->GetRowList();
174
175         FOREACH(it, rowList) {
176             Origin origin(it->Get_scheme(), it->Get_host(), it->Get_port());
177             list.push_back(
178                 SecurityOriginDataPtr(
179                     new SecurityOriginData(
180                         static_cast<Feature>(it->Get_feature()), origin)));
181         }
182         return list;
183     }
184     SQL_CONNECTION_EXCEPTION_HANDLER_END("Failed to get data  list")
185 }
186
187 Result SecurityOriginDAO::getResult(
188     const SecurityOriginData &securityOriginData)
189 {
190     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
191     {
192         SECURITY_ORIGIN_DB_SELECT(select,
193                                   SecurityOriginInfo,
194                                   &m_securityOriginDBInterface);
195         select->Where(
196             And(And(And(Equals<SecurityOriginInfo::feature>(securityOriginData.
197                                                                 feature),
198                         Equals<SecurityOriginInfo::scheme>(securityOriginData.
199                                                                origin.scheme)),
200                     Equals<SecurityOriginInfo::host>(securityOriginData.origin.
201                                                          host)),
202                 Equals<SecurityOriginInfo::port>(securityOriginData.origin.port)));
203         SecurityOriginInfo::Select::RowList rows = select->GetRowList();
204
205         if (rows.empty()) {
206             return RESULT_UNKNOWN;
207         }
208         SecurityOriginInfo::Row row = rows.front();
209         return static_cast<Result>(row.Get_result());
210     }
211     SQL_CONNECTION_EXCEPTION_HANDLER_END(
212         "Failed to get result for security origin")
213 }
214
215 bool SecurityOriginDAO::isReadOnly(const SecurityOriginData &securityOriginData)
216 {
217     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
218     {
219         SECURITY_ORIGIN_DB_SELECT(select, SecurityOriginInfo, &m_securityOriginDBInterface);
220         select->Where(
221             And(And(And(Equals<SecurityOriginInfo::feature>(securityOriginData.feature),
222                         Equals<SecurityOriginInfo::scheme>(securityOriginData.origin.scheme)),
223                     Equals<SecurityOriginInfo::host>(securityOriginData.origin.host)),
224                 Equals<SecurityOriginInfo::port>(securityOriginData.origin.port)));
225         SecurityOriginInfo::Select::RowList rows = select->GetRowList();
226
227         if (rows.empty()) {
228             return RESULT_UNKNOWN;
229         }
230         SecurityOriginInfo::Row row = rows.front();
231         return row.Get_readonly() ? true : false;
232     }
233     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to get readonly property")
234 }
235
236 void SecurityOriginDAO::setSecurityOriginData(const SecurityOriginData &securityOriginData,
237                                               const Result result,
238                                               const bool readOnly)
239 {
240     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
241     {
242         ScopedTransaction transaction(&m_securityOriginDBInterface);
243         SecurityOriginInfo::Row row;
244         row.Set_feature(securityOriginData.feature);
245         row.Set_scheme(securityOriginData.origin.scheme);
246         row.Set_host(securityOriginData.origin.host);
247         row.Set_port(securityOriginData.origin.port);
248         row.Set_result(result);
249         row.Set_readonly(readOnly ? 1 : 0);
250
251         if (true == hasResult(securityOriginData)) {
252             SECURITY_ORIGIN_DB_UPDATE(update,
253                                       SecurityOriginInfo,
254                                       &m_securityOriginDBInterface);
255             update->Values(row);
256             update->Execute();
257         } else {
258             SECURITY_ORIGIN_DB_INSERT(
259                 insert,
260                 SecurityOriginInfo,
261                 &m_securityOriginDBInterface);
262             insert->Values(row);
263             insert->Execute();
264         }
265         transaction.Commit();
266     }
267     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to set security origin data")
268 }
269
270 void SecurityOriginDAO::setPrivilegeSecurityOriginData(const Feature feature,
271                                                        bool isOnlyAllowedLocalOrigin)
272 {
273     Origin origin(DPL::FromUTF8String("file"),
274                   DPL::FromUTF8String(""),
275                   0);
276     if (!isOnlyAllowedLocalOrigin) {
277         origin.scheme = DPL::FromUTF8String("");
278     }
279     SecurityOriginData data(feature, origin);
280     setSecurityOriginData(data, RESULT_ALLOW_ALWAYS, true);
281 }
282
283 void SecurityOriginDAO::removeSecurityOriginData(
284     const SecurityOriginData &securityOriginData)
285 {
286     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
287     {
288         ScopedTransaction transaction(&m_securityOriginDBInterface);
289
290         if (true == hasResult(securityOriginData)) {
291             SECURITY_ORIGIN_DB_DELETE(del,
292                                       SecurityOriginInfo,
293                                       &m_securityOriginDBInterface)
294             del->Where(
295                 And(And(And(Equals<SecurityOriginInfo::feature>(
296                                 securityOriginData.feature),
297                             Equals<SecurityOriginInfo::scheme>(
298                                 securityOriginData.origin.scheme)),
299                         Equals<SecurityOriginInfo::host>(securityOriginData.
300                                                              origin.host)),
301                     Equals<SecurityOriginInfo::port>(securityOriginData.origin.
302                                                          port)));
303             del->Execute();
304             transaction.Commit();
305         }
306     }
307     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to set security origin data")
308 }
309
310 void SecurityOriginDAO::removeSecurityOriginData(const Result result)
311 {
312     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
313     {
314         ScopedTransaction transaction(&m_securityOriginDBInterface);
315         SECURITY_ORIGIN_DB_DELETE(del,
316                                   SecurityOriginInfo,
317                                   &m_securityOriginDBInterface)
318         del->Where(Equals<SecurityOriginInfo::result>(result));
319         del->Execute();
320         transaction.Commit();
321     }
322     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to remove data by result")
323 }
324
325 bool SecurityOriginDAO::hasResult(const SecurityOriginData &securityOriginData)
326 {
327     Result res = getResult(securityOriginData);
328     return (res != RESULT_UNKNOWN);
329 }
330
331 #undef SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
332 #undef SQL_CONNECTION_EXCEPTION_HANDLER_END
333 } // namespace SecurityOriginDB