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