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