f7c9c9f0734153b6eaa93795521aed6d2e44f7d6
[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 WidgetHandle WIDGET_HANDLE_START_VALUE = 1000;
52 const DPL::String BR = DPL::FromUTF8String("<br>");
53 const std::string WIDGET_NOT_COMPATIBLE = "This widget is "
54         "not compatible with WRT.<br><br>";
55 const std::string QUESTION = "Do you want to install it anyway?";
56
57 const char *const DEFAULT_LANGUAGE = "default";
58
59 const char *const WRT_WIDGET_CONFIG_FILE_NAME = "config.xml";
60
61 const std::string WINDGET_INSTALL_NETWORK_ACCESS = "network access";
62 }
63
64
65 namespace Jobs {
66 namespace WidgetInstall {
67 void InstallerTaskWidgetPopupData::PopupData::addWidgetInfo(
68         const DPL::String &info)
69 {
70     widgetInfo = info;
71 }
72
73 TaskWidgetConfig::TaskWidgetConfig(InstallerContext& installContext) :
74     DPL::TaskDecl<TaskWidgetConfig>(this),
75     m_installContext(installContext),
76     WidgetInstallPopup(installContext)
77 {
78     AddStep(&TaskWidgetConfig::StepProcessConfigurationFile);
79     AddStep(&TaskWidgetConfig::ReadLocaleFolders);
80     AddStep(&TaskWidgetConfig::ProcessLocalizedStartFiles);
81     AddStep(&TaskWidgetConfig::ProcessBackgroundPageFile);
82     AddStep(&TaskWidgetConfig::ProcessLocalizedIcons);
83     AddStep(&TaskWidgetConfig::StepVerifyFeatures);
84
85     if (!GlobalSettings::TestModeEnabled() && !m_installContext.m_quiet) {
86         AddStep(&TaskWidgetConfig::StepCancelWidgetInstallationAfterVerifyFeatures);
87         AddStep(&TaskWidgetConfig::StepShowWidgetInfo);
88         AddStep(&TaskWidgetConfig::StepCancelWidgetInstallation);
89         AddStep(&TaskWidgetConfig::StepCheckMinVersionInfo);
90         AddStep(&TaskWidgetConfig::StepCancelWidgetInstallationAfterMinVersion);
91         AddStep(&TaskWidgetConfig::StepDeletePopupWin);
92     }
93 }
94
95 void TaskWidgetConfig::StepProcessConfigurationFile()
96 {
97     Try
98     {
99         std::string path = m_installContext.locations->getConfigurationDir();
100         LogInfo("path: " << path);
101
102         processFile(path, m_installContext.widgetConfig);
103     }
104     Catch(Exception::ConfigParseFailed)
105     {
106         LogError("Parsing failed.");
107         ReThrow(Exceptions::WidgetConfigFileInvalid);
108     }
109     Try
110     {
111         // To get widget type for distribute WAC, TIZEN WebApp
112         setApplicationType();
113     }
114     Catch(Exception::ConfigParseFailed)
115     {
116         LogError("Config.xml has more than one namespace");
117         ReThrow(Exceptions::WidgetConfigFileInvalid);
118     }
119
120     m_installContext.job->UpdateProgress(
121         InstallerContext::INSTALL_WIDGET_CONFIG1,
122         "Parse elements of configuration file and save them");
123 }
124
125 void TaskWidgetConfig::ReadLocaleFolders()
126 {
127     LogDebug("Reading locale");
128     //Adding default locale
129     m_localeFolders.insert(L"");
130
131     std::string localePath = m_installContext.locations->getConfigurationDir() + "/locales";
132     DIR* localeDir = opendir(localePath.c_str());
133     if (!localeDir) {
134         LogDebug("No /locales directory in the widget package.");
135         return;
136     }
137
138     struct dirent* dirent;
139     struct stat statStruct;
140     do {
141         errno = 0;
142         if ((dirent = readdir(localeDir))) {
143             DPL::String dirName = DPL::FromUTF8String(dirent->d_name);
144             std::string absoluteDirName = localePath + "/";
145             absoluteDirName += dirent->d_name;
146
147             if (stat(absoluteDirName.c_str(), &statStruct) != 0) {
148                 LogError("stat() failed with " << DPL::GetErrnoString());
149                 continue;
150             }
151
152             if (S_ISDIR(statStruct.st_mode)) {
153                 //Yes, we ignore current, parent & hidden directories
154                 if (dirName[0] != L'.') {
155                     LogDebug("Adding locale directory \"" << dirName << "\"");
156                     m_localeFolders.insert(dirName);
157                 }
158             }
159         }
160     }
161     while (dirent);
162
163     if (errno != 0) {
164         LogError("readdir() failed with " << DPL::GetErrnoString());
165     }
166
167     if (closedir(localeDir)) {
168         LogError("closedir() failed with " << 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         LogDebug("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                     LogDebug("Invalid widget configuration file!");
716                     //                    _rethrown_exception.Dump();
717                     *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
718                     closedir(dir);
719                     return false;
720                 }
721
722                 has_config_xml = true;
723                 break;
724             }
725         }
726     }
727     closedir(dir);
728
729     //We must have config.xml so leaveing if we doesn't
730     if (!has_config_xml) {
731         LogDebug("Invalid archive");
732         *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
733         return false;
734     }
735     return true;
736 }
737
738 bool TaskWidgetConfig::locateAndParseConfigurationFile(
739         const std::string& _currentPath,
740         WrtDB::WidgetRegisterInfo& pWidgetConfigInfo,
741         const std::string& baseFolder,
742         int* pErrCode)
743 {
744     using namespace WrtDB;
745
746     if (!pErrCode) {
747         return false;
748     }
749
750     ConfigParserData& configInfo = pWidgetConfigInfo.configInfo;
751
752     // check if this installation from browser, or not.
753     size_t pos = _currentPath.rfind("/");
754     std::ostringstream infoPath;
755     infoPath << _currentPath.substr(pos+1);
756
757     if (infoPath.str() != WRT_WIDGET_CONFIG_FILE_NAME) {
758         if (_currentPath.empty() || baseFolder.empty()) {
759             *pErrCode = WRT_ERR_INVALID_ARG;
760             return false;
761         }
762         // in case of general installation using wgt archive
763         if(!parseConfigurationFileWidget(configInfo, _currentPath, pErrCode))
764         {
765             return false;
766         }
767     } else {
768         // in case of browser installation
769         if(!parseConfigurationFileBrowser(configInfo, _currentPath, pErrCode))
770         {
771             return false;
772         }
773     }
774
775     if(!fillWidgetConfig(pWidgetConfigInfo, configInfo))
776     {
777         *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
778         return false;
779     }
780     return true;
781 }
782
783 bool TaskWidgetConfig::fillWidgetConfig(WrtDB::WidgetRegisterInfo& pWidgetConfigInfo,
784                                         WrtDB::ConfigParserData& configInfo)
785 {
786     if (!!configInfo.widget_id) {
787         if (!pWidgetConfigInfo.guid) {
788             pWidgetConfigInfo.guid = configInfo.widget_id;
789         } else {
790             if (pWidgetConfigInfo.guid != configInfo.widget_id) {
791                 LogDebug("Invalid archive");
792                 return false;
793             }
794         }
795     }
796     if (!!configInfo.tizenId) {
797         if (!pWidgetConfigInfo.pkgname) {
798             pWidgetConfigInfo.pkgname = configInfo.tizenId;
799         } else {
800             if (pWidgetConfigInfo.pkgname != configInfo.tizenId) {
801                 LogDebug("Invalid archive - Tizen ID not same error");
802                 return false;
803             }
804         }
805     }
806     if (!!configInfo.version) {
807         if (!pWidgetConfigInfo.version) {
808             pWidgetConfigInfo.version = configInfo.version;
809         } else {
810             if (pWidgetConfigInfo.version != configInfo.version) {
811                 LogDebug("Invalid archive");
812                 return false;
813             }
814         }
815     }
816     if (!!configInfo.minVersionRequired) {
817         pWidgetConfigInfo.minVersion = configInfo.minVersionRequired;
818     } else if (!!configInfo.tizenMinVersionRequired) {
819         pWidgetConfigInfo.minVersion = configInfo.tizenMinVersionRequired;
820     }
821     return true;
822 }
823
824 void TaskWidgetConfig::processFile(const std::string& path,
825         WrtDB::WidgetRegisterInfo &widgetConfiguration)
826 {
827     int pErrCode;
828
829     if (!locateAndParseConfigurationFile(path, widgetConfiguration,
830                                          DEFAULT_LANGUAGE, &pErrCode)) {
831         LogWarning("Widget archive: Failed while parsing config file");
832         ThrowMsg(Exception::ConfigParseFailed, path);
833     }
834 }
835
836 } //namespace WidgetInstall
837 } //namespace Jobs