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