2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file job_widget_install.cpp
18 * @author Radoslaw Wicik r.wicik@samsung.com
19 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
21 * @brief Implementation file for main installer task
31 #include <dpl/noncopyable.h>
32 #include <dpl/abstract_waitable_input_adapter.h>
33 #include <dpl/abstract_waitable_output_adapter.h>
34 #include <dpl/zip_input.h>
35 #include <dpl/binary_queue.h>
37 #include <dpl/assert.h>
38 #include <dpl/sstream.h>
39 #include <dpl/file_input.h>
40 #include <dpl/utils/wrt_utility.h>
41 #include <dpl/wrt-dao-ro/common_dao_types.h>
42 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
43 #include <dpl/wrt-dao-ro/global_config.h>
44 #include <dpl/wrt-dao-ro/config_parser_data.h>
45 #include <dpl/wrt-dao-rw/global_dao.h> // TODO remove
46 #include <dpl/localization/w3c_file_localization.h>
48 #include <libiriwrapper.h>
49 #include <pkg-manager/pkgmgr_signal.h>
50 #include <app_manager.h>
52 #include "root_parser.h"
53 #include "widget_parser.h"
54 #include "parser_runner.h"
55 #include <widget_install/job_widget_install.h>
56 #include <widget_install/task_certify.h>
57 #include <widget_install/task_widget_config.h>
58 #include <widget_install/task_file_manipulation.h>
59 #include <widget_install/task_ace_check.h>
60 #include <widget_install/task_smack.h>
61 #include <widget_install/task_manifest_file.h>
62 #include <widget_install/task_prepare_files.h>
63 #include <widget_install/task_recovery.h>
64 #include <widget_install/task_install_ospsvc.h>
65 #include <widget_install/task_update_files.h>
66 #include <widget_install/task_database.h>
67 #include <widget_install/task_remove_backup.h>
68 #include <widget_install/task_encrypt_resource.h>
69 #include <widget_install/task_certificates.h>
70 #include <widget_install/task_unzip.h>
71 #include <widget_install/task_commons.h>
72 #include <widget_install/task_prepare_reinstall.h>
74 #include <widget_install/widget_install_errors.h>
75 #include <widget_install/widget_install_context.h>
76 #include <widget_install_to_external.h>
78 using namespace WrtDB;
79 using namespace Jobs::Exceptions;
81 namespace // anonymous
83 const char * const CONFIG_XML = "config.xml";
84 const char * const WITH_OSP_XML = "res/wgt/config.xml";
86 //allowed: a-z, A-Z, 0-9
87 const char* REG_TIZENID_PATTERN = "^[a-zA-Z0-9]{10}.{1,}$";
88 const char* REG_NAME_PATTERN = "^[a-zA-Z0-9._-]{1,}$";
89 const size_t PACKAGE_ID_LENGTH = 10;
91 static const DPL::String SETTING_VALUE_ENCRYPTION = L"encryption";
92 static const DPL::String SETTING_VALUE_ENCRYPTION_ENABLE = L"enable";
93 const DPL::String SETTING_VALUE_INSTALLTOEXT_NAME =
95 const DPL::String SETTING_VALUE_INSTALLTOEXT_PREPER_EXT =
98 const std::string XML_EXTENSION = ".xml";
100 bool hasExtension(const std::string& filename, const std::string& extension)
102 LogDebug("Looking for extension " << extension << " in: " << filename);
103 size_t fileLen = filename.length();
104 size_t extLen = extension.length();
105 if (fileLen < extLen) {
106 LogError("Filename " << filename << " is shorter than extension "
110 return (0 == filename.compare(fileLen - extLen, extLen, extension));
112 } // namespace anonymous
115 namespace WidgetInstall {
116 class InstallerTaskFail :
117 public DPL::TaskDecl<InstallerTaskFail>
120 ConfigureResult m_result;
124 if (m_result == ConfigureResult::Deferred) {
125 ThrowMsg(Jobs::WidgetInstall::Exceptions::Deferred,
126 "widget installation or update deferred!");
127 } else if (m_result == ConfigureResult::Failed_InvalidConfig) {
128 ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid,
130 } else if (m_result == ConfigureResult::Failed_LowerVersion) {
131 ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageLowerVersion,
132 "package version is lower than installed version");
133 } else if (m_result == ConfigureResult::Failed_AlreadyInstalled) {
134 ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageAlreadyInstalled,
135 "package is already installed");
136 } else if (m_result == ConfigureResult::Failed_WidgetRunning) {
137 ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError,
138 "widget is running");
139 } else if (m_result == ConfigureResult::Failed_DrmError) {
140 ThrowMsg(Jobs::WidgetInstall::Exceptions::DRMFailed,
143 ThrowMsg(Jobs::WidgetInstall::Exceptions::NotAllowed,
144 "widget installation or update not allowed!");
149 InstallerTaskFail(ConfigureResult result) :
150 DPL::TaskDecl<InstallerTaskFail>(this),
153 AddStep(&InstallerTaskFail::StepFail);
157 JobWidgetInstall::JobWidgetInstall(
158 std::string const &widgetPath,
159 const WidgetInstallationStruct &
162 JobContextBase<WidgetInstallationStruct>(installerStruct),
163 m_exceptionCaught(Jobs::Exceptions::Success)
165 m_installerContext.mode = m_jobStruct.m_installMode;
166 ConfigureResult result = PrePareInstallation(widgetPath);
168 if (result == ConfigureResult::Ok) {
169 LogInfo("Configure installation succeeded");
170 m_installerContext.job->SetProgressFlag(true);
172 AddTask(new TaskRecovery(m_installerContext));
174 // Create installation tasks
175 if (m_installerContext.widgetConfig.packagingType !=
176 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
177 m_installerContext.widgetConfig.packagingType !=
178 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
181 AddTask(new TaskUnzip(m_installerContext));
184 AddTask(new TaskWidgetConfig(m_installerContext));
185 if (m_installerContext.widgetConfig.packagingType ==
186 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
188 AddTask(new TaskPrepareFiles(m_installerContext));
190 AddTask(new TaskCertify(m_installerContext));
191 if (m_needEncryption) {
192 AddTask(new TaskEncryptResource(m_installerContext));
195 AddTask(new TaskFileManipulation(m_installerContext));
197 AddTask(new TaskManifestFile(m_installerContext));
198 if (m_installerContext.widgetConfig.packagingType ==
199 PKG_TYPE_HYBRID_WEB_APP)
201 AddTask(new TaskInstallOspsvc(m_installerContext));
203 AddTask(new TaskCertificates(m_installerContext));
204 AddTask(new TaskDatabase(m_installerContext));
205 AddTask(new TaskAceCheck(m_installerContext));
206 AddTask(new TaskSmack(m_installerContext));
207 } else if (result == ConfigureResult::Updated) {
208 LogInfo("Configure installation updated");
209 LogInfo("Widget Update");
210 m_installerContext.job->SetProgressFlag(true);
212 if (m_installerContext.mode.command ==
213 InstallMode::Command::REINSTALL)
215 AddTask(new TaskPrepareReinstall(m_installerContext));
218 if (m_installerContext.widgetConfig.packagingType !=
219 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
220 m_installerContext.widgetConfig.packagingType !=
221 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
224 AddTask(new TaskUnzip(m_installerContext));
227 AddTask(new TaskWidgetConfig(m_installerContext));
229 if (m_installerContext.widgetConfig.packagingType ==
230 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
232 AddTask(new TaskPrepareFiles(m_installerContext));
235 AddTask(new TaskCertify(m_installerContext));
236 if (m_needEncryption) {
237 AddTask(new TaskEncryptResource(m_installerContext));
240 if (m_installerContext.widgetConfig.packagingType !=
241 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
243 AddTask(new TaskUpdateFiles(m_installerContext));
246 AddTask(new TaskManifestFile(m_installerContext));
247 if (m_installerContext.widgetConfig.packagingType ==
248 PKG_TYPE_HYBRID_WEB_APP)
250 AddTask(new TaskInstallOspsvc(m_installerContext));
252 if (m_installerContext.widgetConfig.packagingType !=
253 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
255 AddTask(new TaskRemoveBackupFiles(m_installerContext));
257 AddTask(new TaskDatabase(m_installerContext));
258 AddTask(new TaskAceCheck(m_installerContext));
259 //TODO: remove widgetHandle from this task and move before database task
260 // by now widget handle is needed in ace check
261 // Any error in acecheck while update will break widget
262 AddTask(new TaskSmack(m_installerContext));
263 } else if (result == ConfigureResult::Deferred) {
264 // Installation is deferred
265 LogInfo("Configure installation deferred");
267 AddTask(new InstallerTaskFail(result));
268 } else if (result >= ConfigureResult::Failed &&
269 result <= ConfigureResult::Failed_DrmError) {
270 // Installation is not allowed to proceed due to widget update policy
271 LogWarning("Configure installation failed!");
273 AddTask(new InstallerTaskFail(result));
275 Assert(false && "Invalid configure result!");
279 ConfigureResult JobWidgetInstall::PrePareInstallation(
280 const std::string &widgetPath)
282 ConfigureResult result;
283 m_needEncryption = false;
288 if (m_installerContext.mode.extension == InstallMode::ExtensionType::DIR) {
289 std::ostringstream tempPathBuilder;
290 tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath();
291 tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath();
292 tempPathBuilder << "/";
293 tempPathBuilder << widgetPath;
294 tempDir = tempPathBuilder.str();;
297 Jobs::WidgetInstall::createTempPath(
298 m_installerContext.mode.installTime ==
299 InstallMode::InstallTime::PRELOAD);
302 m_isDRM = isDRMWidget(widgetPath);
303 if (true == m_isDRM) {
304 LogDebug("decrypt DRM widget");
305 if (DecryptDRMWidget(widgetPath, tempDir)) {
306 LogDebug("Failed decrypt DRM widget");
307 return ConfigureResult::Failed_DrmError;
311 LogDebug("widgetPath:" << widgetPath);
313 m_installerContext.widgetConfig.packagingType =
314 checkPackageType(widgetPath, tempDir);
315 ConfigParserData configData = getWidgetDataFromXML(
318 m_installerContext.widgetConfig.packagingType,
320 m_installerContext.mode.command == InstallMode::Command::REINSTALL);
321 LogDebug("widget packaging type : " <<
322 m_installerContext.widgetConfig.packagingType.pkgType);
324 setTizenId(configData);
325 setApplicationType(configData);
326 m_needEncryption = detectResourceEncryption(configData);
327 setInstallLocationType(configData);
329 // Configure installation
330 result = ConfigureInstallation(widgetPath, configData, tempDir);
332 Catch(Exceptions::ExtractFileFailed)
334 LogError("Failed to create temporary path for widget");
335 result = ConfigureResult::Failed_InvalidConfig;
341 void JobWidgetInstall::setTizenId(
342 const WrtDB::ConfigParserData &configInfo)
344 bool shouldMakeAppid = false;
345 using namespace PackageManager;
346 if (!!configInfo.tizenAppId) {
347 LogDebug("Setting tizenAppId provided in config.xml: " <<
348 configInfo.tizenAppId);
350 m_installerContext.widgetConfig.tzAppid = *configInfo.tizenAppId;
352 if (!!configInfo.tizenPkgId) {
353 LogDebug("Setting tizenPkgId provided in config.xml: " <<
354 configInfo.tizenPkgId);
356 m_installerContext.widgetConfig.tzPkgid = *configInfo.tizenPkgId;
358 DPL::String appid = *configInfo.tizenAppId;
359 if (appid.length() > PACKAGE_ID_LENGTH) {
360 m_installerContext.widgetConfig.tzPkgid =
361 appid.substr(0, PACKAGE_ID_LENGTH);
363 //old version appid only has 10byte random character is able to install for a while.
364 //this case appid equal pkgid.
365 m_installerContext.widgetConfig.tzPkgid =
366 *configInfo.tizenAppId;
367 shouldMakeAppid = true;
371 shouldMakeAppid = true;
372 TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId();
373 LogDebug("Checking if pkg id is unique");
375 if (!validateTizenPackageID(pkgId)) {
376 //path exist, chose another one
377 pkgId = WidgetDAOReadOnly::generatePkgId();
382 m_installerContext.widgetConfig.tzPkgid = pkgId;
383 LogInfo("tizen_id name was generated by WRT: " <<
384 m_installerContext.widgetConfig.tzPkgid);
387 if (shouldMakeAppid == true) {
388 DPL::OptionalString name;
389 DPL::OptionalString defaultLocale = configInfo.defaultlocale;
391 FOREACH(localizedData, configInfo.localizedDataSet)
393 Locale i = localizedData->first;
394 if (!!defaultLocale) {
395 if (defaultLocale == i) {
396 name = localizedData->second.name;
400 name = localizedData->second.name;
405 if (regcomp(®x, REG_NAME_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
406 LogDebug("Regcomp failed");
409 LogDebug("Name : " << name);
410 if (!name || (regexec(®x, DPL::ToUTF8String(*name).c_str(),
411 static_cast<size_t>(0), NULL, 0) != REG_NOERROR))
413 // TODO : generate name move to wrt-commons
414 std::string allowedString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
415 std::ostringstream genName;
417 gettimeofday(&tv, NULL);
418 unsigned int seed = time(NULL) + tv.tv_usec;
420 genName << "_" << allowedString[rand_r(&seed) % allowedString.length()];
421 name = DPL::FromUTF8String(genName.str());
422 LogDebug("name was generated by WRT");
425 LogDebug("Name : " << name);
426 std::ostringstream genid;
427 genid << m_installerContext.widgetConfig.tzPkgid << "." << name;
428 LogDebug("tizen appid was generated by WRT : " << genid.str());
430 DPL::OptionalString appid = DPL::FromUTF8String(genid.str());
431 NormalizeAndTrimSpaceString(appid);
432 m_installerContext.widgetConfig.tzAppid = *appid;
435 // send start signal of pkgmgr
436 getInstallerStruct().pkgmgrInterface->setPkgname(DPL::ToUTF8String(
440 LogInfo("Tizen App Id : " << m_installerContext.widgetConfig.tzAppid);
441 LogInfo("Tizen Pkg Id : " << m_installerContext.widgetConfig.tzPkgid);
442 LogInfo("W3C Widget GUID : " << m_installerContext.widgetConfig.guid);
445 void JobWidgetInstall::configureWidgetLocation(const std::string & widgetPath,
446 const std::string& tempPath)
448 m_installerContext.locations =
449 WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
451 widgetPath, tempPath,
452 m_installerContext.widgetConfig.packagingType,
453 m_installerContext.locationType);
454 m_installerContext.locations->registerAppid(
455 DPL::ToUTF8String(m_installerContext.widgetConfig.tzAppid));
457 LogInfo("widgetSource " << widgetPath);
460 ConfigureResult JobWidgetInstall::ConfigureInstallation(
461 const std::string &widgetSource,
462 const WrtDB::ConfigParserData &configData,
463 const std::string &tempPath)
465 ConfigureResult result = ConfigureResult::Failed;
466 WidgetUpdateInfo update;
468 // checking installed web application
470 // checking existing application is installed
471 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
472 // no excpetion means, it isn't update mode
473 getInstallerStruct().pkgmgrInterface->sendSignal(
475 PKGMGR_START_UPDATE);
477 update = detectWidgetUpdate(configData,
478 m_installerContext.widgetConfig.tzAppid);
479 result = checkWidgetUpdate(update);
480 if (result != ConfigureResult::Updated) {
481 // Already installed TizenAppId. return failed
482 return ConfigureResult::Failed_AlreadyInstalled;
484 m_installerContext.isUpdateMode = true;
486 Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
487 result = ConfigureResult::Ok;
488 getInstallerStruct().pkgmgrInterface->sendSignal(
490 PKGMGR_START_INSTALL);
491 m_installerContext.isUpdateMode = false;
493 if (!validateTizenApplicationID(
494 m_installerContext.widgetConfig.tzAppid))
496 LogError("tizen application ID is already used");
497 return ConfigureResult::Failed_InvalidConfig;
499 if (!validateTizenPackageID(m_installerContext.widgetConfig.tzPkgid)) {
500 LogError("tizen package ID is already used");
501 return ConfigureResult::Failed_AlreadyInstalled;
505 configureWidgetLocation(widgetSource, tempPath);
507 // Init installer context
508 m_installerContext.installStep = InstallerContext::INSTALL_START;
509 m_installerContext.job = this;
510 m_installerContext.widgetConfig.shareHref = std::string();
515 bool JobWidgetInstall::validateTizenApplicationID(
516 const WrtDB::TizenAppId &tizenAppId)
518 LogInfo("tizen application ID = [" << tizenAppId << "]");
521 if (regcomp(®, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
522 LogDebug("Regcomp failed");
525 if (regexec(®, DPL::ToUTF8String(tizenAppId).c_str(), 0, NULL, 0)
535 bool JobWidgetInstall::validateTizenPackageID(
536 const WrtDB::TizenPkgId &tizenPkgId)
538 std::string pkgId = DPL::ToUTF8String(tizenPkgId);
540 std::string installPath =
541 std::string(GlobalConfig::GetUserInstalledWidgetPath()) +
543 std::string preinstallPath =
544 std::string(GlobalConfig::GetUserPreloadedWidgetPath()) +
548 if ((stat(installPath.c_str(), &dirStat) == 0) ||
549 (stat(preinstallPath.c_str(), &dirStat) == 0))
556 ConfigureResult JobWidgetInstall::checkWidgetUpdate(
557 const WidgetUpdateInfo &update)
559 LogInfo("incoming version = '" << update.incomingVersion);
560 LogInfo("Tizen AppID = " << update.tzAppId);
562 if (update.existingVersion.IsNull() || update.incomingVersion.IsNull()) {
563 return ConfigureResult::Failed;
566 // Check running state
567 bool isRunning = false;
569 app_manager_is_running(DPL::ToUTF8String(update.tzAppId).c_str(),
571 if (APP_MANAGER_ERROR_NONE != ret) {
572 LogError("Fail to get running state");
573 return ConfigureResult::Failed_WidgetRunning;
576 if (true == isRunning) {
577 // get app_context for running application
578 // app_context must be released with app_context_destroy
579 app_context_h appCtx = NULL;
581 app_manager_get_app_context(
582 DPL::ToUTF8String(update.tzAppId).c_str(),
584 if (APP_MANAGER_ERROR_NONE != ret) {
585 LogError("Fail to get app_context");
586 return ConfigureResult::Failed_WidgetRunning;
589 // terminate app_context_h
590 ret = app_manager_terminate_app(appCtx);
591 if (APP_MANAGER_ERROR_NONE != ret) {
592 LogError("Fail to terminate running application");
593 app_context_destroy(appCtx);
594 return ConfigureResult::Failed_WidgetRunning;
596 app_context_destroy(appCtx);
597 // app_manager_terminate_app isn't sync API
598 // wait until application isn't running (50ms * 100)
599 bool isStillRunning = true;
600 int checkingloop = 100;
601 struct timespec duration = { 0, 50 * 1000 * 1000 };
602 while (--checkingloop >= 0) {
603 nanosleep(&duration, NULL);
605 app_manager_is_running(
606 DPL::ToUTF8String(update.tzAppId).c_str(),
608 if (APP_MANAGER_ERROR_NONE != ret) {
609 LogError("Fail to get running state");
610 return ConfigureResult::Failed_WidgetRunning;
612 if (!isStillRunning) {
616 if (isStillRunning) {
617 LogError("Fail to terminate running application");
618 return ConfigureResult::Failed_WidgetRunning;
620 LogInfo("terminate application");
624 m_installerContext.widgetConfig.tzAppid = update.tzAppId;
626 if (isUpperVersion(update.existingVersion, update.incomingVersion) ||
627 m_installerContext.mode.extension == InstallMode::ExtensionType::DIR)
629 LogInfo("Whether widget policy allow proceed ok");
630 return ConfigureResult::Updated;
632 return ConfigureResult::Failed_LowerVersion;
635 return ConfigureResult::Failed;
638 bool JobWidgetInstall::isUpperVersion(
639 const OptionalWidgetVersion &existingVersion,
640 const OptionalWidgetVersion &incomingVersion)
642 LogInfo("Existing version = '" << *existingVersion);
643 LogInfo("Incoming version = '" << *incomingVersion);
645 if (!existingVersion && !incomingVersion) {
647 } else if (!existingVersion && !!incomingVersion) {
649 } else if (!!existingVersion && !incomingVersion) {
652 if (!existingVersion->IsWac() || !incomingVersion->IsWac()) {
655 if (*incomingVersion == *existingVersion) {
657 } else if (*incomingVersion > *existingVersion) {
666 ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
667 const std::string &widgetSource,
668 const std::string &tempPath,
669 WrtDB::PackagingType pkgType,
675 ConfigParserData configInfo;
679 if (pkgType == PKG_TYPE_HOSTED_WEB_APP) {
680 parser.Parse(widgetSource,
682 new RootParser<WidgetParser>(configInfo,
683 DPL::FromUTF32String(
685 } else if (pkgType == PKG_TYPE_DIRECTORY_WEB_APP) {
686 std::string configPath;
687 configPath = tempPath;
689 configPath += WITH_OSP_XML;
692 // checking RDS data directory
693 if (access(configPath.c_str(), F_OK) != 0) {
694 std::string tzAppId =
695 widgetSource.substr(widgetSource.find_last_of("/")+1);
696 WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTzAppId(DPL::FromUTF8String(tzAppId)));
697 configPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath());
699 configPath += WITH_OSP_XML;
702 parser.Parse(configPath,
704 new RootParser<WidgetParser>(
706 DPL::FromUTF32String(L"widget"))));
709 std::unique_ptr<DPL::ZipInput> zipFile(
710 new DPL::ZipInput(widgetSource));
712 std::unique_ptr<DPL::ZipInput::File> configFile;
714 // Open config.xml file
715 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
716 configFile.reset(zipFile->OpenFile(WITH_OSP_XML));
718 configFile.reset(zipFile->OpenFile(CONFIG_XML));
722 DPL::BinaryQueue buffer;
723 DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
724 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
725 DPL::Copy(&inputAdapter, &outputAdapter);
726 parser.Parse(&buffer,
728 new RootParser<WidgetParser>(configInfo,
734 std::string configFile;
735 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
736 configFile = tempPath + "/" + WITH_OSP_XML;
738 configFile = tempPath + "/" + CONFIG_XML;
741 parser.Parse(configFile,
743 new RootParser<WidgetParser>(configInfo,
750 Catch(DPL::ZipInput::Exception::OpenFailed)
752 LogError("Failed to open widget package");
753 return ConfigParserData();
755 Catch(DPL::ZipInput::Exception::OpenFileFailed)
757 LogError("Failed to open config.xml file");
758 return ConfigParserData();
760 Catch(DPL::CopyFailed)
762 LogError("Failed to extract config.xml file");
763 return ConfigParserData();
765 Catch(DPL::FileInput::Exception::OpenFailed)
767 LogError("Failed to open config.xml file");
768 return ConfigParserData();
770 Catch(ElementParser::Exception::ParseError)
772 LogError("Failed to parse config.xml file");
773 return ConfigParserData();
775 Catch(DPL::ZipInput::Exception::SeekFileFailed)
777 LogError("Failed to seek widget archive - corrupted package?");
778 return ConfigParserData();
783 WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
784 const ConfigParserData &configInfo,
785 const WrtDB::TizenAppId &tizenId)
787 LogInfo("Checking up widget package for config.xml...");
788 OptionalWidgetVersion incomingVersion;
790 if (!configInfo.version.IsNull()) {
792 DPL::Optional<WidgetVersion>(
793 WidgetVersion(*configInfo.version));
796 WidgetDAOReadOnly dao(tizenId);
798 OptionalWidgetVersion optVersion;
799 DPL::OptionalString version = dao.getVersion();
800 if (!version.IsNull()) {
801 optVersion = OptionalWidgetVersion(WidgetVersion(*version));
804 return WidgetUpdateInfo(
810 void JobWidgetInstall::SendProgress()
812 using namespace PackageManager;
813 if (GetProgressFlag() != false) {
814 if (getInstallerStruct().progressCallback != NULL) {
815 // send progress signal of pkgmgr
816 std::ostringstream percent;
817 percent << static_cast<int>(GetProgressPercent());
818 getInstallerStruct().pkgmgrInterface->sendSignal(
822 LogDebug("Call widget install progressCallbak");
823 getInstallerStruct().progressCallback(
824 getInstallerStruct().userParam,
825 GetProgressPercent(),
826 GetProgressDescription());
831 void JobWidgetInstall::SendProgressIconPath(const std::string &path)
833 using namespace PackageManager;
834 if (GetProgressFlag() != false) {
835 if (getInstallerStruct().progressCallback != NULL) {
836 // send progress signal of pkgmgr
837 getInstallerStruct().pkgmgrInterface->sendSignal(
844 void JobWidgetInstall::SendFinishedSuccess()
846 using namespace PackageManager;
847 // TODO : sync should move to separate task.
850 if (INSTALL_LOCATION_TYPE_EXTERNAL == m_installerContext.locationType) {
851 if (m_installerContext.isUpdateMode) {
852 WidgetInstallToExtSingleton::Instance().postUpgrade(true);
854 WidgetInstallToExtSingleton::Instance().postInstallation(true);
856 WidgetInstallToExtSingleton::Instance().deinitialize();
859 // remove widget install information file
860 unlink(m_installerContext.installInfo.c_str());
863 JobWidgetInstall::displayWidgetInfo();
865 TizenAppId& tizenId = m_installerContext.widgetConfig.tzAppid;
867 // send signal of pkgmgr
868 getInstallerStruct().pkgmgrInterface->sendSignal(
872 LogDebug("Call widget install successfinishedCallback");
873 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
875 tizenId), Jobs::Exceptions::Success);
878 void JobWidgetInstall::SendFinishedFailure()
880 using namespace PackageManager;
881 // remove widget install information file
882 unlink(m_installerContext.installInfo.c_str());
884 LogError("Error number: " << m_exceptionCaught);
885 LogError("Message: " << m_exceptionMessage);
886 TizenAppId & tizenId = m_installerContext.widgetConfig.tzAppid;
888 LogDebug("Call widget install failure finishedCallback");
889 std::stringstream errorNum;
890 errorNum << m_exceptionCaught;
892 // send signal of pkgmgr
893 getInstallerStruct().pkgmgrInterface->sendSignal(
897 getInstallerStruct().pkgmgrInterface->sendSignal(
901 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
903 tizenId), m_exceptionCaught);
906 void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
908 m_exceptionCaught = static_cast<Jobs::Exceptions::Type>(e.getParam());
909 m_exceptionMessage = e.GetMessage();
912 void JobWidgetInstall::displayWidgetInfo()
914 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
916 std::ostringstream out;
917 WidgetLocalizedInfo localizedInfo =
918 W3CFileLocalization::getLocalizedInfo(dao.getTzAppId());
921 "===================================== INSTALLED WIDGET INFO =========" \
922 "============================";
923 out << std::endl << "Name: " << localizedInfo.name;
924 out << std::endl << "AppId: " << dao.getTzAppId();
925 WidgetSize size = dao.getPreferredSize();
926 out << std::endl << "Width: " << size.width;
927 out << std::endl << "Height: " << size.height;
928 out << std::endl << "Start File: " <<
929 W3CFileLocalization::getStartFile(dao.getTzAppId());
930 out << std::endl << "Version: " << dao.getVersion();
931 out << std::endl << "Licence: " <<
932 localizedInfo.license;
933 out << std::endl << "Licence Href: " <<
934 localizedInfo.licenseHref;
935 out << std::endl << "Description: " <<
936 localizedInfo.description;
937 out << std::endl << "Widget Id: " << dao.getGUID();
938 out << std::endl << "Widget recognized: " << dao.isRecognized();
939 out << std::endl << "Widget distributor signed: " <<
940 dao.isDistributorSigned();
941 out << std::endl << "Widget trusted: " << dao.isTrusted();
943 OptionalWidgetIcon icon = W3CFileLocalization::getIcon(dao.getTzAppId());
944 DPL::OptionalString iconSrc =
945 !!icon ? icon->src : DPL::OptionalString::Null;
946 out << std::endl << "Icon: " << iconSrc;
948 out << std::endl << "Preferences:";
950 PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList();
953 out << std::endl << " Key: " <<
955 out << std::endl << " Readonly: " <<
960 out << std::endl << "Features:";
962 WidgetFeatureSet list = dao.getFeaturesList();
965 out << std::endl << " Name: " << it->name;
974 WrtDB::PackagingType JobWidgetInstall::checkPackageType(
975 const std::string &widgetSource,
976 const std::string &tempPath)
978 // Check installation type (direcotory/ or config.xml or widget.wgt)
979 if (m_installerContext.mode.extension == InstallMode::ExtensionType::DIR) {
980 LogDebug("Install directly from directory");
981 return PKG_TYPE_DIRECTORY_WEB_APP;
983 if (hasExtension(widgetSource, XML_EXTENSION)) {
984 LogInfo("Hosted app installation");
985 return PKG_TYPE_HOSTED_WEB_APP;
989 std::string configFile = tempPath + "/" + CONFIG_XML;
990 if (WrtUtilFileExists(configFile)) {
991 return PKG_TYPE_NOMAL_WEB_APP;
994 configFile = tempPath + "/" + WITH_OSP_XML;
995 if (WrtUtilFileExists(configFile)) {
996 return PKG_TYPE_HYBRID_WEB_APP;
999 std::unique_ptr<DPL::ZipInput> zipFile;
1004 zipFile.reset(new DPL::ZipInput(widgetSource));
1006 Catch(DPL::ZipInput::Exception::OpenFailed)
1008 LogDebug("Failed to open widget package");
1009 return PKG_TYPE_UNKNOWN;
1011 Catch(DPL::ZipInput::Exception::SeekFileFailed)
1013 LogError("Failed to seek widget package file");
1014 return PKG_TYPE_UNKNOWN;
1019 // Open config.xml file in package root
1020 std::unique_ptr<DPL::ZipInput::File> configFile(
1021 zipFile->OpenFile(CONFIG_XML));
1022 return PKG_TYPE_NOMAL_WEB_APP;
1024 Catch(DPL::ZipInput::Exception::OpenFileFailed)
1026 LogDebug("Could not find config.xml");
1031 // Open config.xml file in package root
1032 std::unique_ptr<DPL::ZipInput::File> configFile(
1033 zipFile->OpenFile(WITH_OSP_XML));
1035 return PKG_TYPE_HYBRID_WEB_APP;
1037 Catch(DPL::ZipInput::Exception::OpenFileFailed)
1039 LogDebug("Could not find wgt/config.xml");
1040 return PKG_TYPE_UNKNOWN;
1044 return PKG_TYPE_UNKNOWN;
1047 void JobWidgetInstall::setApplicationType(
1048 const WrtDB::ConfigParserData &configInfo)
1050 FOREACH(iterator, configInfo.nameSpaces) {
1051 LogInfo("namespace = [" << *iterator << "]");
1052 AppType currentAppType = APP_TYPE_UNKNOWN;
1054 if (*iterator == ConfigurationNamespace::W3CWidgetNamespaceName) {
1058 ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement ||
1060 ConfigurationNamespace::WacWidgetNamespaceName)
1062 currentAppType = APP_TYPE_WAC20;
1063 } else if (*iterator ==
1064 ConfigurationNamespace::TizenWebAppNamespaceName)
1066 currentAppType = APP_TYPE_TIZENWEBAPP;
1069 if (m_installerContext.widgetConfig.webAppType ==
1072 m_installerContext.widgetConfig.webAppType = currentAppType;
1073 } else if (m_installerContext.widgetConfig.webAppType ==
1078 ThrowMsg(Exceptions::WidgetConfigFileInvalid,
1079 "Config.xml has more than one namespace");
1083 // If there is no define, type set to WAC 2.0
1084 if (m_installerContext.widgetConfig.webAppType == APP_TYPE_UNKNOWN) {
1085 m_installerContext.widgetConfig.webAppType = APP_TYPE_WAC20;
1088 LogInfo("type = [" <<
1089 m_installerContext.widgetConfig.webAppType.getApptypeToString() <<
1093 bool JobWidgetInstall::detectResourceEncryption(
1094 const WrtDB::ConfigParserData &configData)
1096 FOREACH(it, configData.settingsList)
1098 if (it->m_name == SETTING_VALUE_ENCRYPTION &&
1099 it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE)
1101 LogDebug("resource need encryption");
1108 void JobWidgetInstall::setInstallLocationType(
1110 WrtDB::ConfigParserData &
1113 m_installerContext.locationType = INSTALL_LOCATION_TYPE_NOMAL;
1115 if (m_installerContext.mode.installTime == InstallMode::InstallTime::PRELOAD) {
1116 m_installerContext.locationType =
1117 INSTALL_LOCATION_TYPE_PRELOAD;
1119 FOREACH(it, configData.settingsList)
1121 if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME &&
1123 SETTING_VALUE_INSTALLTOEXT_PREPER_EXT)
1125 LogDebug("This widget will be installed to sd card");
1126 m_installerContext.locationType =
1127 INSTALL_LOCATION_TYPE_EXTERNAL;
1133 bool JobWidgetInstall::isDRMWidget(std::string /*widgetPath*/)
1139 bool JobWidgetInstall::DecryptDRMWidget(std::string /*widgetPath*/,
1140 std::string /*destPath*/)
1145 } //namespace WidgetInstall