2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
34 using namespace WrtDB;
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");
41 bool checkDirectoryExist(const std::string& pkgId)
43 DPL::Utils::Path installPath(GlobalConfig::GetUserInstalledWidgetPath());
45 return installPath.Exists();
50 namespace WidgetUninstall {
52 class UninstallerTaskFail :
53 public DPL::TaskDecl<UninstallerTaskFail>
56 WidgetStatus m_status;
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");
67 Throw(Jobs::WidgetUninstall::Exceptions::Base);
72 UninstallerTaskFail(WidgetStatus status) :
73 DPL::TaskDecl<UninstallerTaskFail>(this),
77 AddStep(&UninstallerTaskFail::StepFail);
81 JobWidgetUninstall::JobWidgetUninstall(
82 const std::string & tizenPkgId,
83 const WidgetUninstallationStruct &
86 JobContextBase<WidgetUninstallationStruct>(uninstallerStruct),
87 m_exceptionCaught(Jobs::Exceptions::Success),
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;
99 WidgetStatus status = getWidgetStatus(tizenPkgId);
101 if (WidgetStatus::Ok == status) {
102 //TODO: check and save type
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();
113 _D("Widget model exists. Pkg id : %s", m_context.tzPkgid.c_str());
115 // send start signal of pkgmgr
116 if (GetInstallerStruct().pkgmgrInterface->setPkgname(m_context.tzPkgid))
118 GetInstallerStruct().pkgmgrInterface->startJob(InstallationType::Uninstallation);
121 AddTask(new TaskCheck(m_context));
122 if (packagingType == PKG_TYPE_HYBRID_WEB_APP) {
123 AddTask(new TaskUninstallOspsvc(m_context));
125 AddTask(new TaskDeletePkgInfo(m_context));
126 AddTask(new TaskDbUpdate(m_context));
127 AddTask(new TaskSmack(m_context));
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));
139 AddTask(new UninstallerTaskFail(WidgetStatus::UNRECOGNIZED));
141 } Catch(WidgetDAOReadOnly::Exception::Base) {
142 AddTask(new UninstallerTaskFail(WidgetStatus::UNRECOGNIZED));
146 // regexec() function does not work properly in specific locale (ex, Estonian)
147 // So, change locale temporally before call regcomp and regexec
151 currentLocale = setlocale(LC_ALL , NULL);
152 if (NULL == setlocale(LC_ALL, "C")) {
153 _W("Failed to change locale to \"C\"");
158 if (NULL == setlocale(LC_ALL, currentLocale.c_str())) {
159 _W("Failed to set previous locale");
164 std::string currentLocale;
167 WidgetStatus JobWidgetUninstall::getWidgetStatus(const std::string &id)
172 if(regcomp(®x, REG_TIZEN_PKGID_PATTERN, REG_NOSUB | REG_EXTENDED)!=0){
173 _D("Regcomp failed");
175 std::string pkgId = id;
176 DPL::Utils::Path installPath;
178 if ((regexec(®x, id.c_str(),
179 static_cast<size_t>(0), NULL, 0) != REG_NOERROR)) {
181 pkgId = id.substr(0, PKGID_LENTH);
183 //Service app cannot uninstall by appid
184 WrtDB::WidgetDAOReadOnly dao(DPL::FromUTF8String(id));
185 if( dao.getWidgetType().appType == APP_TYPE_TIZENWEBSERVICE ){
186 _E("Service app cannot uninstall by appid");
187 return WidgetStatus::NOT_INSTALLED;
191 m_context.tzAppIdList = WrtDB::WidgetDAOReadOnly::getTzAppIdList(DPL::FromUTF8String(pkgId));
192 if( m_context.tzAppIdList.empty() ){
193 if(checkDirectoryExist(pkgId)) {
194 _E("installed widget status is abnormal");
196 return WidgetStatus::ABNORMAL;
198 return WidgetStatus::NOT_INSTALLED;
201 return WidgetStatus::Ok;
204 std::string JobWidgetUninstall::getRemovedTizenId() const
209 bool JobWidgetUninstall::getRemoveStartedFlag() const
211 return m_context.removeStarted;
214 bool JobWidgetUninstall::getRemoveFinishedFlag() const
216 return m_context.removeFinished;
219 DPL::Utils::Path JobWidgetUninstall::getManifestFile() const
221 std::ostringstream manifest_name;
222 manifest_name << m_context.tzPkgid << ".xml";
223 DPL::Utils::Path manifestFile;
225 const DPL::Utils::Path PRELOAD_INSTALLED_PATH("/usr/apps/" + m_context.tzPkgid);
226 const DPL::Utils::Path USR_PACKAGES_PATH("/usr/share/packages");
227 const DPL::Utils::Path OPT_PACKAGES_PATH("/opt/share/packages");
229 if (PRELOAD_INSTALLED_PATH == m_context.installedPath) {
230 _D("This widget is preloaded.");
231 manifestFile = USR_PACKAGES_PATH;
233 manifestFile = OPT_PACKAGES_PATH;
236 manifestFile /= manifest_name.str();
237 _D("Manifest file : %s", manifestFile.Fullpath().c_str());
242 void JobWidgetUninstall::SendProgress()
244 using namespace PackageManager;
245 if (!getRemoveStartedFlag() ||
246 (getRemoveStartedFlag() && getRemoveFinishedFlag()))
248 if (NULL != GetInstallerStruct().progressCallback) {
249 // send progress signal of pkgmgr
250 std::ostringstream percent;
251 percent << static_cast<int>(GetProgressPercent());
253 _D("Call widget uninstall progressCallback");
254 GetInstallerStruct().progressCallback(
255 GetInstallerStruct().userParam,
256 GetProgressPercent(), GetProgressDescription());
261 void JobWidgetUninstall::SendFinishedSuccess()
263 using namespace PackageManager;
264 // send signal of pkgmgr
265 GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught);
267 _D("Call widget uninstall success finishedCallback");
268 GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam,
270 Jobs::Exceptions::Success);
273 void JobWidgetUninstall::SendFinishedFailure()
275 using namespace PackageManager;
277 LOGE(COLOR_ERROR "Error in uninstallation step: %d" COLOR_END, m_exceptionCaught);
278 LOGE(COLOR_ERROR "Message: %s" COLOR_END, m_exceptionMessage.c_str());
279 fprintf(stderr, "[Err:%d] %s", m_exceptionCaught, m_exceptionMessage.c_str());
281 // send signal of pkgmgr
282 GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught);
284 _D("Call widget uninstall failure finishedCallback");
285 GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam,
288 _D("[JobWidgetUninstall] Asynchronous failure callback status sent");
291 void JobWidgetUninstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
293 m_exceptionCaught = static_cast<Jobs::Exceptions::Type>(e.getParam());
294 m_exceptionMessage = e.GetMessage();
296 } //namespace WidgetUninstall