save installed path to db for preload widget
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_widget_config.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    task_widget_config.cpp
18  * @author  Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version 1.0
20  * @brief   Implementation file for installer task widget config
21  */
22
23 #include <sstream>
24 #include <string>
25 #include <sys/stat.h>
26 #include <dirent.h>
27
28 #include <dpl/errno_string.h>
29 #include <dpl/foreach.h>
30 #include <dpl/localization/w3c_file_localization.h>
31 #include <dpl/singleton_impl.h>
32 #include <dpl/utils/mime_type_utils.h>
33 #include <dpl/utils/wrt_global_settings.h>
34 #include <dpl/utils/wrt_utility.h>
35 #include <dpl/wrt-dao-ro/global_config.h>
36 #include <dpl/wrt-dao-rw/feature_dao.h>
37
38 #include <libiriwrapper.h>
39 #include <parser_runner.h>
40 #include <root_parser.h>
41
42 #include <widget_install/job_widget_install.h>
43 #include <widget_install/task_widget_config.h>
44 #include <widget_install/widget_install_context.h>
45 #include <widget_install/widget_install_errors.h>
46 #include <widget_parser.h>
47 #include <wrt_error.h>
48
49
50 namespace { // anonymous
51 const DPL::String BR = DPL::FromUTF8String("<br>");
52 const std::string WIDGET_NOT_COMPATIBLE = "This widget is "
53         "not compatible with WRT.<br><br>";
54 const std::string QUESTION = "Do you want to install it anyway?";
55
56 const char *const DEFAULT_LANGUAGE = "default";
57
58 const char *const WRT_WIDGET_CONFIG_FILE_NAME = "config.xml";
59
60 const std::string WINDGET_INSTALL_NETWORK_ACCESS = "network access";
61 }
62
63
64 namespace Jobs {
65 namespace WidgetInstall {
66 void InstallerTaskWidgetPopupData::PopupData::addWidgetInfo(
67         const DPL::String &info)
68 {
69     widgetInfo = info;
70 }
71
72 TaskWidgetConfig::TaskWidgetConfig(InstallerContext& installContext) :
73     DPL::TaskDecl<TaskWidgetConfig>(this),
74     WidgetInstallPopup(installContext),
75     m_installContext(installContext)
76
77 {
78     AddStep(&TaskWidgetConfig::StepProcessConfigurationFile);
79     AddStep(&TaskWidgetConfig::ReadLocaleFolders);
80     AddStep(&TaskWidgetConfig::ProcessLocalizedStartFiles);
81     AddStep(&TaskWidgetConfig::ProcessBackgroundPageFile);
82     AddStep(&TaskWidgetConfig::ProcessLocalizedIcons);
83     AddStep(&TaskWidgetConfig::ProcessWidgetInstalledPath);
84     AddStep(&TaskWidgetConfig::StepVerifyFeatures);
85     AddStep(&TaskWidgetConfig::StepCheckMinVersionInfo);
86
87     if (!GlobalSettings::TestModeEnabled() && !m_installContext.m_quiet) {
88         AddStep(&TaskWidgetConfig::StepCancelWidgetInstallationAfterVerifyFeatures);
89         AddStep(&TaskWidgetConfig::StepShowWidgetInfo);
90         AddStep(&TaskWidgetConfig::StepCancelWidgetInstallation);
91         AddStep(&TaskWidgetConfig::StepCancelWidgetInstallationAfterMinVersion);
92         AddStep(&TaskWidgetConfig::StepDeletePopupWin);
93     }
94 }
95
96 void TaskWidgetConfig::StepProcessConfigurationFile()
97 {
98     Try
99     {
100         std::string path = m_installContext.locations->getConfigurationDir();
101         LogInfo("path: " << path);
102
103         processFile(path, m_installContext.widgetConfig);
104     }
105     Catch(Exception::ConfigParseFailed)
106     {
107         LogError("Parsing failed.");
108         ReThrow(Exceptions::WidgetConfigFileInvalid);
109     }
110     Try
111     {
112         // To get widget type for distribute WAC, TIZEN WebApp
113         setApplicationType();
114     }
115     Catch(Exception::ConfigParseFailed)
116     {
117         LogError("Config.xml has more than one namespace");
118         ReThrow(Exceptions::WidgetConfigFileInvalid);
119     }
120
121     m_installContext.job->UpdateProgress(
122         InstallerContext::INSTALL_WIDGET_CONFIG1,
123         "Parse elements of configuration file and save them");
124 }
125
126 void TaskWidgetConfig::ReadLocaleFolders()
127 {
128     LogDebug("Reading locale");
129     //Adding default locale
130     m_localeFolders.insert(L"");
131
132     std::string localePath = m_installContext.locations->getConfigurationDir() + "/locales";
133     DIR* localeDir = opendir(localePath.c_str());
134     if (!localeDir) {
135         LogDebug("No /locales directory in the widget package.");
136         return;
137     }
138
139     struct dirent* dirent;
140     struct stat statStruct;
141     do {
142         errno = 0;
143         if ((dirent = readdir(localeDir))) {
144             DPL::String dirName = DPL::FromUTF8String(dirent->d_name);
145             std::string absoluteDirName = localePath + "/";
146             absoluteDirName += dirent->d_name;
147
148             if (stat(absoluteDirName.c_str(), &statStruct) != 0) {
149                 LogError("stat() failed with " << DPL::GetErrnoString());
150                 continue;
151             }
152
153             if (S_ISDIR(statStruct.st_mode)) {
154                 //Yes, we ignore current, parent & hidden directories
155                 if (dirName[0] != L'.') {
156                     LogDebug("Adding locale directory \"" << dirName << "\"");
157                     m_localeFolders.insert(dirName);
158                 }
159             }
160         }
161     }
162     while (dirent);
163
164     if (errno != 0) {
165         LogError("readdir() failed with " << DPL::GetErrnoString());
166     }
167
168     if (-1 == TEMP_FAILURE_RETRY(closedir(localeDir))) {
169         LogError("Failed to close dir: " << localePath << " with error: "
170                 << DPL::GetErrnoString());
171     }
172 }
173
174 void TaskWidgetConfig::ProcessLocalizedStartFiles()
175 {
176     typedef DPL::String S;
177     ProcessStartFile(
178         m_installContext.widgetConfig.configInfo.startFile,
179         m_installContext.widgetConfig.configInfo.
180             startFileContentType,
181         m_installContext.widgetConfig.configInfo.startFileEncoding,
182         true);
183     ProcessStartFile(S(L"index.htm"), S(L"text/html"));
184     ProcessStartFile(S(L"index.html"), S(L"text/html"));
185     ProcessStartFile(S(L"index.svg"), S(L"image/svg+xml"));
186     ProcessStartFile(S(L"index.xhtml"), S(L"application/xhtml+xml"));
187     ProcessStartFile(S(L"index.xht"), S(L"application/xhtml+xml"));
188     // TODO: (l.wrzosek) we need better check if in current locales widget is valid.
189     FOREACH(it, m_installContext.widgetConfig.localizationData.startFiles) {
190         if (it->propertiesForLocales.size() > 0) {
191             return;
192         }
193     }
194     ThrowMsg(Exceptions::WidgetConfigFileInvalid,
195              L"The Widget has no valid start file");
196 }
197
198 void TaskWidgetConfig::ProcessStartFile(const DPL::OptionalString& path,
199         const DPL::OptionalString& type,
200         const DPL::OptionalString& encoding,
201         bool typeForcedInConfig)
202 {
203     using namespace WrtDB;
204
205     if (!!path) {
206         WidgetRegisterInfo::LocalizedStartFile startFileData;
207         startFileData.path = *path;
208
209         FOREACH(i, m_localeFolders) {
210             DPL::String pathPrefix = *i;
211             if (!pathPrefix.empty()) {
212                 pathPrefix = L"locales/" + pathPrefix + L"/";
213             }
214
215             DPL::String relativePath = pathPrefix + *path;
216             DPL::String absolutePath = DPL::FromUTF8String(
217                     m_installContext.locations->getConfigurationDir()) + L"/" + relativePath;
218
219             // get property data from packaged app
220             if (WrtUtilFileExists(DPL::ToUTF8String(absolutePath))) {
221                 WidgetRegisterInfo::StartFileProperties startFileProperties;
222                 if (!!type) {
223                     startFileProperties.type = *type;
224                 } else {
225                     startFileProperties.type =
226                         MimeTypeUtils::identifyFileMimeType(absolutePath);
227                 }
228
229                 //proceed only if MIME type is supported
230                 if (MimeTypeUtils::isMimeTypeSupportedForStartFile(
231                         startFileProperties.type))
232                 {
233                     if (!!encoding) {
234                         startFileProperties.encoding = *encoding;
235                     } else {
236                         MimeTypeUtils::MimeAttributes attributes =
237                             MimeTypeUtils::getMimeAttributes(
238                             startFileProperties.type);
239                         if (attributes.count(L"charset") > 0) {
240                             startFileProperties.encoding =
241                                 attributes[L"charset"];
242                         } else {
243                             startFileProperties.encoding = L"UTF-8";
244                         }
245                     }
246
247                     startFileData.propertiesForLocales[*i] =
248                         startFileProperties;
249                 } else {
250                     //9.1.16.5.content.8
251                     //(there seems to be no similar requirement in .6,
252                     //so let's throw only when mime type is
253                     // provided explcitly in config.xml)
254                     if (typeForcedInConfig) {
255                         ThrowMsg(Exceptions::WidgetConfigFileInvalid,
256                                  "Unsupported MIME type for start file.");
257                     }
258                 }
259             } else {
260                 // set property data for hosted start url
261                 // Hosted start url only support TIZEN WebApp
262                 if (m_installContext.widgetConfig.webAppType ==
263                         APP_TYPE_TIZENWEBAPP)
264                 {
265                     const char *startPath =
266                         DPL::ToUTF8String(startFileData.path).c_str();
267                     if (strstr(startPath, "http") == startPath) {
268                         WidgetRegisterInfo::StartFileProperties
269                             startFileProperties;
270                         if (!!type) {
271                             startFileProperties.type = *type;
272                         }
273                         if (!!encoding) {
274                             startFileProperties.encoding = *encoding;
275                         }
276                         startFileData.propertiesForLocales[*i] =
277                             startFileProperties;
278                     }
279                 }
280             }
281         }
282
283         m_installContext.widgetConfig.localizationData.startFiles.push_back(
284             startFileData);
285     }
286 }
287
288 void TaskWidgetConfig::ProcessBackgroundPageFile()
289 {
290     if (!!m_installContext.widgetConfig.configInfo.backgroundPage) {
291         // check whether file exists
292         DPL::String backgroundPagePath = DPL::FromUTF8String(
293             m_installContext.locations->getConfigurationDir()) + L"/" +
294             *m_installContext.widgetConfig.configInfo.backgroundPage;
295         //if no then cancel installation
296         if (!WrtUtilFileExists(DPL::ToUTF8String(backgroundPagePath))) {
297             ThrowMsg(Exceptions::WidgetConfigFileInvalid,
298                     L"Given background page file not found in archive");
299         }
300     }
301 }
302
303 void TaskWidgetConfig::ProcessLocalizedIcons()
304 {
305     using namespace WrtDB;
306     ProcessIcon(ConfigParserData::Icon(L"icon.svg"));
307     ProcessIcon(ConfigParserData::Icon(L"icon.ico"));
308     ProcessIcon(ConfigParserData::Icon(L"icon.png"));
309     ProcessIcon(ConfigParserData::Icon(L"icon.gif"));
310     ProcessIcon(ConfigParserData::Icon(L"icon.jpg"));
311
312     FOREACH(i, m_installContext.widgetConfig.configInfo.iconsList)
313     {
314         ProcessIcon(*i);
315     }
316 }
317
318 void TaskWidgetConfig::ProcessIcon(const WrtDB::ConfigParserData::Icon& icon)
319 {
320     LogInfo("enter");
321     bool isAnyIconValid = false;
322     //In case a default filename is passed as custom filename in config.xml, we
323     //need to keep a set of already processed filenames to avoid icon duplication
324     //in database.
325
326     using namespace WrtDB;
327
328     if (m_processedIconSet.count(icon.src) > 0) {
329         return;
330     }
331     m_processedIconSet.insert(icon.src);
332
333     LocaleSet localesAvailableForIcon;
334
335     FOREACH(i, m_localeFolders)
336     {
337         DPL::String pathPrefix = *i;
338         if (!pathPrefix.empty()) {
339             pathPrefix = L"locales/" + pathPrefix + L"/";
340         }
341
342         DPL::String relativePath = pathPrefix + icon.src;
343         DPL::String absolutePath = DPL::FromUTF8String(
344                 m_installContext.locations->getConfigurationDir()) + L"/" + relativePath;
345
346         if (WrtUtilFileExists(DPL::ToUTF8String(absolutePath))) {
347             DPL::String type = MimeTypeUtils::identifyFileMimeType(absolutePath);
348
349             if (MimeTypeUtils::isMimeTypeSupportedForIcon(type)) {
350                 isAnyIconValid = true;
351                 localesAvailableForIcon.insert(*i);
352                 LogInfo("Icon absolutePath :" << absolutePath <<
353                         ", assigned locale :" << *i << ", type: " << type);
354             }
355         }
356     }
357
358     if(isAnyIconValid)
359     {
360         WidgetRegisterInfo::LocalizedIcon localizedIcon(icon,
361                                                         localesAvailableForIcon);
362         m_installContext.widgetConfig.localizationData.icons.push_back(
363             localizedIcon);
364     }
365 }
366
367 void TaskWidgetConfig::ProcessWidgetInstalledPath()
368 {
369     LogDebug("ProcessWidgetInstalledPath");
370     m_installContext.widgetConfig.widgetInstalledPath =
371         DPL::FromUTF8String(m_installContext.locations->getPackageInstallationDir());
372 }
373
374 void TaskWidgetConfig::StepCancelWidgetInstallationAfterVerifyFeatures()
375 {
376     LogDebug("StepCancelWidgetInstallationAfterVerifyFeatures");
377     if (InfoPopupButton::WRT_POPUP_BUTTON_CANCEL == m_installCancel) {
378         m_installCancel = WRT_POPUP_BUTTON;
379         destroyPopup();
380         ThrowMsg(Exceptions::WidgetConfigFileInvalid, "Widget not allowed");
381     }
382 }
383
384 void TaskWidgetConfig::StepCancelWidgetInstallation()
385 {
386     if (InfoPopupButton::WRT_POPUP_BUTTON_CANCEL == m_installCancel) {
387         m_installCancel = WRT_POPUP_BUTTON;
388         destroyPopup();
389         ThrowMsg(Exceptions::NotAllowed, "Widget not allowed");
390     }
391 }
392
393 void TaskWidgetConfig::StepCancelWidgetInstallationAfterMinVersion()
394 {
395     if (InfoPopupButton::WRT_POPUP_BUTTON_CANCEL == m_installCancel) {
396         m_installCancel = WRT_POPUP_BUTTON;
397         destroyPopup();
398         ThrowMsg(Exceptions::NotAllowed, "WRT version incompatible.");
399     }
400 }
401
402 void TaskWidgetConfig::createInstallPopup(PopupType type, const std::string &label)
403 {
404     m_installContext.job->Pause();
405     if (m_popup)
406         destroyPopup();
407
408     bool ret = createPopup();
409     if (ret)
410     {
411         loadPopup( type, label);
412         showPopup();
413     }
414 }
415
416 void TaskWidgetConfig::StepDeletePopupWin()
417 {
418     destroyPopup();
419 }
420
421 void TaskWidgetConfig::StepShowWidgetInfo()
422 {
423     if (!m_popupData.widgetInfo.empty()) {
424             std::string label = DPL::ToUTF8String(m_popupData.widgetInfo);
425             createInstallPopup(PopupType::WIDGET_FEATURE_INFO, label);
426         m_installContext.job->UpdateProgress(
427             InstallerContext::INSTALL_WIDGET_CONFIG2,
428             "Show Widget Info Finished");
429     }
430 }
431
432 void TaskWidgetConfig::StepCheckMinVersionInfo()
433 {
434     if (!isMinVersionCompatible(
435                 m_installContext.widgetConfig.webAppType.appType,
436                 m_installContext.widgetConfig.minVersion)) {
437         if(!GlobalSettings::TestModeEnabled() && !m_installContext.m_quiet)
438         {
439             LogDebug("Platform version to low - launching");
440             std::string label = WIDGET_NOT_COMPATIBLE + QUESTION;
441             createInstallPopup(PopupType::WIDGET_MIN_VERSION, label);
442         }
443         else
444         {
445             LogError("Platform version lower than required -> cancelling installation");
446             ThrowMsg(Exceptions::NotAllowed,
447                     "Platform version does not meet requirements");
448         }
449     }
450
451     m_installContext.job->UpdateProgress(
452             InstallerContext::INSTALL_WIDGET_CONFIG2,
453             "Check MinVersion Finished");
454 }
455
456 void TaskWidgetConfig::StepVerifyFeatures()
457 {
458     using namespace WrtDB;
459     ConfigParserData &data = m_installContext.widgetConfig.configInfo;
460     ConfigParserData::FeaturesList list = data.featuresList;
461     ConfigParserData::FeaturesList newList;
462
463     //in case of tests, this variable is unused
464     std::string featureInfo;
465     FOREACH(it, list)
466     {
467         // check feature vender for permission
468         // WAC, TIZEN WebApp cannot use other feature
469
470         if (!isFeatureAllowed(m_installContext.widgetConfig.webAppType.appType,
471                               it->name))
472         {
473             LogInfo("This application type not allowed to use this feature");
474             ThrowMsg(
475                 Exceptions::WidgetConfigFileInvalid,
476                 "This app type [" <<
477                 m_installContext.widgetConfig.webAppType.getApptypeToString() <<
478                 "] cannot be allowed to use [" <<
479                 DPL::ToUTF8String(it->name) + "] feature");
480         }
481         if (!WrtDB::FeatureDAOReadOnly::isFeatureInstalled(
482                 DPL::ToUTF8String(it->name))) {
483             LogWarning("Feature not found. Checking if required :[" <<
484                        DPL::ToUTF8String(it->name) << "]");
485
486             if (it->required) {
487                 /**
488                  * WL-3210 The WRT MUST inform the user if a widget cannot be
489                  * installed because one or more required features are not
490                  * supported.
491                  */
492                 std::ostringstream os;
493                 os << "Widget cannot be installed, required feature is missing:["
494                     << DPL::ToUTF8String(it->name) << "]";
495                 if (!GlobalSettings::TestModeEnabled() && !isTizenWebApp()) {
496                     std::string label = os.str();
497                     createInstallPopup(PopupType::WIDGET_WRONG_FEATURE_INFO, label);
498                 }
499                 ThrowMsg(Exceptions::WidgetConfigFileInvalid, os.str());
500             }
501         } else {
502             newList.insert(*it);
503             featureInfo += DPL::ToUTF8String(it->name);
504             featureInfo += DPL::ToUTF8String(BR);
505         }
506     }
507     if(!data.accessInfoSet.empty()) {
508         featureInfo += WINDGET_INSTALL_NETWORK_ACCESS;
509         featureInfo += DPL::ToUTF8String(BR);
510     }
511     data.featuresList = newList;
512     if (!featureInfo.empty()) {
513         m_popupData.addWidgetInfo(DPL::FromUTF8String(featureInfo));
514     }
515
516     m_installContext.job->UpdateProgress(
517         InstallerContext::INSTALL_WIDGET_CONFIG2,
518         "Widget Config step2 Finished");
519 }
520
521 void TaskWidgetConfig::setApplicationType()
522 {
523     using namespace WrtDB;
524     WidgetRegisterInfo* widgetInfo = &(m_installContext.widgetConfig);
525     ConfigParserData* configInfo = &(widgetInfo->configInfo);
526
527     FOREACH(iterator, configInfo->nameSpaces) {
528         LogInfo("namespace = [" << *iterator << "]");
529         AppType currentAppType = APP_TYPE_UNKNOWN;
530
531         if (*iterator == ConfigurationNamespace::W3CWidgetNamespaceName) {
532             continue;
533         } else if (
534             *iterator ==
535             ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement ||
536             *iterator ==
537             ConfigurationNamespace::WacWidgetNamespaceName)
538         {
539             currentAppType = APP_TYPE_WAC20;
540         } else if (*iterator == ConfigurationNamespace::TizenWebAppNamespaceName) {
541             currentAppType = APP_TYPE_TIZENWEBAPP;
542         }
543
544         if (widgetInfo->webAppType == APP_TYPE_UNKNOWN) {
545             widgetInfo->webAppType = currentAppType;
546         } else if (widgetInfo->webAppType == currentAppType) {
547             continue;
548         } else {
549             ThrowMsg(Exceptions::WidgetConfigFileInvalid,
550                      "Config.xml has more than one namespace");
551         }
552     }
553
554     // If there is no define, type set to WAC 2.0
555     if (widgetInfo->webAppType == APP_TYPE_UNKNOWN) {
556         widgetInfo->webAppType = APP_TYPE_WAC20;
557     }
558
559     LogInfo("type = [" << widgetInfo->webAppType.getApptypeToString() << "]");
560 }
561
562 bool TaskWidgetConfig::isFeatureAllowed(WrtDB::AppType appType,
563                                         DPL::String featureName)
564 {
565     using namespace WrtDB;
566     LogInfo("AppType = [" <<
567             WidgetType(appType).getApptypeToString() << "]");
568     LogInfo("FetureName = [" << featureName << "]");
569
570     AppType featureType = APP_TYPE_UNKNOWN;
571     const char* feature = DPL::ToUTF8String(featureName).c_str();
572     // check prefix of  feature name
573     if (strstr(feature, PluginsPrefix::TIZENPluginsPrefix) == feature) {
574         // Tizen WebApp feature
575         featureType = APP_TYPE_TIZENWEBAPP;
576     } else if (strstr(feature, PluginsPrefix::WACPluginsPrefix) == feature) {
577         // WAC 2.0 feature
578         featureType = APP_TYPE_WAC20;
579     } else if (strstr(feature, PluginsPrefix::W3CPluginsPrefix) == feature) {
580         // W3C standard feature
581         // Both WAC and TIZEN WebApp are possible to use W3C plugins
582         return true;
583     } else {
584         // unknown feature
585         // unknown feature will be checked next step
586         return true;
587     }
588
589     if (appType == featureType) {
590         return true;
591     }
592     return false;
593 }
594
595 bool TaskWidgetConfig::parseVersionString(const std::string &version,
596         long &majorVersion, long &minorVersion, long &microVersion) const
597 {
598     std::istringstream inputString(version);
599     inputString >> majorVersion;
600     if (inputString.bad() || inputString.fail()) {
601         LogWarning("Invalid minVersion format.");
602         return false;
603     }
604     inputString.get(); // skip period
605     inputString >> minorVersion;
606     if (inputString.bad() || inputString.fail()) {
607         LogWarning("Invalid minVersion format");
608         return false;
609     } else {
610         inputString.get(); // skip period
611         if (inputString.bad() || inputString.fail()) {
612             inputString >> microVersion;
613         }
614     }
615     return true;
616 }
617
618 bool TaskWidgetConfig::isMinVersionCompatible(WrtDB::AppType appType,
619         const DPL::OptionalString &widgetVersion) const
620 {
621     if (widgetVersion.IsNull() || (*widgetVersion).empty())
622     {
623         LogWarning("minVersion attribute is empty. WRT assumes platform "
624                 "supports this widget.");
625         return true;
626     }
627
628     //Parse widget version
629     long majorWidget = 0, minorWidget = 0, microWidget = 0;
630     if (!parseVersionString(DPL::ToUTF8String(*widgetVersion), majorWidget,
631             minorWidget, microWidget)) {
632         LogWarning("Invalid format of widget version string.");
633         return true;
634     }
635
636     //Parse supported version
637     long majorSupported = 0, minorSupported = 0, microSupported = 0;
638     std::string version;
639     if (appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) {
640         version = WrtDB::GlobalConfig::GetTizenVersion();
641     } else if (appType == WrtDB::AppType::APP_TYPE_WAC20) {
642         version = WrtDB::GlobalConfig::GetWACVersion();
643     } else {
644         LogWarning("Invaild AppType");
645         return false;
646     }
647
648     if (!parseVersionString(version,
649                 majorSupported, minorSupported, microSupported)) {
650         LogWarning("Invalid format of platform version string.");
651         return true;
652     }
653
654     if (majorWidget > majorSupported ||
655             (majorWidget == majorSupported && minorWidget > minorSupported) ||
656             (majorWidget == majorSupported && minorWidget == minorSupported
657                     && microWidget > microSupported))
658     {
659         LogInfo("Platform doesn't support this widget.");
660         return false;
661     }
662     return true;
663 }
664
665 bool TaskWidgetConfig::isTizenWebApp() const
666 {
667     bool ret = FALSE;
668     if (m_installContext.widgetConfig.webAppType.appType
669             == WrtDB::AppType::APP_TYPE_TIZENWEBAPP)
670         ret = TRUE;
671
672     return ret;
673 }
674
675 bool TaskWidgetConfig::parseConfigurationFileBrowser(WrtDB::ConfigParserData& configInfo,
676                                     const std::string& _currentPath, int* pErrCode)
677 {
678     ParserRunner parser;
679     Try
680     {
681         parser.Parse(_currentPath, ElementParserPtr(new
682                                                   RootParser<
683                                                       WidgetParser>(
684                                                       configInfo,
685                                                       DPL::FromUTF32String(
686                                                           L"widget"))));
687     }
688     Catch(ElementParser::Exception::Base)
689     {
690         LogError("Invalid widget configuration file!");
691         *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
692         return false;
693     }
694     return true;
695 }
696
697 bool TaskWidgetConfig::parseConfigurationFileWidget(WrtDB::ConfigParserData& configInfo,
698                                     const std::string& _currentPath, int* pErrCode)
699 {
700     ParserRunner parser;
701
702     //TODO: rewrite this madness
703     std::string cfgAbsPath;
704     DIR* dir = NULL;
705     struct dirent* ptr = NULL;
706
707     dir = opendir(_currentPath.c_str());
708     if (dir == NULL) {
709         *pErrCode = WRT_ERR_UNKNOWN;
710         return false;
711     }
712     bool has_config_xml = false;
713     errno = 0;
714     while ((ptr = readdir(dir)) != NULL) { //Find configuration file, based on its name
715         if (ptr->d_type == DT_REG) {
716             if (!strcmp(ptr->d_name, WRT_WIDGET_CONFIG_FILE_NAME)) {
717                 std::string dName(ptr->d_name);
718                 WrtUtilJoinPaths(cfgAbsPath, _currentPath, dName);
719
720                 //Parse widget configuration file
721                 LogDebug("Found config: " << cfgAbsPath);
722
723                 Try
724                 {
725                     parser.Parse(cfgAbsPath, ElementParserPtr(new
726                                                               RootParser<
727                                                                   WidgetParser>(
728                                                                   configInfo,
729                                                                   DPL
730                                                                       ::
731                                                                       FromUTF32String(
732                                                                       L"widget"))));
733                 }
734                 Catch(ElementParser::Exception::Base)
735                 {
736                     LogError("Invalid widget configuration file!");
737                     //                    _rethrown_exception.Dump();
738                     *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
739                     if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
740                         LogError("Failed to close dir: " << _currentPath << " with error: "
741                                 << DPL::GetErrnoString());
742                     }
743                     return false;
744                 }
745
746                 has_config_xml = true;
747                 break;
748             }
749         }
750     }
751     if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
752         LogError("Failed to close dir: " << _currentPath << " with error: "
753                 << DPL::GetErrnoString());
754     }
755
756     //We must have config.xml so leaveing if we doesn't
757     if (!has_config_xml) {
758         LogError("Invalid archive");
759         *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
760         return false;
761     }
762     return true;
763 }
764
765 bool TaskWidgetConfig::locateAndParseConfigurationFile(
766         const std::string& _currentPath,
767         WrtDB::WidgetRegisterInfo& pWidgetConfigInfo,
768         const std::string& baseFolder,
769         int* pErrCode)
770 {
771     using namespace WrtDB;
772
773     if (!pErrCode) {
774         return false;
775     }
776
777     ConfigParserData& configInfo = pWidgetConfigInfo.configInfo;
778
779     // check if this installation from browser, or not.
780     size_t pos = _currentPath.rfind("/");
781     std::ostringstream infoPath;
782     infoPath << _currentPath.substr(pos+1);
783
784     if (infoPath.str() != WRT_WIDGET_CONFIG_FILE_NAME) {
785         if (_currentPath.empty() || baseFolder.empty()) {
786             *pErrCode = WRT_ERR_INVALID_ARG;
787             return false;
788         }
789         // in case of general installation using wgt archive
790         if(!parseConfigurationFileWidget(configInfo, _currentPath, pErrCode))
791         {
792             return false;
793         }
794     } else {
795         // in case of browser installation
796         if(!parseConfigurationFileBrowser(configInfo, _currentPath, pErrCode))
797         {
798             return false;
799         }
800     }
801
802     if(!fillWidgetConfig(pWidgetConfigInfo, configInfo))
803     {
804         *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
805         return false;
806     }
807     return true;
808 }
809
810 bool TaskWidgetConfig::fillWidgetConfig(WrtDB::WidgetRegisterInfo& pWidgetConfigInfo,
811                                         WrtDB::ConfigParserData& configInfo)
812 {
813     if (!!configInfo.widget_id) {
814         if (!pWidgetConfigInfo.guid) {
815             pWidgetConfigInfo.guid = configInfo.widget_id;
816         } else {
817             if (pWidgetConfigInfo.guid != configInfo.widget_id) {
818                 LogError("Invalid archive");
819                 return false;
820             }
821         }
822     }
823     if (!!configInfo.tizenId) {
824         if (!pWidgetConfigInfo.pkgname) {
825             pWidgetConfigInfo.pkgname = configInfo.tizenId;
826         } else {
827             if (pWidgetConfigInfo.pkgname != configInfo.tizenId) {
828                 LogError("Invalid archive - Tizen ID not same error");
829                 return false;
830             }
831         }
832     }
833     if (!!configInfo.version) {
834         if (!pWidgetConfigInfo.version) {
835             pWidgetConfigInfo.version = configInfo.version;
836         } else {
837             if (pWidgetConfigInfo.version != configInfo.version) {
838                 LogError("Invalid archive");
839                 return false;
840             }
841         }
842     }
843     if (!!configInfo.minVersionRequired) {
844         pWidgetConfigInfo.minVersion = configInfo.minVersionRequired;
845     } else if (!!configInfo.tizenMinVersionRequired) {
846         pWidgetConfigInfo.minVersion = configInfo.tizenMinVersionRequired;
847     }
848     return true;
849 }
850
851 void TaskWidgetConfig::processFile(const std::string& path,
852         WrtDB::WidgetRegisterInfo &widgetConfiguration)
853 {
854     int pErrCode;
855
856     if (!locateAndParseConfigurationFile(path, widgetConfiguration,
857                                          DEFAULT_LANGUAGE, &pErrCode)) {
858         LogWarning("Widget archive: Failed while parsing config file");
859         ThrowMsg(Exception::ConfigParseFailed, path);
860     }
861 }
862
863 } //namespace WidgetInstall
864 } //namespace Jobs