Initialize Tizen 2.3
[framework/web/wrt-installer.git] / src_wearable / jobs / widget_install / task_database.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    task_new_db_insert.cpp
18  * @author  Lukasz Wrzosek(l.wrzosek@samsung.com)
19  * @author  Soyoung kim(sy037.kim@samsung.com)
20  * @version 1.0
21  * @brief   Implementation file for installer task database updating for widget
22  * update
23  */
24 #include <unistd.h>
25 #include <cstdio>
26 #include <time.h>
27 #include <sys/stat.h>
28 #include <widget_install/task_database.h>
29 #include <widget_install/job_widget_install.h>
30 #include <widget_install/widget_install_errors.h>
31 #include <widget_install/widget_install_context.h>
32 #ifdef DBOX_ENABLED
33 #include <web_provider_livebox_info.h>
34 #endif
35 #include <dpl/wrt-dao-rw/widget_dao.h>
36 #include <dpl/foreach.h>
37 #include <dpl/utils/wrt_utility.h>
38 #include <dpl/assert.h>
39 #include <wrt-commons/security-origin-dao/security_origin_dao.h>
40 #include <wrt-commons/widget-interface-dao/widget_interface_dao.h>
41 #include <dpl/wrt-dao-ro/global_config.h>
42 #include <dpl/wrt-dao-ro/widget_dao_types.h>
43 #include <string>
44 #include <sstream>
45 #include <ace_api_install.h>
46 #include <ace_registration.h>
47 #include <errno.h>
48 #include <string.h>
49 #include <map>
50 #include <installer_log.h>
51
52 using namespace WrtDB;
53
54 namespace Jobs {
55 namespace WidgetInstall {
56 TaskDatabase::TaskDatabase(InstallerContext& context) :
57     DPL::TaskDecl<TaskDatabase>(this),
58     m_context(context)
59 {
60     AddStep(&TaskDatabase::StartStep);
61     AddStep(&TaskDatabase::StepRegisterExternalFiles);
62     AddStep(&TaskDatabase::StepWrtDBInsert);
63     AddStep(&TaskDatabase::StepAceDBInsert);
64     AddStep(&TaskDatabase::StepSecurityOriginDBInsert);
65     AddStep(&TaskDatabase::StepWidgetInterfaceDBInsert);
66     AddStep(&TaskDatabase::StepRemoveExternalFiles);
67 #ifdef DBOX_ENABLED
68     AddStep(&TaskDatabase::StepLiveboxDBInsert);
69 #endif
70     AddStep(&TaskDatabase::EndStep);
71
72     AddAbortStep(&TaskDatabase::StepAbortDBInsert);
73     AddAbortStep(&TaskDatabase::StepAbortAceDBInsert);
74     AddAbortStep(&TaskDatabase::StepAbortWidgetInterfaceDBInsert);
75 }
76
77 void TaskDatabase::StepWrtDBInsert()
78 {
79     Try
80     {
81         /* Set install Time */
82         time(&m_context.widgetConfig.installedTime);
83
84         if (m_context.isUpdateMode) { //update
85             _D("Registering widget... (update)");
86             Try
87             {
88                 std::list<TizenAppId> idList = WidgetDAOReadOnly::getTzAppIdList(m_context.widgetConfig.tzPkgid);
89                 FOREACH(it , idList ){
90                     //installed AppId list, It need to delete ACE Database corresponding record
91                     m_handleToRemoveList.push_back(WidgetDAOReadOnly::getHandle(*it));
92                     WrtDB::TizenAppId backAppId = *it + L".backup";
93                     m_backAppIdList.push_back(backAppId);
94                     //Change all installed tzAppid to .backup
95                     WidgetDAO::updateTizenAppId(*it, backAppId);
96             }
97
98             WidgetDAO::registerWidget(m_context.widgetConfig.tzAppid,
99                                       m_context.widgetConfig,
100                                       m_context.widgetSecurity);
101                 m_handleList.push_back(WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid));
102
103                 FOREACH(iterator, m_context.widgetConfig.configInfo.serviceAppInfoList) {
104                     WrtDB::TizenAppId tizenAppId = iterator->serviceId;
105                     WidgetDAO::registerService(*iterator, m_context.widgetConfig, m_context.widgetSecurity);
106                     m_handleList.push_back(WidgetDAOReadOnly::getHandle(tizenAppId));
107                 }
108             }
109             Catch(WidgetDAOReadOnly::Exception::WidgetNotExist)
110             {
111                 LogError(
112                     "Given tizenId not found for update installation (Same GUID?)");
113                 ThrowMsg(Exceptions::DatabaseFailure,
114                          "Given tizenId not found for update installation");
115             }
116         } else { //new installation
117             _D("Registering widget...");
118             WidgetDAO::registerWidget(
119                 m_context.widgetConfig.tzAppid,
120                 m_context.widgetConfig,
121                 m_context.widgetSecurity);
122
123             m_handleList.push_back(WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid));
124
125             FOREACH(iterator, m_context.widgetConfig.configInfo.serviceAppInfoList) {
126                     WidgetDAO::registerService(*iterator, m_context.widgetConfig, m_context.widgetSecurity);
127                     m_handleList.push_back(WidgetDAOReadOnly::getHandle(iterator->serviceId));
128             }
129         }
130
131         FOREACH(cap, m_context.staticPermittedDevCaps) {
132             _D("staticPermittedDevCaps : %ls smack status: %d", cap->first.c_str(), cap->second);
133         }
134
135         _D("Widget registered");
136     }
137     Catch(WidgetDAO::Exception::DatabaseError)
138     {
139         _E("Database failure!");
140         ReThrowMsg(Exceptions::InsertNewWidgetFailed, "Database failure!");
141     }
142     Catch(DPL::DB::SqlConnection::Exception::Base)
143     {
144         _E("Database failure!");
145         ReThrowMsg(Exceptions::InsertNewWidgetFailed, "Database failure!");
146     }
147 }
148
149 void TaskDatabase::StepAceDBInsert()
150 {
151     FOREACH(iterHandleToRemove, m_handleToRemoveList)
152     {
153         if (INVALID_WIDGET_HANDLE != *iterHandleToRemove) {
154             _D("Removing old insallation. Handle: %d", *iterHandleToRemove);
155             if (ACE_OK != ace_unregister_widget(
156                     static_cast<ace_widget_handle_t>(*iterHandleToRemove)))
157             {
158                 _W("Error while removing ace entry for previous insallation");
159             }
160         }
161     }
162
163     FOREACH(iterHandle, m_handleList)
164     {
165         if (!AceApi::registerAceWidget(*iterHandle, m_context.widgetConfig,
166                                    m_context.widgetSecurity.getCertificateList()))
167         {
168             _E("ace database insert failed");
169             ThrowMsg(Exceptions::UpdateFailed,
170                  "Update failure. ace_register_widget failed");
171         }
172         _D("Ace data inserted");
173     }
174 }
175
176 void TaskDatabase::StepSecurityOriginDBInsert()
177 {
178     _D("Create Security origin database");
179     // automatically create security origin database
180     using namespace SecurityOriginDB;
181     using namespace WrtDB;
182
183     try{
184         SecurityOriginDAO dao(m_context.locations->getPkgId());
185         // Checking privilege list for setting security origin exception data
186         FOREACH(it, m_context.widgetConfig.configInfo.privilegeList) {
187             std::map<std::string, Feature>::const_iterator result =
188                 g_W3CPrivilegeTextMap.find(DPL::ToUTF8String(it->name));
189             if (result != g_W3CPrivilegeTextMap.end()) {
190                 if (result->second == FEATURE_USER_MEDIA) {
191                     dao.setPrivilegeSecurityOriginData(result->second, false);
192                 } else if (result->second == FEATURE_FULLSCREEN_MODE) {
193                     continue;
194                 } else {
195                     dao.setPrivilegeSecurityOriginData(result->second);
196                 }
197             }
198         }
199     }catch(const SecurityOriginDAO::Exception::DatabaseError& err){
200         _E("error open SecurityOrigin db %s", err.GetMessage().c_str());
201         ThrowMsg(Exceptions::UpdateFailed, "Cannot open SecurityOrigin DB");
202     }
203 }
204
205 void TaskDatabase::StepWidgetInterfaceDBInsert()
206 {
207     _D("Create Widget Interface database");
208     using namespace WidgetInterfaceDB;
209     using namespace WrtDB;
210
211     DbWidgetHandle handle =
212         WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid);
213
214     // backup database
215     if (m_context.isUpdateMode) {
216         std::string dbPath = WidgetInterfaceDAO::databaseFileName(handle);
217         std::string backupDbPath = dbPath;
218         backupDbPath += GlobalConfig::GetBackupDatabaseSuffix();
219         _D("\"%s\" to \"%s\"", dbPath.c_str(), backupDbPath.c_str());
220         if (0 != std::rename(dbPath.c_str(), backupDbPath.c_str())) {
221             _E("widget interface database backup failed");
222             ThrowMsg(Exceptions::UpdateFailed,
223                      "widget interface database backup failed");
224         }
225     }
226
227     Try
228     {
229         // automatically create widget interface database
230         WidgetInterfaceDAO dao(handle);
231     }
232     Catch(WidgetInterfaceDAO::Exception::DatabaseError)
233     {
234         _E("widget interface database create failed");
235         ThrowMsg(Exceptions::UpdateFailed,
236                  "widget interface database create failed");
237     }
238 }
239
240 void TaskDatabase::StepRegisterExternalFiles()
241 {
242     WrtDB::ExternalLocationList externalLocationsUpdate =
243         m_context.locations->listExternalLocations();
244     if (m_context.isUpdateMode) { //update
245         Try
246         {
247             WidgetDAOReadOnly dao(WidgetDAOReadOnly::getHandleByPkgId(m_context.widgetConfig.tzPkgid));
248             WrtDB::ExternalLocationList externalLocationsDB =
249                 dao.getWidgetExternalLocations();
250             FOREACH(file, externalLocationsDB)
251             {
252                 if (std::find(externalLocationsUpdate.begin(),
253                               externalLocationsUpdate.end(),
254                               *file) == externalLocationsUpdate.end())
255                 {
256                     m_externalLocationsToRemove.push_back(*file);
257                 }
258             }
259         }
260         Catch(WidgetDAOReadOnly::Exception::WidgetNotExist)
261         {
262             _E("Given tizenId not found for update installation (Same GUID?)");
263             ThrowMsg(Exceptions::UpdateFailed,
264                      "Given tizenId not found for update installation");
265         }
266     }
267     _D("Registering external files:");
268     FOREACH(file, externalLocationsUpdate)
269     {
270         _D("  -> %s", (*file).c_str());
271     }
272
273     //set external locations to be registered
274     m_context.widgetConfig.externalLocations = externalLocationsUpdate;
275 }
276
277 void TaskDatabase::StepRemoveExternalFiles()
278 {
279     if (!m_externalLocationsToRemove.empty()) {
280         _D("Removing external files:");
281     }
282
283     FOREACH(file, m_externalLocationsToRemove)
284     {
285         if (WrtUtilFileExists(*file)) {
286             _D("  -> %s", (*file).c_str());
287             if (-1 == remove(file->c_str())) {
288                 ThrowMsg(Exceptions::RemovingFileFailure,
289                          "Failed to remove external file");
290             }
291         } else if (WrtUtilDirExists(*file)) {
292             _D("  -> %s", (*file).c_str());
293             if (!WrtUtilRemove(*file)) {
294                 ThrowMsg(Exceptions::RemovingFolderFailure,
295                          "Failed to remove external directory");
296             }
297         } else {
298             _W("  -> %s(no such a path)", (*file).c_str());
299         }
300     }
301 }
302
303 void TaskDatabase::StepAbortDBInsert()
304 {
305     _W("[DB Update Task] Aborting... (DB Clean)");
306     Try
307     {
308             WidgetDAO::unregisterWidget(m_context.widgetConfig.tzAppid);
309
310         FOREACH(iter, m_context.widgetConfig.configInfo.serviceAppInfoList) {
311             WidgetDAO::unregisterWidget(iter->serviceId);
312         }
313
314         if (m_context.isUpdateMode) {
315             FOREACH(iter, m_backAppIdList) {
316                 unsigned pos = (*iter).find(L".backup");
317                 TizenAppId str = (*iter).substr(0, pos);
318                 WidgetDAO::updateTizenAppId(*iter, str);
319             }
320         }
321         _D("Cleaning DB successful!");
322     }
323     Catch(DPL::DB::SqlConnection::Exception::Base)
324     {
325         _E("Failed to handle StepAbortDBClean!");
326     }
327 }
328
329 void TaskDatabase::StepAbortAceDBInsert()
330 {
331     _W("[DB Update Task] ACE DB Aborting... (DB Clean)");
332
333     FOREACH(iter, m_handleList) {
334             ace_unregister_widget(static_cast<ace_widget_handle_t>(*iter));
335     }
336
337     FOREACH(iter, m_handleToRemoveList) {
338         // Remove also old one. If it was already updated nothing wrong will happen,
339         // but if not old widget will be removed.
340         if (INVALID_WIDGET_HANDLE != *iter) {
341             ace_unregister_widget(static_cast<ace_widget_handle_t>(*iter));
342         }
343
344         if (!AceApi::registerAceWidgetFromDB(*iter))
345         {
346         _E("ace database restore failed");
347         }
348     }
349     _D("Ace data inserted");
350 }
351
352 void TaskDatabase::StepAbortWidgetInterfaceDBInsert()
353 {
354     _D("[DB Update Task] Widget interface Aborting...");
355     using namespace WidgetInterfaceDB;
356     using namespace WrtDB;
357
358     DbWidgetHandle handle =
359         WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid);
360     std::string dbPath = WidgetInterfaceDAO::databaseFileName(handle);
361
362     // remove database
363     if (remove(dbPath.c_str()) != 0) {
364         _W("Fail to remove");
365     }
366
367     // rollback database
368     if (m_context.isUpdateMode) {
369         std::string backupDbPath = dbPath;
370         backupDbPath += GlobalConfig::GetBackupDatabaseSuffix();
371         _D("\"%s\" to \"%s\"", dbPath.c_str(), backupDbPath.c_str());
372         if (0 != std::rename(backupDbPath.c_str(), dbPath.c_str())) {
373             _W("Fail to rollback");
374         }
375     }
376 }
377
378 #ifdef DBOX_ENABLED
379 void TaskDatabase::StepLiveboxDBInsert()
380 {
381     if (m_context.widgetConfig.configInfo.m_livebox.size() <= 0) {
382         return;
383     }
384
385     std::string tizenId = DPL::ToUTF8String(m_context.widgetConfig.tzAppid);
386
387     // insert specific information to web livebox db
388     for (auto it = m_context.widgetConfig.configInfo.m_livebox.begin();
389          it != m_context.widgetConfig.configInfo.m_livebox.end(); ++it)
390     {
391         std::string boxId = DPL::ToUTF8String((**it).m_liveboxId);
392         std::string boxType;
393         if ((**it).m_type.empty()) {
394             boxType = web_provider_livebox_get_default_type();
395         } else {
396             boxType = DPL::ToUTF8String((**it).m_type);
397         }
398         _D("livebox id: %s", boxId.c_str());
399         _D("livebox type: %s", boxType.c_str());
400
401         int autoLaunch = (**it).m_autoLaunch == L"true" ? 1 : 0;
402         _D("livebox auto-launch: %d", autoLaunch);
403
404         int mouseEvent = (**it).m_boxInfo.m_boxMouseEvent == L"true" ? 1 : 0;
405         _D("livebox mouse-event: %d", mouseEvent);
406
407         int pdFastOpen = (**it).m_boxInfo.m_pdFastOpen == L"true" ? 1 : 0;
408         _D("livebox pd fast-open: %d", pdFastOpen);
409
410         if (m_context.isUpdateMode) {
411             web_provider_livebox_delete_by_app_id(tizenId.c_str());
412         }
413         web_provider_livebox_insert_box_info(
414                 boxId.c_str(), tizenId.c_str(), boxType.c_str(),
415                 autoLaunch, mouseEvent, pdFastOpen);
416     }
417 }
418 #endif
419
420 void TaskDatabase::StartStep()
421 {
422     LOGD("--------- <TaskDatabase> : START ----------");
423 }
424
425 void TaskDatabase::EndStep()
426 {
427     LOGD("--------- <TaskDatabase> : END ----------");
428 }
429 } //namespace WidgetInstall
430 } //namespace Jobs