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