70c63400ffca784a2a1d5ba088231836dea44c4e
[platform/framework/web/wrt-installer.git] / src / jobs / widget_uninstall / job_widget_uninstall.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 #include <regex.h>
18 #include <sys/stat.h>
19 #include <widget_uninstall/job_widget_uninstall.h>
20 #include <widget_uninstall/widget_uninstall_errors.h>
21 #include <widget_uninstall/task_check.h>
22 #include <widget_uninstall/task_db_update.h>
23 #include <widget_uninstall/task_remove_files.h>
24 #include <widget_uninstall/task_remove_custom_handlers.h>
25 #include <widget_uninstall/task_smack.h>
26 #include <widget_uninstall/task_uninstall_ospsvc.h>
27 #include <widget_uninstall/task_delete_certificates.h>
28 #include <dpl/wrt-dao-ro/global_config.h>
29 #include <pkg-manager/pkgmgr_signal.h>
30 #include <app2ext_interface.h>
31 #include <dpl/utils/path.h>
32
33 using namespace WrtDB;
34
35 namespace { //anonymous
36 const char* REG_TIZEN_PKGID_PATTERN = "^[a-zA-Z0-9]{10}$";
37 const int PKGID_LENTH = 10;
38 const DPL::Utils::Path PRELOAD_INSTALLED_PATH("/usr/apps");
39
40 bool checkDirectoryExist(const std::string& pkgId)
41 {
42     DPL::Utils::Path installPath(GlobalConfig::GetUserInstalledWidgetPath());
43     installPath /= pkgId;
44     return installPath.Exists();
45 }
46 }
47
48 namespace Jobs {
49 namespace WidgetUninstall {
50
51 class UninstallerTaskFail :
52     public DPL::TaskDecl<UninstallerTaskFail>
53 {
54   private:
55     WidgetStatus m_status;
56
57     void StepFail()
58     {
59         if (WidgetStatus::NOT_INSTALLED == m_status) {
60             ThrowMsg(Jobs::WidgetUninstall::Exceptions::WidgetNotExist,
61                      "Widget does not exist");
62         } else if (WidgetStatus::PREALOAD == m_status) {
63             ThrowMsg(Jobs::WidgetUninstall::Exceptions::Unremovable,
64                      "Widget cann't uninstall");
65         } else {
66             Throw(Jobs::WidgetUninstall::Exceptions::Base);
67         }
68     }
69
70   public:
71     UninstallerTaskFail(WidgetStatus status) :
72         DPL::TaskDecl<UninstallerTaskFail>(this),
73         m_status(status)
74
75     {
76         AddStep(&UninstallerTaskFail::StepFail);
77     }
78 };
79
80 JobWidgetUninstall::JobWidgetUninstall(
81     const std::string & tizenAppId,
82     const WidgetUninstallationStruct &
83     uninstallerStruct) :
84     Job(Uninstallation),
85     JobContextBase<WidgetUninstallationStruct>(uninstallerStruct)
86 {
87     using namespace PackageManager;
88     m_context.removeStarted = false;
89     m_context.removeFinished = false;
90     m_context.removeAbnormal = false;
91     m_context.uninstallStep = UninstallerContext::UNINSTALL_START;
92     m_context.job = this;
93
94     Try
95     {
96         WidgetStatus status = getWidgetStatus(tizenAppId);
97
98         if (WidgetStatus::Ok == status) {
99             WrtDB::WidgetDAOReadOnly dao(DPL::FromUTF8String(m_context.tzAppid));
100             m_context.tzPkgid = DPL::ToUTF8String(dao.getTizenPkgId());
101             m_context.locations = WidgetLocation(m_context.tzPkgid);
102             m_context.locations->registerAppid(m_context.tzAppid);
103             m_context.installedPath =
104                 DPL::Utils::Path(*dao.getWidgetInstalledPath());
105
106             LogInfo("Widget model exists. App id : " << m_context.tzAppid);
107
108             AddTask(new TaskSmack(m_context));
109             AddTask(new TaskCheck(m_context));
110
111             if (dao.getPackagingType() == PKG_TYPE_HYBRID_WEB_APP) {
112                 AddTask(new TaskUninstallOspsvc(m_context));
113             }
114             AddTask(new TaskRemoveFiles(m_context));
115             AddTask(new TaskDbUpdate(m_context));
116             AddTask(new TaskRemoveCustomHandlers(m_context));
117             AddTask(new TaskDeleteCertificates(m_context));
118
119             // send start signal of pkgmgr
120             if (getInstallerStruct().pkgmgrInterface->setPkgname(m_context.tzPkgid))
121             {
122                 getInstallerStruct().pkgmgrInterface->sendSignal(
123                         PKGMGR_START_KEY,
124                         PKGMGR_START_UNINSTALL);
125             }
126         } else if (WidgetStatus::NOT_INSTALLED == status ||
127                 WidgetStatus::PREALOAD == status) {
128             AddTask(new UninstallerTaskFail(status));
129         } else if (WidgetStatus::ABNORMAL == status) {
130             m_context.locations = WidgetLocation(m_context.tzPkgid);
131             m_context.removeAbnormal = true;
132             AddTask(new TaskRemoveFiles(m_context));
133         } else {
134             AddTask(new UninstallerTaskFail(WidgetStatus::UNRECOGNIZED));
135         }
136     } Catch(WidgetDAOReadOnly::Exception::Base) {
137         AddTask(new UninstallerTaskFail(WidgetStatus::UNRECOGNIZED));
138     }
139 }
140
141 WidgetStatus JobWidgetUninstall::getWidgetStatus(const std::string &id)
142 {
143     regex_t regx;
144     if(regcomp(&regx, REG_TIZEN_PKGID_PATTERN, REG_NOSUB | REG_EXTENDED)!=0){
145         LogDebug("Regcomp failed");
146     }
147     std::string pkgId;
148     DPL::Utils::Path installPath;
149
150     Try {
151         if ((regexec(&regx, id.c_str(),
152                         static_cast<size_t>(0), NULL, 0) == REG_NOERROR)) {
153             pkgId = id;
154
155             TizenAppId appid =
156                 WrtDB::WidgetDAOReadOnly::getTzAppId(
157                         DPL::FromUTF8String(id));
158             LogDebug("Get appid from pkgid : " << appid);
159             m_context.tzAppid = DPL::ToUTF8String(appid);
160             WrtDB::WidgetDAOReadOnly dao(appid);
161             installPath = DPL::Utils::Path(*dao.getWidgetInstalledPath());
162         } else {
163             pkgId = id.substr(0, PKGID_LENTH);
164             WrtDB::WidgetDAOReadOnly dao(DPL::FromUTF8String(id));
165             m_context.tzAppid = id;
166             installPath = DPL::Utils::Path(*dao.getWidgetInstalledPath());
167         }
168         if(installPath.isSubPath(PRELOAD_INSTALLED_PATH)){
169             LogDebug("This widget is prealoded.");
170         }
171     } Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
172         LogDebug("package id : " << pkgId);
173         m_context.tzPkgid = pkgId;
174         if (!pkgId.empty()) {
175             if(checkDirectoryExist(pkgId)) {
176                 LogError("installed widget status is abnormal");
177                 return WidgetStatus::ABNORMAL;
178             }
179         }
180         return WidgetStatus::NOT_INSTALLED;
181     }
182     return WidgetStatus::Ok;
183 }
184
185 std::string JobWidgetUninstall::getRemovedTizenId() const
186 {
187     return m_context.tzAppid;
188 }
189
190 bool JobWidgetUninstall::getRemoveStartedFlag() const
191 {
192     return m_context.removeStarted;
193 }
194
195 bool JobWidgetUninstall::getRemoveFinishedFlag() const
196 {
197     return m_context.removeFinished;
198 }
199
200 void JobWidgetUninstall::SendProgress()
201 {
202     using namespace PackageManager;
203     if (!getRemoveStartedFlag() ||
204         (getRemoveStartedFlag() && getRemoveFinishedFlag()))
205     {
206         if (NULL != getInstallerStruct().progressCallback) {
207             // send progress signal of pkgmgr
208             std::ostringstream percent;
209             percent << static_cast<int>(GetProgressPercent());
210
211             LogDebug("Call widget uninstall progressCallback");
212             getInstallerStruct().progressCallback(
213                 getInstallerStruct().userParam,
214                 GetProgressPercent(), GetProgressDescription());
215         }
216     }
217 }
218
219 void JobWidgetUninstall::SendFinishedSuccess()
220 {
221     using namespace PackageManager;
222     // send signal of pkgmgr
223     getInstallerStruct().pkgmgrInterface->sendSignal(
224         PKGMGR_END_KEY,
225         PKGMGR_END_SUCCESS);
226
227     LogDebug("Call widget uninstall success finishedCallback");
228     getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
229                                           getRemovedTizenId(),
230                                           Jobs::Exceptions::Success);
231 }
232
233 void JobWidgetUninstall::SendFinishedFailure()
234 {
235     using namespace PackageManager;
236     LogError("Error in uninstallation step: " << m_exceptionCaught);
237     LogError("Message: " << m_exceptionMessage);
238
239     // send signal of pkgmgr
240     getInstallerStruct().pkgmgrInterface->sendSignal(
241         PKGMGR_END_KEY,
242         PKGMGR_END_FAILURE);
243
244     LogDebug("Call widget uninstall failure finishedCallback");
245     getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
246                                           getRemovedTizenId(),
247                                           m_exceptionCaught); //TODO
248     LogDebug("[JobWidgetUninstall] Asynchronous failure callback status sent");
249 }
250
251 void JobWidgetUninstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
252 {
253     m_exceptionCaught = static_cast<Jobs::Exceptions::Type>(e.getParam());
254     m_exceptionMessage = e.GetMessage();
255 }
256 } //namespace WidgetUninstall
257 } //namespace Jobs