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