Change pkgname to appid for docomo request. PART2
[framework/web/wrt-installer.git] / src / jobs / widget_install / job_widget_install.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file    job_widget_install.cpp
18  * @author  Radoslaw Wicik r.wicik@samsung.com
19  * @author  Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20  * @version 1.0
21  * @brief   Implementation file for main installer task
22  */
23 #include <memory>
24 #include <string>
25 #include <sys/time.h>
26 #include <ctime>
27 #include <cstdlib>
28 #include <limits.h>
29 #include <regex.h>
30
31 #include <dpl/noncopyable.h>
32 #include <dpl/abstract_waitable_input_adapter.h>
33 #include <dpl/abstract_waitable_output_adapter.h>
34 #include <dpl/zip_input.h>
35 #include <dpl/binary_queue.h>
36 #include <dpl/copy.h>
37 #include <dpl/assert.h>
38 #include <dpl/sstream.h>
39 #include <dpl/file_input.h>
40 #include <dpl/utils/wrt_utility.h>
41 #include <dpl/wrt-dao-ro/common_dao_types.h>
42 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
43 #include <dpl/wrt-dao-ro/global_config.h>
44 #include <dpl/wrt-dao-rw/global_dao.h> // TODO remove
45 #include <dpl/localization/w3c_file_localization.h>
46
47 #include <libiriwrapper.h>
48 #include <pkg-manager/pkgmgr_signal.h>
49 #include <app_manager.h>
50 //#include <drm_client.h>
51 #include <drm-oem-intel.h> //temporary code
52
53 #include "root_parser.h"
54 #include "widget_parser.h"
55 #include "parser_runner.h"
56 #include <widget_install/job_widget_install.h>
57 #include <widget_install/task_certify.h>
58 #include <widget_install/task_widget_config.h>
59 #include <widget_install/task_file_manipulation.h>
60 #include <widget_install/task_ace_check.h>
61 #include <widget_install/task_smack.h>
62 #include <widget_install/task_manifest_file.h>
63 #include <widget_install/task_prepare_files.h>
64 #include <widget_install/task_recovery.h>
65 #include <widget_install/task_install_ospsvc.h>
66 #include <widget_install/task_update_files.h>
67 #include <widget_install/task_database.h>
68 #include <widget_install/task_remove_backup.h>
69 #include <widget_install/task_encrypt_resource.h>
70 #include <widget_install/task_certificates.h>
71 #include <widget_install/task_unzip.h>
72 #include <widget_install/task_commons.h>
73
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 #include <widget_install_to_external.h>
79
80 using namespace WrtDB;
81
82 namespace // anonymous
83 {
84 const char * const CONFIG_XML = "config.xml";
85 const char * const WITH_OSP_XML = "res/wgt/config.xml";
86
87 //allowed: a-z, A-Z, 0-9
88 const char* REG_TIZENID_PATTERN = "^[a-zA-Z0-9]{10}.[a-zA-Z0-9]{1,}$";
89 const size_t PACKAGE_ID_LENGTH = 10;
90
91 static const DPL::String SETTING_VALUE_ENCRYPTION = L"encryption";
92 static const DPL::String SETTING_VALUE_ENCRYPTION_ENABLE = L"enable";
93 const DPL::String SETTING_VALUE_INSTALLTOEXT_NAME =
94     L"install-location-type";
95 const DPL::String SETTING_VALUE_INSTALLTOEXT_PREPER_EXT =
96     L"prefer-external";
97
98 class InstallerTaskFail :
99     public DPL::TaskDecl<InstallerTaskFail>
100 {
101   private:
102     bool m_deferred;
103
104     void StepFail()
105     {
106         if (m_deferred) {
107             ThrowMsg(Jobs::WidgetInstall::Exceptions::Deferred,
108                      "Widget installation or update deferred!");
109         } else {
110             ThrowMsg(Jobs::WidgetInstall::Exceptions::NotAllowed,
111                      "Widget installation or update not allowed!");
112         }
113     }
114
115   public:
116     InstallerTaskFail(bool deferred) :
117         DPL::TaskDecl<InstallerTaskFail>(this),
118         m_deferred(deferred)
119     {
120         AddStep(&InstallerTaskFail::StepFail);
121     }
122 };
123
124 const std::string XML_EXTENSION = ".xml";
125
126 bool hasExtension(const std::string& filename, const std::string& extension) {
127     LogDebug("Looking for extension " << extension << " in: "  << filename);
128     size_t fileLen = filename.length();
129     size_t extLen = extension.length();
130     if (fileLen < extLen) {
131         LogError("Filename " << filename << " is shorter than extension "
132                  << extension);
133         return false;
134     }
135     return (0 == filename.compare(fileLen-extLen, extLen, extension));
136 }
137
138 bool checkTizenPkgIdExist(const std::string& tizenPkgId) {
139     std::string installPath =
140         std::string(GlobalConfig::GetUserInstalledWidgetPath()) +
141         "/" + tizenPkgId;
142     std::string preinstallPath =
143         std::string(GlobalConfig::GetUserPreloadedWidgetPath()) +
144         "/" + tizenPkgId;
145
146     struct stat dirStat;
147     if ((stat(installPath.c_str(), &dirStat) == 0) &&
148             (stat(preinstallPath.c_str(), &dirStat) == 0)) {
149         return true;
150     }
151     return false;
152 }
153 } // namespace anonymous
154
155 namespace Jobs {
156 namespace WidgetInstall {
157 JobWidgetInstall::JobWidgetInstall(std::string const &widgetPath,
158         const WidgetInstallationStruct &installerStruct) :
159     Job(Installation),
160     JobContextBase<WidgetInstallationStruct>(installerStruct),
161     m_exceptionCaught(Exceptions::Success)
162 {
163     struct timeval tv;
164     gettimeofday(&tv, NULL);
165     srand(time(NULL) + tv.tv_usec);
166
167     m_installerContext.m_quiet = m_jobStruct.m_quiet;
168
169     ConfigureResult result = PrePareInstallation(widgetPath);
170
171     if (result == ConfigureResult::Ok) {
172         LogInfo("Configure installation succeeded");
173
174         AddTask(new TaskRecovery(m_installerContext));
175
176         // Create installation tasks
177         if (m_installerContext.widgetConfig.packagingType !=
178                 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
179             m_installerContext.widgetConfig.packagingType !=
180                 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
181             !m_isDRM)
182         {
183             AddTask(new TaskUnzip(m_installerContext));
184         }
185
186         AddTask(new TaskWidgetConfig(m_installerContext));
187         if (m_installerContext.widgetConfig.packagingType  ==
188                 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
189         {
190             AddTask(new TaskPrepareFiles(m_installerContext));
191         }
192         AddTask(new TaskCertify(m_installerContext));
193         if (m_needEncryption) {
194             AddTask(new TaskEncryptResource(m_installerContext));
195         }
196
197         AddTask(new TaskFileManipulation(m_installerContext));
198         // TODO: Update progress information for this task
199
200         //This is sort of quick solution, because ACE verdicts are based upon
201         //data from DAO (DB). So AceCheck for now has to be AFTER DbUpdate
202         //task.
203         AddTask(new TaskSmack(m_installerContext));
204
205         AddTask(new TaskManifestFile(m_installerContext));
206         AddTask(new TaskCertificates(m_installerContext));
207         if (m_installerContext.widgetConfig.packagingType ==
208                 PKG_TYPE_HYBRID_WEB_APP) {
209             AddTask(new TaskInstallOspsvc(m_installerContext));
210         }
211         AddTask(new TaskPluginsCopy(m_installerContext));
212         AddTask(new TaskDatabase(m_installerContext));
213         AddTask(new TaskAceCheck(m_installerContext));
214     } else if (result == ConfigureResult::Updated) {
215         LogInfo("Configure installation updated");
216         LogInfo("Widget Update");
217         if (m_installerContext.widgetConfig.packagingType !=
218                 WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
219             m_installerContext.widgetConfig.packagingType !=
220                 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP &&
221             !m_isDRM)
222         {
223             AddTask(new TaskUnzip(m_installerContext));
224         }
225
226         AddTask(new TaskWidgetConfig(m_installerContext));
227
228         if (m_installerContext.widgetConfig.packagingType ==
229                 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
230         {
231             AddTask(new TaskPrepareFiles(m_installerContext));
232         }
233
234         AddTask(new TaskCertify(m_installerContext));
235         if (m_installerContext.widgetConfig.packagingType !=
236             WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
237         {
238             AddTask(new TaskUpdateFiles(m_installerContext));
239         }
240
241         /* TODO : To backup file, save md5 values */
242         AddTask(new TaskSmack(m_installerContext));
243
244         AddTask(new TaskManifestFile(m_installerContext));
245         if (m_installerContext.widgetConfig.packagingType ==
246                 PKG_TYPE_HYBRID_WEB_APP) {
247             AddTask(new TaskInstallOspsvc(m_installerContext));
248         }
249         if (m_installerContext.widgetConfig.packagingType !=
250             WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
251         {
252             AddTask(new TaskRemoveBackupFiles(m_installerContext));
253         }
254         AddTask(new TaskPluginsCopy(m_installerContext));
255         AddTask(new TaskDatabase(m_installerContext));
256         AddTask(new TaskAceCheck(m_installerContext));
257         //TODO: remove widgetHandle from this task and move before database task
258         // by now widget handle is needed in ace check
259         // Any error in acecheck while update will break widget
260
261     } else if (result == ConfigureResult::Deferred) {
262         // Installation is deferred
263         LogInfo("Configure installation deferred");
264
265         AddTask(new InstallerTaskFail(true));
266     } else if (result == ConfigureResult::Failed) {
267         // Installation is not allowed to proceed due to widget update policy
268         LogWarning("Configure installation failed!");
269
270         AddTask(new InstallerTaskFail(false));
271     } else {
272         Assert(false && "Invalid configure result!");
273     }
274 }
275
276 JobWidgetInstall::ConfigureResult JobWidgetInstall::PrePareInstallation(
277         const std::string &widgetPath)
278 {
279     ConfigureResult result;
280     m_needEncryption = false;
281
282     Try
283     {
284         std::string tempDir =
285             Jobs::WidgetInstall::createTempPath(m_jobStruct.m_preload);
286
287         m_isDRM = isDRMWidget(widgetPath);
288         if (true == m_isDRM) {
289             LogDebug("decrypt DRM widget");
290             if(DecryptDRMWidget(widgetPath, tempDir)) {
291                 LogDebug("Failed decrypt DRM widget");
292                 return ConfigureResult::Failed;
293             }
294         }
295
296         LogDebug("widgetPath:" << widgetPath);
297
298         m_installerContext.widgetConfig.packagingType =
299             checkPackageType(widgetPath, tempDir);
300         ConfigParserData configData = getWidgetDataFromXML(
301             widgetPath,
302             tempDir,
303             m_installerContext.widgetConfig.packagingType,
304             m_isDRM);
305         LogDebug("widget packaging type : " <<
306                 m_installerContext.widgetConfig.packagingType.pkgType);
307
308         setTizenId(configData);
309         setApplicationType(configData);
310         m_needEncryption = detectResourceEncryption(configData);
311         setInstallLocationType(configData);
312
313         // Configure installation
314         result = ConfigureInstallation(widgetPath, configData, tempDir);
315     }
316     Catch(Exceptions::ExtractFileFailed)
317     {
318         LogError("Failed to create temporary path for widget");
319         result = ConfigureResult::Failed;
320     }
321
322     return result;
323 }
324
325 void JobWidgetInstall::setTizenId(
326         const WrtDB::ConfigParserData &configInfo)
327 {
328     bool shouldMakeAppid = false;
329     using namespace PackageManager;
330     if(!!configInfo.tizenAppId) {
331         LogDebug("Setting tizenAppId provided in config.xml: " <<
332                 configInfo.tizenAppId);
333
334         m_installerContext.widgetConfig.tzAppid = *configInfo.tizenAppId;
335         //check package id.
336         if(!!configInfo.tizenPkgId) {
337             LogDebug("Setting tizenPkgId provided in config.xml: " <<
338                     configInfo.tizenPkgId);
339
340             m_installerContext.widgetConfig.tzPkgid = *configInfo.tizenPkgId;
341         } else {
342             std::string appid = DPL::ToUTF8String(*configInfo.tizenAppId);
343             if(appid.length() > PACKAGE_ID_LENGTH) {
344                 m_installerContext.widgetConfig.tzPkgid =
345                     DPL::FromUTF8String(appid.substr(PACKAGE_ID_LENGTH));
346             } else {
347                 m_installerContext.widgetConfig.tzPkgid =
348                     *configInfo.tizenAppId;
349             }
350             shouldMakeAppid = true;
351         }
352     } else {
353         shouldMakeAppid = true;
354         TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId();
355         LogDebug("Checking if pkg id is unique");
356         while (true) {
357             if (checkTizenPkgIdExist(DPL::ToUTF8String(pkgId))) {
358                 //path exist, chose another one
359                 pkgId = WidgetDAOReadOnly::generatePkgId();
360                 continue;
361             }
362             break;
363         }
364         m_installerContext.widgetConfig.tzPkgid = pkgId;
365         LogInfo("tizen_id name was generated by WRT: " <<
366                 m_installerContext.widgetConfig.tzPkgid);
367
368     }
369
370     if(shouldMakeAppid == true) {
371         DPL::OptionalString name;
372         DPL::OptionalString defaultLocale = configInfo.defaultlocale;
373
374         FOREACH(localizedData, configInfo.localizedDataSet)
375         {
376             Locale i = localizedData->first;
377             if (!!defaultLocale) {
378                 if (defaultLocale == i) {
379                     name = localizedData->second.name;
380                     break;
381                 }
382
383             } else {
384                 name = localizedData->second.name;
385                 break;
386             }
387         }
388         if (!!name) {
389             LogDebug("Name : " << name);
390             std::ostringstream appid;
391             appid << m_installerContext.widgetConfig.tzPkgid << "." << name;
392             LogDebug("tizen appid was generated by WRT : " << appid.str());
393             m_installerContext.widgetConfig.tzAppid =
394                 DPL::FromUTF8String(appid.str());
395         } else {
396             m_installerContext.widgetConfig.tzAppid =
397                 m_installerContext.widgetConfig.tzPkgid;
398         }
399     }
400
401     // send start signal of pkgmgr
402     getInstallerStruct().pkgmgrInterface->setPkgname(DPL::ToUTF8String(
403                 m_installerContext.widgetConfig.tzAppid));
404     getInstallerStruct().pkgmgrInterface->sendSignal(
405             PKGMGR_START_KEY,
406             PKGMGR_START_INSTALL);
407
408     LogInfo("Tizen App Id : " << m_installerContext.widgetConfig.tzAppid);
409     LogInfo("Tizen Pkg Id : " << m_installerContext.widgetConfig.tzPkgid);
410     LogInfo("W3C Widget GUID : " << m_installerContext.widgetConfig.guid);
411 }
412
413 void JobWidgetInstall::configureWidgetLocation(const std::string & widgetPath,
414                                                const std::string& tempPath)
415 {
416     m_installerContext.locations =
417         WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.tzPkgid),
418                 widgetPath, tempPath,
419                 m_installerContext.widgetConfig.packagingType,
420                 m_installerContext.locationType);
421     m_installerContext.locations->registerAppid(
422             DPL::ToUTF8String(m_installerContext.widgetConfig.tzAppid));
423
424     LogInfo("widgetSource " << widgetPath);
425 }
426
427 JobWidgetInstall::ConfigureResult JobWidgetInstall::ConfigureInstallation(
428         const std::string &widgetSource,
429         const WrtDB::ConfigParserData &configData,
430         const std::string &tempPath)
431 {
432     WidgetUpdateInfo update = detectWidgetUpdate(configData,
433             m_installerContext.widgetConfig.webAppType,
434             m_installerContext.widgetConfig.tzAppid);
435     ConfigureResult result = checkWidgetUpdate(update);
436
437     // Validate tizenId
438     regex_t reg;
439     if(regcomp(&reg, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED)!=0){
440         LogDebug("Regcomp failed");
441     }
442
443     if ((regexec(&reg,
444                     DPL::ToUTF8String(m_installerContext.widgetConfig.tzAppid).c_str(),
445                     static_cast<size_t>(0), NULL, 0) != REG_NOERROR) ||
446             (checkTizenPkgIdExist(DPL::ToUTF8String(m_installerContext.widgetConfig.tzPkgid)) &&
447              result != ConfigureResult::Updated))
448     {
449         //it is true when tizenId does not fit REG_TIZENID_PATTERN
450         LogError("tizen_id provided but not proper.");
451         regfree(&reg);
452         return ConfigureResult::Failed;
453     }
454     regfree(&reg);
455
456     configureWidgetLocation(widgetSource, tempPath);
457
458     // Init installer context
459     m_installerContext.installStep = InstallerContext::INSTALL_START;
460     m_installerContext.job = this;
461     m_installerContext.existingWidgetInfo = update.existingWidgetInfo;
462     m_installerContext.widgetConfig.shareHref = std::string();
463
464     return result;
465 }
466
467 JobWidgetInstall::ConfigureResult JobWidgetInstall::checkWidgetUpdate(
468         const WidgetUpdateInfo &update)
469 {
470     LogInfo(
471         "Widget install/update: incoming guid = '" <<
472         update.incomingGUID << "'");
473     LogInfo(
474         "Widget install/update: incoming version = '" <<
475         update.incomingVersion << "'");
476
477     // Check policy
478     WidgetUpdateMode::Type updateTypeCheckBit;
479
480     if (update.existingWidgetInfo.isExist == false) {
481         LogInfo("Widget info does not exist");
482         updateTypeCheckBit = WidgetUpdateMode::NotInstalled;
483     } else {
484         LogInfo("Widget info exists. appid: " <<
485                 update.existingWidgetInfo.tzAppid);
486
487         TizenAppId tzAppid = update.existingWidgetInfo.tzAppid;
488
489         LogInfo("Widget model exists. tizen app id: " << tzAppid);
490
491         // Check running state
492         int retval = APP_MANAGER_ERROR_NONE;
493         bool isRunning = false;
494         retval = app_manager_is_running(DPL::ToUTF8String(tzAppid).c_str(), &isRunning);
495         if (APP_MANAGER_ERROR_NONE != retval) {
496             LogError("Fail to get running state");
497             return ConfigureResult::Failed;
498         }
499
500         if (true == isRunning) {
501             // Must be deferred when update in progress
502             if (m_jobStruct.updateMode == WidgetUpdateMode::PolicyWac) {
503                 LogInfo(
504                     "Widget is already running. Policy is update according to WAC");
505
506                 return ConfigureResult::Deferred;
507             } else {
508                 LogInfo(
509                     "Widget is already running. Policy is not update according to WAC");
510
511                 return ConfigureResult::Failed;
512             }
513         }
514
515         m_installerContext.widgetConfig.tzAppid = tzAppid;
516         OptionalWidgetVersion existingVersion;
517         existingVersion = update.existingWidgetInfo.existingVersion;
518         OptionalWidgetVersion incomingVersion = update.incomingVersion;
519
520         updateTypeCheckBit = CalcWidgetUpdatePolicy(existingVersion,
521                                                     incomingVersion);
522         // Calc proceed flag
523         if ((m_jobStruct.updateMode & updateTypeCheckBit) > 0 ||
524             m_jobStruct.updateMode ==
525                 WidgetUpdateMode::PolicyDirectoryForceInstall)
526         {
527             LogInfo("Whether widget policy allow proceed ok");
528             return ConfigureResult::Updated;
529         }
530         else
531             return ConfigureResult::Failed;
532     }
533     return ConfigureResult::Ok;
534 }
535
536 WidgetUpdateMode::Type JobWidgetInstall::CalcWidgetUpdatePolicy(
537         const OptionalWidgetVersion &existingVersion,
538         const OptionalWidgetVersion &incomingVersion) const
539 {
540     // Widget is installed, check versions
541     if (!existingVersion && !incomingVersion) {
542         return WidgetUpdateMode::ExistingVersionEqual;
543     } else if (!existingVersion && !!incomingVersion) {
544         return WidgetUpdateMode::ExistingVersionNewer;
545     } else if (!!existingVersion && !incomingVersion) {
546         return WidgetUpdateMode::ExistingVersionOlder;
547     } else {
548         LogInfo("Existing widget: version = '" << *existingVersion << "'");
549
550         if (!existingVersion->IsWac() && !incomingVersion->IsWac()) {
551             return WidgetUpdateMode::BothVersionsNotStd;
552         } else if (!existingVersion->IsWac()) {
553             return WidgetUpdateMode::ExistingVersionNotStd;
554         } else if (!incomingVersion->IsWac()) {
555             return WidgetUpdateMode::IncomingVersionNotStd;
556         } else {
557             // Both versions are WAC-comparable. Do compare.
558             if (*incomingVersion == *existingVersion) {
559                 return WidgetUpdateMode::ExistingVersionEqual;
560             } else if (*incomingVersion > *existingVersion) {
561                 return WidgetUpdateMode::ExistingVersionOlder;
562             } else {
563                 return WidgetUpdateMode::ExistingVersionNewer;
564             }
565         }
566     }
567 }
568
569 ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
570         const std::string &widgetSource,
571         const std::string &tempPath,
572         WrtDB::PackagingType pkgType,
573         bool isDRM)
574 {
575     // Parse config
576     ParserRunner parser;
577     ConfigParserData configInfo;
578
579     Try
580     {
581         if (pkgType == PKG_TYPE_HOSTED_WEB_APP) {
582             parser.Parse(widgetSource,
583                     ElementParserPtr(
584                         new RootParser<WidgetParser>(configInfo,
585                             DPL::FromUTF32String(
586                                 L"widget"))));
587         } else if (pkgType == PKG_TYPE_DIRECTORY_WEB_APP) {
588             parser.Parse(widgetSource + '/' + WITH_OSP_XML,
589                          ElementParserPtr(
590                              new RootParser<WidgetParser>(
591                              configInfo,
592                              DPL::FromUTF32String(L"widget"))));
593         } else {
594             if (!isDRM) {
595                 std::unique_ptr<DPL::ZipInput> zipFile(
596                         new DPL::ZipInput(widgetSource));
597
598                 std::unique_ptr<DPL::ZipInput::File> configFile;
599
600                 // Open config.xml file
601                 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
602                     configFile.reset(zipFile->OpenFile(WITH_OSP_XML));
603                 } else {
604                     configFile.reset(zipFile->OpenFile(CONFIG_XML));
605                 }
606
607                 // Extract config
608                 DPL::BinaryQueue buffer;
609                 DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
610                 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
611                 DPL::Copy(&inputAdapter, &outputAdapter);
612                 parser.Parse(&buffer,
613                         ElementParserPtr(
614                             new RootParser<WidgetParser>(configInfo,
615                                 DPL::FromUTF32String(
616                                     L"widget"))));
617             } else {
618                 // DRM widget
619                 std::string configFile;
620                 if (pkgType == PKG_TYPE_HYBRID_WEB_APP) {
621                     configFile = tempPath + "/" + WITH_OSP_XML;
622                 } else {
623                     configFile = tempPath + "/" + CONFIG_XML;
624                 }
625
626                 parser.Parse(configFile,
627                         ElementParserPtr(
628                             new RootParser<WidgetParser>(configInfo,
629                                 DPL::FromUTF32String(
630                                     L"widget"))));
631             }
632         }
633     }
634     Catch(DPL::ZipInput::Exception::OpenFailed)
635     {
636         LogError("Failed to open widget package");
637         return ConfigParserData();
638     }
639     Catch(DPL::ZipInput::Exception::OpenFileFailed)
640     {
641         LogError("Failed to open config.xml file");
642         return ConfigParserData();
643     }
644     Catch(DPL::CopyFailed)
645     {
646         LogError("Failed to extract config.xml file");
647         return ConfigParserData();
648     }
649     Catch(DPL::FileInput::Exception::OpenFailed)
650     {
651         LogError("Failed to open config.xml file");
652         return ConfigParserData();
653     }
654     Catch(ElementParser::Exception::ParseError)
655     {
656         LogError("Failed to parse config.xml file");
657         return ConfigParserData();
658     }
659     Catch(DPL::ZipInput::Exception::SeekFileFailed)
660     {
661         LogError("Failed to seek widget archive - corrupted package?");
662         return ConfigParserData();
663     }
664     return configInfo;
665 }
666
667 WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
668         const ConfigParserData &configInfo,
669         const WrtDB::WidgetType appType,
670         const WrtDB::TizenAppId &tizenId)
671 {
672     LogInfo("Checking up widget package for config.xml...");
673
674     DPL::OptionalString widgetGUID;
675     OptionalWidgetVersion widgetVersion;
676
677     // Check widget id
678     widgetGUID = configInfo.widget_id;
679
680     if (widgetGUID.IsNull()) {
681         LogWarning("Installed widget has no GUID");
682         return WidgetUpdateInfo();
683     }
684
685     LogDebug("Installed widget GUID: " << *widgetGUID);
686
687     // Locate widget ID with this GUID
688     // Incoming widget version
689     if (!configInfo.version.IsNull()) {
690         widgetVersion =
691             DPL::Optional<WidgetVersion>(
692                 WidgetVersion(*configInfo.version));
693     }
694
695     if (appType == APP_TYPE_WAC20) {
696         Try
697         {
698             // Search widget handle by GUID
699             WidgetDAOReadOnly dao(widgetGUID);
700             return WidgetUpdateInfo(
701                     widgetGUID,
702                     widgetVersion,
703                     WidgetUpdateInfo::ExistingWidgetInfo(
704                         dao.getTzAppId(), dao.getVersion()));
705         }
706         Catch(WidgetDAOReadOnly::Exception::WidgetNotExist)
707         {
708             // GUID isn't installed
709             return WidgetUpdateInfo(
710                     widgetGUID,
711                     widgetVersion,
712                     WidgetUpdateInfo::ExistingWidgetInfo());
713         }
714     } else {
715         Try
716         {
717             // Search widget handle by appId
718             WidgetDAOReadOnly dao(tizenId);
719             return WidgetUpdateInfo(
720                     widgetGUID,
721                     widgetVersion,
722                     WidgetUpdateInfo::ExistingWidgetInfo(
723                         dao.getTzAppId(), dao.getVersion()));
724         }
725         Catch(WidgetDAOReadOnly::Exception::WidgetNotExist)
726         {
727             // GUID isn't installed
728             return WidgetUpdateInfo(
729                     widgetGUID,
730                     widgetVersion,
731                     WidgetUpdateInfo::ExistingWidgetInfo());
732         }
733
734     }
735 }
736
737 void JobWidgetInstall::SendProgress()
738 {
739     using namespace PackageManager;
740     if (GetProgressFlag() != false) {
741         if (getInstallerStruct().progressCallback != NULL) {
742             // send progress signal of pkgmgr
743             std::ostringstream percent;
744             percent << static_cast<int>(GetProgressPercent());
745             getInstallerStruct().pkgmgrInterface->sendSignal(
746                         PKGMGR_PROGRESS_KEY,
747                         percent.str());
748
749             LogDebug("Call widget install progressCallbak");
750             getInstallerStruct().progressCallback(getInstallerStruct().userParam,
751                     GetProgressPercent(),GetProgressDescription());
752         }
753     }
754 }
755
756 void JobWidgetInstall::SendFinishedSuccess()
757 {
758     using namespace PackageManager;
759     // TODO : sync should move to separate task.
760     sync();
761
762
763     if (INSTALL_LOCATION_TYPE_EXTERNAL == m_installerContext.locationType) {
764         if (false == m_installerContext.existingWidgetInfo.isExist) {
765             WidgetInstallToExtSingleton::Instance().postInstallation(true);
766         } else {
767             WidgetInstallToExtSingleton::Instance().postUpgrade(true);
768         }
769         WidgetInstallToExtSingleton::Instance().deinitialize();
770     }
771
772     // remove widget install information file
773     unlink(m_installerContext.installInfo.c_str());
774
775     //inform widget info
776     JobWidgetInstall::displayWidgetInfo();
777
778     TizenAppId& tizenId = m_installerContext.widgetConfig.tzAppid;
779
780     // send signal of pkgmgr
781     getInstallerStruct().pkgmgrInterface->sendSignal(
782                 PKGMGR_END_KEY,
783                 PKGMGR_END_SUCCESS);
784
785     LogDebug("Call widget install successfinishedCallback");
786     getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
787             DPL::ToUTF8String(tizenId), Exceptions::Success);
788 }
789
790 void JobWidgetInstall::SendFinishedFailure()
791 {
792     using namespace PackageManager;
793     // remove widget install information file
794     unlink(m_installerContext.installInfo.c_str());
795
796     LogError("Error in installation step: " << m_exceptionCaught);
797     LogError("Message: " << m_exceptionMessage);
798     TizenAppId & tizenId = m_installerContext.widgetConfig.tzAppid;
799
800     LogDebug("Call widget install failure finishedCallback");
801
802     // send signal of pkgmgr
803     getInstallerStruct().pkgmgrInterface->sendSignal(
804                 PKGMGR_END_KEY,
805                 PKGMGR_END_FAILURE);
806
807     getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
808             DPL::ToUTF8String(tizenId), m_exceptionCaught);
809 }
810
811 void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
812 {
813     m_exceptionCaught = static_cast<Exceptions::Type>(e.getParam());
814     m_exceptionMessage = e.GetMessage();
815 }
816
817 void JobWidgetInstall::displayWidgetInfo()
818 {
819     WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
820
821     std::ostringstream out;
822     WidgetLocalizedInfo localizedInfo =
823         W3CFileLocalization::getLocalizedInfo(dao.getTzAppId());
824
825     out << std::endl <<
826         "===================================== INSTALLED WIDGET INFO ========="\
827         "============================";
828     out << std::endl << "Name:                        " << localizedInfo.name;
829     out << std::endl << "AppId:                     " << dao.getTzAppId();
830     WidgetSize size = dao.getPreferredSize();
831     out << std::endl << "Width:                       " << size.width;
832     out << std::endl << "Height:                      " << size.height;
833     out << std::endl << "Start File:                  " <<
834         W3CFileLocalization::getStartFile(dao.getTzAppId());
835     out << std::endl << "Version:                     " << dao.getVersion();
836     out << std::endl << "Licence:                     " <<
837         localizedInfo.license;
838     out << std::endl << "Licence Href:                " <<
839         localizedInfo.licenseHref;
840     out << std::endl << "Description:                 " <<
841         localizedInfo.description;
842     out << std::endl << "Widget Id:                   " << dao.getGUID();
843     out << std::endl << "Widget recognized:           " << dao.isRecognized();
844     out << std::endl << "Widget wac signed:           " << dao.isWacSigned();
845     out << std::endl << "Widget distributor signed:   " <<
846         dao.isDistributorSigned();
847     out << std::endl << "Widget trusted:              " << dao.isTrusted();
848
849     OptionalWidgetIcon icon = W3CFileLocalization::getIcon(dao.getTzAppId());
850     DPL::OptionalString iconSrc = !!icon ? icon->src : DPL::OptionalString::Null;
851     out << std::endl << "Icon:                        " << iconSrc;
852
853     out << std::endl << "Preferences:";
854     {
855         PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList();
856         FOREACH(it, list)
857         {
858             out << std::endl << "  Key:                       " <<
859                 it->key_name;
860             out << std::endl << "      Readonly:              " <<
861                 it->readonly;
862         }
863     }
864
865     out << std::endl << "Features:";
866     {
867         WidgetFeatureSet list = dao.getFeaturesList();
868         FOREACH(it, list)
869         {
870             out << std::endl << "  Name:                      " << it->name;
871             out << std::endl << "      Required:              " << it->required;
872             out << std::endl << "      Params:";
873         }
874     }
875
876     out << std::endl;
877
878     LogInfo(out.str());
879 }
880
881 WrtDB::PackagingType JobWidgetInstall::checkPackageType(
882         const std::string &widgetSource,
883         const std::string &tempPath)
884 {
885     // Check installation type (direcotory/ or config.xml or widget.wgt)
886     if (WidgetUpdateMode::PolicyDirectoryForceInstall == m_jobStruct.updateMode)
887     {
888         LogDebug("Install directly from directory");
889         return PKG_TYPE_DIRECTORY_WEB_APP;
890     }
891     if (hasExtension(widgetSource, XML_EXTENSION)) {
892         LogInfo("Hosted app installation");
893         return PKG_TYPE_HOSTED_WEB_APP;
894     }
895
896     if (m_isDRM) {
897         std::string configFile = tempPath + "/" + CONFIG_XML;
898         if (WrtUtilFileExists(configFile)) {
899             return PKG_TYPE_NOMAL_WEB_APP;
900         }
901
902         configFile = tempPath + "/" + WITH_OSP_XML;
903         if (WrtUtilFileExists(configFile)) {
904             return PKG_TYPE_HYBRID_WEB_APP;
905         }
906     } else {
907         std::unique_ptr<DPL::ZipInput> zipFile;
908
909         Try
910         {
911             // Open zip file
912             zipFile.reset(new DPL::ZipInput(widgetSource));
913
914         }
915         Catch(DPL::ZipInput::Exception::OpenFailed)
916         {
917             LogDebug("Failed to open widget package");
918             return PKG_TYPE_UNKNOWN;
919         }
920         Catch(DPL::ZipInput::Exception::SeekFileFailed)
921         {
922             LogError("Failed to seek widget package file");
923             return PKG_TYPE_UNKNOWN;
924         }
925
926         Try
927         {
928             // Open config.xml file in package root
929             std::unique_ptr<DPL::ZipInput::File> configFile(
930                     zipFile->OpenFile(CONFIG_XML));
931             return PKG_TYPE_NOMAL_WEB_APP;
932         }
933         Catch(DPL::ZipInput::Exception::OpenFileFailed)
934         {
935             LogDebug("Could not find config.xml");
936         }
937
938         Try
939         {
940             // Open config.xml file in package root
941             std::unique_ptr<DPL::ZipInput::File> configFile(
942                     zipFile->OpenFile(WITH_OSP_XML));
943
944             return PKG_TYPE_HYBRID_WEB_APP;
945         }
946         Catch(DPL::ZipInput::Exception::OpenFileFailed)
947         {
948             LogDebug("Could not find wgt/config.xml");
949             return PKG_TYPE_UNKNOWN;
950         }
951     }
952
953     return PKG_TYPE_UNKNOWN;
954 }
955
956 void JobWidgetInstall::setApplicationType(
957         const WrtDB::ConfigParserData &configInfo)
958 {
959
960     FOREACH(iterator, configInfo.nameSpaces) {
961         LogInfo("namespace = [" << *iterator << "]");
962         AppType currentAppType = APP_TYPE_UNKNOWN;
963
964         if (*iterator == ConfigurationNamespace::W3CWidgetNamespaceName) {
965             continue;
966         } else if (
967             *iterator ==
968             ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement ||
969             *iterator ==
970             ConfigurationNamespace::WacWidgetNamespaceName)
971         {
972             currentAppType = APP_TYPE_WAC20;
973         } else if (*iterator ==
974                 ConfigurationNamespace::TizenWebAppNamespaceName) {
975             currentAppType = APP_TYPE_TIZENWEBAPP;
976         }
977
978         if (m_installerContext.widgetConfig.webAppType ==
979                 APP_TYPE_UNKNOWN) {
980             m_installerContext.widgetConfig.webAppType = currentAppType;
981         } else if (m_installerContext.widgetConfig.webAppType ==
982                 currentAppType) {
983             continue;
984         } else {
985             ThrowMsg(Exceptions::WidgetConfigFileInvalid,
986                      "Config.xml has more than one namespace");
987         }
988     }
989
990     // If there is no define, type set to WAC 2.0
991     if (m_installerContext.widgetConfig.webAppType == APP_TYPE_UNKNOWN) {
992         m_installerContext.widgetConfig.webAppType = APP_TYPE_WAC20;
993     }
994
995     LogInfo("type = [" <<
996             m_installerContext.widgetConfig.webAppType.getApptypeToString() << "]");
997 }
998
999 bool JobWidgetInstall::detectResourceEncryption(const WrtDB::ConfigParserData &configData)
1000 {
1001     FOREACH(it, configData.settingsList)
1002     {
1003         if (it->m_name == SETTING_VALUE_ENCRYPTION &&
1004                 it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE) {
1005             LogDebug("resource need encryption");
1006             return true;
1007         }
1008     }
1009     return false;
1010 }
1011
1012 void JobWidgetInstall::setInstallLocationType(const
1013         WrtDB::ConfigParserData &configData)
1014 {
1015     m_installerContext.locationType = INSTALL_LOCATION_TYPE_NOMAL;
1016
1017     if (true == m_jobStruct.m_preload) {
1018         m_installerContext.locationType =
1019             INSTALL_LOCATION_TYPE_PRELOAD;
1020     } else {
1021         FOREACH(it, configData.settingsList)
1022         {
1023             if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME &&
1024                     it->m_value ==
1025                     SETTING_VALUE_INSTALLTOEXT_PREPER_EXT) {
1026                 LogDebug("This widget will be installed to sd card");
1027                 m_installerContext.locationType =
1028                     INSTALL_LOCATION_TYPE_EXTERNAL;
1029             }
1030         }
1031     }
1032 }
1033
1034 bool JobWidgetInstall::isDRMWidget(std::string widgetPath)
1035 {
1036     /* TODO :
1037     drm_bool_type_e is_drm_file = DRM_UNKNOWN;
1038     int ret = -1;
1039
1040     ret = drm_is_drm_file(widgetPath.c_str(), &is_drm_file);
1041     if(DRM_RETURN_SUCCESS == ret && DRM_TRUE == is_drm_file) {
1042     */
1043
1044     /* blow code temporary code for drm. */
1045     int ret = drm_oem_intel_isDrmFile(const_cast<char*>(widgetPath.c_str()));
1046     if ( 1 == ret) {
1047         return true;
1048     } else {
1049         return false;
1050     }
1051 }
1052
1053 bool JobWidgetInstall::DecryptDRMWidget(std::string widgetPath,
1054         std::string destPath)
1055 {
1056     /* TODO :
1057     drm_trusted_sapps_decrypt_package_info_s package_info;
1058
1059     strncpy(package_info.sadcf_filepath, widgetPath.c_str(),
1060             sizeof(package_info.sadcf_filepath));
1061     strncpy(package_info.decrypt_filepath, destPath.c_str(),
1062             sizeof(package_info.decrypt_filepath));
1063
1064     drm_trusted_request_type_e requestType =
1065         DRM_TRUSTED_REQ_TYPE_SAPPS_DECRYPT_PACKAGE;
1066
1067     int ret = drm_trusted_handle_request(requestType,
1068                                          (void *)&package_info, NULL);
1069     if (DRM_TRUSTED_RETURN_SUCCESS == ret) {
1070         return true;
1071     } else {
1072         return false;
1073     }
1074     */
1075     if (drm_oem_intel_decrypt_package(const_cast<char*>(widgetPath.c_str()),
1076                 const_cast<char*>(destPath.c_str())) != 0) {
1077         return true;
1078     } else {
1079         return false;
1080     }
1081 }
1082
1083 } //namespace WidgetInstall
1084 } //namespace Jobs