2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file job_widget_install.cpp
18 * @author Radoslaw Wicik r.wicik@samsung.com
19 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
21 * @brief Implementation file for main installer task
31 #include <dpl/noncopyable.h>
32 #include <dpl/abstract_waitable_input_adapter.h>
33 #include <dpl/abstract_waitable_output_adapter.h>
34 #include <dpl/zip_input.h>
35 #include <dpl/binary_queue.h>
37 #include <dpl/assert.h>
38 #include <dpl/sstream.h>
39 #include <dpl/file_input.h>
40 #include <dpl/utils/wrt_utility.h>
41 #include <dpl/wrt-dao-ro/common_dao_types.h>
42 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
43 #include <dpl/wrt-dao-ro/global_config.h>
44 #include <dpl/wrt-dao-ro/config_parser_data.h>
45 #include <dpl/wrt-dao-rw/global_dao.h> // TODO remove
46 #include <dpl/localization/w3c_file_localization.h>
48 #include <libiriwrapper.h>
49 #include <pkg-manager/pkgmgr_signal.h>
50 #include <app_manager.h>
52 #include "root_parser.h"
53 #include "widget_parser.h"
54 #include "parser_runner.h"
55 #include <widget_install/job_widget_install.h>
56 #include <widget_install/task_certify.h>
57 #include <widget_install/task_widget_config.h>
58 #include <widget_install/task_file_manipulation.h>
59 #include <widget_install/task_ace_check.h>
60 #include <widget_install/task_smack.h>
61 #include <widget_install/task_manifest_file.h>
62 #include <widget_install/task_prepare_files.h>
63 #include <widget_install/task_recovery.h>
64 #include <widget_install/task_install_ospsvc.h>
65 #include <widget_install/task_update_files.h>
66 #include <widget_install/task_database.h>
67 #include <widget_install/task_remove_backup.h>
68 #include <widget_install/task_encrypt_resource.h>
69 #include <widget_install/task_certificates.h>
70 #include <widget_install/task_unzip.h>
71 #include <widget_install/task_commons.h>
72 #include <widget_install/task_plugins_copy.h>
73 #include <widget_install/task_prepare_reinstall.h>
75 #include <widget_install/widget_install_errors.h>
76 #include <widget_install/widget_install_context.h>
77 #include <widget_install_to_external.h>
79 using namespace WrtDB;
80 using namespace Jobs::Exceptions;
82 namespace // anonymous
84 const char * const CONFIG_XML = "config.xml";
85 const char * const WITH_OSP_XML = "res/wgt/config.xml";
87 //allowed: a-z, A-Z, 0-9
88 const char* REG_TIZENID_PATTERN = "^[a-zA-Z0-9]{10}.{1,}$";
89 const char* REG_NAME_PATTERN = "^[a-zA-Z0-9._-]{1,}$";
90 const size_t PACKAGE_ID_LENGTH = 10;
92 static const DPL::String SETTING_VALUE_ENCRYPTION = L"encryption";
93 static const DPL::String SETTING_VALUE_ENCRYPTION_ENABLE = L"enable";
94 const DPL::String SETTING_VALUE_INSTALLTOEXT_NAME =
96 const DPL::String SETTING_VALUE_INSTALLTOEXT_PREPER_EXT =
99 const std::string XML_EXTENSION = ".xml";
101 bool hasExtension(const std::string& filename, const std::string& extension)
103 LogDebug("Looking for extension " << extension << " in: " << filename);
104 size_t fileLen = filename.length();
105 size_t extLen = extension.length();
106 if (fileLen < extLen) {
107 LogError("Filename " << filename << " is shorter than extension "
111 return (0 == filename.compare(fileLen - extLen, extLen, extension));
113 } // namespace anonymous
116 namespace WidgetInstall {
117 class InstallerTaskFail :
118 public DPL::TaskDecl<InstallerTaskFail>
121 ConfigureResult m_result;
125 if (m_result == ConfigureResult::Deferred) {
126 ThrowMsg(Jobs::WidgetInstall::Exceptions::Deferred,
127 "widget installation or update deferred!");
128 } else if (m_result == ConfigureResult::Failed_InvalidConfig) {
129 ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid,
131 } else if (m_result == ConfigureResult::Failed_LowerVersion) {
132 ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageLowerVersion,
133 "package version is lower than installed version");
134 } else if (m_result == ConfigureResult::Failed_AlreadyInstalled) {
135 ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageAlreadyInstalled,
136 "package is already installed");
137 } else if (m_result == ConfigureResult::Failed_WidgetRunning) {
138 ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError,
139 "widget is running");
140 } else if (m_result == ConfigureResult::Failed_DrmError) {
141 ThrowMsg(Jobs::WidgetInstall::Exceptions::DRMFailed,
144 ThrowMsg(Jobs::WidgetInstall::Exceptions::NotAllowed,
145 "widget installation or update not allowed!");
150 InstallerTaskFail(ConfigureResult result) :
151 DPL::TaskDecl<InstallerTaskFail>(this),
154 AddStep(&InstallerTaskFail::StepFail);
158 JobWidgetInstall::JobWidgetInstall(
159 std::string const &widgetPath,
160 const WidgetInstallationStruct &
163 JobContextBase<WidgetInstallationStruct>(installerStruct),
164 m_exceptionCaught(Jobs::Exceptions::Success)
166 m_installerContext.m_quiet = m_jobStruct.m_quiet;
168 ConfigureResult result = PrePareInstallation(widgetPath);
170 if (result == ConfigureResult::Ok) {
171 LogInfo("Configure installation succeeded");
172 m_installerContext.job->SetProgressFlag(true);
174 AddTask(new TaskRecovery(m_installerContext));
176 // Create installation tasks
177 if (m_installerContext.widgetConfig.packagingType !=
178 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
179 m_installerContext.widgetConfig.packagingType !=
180 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
183 AddTask(new TaskUnzip(m_installerContext));
186 AddTask(new TaskWidgetConfig(m_installerContext));
187 if (m_installerContext.widgetConfig.packagingType ==
188 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
190 AddTask(new TaskPrepareFiles(m_installerContext));
192 AddTask(new TaskCertify(m_installerContext));
193 if (m_needEncryption) {
194 AddTask(new TaskEncryptResource(m_installerContext));
197 AddTask(new TaskFileManipulation(m_installerContext));
198 // TODO: Update progress information for this task
200 //This is sort of quick solution, because ACE verdicts are based upon
201 //data from DAO (DB). So AceCheck for now has to be AFTER DbUpdate
203 AddTask(new TaskSmack(m_installerContext));
205 AddTask(new TaskManifestFile(m_installerContext));
206 if (m_installerContext.widgetConfig.packagingType ==
207 PKG_TYPE_HYBRID_WEB_APP)
209 AddTask(new TaskInstallOspsvc(m_installerContext));
211 AddTask(new TaskCertificates(m_installerContext));
212 AddTask(new TaskPluginsCopy(m_installerContext));
213 AddTask(new TaskDatabase(m_installerContext));
214 AddTask(new TaskAceCheck(m_installerContext));
215 } else if (result == ConfigureResult::Updated) {
216 LogInfo("Configure installation updated");
217 LogInfo("Widget Update");
218 m_installerContext.job->SetProgressFlag(true);
220 if (m_jobStruct.m_installMode ==
221 InstallMode::REINSTALL_MODE_DIRECTORY)
223 AddTask(new TaskPrepareReinstall(m_installerContext));
226 if (m_installerContext.widgetConfig.packagingType !=
227 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
228 m_installerContext.widgetConfig.packagingType !=
229 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
232 AddTask(new TaskUnzip(m_installerContext));
235 AddTask(new TaskWidgetConfig(m_installerContext));
237 if (m_installerContext.widgetConfig.packagingType ==
238 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
240 AddTask(new TaskPrepareFiles(m_installerContext));
243 AddTask(new TaskCertify(m_installerContext));
244 if (m_needEncryption) {
245 AddTask(new TaskEncryptResource(m_installerContext));
248 if (m_installerContext.widgetConfig.packagingType !=
249 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
251 AddTask(new TaskUpdateFiles(m_installerContext));
254 /* TODO : To backup file, save md5 values */
255 AddTask(new TaskSmack(m_installerContext));
257 AddTask(new TaskManifestFile(m_installerContext));
258 if (m_installerContext.widgetConfig.packagingType ==
259 PKG_TYPE_HYBRID_WEB_APP)
261 AddTask(new TaskInstallOspsvc(m_installerContext));
263 if (m_installerContext.widgetConfig.packagingType !=
264 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
266 AddTask(new TaskRemoveBackupFiles(m_installerContext));
268 AddTask(new TaskPluginsCopy(m_installerContext));
269 AddTask(new TaskDatabase(m_installerContext));
270 AddTask(new TaskAceCheck(m_installerContext));
271 //TODO: remove widgetHandle from this task and move before database task
272 // by now widget handle is needed in ace check
273 // Any error in acecheck while update will break widget
274 } else if (result == ConfigureResult::Deferred) {
275 // Installation is deferred
276 LogInfo("Configure installation deferred");
278 AddTask(new InstallerTaskFail(result));
279 } else if (result >= ConfigureResult::Failed &&
280 result <= ConfigureResult::Failed_DrmError) {
281 // Installation is not allowed to proceed due to widget update policy
282 LogWarning("Configure installation failed!");
284 AddTask(new InstallerTaskFail(result));
286 Assert(false && "Invalid configure result!");
290 ConfigureResult JobWidgetInstall::PrePareInstallation(
291 const std::string &widgetPath)
293 ConfigureResult result;
294 m_needEncryption = false;
299 if (m_jobStruct.m_installMode ==
300 InstallMode::REINSTALL_MODE_DIRECTORY)
302 std::ostringstream tempPathBuilder;
303 tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath();
304 tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath();
305 tempPathBuilder << "/";
306 tempPathBuilder << widgetPath;
307 tempDir = tempPathBuilder.str();;
310 Jobs::WidgetInstall::createTempPath(
311 m_jobStruct.m_installMode ==
312 InstallMode::INSTALL_MODE_PRELOAD);
315 m_isDRM = isDRMWidget(widgetPath);
316 if (true == m_isDRM) {
317 LogDebug("decrypt DRM widget");
318 if (DecryptDRMWidget(widgetPath, tempDir)) {
319 LogDebug("Failed decrypt DRM widget");
320 return ConfigureResult::Failed_DrmError;
324 LogDebug("widgetPath:" << widgetPath);
326 m_installerContext.widgetConfig.packagingType =
327 checkPackageType(widgetPath, tempDir);
328 ConfigParserData configData = getWidgetDataFromXML(
331 m_installerContext.widgetConfig.packagingType,
333 m_jobStruct.m_installMode ==
334 InstallMode::REINSTALL_MODE_DIRECTORY);
335 LogDebug("widget packaging type : " <<
336 m_installerContext.widgetConfig.packagingType.pkgType);
338 setTizenId(configData);
339 setApplicationType(configData);
340 m_needEncryption = detectResourceEncryption(configData);
341 setInstallLocationType(configData);
343 // Configure installation
344 result = ConfigureInstallation(widgetPath, configData, tempDir);
346 Catch(Exceptions::ExtractFileFailed)
348 LogError("Failed to create temporary path for widget");
349 result = ConfigureResult::Failed_InvalidConfig;
355 void JobWidgetInstall::setTizenId(
356 const WrtDB::ConfigParserData &configInfo)
358 bool shouldMakeAppid = false;
359 using namespace PackageManager;
360 if (!!configInfo.tizenAppId) {
361 LogDebug("Setting tizenAppId provided in config.xml: " <<
362 configInfo.tizenAppId);
364 m_installerContext.widgetConfig.tzAppid = *configInfo.tizenAppId;
366 if (!!configInfo.tizenPkgId) {
367 LogDebug("Setting tizenPkgId provided in config.xml: " <<
368 configInfo.tizenPkgId);
370 m_installerContext.widgetConfig.tzPkgid = *configInfo.tizenPkgId;
372 DPL::String appid = *configInfo.tizenAppId;
373 if (appid.length() > PACKAGE_ID_LENGTH) {
374 m_installerContext.widgetConfig.tzPkgid =
375 appid.substr(0, PACKAGE_ID_LENGTH);
377 //old version appid only has 10byte random character is able to install for a while.
378 //this case appid equal pkgid.
379 m_installerContext.widgetConfig.tzPkgid =
380 *configInfo.tizenAppId;
381 shouldMakeAppid = true;
385 shouldMakeAppid = true;
386 TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId();
387 LogDebug("Checking if pkg id is unique");
389 if (!validateTizenPackageID(pkgId)) {
390 //path exist, chose another one
391 pkgId = WidgetDAOReadOnly::generatePkgId();
396 m_installerContext.widgetConfig.tzPkgid = pkgId;
397 LogInfo("tizen_id name was generated by WRT: " <<
398 m_installerContext.widgetConfig.tzPkgid);
401 if (shouldMakeAppid == true) {
402 DPL::OptionalString name;
403 DPL::OptionalString defaultLocale = configInfo.defaultlocale;
405 FOREACH(localizedData, configInfo.localizedDataSet)
407 Locale i = localizedData->first;
408 if (!!defaultLocale) {
409 if (defaultLocale == i) {
410 name = localizedData->second.name;
414 name = localizedData->second.name;
419 if (regcomp(®x, REG_NAME_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
420 LogDebug("Regcomp failed");
423 LogDebug("Name : " << name);
424 if (!name || (regexec(®x, DPL::ToUTF8String(*name).c_str(),
425 static_cast<size_t>(0), NULL, 0) != REG_NOERROR))
427 // TODO : generate name move to wrt-commons
428 std::string allowedString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
429 std::ostringstream genName;
431 gettimeofday(&tv, NULL);
432 unsigned int seed = time(NULL) + tv.tv_usec;
434 genName << "_" << allowedString[rand_r(&seed) % allowedString.length()];
435 name = DPL::FromUTF8String(genName.str());
436 LogDebug("name was generated by WRT");
439 LogDebug("Name : " << name);
440 std::ostringstream genid;
441 genid << m_installerContext.widgetConfig.tzPkgid << "." << name;
442 LogDebug("tizen appid was generated by WRT : " << genid.str());
444 DPL::OptionalString appid = DPL::FromUTF8String(genid.str());
445 NormalizeAndTrimSpaceString(appid);
446 m_installerContext.widgetConfig.tzAppid = *appid;
449 // send start signal of pkgmgr
450 getInstallerStruct().pkgmgrInterface->setPkgname(DPL::ToUTF8String(
454 LogInfo("Tizen App Id : " << m_installerContext.widgetConfig.tzAppid);
455 LogInfo("Tizen Pkg Id : " << m_installerContext.widgetConfig.tzPkgid);
456 LogInfo("W3C Widget GUID : " << m_installerContext.widgetConfig.guid);
459 void JobWidgetInstall::configureWidgetLocation(const std::string & widgetPath,
460 const std::string& tempPath)
462 if (m_jobStruct.m_installMode ==
463 InstallMode::REINSTALL_MODE_DIRECTORY)
465 // replace widget path to installed path
466 m_installerContext.locations =
467 WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
469 widgetPath, tempPath,
470 m_installerContext.widgetConfig.packagingType,
471 m_installerContext.locationType);
473 m_installerContext.locations =
474 WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
476 widgetPath, tempPath,
477 m_installerContext.widgetConfig.packagingType,
478 m_installerContext.locationType);
480 m_installerContext.locations->registerAppid(
481 DPL::ToUTF8String(m_installerContext.widgetConfig.tzAppid));
483 LogInfo("widgetSource " << widgetPath);
486 ConfigureResult JobWidgetInstall::ConfigureInstallation(
487 const std::string &widgetSource,
488 const WrtDB::ConfigParserData &configData,
489 const std::string &tempPath)
491 ConfigureResult result = ConfigureResult::Failed;
492 WidgetUpdateInfo update;
494 // checking installed web application
496 // checking existing application is installed
497 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
498 // no excpetion means, it isn't update mode
499 getInstallerStruct().pkgmgrInterface->sendSignal(
501 PKGMGR_START_UPDATE);
503 update = detectWidgetUpdate(configData,
504 m_installerContext.widgetConfig.tzAppid);
505 result = checkWidgetUpdate(update);
506 if (result != ConfigureResult::Updated) {
507 // Already installed TizenAppId. return failed
508 return ConfigureResult::Failed_AlreadyInstalled;
510 m_installerContext.isUpdateMode = true;
512 Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
513 result = ConfigureResult::Ok;
514 getInstallerStruct().pkgmgrInterface->sendSignal(
516 PKGMGR_START_INSTALL);
517 m_installerContext.isUpdateMode = false;
519 if (!validateTizenApplicationID(
520 m_installerContext.widgetConfig.tzAppid))
522 LogError("tizen application ID is already used");
523 return ConfigureResult::Failed_InvalidConfig;
525 if (!validateTizenPackageID(m_installerContext.widgetConfig.tzPkgid)) {
526 LogError("tizen package ID is already used");
527 return ConfigureResult::Failed_AlreadyInstalled;
531 configureWidgetLocation(widgetSource, tempPath);
533 // Init installer context
534 m_installerContext.installStep = InstallerContext::INSTALL_START;
535 m_installerContext.job = this;
536 m_installerContext.widgetConfig.shareHref = std::string();
541 bool JobWidgetInstall::validateTizenApplicationID(
542 const WrtDB::TizenAppId &tizenAppId)
544 LogInfo("tizen application ID = [" << tizenAppId << "]");
547 if (regcomp(®, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
548 LogDebug("Regcomp failed");
551 if (regexec(®, DPL::ToUTF8String(tizenAppId).c_str(), 0, NULL, 0)
561 bool JobWidgetInstall::validateTizenPackageID(
562 const WrtDB::TizenPkgId &tizenPkgId)
564 std::string pkgId = DPL::ToUTF8String(tizenPkgId);
566 std::string installPath =
567 std::string(GlobalConfig::GetUserInstalledWidgetPath()) +
569 std::string preinstallPath =
570 std::string(GlobalConfig::GetUserPreloadedWidgetPath()) +
574 if ((stat(installPath.c_str(), &dirStat) == 0) ||
575 (stat(preinstallPath.c_str(), &dirStat) == 0))
582 ConfigureResult JobWidgetInstall::checkWidgetUpdate(
583 const WidgetUpdateInfo &update)
585 LogInfo("incoming version = '" << update.incomingVersion);
586 LogInfo("Tizen AppID = " << update.tzAppId);
588 // Check running state
589 bool isRunning = false;
591 app_manager_is_running(DPL::ToUTF8String(update.tzAppId).c_str(),
593 if (APP_MANAGER_ERROR_NONE != retval || isRunning) {
594 LogError("Fail to get running state");
595 return ConfigureResult::Failed_WidgetRunning;
598 m_installerContext.widgetConfig.tzAppid = update.tzAppId;
600 if (isUpperVersion(update.existingVersion, update.incomingVersion) ||
601 (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY) ||
602 (m_jobStruct.m_installMode == InstallMode::REINSTALL_MODE_DIRECTORY))
604 LogInfo("Whether widget policy allow proceed ok");
605 return ConfigureResult::Updated;
607 return ConfigureResult::Failed_LowerVersion;
610 return ConfigureResult::Failed;
613 bool JobWidgetInstall::isUpperVersion(
614 const OptionalWidgetVersion &existingVersion,
615 const OptionalWidgetVersion &incomingVersion)
617 LogInfo("Existing version = '" << *existingVersion);
618 LogInfo("Incoming version = '" << *incomingVersion);
620 if (!existingVersion && !incomingVersion) {
622 } else if (!existingVersion && !!incomingVersion) {
624 } else if (!!existingVersion && !incomingVersion) {
627 if (!existingVersion->IsWac() || !incomingVersion->IsWac()) {
630 if (*incomingVersion == *existingVersion) {
632 } else if (*incomingVersion > *existingVersion) {
641 ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
642 const std::string &widgetSource,
643 const std::string &tempPath,
644 WrtDB::PackagingType pkgType,
650 ConfigParserData configInfo;
654 if (pkgType == PKG_TYPE_HOSTED_WEB_APP) {
655 parser.Parse(widgetSource,
657 new RootParser<WidgetParser>(configInfo,
658 DPL::FromUTF32String(
660 } else if (pkgType == PKG_TYPE_DIRECTORY_WEB_APP) {
661 std::string configPath;
662 configPath = tempPath;
664 configPath += WITH_OSP_XML;
667 // checking RDS data directory
668 if (access(configPath.c_str(), F_OK) != 0) {
669 std::string tzAppId =
670 widgetSource.substr(widgetSource.find_last_of("/")+1);
671 WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTzAppId(DPL::FromUTF8String(tzAppId)));
672 configPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath());
674 configPath += WITH_OSP_XML;
677 parser.Parse(configPath,
679 new RootParser<WidgetParser>(
681 DPL::FromUTF32String(L"widget"))));
684 std::unique_ptr<DPL::ZipInput> zipFile(
685 new DPL::ZipInput(widgetSource));
687 std::unique_ptr<DPL::ZipInput::File> configFile;
689 // Open config.xml file
690 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
691 configFile.reset(zipFile->OpenFile(WITH_OSP_XML));
693 configFile.reset(zipFile->OpenFile(CONFIG_XML));
697 DPL::BinaryQueue buffer;
698 DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
699 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
700 DPL::Copy(&inputAdapter, &outputAdapter);
701 parser.Parse(&buffer,
703 new RootParser<WidgetParser>(configInfo,
709 std::string configFile;
710 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
711 configFile = tempPath + "/" + WITH_OSP_XML;
713 configFile = tempPath + "/" + CONFIG_XML;
716 parser.Parse(configFile,
718 new RootParser<WidgetParser>(configInfo,
725 Catch(DPL::ZipInput::Exception::OpenFailed)
727 LogError("Failed to open widget package");
728 return ConfigParserData();
730 Catch(DPL::ZipInput::Exception::OpenFileFailed)
732 LogError("Failed to open config.xml file");
733 return ConfigParserData();
735 Catch(DPL::CopyFailed)
737 LogError("Failed to extract config.xml file");
738 return ConfigParserData();
740 Catch(DPL::FileInput::Exception::OpenFailed)
742 LogError("Failed to open config.xml file");
743 return ConfigParserData();
745 Catch(ElementParser::Exception::ParseError)
747 LogError("Failed to parse config.xml file");
748 return ConfigParserData();
750 Catch(DPL::ZipInput::Exception::SeekFileFailed)
752 LogError("Failed to seek widget archive - corrupted package?");
753 return ConfigParserData();
758 WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
759 const ConfigParserData &configInfo,
760 const WrtDB::TizenAppId &tizenId)
762 LogInfo("Checking up widget package for config.xml...");
763 OptionalWidgetVersion incomingVersion;
765 if (!configInfo.version.IsNull()) {
767 DPL::Optional<WidgetVersion>(
768 WidgetVersion(*configInfo.version));
771 WidgetDAOReadOnly dao(tizenId);
772 return WidgetUpdateInfo(
774 WidgetVersion(*dao.getVersion()),
778 void JobWidgetInstall::SendProgress()
780 using namespace PackageManager;
781 if (GetProgressFlag() != false) {
782 if (getInstallerStruct().progressCallback != NULL) {
783 // send progress signal of pkgmgr
784 std::ostringstream percent;
785 percent << static_cast<int>(GetProgressPercent());
786 getInstallerStruct().pkgmgrInterface->sendSignal(
790 LogDebug("Call widget install progressCallbak");
791 getInstallerStruct().progressCallback(
792 getInstallerStruct().userParam,
793 GetProgressPercent(),
794 GetProgressDescription());
799 void JobWidgetInstall::SendProgressIconPath(const std::string &path)
801 using namespace PackageManager;
802 if (GetProgressFlag() != false) {
803 if (getInstallerStruct().progressCallback != NULL) {
804 // send progress signal of pkgmgr
805 getInstallerStruct().pkgmgrInterface->sendSignal(
812 void JobWidgetInstall::SendFinishedSuccess()
814 using namespace PackageManager;
815 // TODO : sync should move to separate task.
818 if (INSTALL_LOCATION_TYPE_EXTERNAL == m_installerContext.locationType) {
819 if (m_installerContext.isUpdateMode) {
820 WidgetInstallToExtSingleton::Instance().postUpgrade(true);
822 WidgetInstallToExtSingleton::Instance().postInstallation(true);
824 WidgetInstallToExtSingleton::Instance().deinitialize();
827 // remove widget install information file
828 unlink(m_installerContext.installInfo.c_str());
831 JobWidgetInstall::displayWidgetInfo();
833 TizenAppId& tizenId = m_installerContext.widgetConfig.tzAppid;
835 // send signal of pkgmgr
836 getInstallerStruct().pkgmgrInterface->sendSignal(
840 LogDebug("Call widget install successfinishedCallback");
841 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
843 tizenId), Jobs::Exceptions::Success);
846 void JobWidgetInstall::SendFinishedFailure()
848 using namespace PackageManager;
849 // remove widget install information file
850 unlink(m_installerContext.installInfo.c_str());
852 LogError("Error number: " << m_exceptionCaught);
853 LogError("Message: " << m_exceptionMessage);
854 TizenAppId & tizenId = m_installerContext.widgetConfig.tzAppid;
856 LogDebug("Call widget install failure finishedCallback");
857 std::stringstream errorNum;
858 errorNum << m_exceptionCaught;
860 // send signal of pkgmgr
861 getInstallerStruct().pkgmgrInterface->sendSignal(
865 getInstallerStruct().pkgmgrInterface->sendSignal(
869 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
871 tizenId), m_exceptionCaught);
874 void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
876 m_exceptionCaught = static_cast<Jobs::Exceptions::Type>(e.getParam());
877 m_exceptionMessage = e.GetMessage();
880 void JobWidgetInstall::displayWidgetInfo()
882 WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
884 std::ostringstream out;
885 WidgetLocalizedInfo localizedInfo =
886 W3CFileLocalization::getLocalizedInfo(dao.getTzAppId());
889 "===================================== INSTALLED WIDGET INFO =========" \
890 "============================";
891 out << std::endl << "Name: " << localizedInfo.name;
892 out << std::endl << "AppId: " << dao.getTzAppId();
893 WidgetSize size = dao.getPreferredSize();
894 out << std::endl << "Width: " << size.width;
895 out << std::endl << "Height: " << size.height;
896 out << std::endl << "Start File: " <<
897 W3CFileLocalization::getStartFile(dao.getTzAppId());
898 out << std::endl << "Version: " << dao.getVersion();
899 out << std::endl << "Licence: " <<
900 localizedInfo.license;
901 out << std::endl << "Licence Href: " <<
902 localizedInfo.licenseHref;
903 out << std::endl << "Description: " <<
904 localizedInfo.description;
905 out << std::endl << "Widget Id: " << dao.getGUID();
906 out << std::endl << "Widget recognized: " << dao.isRecognized();
907 out << std::endl << "Widget distributor signed: " <<
908 dao.isDistributorSigned();
909 out << std::endl << "Widget trusted: " << dao.isTrusted();
911 OptionalWidgetIcon icon = W3CFileLocalization::getIcon(dao.getTzAppId());
912 DPL::OptionalString iconSrc =
913 !!icon ? icon->src : DPL::OptionalString::Null;
914 out << std::endl << "Icon: " << iconSrc;
916 out << std::endl << "Preferences:";
918 PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList();
921 out << std::endl << " Key: " <<
923 out << std::endl << " Readonly: " <<
928 out << std::endl << "Features:";
930 WidgetFeatureSet list = dao.getFeaturesList();
933 out << std::endl << " Name: " << it->name;
942 WrtDB::PackagingType JobWidgetInstall::checkPackageType(
943 const std::string &widgetSource,
944 const std::string &tempPath)
946 // Check installation type (direcotory/ or config.xml or widget.wgt)
947 if (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY ||
948 m_jobStruct.m_installMode == InstallMode::REINSTALL_MODE_DIRECTORY)
950 LogDebug("Install directly from directory");
951 return PKG_TYPE_DIRECTORY_WEB_APP;
953 if (hasExtension(widgetSource, XML_EXTENSION)) {
954 LogInfo("Hosted app installation");
955 return PKG_TYPE_HOSTED_WEB_APP;
959 std::string configFile = tempPath + "/" + CONFIG_XML;
960 if (WrtUtilFileExists(configFile)) {
961 return PKG_TYPE_NOMAL_WEB_APP;
964 configFile = tempPath + "/" + WITH_OSP_XML;
965 if (WrtUtilFileExists(configFile)) {
966 return PKG_TYPE_HYBRID_WEB_APP;
969 std::unique_ptr<DPL::ZipInput> zipFile;
974 zipFile.reset(new DPL::ZipInput(widgetSource));
976 Catch(DPL::ZipInput::Exception::OpenFailed)
978 LogDebug("Failed to open widget package");
979 return PKG_TYPE_UNKNOWN;
981 Catch(DPL::ZipInput::Exception::SeekFileFailed)
983 LogError("Failed to seek widget package file");
984 return PKG_TYPE_UNKNOWN;
989 // Open config.xml file in package root
990 std::unique_ptr<DPL::ZipInput::File> configFile(
991 zipFile->OpenFile(CONFIG_XML));
992 return PKG_TYPE_NOMAL_WEB_APP;
994 Catch(DPL::ZipInput::Exception::OpenFileFailed)
996 LogDebug("Could not find config.xml");
1001 // Open config.xml file in package root
1002 std::unique_ptr<DPL::ZipInput::File> configFile(
1003 zipFile->OpenFile(WITH_OSP_XML));
1005 return PKG_TYPE_HYBRID_WEB_APP;
1007 Catch(DPL::ZipInput::Exception::OpenFileFailed)
1009 LogDebug("Could not find wgt/config.xml");
1010 return PKG_TYPE_UNKNOWN;
1014 return PKG_TYPE_UNKNOWN;
1017 void JobWidgetInstall::setApplicationType(
1018 const WrtDB::ConfigParserData &configInfo)
1020 FOREACH(iterator, configInfo.nameSpaces) {
1021 LogInfo("namespace = [" << *iterator << "]");
1022 AppType currentAppType = APP_TYPE_UNKNOWN;
1024 if (*iterator == ConfigurationNamespace::W3CWidgetNamespaceName) {
1028 ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement ||
1030 ConfigurationNamespace::WacWidgetNamespaceName)
1032 currentAppType = APP_TYPE_WAC20;
1033 } else if (*iterator ==
1034 ConfigurationNamespace::TizenWebAppNamespaceName)
1036 currentAppType = APP_TYPE_TIZENWEBAPP;
1039 if (m_installerContext.widgetConfig.webAppType ==
1042 m_installerContext.widgetConfig.webAppType = currentAppType;
1043 } else if (m_installerContext.widgetConfig.webAppType ==
1048 ThrowMsg(Exceptions::WidgetConfigFileInvalid,
1049 "Config.xml has more than one namespace");
1053 // If there is no define, type set to WAC 2.0
1054 if (m_installerContext.widgetConfig.webAppType == APP_TYPE_UNKNOWN) {
1055 m_installerContext.widgetConfig.webAppType = APP_TYPE_WAC20;
1058 LogInfo("type = [" <<
1059 m_installerContext.widgetConfig.webAppType.getApptypeToString() <<
1063 bool JobWidgetInstall::detectResourceEncryption(
1064 const WrtDB::ConfigParserData &configData)
1066 FOREACH(it, configData.settingsList)
1068 if (it->m_name == SETTING_VALUE_ENCRYPTION &&
1069 it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE)
1071 LogDebug("resource need encryption");
1078 void JobWidgetInstall::setInstallLocationType(
1080 WrtDB::ConfigParserData &
1083 m_installerContext.locationType = INSTALL_LOCATION_TYPE_NOMAL;
1085 if (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_PRELOAD) {
1086 m_installerContext.locationType =
1087 INSTALL_LOCATION_TYPE_PRELOAD;
1089 FOREACH(it, configData.settingsList)
1091 if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME &&
1093 SETTING_VALUE_INSTALLTOEXT_PREPER_EXT)
1095 LogDebug("This widget will be installed to sd card");
1096 m_installerContext.locationType =
1097 INSTALL_LOCATION_TYPE_EXTERNAL;
1103 bool JobWidgetInstall::isDRMWidget(std::string /*widgetPath*/)
1109 bool JobWidgetInstall::DecryptDRMWidget(std::string /*widgetPath*/,
1110 std::string /*destPath*/)
1115 } //namespace WidgetInstall