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