9bb4897ca22511a63f728de31836e01f9a9f0970
[framework/web/wrt-installer.git] / src_wearable / 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 & tizenPkgId,
83     const WidgetUninstallationStruct &
84     uninstallerStruct) :
85     Job(Uninstallation),
86     JobContextBase<WidgetUninstallationStruct>(uninstallerStruct),
87     m_id(tizenPkgId),
88     m_exceptionCaught(Jobs::Exceptions::Success)
89 {
90     using namespace PackageManager;
91     m_context.removeStarted = false;
92     m_context.removeFinished = false;
93     m_context.removeAbnormal = false;
94     m_context.uninstallStep = UninstallerContext::UNINSTALL_START;
95     m_context.job = this;
96
97     Try
98     {
99         WidgetStatus status = getWidgetStatus(tizenPkgId);
100
101         if (WidgetStatus::Ok == status) {
102             //TODO: check and save type
103
104             WrtDB::WidgetDAOReadOnly dao(*m_context.tzAppIdList.begin());
105             m_context.tzPkgid = DPL::ToUTF8String(dao.getTizenPkgId());
106             m_context.locations = WidgetLocation(m_context.tzPkgid);
107             m_context.locations->registerAppid(DPL::ToUTF8String(*m_context.tzAppIdList.begin()));
108             m_context.installedPath =
109                 DPL::Utils::Path(*dao.getWidgetInstalledPath());
110             m_context.manifestFile = getManifestFile();
111             PackagingType packagingType = dao.getPackagingType();
112
113             _D("Widget model exists. Pkg id : %s", m_context.tzPkgid.c_str());
114
115             // send start signal of pkgmgr
116             if (GetInstallerStruct().pkgmgrInterface->setPkgname(m_context.tzPkgid))
117             {
118                 GetInstallerStruct().pkgmgrInterface->startJob(InstallationType::Uninstallation);
119             }
120
121             AddTask(new TaskCheck(m_context));
122             if (packagingType == PKG_TYPE_HYBRID_WEB_APP) {
123                 AddTask(new TaskUninstallOspsvc(m_context));
124             }
125             AddTask(new TaskDeletePkgInfo(m_context));
126             AddTask(new TaskDbUpdate(m_context));
127             AddTask(new TaskSmack(m_context));
128
129             AddTask(new TaskRemoveCustomHandlers(m_context));
130             AddTask(new TaskRemoveFiles(m_context));
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         _D("Regcomp failed");
151     }
152     std::string pkgId = id;
153     DPL::Utils::Path installPath;
154             if ((regexec(&regx, id.c_str(),
155         static_cast<size_t>(0), NULL, 0) != REG_NOERROR)) {
156         //appid was passed
157                 pkgId = id.substr(0, PKGID_LENTH);
158
159         //Service app cannot uninstall by appid
160                 WrtDB::WidgetDAOReadOnly dao(DPL::FromUTF8String(id));
161         if( dao.getWidgetType().appType == APP_TYPE_TIZENWEBSERVICE ){
162             _E("Service app cannot uninstall by appid");
163             return WidgetStatus::NOT_INSTALLED;
164             }
165             }
166
167     m_context.tzAppIdList = WrtDB::WidgetDAOReadOnly::getTzAppIdList(DPL::FromUTF8String(pkgId));
168     if( m_context.tzAppIdList.empty() ){
169                 if(checkDirectoryExist(pkgId)) {
170                     _E("installed widget status is abnormal");
171                     return WidgetStatus::ABNORMAL;
172                 }
173             return WidgetStatus::NOT_INSTALLED;
174         }
175     return WidgetStatus::Ok;
176 }
177
178 std::string JobWidgetUninstall::getRemovedTizenId() const
179 {
180     return m_id;
181 }
182
183 bool JobWidgetUninstall::getRemoveStartedFlag() const
184 {
185     return m_context.removeStarted;
186 }
187
188 bool JobWidgetUninstall::getRemoveFinishedFlag() const
189 {
190     return m_context.removeFinished;
191 }
192
193 DPL::Utils::Path JobWidgetUninstall::getManifestFile() const
194 {
195     std::ostringstream manifest_name;
196     manifest_name << m_context.tzPkgid << ".xml";
197     DPL::Utils::Path manifestFile;
198
199     const DPL::Utils::Path PRELOAD_INSTALLED_PATH("/usr/apps/" + m_context.tzPkgid);
200     const DPL::Utils::Path USR_PACKAGES_PATH("/usr/share/packages");
201     const DPL::Utils::Path OPT_PACKAGES_PATH("/opt/share/packages");
202
203     if (PRELOAD_INSTALLED_PATH == m_context.installedPath) {
204         _D("This widget is preloaded.");
205         manifestFile = USR_PACKAGES_PATH;
206     } else {
207         manifestFile = OPT_PACKAGES_PATH;
208     }
209
210     manifestFile /= manifest_name.str();
211     _D("Manifest file : %s", manifestFile.Fullpath().c_str());
212
213     return manifestFile;
214 }
215
216 void JobWidgetUninstall::SendProgress()
217 {
218     using namespace PackageManager;
219     if (!getRemoveStartedFlag() ||
220         (getRemoveStartedFlag() && getRemoveFinishedFlag()))
221     {
222         if (NULL != GetInstallerStruct().progressCallback) {
223             // send progress signal of pkgmgr
224             std::ostringstream percent;
225             percent << static_cast<int>(GetProgressPercent());
226
227             _D("Call widget uninstall progressCallback");
228             GetInstallerStruct().progressCallback(
229                 GetInstallerStruct().userParam,
230                 GetProgressPercent(), GetProgressDescription());
231         }
232     }
233 }
234
235 void JobWidgetUninstall::SendFinishedSuccess()
236 {
237     using namespace PackageManager;
238     // send signal of pkgmgr
239     GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught);
240
241     _D("Call widget uninstall success finishedCallback");
242     GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam,
243                                           getRemovedTizenId(),
244                                           Jobs::Exceptions::Success);
245 }
246
247 void JobWidgetUninstall::SendFinishedFailure()
248 {
249     using namespace PackageManager;
250
251     LOGE(COLOR_ERROR "Error in uninstallation step: %d" COLOR_END, m_exceptionCaught);
252     LOGE(COLOR_ERROR "Message: %s" COLOR_END, m_exceptionMessage.c_str());
253     fprintf(stderr, "[Err:%d] %s", m_exceptionCaught, m_exceptionMessage.c_str());
254
255     // send signal of pkgmgr
256     GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught);
257
258     _D("Call widget uninstall failure finishedCallback");
259     GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam,
260                                           getRemovedTizenId(),
261                                           m_exceptionCaught);
262     _D("[JobWidgetUninstall] Asynchronous failure callback status sent");
263 }
264
265 void JobWidgetUninstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
266 {
267     m_exceptionCaught = static_cast<Jobs::Exceptions::Type>(e.getParam());
268     m_exceptionMessage = e.GetMessage();
269 }
270 } //namespace WidgetUninstall
271 } //namespace Jobs