Pkgname (tizen id) - not null
[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_NOTNULL = *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_NOTNULL = 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_NOTNULL);
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_NOTNULL),
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::String pkgname = update.existingWidgetInfo.pkgname;
388
389         LogInfo("Widget model exists. package name: " << pkgname);
390
391         // Check running state
392         int retval = APP_MANAGER_ERROR_NONE;
393         bool isRunning = false;
394         retval = app_manager_is_running(DPL::ToUTF8String(pkgname).c_str(), &isRunning);
395         if (APP_MANAGER_ERROR_NONE != retval) {
396             LogError("Fail to get running state");
397             return ConfigureResult::Failed;
398         }
399
400         if (true == isRunning) {
401             // Must be deferred when update in progress
402             if (m_jobStruct.updateMode == WidgetUpdateMode::PolicyWac) {
403                 LogInfo(
404                     "Widget is already running. Policy is update according to WAC");
405
406                 return ConfigureResult::Deferred;
407             } else {
408                 LogInfo(
409                     "Widget is already running. Policy is not update according to WAC");
410                 LogInfo("Installation aborted: " << widgetSource);
411
412                 return ConfigureResult::Failed;
413             }
414         }
415
416         m_installerContext.widgetConfig.pkgname_NOTNULL = pkgname;
417         OptionalWidgetVersion existingVersion;
418         existingVersion = update.existingWidgetInfo.existingVersion;
419         OptionalWidgetVersion incomingVersion = update.incomingVersion;
420
421         updateTypeCheckBit = CalcWidgetUpdatePolicy(existingVersion,
422                                                     incomingVersion);
423         // Calc proceed flag
424         if ((m_jobStruct.updateMode & updateTypeCheckBit) > 0 ||
425             m_jobStruct.updateMode ==
426                 WidgetUpdateMode::PolicyDirectoryForceInstall)
427         {
428             LogInfo("Whether widget policy allow proceed ok");
429             ret = ConfigureResult::Updated;
430         }
431         else
432             return ConfigureResult::Failed;
433     }
434
435     if (!setTizenId(configData, ret)) {
436         return ConfigureResult::Failed;
437     } else {
438         using namespace PackageManager;
439         LogInfo("Tizen Id: " << m_installerContext.widgetConfig.pkgname_NOTNULL);
440
441         configureWidgetLocation(widgetSource, tempPath);
442
443         // send start signal of pkgmgr
444         PkgmgrSignalSingleton::Instance().setPkgname(
445                 DPL::ToUTF8String(m_installerContext.widgetConfig.pkgname_NOTNULL));
446         PkgmgrSignalSingleton::Instance().sendSignal(PKGMGR_START_KEY,
447                 PKGMGR_START_INSTALL);
448     }
449
450     // Init installer context
451     m_installerContext.installStep = InstallerContext::INSTALL_START;
452     m_installerContext.job = this;
453     m_installerContext.existingWidgetInfo = update.existingWidgetInfo;
454     m_installerContext.widgetConfig.shareHref = std::string();
455
456     // Return result
457     return ret;
458 }
459
460 WidgetUpdateMode::Type JobWidgetInstall::CalcWidgetUpdatePolicy(
461         const OptionalWidgetVersion &existingVersion,
462         const OptionalWidgetVersion &incomingVersion) const
463 {
464     // Widget is installed, check versions
465     if (!existingVersion && !incomingVersion) {
466         return WidgetUpdateMode::ExistingVersionEqual;
467     } else if (!existingVersion && !!incomingVersion) {
468         return WidgetUpdateMode::ExistingVersionNewer;
469     } else if (!!existingVersion && !incomingVersion) {
470         return WidgetUpdateMode::ExistingVersionOlder;
471     } else {
472         LogInfo("Existing widget: version = '" << *existingVersion << "'");
473
474         if (!existingVersion->IsWac() && !incomingVersion->IsWac()) {
475             return WidgetUpdateMode::BothVersionsNotStd;
476         } else if (!existingVersion->IsWac()) {
477             return WidgetUpdateMode::ExistingVersionNotStd;
478         } else if (!incomingVersion->IsWac()) {
479             return WidgetUpdateMode::IncomingVersionNotStd;
480         } else {
481             // Both versions are WAC-comparable. Do compare.
482             if (*incomingVersion == *existingVersion) {
483                 return WidgetUpdateMode::ExistingVersionEqual;
484             } else if (*incomingVersion > *existingVersion) {
485                 return WidgetUpdateMode::ExistingVersionOlder;
486             } else {
487                 return WidgetUpdateMode::ExistingVersionNewer;
488             }
489         }
490     }
491 }
492
493 ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
494         const std::string &widgetSource,
495         const std::string &tempPath,
496         WrtDB::PackagingType pkgType,
497         bool isDRM)
498 {
499     // Parse config
500     ParserRunner parser;
501     ConfigParserData configInfo;
502
503     Try
504     {
505         if (pkgType == PKG_TYPE_HOSTED_WEB_APP) {
506             parser.Parse(widgetSource,
507                     ElementParserPtr(
508                         new RootParser<WidgetParser>(configInfo,
509                             DPL::FromUTF32String(
510                                 L"widget"))));
511         } else if (pkgType == PKG_TYPE_DIRECTORY_WEB_APP) {
512             parser.Parse(widgetSource + '/' + CONFIG_XML,
513                          ElementParserPtr(
514                              new RootParser<WidgetParser>(
515                              configInfo,
516                              DPL::FromUTF32String(L"widget"))));
517         } else {
518             if (!isDRM) {
519                 std::unique_ptr<DPL::ZipInput> zipFile(
520                         new DPL::ZipInput(widgetSource));
521
522                 std::unique_ptr<DPL::ZipInput::File> configFile;
523
524                 // Open config.xml file
525                 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
526                     configFile.reset(zipFile->OpenFile(WITH_OSP_XML));
527                 } else {
528                     configFile.reset(zipFile->OpenFile(CONFIG_XML));
529                 }
530
531                 // Extract config
532                 DPL::BinaryQueue buffer;
533                 DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
534                 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
535                 DPL::Copy(&inputAdapter, &outputAdapter);
536                 parser.Parse(&buffer,
537                         ElementParserPtr(
538                             new RootParser<WidgetParser>(configInfo,
539                                 DPL::FromUTF32String(
540                                     L"widget"))));
541             } else {
542                 // DRM widget
543                 std::string configFile;
544                 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
545                     configFile = tempPath + "/" + WITH_OSP_XML;
546                 } else {
547                     configFile = tempPath + "/" + CONFIG_XML;
548                 }
549
550                 parser.Parse(configFile,
551                         ElementParserPtr(
552                             new RootParser<WidgetParser>(configInfo,
553                                 DPL::FromUTF32String(
554                                     L"widget"))));
555             }
556         }
557     }
558     Catch(DPL::ZipInput::Exception::OpenFailed)
559     {
560         LogError("Failed to open widget package");
561         return ConfigParserData();
562     }
563     Catch(DPL::ZipInput::Exception::OpenFileFailed)
564     {
565         LogError("Failed to open config.xml file");
566         return ConfigParserData();
567     }
568     Catch(DPL::CopyFailed)
569     {
570         LogError("Failed to extract config.xml file");
571         return ConfigParserData();
572     }
573     Catch(DPL::FileInput::Exception::OpenFailed)
574     {
575         LogError("Failed to open config.xml file");
576         return ConfigParserData();
577     }
578     Catch(ElementParser::Exception::ParseError)
579     {
580         LogError("Failed to parse config.xml file");
581         return ConfigParserData();
582     }
583     return configInfo;
584 }
585
586 WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
587         const ConfigParserData &configInfo)
588 {
589     LogInfo("Checking up widget package for config.xml...");
590
591     DPL::OptionalString widgetGUID;
592     OptionalWidgetVersion widgetVersion;
593
594     // Check widget id
595     widgetGUID = configInfo.widget_id;
596
597     if (widgetGUID.IsNull()) {
598         LogWarning("Installed widget has no GUID");
599         return WidgetUpdateInfo();
600     }
601
602     LogDebug("Installed widget GUID: " << *widgetGUID);
603
604     // Locate widget ID with this GUID
605     // Incoming widget version
606     if (!configInfo.version.IsNull()) {
607         widgetVersion =
608             DPL::Optional<WidgetVersion>(
609                 WidgetVersion(*configInfo.version));
610     }
611
612     Try
613     {
614         // Search widget handle by GUID
615         WidgetDAOReadOnly dao(widgetGUID);
616         return WidgetUpdateInfo(
617             widgetGUID,
618             widgetVersion,
619             WidgetUpdateInfo::ExistingWidgetInfo(
620                 dao.getPkgname_NOTNULL(), dao.getVersion()));
621     }
622     Catch(WidgetDAOReadOnly::Exception::WidgetNotExist)
623     {
624         // GUID isn't installed
625         return WidgetUpdateInfo(
626             widgetGUID,
627             widgetVersion,
628             WidgetUpdateInfo::ExistingWidgetInfo());
629     }
630 }
631
632 void JobWidgetInstall::SendProgress()
633 {
634     using namespace PackageManager;
635     if (GetProgressFlag() != false) {
636         if (getInstallerStruct().progressCallback != NULL) {
637             // send progress signal of pkgmgr
638             std::ostringstream percent;
639             percent << static_cast<int>(GetProgressPercent());
640             PkgmgrSignalSingleton::Instance().sendSignal(
641                         PKGMGR_PROGRESS_KEY,
642                         percent.str());
643
644             LogDebug("Call widget install progressCallbak");
645             getInstallerStruct().progressCallback(getInstallerStruct().userParam,
646                     GetProgressPercent(),GetProgressDescription());
647         }
648     }
649 }
650
651 void JobWidgetInstall::SendFinishedSuccess()
652 {
653     using namespace PackageManager;
654     // TODO : sync should move to separate task.
655     sync();
656
657     // remove widget install information file
658     unlink(m_installerContext.installInfo.c_str());
659
660     //inform widget info
661     JobWidgetInstall::displayWidgetInfo();
662
663     DPL::String & tizenId = m_installerContext.widgetConfig.pkgname_NOTNULL;
664
665     // send signal of pkgmgr
666     PkgmgrSignalSingleton::Instance().sendSignal(
667                 PKGMGR_END_KEY,
668                 PKGMGR_END_SUCCESS);
669
670     LogDebug("Call widget install successfinishedCallback");
671     getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
672             DPL::ToUTF8String(tizenId), Exceptions::Success);
673 }
674
675 void JobWidgetInstall::SendFinishedFailure()
676 {
677     using namespace PackageManager;
678     // remove widget install information file
679     unlink(m_installerContext.installInfo.c_str());
680
681     LogError("Error in installation step: " << m_exceptionCaught);
682     LogError("Message: " << m_exceptionMessage);
683     DPL::String & tizenId = m_installerContext.widgetConfig.pkgname_NOTNULL;
684
685     LogDebug("Call widget install failure finishedCallback");
686
687     // send signal of pkgmgr
688     PkgmgrSignalSingleton::Instance().sendSignal(
689                 PKGMGR_END_KEY,
690                 PKGMGR_END_FAILURE);
691
692     getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
693             DPL::ToUTF8String(tizenId), m_exceptionCaught);
694 }
695
696 void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
697 {
698     m_exceptionCaught = static_cast<Exceptions::Type>(e.getParam());
699     m_exceptionMessage = e.GetMessage();
700 }
701
702 void JobWidgetInstall::displayWidgetInfo()
703 {
704     WidgetDAOReadOnly dao(m_installerContext.locations->getPkgname());
705
706     std::ostringstream out;
707     WidgetLocalizedInfo localizedInfo =
708         W3CFileLocalization::getLocalizedInfo(dao.getPkgname_NOTNULL());
709
710     out << std::endl <<
711         "===================================== INSTALLED WIDGET INFO ========="\
712         "============================";
713     out << std::endl << "Name:                        " << localizedInfo.name;
714     out << std::endl << "PkgName:                     " << dao.getPkgname_NOTNULL();
715     WidgetSize size = dao.getPreferredSize();
716     out << std::endl << "Width:                       " << size.width;
717     out << std::endl << "Height:                      " << size.height;
718     out << std::endl << "Start File:                  " <<
719         W3CFileLocalization::getStartFile(dao.getPkgname_NOTNULL());
720     out << std::endl << "Version:                     " << dao.getVersion();
721     out << std::endl << "Licence:                     " <<
722         localizedInfo.license;
723     out << std::endl << "Licence Href:                " <<
724         localizedInfo.licenseHref;
725     out << std::endl << "Description:                 " <<
726         localizedInfo.description;
727     out << std::endl << "Widget Id:                   " << dao.getGUID();
728     out << std::endl << "Widget recognized:           " << dao.isRecognized();
729     out << std::endl << "Widget wac signed:           " << dao.isWacSigned();
730     out << std::endl << "Widget distributor signed:   " <<
731         dao.isDistributorSigned();
732     out << std::endl << "Widget trusted:              " << dao.isTrusted();
733
734     OptionalWidgetIcon icon = W3CFileLocalization::getIcon(dao.getPkgname_NOTNULL());
735     DPL::OptionalString iconSrc =
736         !!icon ? icon->src : DPL::OptionalString::Null;
737     out << std::endl << "Icon:                        " << iconSrc;
738
739     out << std::endl << "Preferences:";
740     {
741         PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList();
742         FOREACH(it, list)
743         {
744             out << std::endl << "  Key:                       " <<
745                 it->key_name;
746             out << std::endl << "      Readonly:              " <<
747                 it->readonly;
748         }
749     }
750
751     out << std::endl << "Features:";
752     {
753         WidgetFeatureSet list = dao.getFeaturesList();
754         FOREACH(it, list)
755         {
756             out << std::endl << "  Name:                      " << it->name;
757             out << std::endl << "      Required:              " << it->required;
758             out << std::endl << "      Params:";
759         }
760     }
761
762     out << std::endl;
763
764     LogInfo(out.str());
765 }
766
767 WrtDB::PackagingType JobWidgetInstall::checkPackageType(
768         const std::string &widgetSource,
769         const std::string &tempPath)
770 {
771     // Check installation type (direcotory/ or config.xml or widget.wgt)
772     if (WidgetUpdateMode::PolicyDirectoryForceInstall == m_jobStruct.updateMode)
773     {
774         LogDebug("Install directly from directory");
775         return PKG_TYPE_DIRECTORY_WEB_APP;
776     }
777     if (hasExtension(widgetSource, XML_EXTENSION)) {
778         LogInfo("Hosted app installation");
779         return PKG_TYPE_HOSTED_WEB_APP;
780     }
781
782     if (m_isDRM) {
783         std::string configFile = tempPath + "/" + CONFIG_XML;
784         if (WrtUtilFileExists(configFile)) {
785             return PKG_TYPE_NOMAL_WEB_APP;
786         }
787
788         configFile = tempPath + "/" + WITH_OSP_XML;
789         if (WrtUtilFileExists(configFile)) {
790             return PKG_TYPE_HYBRID_WEB_APP;
791         }
792     } else {
793         std::unique_ptr<DPL::ZipInput> zipFile;
794
795         Try
796         {
797             // Open zip file
798             zipFile.reset(new DPL::ZipInput(widgetSource));
799
800         }
801         Catch(DPL::ZipInput::Exception::OpenFailed)
802         {
803             LogDebug("Failed to open widget package");
804             return PKG_TYPE_UNKNOWN;
805         }
806
807         Try
808         {
809             // Open config.xml file in package root
810             std::unique_ptr<DPL::ZipInput::File> configFile(
811                     zipFile->OpenFile(CONFIG_XML));
812             return PKG_TYPE_NOMAL_WEB_APP;
813         }
814         Catch(DPL::ZipInput::Exception::OpenFileFailed)
815         {
816             LogDebug("Could not find config.xml");
817         }
818
819         Try
820         {
821             // Open config.xml file in package root
822             std::unique_ptr<DPL::ZipInput::File> configFile(
823                     zipFile->OpenFile(WITH_OSP_XML));
824
825             return PKG_TYPE_HYBRID_WEB_APP;
826         }
827         Catch(DPL::ZipInput::Exception::OpenFileFailed)
828         {
829             LogDebug("Could not find wgt/config.xml");
830             return PKG_TYPE_UNKNOWN;
831         }
832     }
833
834     return PKG_TYPE_UNKNOWN;
835 }
836
837 bool JobWidgetInstall::detectResourceEncryption(const WrtDB::ConfigParserData &configData)
838 {
839     FOREACH(it, configData.settingsList)
840     {
841         if (it->m_name == SETTING_VALUE_ENCRYPTION &&
842                 it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE) {
843             LogDebug("resource need encryption");
844             return true;
845         }
846     }
847     return false;
848 }
849
850 bool JobWidgetInstall::isDRMWidget(std::string widgetPath)
851 {
852     /* TODO :
853     drm_bool_type_e is_drm_file = DRM_UNKNOWN;
854     int ret = -1;
855
856     ret = drm_is_drm_file(widgetPath.c_str(), &is_drm_file);
857     if(DRM_RETURN_SUCCESS == ret && DRM_TRUE == is_drm_file) {
858     */
859
860     /* blow code temporary code for drm. */
861     int ret = drm_oem_intel_isDrmFile(const_cast<char*>(widgetPath.c_str()));
862     if ( 1 == ret) {
863         return true;
864     } else {
865         return false;
866     }
867 }
868
869 bool JobWidgetInstall::DecryptDRMWidget(std::string widgetPath,
870         std::string destPath)
871 {
872     /* TODO :
873     drm_trusted_sapps_decrypt_package_info_s package_info;
874
875     strncpy(package_info.sadcf_filepath, widgetPath.c_str(),
876             sizeof(package_info.sadcf_filepath));
877     strncpy(package_info.decrypt_filepath, destPath.c_str(),
878             sizeof(package_info.decrypt_filepath));
879
880     drm_trusted_request_type_e requestType =
881         DRM_TRUSTED_REQ_TYPE_SAPPS_DECRYPT_PACKAGE;
882
883     int ret = drm_trusted_handle_request(requestType,
884                                          (void *)&package_info, NULL);
885     if (DRM_TRUSTED_RETURN_SUCCESS == ret) {
886         return true;
887     } else {
888         return false;
889     }
890     */
891     if (drm_oem_intel_decrypt_package(const_cast<char*>(widgetPath.c_str()),
892                 const_cast<char*>(destPath.c_str())) != 0) {
893         return true;
894     } else {
895         return false;
896     }
897 }
898
899 } //namespace WidgetInstall
900 } //namespace Jobs