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