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