24db446b68f6932be160549543f16c00360972cd
[framework/web/wrt-installer.git] / src / jobs / widget_install / job_widget_install.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 /*
17  * @file    job_widget_install.cpp
18  * @author  Radoslaw Wicik r.wicik@samsung.com
19  * @author  Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20  * @version 1.0
21  * @brief   Implementation file for main installer task
22  */
23 #include <dpl/noncopyable.h>
24 #include <dpl/abstract_waitable_input_adapter.h>
25 #include <dpl/abstract_waitable_output_adapter.h>
26 #include <dpl/zip_input.h>
27 #include <dpl/scoped_ptr.h>
28 #include <dpl/binary_queue.h>
29 #include <dpl/copy.h>
30 #include <dpl/assert.h>
31 #include <dpl/sstream.h>
32 #include <dpl/wrt-dao-ro/common_dao_types.h>
33 #include "root_parser.h"
34 #include "widget_parser.h"
35 #include "parser_runner.h"
36 #include <widget_install/job_widget_install.h>
37 #include <widget_install/task_unzip.h>
38 #include <widget_install/task_certify.h>
39 #include <widget_install/task_widget_config.h>
40 #include <widget_install/task_db_update.h>
41 #include <widget_install/task_ace_check.h>
42 #include <widget_install/task_smack.h>
43 #include <widget_install/task_manifest_file.h>
44 #include <widget_install/task_private_storage.h>
45 #include <widget_install/task_prepare_files.h>
46 #include <widget_install/task_recovery.h>
47 #include <widget_install/task_install_ospsvc.h>
48 #include <widget_install/task_update_files.h>
49 #include <widget_install/task_new_db_insert.h>
50 #include <widget_install/task_remove_backup.h>
51 #include <widget_install/task_encrypt_resource.h>
52 #include <widget_install/widget_install_errors.h>
53 #include <widget_install/widget_install_context.h>
54 #include <string>
55 #include <sys/time.h>
56 #include <ctime>
57 #include <cstdlib>
58 #include <limits.h>
59 #include <regex.h>
60 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
61 #include <dpl/wrt-dao-ro/global_config.h>
62 #include <dpl/wrt-dao-rw/global_dao.h> // TODO remove
63 #include <aul.h>
64 #include <dpl/localization/w3c_file_localization.h>
65 #include <libiriwrapper.h>
66 #include <pkg-manager/pkgmgr_signal.h>
67
68 using namespace WrtDB;
69
70 namespace // anonymous
71 {
72 const char * const CONFIG_XML = "config.xml";
73 const char * const WITH_OSP_XML = "res/wgt/config.xml";
74
75 //allowed: a-z, A-Z, 0-9, '.', '-', '_', ' '
76 const char* REG_TIZENID_PATTERN = "^[-. a-zA-Z0-9_@+=]*$";
77 const int RESERVED_COUNT = 20;  //number of chars reserved in name (e.g. for '.desktop')
78 const int MAX_TIZENID_LENTH = 255 - RESERVED_COUNT;
79
80 static const DPL::String SETTING_VALUE_ENCRYPTION = L"encryption";
81 static const DPL::String SETTING_VALUE_ENCRYPTION_ENABLE = L"enable";
82
83 class InstallerTaskFail :
84     public DPL::TaskDecl<InstallerTaskFail>
85 {
86   private:
87     bool m_deferred;
88
89     void StepFail()
90     {
91         if (m_deferred) {
92             ThrowMsg(Jobs::WidgetInstall::Exceptions::Deferred,
93                      "Widget installation or update deferred!");
94         } else {
95             ThrowMsg(Jobs::WidgetInstall::Exceptions::NotAllowed,
96                      "Widget installation or update not allowed!");
97         }
98     }
99
100   public:
101     InstallerTaskFail(bool deferred) :
102         DPL::TaskDecl<InstallerTaskFail>(this),
103         m_deferred(deferred)
104     {
105         AddStep(&InstallerTaskFail::StepFail);
106     }
107 };
108
109 const std::string XML_EXTENSION = ".xml";
110
111 bool hasExtension(const std::string& filename, const std::string& extension) {
112     LogDebug("Looking for extension " << extension << " in: "  << filename);
113     size_t fileLen = filename.length();
114     size_t extLen = extension.length();
115     if (fileLen < extLen) {
116         LogError("Filename " << filename << " is shorter than extension "
117                  << extension);
118         return false;
119     }
120     return (0 == filename.compare(fileLen-extLen, extLen, extension));
121 }
122 } // namespace anonymous
123
124 namespace Jobs {
125 namespace WidgetInstall {
126 JobWidgetInstall::JobWidgetInstall(std::string const &widgetPath,
127         const WidgetInstallationStruct &installerStruct) :
128     Job(Installation),
129     JobContextBase<WidgetInstallationStruct>(installerStruct),
130     m_exceptionCaught(Exceptions::Success)
131 {
132     // Check installation type (config.xml or widget.wgt)
133     m_installerContext.browserRequest = hasExtension(widgetPath, XML_EXTENSION);
134
135     LogInfo("Hosted app installation: " << m_installerContext.browserRequest);
136
137     struct timeval tv;
138     gettimeofday(&tv, NULL);
139     srand(time(NULL) + tv.tv_usec);
140     WrtDB::DbWidgetHandle handle;
141     do {
142         handle = rand() % INT_MAX + 1;
143         LogInfo("Random widget handle: " << handle);
144     } while (WidgetDAOReadOnly::isWidgetInstalled(handle));
145
146     m_installerContext.widgetHandle = handle;
147     m_installerContext.m_quiet = m_jobStruct.m_quiet;
148
149     m_installerContext.widgetConfig.pType = checkPackageType(widgetPath);
150
151     ConfigParserData configData = getWidgetDataFromXML(widgetPath,
152             m_installerContext.browserRequest,
153             m_installerContext.widgetConfig.pType);
154     WidgetUpdateInfo update = detectWidgetUpdate(configData);
155     bool needEncryption = detectResourceEncryption(configData);
156
157     // Configure installation
158     ConfigureResult result = ConfigureInstallation(widgetPath,
159             m_installerContext.browserRequest, update);
160     if (!setTizenId(configData)) {
161         result = ConfigureResult::Failed;
162     } else {
163         using namespace PackageManager;
164         LogInfo("WidgetHandle: " << m_installerContext.widgetHandle);
165         LogInfo("Tizen Id: " << m_installerContext.widgetConfig.pkgname);
166
167         // send start signal of pkgmgr
168         PkgmgrSignalSingleton::Instance().setPkgname(
169                     DPL::ToUTF8String(
170                         *m_installerContext.widgetConfig.pkgname));
171         PkgmgrSignalSingleton::Instance().sendSignal(
172                     PKGMGR_START_KEY,
173                     PKGMGR_START_INSTALL);
174     }
175
176     if (result == ConfigureResult::Ok) {
177         LogInfo("Configure installation succeeded");
178
179         AddTask(new TaskRecovery(m_installerContext));
180
181         // Create installation tasks
182         if (!m_installerContext.browserRequest) {
183             AddTask(new TaskUnzip(m_installerContext));
184         }
185         AddTask(new TaskWidgetConfig(m_installerContext));
186         AddTask(new TaskCertify(m_installerContext));
187         if (needEncryption) {
188             AddTask(new TaskEncryptResource(m_installerContext));
189         }
190         AddTask(new TaskDbUpdate(m_installerContext));
191         // TODO: Update progress information for this task
192
193         AddTask(new TaskPrivateStorage(m_installerContext));
194         AddTask(new TaskAceCheck(m_installerContext));
195         //This is sort of quick solution, because ACE verdicts are based upon
196         //data from DAO (DB). So AceCheck for now has to be AFTER DbUpdate
197         //task.
198         AddTask(new TaskSmack(m_installerContext));
199
200         AddTask(new TaskManifestFile(m_installerContext));
201         if (m_installerContext.widgetConfig.pType ==
202                 PKG_TYPE_TIZEN_WITHSVCAPP) {
203             AddTask(new TaskInstallOspsvc(m_installerContext));
204         }
205     } else if (result == ConfigureResult::Updated) {
206         LogInfo("Configure installation updated");
207         LogInfo("Widget Update");
208
209         if (!m_installerContext.browserRequest) {
210             AddTask(new TaskUnzip(m_installerContext));
211         }
212         AddTask(new TaskWidgetConfig(m_installerContext));
213
214         AddTask(new TaskCertify(m_installerContext));
215         AddTask(new TaskUpdateFiles(m_installerContext));
216         AddTask(new TaskNewDbInsert(m_installerContext));
217
218         /* TODO : To backup file, save md5 values */
219         AddTask(new TaskAceCheck(m_installerContext));
220         AddTask(new TaskSmack(m_installerContext));
221
222         AddTask(new TaskManifestFile(m_installerContext));
223         AddTask(new TaskRemoveBackupFiles(m_installerContext));
224         if (m_installerContext.widgetConfig.pType ==
225                 PKG_TYPE_TIZEN_WITHSVCAPP) {
226             AddTask(new TaskInstallOspsvc(m_installerContext));
227         }
228     } else if (result == ConfigureResult::Deferred) {
229         // Installation is deferred
230         LogInfo("Configure installation deferred");
231
232         AddTask(new InstallerTaskFail(true));
233     } else if (result == ConfigureResult::Failed) {
234         // Installation is not allowed to proceed due to widget update policy
235         LogWarning("Configure installation failed!");
236
237         AddTask(new InstallerTaskFail(false));
238     } else {
239         Assert(false && "Invalid configure result!");
240     }
241 }
242
243 bool JobWidgetInstall::setTizenId(
244         const WrtDB::ConfigParserData &configInfo)
245 {
246     Assert(!!m_installerContext.widgetHandle
247            && "Widget Handle should be initialized");
248
249     regex_t reg;
250     regcomp(&reg, REG_TIZENID_PATTERN, REG_NOSUB);
251     struct stat dirStat;
252     if(!!configInfo.tizenId) {
253         LogDebug("Setting tizenId provided in config.xml");
254         if ((regexec(&reg, DPL::ToUTF8String(*(configInfo.tizenId)).c_str(),
255              static_cast<size_t>(0), NULL, 0) != 0) ||
256             (DPL::ToUTF8String(*(configInfo.tizenId)).size() > MAX_TIZENID_LENTH) ||
257             (stat((std::string(GlobalConfig::GetUserInstalledWidgetPath()) + "/"
258                    + DPL::ToUTF8String(*(configInfo.tizenId))).c_str(), &dirStat) == 0))
259         {
260             //it is true when tizenId does not fit REG_TIZENID_PATTERN
261             LogError("pkgName provided but not proper.");
262             regfree(&reg);
263             return false;
264         }
265         m_installerContext.widgetConfig.pkgname = configInfo.tizenId;
266
267     } else {
268         LogInfo("package name is generated by WRT");
269         // tizen id should be generated by secure random algorithm
270         std::string pkgName = WrtDB::GlobalConfig::GetPkgnamePrefix();
271
272         bool named = false;
273         FOREACH(it, configInfo.localizedDataSet)
274         {
275             if (!!((it->second).name)) {
276                 //there is a name provided
277                 std::string name =  DPL::ToUTF8String(*(it->second).name);
278                 //cut very long widget's name
279                 name = name.substr(0, MAX_TIZENID_LENTH - strlen(
280                     WrtDB::GlobalConfig::GetPkgnamePrefix()));
281                 //check name if all characters are supported by filesystem
282                 if (regexec(&reg, name.c_str(), static_cast<size_t>(0), NULL, 0)
283                     == 0)
284                 {
285                     //WidgetName is ok and can be used as package name
286                     //replace all spaces with '_'
287                     size_t pos = 0;
288                     while((pos = name.find(" ", pos)) != std::string::npos) {
289                         name.replace(pos, 1, "_");
290                         ++pos;
291                     }
292                     pkgName += name;
293                     named = true;
294                 }
295                 break;
296             }
297         }
298
299         if (!named) // there is no widget name provided, use widgetHandle
300         {
301             pkgName += std::to_string(*(m_installerContext.widgetHandle));
302         }
303
304         //check if there is package with same name and if generate different name
305         std::string path = GlobalConfig::GetUserInstalledWidgetPath();
306         path += "/";
307
308         std::ostringstream newPath;
309         newPath << path << pkgName;
310
311         std::string suffix;
312         for (int i = 0;; ++i) {
313             if (stat(newPath.str().c_str(), &dirStat) == 0) {
314                 //path exist, chose another one, eg. widgetName1
315                 suffix = std::to_string(i + 1);
316                 pkgName = pkgName.substr(
317                         0, MAX_TIZENID_LENTH - suffix.size());
318                 newPath.str("");
319                 newPath << path << pkgName << suffix;
320                 continue;
321             }
322             pkgName += suffix;
323             break;
324         }
325
326         m_installerContext.widgetConfig.pkgname =
327             DPL::FromUTF8String(pkgName);
328
329     }
330     regfree(&reg);
331
332     LogInfo("Tizen Id : " << m_installerContext.widgetConfig.pkgname);
333     LogInfo("W3C Widget GUID : " << m_installerContext.widgetConfig.guid);
334     return true;
335 }
336
337 DPL::Optional<WidgetHandle> JobWidgetInstall::getNewWidgetHandle() const
338 {
339     return m_installerContext.widgetHandle;
340 }
341
342 JobWidgetInstall::ConfigureResult JobWidgetInstall::ConfigureInstallation(
343         const std::string &widgetSource,
344         bool fromBrowser,
345         const WidgetUpdateInfo &update)
346 {
347     LogInfo(
348         "Widget install/update: incoming guid = '" <<
349         update.incomingGUID << "'");
350     LogInfo(
351         "Widget install/update: incoming version = '" <<
352         update.incomingVersion << "'");
353
354     // Check policy
355     WidgetUpdateMode::Type updateTypeCheckBit;
356
357     if (update.existingWidgetInfo.isExist == false) {
358         LogInfo("Widget info does not exist");
359         updateTypeCheckBit = WidgetUpdateMode::NotInstalled;
360     } else {
361         LogInfo("Widget info exists. Handle: " <<
362                 update.existingWidgetInfo.existingHandle);
363
364         DPL::OptionalString pkgname =
365             WidgetDAOReadOnly(update.existingWidgetInfo.existingHandle).getPkgname();
366
367         if(pkgname.IsNull()) {
368             LogInfo("But package name doesn't exist");
369             return ConfigureResult::Failed;
370         }
371
372         LogInfo("Widget model exists. package name: " << pkgname);
373         if (aul_app_is_running(DPL::ToUTF8String(*pkgname).c_str())) {
374             // Must be deferred when update in progress
375             if (m_jobStruct.updateMode == WidgetUpdateMode::PolicyWac) {
376                 LogInfo(
377                     "Widget is already running. Policy is update according to WAC");
378
379                 return ConfigureResult::Deferred;
380             } else {
381                 LogInfo(
382                     "Widget is already running. Policy is not update according to WAC");
383                 LogInfo("Installation aborted: " << widgetSource);
384
385                 return ConfigureResult::Failed;
386             }
387         }
388
389         m_installerContext.widgetConfig.pkgname = pkgname;
390         OptionalWidgetVersion existingVersion;
391         existingVersion = update.existingWidgetInfo.existingVersion;
392         OptionalWidgetVersion incomingVersion = update.incomingVersion;
393
394         updateTypeCheckBit = CalcWidgetUpdatePolicy(existingVersion,
395                                                     incomingVersion);
396     }
397
398     // Calc proceed flag
399     bool canProceed = (m_jobStruct.updateMode & updateTypeCheckBit) > 0;
400
401     LogInfo("Whether widget policy allow proceed: " << canProceed);
402
403     // Init installer context
404     m_installerContext.widgetSource = widgetSource;
405     m_installerContext.tempWidgetPath = std::string();
406
407     // setup config xml path
408     if (fromBrowser) {
409         LogInfo("widgetSource " << widgetSource);
410         size_t slash = widgetSource.find_last_of("\\/");
411         if (std::string::npos != slash) {
412             m_installerContext.tempWidgetPath = widgetSource.substr(0, slash+1);
413         } else {
414             m_installerContext.tempWidgetPath = ".";
415         }
416     }
417
418     m_installerContext.installStep = InstallerContext::INSTALL_START;
419     m_installerContext.job = this;
420     m_installerContext.existingWidgetInfo = update.existingWidgetInfo;
421     m_installerContext.widgetConfig.shareHref = std::string();
422
423     if (m_installerContext.existingWidgetInfo.isExist) {
424         return canProceed ? ConfigureResult::Updated : ConfigureResult::Failed;
425     }
426
427     // Return result
428     return canProceed ? ConfigureResult::Ok : ConfigureResult::Failed;
429 }
430
431 WidgetUpdateMode::Type JobWidgetInstall::CalcWidgetUpdatePolicy(
432         const OptionalWidgetVersion &existingVersion,
433         const OptionalWidgetVersion &incomingVersion) const
434 {
435     // Widget is installed, check versions
436     if (!existingVersion && !incomingVersion) {
437         return WidgetUpdateMode::ExistingVersionEqual;
438     } else if (!existingVersion && !!incomingVersion) {
439         return WidgetUpdateMode::ExistingVersionNewer;
440     } else if (!!existingVersion && !incomingVersion) {
441         return WidgetUpdateMode::ExistingVersionOlder;
442     } else {
443         LogInfo("Existing widget: version = '" << *existingVersion << "'");
444
445         if (!existingVersion->IsWac() && !incomingVersion->IsWac()) {
446             return WidgetUpdateMode::BothVersionsNotStd;
447         } else if (!existingVersion->IsWac()) {
448             return WidgetUpdateMode::ExistingVersionNotStd;
449         } else if (!incomingVersion->IsWac()) {
450             return WidgetUpdateMode::IncomingVersionNotStd;
451         } else {
452             // Both versions are WAC-comparable. Do compare.
453             if (*incomingVersion == *existingVersion) {
454                 return WidgetUpdateMode::ExistingVersionEqual;
455             } else if (*incomingVersion > *existingVersion) {
456                 return WidgetUpdateMode::ExistingVersionOlder;
457             } else {
458                 return WidgetUpdateMode::ExistingVersionNewer;
459             }
460         }
461     }
462 }
463
464 ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
465         const std::string &widgetSource,
466         bool fromBrowser, WrtDB::PkgType isOspsvc)
467 {
468     Try
469     {
470         // Parse config
471         ParserRunner parser;
472         ConfigParserData configInfo;
473
474         if (fromBrowser) {
475             parser.Parse(widgetSource,
476                          ElementParserPtr(
477                              new RootParser<WidgetParser>(configInfo,
478                                                           DPL::FromUTF32String(
479                                                               L"widget"))));
480         }
481         else {
482             // Open zip file
483             DPL::ScopedPtr<DPL::ZipInput> zipFile(
484                 new DPL::ZipInput(widgetSource));
485
486             DPL::ScopedPtr<DPL::ZipInput::File> configFile;
487
488             // Open config.xml file
489             if (isOspsvc == PKG_TYPE_TIZEN_WITHSVCAPP) {
490                 configFile.Reset(zipFile->OpenFile(WITH_OSP_XML));
491             } else {
492                 configFile.Reset(zipFile->OpenFile(CONFIG_XML));
493             }
494
495             // Extract config
496             DPL::BinaryQueue buffer;
497             DPL::AbstractWaitableInputAdapter inputAdapter(configFile.Get());
498             DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
499             DPL::Copy(&inputAdapter, &outputAdapter);
500             parser.Parse(&buffer,
501                          ElementParserPtr(
502                              new RootParser<WidgetParser>(configInfo,
503                                                           DPL::FromUTF32String(
504                                                               L"widget"))));
505         }
506
507         return configInfo;
508     }
509     Catch(DPL::ZipInput::Exception::OpenFailed)
510     {
511         LogDebug("Failed to open widget package");
512         return ConfigParserData();
513     }
514     Catch(DPL::ZipInput::Exception::OpenFileFailed)
515     {
516         LogDebug("Failed to open config.xml file");
517         return ConfigParserData();
518     }
519     Catch(DPL::CopyFailed)
520     {
521         LogDebug("Failed to extract config.xml file");
522         return ConfigParserData();
523     }
524     Catch(ElementParser::Exception::ParseError)
525     {
526         LogDebug("Failed to parse config.xml file");
527         return ConfigParserData();
528     }
529 }
530
531 WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
532         const ConfigParserData &configInfo)
533 {
534     LogInfo("Checking up widget package for config.xml...");
535
536     DPL::OptionalString widgetGUID;
537     OptionalWidgetVersion widgetVersion;
538
539     // Check widget id
540     widgetGUID = configInfo.widget_id;
541
542     if (widgetGUID.IsNull()) {
543         LogDebug("Installed widget has no GUID");
544         return WidgetUpdateInfo();
545     }
546
547     LogDebug("Installed widget GUID: " << *widgetGUID);
548
549     // Locate widget ID with this GUID
550     // Incoming widget version
551     if (!configInfo.version.IsNull()) {
552         widgetVersion =
553             DPL::Optional<WidgetVersion>(
554                 WidgetVersion(*configInfo.version));
555     }
556
557     Try
558     {
559         // Search widget handle by GUID
560         WidgetDAOReadOnly dao(widgetGUID);
561         return WidgetUpdateInfo(
562             widgetGUID,
563             widgetVersion,
564             WidgetUpdateInfo::ExistingWidgetInfo(
565                 dao.getHandle(), dao.getVersion()));
566     }
567     Catch(WidgetDAOReadOnly::Exception::WidgetNotExist)
568     {
569         // GUID isn't installed
570         return WidgetUpdateInfo(
571             widgetGUID,
572             widgetVersion,
573             WidgetUpdateInfo::ExistingWidgetInfo());
574     }
575 }
576
577 void JobWidgetInstall::SendProgress()
578 {
579     using namespace PackageManager;
580     if (GetProgressFlag() != false) {
581         if (getInstallerStruct().progressCallback != NULL) {
582             // send progress signal of pkgmgr
583             std::ostringstream percent;
584             percent << static_cast<int>(GetProgressPercent());
585             PkgmgrSignalSingleton::Instance().sendSignal(
586                         PKGMGR_PROGRESS_KEY,
587                         percent.str());
588
589             LogDebug("Call widget install progressCallbak");
590             getInstallerStruct().progressCallback(getInstallerStruct().userParam,
591                     GetProgressPercent(),GetProgressDescription());
592         }
593     }
594 }
595
596 void JobWidgetInstall::SendFinishedSuccess()
597 {
598     using namespace PackageManager;
599     // TODO : sync should move to separate task.
600     sync();
601
602     // remove widget install information file
603     unlink(m_installerContext.installInfo.c_str());
604
605     //inform widget info
606     JobWidgetInstall::displayWidgetInfo();
607
608     DPL::Optional<WidgetHandle> handle = getNewWidgetHandle();
609
610     // send signal of pkgmgr
611     PkgmgrSignalSingleton::Instance().sendSignal(
612                 PKGMGR_END_KEY,
613                 PKGMGR_END_SUCCESS);
614
615     LogDebug("Call widget install successfinishedCallback");
616     getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
617             !!handle ? *handle : WrtDB::INVALID_WIDGET_HANDLE, Exceptions::Success);
618 }
619
620 void JobWidgetInstall::SendFinishedFailure()
621 {
622     using namespace PackageManager;
623     // remove widget install information file
624     unlink(m_installerContext.installInfo.c_str());
625
626     LogError("Error in installation step: " << m_exceptionCaught);
627     LogError("Message: " << m_exceptionMessage);
628     DPL::Optional<WidgetHandle> handle = getNewWidgetHandle();
629
630     LogDebug("Call widget install failure finishedCallback");
631
632     // send signal of pkgmgr
633     PkgmgrSignalSingleton::Instance().sendSignal(
634                 PKGMGR_END_KEY,
635                 PKGMGR_END_FAILURE);
636
637     getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
638             !!handle ? *handle : WrtDB::INVALID_WIDGET_HANDLE, m_exceptionCaught);
639 }
640
641 void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
642 {
643     m_exceptionCaught = static_cast<Exceptions::Type>(e.getParam());
644     m_exceptionMessage = e.GetMessage();
645 }
646
647 void JobWidgetInstall::displayWidgetInfo()
648 {
649     DPL::Optional<WidgetHandle> handle = getNewWidgetHandle();
650     Assert(!!handle);
651
652     WidgetDAOReadOnly dao(*handle);
653
654     std::ostringstream out;
655     WidgetLocalizedInfo localizedInfo =
656         W3CFileLocalization::getLocalizedInfo(*handle);
657
658     out << std::endl <<
659         "===================================== INSTALLED WIDGET INFO ========="\
660         "============================";
661     out << std::endl << "Name:                        " << localizedInfo.name;
662     out << std::endl << "PkgName:                     " << dao.getPkgname();
663     WidgetSize size = dao.getPreferredSize();
664     out << std::endl << "Width:                       " << size.width;
665     out << std::endl << "Height:                      " << size.height;
666     out << std::endl << "Start File:                  " <<
667         W3CFileLocalization::getStartFile(*handle);
668     out << std::endl << "Version:                     " << dao.getVersion();
669     out << std::endl << "Licence:                     " <<
670         localizedInfo.license;
671     out << std::endl << "Licence Href:                " <<
672         localizedInfo.licenseHref;
673     out << std::endl << "Description:                 " <<
674         localizedInfo.description;
675     out << std::endl << "Widget Id:                   " << dao.getGUID();
676     out << std::endl << "Widget recognized:           " << dao.isRecognized();
677     out << std::endl << "Widget wac signed:           " << dao.isWacSigned();
678     out << std::endl << "Widget distributor signed:   " <<
679         dao.isDistributorSigned();
680     out << std::endl << "Widget trusted:              " << dao.isTrusted();
681
682     OptionalWidgetIcon icon = W3CFileLocalization::getIcon(*handle);
683     DPL::OptionalString iconSrc =
684         !!icon ? icon->src : DPL::OptionalString::Null;
685     out << std::endl << "Icon:                        " << iconSrc;
686
687     out << std::endl << "Preferences:";
688     {
689         PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList();
690         FOREACH(it, list)
691         {
692             out << std::endl << "  Key:                       " <<
693                 it->key_name;
694             out << std::endl << "      Readonly:              " <<
695                 it->readonly;
696         }
697     }
698
699     out << std::endl << "Features:";
700     {
701         WidgetFeatureSet list = dao.getFeaturesList();
702         FOREACH(it, list)
703         {
704             out << std::endl << "  Name:                      " << it->name;
705             out << std::endl << "      Required:              " << it->required;
706             out << std::endl << "      Params:";
707         }
708     }
709
710     out << std::endl;
711
712     LogInfo(out.str());
713 }
714
715 WrtDB::PackagingType JobWidgetInstall::checkPackageType(
716         const std::string &widgetSource)
717 {
718     using namespace WrtDB;
719
720     PackagingType pType = PKG_TYPE_UNKNOWN;
721     DPL::ScopedPtr<DPL::ZipInput> zipFile;
722
723     Try
724     {
725         // Open zip file
726         zipFile.Reset(new DPL::ZipInput(widgetSource));
727
728     }
729     Catch(DPL::ZipInput::Exception::OpenFailed)
730     {
731         LogDebug("Failed to open widget package");
732         return PKG_TYPE_UNKNOWN;
733     }
734
735     Try
736     {
737         // Open config.xml file in package root
738         DPL::ScopedPtr<DPL::ZipInput::File> configFile(
739                 zipFile->OpenFile(CONFIG_XML));
740         pType = PKG_TYPE_TIZEN_WEBAPP;
741     }
742     Catch(DPL::ZipInput::Exception::OpenFileFailed)
743     {
744         LogDebug("Could not find config.xml");
745     }
746
747     Try
748     {
749         // Open config.xml file in package root
750         DPL::ScopedPtr<DPL::ZipInput::File> configFile(
751                 zipFile->OpenFile(WITH_OSP_XML));
752         if (pType == PKG_TYPE_TIZEN_WEBAPP) {
753             return PKG_TYPE_UNKNOWN;
754         }
755
756         pType = PKG_TYPE_TIZEN_WITHSVCAPP;
757     }
758     Catch(DPL::ZipInput::Exception::OpenFileFailed)
759     {
760         LogDebug("Could not find wgt/config.xml");
761         return PKG_TYPE_UNKNOWN;
762     }
763
764     return pType;
765 }
766
767 bool JobWidgetInstall::detectResourceEncryption(const WrtDB::ConfigParserData &configData)
768 {
769     FOREACH(it, configData.settingsList)
770     {
771         if (it->m_name == SETTING_VALUE_ENCRYPTION &&
772                 it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE) {
773             LogDebug("resource need encryption");
774             return true;
775         }
776     }
777     return false;
778 }
779
780 } //namespace WidgetInstall
781 } //namespace Jobs