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.
17 * @file job_widget_install.cpp
18 * @author Radoslaw Wicik r.wicik@samsung.com
19 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
21 * @brief Implementation file for main installer task
31 #include <dpl/noncopyable.h>
32 #include <dpl/abstract_waitable_input_adapter.h>
33 #include <dpl/abstract_waitable_output_adapter.h>
34 #include <dpl/zip_input.h>
35 #include <dpl/binary_queue.h>
37 #include <dpl/assert.h>
38 #include <dpl/sstream.h>
39 #include <dpl/file_input.h>
40 #include <dpl/utils/wrt_utility.h>
41 #include <dpl/wrt-dao-ro/common_dao_types.h>
42 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
43 #include <dpl/wrt-dao-ro/global_config.h>
44 #include <dpl/wrt-dao-ro/config_parser_data.h>
45 #include <dpl/wrt-dao-rw/global_dao.h> // TODO remove
46 #include <dpl/localization/w3c_file_localization.h>
48 #include <libiriwrapper.h>
49 #include <pkg-manager/pkgmgr_signal.h>
50 #include <app_manager.h>
52 #include "root_parser.h"
53 #include "widget_parser.h"
54 #include "parser_runner.h"
55 #include <widget_install/job_widget_install.h>
56 #include <widget_install/task_certify.h>
57 #include <widget_install/task_widget_config.h>
58 #include <widget_install/task_file_manipulation.h>
59 #include <widget_install/task_ace_check.h>
60 #include <widget_install/task_smack.h>
61 #include <widget_install/task_manifest_file.h>
62 #include <widget_install/task_prepare_files.h>
63 #include <widget_install/task_recovery.h>
64 #include <widget_install/task_install_ospsvc.h>
65 #include <widget_install/task_update_files.h>
66 #include <widget_install/task_database.h>
67 #include <widget_install/task_remove_backup.h>
68 #include <widget_install/task_encrypt_resource.h>
69 #include <widget_install/task_certificates.h>
70 #include <widget_install/task_unzip.h>
71 #include <widget_install/task_commons.h>
72 #include <widget_install/task_prepare_reinstall.h>
74 #include <widget_install/widget_install_errors.h>
75 #include <widget_install/widget_install_context.h>
76 #include <widget_install_to_external.h>
78 using namespace WrtDB;
79 using namespace Jobs::Exceptions;
81 namespace // anonymous
83 const char * const CONFIG_XML = "config.xml";
84 const char * const WITH_OSP_XML = "res/wgt/config.xml";
86 //allowed: a-z, A-Z, 0-9
87 const char* REG_TIZENID_PATTERN = "^[a-zA-Z0-9]{10}.{1,}$";
88 const char* REG_NAME_PATTERN = "^[a-zA-Z0-9._-]{1,}$";
89 const size_t PACKAGE_ID_LENGTH = 10;
91 static const DPL::String SETTING_VALUE_ENCRYPTION = L"encryption";
92 static const DPL::String SETTING_VALUE_ENCRYPTION_ENABLE = L"enable";
93 const DPL::String SETTING_VALUE_INSTALLTOEXT_NAME =
95 const DPL::String SETTING_VALUE_INSTALLTOEXT_PREPER_EXT =
98 const std::string XML_EXTENSION = ".xml";
100 bool hasExtension(const std::string& filename, const std::string& extension)
102 LogDebug("Looking for extension " << extension << " in: " << filename);
103 size_t fileLen = filename.length();
104 size_t extLen = extension.length();
105 if (fileLen < extLen) {
106 LogError("Filename " << filename << " is shorter than extension "
110 return (0 == filename.compare(fileLen - extLen, extLen, extension));
112 } // namespace anonymous
115 namespace WidgetInstall {
116 class InstallerTaskFail :
117 public DPL::TaskDecl<InstallerTaskFail>
120 ConfigureResult m_result;
124 if (m_result == ConfigureResult::Deferred) {
125 ThrowMsg(Jobs::WidgetInstall::Exceptions::Deferred,
126 "widget installation or update deferred!");
127 } else if (m_result == ConfigureResult::Failed_InvalidConfig) {
128 ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid,
130 } else if (m_result == ConfigureResult::Failed_LowerVersion) {
131 ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageLowerVersion,
132 "package version is lower than installed version");
133 } else if (m_result == ConfigureResult::Failed_AlreadyInstalled) {
134 ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageAlreadyInstalled,
135 "package is already installed");
136 } else if (m_result == ConfigureResult::Failed_WidgetRunning) {
137 ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError,
138 "widget is running");
139 } else if (m_result == ConfigureResult::Failed_DrmError) {
140 ThrowMsg(Jobs::WidgetInstall::Exceptions::DRMFailed,
143 ThrowMsg(Jobs::WidgetInstall::Exceptions::NotAllowed,
144 "widget installation or update not allowed!");
149 InstallerTaskFail(ConfigureResult result) :
150 DPL::TaskDecl<InstallerTaskFail>(this),
153 AddStep(&InstallerTaskFail::StepFail);
157 JobWidgetInstall::JobWidgetInstall(
158 std::string const &widgetPath,
159 const WidgetInstallationStruct &
162 JobContextBase<WidgetInstallationStruct>(installerStruct),
163 m_exceptionCaught(Jobs::Exceptions::Success)
165 m_installerContext.mode = m_jobStruct.m_installMode;
166 ConfigureResult result = PrePareInstallation(widgetPath);
168 if (result == ConfigureResult::Ok) {
169 LogInfo("Configure installation succeeded");
170 m_installerContext.job->SetProgressFlag(true);
172 AddTask(new TaskRecovery(m_installerContext));
174 // Create installation tasks
175 if (m_installerContext.widgetConfig.packagingType !=
176 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
177 m_installerContext.widgetConfig.packagingType !=
178 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
181 AddTask(new TaskUnzip(m_installerContext));
184 AddTask(new TaskWidgetConfig(m_installerContext));
185 if (m_installerContext.widgetConfig.packagingType ==
186 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
188 AddTask(new TaskPrepareFiles(m_installerContext));
190 AddTask(new TaskCertify(m_installerContext));
191 if (m_needEncryption) {
192 AddTask(new TaskEncryptResource(m_installerContext));
195 AddTask(new TaskFileManipulation(m_installerContext));
197 AddTask(new TaskManifestFile(m_installerContext));
198 if (m_installerContext.widgetConfig.packagingType ==
199 PKG_TYPE_HYBRID_WEB_APP)
201 AddTask(new TaskInstallOspsvc(m_installerContext));
203 AddTask(new TaskCertificates(m_installerContext));
204 AddTask(new TaskDatabase(m_installerContext));
205 AddTask(new TaskAceCheck(m_installerContext));
206 AddTask(new TaskSmack(m_installerContext));
207 } else if (result == ConfigureResult::Updated) {
208 LogInfo("Configure installation updated");
209 LogInfo("Widget Update");
210 m_installerContext.job->SetProgressFlag(true);
212 if (m_installerContext.mode.command ==
213 InstallMode::Command::REINSTALL)
215 AddTask(new TaskPrepareReinstall(m_installerContext));
218 if (m_installerContext.widgetConfig.packagingType !=
219 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
220 m_installerContext.widgetConfig.packagingType !=
221 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
224 AddTask(new TaskUnzip(m_installerContext));
227 AddTask(new TaskWidgetConfig(m_installerContext));
229 if (m_installerContext.widgetConfig.packagingType ==
230 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
232 AddTask(new TaskPrepareFiles(m_installerContext));
235 AddTask(new TaskCertify(m_installerContext));
236 if (m_needEncryption) {
237 AddTask(new TaskEncryptResource(m_installerContext));
240 if (m_installerContext.widgetConfig.packagingType !=
241 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
243 AddTask(new TaskUpdateFiles(m_installerContext));
244 AddTask(new TaskFileManipulation(m_installerContext));
247 AddTask(new TaskManifestFile(m_installerContext));
248 if (m_installerContext.widgetConfig.packagingType ==
249 PKG_TYPE_HYBRID_WEB_APP)
251 AddTask(new TaskInstallOspsvc(m_installerContext));
253 AddTask(new TaskCertificates(m_installerContext));
254 AddTask(new TaskDatabase(m_installerContext));
255 AddTask(new TaskAceCheck(m_installerContext));
256 //TODO: remove widgetHandle from this task and move before database task
257 // by now widget handle is needed in ace check
258 // Any error in acecheck while update will break widget
259 AddTask(new TaskSmack(m_installerContext));
260 AddTask(new TaskRemoveBackupFiles(m_installerContext));
261 } else if (result == ConfigureResult::Deferred) {
262 // Installation is deferred
263 LogInfo("Configure installation deferred");
265 AddTask(new InstallerTaskFail(result));
266 } else if (result >= ConfigureResult::Failed &&
267 result <= ConfigureResult::Failed_DrmError) {
268 // Installation is not allowed to proceed due to widget update policy
269 LogWarning("Configure installation failed!");
271 AddTask(new InstallerTaskFail(result));
273 Assert(false && "Invalid configure result!");
277 ConfigureResult JobWidgetInstall::PrePareInstallation(
278 const std::string &widgetPath)
280 ConfigureResult result;
281 m_needEncryption = false;
286 if (m_installerContext.mode.extension == InstallMode::ExtensionType::DIR) {
287 std::ostringstream tempPathBuilder;
288 tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath();
289 tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath();
290 tempPathBuilder << "/";
291 tempPathBuilder << widgetPath;
292 tempDir = tempPathBuilder.str();;
295 Jobs::WidgetInstall::createTempPath(
296 m_installerContext.mode.rootPath ==
297 InstallMode::RootPath::RO);
300 m_isDRM = isDRMWidget(widgetPath);
301 if (true == m_isDRM) {
302 LogDebug("decrypt DRM widget");
303 if (DecryptDRMWidget(widgetPath, tempDir)) {
304 LogDebug("Failed decrypt DRM widget");
305 return ConfigureResult::Failed_DrmError;
309 LogDebug("widgetPath:" << widgetPath);
311 m_installerContext.widgetConfig.packagingType =
312 checkPackageType(widgetPath, tempDir);
313 ConfigParserData configData = getWidgetDataFromXML(
316 m_installerContext.widgetConfig.packagingType,
318 m_installerContext.mode.command == InstallMode::Command::REINSTALL);
319 LogDebug("widget packaging type : " <<
320 m_installerContext.widgetConfig.packagingType.pkgType);
322 setTizenId(configData);
323 setApplicationType(configData);
324 m_needEncryption = detectResourceEncryption(configData);
325 setInstallLocationType(configData);
327 // Configure installation
328 result = ConfigureInstallation(widgetPath, configData, tempDir);
330 Catch(Exceptions::ExtractFileFailed)
332 LogError("Failed to create temporary path for widget");
333 result = ConfigureResult::Failed_InvalidConfig;
339 void JobWidgetInstall::setTizenId(
340 const WrtDB::ConfigParserData &configInfo)
342 bool shouldMakeAppid = false;
343 using namespace PackageManager;
344 if (!!configInfo.tizenAppId) {
345 LogDebug("Setting tizenAppId provided in config.xml: " <<
346 configInfo.tizenAppId);
348 m_installerContext.widgetConfig.tzAppid = *configInfo.tizenAppId;
350 if (!!configInfo.tizenPkgId) {
351 LogDebug("Setting tizenPkgId provided in config.xml: " <<
352 configInfo.tizenPkgId);
354 m_installerContext.widgetConfig.tzPkgid = *configInfo.tizenPkgId;
356 DPL::String appid = *configInfo.tizenAppId;
357 if (appid.length() > PACKAGE_ID_LENGTH) {
358 m_installerContext.widgetConfig.tzPkgid =
359 appid.substr(0, PACKAGE_ID_LENGTH);
361 //old version appid only has 10byte random character is able to install for a while.
362 //this case appid equal pkgid.
363 m_installerContext.widgetConfig.tzPkgid =
364 *configInfo.tizenAppId;
365 shouldMakeAppid = true;
369 shouldMakeAppid = true;
370 TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId();
371 LogDebug("Checking if pkg id is unique");
373 if (!validateTizenPackageID(pkgId)) {
374 //path exist, chose another one
375 pkgId = WidgetDAOReadOnly::generatePkgId();
380 m_installerContext.widgetConfig.tzPkgid = pkgId;
381 LogInfo("tizen_id name was generated by WRT: " <<
382 m_installerContext.widgetConfig.tzPkgid);
385 if (shouldMakeAppid == true) {
386 DPL::OptionalString name;
387 DPL::OptionalString defaultLocale = configInfo.defaultlocale;
389 FOREACH(localizedData, configInfo.localizedDataSet)
391 Locale i = localizedData->first;
392 if (!!defaultLocale) {
393 if (defaultLocale == i) {
394 name = localizedData->second.name;
398 name = localizedData->second.name;
403 if (regcomp(®x, REG_NAME_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
404 LogDebug("Regcomp failed");
407 LogDebug("Name : " << name);
408 if (!name || (regexec(®x, DPL::ToUTF8String(*name).c_str(),
409 static_cast<size_t>(0), NULL, 0) != REG_NOERROR))
411 // TODO : generate name move to wrt-commons
412 std::string allowedString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
413 std::ostringstream genName;
415 gettimeofday(&tv, NULL);
416 unsigned int seed = time(NULL) + tv.tv_usec;
418 genName << "_" << allowedString[rand_r(&seed) % allowedString.length()];
419 name = DPL::FromUTF8String(genName.str());
420 LogDebug("name was generated by WRT");
423 LogDebug("Name : " << name);
424 std::ostringstream genid;
425 genid << m_installerContext.widgetConfig.tzPkgid << "." << name;
426 LogDebug("tizen appid was generated by WRT : " << genid.str());
428 DPL::OptionalString appid = DPL::FromUTF8String(genid.str());
429 NormalizeAndTrimSpaceString(appid);
430 m_installerContext.widgetConfig.tzAppid = *appid;
433 // send start signal of pkgmgr
434 getInstallerStruct().pkgmgrInterface->setPkgname(DPL::ToUTF8String(
438 LogInfo("Tizen App Id : " << m_installerContext.widgetConfig.tzAppid);
439 LogInfo("Tizen Pkg Id : " << m_installerContext.widgetConfig.tzPkgid);
440 LogInfo("W3C Widget GUID : " << m_installerContext.widgetConfig.guid);
443 void JobWidgetInstall::configureWidgetLocation(const std::string & widgetPath,
444 const std::string& tempPath)
446 m_installerContext.locations =
447 WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
449 widgetPath, tempPath,
450 m_installerContext.widgetConfig.packagingType,
451 m_installerContext.mode.rootPath ==
452 InstallMode::RootPath::RO);
453 m_installerContext.locations->registerAppid(
454 DPL::ToUTF8String(m_installerContext.widgetConfig.tzAppid));
456 LogInfo("widgetSource " << widgetPath);
459 ConfigureResult JobWidgetInstall::ConfigureInstallation(
460 const std::string &widgetSource,
461 const WrtDB::ConfigParserData &configData,
462 const std::string &tempPath)
464 ConfigureResult result = ConfigureResult::Failed;
465 WidgetUpdateInfo update;
467 // checking installed web application
469 // checking existing application is installed
470 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
471 // no excpetion means, it isn't update mode
472 getInstallerStruct().pkgmgrInterface->sendSignal(
474 PKGMGR_START_UPDATE);
476 update = detectWidgetUpdate(configData,
477 m_installerContext.widgetConfig.tzAppid);
478 result = checkWidgetUpdate(update);
479 if (result != ConfigureResult::Updated) {
480 // Already installed TizenAppId. return failed
481 return ConfigureResult::Failed_AlreadyInstalled;
483 m_installerContext.isUpdateMode = true;
485 Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
486 result = ConfigureResult::Ok;
487 getInstallerStruct().pkgmgrInterface->sendSignal(
489 PKGMGR_START_INSTALL);
490 m_installerContext.isUpdateMode = false;
492 if (!validateTizenApplicationID(
493 m_installerContext.widgetConfig.tzAppid))
495 LogError("tizen application ID is already used");
496 return ConfigureResult::Failed_InvalidConfig;
498 if (!validateTizenPackageID(m_installerContext.widgetConfig.tzPkgid)) {
499 LogError("tizen package ID is already used");
500 return ConfigureResult::Failed_AlreadyInstalled;
504 configureWidgetLocation(widgetSource, tempPath);
506 // Init installer context
507 m_installerContext.installStep = InstallerContext::INSTALL_START;
508 m_installerContext.job = this;
509 m_installerContext.widgetConfig.shareHref = std::string();
514 bool JobWidgetInstall::validateTizenApplicationID(
515 const WrtDB::TizenAppId &tizenAppId)
517 LogInfo("tizen application ID = [" << tizenAppId << "]");
520 if (regcomp(®, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
521 LogDebug("Regcomp failed");
524 if (regexec(®, DPL::ToUTF8String(tizenAppId).c_str(), 0, NULL, 0)
534 bool JobWidgetInstall::validateTizenPackageID(
535 const WrtDB::TizenPkgId &tizenPkgId)
537 std::string pkgId = DPL::ToUTF8String(tizenPkgId);
539 std::string installPath =
540 std::string(GlobalConfig::GetUserInstalledWidgetPath()) +
542 std::string preinstallPath =
543 std::string(GlobalConfig::GetUserPreloadedWidgetPath()) +
547 if ((stat(installPath.c_str(), &dirStat) == 0) ||
548 (stat(preinstallPath.c_str(), &dirStat) == 0))
555 ConfigureResult JobWidgetInstall::checkWidgetUpdate(
556 const WidgetUpdateInfo &update)
558 if (update.existingVersion.IsNull() || update.incomingVersion.IsNull()) {
559 return ConfigureResult::Failed;
562 LogInfo("existing version = '" << update.existingVersion);
563 LogInfo("incoming version = '" << update.incomingVersion);
564 LogInfo("Tizen AppID = " << update.tzAppId);
566 // Check running state
567 bool isRunning = false;
569 app_manager_is_running(DPL::ToUTF8String(update.tzAppId).c_str(),
571 if (APP_MANAGER_ERROR_NONE != ret) {
572 LogError("Fail to get running state");
573 return ConfigureResult::Failed_WidgetRunning;
576 if (true == isRunning) {
577 // get app_context for running application
578 // app_context must be released with app_context_destroy
579 app_context_h appCtx = NULL;
581 app_manager_get_app_context(
582 DPL::ToUTF8String(update.tzAppId).c_str(),
584 if (APP_MANAGER_ERROR_NONE != ret) {
585 LogError("Fail to get app_context");
586 return ConfigureResult::Failed_WidgetRunning;
589 // terminate app_context_h
590 ret = app_manager_terminate_app(appCtx);
591 if (APP_MANAGER_ERROR_NONE != ret) {
592 LogError("Fail to terminate running application");
593 app_context_destroy(appCtx);
594 return ConfigureResult::Failed_WidgetRunning;
596 app_context_destroy(appCtx);
597 // app_manager_terminate_app isn't sync API
598 // wait until application isn't running (50ms * 100)
599 bool isStillRunning = true;
600 int checkingloop = 100;
601 struct timespec duration = { 0, 50 * 1000 * 1000 };
602 while (--checkingloop >= 0) {
603 nanosleep(&duration, NULL);
605 app_manager_is_running(
606 DPL::ToUTF8String(update.tzAppId).c_str(),
608 if (APP_MANAGER_ERROR_NONE != ret) {
609 LogError("Fail to get running state");
610 return ConfigureResult::Failed_WidgetRunning;
612 if (!isStillRunning) {
616 if (isStillRunning) {
617 LogError("Fail to terminate running application");
618 return ConfigureResult::Failed_WidgetRunning;
620 LogInfo("terminate application");
624 m_installerContext.widgetConfig.tzAppid = update.tzAppId;
626 if (!!update.existingVersion ||
627 m_installerContext.mode.extension ==
628 InstallMode::ExtensionType::DIR) {
629 return ConfigureResult::Updated;
632 return ConfigureResult::Failed;
635 ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
636 const std::string &widgetSource,
637 const std::string &tempPath,
638 WrtDB::PackagingType pkgType,
644 ConfigParserData configInfo;
648 if (pkgType == PKG_TYPE_HOSTED_WEB_APP) {
649 parser.Parse(widgetSource,
651 new RootParser<WidgetParser>(configInfo,
652 DPL::FromUTF32String(
654 } else if (pkgType == PKG_TYPE_DIRECTORY_WEB_APP) {
655 std::string configPath;
656 configPath = tempPath;
658 configPath += WITH_OSP_XML;
661 // checking RDS data directory
662 if (access(configPath.c_str(), F_OK) != 0) {
663 std::string tzAppId =
664 widgetSource.substr(widgetSource.find_last_of("/")+1);
665 WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTzAppId(DPL::FromUTF8String(tzAppId)));
666 configPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath());
668 configPath += WITH_OSP_XML;
671 parser.Parse(configPath,
673 new RootParser<WidgetParser>(
675 DPL::FromUTF32String(L"widget"))));
678 std::unique_ptr<DPL::ZipInput> zipFile(
679 new DPL::ZipInput(widgetSource));
681 std::unique_ptr<DPL::ZipInput::File> configFile;
683 // Open config.xml file
684 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
685 configFile.reset(zipFile->OpenFile(WITH_OSP_XML));
687 configFile.reset(zipFile->OpenFile(CONFIG_XML));
691 DPL::BinaryQueue buffer;
692 DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
693 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
694 DPL::Copy(&inputAdapter, &outputAdapter);
695 parser.Parse(&buffer,
697 new RootParser<WidgetParser>(configInfo,
703 std::string configFile;
704 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
705 configFile = tempPath + "/" + WITH_OSP_XML;
707 configFile = tempPath + "/" + CONFIG_XML;
710 parser.Parse(configFile,
712 new RootParser<WidgetParser>(configInfo,
719 Catch(DPL::ZipInput::Exception::OpenFailed)
721 LogError("Failed to open widget package");
722 return ConfigParserData();
724 Catch(DPL::ZipInput::Exception::OpenFileFailed)
726 LogError("Failed to open config.xml file");
727 return ConfigParserData();
729 Catch(DPL::CopyFailed)
731 LogError("Failed to extract config.xml file");
732 return ConfigParserData();
734 Catch(DPL::FileInput::Exception::OpenFailed)
736 LogError("Failed to open config.xml file");
737 return ConfigParserData();
739 Catch(ElementParser::Exception::ParseError)
741 LogError("Failed to parse config.xml file");
742 return ConfigParserData();
744 Catch(DPL::ZipInput::Exception::SeekFileFailed)
746 LogError("Failed to seek widget archive - corrupted package?");
747 return ConfigParserData();
752 WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
753 const ConfigParserData &configInfo,
754 const WrtDB::TizenAppId &tizenId)
756 LogInfo("Checking up widget package for config.xml...");
757 OptionalWidgetVersion incomingVersion;
759 if (!configInfo.version.IsNull()) {
761 DPL::Optional<WidgetVersion>(
762 WidgetVersion(*configInfo.version));
765 WidgetDAOReadOnly dao(tizenId);
767 OptionalWidgetVersion optVersion;
768 DPL::OptionalString version = dao.getVersion();
769 if (!version.IsNull()) {
770 optVersion = OptionalWidgetVersion(WidgetVersion(*version));
773 return WidgetUpdateInfo(
779 void JobWidgetInstall::SendProgress()
781 using namespace PackageManager;
782 if (GetProgressFlag() != false) {
783 if (getInstallerStruct().progressCallback != NULL) {
784 // send progress signal of pkgmgr
785 std::ostringstream percent;
786 percent << static_cast<int>(GetProgressPercent());
787 getInstallerStruct().pkgmgrInterface->sendSignal(
791 LogDebug("Call widget install progressCallbak");
792 getInstallerStruct().progressCallback(
793 getInstallerStruct().userParam,
794 GetProgressPercent(),
795 GetProgressDescription());
800 void JobWidgetInstall::SendProgressIconPath(const std::string &path)
802 using namespace PackageManager;
803 if (GetProgressFlag() != false) {
804 if (getInstallerStruct().progressCallback != NULL) {
805 // send progress signal of pkgmgr
806 getInstallerStruct().pkgmgrInterface->sendSignal(
813 void JobWidgetInstall::SendFinishedSuccess()
815 using namespace PackageManager;
816 // TODO : sync should move to separate task.
819 if (INSTALL_LOCATION_TYPE_EXTERNAL == m_installerContext.locationType) {
820 if (m_installerContext.isUpdateMode) {
821 WidgetInstallToExtSingleton::Instance().postUpgrade(true);
823 WidgetInstallToExtSingleton::Instance().postInstallation(true);
825 WidgetInstallToExtSingleton::Instance().deinitialize();
828 // remove widget install information file
829 unlink(m_installerContext.installInfo.c_str());
832 JobWidgetInstall::displayWidgetInfo();
834 TizenAppId& tizenId = m_installerContext.widgetConfig.tzAppid;
836 // send signal of pkgmgr
837 getInstallerStruct().pkgmgrInterface->sendSignal(
841 LogDebug("Call widget install successfinishedCallback");
842 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
844 tizenId), Jobs::Exceptions::Success);
847 void JobWidgetInstall::SendFinishedFailure()
849 using namespace PackageManager;
850 // remove widget install information file
851 unlink(m_installerContext.installInfo.c_str());
853 LogError("Error number: " << m_exceptionCaught);
854 LogError("Message: " << m_exceptionMessage);
855 TizenAppId & tizenId = m_installerContext.widgetConfig.tzAppid;
857 LogDebug("Call widget install failure finishedCallback");
858 std::stringstream errorNum;
859 errorNum << m_exceptionCaught;
861 // send signal of pkgmgr
862 getInstallerStruct().pkgmgrInterface->sendSignal(
866 getInstallerStruct().pkgmgrInterface->sendSignal(
870 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
872 tizenId), m_exceptionCaught);
875 void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
877 m_exceptionCaught = static_cast<Jobs::Exceptions::Type>(e.getParam());
878 m_exceptionMessage = e.GetMessage();
881 void JobWidgetInstall::displayWidgetInfo()
883 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
885 std::ostringstream out;
886 WidgetLocalizedInfo localizedInfo =
887 W3CFileLocalization::getLocalizedInfo(dao.getTzAppId());
890 "===================================== INSTALLED WIDGET INFO =========" \
891 "============================";
892 out << std::endl << "Name: " << localizedInfo.name;
893 out << std::endl << "AppId: " << dao.getTzAppId();
894 WidgetSize size = dao.getPreferredSize();
895 out << std::endl << "Width: " << size.width;
896 out << std::endl << "Height: " << size.height;
897 out << std::endl << "Start File: " <<
898 W3CFileLocalization::getStartFile(dao.getTzAppId());
899 out << std::endl << "Version: " << dao.getVersion();
900 out << std::endl << "Licence: " <<
901 localizedInfo.license;
902 out << std::endl << "Licence Href: " <<
903 localizedInfo.licenseHref;
904 out << std::endl << "Description: " <<
905 localizedInfo.description;
906 out << std::endl << "Widget Id: " << dao.getGUID();
907 out << std::endl << "Widget recognized: " << dao.isRecognized();
908 out << std::endl << "Widget distributor signed: " <<
909 dao.isDistributorSigned();
910 out << std::endl << "Widget trusted: " << dao.isTrusted();
912 OptionalWidgetIcon icon = W3CFileLocalization::getIcon(dao.getTzAppId());
913 DPL::OptionalString iconSrc =
914 !!icon ? icon->src : DPL::OptionalString::Null;
915 out << std::endl << "Icon: " << iconSrc;
917 out << std::endl << "Preferences:";
919 PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList();
922 out << std::endl << " Key: " <<
924 out << std::endl << " Readonly: " <<
929 out << std::endl << "Features:";
931 WidgetFeatureSet list = dao.getFeaturesList();
934 out << std::endl << " Name: " << it->name;
943 WrtDB::PackagingType JobWidgetInstall::checkPackageType(
944 const std::string &widgetSource,
945 const std::string &tempPath)
947 // Check installation type (direcotory/ or config.xml or widget.wgt)
948 if (m_installerContext.mode.extension == InstallMode::ExtensionType::DIR) {
949 LogDebug("Install directly from directory");
950 return PKG_TYPE_DIRECTORY_WEB_APP;
952 if (hasExtension(widgetSource, XML_EXTENSION)) {
953 LogInfo("Hosted app installation");
954 return PKG_TYPE_HOSTED_WEB_APP;
958 std::string configFile = tempPath + "/" + CONFIG_XML;
959 if (WrtUtilFileExists(configFile)) {
960 return PKG_TYPE_NOMAL_WEB_APP;
963 configFile = tempPath + "/" + WITH_OSP_XML;
964 if (WrtUtilFileExists(configFile)) {
965 return PKG_TYPE_HYBRID_WEB_APP;
968 std::unique_ptr<DPL::ZipInput> zipFile;
973 zipFile.reset(new DPL::ZipInput(widgetSource));
975 Catch(DPL::ZipInput::Exception::OpenFailed)
977 LogDebug("Failed to open widget package");
978 return PKG_TYPE_UNKNOWN;
980 Catch(DPL::ZipInput::Exception::SeekFileFailed)
982 LogError("Failed to seek widget package file");
983 return PKG_TYPE_UNKNOWN;
988 // Open config.xml file in package root
989 std::unique_ptr<DPL::ZipInput::File> configFile(
990 zipFile->OpenFile(CONFIG_XML));
991 return PKG_TYPE_NOMAL_WEB_APP;
993 Catch(DPL::ZipInput::Exception::OpenFileFailed)
995 LogDebug("Could not find config.xml");
1000 // Open config.xml file in package root
1001 std::unique_ptr<DPL::ZipInput::File> configFile(
1002 zipFile->OpenFile(WITH_OSP_XML));
1004 return PKG_TYPE_HYBRID_WEB_APP;
1006 Catch(DPL::ZipInput::Exception::OpenFileFailed)
1008 LogDebug("Could not find wgt/config.xml");
1009 return PKG_TYPE_UNKNOWN;
1013 return PKG_TYPE_UNKNOWN;
1016 void JobWidgetInstall::setApplicationType(
1017 const WrtDB::ConfigParserData &configInfo)
1019 FOREACH(iterator, configInfo.nameSpaces) {
1020 LogInfo("namespace = [" << *iterator << "]");
1021 AppType currentAppType = APP_TYPE_UNKNOWN;
1023 if (*iterator == ConfigurationNamespace::W3CWidgetNamespaceName) {
1027 ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement ||
1029 ConfigurationNamespace::WacWidgetNamespaceName)
1031 currentAppType = APP_TYPE_WAC20;
1032 } else if (*iterator ==
1033 ConfigurationNamespace::TizenWebAppNamespaceName)
1035 currentAppType = APP_TYPE_TIZENWEBAPP;
1038 if (m_installerContext.widgetConfig.webAppType ==
1041 m_installerContext.widgetConfig.webAppType = currentAppType;
1042 } else if (m_installerContext.widgetConfig.webAppType ==
1047 ThrowMsg(Exceptions::WidgetConfigFileInvalid,
1048 "Config.xml has more than one namespace");
1052 // If there is no define, type set to WAC 2.0
1053 if (m_installerContext.widgetConfig.webAppType == APP_TYPE_UNKNOWN) {
1054 m_installerContext.widgetConfig.webAppType = APP_TYPE_WAC20;
1057 LogInfo("type = [" <<
1058 m_installerContext.widgetConfig.webAppType.getApptypeToString() <<
1062 bool JobWidgetInstall::detectResourceEncryption(
1063 const WrtDB::ConfigParserData &configData)
1065 FOREACH(it, configData.settingsList)
1067 if (it->m_name == SETTING_VALUE_ENCRYPTION &&
1068 it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE)
1070 LogDebug("resource need encryption");
1077 void JobWidgetInstall::setInstallLocationType(
1078 const WrtDB::ConfigParserData & configData)
1080 m_installerContext.locationType = INSTALL_LOCATION_TYPE_NOMAL;
1081 if (m_installerContext.mode.installTime != InstallMode::InstallTime::PRELOAD) {
1082 FOREACH(it, configData.settingsList) {
1083 if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME &&
1085 SETTING_VALUE_INSTALLTOEXT_PREPER_EXT)
1087 LogDebug("This widget will be installed to sd card");
1088 m_installerContext.locationType =
1089 INSTALL_LOCATION_TYPE_EXTERNAL;
1095 bool JobWidgetInstall::isDRMWidget(std::string /*widgetPath*/)
1101 bool JobWidgetInstall::DecryptDRMWidget(std::string /*widgetPath*/,
1102 std::string /*destPath*/)
1107 } //namespace WidgetInstall