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