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 ConfigureResult result = PrePareInstallation(widgetPath);
167 if (result == ConfigureResult::Ok) {
168 LogInfo("Configure installation succeeded");
169 m_installerContext.job->SetProgressFlag(true);
171 AddTask(new TaskRecovery(m_installerContext));
173 // Create installation tasks
174 if (m_installerContext.widgetConfig.packagingType !=
175 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
176 m_installerContext.widgetConfig.packagingType !=
177 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
180 AddTask(new TaskUnzip(m_installerContext));
183 AddTask(new TaskWidgetConfig(m_installerContext));
184 if (m_installerContext.widgetConfig.packagingType ==
185 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
187 AddTask(new TaskPrepareFiles(m_installerContext));
189 AddTask(new TaskCertify(m_installerContext));
190 if (m_needEncryption) {
191 AddTask(new TaskEncryptResource(m_installerContext));
194 AddTask(new TaskFileManipulation(m_installerContext));
196 AddTask(new TaskManifestFile(m_installerContext));
197 if (m_installerContext.widgetConfig.packagingType ==
198 PKG_TYPE_HYBRID_WEB_APP)
200 AddTask(new TaskInstallOspsvc(m_installerContext));
202 AddTask(new TaskCertificates(m_installerContext));
203 AddTask(new TaskDatabase(m_installerContext));
204 AddTask(new TaskAceCheck(m_installerContext));
205 AddTask(new TaskSmack(m_installerContext));
206 } else if (result == ConfigureResult::Updated) {
207 LogInfo("Configure installation updated");
208 LogInfo("Widget Update");
209 m_installerContext.job->SetProgressFlag(true);
211 if (m_jobStruct.m_installMode ==
212 InstallMode::REINSTALL_MODE_DIRECTORY)
214 AddTask(new TaskPrepareReinstall(m_installerContext));
217 if (m_installerContext.widgetConfig.packagingType !=
218 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
219 m_installerContext.widgetConfig.packagingType !=
220 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
223 AddTask(new TaskUnzip(m_installerContext));
226 AddTask(new TaskWidgetConfig(m_installerContext));
228 if (m_installerContext.widgetConfig.packagingType ==
229 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
231 AddTask(new TaskPrepareFiles(m_installerContext));
234 AddTask(new TaskCertify(m_installerContext));
235 if (m_needEncryption) {
236 AddTask(new TaskEncryptResource(m_installerContext));
239 if (m_installerContext.widgetConfig.packagingType !=
240 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
242 AddTask(new TaskUpdateFiles(m_installerContext));
245 AddTask(new TaskManifestFile(m_installerContext));
246 if (m_installerContext.widgetConfig.packagingType ==
247 PKG_TYPE_HYBRID_WEB_APP)
249 AddTask(new TaskInstallOspsvc(m_installerContext));
251 if (m_installerContext.widgetConfig.packagingType !=
252 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
254 AddTask(new TaskRemoveBackupFiles(m_installerContext));
256 AddTask(new TaskDatabase(m_installerContext));
257 AddTask(new TaskAceCheck(m_installerContext));
258 //TODO: remove widgetHandle from this task and move before database task
259 // by now widget handle is needed in ace check
260 // Any error in acecheck while update will break widget
261 AddTask(new TaskSmack(m_installerContext));
262 } else if (result == ConfigureResult::Deferred) {
263 // Installation is deferred
264 LogInfo("Configure installation deferred");
266 AddTask(new InstallerTaskFail(result));
267 } else if (result >= ConfigureResult::Failed &&
268 result <= ConfigureResult::Failed_DrmError) {
269 // Installation is not allowed to proceed due to widget update policy
270 LogWarning("Configure installation failed!");
272 AddTask(new InstallerTaskFail(result));
274 Assert(false && "Invalid configure result!");
278 ConfigureResult JobWidgetInstall::PrePareInstallation(
279 const std::string &widgetPath)
281 ConfigureResult result;
282 m_needEncryption = false;
287 if (m_jobStruct.m_installMode ==
288 InstallMode::REINSTALL_MODE_DIRECTORY)
290 std::ostringstream tempPathBuilder;
291 tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath();
292 tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath();
293 tempPathBuilder << "/";
294 tempPathBuilder << widgetPath;
295 tempDir = tempPathBuilder.str();;
298 Jobs::WidgetInstall::createTempPath(
299 m_jobStruct.m_installMode ==
300 InstallMode::INSTALL_MODE_PRELOAD);
303 m_isDRM = isDRMWidget(widgetPath);
304 if (true == m_isDRM) {
305 LogDebug("decrypt DRM widget");
306 if (DecryptDRMWidget(widgetPath, tempDir)) {
307 LogDebug("Failed decrypt DRM widget");
308 return ConfigureResult::Failed_DrmError;
312 LogDebug("widgetPath:" << widgetPath);
314 m_installerContext.widgetConfig.packagingType =
315 checkPackageType(widgetPath, tempDir);
316 ConfigParserData configData = getWidgetDataFromXML(
319 m_installerContext.widgetConfig.packagingType,
321 m_jobStruct.m_installMode ==
322 InstallMode::REINSTALL_MODE_DIRECTORY);
323 LogDebug("widget packaging type : " <<
324 m_installerContext.widgetConfig.packagingType.pkgType);
326 setTizenId(configData);
327 setApplicationType(configData);
328 m_needEncryption = detectResourceEncryption(configData);
329 setInstallLocationType(configData);
331 // Configure installation
332 result = ConfigureInstallation(widgetPath, configData, tempDir);
334 Catch(Exceptions::ExtractFileFailed)
336 LogError("Failed to create temporary path for widget");
337 result = ConfigureResult::Failed_InvalidConfig;
343 void JobWidgetInstall::setTizenId(
344 const WrtDB::ConfigParserData &configInfo)
346 bool shouldMakeAppid = false;
347 using namespace PackageManager;
348 if (!!configInfo.tizenAppId) {
349 LogDebug("Setting tizenAppId provided in config.xml: " <<
350 configInfo.tizenAppId);
352 m_installerContext.widgetConfig.tzAppid = *configInfo.tizenAppId;
354 if (!!configInfo.tizenPkgId) {
355 LogDebug("Setting tizenPkgId provided in config.xml: " <<
356 configInfo.tizenPkgId);
358 m_installerContext.widgetConfig.tzPkgid = *configInfo.tizenPkgId;
360 DPL::String appid = *configInfo.tizenAppId;
361 if (appid.length() > PACKAGE_ID_LENGTH) {
362 m_installerContext.widgetConfig.tzPkgid =
363 appid.substr(0, PACKAGE_ID_LENGTH);
365 //old version appid only has 10byte random character is able to install for a while.
366 //this case appid equal pkgid.
367 m_installerContext.widgetConfig.tzPkgid =
368 *configInfo.tizenAppId;
369 shouldMakeAppid = true;
373 shouldMakeAppid = true;
374 TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId();
375 LogDebug("Checking if pkg id is unique");
377 if (!validateTizenPackageID(pkgId)) {
378 //path exist, chose another one
379 pkgId = WidgetDAOReadOnly::generatePkgId();
384 m_installerContext.widgetConfig.tzPkgid = pkgId;
385 LogInfo("tizen_id name was generated by WRT: " <<
386 m_installerContext.widgetConfig.tzPkgid);
389 if (shouldMakeAppid == true) {
390 DPL::OptionalString name;
391 DPL::OptionalString defaultLocale = configInfo.defaultlocale;
393 FOREACH(localizedData, configInfo.localizedDataSet)
395 Locale i = localizedData->first;
396 if (!!defaultLocale) {
397 if (defaultLocale == i) {
398 name = localizedData->second.name;
402 name = localizedData->second.name;
407 if (regcomp(®x, REG_NAME_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
408 LogDebug("Regcomp failed");
411 LogDebug("Name : " << name);
412 if (!name || (regexec(®x, DPL::ToUTF8String(*name).c_str(),
413 static_cast<size_t>(0), NULL, 0) != REG_NOERROR))
415 // TODO : generate name move to wrt-commons
416 std::string allowedString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
417 std::ostringstream genName;
419 gettimeofday(&tv, NULL);
420 unsigned int seed = time(NULL) + tv.tv_usec;
422 genName << "_" << allowedString[rand_r(&seed) % allowedString.length()];
423 name = DPL::FromUTF8String(genName.str());
424 LogDebug("name was generated by WRT");
427 LogDebug("Name : " << name);
428 std::ostringstream genid;
429 genid << m_installerContext.widgetConfig.tzPkgid << "." << name;
430 LogDebug("tizen appid was generated by WRT : " << genid.str());
432 DPL::OptionalString appid = DPL::FromUTF8String(genid.str());
433 NormalizeAndTrimSpaceString(appid);
434 m_installerContext.widgetConfig.tzAppid = *appid;
437 // send start signal of pkgmgr
438 getInstallerStruct().pkgmgrInterface->setPkgname(DPL::ToUTF8String(
442 LogInfo("Tizen App Id : " << m_installerContext.widgetConfig.tzAppid);
443 LogInfo("Tizen Pkg Id : " << m_installerContext.widgetConfig.tzPkgid);
444 LogInfo("W3C Widget GUID : " << m_installerContext.widgetConfig.guid);
447 void JobWidgetInstall::configureWidgetLocation(const std::string & widgetPath,
448 const std::string& tempPath)
450 if (m_jobStruct.m_installMode ==
451 InstallMode::REINSTALL_MODE_DIRECTORY)
453 // replace widget path to installed path
454 m_installerContext.locations =
455 WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
457 widgetPath, tempPath,
458 m_installerContext.widgetConfig.packagingType,
459 m_installerContext.locationType);
461 m_installerContext.locations =
462 WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
464 widgetPath, tempPath,
465 m_installerContext.widgetConfig.packagingType,
466 m_installerContext.locationType);
468 m_installerContext.locations->registerAppid(
469 DPL::ToUTF8String(m_installerContext.widgetConfig.tzAppid));
471 LogInfo("widgetSource " << widgetPath);
474 ConfigureResult JobWidgetInstall::ConfigureInstallation(
475 const std::string &widgetSource,
476 const WrtDB::ConfigParserData &configData,
477 const std::string &tempPath)
479 ConfigureResult result = ConfigureResult::Failed;
480 WidgetUpdateInfo update;
482 // checking installed web application
484 // checking existing application is installed
485 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
486 // no excpetion means, it isn't update mode
487 getInstallerStruct().pkgmgrInterface->sendSignal(
489 PKGMGR_START_UPDATE);
491 update = detectWidgetUpdate(configData,
492 m_installerContext.widgetConfig.tzAppid);
493 result = checkWidgetUpdate(update);
494 if (result != ConfigureResult::Updated) {
495 // Already installed TizenAppId. return failed
496 return ConfigureResult::Failed_AlreadyInstalled;
498 m_installerContext.isUpdateMode = true;
500 Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
501 result = ConfigureResult::Ok;
502 getInstallerStruct().pkgmgrInterface->sendSignal(
504 PKGMGR_START_INSTALL);
505 m_installerContext.isUpdateMode = false;
507 if (!validateTizenApplicationID(
508 m_installerContext.widgetConfig.tzAppid))
510 LogError("tizen application ID is already used");
511 return ConfigureResult::Failed_InvalidConfig;
513 if (!validateTizenPackageID(m_installerContext.widgetConfig.tzPkgid)) {
514 LogError("tizen package ID is already used");
515 return ConfigureResult::Failed_AlreadyInstalled;
519 configureWidgetLocation(widgetSource, tempPath);
521 // Init installer context
522 m_installerContext.installStep = InstallerContext::INSTALL_START;
523 m_installerContext.job = this;
524 m_installerContext.widgetConfig.shareHref = std::string();
529 bool JobWidgetInstall::validateTizenApplicationID(
530 const WrtDB::TizenAppId &tizenAppId)
532 LogInfo("tizen application ID = [" << tizenAppId << "]");
535 if (regcomp(®, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
536 LogDebug("Regcomp failed");
539 if (regexec(®, DPL::ToUTF8String(tizenAppId).c_str(), 0, NULL, 0)
549 bool JobWidgetInstall::validateTizenPackageID(
550 const WrtDB::TizenPkgId &tizenPkgId)
552 std::string pkgId = DPL::ToUTF8String(tizenPkgId);
554 std::string installPath =
555 std::string(GlobalConfig::GetUserInstalledWidgetPath()) +
557 std::string preinstallPath =
558 std::string(GlobalConfig::GetUserPreloadedWidgetPath()) +
562 if ((stat(installPath.c_str(), &dirStat) == 0) ||
563 (stat(preinstallPath.c_str(), &dirStat) == 0))
570 ConfigureResult JobWidgetInstall::checkWidgetUpdate(
571 const WidgetUpdateInfo &update)
573 LogInfo("incoming version = '" << update.incomingVersion);
574 LogInfo("Tizen AppID = " << update.tzAppId);
576 if (update.existingVersion.IsNull() || update.incomingVersion.IsNull()) {
577 return ConfigureResult::Failed;
580 // Check running state
581 bool isRunning = false;
583 app_manager_is_running(DPL::ToUTF8String(update.tzAppId).c_str(),
585 if (APP_MANAGER_ERROR_NONE != ret) {
586 LogError("Fail to get running state");
587 return ConfigureResult::Failed_WidgetRunning;
590 if (true == isRunning) {
591 // get app_context for running application
592 // app_context must be released with app_context_destroy
593 app_context_h appCtx = NULL;
595 app_manager_get_app_context(
596 DPL::ToUTF8String(update.tzAppId).c_str(),
598 if (APP_MANAGER_ERROR_NONE != ret) {
599 LogError("Fail to get app_context");
600 return ConfigureResult::Failed_WidgetRunning;
603 // terminate app_context_h
604 ret = app_manager_terminate_app(appCtx);
605 if (APP_MANAGER_ERROR_NONE != ret) {
606 LogError("Fail to terminate running application");
607 app_context_destroy(appCtx);
608 return ConfigureResult::Failed_WidgetRunning;
610 app_context_destroy(appCtx);
611 // app_manager_terminate_app isn't sync API
612 // wait until application isn't running (50ms * 100)
613 bool isStillRunning = true;
614 int checkingloop = 100;
615 struct timespec duration = { 0, 50 * 1000 * 1000 };
616 while (--checkingloop >= 0) {
617 nanosleep(&duration, NULL);
619 app_manager_is_running(
620 DPL::ToUTF8String(update.tzAppId).c_str(),
622 if (APP_MANAGER_ERROR_NONE != ret) {
623 LogError("Fail to get running state");
624 return ConfigureResult::Failed_WidgetRunning;
626 if (!isStillRunning) {
630 if (isStillRunning) {
631 LogError("Fail to terminate running application");
632 return ConfigureResult::Failed_WidgetRunning;
634 LogInfo("terminate application");
638 m_installerContext.widgetConfig.tzAppid = update.tzAppId;
640 if (isUpperVersion(update.existingVersion, update.incomingVersion) ||
641 (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY) ||
642 (m_jobStruct.m_installMode == InstallMode::REINSTALL_MODE_DIRECTORY))
644 LogInfo("Whether widget policy allow proceed ok");
645 return ConfigureResult::Updated;
647 return ConfigureResult::Failed_LowerVersion;
650 return ConfigureResult::Failed;
653 bool JobWidgetInstall::isUpperVersion(
654 const OptionalWidgetVersion &existingVersion,
655 const OptionalWidgetVersion &incomingVersion)
657 LogInfo("Existing version = '" << *existingVersion);
658 LogInfo("Incoming version = '" << *incomingVersion);
660 if (!existingVersion && !incomingVersion) {
662 } else if (!existingVersion && !!incomingVersion) {
664 } else if (!!existingVersion && !incomingVersion) {
667 if (!existingVersion->IsWac() || !incomingVersion->IsWac()) {
670 if (*incomingVersion == *existingVersion) {
672 } else if (*incomingVersion > *existingVersion) {
681 ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
682 const std::string &widgetSource,
683 const std::string &tempPath,
684 WrtDB::PackagingType pkgType,
690 ConfigParserData configInfo;
694 if (pkgType == PKG_TYPE_HOSTED_WEB_APP) {
695 parser.Parse(widgetSource,
697 new RootParser<WidgetParser>(configInfo,
698 DPL::FromUTF32String(
700 } else if (pkgType == PKG_TYPE_DIRECTORY_WEB_APP) {
701 std::string configPath;
702 configPath = tempPath;
704 configPath += WITH_OSP_XML;
707 // checking RDS data directory
708 if (access(configPath.c_str(), F_OK) != 0) {
709 std::string tzAppId =
710 widgetSource.substr(widgetSource.find_last_of("/")+1);
711 WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTzAppId(DPL::FromUTF8String(tzAppId)));
712 configPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath());
714 configPath += WITH_OSP_XML;
717 parser.Parse(configPath,
719 new RootParser<WidgetParser>(
721 DPL::FromUTF32String(L"widget"))));
724 std::unique_ptr<DPL::ZipInput> zipFile(
725 new DPL::ZipInput(widgetSource));
727 std::unique_ptr<DPL::ZipInput::File> configFile;
729 // Open config.xml file
730 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
731 configFile.reset(zipFile->OpenFile(WITH_OSP_XML));
733 configFile.reset(zipFile->OpenFile(CONFIG_XML));
737 DPL::BinaryQueue buffer;
738 DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
739 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
740 DPL::Copy(&inputAdapter, &outputAdapter);
741 parser.Parse(&buffer,
743 new RootParser<WidgetParser>(configInfo,
749 std::string configFile;
750 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
751 configFile = tempPath + "/" + WITH_OSP_XML;
753 configFile = tempPath + "/" + CONFIG_XML;
756 parser.Parse(configFile,
758 new RootParser<WidgetParser>(configInfo,
765 Catch(DPL::ZipInput::Exception::OpenFailed)
767 LogError("Failed to open widget package");
768 return ConfigParserData();
770 Catch(DPL::ZipInput::Exception::OpenFileFailed)
772 LogError("Failed to open config.xml file");
773 return ConfigParserData();
775 Catch(DPL::CopyFailed)
777 LogError("Failed to extract config.xml file");
778 return ConfigParserData();
780 Catch(DPL::FileInput::Exception::OpenFailed)
782 LogError("Failed to open config.xml file");
783 return ConfigParserData();
785 Catch(ElementParser::Exception::ParseError)
787 LogError("Failed to parse config.xml file");
788 return ConfigParserData();
790 Catch(DPL::ZipInput::Exception::SeekFileFailed)
792 LogError("Failed to seek widget archive - corrupted package?");
793 return ConfigParserData();
798 WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
799 const ConfigParserData &configInfo,
800 const WrtDB::TizenAppId &tizenId)
802 LogInfo("Checking up widget package for config.xml...");
803 OptionalWidgetVersion incomingVersion;
805 if (!configInfo.version.IsNull()) {
807 DPL::Optional<WidgetVersion>(
808 WidgetVersion(*configInfo.version));
811 WidgetDAOReadOnly dao(tizenId);
813 OptionalWidgetVersion optVersion;
814 DPL::OptionalString version = dao.getVersion();
815 if (!version.IsNull()) {
816 optVersion = OptionalWidgetVersion(WidgetVersion(*version));
819 return WidgetUpdateInfo(
825 void JobWidgetInstall::SendProgress()
827 using namespace PackageManager;
828 if (GetProgressFlag() != false) {
829 if (getInstallerStruct().progressCallback != NULL) {
830 // send progress signal of pkgmgr
831 std::ostringstream percent;
832 percent << static_cast<int>(GetProgressPercent());
833 getInstallerStruct().pkgmgrInterface->sendSignal(
837 LogDebug("Call widget install progressCallbak");
838 getInstallerStruct().progressCallback(
839 getInstallerStruct().userParam,
840 GetProgressPercent(),
841 GetProgressDescription());
846 void JobWidgetInstall::SendProgressIconPath(const std::string &path)
848 using namespace PackageManager;
849 if (GetProgressFlag() != false) {
850 if (getInstallerStruct().progressCallback != NULL) {
851 // send progress signal of pkgmgr
852 getInstallerStruct().pkgmgrInterface->sendSignal(
859 void JobWidgetInstall::SendFinishedSuccess()
861 using namespace PackageManager;
862 // TODO : sync should move to separate task.
865 if (INSTALL_LOCATION_TYPE_EXTERNAL == m_installerContext.locationType) {
866 if (m_installerContext.isUpdateMode) {
867 WidgetInstallToExtSingleton::Instance().postUpgrade(true);
869 WidgetInstallToExtSingleton::Instance().postInstallation(true);
871 WidgetInstallToExtSingleton::Instance().deinitialize();
874 // remove widget install information file
875 unlink(m_installerContext.installInfo.c_str());
878 JobWidgetInstall::displayWidgetInfo();
880 TizenAppId& tizenId = m_installerContext.widgetConfig.tzAppid;
882 // send signal of pkgmgr
883 getInstallerStruct().pkgmgrInterface->sendSignal(
887 LogDebug("Call widget install successfinishedCallback");
888 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
890 tizenId), Jobs::Exceptions::Success);
893 void JobWidgetInstall::SendFinishedFailure()
895 using namespace PackageManager;
896 // remove widget install information file
897 unlink(m_installerContext.installInfo.c_str());
899 LogError("Error number: " << m_exceptionCaught);
900 LogError("Message: " << m_exceptionMessage);
901 TizenAppId & tizenId = m_installerContext.widgetConfig.tzAppid;
903 LogDebug("Call widget install failure finishedCallback");
904 std::stringstream errorNum;
905 errorNum << m_exceptionCaught;
907 // send signal of pkgmgr
908 getInstallerStruct().pkgmgrInterface->sendSignal(
912 getInstallerStruct().pkgmgrInterface->sendSignal(
916 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
918 tizenId), m_exceptionCaught);
921 void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
923 m_exceptionCaught = static_cast<Jobs::Exceptions::Type>(e.getParam());
924 m_exceptionMessage = e.GetMessage();
927 void JobWidgetInstall::displayWidgetInfo()
929 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
931 std::ostringstream out;
932 WidgetLocalizedInfo localizedInfo =
933 W3CFileLocalization::getLocalizedInfo(dao.getTzAppId());
936 "===================================== INSTALLED WIDGET INFO =========" \
937 "============================";
938 out << std::endl << "Name: " << localizedInfo.name;
939 out << std::endl << "AppId: " << dao.getTzAppId();
940 WidgetSize size = dao.getPreferredSize();
941 out << std::endl << "Width: " << size.width;
942 out << std::endl << "Height: " << size.height;
943 out << std::endl << "Start File: " <<
944 W3CFileLocalization::getStartFile(dao.getTzAppId());
945 out << std::endl << "Version: " << dao.getVersion();
946 out << std::endl << "Licence: " <<
947 localizedInfo.license;
948 out << std::endl << "Licence Href: " <<
949 localizedInfo.licenseHref;
950 out << std::endl << "Description: " <<
951 localizedInfo.description;
952 out << std::endl << "Widget Id: " << dao.getGUID();
953 out << std::endl << "Widget recognized: " << dao.isRecognized();
954 out << std::endl << "Widget distributor signed: " <<
955 dao.isDistributorSigned();
956 out << std::endl << "Widget trusted: " << dao.isTrusted();
958 OptionalWidgetIcon icon = W3CFileLocalization::getIcon(dao.getTzAppId());
959 DPL::OptionalString iconSrc =
960 !!icon ? icon->src : DPL::OptionalString::Null;
961 out << std::endl << "Icon: " << iconSrc;
963 out << std::endl << "Preferences:";
965 PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList();
968 out << std::endl << " Key: " <<
970 out << std::endl << " Readonly: " <<
975 out << std::endl << "Features:";
977 WidgetFeatureSet list = dao.getFeaturesList();
980 out << std::endl << " Name: " << it->name;
989 WrtDB::PackagingType JobWidgetInstall::checkPackageType(
990 const std::string &widgetSource,
991 const std::string &tempPath)
993 // Check installation type (direcotory/ or config.xml or widget.wgt)
994 if (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY ||
995 m_jobStruct.m_installMode == InstallMode::REINSTALL_MODE_DIRECTORY)
997 LogDebug("Install directly from directory");
998 return PKG_TYPE_DIRECTORY_WEB_APP;
1000 if (hasExtension(widgetSource, XML_EXTENSION)) {
1001 LogInfo("Hosted app installation");
1002 return PKG_TYPE_HOSTED_WEB_APP;
1006 std::string configFile = tempPath + "/" + CONFIG_XML;
1007 if (WrtUtilFileExists(configFile)) {
1008 return PKG_TYPE_NOMAL_WEB_APP;
1011 configFile = tempPath + "/" + WITH_OSP_XML;
1012 if (WrtUtilFileExists(configFile)) {
1013 return PKG_TYPE_HYBRID_WEB_APP;
1016 std::unique_ptr<DPL::ZipInput> zipFile;
1021 zipFile.reset(new DPL::ZipInput(widgetSource));
1023 Catch(DPL::ZipInput::Exception::OpenFailed)
1025 LogDebug("Failed to open widget package");
1026 return PKG_TYPE_UNKNOWN;
1028 Catch(DPL::ZipInput::Exception::SeekFileFailed)
1030 LogError("Failed to seek widget package file");
1031 return PKG_TYPE_UNKNOWN;
1036 // Open config.xml file in package root
1037 std::unique_ptr<DPL::ZipInput::File> configFile(
1038 zipFile->OpenFile(CONFIG_XML));
1039 return PKG_TYPE_NOMAL_WEB_APP;
1041 Catch(DPL::ZipInput::Exception::OpenFileFailed)
1043 LogDebug("Could not find config.xml");
1048 // Open config.xml file in package root
1049 std::unique_ptr<DPL::ZipInput::File> configFile(
1050 zipFile->OpenFile(WITH_OSP_XML));
1052 return PKG_TYPE_HYBRID_WEB_APP;
1054 Catch(DPL::ZipInput::Exception::OpenFileFailed)
1056 LogDebug("Could not find wgt/config.xml");
1057 return PKG_TYPE_UNKNOWN;
1061 return PKG_TYPE_UNKNOWN;
1064 void JobWidgetInstall::setApplicationType(
1065 const WrtDB::ConfigParserData &configInfo)
1067 FOREACH(iterator, configInfo.nameSpaces) {
1068 LogInfo("namespace = [" << *iterator << "]");
1069 AppType currentAppType = APP_TYPE_UNKNOWN;
1071 if (*iterator == ConfigurationNamespace::W3CWidgetNamespaceName) {
1075 ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement ||
1077 ConfigurationNamespace::WacWidgetNamespaceName)
1079 currentAppType = APP_TYPE_WAC20;
1080 } else if (*iterator ==
1081 ConfigurationNamespace::TizenWebAppNamespaceName)
1083 currentAppType = APP_TYPE_TIZENWEBAPP;
1086 if (m_installerContext.widgetConfig.webAppType ==
1089 m_installerContext.widgetConfig.webAppType = currentAppType;
1090 } else if (m_installerContext.widgetConfig.webAppType ==
1095 ThrowMsg(Exceptions::WidgetConfigFileInvalid,
1096 "Config.xml has more than one namespace");
1100 // If there is no define, type set to WAC 2.0
1101 if (m_installerContext.widgetConfig.webAppType == APP_TYPE_UNKNOWN) {
1102 m_installerContext.widgetConfig.webAppType = APP_TYPE_WAC20;
1105 LogInfo("type = [" <<
1106 m_installerContext.widgetConfig.webAppType.getApptypeToString() <<
1110 bool JobWidgetInstall::detectResourceEncryption(
1111 const WrtDB::ConfigParserData &configData)
1113 FOREACH(it, configData.settingsList)
1115 if (it->m_name == SETTING_VALUE_ENCRYPTION &&
1116 it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE)
1118 LogDebug("resource need encryption");
1125 void JobWidgetInstall::setInstallLocationType(
1127 WrtDB::ConfigParserData &
1130 m_installerContext.locationType = INSTALL_LOCATION_TYPE_NOMAL;
1132 if (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_PRELOAD) {
1133 m_installerContext.locationType =
1134 INSTALL_LOCATION_TYPE_PRELOAD;
1136 FOREACH(it, configData.settingsList)
1138 if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME &&
1140 SETTING_VALUE_INSTALLTOEXT_PREPER_EXT)
1142 LogDebug("This widget will be installed to sd card");
1143 m_installerContext.locationType =
1144 INSTALL_LOCATION_TYPE_EXTERNAL;
1150 bool JobWidgetInstall::isDRMWidget(std::string /*widgetPath*/)
1156 bool JobWidgetInstall::DecryptDRMWidget(std::string /*widgetPath*/,
1157 std::string /*destPath*/)
1162 } //namespace WidgetInstall