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