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