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_plugins_copy.h>
73 #include <widget_install/task_prepare_reinstall.h>
75 #include <widget_install/widget_install_errors.h>
76 #include <widget_install/widget_install_context.h>
77 #include <widget_install_to_external.h>
79 using namespace WrtDB;
80 using namespace Jobs::Exceptions;
82 namespace // anonymous
84 const char * const CONFIG_XML = "config.xml";
85 const char * const WITH_OSP_XML = "res/wgt/config.xml";
87 //allowed: a-z, A-Z, 0-9
88 const char* REG_TIZENID_PATTERN = "^[a-zA-Z0-9]{10}.{1,}$";
89 const char* REG_NAME_PATTERN = "^[a-zA-Z0-9._-]{1,}$";
90 const size_t PACKAGE_ID_LENGTH = 10;
92 static const DPL::String SETTING_VALUE_ENCRYPTION = L"encryption";
93 static const DPL::String SETTING_VALUE_ENCRYPTION_ENABLE = L"enable";
94 const DPL::String SETTING_VALUE_INSTALLTOEXT_NAME =
96 const DPL::String SETTING_VALUE_INSTALLTOEXT_PREPER_EXT =
99 const std::string XML_EXTENSION = ".xml";
101 bool hasExtension(const std::string& filename, const std::string& extension)
103 LogDebug("Looking for extension " << extension << " in: " << filename);
104 size_t fileLen = filename.length();
105 size_t extLen = extension.length();
106 if (fileLen < extLen) {
107 LogError("Filename " << filename << " is shorter than extension "
111 return (0 == filename.compare(fileLen - extLen, extLen, extension));
113 } // namespace anonymous
116 namespace WidgetInstall {
117 class InstallerTaskFail :
118 public DPL::TaskDecl<InstallerTaskFail>
121 ConfigureResult m_result;
125 if (m_result == ConfigureResult::Deferred) {
126 ThrowMsg(Jobs::WidgetInstall::Exceptions::Deferred,
127 "widget installation or update deferred!");
128 } else if (m_result == ConfigureResult::Failed_InvalidConfig) {
129 ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid,
131 } else if (m_result == ConfigureResult::Failed_LowerVersion) {
132 ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageLowerVersion,
133 "package version is lower than installed version");
134 } else if (m_result == ConfigureResult::Failed_AlreadyInstalled) {
135 ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageAlreadyInstalled,
136 "package is already installed");
137 } else if (m_result == ConfigureResult::Failed_WidgetRunning) {
138 ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError,
139 "widget is running");
140 } else if (m_result == ConfigureResult::Failed_DrmError) {
141 ThrowMsg(Jobs::WidgetInstall::Exceptions::DRMFailed,
144 ThrowMsg(Jobs::WidgetInstall::Exceptions::NotAllowed,
145 "widget installation or update not allowed!");
150 InstallerTaskFail(ConfigureResult result) :
151 DPL::TaskDecl<InstallerTaskFail>(this),
154 AddStep(&InstallerTaskFail::StepFail);
158 JobWidgetInstall::JobWidgetInstall(
159 std::string const &widgetPath,
160 const WidgetInstallationStruct &
163 JobContextBase<WidgetInstallationStruct>(installerStruct),
164 m_exceptionCaught(Jobs::Exceptions::Success)
166 m_installerContext.m_quiet = m_jobStruct.m_quiet;
168 ConfigureResult result = PrePareInstallation(widgetPath);
170 if (result == ConfigureResult::Ok) {
171 LogInfo("Configure installation succeeded");
172 m_installerContext.job->SetProgressFlag(true);
174 AddTask(new TaskRecovery(m_installerContext));
176 // Create installation tasks
177 if (m_installerContext.widgetConfig.packagingType !=
178 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
179 m_installerContext.widgetConfig.packagingType !=
180 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
183 AddTask(new TaskUnzip(m_installerContext));
186 AddTask(new TaskWidgetConfig(m_installerContext));
187 if (m_installerContext.widgetConfig.packagingType ==
188 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
190 AddTask(new TaskPrepareFiles(m_installerContext));
192 AddTask(new TaskCertify(m_installerContext));
193 if (m_needEncryption) {
194 AddTask(new TaskEncryptResource(m_installerContext));
197 AddTask(new TaskFileManipulation(m_installerContext));
198 // TODO: Update progress information for this task
200 //This is sort of quick solution, because ACE verdicts are based upon
201 //data from DAO (DB). So AceCheck for now has to be AFTER DbUpdate
203 AddTask(new TaskSmack(m_installerContext));
205 AddTask(new TaskManifestFile(m_installerContext));
206 if (m_installerContext.widgetConfig.packagingType ==
207 PKG_TYPE_HYBRID_WEB_APP)
209 AddTask(new TaskInstallOspsvc(m_installerContext));
211 AddTask(new TaskCertificates(m_installerContext));
212 AddTask(new TaskPluginsCopy(m_installerContext));
213 AddTask(new TaskDatabase(m_installerContext));
214 AddTask(new TaskAceCheck(m_installerContext));
215 } else if (result == ConfigureResult::Updated) {
216 LogInfo("Configure installation updated");
217 LogInfo("Widget Update");
218 m_installerContext.job->SetProgressFlag(true);
220 if (m_jobStruct.m_installMode ==
221 InstallMode::REINSTALL_MODE_DIRECTORY)
223 AddTask(new TaskPrepareReinstall(m_installerContext));
226 if (m_installerContext.widgetConfig.packagingType !=
227 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
228 m_installerContext.widgetConfig.packagingType !=
229 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
232 AddTask(new TaskUnzip(m_installerContext));
235 AddTask(new TaskWidgetConfig(m_installerContext));
237 if (m_installerContext.widgetConfig.packagingType ==
238 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
240 AddTask(new TaskPrepareFiles(m_installerContext));
243 AddTask(new TaskCertify(m_installerContext));
244 if (m_needEncryption) {
245 AddTask(new TaskEncryptResource(m_installerContext));
248 if (m_installerContext.widgetConfig.packagingType !=
249 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
251 AddTask(new TaskUpdateFiles(m_installerContext));
254 /* TODO : To backup file, save md5 values */
255 AddTask(new TaskSmack(m_installerContext));
257 AddTask(new TaskManifestFile(m_installerContext));
258 if (m_installerContext.widgetConfig.packagingType ==
259 PKG_TYPE_HYBRID_WEB_APP)
261 AddTask(new TaskInstallOspsvc(m_installerContext));
263 if (m_installerContext.widgetConfig.packagingType !=
264 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
266 AddTask(new TaskRemoveBackupFiles(m_installerContext));
268 AddTask(new TaskPluginsCopy(m_installerContext));
269 AddTask(new TaskDatabase(m_installerContext));
270 AddTask(new TaskAceCheck(m_installerContext));
271 //TODO: remove widgetHandle from this task and move before database task
272 // by now widget handle is needed in ace check
273 // Any error in acecheck while update will break widget
274 } else if (result == ConfigureResult::Deferred) {
275 // Installation is deferred
276 LogInfo("Configure installation deferred");
278 AddTask(new InstallerTaskFail(result));
279 } else if (result >= ConfigureResult::Failed &&
280 result <= ConfigureResult::Failed_DrmError) {
281 // Installation is not allowed to proceed due to widget update policy
282 LogWarning("Configure installation failed!");
284 AddTask(new InstallerTaskFail(result));
286 Assert(false && "Invalid configure result!");
290 ConfigureResult JobWidgetInstall::PrePareInstallation(
291 const std::string &widgetPath)
293 ConfigureResult result;
294 m_needEncryption = false;
299 if (m_jobStruct.m_installMode ==
300 InstallMode::REINSTALL_MODE_DIRECTORY)
302 std::ostringstream tempPathBuilder;
303 tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath();
304 tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath();
305 tempPathBuilder << "/";
306 tempPathBuilder << widgetPath;
307 tempDir = tempPathBuilder.str();;
310 Jobs::WidgetInstall::createTempPath(
311 m_jobStruct.m_installMode ==
312 InstallMode::INSTALL_MODE_PRELOAD);
315 m_isDRM = isDRMWidget(widgetPath);
316 if (true == m_isDRM) {
317 LogDebug("decrypt DRM widget");
318 if (DecryptDRMWidget(widgetPath, tempDir)) {
319 LogDebug("Failed decrypt DRM widget");
320 return ConfigureResult::Failed_DrmError;
324 LogDebug("widgetPath:" << widgetPath);
326 m_installerContext.widgetConfig.packagingType =
327 checkPackageType(widgetPath, tempDir);
328 ConfigParserData configData = getWidgetDataFromXML(
331 m_installerContext.widgetConfig.packagingType,
333 m_jobStruct.m_installMode ==
334 InstallMode::REINSTALL_MODE_DIRECTORY);
335 LogDebug("widget packaging type : " <<
336 m_installerContext.widgetConfig.packagingType.pkgType);
338 setTizenId(configData);
339 setApplicationType(configData);
340 m_needEncryption = detectResourceEncryption(configData);
341 setInstallLocationType(configData);
343 // Configure installation
344 result = ConfigureInstallation(widgetPath, configData, tempDir);
346 Catch(Exceptions::ExtractFileFailed)
348 LogError("Failed to create temporary path for widget");
349 result = ConfigureResult::Failed_InvalidConfig;
355 void JobWidgetInstall::setTizenId(
356 const WrtDB::ConfigParserData &configInfo)
358 bool shouldMakeAppid = false;
359 using namespace PackageManager;
360 if (!!configInfo.tizenAppId) {
361 LogDebug("Setting tizenAppId provided in config.xml: " <<
362 configInfo.tizenAppId);
364 m_installerContext.widgetConfig.tzAppid = *configInfo.tizenAppId;
366 if (!!configInfo.tizenPkgId) {
367 LogDebug("Setting tizenPkgId provided in config.xml: " <<
368 configInfo.tizenPkgId);
370 m_installerContext.widgetConfig.tzPkgid = *configInfo.tizenPkgId;
372 DPL::String appid = *configInfo.tizenAppId;
373 if (appid.length() > PACKAGE_ID_LENGTH) {
374 m_installerContext.widgetConfig.tzPkgid =
375 appid.substr(0, PACKAGE_ID_LENGTH);
377 //old version appid only has 10byte random character is able to install for a while.
378 //this case appid equal pkgid.
379 m_installerContext.widgetConfig.tzPkgid =
380 *configInfo.tizenAppId;
381 shouldMakeAppid = true;
385 shouldMakeAppid = true;
386 TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId();
387 LogDebug("Checking if pkg id is unique");
389 if (!validateTizenPackageID(pkgId)) {
390 //path exist, chose another one
391 pkgId = WidgetDAOReadOnly::generatePkgId();
396 m_installerContext.widgetConfig.tzPkgid = pkgId;
397 LogInfo("tizen_id name was generated by WRT: " <<
398 m_installerContext.widgetConfig.tzPkgid);
401 if (shouldMakeAppid == true) {
402 DPL::OptionalString name;
403 DPL::OptionalString defaultLocale = configInfo.defaultlocale;
405 FOREACH(localizedData, configInfo.localizedDataSet)
407 Locale i = localizedData->first;
408 if (!!defaultLocale) {
409 if (defaultLocale == i) {
410 name = localizedData->second.name;
414 name = localizedData->second.name;
419 if (regcomp(®x, REG_NAME_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
420 LogDebug("Regcomp failed");
423 LogDebug("Name : " << name);
424 if (!name || (regexec(®x, DPL::ToUTF8String(*name).c_str(),
425 static_cast<size_t>(0), NULL, 0) != REG_NOERROR))
427 // TODO : generate name move to wrt-commons
428 std::string allowedString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
429 std::ostringstream genName;
431 gettimeofday(&tv, NULL);
432 unsigned int seed = time(NULL) + tv.tv_usec;
434 genName << "_" << allowedString[rand_r(&seed) % allowedString.length()];
435 name = DPL::FromUTF8String(genName.str());
436 LogDebug("name was generated by WRT");
439 LogDebug("Name : " << name);
440 std::ostringstream genid;
441 genid << m_installerContext.widgetConfig.tzPkgid << "." << name;
442 LogDebug("tizen appid was generated by WRT : " << genid.str());
444 DPL::OptionalString appid = DPL::FromUTF8String(genid.str());
445 NormalizeAndTrimSpaceString(appid);
446 m_installerContext.widgetConfig.tzAppid = *appid;
449 // send start signal of pkgmgr
450 getInstallerStruct().pkgmgrInterface->setPkgname(DPL::ToUTF8String(
454 LogInfo("Tizen App Id : " << m_installerContext.widgetConfig.tzAppid);
455 LogInfo("Tizen Pkg Id : " << m_installerContext.widgetConfig.tzPkgid);
456 LogInfo("W3C Widget GUID : " << m_installerContext.widgetConfig.guid);
459 void JobWidgetInstall::configureWidgetLocation(const std::string & widgetPath,
460 const std::string& tempPath)
462 if (m_jobStruct.m_installMode ==
463 InstallMode::REINSTALL_MODE_DIRECTORY)
465 // replace widget path to installed path
466 m_installerContext.locations =
467 WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
469 widgetPath, tempPath,
470 m_installerContext.widgetConfig.packagingType,
471 m_installerContext.locationType);
473 m_installerContext.locations =
474 WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
476 widgetPath, tempPath,
477 m_installerContext.widgetConfig.packagingType,
478 m_installerContext.locationType);
480 m_installerContext.locations->registerAppid(
481 DPL::ToUTF8String(m_installerContext.widgetConfig.tzAppid));
483 LogInfo("widgetSource " << widgetPath);
486 ConfigureResult JobWidgetInstall::ConfigureInstallation(
487 const std::string &widgetSource,
488 const WrtDB::ConfigParserData &configData,
489 const std::string &tempPath)
491 ConfigureResult result = ConfigureResult::Failed;
492 WidgetUpdateInfo update;
494 // checking installed web application
496 // checking existing application is installed
497 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
498 // no excpetion means, it isn't update mode
499 getInstallerStruct().pkgmgrInterface->sendSignal(
501 PKGMGR_START_UPDATE);
503 update = detectWidgetUpdate(configData,
504 m_installerContext.widgetConfig.tzAppid);
505 result = checkWidgetUpdate(update);
506 if (result != ConfigureResult::Updated) {
507 // Already installed TizenAppId. return failed
508 return ConfigureResult::Failed_AlreadyInstalled;
510 m_installerContext.isUpdateMode = true;
512 Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
513 result = ConfigureResult::Ok;
514 getInstallerStruct().pkgmgrInterface->sendSignal(
516 PKGMGR_START_INSTALL);
517 m_installerContext.isUpdateMode = false;
519 if (!validateTizenApplicationID(
520 m_installerContext.widgetConfig.tzAppid))
522 LogError("tizen application ID is already used");
523 return ConfigureResult::Failed_InvalidConfig;
525 if (!validateTizenPackageID(m_installerContext.widgetConfig.tzPkgid)) {
526 LogError("tizen package ID is already used");
527 return ConfigureResult::Failed_AlreadyInstalled;
531 configureWidgetLocation(widgetSource, tempPath);
533 // Init installer context
534 m_installerContext.installStep = InstallerContext::INSTALL_START;
535 m_installerContext.job = this;
536 m_installerContext.widgetConfig.shareHref = std::string();
541 bool JobWidgetInstall::validateTizenApplicationID(
542 const WrtDB::TizenAppId &tizenAppId)
544 LogInfo("tizen application ID = [" << tizenAppId << "]");
547 if (regcomp(®, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
548 LogDebug("Regcomp failed");
551 if (regexec(®, DPL::ToUTF8String(tizenAppId).c_str(), 0, NULL, 0)
561 bool JobWidgetInstall::validateTizenPackageID(
562 const WrtDB::TizenPkgId &tizenPkgId)
564 std::string pkgId = DPL::ToUTF8String(tizenPkgId);
566 std::string installPath =
567 std::string(GlobalConfig::GetUserInstalledWidgetPath()) +
569 std::string preinstallPath =
570 std::string(GlobalConfig::GetUserPreloadedWidgetPath()) +
574 if ((stat(installPath.c_str(), &dirStat) == 0) ||
575 (stat(preinstallPath.c_str(), &dirStat) == 0))
582 ConfigureResult JobWidgetInstall::checkWidgetUpdate(
583 const WidgetUpdateInfo &update)
585 LogInfo("incoming version = '" << update.incomingVersion);
586 LogInfo("Tizen AppID = " << update.tzAppId);
588 if (update.existingVersion.IsNull() || update.incomingVersion.IsNull()) {
589 return ConfigureResult::Failed;
592 // Check running state
593 bool isRunning = false;
595 app_manager_is_running(DPL::ToUTF8String(update.tzAppId).c_str(),
597 if (APP_MANAGER_ERROR_NONE != retval || isRunning) {
598 LogError("Fail to get running state");
599 return ConfigureResult::Failed_WidgetRunning;
602 m_installerContext.widgetConfig.tzAppid = update.tzAppId;
604 if (isUpperVersion(update.existingVersion, update.incomingVersion) ||
605 (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY) ||
606 (m_jobStruct.m_installMode == InstallMode::REINSTALL_MODE_DIRECTORY))
608 LogInfo("Whether widget policy allow proceed ok");
609 return ConfigureResult::Updated;
611 return ConfigureResult::Failed_LowerVersion;
614 return ConfigureResult::Failed;
617 bool JobWidgetInstall::isUpperVersion(
618 const OptionalWidgetVersion &existingVersion,
619 const OptionalWidgetVersion &incomingVersion)
621 LogInfo("Existing version = '" << *existingVersion);
622 LogInfo("Incoming version = '" << *incomingVersion);
624 if (!existingVersion && !incomingVersion) {
626 } else if (!existingVersion && !!incomingVersion) {
628 } else if (!!existingVersion && !incomingVersion) {
631 if (!existingVersion->IsWac() || !incomingVersion->IsWac()) {
634 if (*incomingVersion == *existingVersion) {
636 } else if (*incomingVersion > *existingVersion) {
645 ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
646 const std::string &widgetSource,
647 const std::string &tempPath,
648 WrtDB::PackagingType pkgType,
654 ConfigParserData configInfo;
658 if (pkgType == PKG_TYPE_HOSTED_WEB_APP) {
659 parser.Parse(widgetSource,
661 new RootParser<WidgetParser>(configInfo,
662 DPL::FromUTF32String(
664 } else if (pkgType == PKG_TYPE_DIRECTORY_WEB_APP) {
665 std::string configPath;
666 configPath = tempPath;
668 configPath += WITH_OSP_XML;
671 // checking RDS data directory
672 if (access(configPath.c_str(), F_OK) != 0) {
673 std::string tzAppId =
674 widgetSource.substr(widgetSource.find_last_of("/")+1);
675 WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTzAppId(DPL::FromUTF8String(tzAppId)));
676 configPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath());
678 configPath += WITH_OSP_XML;
681 parser.Parse(configPath,
683 new RootParser<WidgetParser>(
685 DPL::FromUTF32String(L"widget"))));
688 std::unique_ptr<DPL::ZipInput> zipFile(
689 new DPL::ZipInput(widgetSource));
691 std::unique_ptr<DPL::ZipInput::File> configFile;
693 // Open config.xml file
694 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
695 configFile.reset(zipFile->OpenFile(WITH_OSP_XML));
697 configFile.reset(zipFile->OpenFile(CONFIG_XML));
701 DPL::BinaryQueue buffer;
702 DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
703 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
704 DPL::Copy(&inputAdapter, &outputAdapter);
705 parser.Parse(&buffer,
707 new RootParser<WidgetParser>(configInfo,
713 std::string configFile;
714 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
715 configFile = tempPath + "/" + WITH_OSP_XML;
717 configFile = tempPath + "/" + CONFIG_XML;
720 parser.Parse(configFile,
722 new RootParser<WidgetParser>(configInfo,
729 Catch(DPL::ZipInput::Exception::OpenFailed)
731 LogError("Failed to open widget package");
732 return ConfigParserData();
734 Catch(DPL::ZipInput::Exception::OpenFileFailed)
736 LogError("Failed to open config.xml file");
737 return ConfigParserData();
739 Catch(DPL::CopyFailed)
741 LogError("Failed to extract config.xml file");
742 return ConfigParserData();
744 Catch(DPL::FileInput::Exception::OpenFailed)
746 LogError("Failed to open config.xml file");
747 return ConfigParserData();
749 Catch(ElementParser::Exception::ParseError)
751 LogError("Failed to parse config.xml file");
752 return ConfigParserData();
754 Catch(DPL::ZipInput::Exception::SeekFileFailed)
756 LogError("Failed to seek widget archive - corrupted package?");
757 return ConfigParserData();
762 WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
763 const ConfigParserData &configInfo,
764 const WrtDB::TizenAppId &tizenId)
766 LogInfo("Checking up widget package for config.xml...");
767 OptionalWidgetVersion incomingVersion;
769 if (!configInfo.version.IsNull()) {
771 DPL::Optional<WidgetVersion>(
772 WidgetVersion(*configInfo.version));
775 WidgetDAOReadOnly dao(tizenId);
777 OptionalWidgetVersion optVersion;
778 DPL::OptionalString version = dao.getVersion();
779 if (!version.IsNull()) {
780 optVersion = OptionalWidgetVersion(WidgetVersion(*version));
783 return WidgetUpdateInfo(
789 void JobWidgetInstall::SendProgress()
791 using namespace PackageManager;
792 if (GetProgressFlag() != false) {
793 if (getInstallerStruct().progressCallback != NULL) {
794 // send progress signal of pkgmgr
795 std::ostringstream percent;
796 percent << static_cast<int>(GetProgressPercent());
797 getInstallerStruct().pkgmgrInterface->sendSignal(
801 LogDebug("Call widget install progressCallbak");
802 getInstallerStruct().progressCallback(
803 getInstallerStruct().userParam,
804 GetProgressPercent(),
805 GetProgressDescription());
810 void JobWidgetInstall::SendProgressIconPath(const std::string &path)
812 using namespace PackageManager;
813 if (GetProgressFlag() != false) {
814 if (getInstallerStruct().progressCallback != NULL) {
815 // send progress signal of pkgmgr
816 getInstallerStruct().pkgmgrInterface->sendSignal(
823 void JobWidgetInstall::SendFinishedSuccess()
825 using namespace PackageManager;
826 // TODO : sync should move to separate task.
829 if (INSTALL_LOCATION_TYPE_EXTERNAL == m_installerContext.locationType) {
830 if (m_installerContext.isUpdateMode) {
831 WidgetInstallToExtSingleton::Instance().postUpgrade(true);
833 WidgetInstallToExtSingleton::Instance().postInstallation(true);
835 WidgetInstallToExtSingleton::Instance().deinitialize();
838 // remove widget install information file
839 unlink(m_installerContext.installInfo.c_str());
842 JobWidgetInstall::displayWidgetInfo();
844 TizenAppId& tizenId = m_installerContext.widgetConfig.tzAppid;
846 // send signal of pkgmgr
847 getInstallerStruct().pkgmgrInterface->sendSignal(
851 LogDebug("Call widget install successfinishedCallback");
852 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
854 tizenId), Jobs::Exceptions::Success);
857 void JobWidgetInstall::SendFinishedFailure()
859 using namespace PackageManager;
860 // remove widget install information file
861 unlink(m_installerContext.installInfo.c_str());
863 LogError("Error number: " << m_exceptionCaught);
864 LogError("Message: " << m_exceptionMessage);
865 TizenAppId & tizenId = m_installerContext.widgetConfig.tzAppid;
867 LogDebug("Call widget install failure finishedCallback");
868 std::stringstream errorNum;
869 errorNum << m_exceptionCaught;
871 // send signal of pkgmgr
872 getInstallerStruct().pkgmgrInterface->sendSignal(
876 getInstallerStruct().pkgmgrInterface->sendSignal(
880 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
882 tizenId), m_exceptionCaught);
885 void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
887 m_exceptionCaught = static_cast<Jobs::Exceptions::Type>(e.getParam());
888 m_exceptionMessage = e.GetMessage();
891 void JobWidgetInstall::displayWidgetInfo()
893 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
895 std::ostringstream out;
896 WidgetLocalizedInfo localizedInfo =
897 W3CFileLocalization::getLocalizedInfo(dao.getTzAppId());
900 "===================================== INSTALLED WIDGET INFO =========" \
901 "============================";
902 out << std::endl << "Name: " << localizedInfo.name;
903 out << std::endl << "AppId: " << dao.getTzAppId();
904 WidgetSize size = dao.getPreferredSize();
905 out << std::endl << "Width: " << size.width;
906 out << std::endl << "Height: " << size.height;
907 out << std::endl << "Start File: " <<
908 W3CFileLocalization::getStartFile(dao.getTzAppId());
909 out << std::endl << "Version: " << dao.getVersion();
910 out << std::endl << "Licence: " <<
911 localizedInfo.license;
912 out << std::endl << "Licence Href: " <<
913 localizedInfo.licenseHref;
914 out << std::endl << "Description: " <<
915 localizedInfo.description;
916 out << std::endl << "Widget Id: " << dao.getGUID();
917 out << std::endl << "Widget recognized: " << dao.isRecognized();
918 out << std::endl << "Widget distributor signed: " <<
919 dao.isDistributorSigned();
920 out << std::endl << "Widget trusted: " << dao.isTrusted();
922 OptionalWidgetIcon icon = W3CFileLocalization::getIcon(dao.getTzAppId());
923 DPL::OptionalString iconSrc =
924 !!icon ? icon->src : DPL::OptionalString::Null;
925 out << std::endl << "Icon: " << iconSrc;
927 out << std::endl << "Preferences:";
929 PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList();
932 out << std::endl << " Key: " <<
934 out << std::endl << " Readonly: " <<
939 out << std::endl << "Features:";
941 WidgetFeatureSet list = dao.getFeaturesList();
944 out << std::endl << " Name: " << it->name;
953 WrtDB::PackagingType JobWidgetInstall::checkPackageType(
954 const std::string &widgetSource,
955 const std::string &tempPath)
957 // Check installation type (direcotory/ or config.xml or widget.wgt)
958 if (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY ||
959 m_jobStruct.m_installMode == InstallMode::REINSTALL_MODE_DIRECTORY)
961 LogDebug("Install directly from directory");
962 return PKG_TYPE_DIRECTORY_WEB_APP;
964 if (hasExtension(widgetSource, XML_EXTENSION)) {
965 LogInfo("Hosted app installation");
966 return PKG_TYPE_HOSTED_WEB_APP;
970 std::string configFile = tempPath + "/" + CONFIG_XML;
971 if (WrtUtilFileExists(configFile)) {
972 return PKG_TYPE_NOMAL_WEB_APP;
975 configFile = tempPath + "/" + WITH_OSP_XML;
976 if (WrtUtilFileExists(configFile)) {
977 return PKG_TYPE_HYBRID_WEB_APP;
980 std::unique_ptr<DPL::ZipInput> zipFile;
985 zipFile.reset(new DPL::ZipInput(widgetSource));
987 Catch(DPL::ZipInput::Exception::OpenFailed)
989 LogDebug("Failed to open widget package");
990 return PKG_TYPE_UNKNOWN;
992 Catch(DPL::ZipInput::Exception::SeekFileFailed)
994 LogError("Failed to seek widget package file");
995 return PKG_TYPE_UNKNOWN;
1000 // Open config.xml file in package root
1001 std::unique_ptr<DPL::ZipInput::File> configFile(
1002 zipFile->OpenFile(CONFIG_XML));
1003 return PKG_TYPE_NOMAL_WEB_APP;
1005 Catch(DPL::ZipInput::Exception::OpenFileFailed)
1007 LogDebug("Could not find config.xml");
1012 // Open config.xml file in package root
1013 std::unique_ptr<DPL::ZipInput::File> configFile(
1014 zipFile->OpenFile(WITH_OSP_XML));
1016 return PKG_TYPE_HYBRID_WEB_APP;
1018 Catch(DPL::ZipInput::Exception::OpenFileFailed)
1020 LogDebug("Could not find wgt/config.xml");
1021 return PKG_TYPE_UNKNOWN;
1025 return PKG_TYPE_UNKNOWN;
1028 void JobWidgetInstall::setApplicationType(
1029 const WrtDB::ConfigParserData &configInfo)
1031 FOREACH(iterator, configInfo.nameSpaces) {
1032 LogInfo("namespace = [" << *iterator << "]");
1033 AppType currentAppType = APP_TYPE_UNKNOWN;
1035 if (*iterator == ConfigurationNamespace::W3CWidgetNamespaceName) {
1039 ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement ||
1041 ConfigurationNamespace::WacWidgetNamespaceName)
1043 currentAppType = APP_TYPE_WAC20;
1044 } else if (*iterator ==
1045 ConfigurationNamespace::TizenWebAppNamespaceName)
1047 currentAppType = APP_TYPE_TIZENWEBAPP;
1050 if (m_installerContext.widgetConfig.webAppType ==
1053 m_installerContext.widgetConfig.webAppType = currentAppType;
1054 } else if (m_installerContext.widgetConfig.webAppType ==
1059 ThrowMsg(Exceptions::WidgetConfigFileInvalid,
1060 "Config.xml has more than one namespace");
1064 // If there is no define, type set to WAC 2.0
1065 if (m_installerContext.widgetConfig.webAppType == APP_TYPE_UNKNOWN) {
1066 m_installerContext.widgetConfig.webAppType = APP_TYPE_WAC20;
1069 LogInfo("type = [" <<
1070 m_installerContext.widgetConfig.webAppType.getApptypeToString() <<
1074 bool JobWidgetInstall::detectResourceEncryption(
1075 const WrtDB::ConfigParserData &configData)
1077 FOREACH(it, configData.settingsList)
1079 if (it->m_name == SETTING_VALUE_ENCRYPTION &&
1080 it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE)
1082 LogDebug("resource need encryption");
1089 void JobWidgetInstall::setInstallLocationType(
1091 WrtDB::ConfigParserData &
1094 m_installerContext.locationType = INSTALL_LOCATION_TYPE_NOMAL;
1096 if (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_PRELOAD) {
1097 m_installerContext.locationType =
1098 INSTALL_LOCATION_TYPE_PRELOAD;
1100 FOREACH(it, configData.settingsList)
1102 if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME &&
1104 SETTING_VALUE_INSTALLTOEXT_PREPER_EXT)
1106 LogDebug("This widget will be installed to sd card");
1107 m_installerContext.locationType =
1108 INSTALL_LOCATION_TYPE_EXTERNAL;
1114 bool JobWidgetInstall::isDRMWidget(std::string /*widgetPath*/)
1120 bool JobWidgetInstall::DecryptDRMWidget(std::string /*widgetPath*/,
1121 std::string /*destPath*/)
1126 } //namespace WidgetInstall