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.m_quiet = m_jobStruct.m_quiet;
167 ConfigureResult result = PrePareInstallation(widgetPath);
169 if (result == ConfigureResult::Ok) {
170 LogInfo("Configure installation succeeded");
171 m_installerContext.job->SetProgressFlag(true);
173 AddTask(new TaskRecovery(m_installerContext));
175 // Create installation tasks
176 if (m_installerContext.widgetConfig.packagingType !=
177 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
178 m_installerContext.widgetConfig.packagingType !=
179 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
182 AddTask(new TaskUnzip(m_installerContext));
185 AddTask(new TaskWidgetConfig(m_installerContext));
186 if (m_installerContext.widgetConfig.packagingType ==
187 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
189 AddTask(new TaskPrepareFiles(m_installerContext));
191 AddTask(new TaskCertify(m_installerContext));
192 if (m_needEncryption) {
193 AddTask(new TaskEncryptResource(m_installerContext));
196 AddTask(new TaskFileManipulation(m_installerContext));
198 AddTask(new TaskManifestFile(m_installerContext));
199 if (m_installerContext.widgetConfig.packagingType ==
200 PKG_TYPE_HYBRID_WEB_APP)
202 AddTask(new TaskInstallOspsvc(m_installerContext));
204 AddTask(new TaskCertificates(m_installerContext));
205 AddTask(new TaskDatabase(m_installerContext));
206 AddTask(new TaskAceCheck(m_installerContext));
207 AddTask(new TaskSmack(m_installerContext));
208 } else if (result == ConfigureResult::Updated) {
209 LogInfo("Configure installation updated");
210 LogInfo("Widget Update");
211 m_installerContext.job->SetProgressFlag(true);
213 if (m_jobStruct.m_installMode ==
214 InstallMode::REINSTALL_MODE_DIRECTORY)
216 AddTask(new TaskPrepareReinstall(m_installerContext));
219 if (m_installerContext.widgetConfig.packagingType !=
220 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
221 m_installerContext.widgetConfig.packagingType !=
222 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
225 AddTask(new TaskUnzip(m_installerContext));
228 AddTask(new TaskWidgetConfig(m_installerContext));
230 if (m_installerContext.widgetConfig.packagingType ==
231 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
233 AddTask(new TaskPrepareFiles(m_installerContext));
236 AddTask(new TaskCertify(m_installerContext));
237 if (m_needEncryption) {
238 AddTask(new TaskEncryptResource(m_installerContext));
241 if (m_installerContext.widgetConfig.packagingType !=
242 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
244 AddTask(new TaskUpdateFiles(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 if (m_installerContext.widgetConfig.packagingType !=
254 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
256 AddTask(new TaskRemoveBackupFiles(m_installerContext));
258 AddTask(new TaskDatabase(m_installerContext));
259 AddTask(new TaskAceCheck(m_installerContext));
260 //TODO: remove widgetHandle from this task and move before database task
261 // by now widget handle is needed in ace check
262 // Any error in acecheck while update will break widget
263 AddTask(new TaskSmack(m_installerContext));
264 } else if (result == ConfigureResult::Deferred) {
265 // Installation is deferred
266 LogInfo("Configure installation deferred");
268 AddTask(new InstallerTaskFail(result));
269 } else if (result >= ConfigureResult::Failed &&
270 result <= ConfigureResult::Failed_DrmError) {
271 // Installation is not allowed to proceed due to widget update policy
272 LogWarning("Configure installation failed!");
274 AddTask(new InstallerTaskFail(result));
276 Assert(false && "Invalid configure result!");
280 ConfigureResult JobWidgetInstall::PrePareInstallation(
281 const std::string &widgetPath)
283 ConfigureResult result;
284 m_needEncryption = false;
289 if (m_jobStruct.m_installMode ==
290 InstallMode::REINSTALL_MODE_DIRECTORY)
292 std::ostringstream tempPathBuilder;
293 tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath();
294 tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath();
295 tempPathBuilder << "/";
296 tempPathBuilder << widgetPath;
297 tempDir = tempPathBuilder.str();;
300 Jobs::WidgetInstall::createTempPath(
301 m_jobStruct.m_installMode ==
302 InstallMode::INSTALL_MODE_PRELOAD);
305 m_isDRM = isDRMWidget(widgetPath);
306 if (true == m_isDRM) {
307 LogDebug("decrypt DRM widget");
308 if (DecryptDRMWidget(widgetPath, tempDir)) {
309 LogDebug("Failed decrypt DRM widget");
310 return ConfigureResult::Failed_DrmError;
314 LogDebug("widgetPath:" << widgetPath);
316 m_installerContext.widgetConfig.packagingType =
317 checkPackageType(widgetPath, tempDir);
318 ConfigParserData configData = getWidgetDataFromXML(
321 m_installerContext.widgetConfig.packagingType,
323 m_jobStruct.m_installMode ==
324 InstallMode::REINSTALL_MODE_DIRECTORY);
325 LogDebug("widget packaging type : " <<
326 m_installerContext.widgetConfig.packagingType.pkgType);
328 setTizenId(configData);
329 setApplicationType(configData);
330 m_needEncryption = detectResourceEncryption(configData);
331 setInstallLocationType(configData);
333 // Configure installation
334 result = ConfigureInstallation(widgetPath, configData, tempDir);
336 Catch(Exceptions::ExtractFileFailed)
338 LogError("Failed to create temporary path for widget");
339 result = ConfigureResult::Failed_InvalidConfig;
345 void JobWidgetInstall::setTizenId(
346 const WrtDB::ConfigParserData &configInfo)
348 bool shouldMakeAppid = false;
349 using namespace PackageManager;
350 if (!!configInfo.tizenAppId) {
351 LogDebug("Setting tizenAppId provided in config.xml: " <<
352 configInfo.tizenAppId);
354 m_installerContext.widgetConfig.tzAppid = *configInfo.tizenAppId;
356 if (!!configInfo.tizenPkgId) {
357 LogDebug("Setting tizenPkgId provided in config.xml: " <<
358 configInfo.tizenPkgId);
360 m_installerContext.widgetConfig.tzPkgid = *configInfo.tizenPkgId;
362 DPL::String appid = *configInfo.tizenAppId;
363 if (appid.length() > PACKAGE_ID_LENGTH) {
364 m_installerContext.widgetConfig.tzPkgid =
365 appid.substr(0, PACKAGE_ID_LENGTH);
367 //old version appid only has 10byte random character is able to install for a while.
368 //this case appid equal pkgid.
369 m_installerContext.widgetConfig.tzPkgid =
370 *configInfo.tizenAppId;
371 shouldMakeAppid = true;
375 shouldMakeAppid = true;
376 TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId();
377 LogDebug("Checking if pkg id is unique");
379 if (!validateTizenPackageID(pkgId)) {
380 //path exist, chose another one
381 pkgId = WidgetDAOReadOnly::generatePkgId();
386 m_installerContext.widgetConfig.tzPkgid = pkgId;
387 LogInfo("tizen_id name was generated by WRT: " <<
388 m_installerContext.widgetConfig.tzPkgid);
391 if (shouldMakeAppid == true) {
392 DPL::OptionalString name;
393 DPL::OptionalString defaultLocale = configInfo.defaultlocale;
395 FOREACH(localizedData, configInfo.localizedDataSet)
397 Locale i = localizedData->first;
398 if (!!defaultLocale) {
399 if (defaultLocale == i) {
400 name = localizedData->second.name;
404 name = localizedData->second.name;
409 if (regcomp(®x, REG_NAME_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
410 LogDebug("Regcomp failed");
413 LogDebug("Name : " << name);
414 if (!name || (regexec(®x, DPL::ToUTF8String(*name).c_str(),
415 static_cast<size_t>(0), NULL, 0) != REG_NOERROR))
417 // TODO : generate name move to wrt-commons
418 std::string allowedString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
419 std::ostringstream genName;
421 gettimeofday(&tv, NULL);
422 unsigned int seed = time(NULL) + tv.tv_usec;
424 genName << "_" << allowedString[rand_r(&seed) % allowedString.length()];
425 name = DPL::FromUTF8String(genName.str());
426 LogDebug("name was generated by WRT");
429 LogDebug("Name : " << name);
430 std::ostringstream genid;
431 genid << m_installerContext.widgetConfig.tzPkgid << "." << name;
432 LogDebug("tizen appid was generated by WRT : " << genid.str());
434 DPL::OptionalString appid = DPL::FromUTF8String(genid.str());
435 NormalizeAndTrimSpaceString(appid);
436 m_installerContext.widgetConfig.tzAppid = *appid;
439 // send start signal of pkgmgr
440 getInstallerStruct().pkgmgrInterface->setPkgname(DPL::ToUTF8String(
444 LogInfo("Tizen App Id : " << m_installerContext.widgetConfig.tzAppid);
445 LogInfo("Tizen Pkg Id : " << m_installerContext.widgetConfig.tzPkgid);
446 LogInfo("W3C Widget GUID : " << m_installerContext.widgetConfig.guid);
449 void JobWidgetInstall::configureWidgetLocation(const std::string & widgetPath,
450 const std::string& tempPath)
452 if (m_jobStruct.m_installMode ==
453 InstallMode::REINSTALL_MODE_DIRECTORY)
455 // replace widget path to installed path
456 m_installerContext.locations =
457 WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
459 widgetPath, tempPath,
460 m_installerContext.widgetConfig.packagingType,
461 m_installerContext.locationType);
463 m_installerContext.locations =
464 WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
466 widgetPath, tempPath,
467 m_installerContext.widgetConfig.packagingType,
468 m_installerContext.locationType);
470 m_installerContext.locations->registerAppid(
471 DPL::ToUTF8String(m_installerContext.widgetConfig.tzAppid));
473 LogInfo("widgetSource " << widgetPath);
476 ConfigureResult JobWidgetInstall::ConfigureInstallation(
477 const std::string &widgetSource,
478 const WrtDB::ConfigParserData &configData,
479 const std::string &tempPath)
481 ConfigureResult result = ConfigureResult::Failed;
482 WidgetUpdateInfo update;
484 // checking installed web application
486 // checking existing application is installed
487 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
488 // no excpetion means, it isn't update mode
489 getInstallerStruct().pkgmgrInterface->sendSignal(
491 PKGMGR_START_UPDATE);
493 update = detectWidgetUpdate(configData,
494 m_installerContext.widgetConfig.tzAppid);
495 result = checkWidgetUpdate(update);
496 if (result != ConfigureResult::Updated) {
497 // Already installed TizenAppId. return failed
498 return ConfigureResult::Failed_AlreadyInstalled;
500 m_installerContext.isUpdateMode = true;
502 Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
503 result = ConfigureResult::Ok;
504 getInstallerStruct().pkgmgrInterface->sendSignal(
506 PKGMGR_START_INSTALL);
507 m_installerContext.isUpdateMode = false;
509 if (!validateTizenApplicationID(
510 m_installerContext.widgetConfig.tzAppid))
512 LogError("tizen application ID is already used");
513 return ConfigureResult::Failed_InvalidConfig;
515 if (!validateTizenPackageID(m_installerContext.widgetConfig.tzPkgid)) {
516 LogError("tizen package ID is already used");
517 return ConfigureResult::Failed_AlreadyInstalled;
521 configureWidgetLocation(widgetSource, tempPath);
523 // Init installer context
524 m_installerContext.installStep = InstallerContext::INSTALL_START;
525 m_installerContext.job = this;
526 m_installerContext.widgetConfig.shareHref = std::string();
531 bool JobWidgetInstall::validateTizenApplicationID(
532 const WrtDB::TizenAppId &tizenAppId)
534 LogInfo("tizen application ID = [" << tizenAppId << "]");
537 if (regcomp(®, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
538 LogDebug("Regcomp failed");
541 if (regexec(®, DPL::ToUTF8String(tizenAppId).c_str(), 0, NULL, 0)
551 bool JobWidgetInstall::validateTizenPackageID(
552 const WrtDB::TizenPkgId &tizenPkgId)
554 std::string pkgId = DPL::ToUTF8String(tizenPkgId);
556 std::string installPath =
557 std::string(GlobalConfig::GetUserInstalledWidgetPath()) +
559 std::string preinstallPath =
560 std::string(GlobalConfig::GetUserPreloadedWidgetPath()) +
564 if ((stat(installPath.c_str(), &dirStat) == 0) ||
565 (stat(preinstallPath.c_str(), &dirStat) == 0))
572 ConfigureResult JobWidgetInstall::checkWidgetUpdate(
573 const WidgetUpdateInfo &update)
575 LogInfo("incoming version = '" << update.incomingVersion);
576 LogInfo("Tizen AppID = " << update.tzAppId);
578 if (update.existingVersion.IsNull() || update.incomingVersion.IsNull()) {
579 return ConfigureResult::Failed;
582 // Check running state
583 bool isRunning = false;
585 app_manager_is_running(DPL::ToUTF8String(update.tzAppId).c_str(),
587 if (APP_MANAGER_ERROR_NONE != ret) {
588 LogError("Fail to get running state");
589 return ConfigureResult::Failed_WidgetRunning;
592 if (true == isRunning) {
593 // get app_context for running application
594 // app_context must be released with app_context_destroy
595 app_context_h appCtx = NULL;
597 app_manager_get_app_context(
598 DPL::ToUTF8String(update.tzAppId).c_str(),
600 if (APP_MANAGER_ERROR_NONE != ret) {
601 LogError("Fail to get app_context");
602 return ConfigureResult::Failed_WidgetRunning;
605 // terminate app_context_h
606 ret = app_manager_terminate_app(appCtx);
607 if (APP_MANAGER_ERROR_NONE != ret) {
608 LogError("Fail to terminate running application");
609 app_context_destroy(appCtx);
610 return ConfigureResult::Failed_WidgetRunning;
612 app_context_destroy(appCtx);
613 // app_manager_terminate_app isn't sync API
614 // wait until application isn't running (50ms * 100)
615 bool isStillRunning = true;
616 int checkingloop = 100;
617 struct timespec duration = { 0, 50 * 1000 * 1000 };
618 while (--checkingloop >= 0) {
619 nanosleep(&duration, NULL);
621 app_manager_is_running(
622 DPL::ToUTF8String(update.tzAppId).c_str(),
624 if (APP_MANAGER_ERROR_NONE != ret) {
625 LogError("Fail to get running state");
626 return ConfigureResult::Failed_WidgetRunning;
628 if (!isStillRunning) {
632 if (isStillRunning) {
633 LogError("Fail to terminate running application");
634 return ConfigureResult::Failed_WidgetRunning;
636 LogInfo("terminate application");
640 m_installerContext.widgetConfig.tzAppid = update.tzAppId;
642 if (isUpperVersion(update.existingVersion, update.incomingVersion) ||
643 (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY) ||
644 (m_jobStruct.m_installMode == InstallMode::REINSTALL_MODE_DIRECTORY))
646 LogInfo("Whether widget policy allow proceed ok");
647 return ConfigureResult::Updated;
649 return ConfigureResult::Failed_LowerVersion;
652 return ConfigureResult::Failed;
655 bool JobWidgetInstall::isUpperVersion(
656 const OptionalWidgetVersion &existingVersion,
657 const OptionalWidgetVersion &incomingVersion)
659 LogInfo("Existing version = '" << *existingVersion);
660 LogInfo("Incoming version = '" << *incomingVersion);
662 if (!existingVersion && !incomingVersion) {
664 } else if (!existingVersion && !!incomingVersion) {
666 } else if (!!existingVersion && !incomingVersion) {
669 if (!existingVersion->IsWac() || !incomingVersion->IsWac()) {
672 if (*incomingVersion == *existingVersion) {
674 } else if (*incomingVersion > *existingVersion) {
683 ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
684 const std::string &widgetSource,
685 const std::string &tempPath,
686 WrtDB::PackagingType pkgType,
692 ConfigParserData configInfo;
696 if (pkgType == PKG_TYPE_HOSTED_WEB_APP) {
697 parser.Parse(widgetSource,
699 new RootParser<WidgetParser>(configInfo,
700 DPL::FromUTF32String(
702 } else if (pkgType == PKG_TYPE_DIRECTORY_WEB_APP) {
703 std::string configPath;
704 configPath = tempPath;
706 configPath += WITH_OSP_XML;
709 // checking RDS data directory
710 if (access(configPath.c_str(), F_OK) != 0) {
711 std::string tzAppId =
712 widgetSource.substr(widgetSource.find_last_of("/")+1);
713 WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTzAppId(DPL::FromUTF8String(tzAppId)));
714 configPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath());
716 configPath += WITH_OSP_XML;
719 parser.Parse(configPath,
721 new RootParser<WidgetParser>(
723 DPL::FromUTF32String(L"widget"))));
726 std::unique_ptr<DPL::ZipInput> zipFile(
727 new DPL::ZipInput(widgetSource));
729 std::unique_ptr<DPL::ZipInput::File> configFile;
731 // Open config.xml file
732 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
733 configFile.reset(zipFile->OpenFile(WITH_OSP_XML));
735 configFile.reset(zipFile->OpenFile(CONFIG_XML));
739 DPL::BinaryQueue buffer;
740 DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
741 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
742 DPL::Copy(&inputAdapter, &outputAdapter);
743 parser.Parse(&buffer,
745 new RootParser<WidgetParser>(configInfo,
751 std::string configFile;
752 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
753 configFile = tempPath + "/" + WITH_OSP_XML;
755 configFile = tempPath + "/" + CONFIG_XML;
758 parser.Parse(configFile,
760 new RootParser<WidgetParser>(configInfo,
767 Catch(DPL::ZipInput::Exception::OpenFailed)
769 LogError("Failed to open widget package");
770 return ConfigParserData();
772 Catch(DPL::ZipInput::Exception::OpenFileFailed)
774 LogError("Failed to open config.xml file");
775 return ConfigParserData();
777 Catch(DPL::CopyFailed)
779 LogError("Failed to extract config.xml file");
780 return ConfigParserData();
782 Catch(DPL::FileInput::Exception::OpenFailed)
784 LogError("Failed to open config.xml file");
785 return ConfigParserData();
787 Catch(ElementParser::Exception::ParseError)
789 LogError("Failed to parse config.xml file");
790 return ConfigParserData();
792 Catch(DPL::ZipInput::Exception::SeekFileFailed)
794 LogError("Failed to seek widget archive - corrupted package?");
795 return ConfigParserData();
800 WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
801 const ConfigParserData &configInfo,
802 const WrtDB::TizenAppId &tizenId)
804 LogInfo("Checking up widget package for config.xml...");
805 OptionalWidgetVersion incomingVersion;
807 if (!configInfo.version.IsNull()) {
809 DPL::Optional<WidgetVersion>(
810 WidgetVersion(*configInfo.version));
813 WidgetDAOReadOnly dao(tizenId);
815 OptionalWidgetVersion optVersion;
816 DPL::OptionalString version = dao.getVersion();
817 if (!version.IsNull()) {
818 optVersion = OptionalWidgetVersion(WidgetVersion(*version));
821 return WidgetUpdateInfo(
827 void JobWidgetInstall::SendProgress()
829 using namespace PackageManager;
830 if (GetProgressFlag() != false) {
831 if (getInstallerStruct().progressCallback != NULL) {
832 // send progress signal of pkgmgr
833 std::ostringstream percent;
834 percent << static_cast<int>(GetProgressPercent());
835 getInstallerStruct().pkgmgrInterface->sendSignal(
839 LogDebug("Call widget install progressCallbak");
840 getInstallerStruct().progressCallback(
841 getInstallerStruct().userParam,
842 GetProgressPercent(),
843 GetProgressDescription());
848 void JobWidgetInstall::SendProgressIconPath(const std::string &path)
850 using namespace PackageManager;
851 if (GetProgressFlag() != false) {
852 if (getInstallerStruct().progressCallback != NULL) {
853 // send progress signal of pkgmgr
854 getInstallerStruct().pkgmgrInterface->sendSignal(
861 void JobWidgetInstall::SendFinishedSuccess()
863 using namespace PackageManager;
864 // TODO : sync should move to separate task.
867 if (INSTALL_LOCATION_TYPE_EXTERNAL == m_installerContext.locationType) {
868 if (m_installerContext.isUpdateMode) {
869 WidgetInstallToExtSingleton::Instance().postUpgrade(true);
871 WidgetInstallToExtSingleton::Instance().postInstallation(true);
873 WidgetInstallToExtSingleton::Instance().deinitialize();
876 // remove widget install information file
877 unlink(m_installerContext.installInfo.c_str());
880 JobWidgetInstall::displayWidgetInfo();
882 TizenAppId& tizenId = m_installerContext.widgetConfig.tzAppid;
884 // send signal of pkgmgr
885 getInstallerStruct().pkgmgrInterface->sendSignal(
889 LogDebug("Call widget install successfinishedCallback");
890 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
892 tizenId), Jobs::Exceptions::Success);
895 void JobWidgetInstall::SendFinishedFailure()
897 using namespace PackageManager;
898 // remove widget install information file
899 unlink(m_installerContext.installInfo.c_str());
901 LogError("Error number: " << m_exceptionCaught);
902 LogError("Message: " << m_exceptionMessage);
903 TizenAppId & tizenId = m_installerContext.widgetConfig.tzAppid;
905 LogDebug("Call widget install failure finishedCallback");
906 std::stringstream errorNum;
907 errorNum << m_exceptionCaught;
909 // send signal of pkgmgr
910 getInstallerStruct().pkgmgrInterface->sendSignal(
914 getInstallerStruct().pkgmgrInterface->sendSignal(
918 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
920 tizenId), m_exceptionCaught);
923 void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
925 m_exceptionCaught = static_cast<Jobs::Exceptions::Type>(e.getParam());
926 m_exceptionMessage = e.GetMessage();
929 void JobWidgetInstall::displayWidgetInfo()
931 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
933 std::ostringstream out;
934 WidgetLocalizedInfo localizedInfo =
935 W3CFileLocalization::getLocalizedInfo(dao.getTzAppId());
938 "===================================== INSTALLED WIDGET INFO =========" \
939 "============================";
940 out << std::endl << "Name: " << localizedInfo.name;
941 out << std::endl << "AppId: " << dao.getTzAppId();
942 WidgetSize size = dao.getPreferredSize();
943 out << std::endl << "Width: " << size.width;
944 out << std::endl << "Height: " << size.height;
945 out << std::endl << "Start File: " <<
946 W3CFileLocalization::getStartFile(dao.getTzAppId());
947 out << std::endl << "Version: " << dao.getVersion();
948 out << std::endl << "Licence: " <<
949 localizedInfo.license;
950 out << std::endl << "Licence Href: " <<
951 localizedInfo.licenseHref;
952 out << std::endl << "Description: " <<
953 localizedInfo.description;
954 out << std::endl << "Widget Id: " << dao.getGUID();
955 out << std::endl << "Widget recognized: " << dao.isRecognized();
956 out << std::endl << "Widget distributor signed: " <<
957 dao.isDistributorSigned();
958 out << std::endl << "Widget trusted: " << dao.isTrusted();
960 OptionalWidgetIcon icon = W3CFileLocalization::getIcon(dao.getTzAppId());
961 DPL::OptionalString iconSrc =
962 !!icon ? icon->src : DPL::OptionalString::Null;
963 out << std::endl << "Icon: " << iconSrc;
965 out << std::endl << "Preferences:";
967 PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList();
970 out << std::endl << " Key: " <<
972 out << std::endl << " Readonly: " <<
977 out << std::endl << "Features:";
979 WidgetFeatureSet list = dao.getFeaturesList();
982 out << std::endl << " Name: " << it->name;
991 WrtDB::PackagingType JobWidgetInstall::checkPackageType(
992 const std::string &widgetSource,
993 const std::string &tempPath)
995 // Check installation type (direcotory/ or config.xml or widget.wgt)
996 if (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY ||
997 m_jobStruct.m_installMode == InstallMode::REINSTALL_MODE_DIRECTORY)
999 LogDebug("Install directly from directory");
1000 return PKG_TYPE_DIRECTORY_WEB_APP;
1002 if (hasExtension(widgetSource, XML_EXTENSION)) {
1003 LogInfo("Hosted app installation");
1004 return PKG_TYPE_HOSTED_WEB_APP;
1008 std::string configFile = tempPath + "/" + CONFIG_XML;
1009 if (WrtUtilFileExists(configFile)) {
1010 return PKG_TYPE_NOMAL_WEB_APP;
1013 configFile = tempPath + "/" + WITH_OSP_XML;
1014 if (WrtUtilFileExists(configFile)) {
1015 return PKG_TYPE_HYBRID_WEB_APP;
1018 std::unique_ptr<DPL::ZipInput> zipFile;
1023 zipFile.reset(new DPL::ZipInput(widgetSource));
1025 Catch(DPL::ZipInput::Exception::OpenFailed)
1027 LogDebug("Failed to open widget package");
1028 return PKG_TYPE_UNKNOWN;
1030 Catch(DPL::ZipInput::Exception::SeekFileFailed)
1032 LogError("Failed to seek widget package file");
1033 return PKG_TYPE_UNKNOWN;
1038 // Open config.xml file in package root
1039 std::unique_ptr<DPL::ZipInput::File> configFile(
1040 zipFile->OpenFile(CONFIG_XML));
1041 return PKG_TYPE_NOMAL_WEB_APP;
1043 Catch(DPL::ZipInput::Exception::OpenFileFailed)
1045 LogDebug("Could not find config.xml");
1050 // Open config.xml file in package root
1051 std::unique_ptr<DPL::ZipInput::File> configFile(
1052 zipFile->OpenFile(WITH_OSP_XML));
1054 return PKG_TYPE_HYBRID_WEB_APP;
1056 Catch(DPL::ZipInput::Exception::OpenFileFailed)
1058 LogDebug("Could not find wgt/config.xml");
1059 return PKG_TYPE_UNKNOWN;
1063 return PKG_TYPE_UNKNOWN;
1066 void JobWidgetInstall::setApplicationType(
1067 const WrtDB::ConfigParserData &configInfo)
1069 FOREACH(iterator, configInfo.nameSpaces) {
1070 LogInfo("namespace = [" << *iterator << "]");
1071 AppType currentAppType = APP_TYPE_UNKNOWN;
1073 if (*iterator == ConfigurationNamespace::W3CWidgetNamespaceName) {
1077 ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement ||
1079 ConfigurationNamespace::WacWidgetNamespaceName)
1081 currentAppType = APP_TYPE_WAC20;
1082 } else if (*iterator ==
1083 ConfigurationNamespace::TizenWebAppNamespaceName)
1085 currentAppType = APP_TYPE_TIZENWEBAPP;
1088 if (m_installerContext.widgetConfig.webAppType ==
1091 m_installerContext.widgetConfig.webAppType = currentAppType;
1092 } else if (m_installerContext.widgetConfig.webAppType ==
1097 ThrowMsg(Exceptions::WidgetConfigFileInvalid,
1098 "Config.xml has more than one namespace");
1102 // If there is no define, type set to WAC 2.0
1103 if (m_installerContext.widgetConfig.webAppType == APP_TYPE_UNKNOWN) {
1104 m_installerContext.widgetConfig.webAppType = APP_TYPE_WAC20;
1107 LogInfo("type = [" <<
1108 m_installerContext.widgetConfig.webAppType.getApptypeToString() <<
1112 bool JobWidgetInstall::detectResourceEncryption(
1113 const WrtDB::ConfigParserData &configData)
1115 FOREACH(it, configData.settingsList)
1117 if (it->m_name == SETTING_VALUE_ENCRYPTION &&
1118 it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE)
1120 LogDebug("resource need encryption");
1127 void JobWidgetInstall::setInstallLocationType(
1129 WrtDB::ConfigParserData &
1132 m_installerContext.locationType = INSTALL_LOCATION_TYPE_NOMAL;
1134 if (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_PRELOAD) {
1135 m_installerContext.locationType =
1136 INSTALL_LOCATION_TYPE_PRELOAD;
1138 FOREACH(it, configData.settingsList)
1140 if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME &&
1142 SETTING_VALUE_INSTALLTOEXT_PREPER_EXT)
1144 LogDebug("This widget will be installed to sd card");
1145 m_installerContext.locationType =
1146 INSTALL_LOCATION_TYPE_EXTERNAL;
1152 bool JobWidgetInstall::isDRMWidget(std::string /*widgetPath*/)
1158 bool JobWidgetInstall::DecryptDRMWidget(std::string /*widgetPath*/,
1159 std::string /*destPath*/)
1164 } //namespace WidgetInstall