1328f0753ac0fc21cf30bcbc8ba4cc73bd8e1989
[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
48 namespace { // anonymous
49 const DPL::String BR = DPL::FromUTF8String("<br>");
50 const std::string WIDGET_NOT_COMPATIBLE = "This widget is "
51                                           "not compatible with WRT.<br><br>";
52 const std::string QUESTION = "Do you want to install it anyway?";
53
54 const char *const DEFAULT_LANGUAGE = "default";
55
56 const char *const WRT_WIDGET_CONFIG_FILE_NAME = "config.xml";
57
58 const std::string WINDGET_INSTALL_NETWORK_ACCESS = "network access";
59 }
60
61 namespace Jobs {
62 namespace WidgetInstall {
63 void InstallerTaskWidgetPopupData::PopupData::addWidgetInfo(
64     const DPL::String &info)
65 {
66     widgetInfo = info;
67 }
68
69 TaskWidgetConfig::TaskWidgetConfig(InstallerContext& installContext) :
70     DPL::TaskDecl<TaskWidgetConfig>(this),
71     m_installContext(installContext)
72 {
73     AddStep(&TaskWidgetConfig::StepProcessConfigurationFile);
74     AddStep(&TaskWidgetConfig::ReadLocaleFolders);
75     AddStep(&TaskWidgetConfig::ProcessLocalizedStartFiles);
76     AddStep(&TaskWidgetConfig::ProcessBackgroundPageFile);
77     AddStep(&TaskWidgetConfig::ProcessLocalizedIcons);
78     AddStep(&TaskWidgetConfig::ProcessWidgetInstalledPath);
79     AddStep(&TaskWidgetConfig::StepVerifyFeatures);
80     AddStep(&TaskWidgetConfig::StepCheckMinVersionInfo);
81 }
82
83 void TaskWidgetConfig::StepProcessConfigurationFile()
84 {
85     Try
86     {
87         std::string path = m_installContext.locations->getConfigurationDir();
88         LogInfo("path: " << path);
89
90         processFile(path, m_installContext.widgetConfig);
91     }
92     Catch(Exception::ConfigParseFailed)
93     {
94         LogError("Parsing failed.");
95         ReThrow(Exceptions::WidgetConfigFileInvalid);
96     }
97
98     m_installContext.job->UpdateProgress(
99         InstallerContext::INSTALL_WIDGET_CONFIG1,
100         "Parse elements of configuration file and save them");
101 }
102
103 void TaskWidgetConfig::ReadLocaleFolders()
104 {
105     LogDebug("Reading locale");
106     //Adding default locale
107     m_localeFolders.insert(L"");
108
109     std::string localePath =
110         m_installContext.locations->getConfigurationDir() + "/locales";
111     DIR* localeDir = opendir(localePath.c_str());
112     if (!localeDir) {
113         LogDebug("No /locales directory in the widget package.");
114         return;
115     }
116
117
118
119     struct stat statStruct;
120     struct dirent dirent;
121     struct dirent *result;
122     int return_code;
123     errno = 0;
124     for (return_code = readdir_r(localeDir, &dirent, &result);
125             result != NULL && return_code == 0;
126             return_code = readdir_r(localeDir, &dirent, &result))
127     {
128         DPL::String dirName = DPL::FromUTF8String(dirent.d_name);
129         std::string absoluteDirName = localePath + "/";
130         absoluteDirName += dirent.d_name;
131
132         if (stat(absoluteDirName.c_str(), &statStruct) != 0) {
133             LogError("stat() failed with " << DPL::GetErrnoString());
134             continue;
135         }
136
137         if (S_ISDIR(statStruct.st_mode)) {
138             //Yes, we ignore current, parent & hidden directories
139             if (dirName[0] != L'.') {
140                 LogDebug("Adding locale directory \"" << dirName << "\"");
141                 m_localeFolders.insert(dirName);
142             }
143         }
144     }
145
146     if (return_code != 0 || errno != 0) {
147         LogError("readdir_r() failed with " << DPL::GetErrnoString());
148     }
149
150     if (-1 == TEMP_FAILURE_RETRY(closedir(localeDir))) {
151         LogError("Failed to close dir: " << localePath << " with error: "
152                                          << DPL::GetErrnoString());
153     }
154 }
155
156 void TaskWidgetConfig::ProcessLocalizedStartFiles()
157 {
158     typedef DPL::String S;
159     ProcessStartFile(
160         m_installContext.widgetConfig.configInfo.startFile,
161         m_installContext.widgetConfig.configInfo.
162             startFileContentType,
163         m_installContext.widgetConfig.configInfo.startFileEncoding,
164         true);
165     ProcessStartFile(S(L"index.htm"), S(L"text/html"));
166     ProcessStartFile(S(L"index.html"), S(L"text/html"));
167     ProcessStartFile(S(L"index.svg"), S(L"image/svg+xml"));
168     ProcessStartFile(S(L"index.xhtml"), S(L"application/xhtml+xml"));
169     ProcessStartFile(S(L"index.xht"), S(L"application/xhtml+xml"));
170     // TODO: (l.wrzosek) we need better check if in current locales widget is
171     // valid.
172     FOREACH(it, m_installContext.widgetConfig.localizationData.startFiles) {
173         if (it->propertiesForLocales.size() > 0) {
174             return;
175         }
176     }
177     ThrowMsg(Exceptions::WidgetConfigFileInvalid,
178              L"The Widget has no valid start file");
179 }
180
181 void TaskWidgetConfig::ProcessStartFile(const DPL::OptionalString& path,
182                                         const DPL::OptionalString& type,
183                                         const DPL::OptionalString& encoding,
184                                         bool typeForcedInConfig)
185 {
186     using namespace WrtDB;
187
188     if (!!path) {
189         WidgetRegisterInfo::LocalizedStartFile startFileData;
190         startFileData.path = *path;
191
192         FOREACH(i, m_localeFolders) {
193             DPL::String pathPrefix = *i;
194             if (!pathPrefix.empty()) {
195                 pathPrefix = L"locales/" + pathPrefix + L"/";
196             }
197
198             DPL::String relativePath = pathPrefix + *path;
199             DPL::String absolutePath = DPL::FromUTF8String(
200                     m_installContext.locations->getConfigurationDir()) + L"/" +
201                 relativePath;
202
203             // get property data from packaged app
204             if (WrtUtilFileExists(DPL::ToUTF8String(absolutePath))) {
205                 WidgetRegisterInfo::StartFileProperties startFileProperties;
206                 if (!!type) {
207                     startFileProperties.type = *type;
208                 } else {
209                     startFileProperties.type =
210                         MimeTypeUtils::identifyFileMimeType(absolutePath);
211                 }
212
213                 //proceed only if MIME type is supported
214                 if (MimeTypeUtils::isMimeTypeSupportedForStartFile(
215                         startFileProperties.type))
216                 {
217                     if (!!encoding) {
218                         startFileProperties.encoding = *encoding;
219                     } else {
220                         MimeTypeUtils::MimeAttributes attributes =
221                             MimeTypeUtils::getMimeAttributes(
222                                 startFileProperties.type);
223                         if (attributes.count(L"charset") > 0) {
224                             startFileProperties.encoding =
225                                 attributes[L"charset"];
226                         } else {
227                             startFileProperties.encoding = L"UTF-8";
228                         }
229                     }
230
231                     startFileData.propertiesForLocales[*i] =
232                         startFileProperties;
233                 } else {
234                     //9.1.16.5.content.8
235                     //(there seems to be no similar requirement in .6,
236                     //so let's throw only when mime type is
237                     // provided explcitly in config.xml)
238                     if (typeForcedInConfig) {
239                         ThrowMsg(Exceptions::WidgetConfigFileInvalid,
240                                  "Unsupported MIME type for start file.");
241                     }
242                 }
243             } else {
244                 // set property data for hosted start url
245                 // Hosted start url only support TIZEN WebApp
246                 if (m_installContext.widgetConfig.webAppType ==
247                     APP_TYPE_TIZENWEBAPP)
248                 {
249                     std::string startPath = DPL::ToUTF8String(
250                             startFileData.path);
251
252                     if (strstr(startPath.c_str(),
253                                "http") == startPath.c_str())
254                     {
255                         WidgetRegisterInfo::StartFileProperties
256                             startFileProperties;
257                         if (!!type) {
258                             startFileProperties.type = *type;
259                         }
260                         if (!!encoding) {
261                             startFileProperties.encoding = *encoding;
262                         }
263                         startFileData.propertiesForLocales[*i] =
264                             startFileProperties;
265                     }
266                 }
267             }
268         }
269
270         m_installContext.widgetConfig.localizationData.startFiles.push_back(
271             startFileData);
272     }
273 }
274
275 void TaskWidgetConfig::ProcessBackgroundPageFile()
276 {
277     if (!!m_installContext.widgetConfig.configInfo.backgroundPage) {
278         // check whether file exists
279         DPL::String backgroundPagePath = DPL::FromUTF8String(
280                 m_installContext.locations->getConfigurationDir()) + L"/" +
281             *m_installContext.widgetConfig.configInfo.backgroundPage;
282         //if no then cancel installation
283         if (!WrtUtilFileExists(DPL::ToUTF8String(backgroundPagePath))) {
284             ThrowMsg(Exceptions::WidgetConfigFileInvalid,
285                      L"Given background page file not found in archive");
286         }
287     }
288 }
289
290 void TaskWidgetConfig::ProcessLocalizedIcons()
291 {
292     using namespace WrtDB;
293     ProcessIcon(ConfigParserData::Icon(L"icon.svg"));
294     ProcessIcon(ConfigParserData::Icon(L"icon.ico"));
295     ProcessIcon(ConfigParserData::Icon(L"icon.png"));
296     ProcessIcon(ConfigParserData::Icon(L"icon.gif"));
297     ProcessIcon(ConfigParserData::Icon(L"icon.jpg"));
298
299     FOREACH(i, m_installContext.widgetConfig.configInfo.iconsList)
300     {
301         ProcessIcon(*i);
302     }
303 }
304
305 void TaskWidgetConfig::ProcessIcon(const WrtDB::ConfigParserData::Icon& icon)
306 {
307     LogInfo("enter");
308     bool isAnyIconValid = false;
309     //In case a default filename is passed as custom filename in config.xml, we
310     //need to keep a set of already processed filenames to avoid icon
311     // duplication
312     //in database.
313
314     using namespace WrtDB;
315
316     if (m_processedIconSet.count(icon.src) > 0) {
317         return;
318     }
319     m_processedIconSet.insert(icon.src);
320
321     LocaleSet localesAvailableForIcon;
322
323     FOREACH(i, m_localeFolders)
324     {
325         DPL::String pathPrefix = *i;
326         if (!pathPrefix.empty()) {
327             pathPrefix = L"locales/" + pathPrefix + L"/";
328         }
329
330         DPL::String relativePath = pathPrefix + icon.src;
331         DPL::String absolutePath = DPL::FromUTF8String(
332                 m_installContext.locations->getConfigurationDir()) + L"/" +
333             relativePath;
334
335         if (WrtUtilFileExists(DPL::ToUTF8String(absolutePath))) {
336             DPL::String type = MimeTypeUtils::identifyFileMimeType(absolutePath);
337
338             if (MimeTypeUtils::isMimeTypeSupportedForIcon(type)) {
339                 isAnyIconValid = true;
340                 localesAvailableForIcon.insert(*i);
341                 LogInfo("Icon absolutePath :" << absolutePath <<
342                         ", assigned locale :" << *i << ", type: " << type);
343             }
344         }
345     }
346
347     if (isAnyIconValid) {
348         WidgetRegisterInfo::LocalizedIcon localizedIcon(icon,
349                                                         localesAvailableForIcon);
350         m_installContext.widgetConfig.localizationData.icons.push_back(
351             localizedIcon);
352     }
353 }
354
355 void TaskWidgetConfig::ProcessWidgetInstalledPath()
356 {
357     LogDebug("ProcessWidgetInstalledPath");
358     m_installContext.widgetConfig.widgetInstalledPath =
359         DPL::FromUTF8String(
360             m_installContext.locations->getPackageInstallationDir());
361 }
362
363 void TaskWidgetConfig::StepCheckMinVersionInfo()
364 {
365     if (!isMinVersionCompatible(
366             m_installContext.widgetConfig.webAppType.appType,
367             m_installContext.widgetConfig.minVersion))
368     {
369         LogError(
370             "Platform version lower than required -> cancelling installation");
371         ThrowMsg(Exceptions::NotAllowed,
372                  "Platform version does not meet requirements");
373     }
374
375     m_installContext.job->UpdateProgress(
376         InstallerContext::INSTALL_WIDGET_CONFIG2,
377         "Check MinVersion Finished");
378 }
379
380 void TaskWidgetConfig::StepVerifyFeatures()
381 {
382     using namespace WrtDB;
383     ConfigParserData &data = m_installContext.widgetConfig.configInfo;
384     ConfigParserData::FeaturesList list = data.featuresList;
385     ConfigParserData::FeaturesList newList;
386
387     //in case of tests, this variable is unused
388     std::string featureInfo;
389     FOREACH(it, list)
390     {
391         // check feature vender for permission
392         // WAC, TIZEN WebApp cannot use other feature
393
394         if (!isFeatureAllowed(m_installContext.widgetConfig.webAppType.appType,
395                               it->name))
396         {
397             LogInfo("This application type not allowed to use this feature");
398             ThrowMsg(
399                 Exceptions::WidgetConfigFileInvalid,
400                 "This app type [" <<
401                 m_installContext.widgetConfig.webAppType.getApptypeToString()
402                                   <<
403                 "] cannot be allowed to use [" <<
404                 DPL::ToUTF8String(it->name) + "] feature");
405         } else {
406             newList.insert(*it);
407             featureInfo += DPL::ToUTF8String(it->name);
408             featureInfo += DPL::ToUTF8String(BR);
409         }
410     }
411     if (!data.accessInfoSet.empty()) {
412         featureInfo += WINDGET_INSTALL_NETWORK_ACCESS;
413         featureInfo += DPL::ToUTF8String(BR);
414     }
415     data.featuresList = newList;
416     if (!featureInfo.empty()) {
417         m_popupData.addWidgetInfo(DPL::FromUTF8String(featureInfo));
418     }
419
420     m_installContext.job->UpdateProgress(
421         InstallerContext::INSTALL_WIDGET_CONFIG2,
422         "Widget Config step2 Finished");
423 }
424
425 bool TaskWidgetConfig::isFeatureAllowed(WrtDB::AppType appType,
426                                         DPL::String featureName)
427 {
428     using namespace WrtDB;
429     LogInfo("AppType = [" <<
430             WidgetType(appType).getApptypeToString() << "]");
431     LogInfo("FetureName = [" << featureName << "]");
432
433     AppType featureType = APP_TYPE_UNKNOWN;
434     std::string featureStr = DPL::ToUTF8String(featureName);
435     const char* feature = featureStr.c_str();
436
437     // check prefix of  feature name
438     if (strstr(feature, PluginsPrefix::TIZENPluginsPrefix) == feature) {
439         // Tizen WebApp feature
440         featureType = APP_TYPE_TIZENWEBAPP;
441     } else if (strstr(feature, PluginsPrefix::WACPluginsPrefix) == feature) {
442         // WAC 2.0 feature
443         featureType = APP_TYPE_WAC20;
444     } else if (strstr(feature, PluginsPrefix::W3CPluginsPrefix) == feature) {
445         // W3C standard feature
446         // Both WAC and TIZEN WebApp are possible to use W3C plugins
447         return true;
448     } else {
449         // unknown feature
450         // unknown feature will be checked next step
451         return true;
452     }
453
454     if (appType == featureType) {
455         return true;
456     }
457     return false;
458 }
459
460 bool TaskWidgetConfig::parseVersionString(const std::string &version,
461                                           long &majorVersion,
462                                           long &minorVersion,
463                                           long &microVersion) const
464 {
465     std::istringstream inputString(version);
466     inputString >> majorVersion;
467     if (inputString.bad() || inputString.fail()) {
468         LogWarning("Invalid minVersion format.");
469         return false;
470     }
471     inputString.get(); // skip period
472     inputString >> minorVersion;
473     if (inputString.bad() || inputString.fail()) {
474         LogWarning("Invalid minVersion format");
475         return false;
476     } else {
477         inputString.get(); // skip period
478         if (inputString.bad() || inputString.fail()) {
479             inputString >> microVersion;
480         }
481     }
482     return true;
483 }
484
485 bool TaskWidgetConfig::isMinVersionCompatible(
486     WrtDB::AppType appType,
487     const DPL::OptionalString &
488     widgetVersion) const
489 {
490     if (widgetVersion.IsNull() || (*widgetVersion).empty()) {
491         if (appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) {
492             return false;
493         } else {
494             LogWarning("minVersion attribute is empty. WRT assumes platform "
495                     "supports this widget.");
496             return true;
497         }
498     }
499
500     //Parse widget version
501     long majorWidget = 0, minorWidget = 0, microWidget = 0;
502     if (!parseVersionString(DPL::ToUTF8String(*widgetVersion), majorWidget,
503                             minorWidget, microWidget))
504     {
505         LogWarning("Invalid format of widget version string.");
506         return false;
507     }
508
509     //Parse supported version
510     long majorSupported = 0, minorSupported = 0, microSupported = 0;
511     std::string version;
512     if (appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) {
513         version = WrtDB::GlobalConfig::GetTizenVersion();
514     } else if (appType == WrtDB::AppType::APP_TYPE_WAC20) {
515         version = WrtDB::GlobalConfig::GetWACVersion();
516     } else {
517         LogWarning("Invaild AppType");
518         return false;
519     }
520
521     if (!parseVersionString(version,
522                             majorSupported, minorSupported, microSupported))
523     {
524         LogWarning("Invalid format of platform version string.");
525         return true;
526     }
527
528     if (majorWidget > majorSupported ||
529         (majorWidget == majorSupported && minorWidget > minorSupported) ||
530         (majorWidget == majorSupported && minorWidget == minorSupported
531          && microWidget > microSupported))
532     {
533         LogInfo("Platform doesn't support this widget.");
534         return false;
535     }
536     return true;
537 }
538
539 bool TaskWidgetConfig::isTizenWebApp() const
540 {
541     bool ret = FALSE;
542     if (m_installContext.widgetConfig.webAppType.appType
543         == WrtDB::AppType::APP_TYPE_TIZENWEBAPP)
544     {
545         ret = TRUE;
546     }
547
548     return ret;
549 }
550
551 bool TaskWidgetConfig::parseConfigurationFileBrowser(
552     WrtDB::ConfigParserData& configInfo,
553     const std::string& _currentPath)
554 {
555     ParserRunner parser;
556     Try
557     {
558         parser.Parse(_currentPath, ElementParserPtr(new
559                                                     RootParser<
560                                                         WidgetParser>(
561                                                         configInfo,
562                                                         DPL::FromUTF32String(
563                                                             L"widget"))));
564     }
565     Catch(ElementParser::Exception::Base)
566     {
567         LogError("Invalid widget configuration file!");
568         return false;
569     }
570     return true;
571 }
572
573 bool TaskWidgetConfig::parseConfigurationFileWidget(
574     WrtDB::ConfigParserData& configInfo,
575     const std::string& _currentPath)
576 {
577     std::string configFilePath;
578     WrtUtilJoinPaths(configFilePath, _currentPath, WRT_WIDGET_CONFIG_FILE_NAME);
579     if (!WrtUtilFileExists(configFilePath))
580     {
581         LogError("Archive does not contain configuration file");
582         return false;
583     }
584
585     LogDebug("Configuration file: " << configFilePath);
586
587     Try
588     {
589         ParserRunner parser;
590         parser.Parse(configFilePath,
591                      ElementParserPtr(new RootParser<WidgetParser>(
592                                           configInfo,
593                                           DPL::FromUTF32String(L"widget"))));
594         return true;
595     }
596     Catch (ElementParser::Exception::Base)
597     {
598         LogError("Invalid configuration file!");
599         return false;
600     }
601 }
602
603 bool TaskWidgetConfig::locateAndParseConfigurationFile(
604     const std::string& _currentPath,
605     WrtDB::WidgetRegisterInfo& pWidgetConfigInfo,
606     const std::string& baseFolder)
607 {
608     using namespace WrtDB;
609
610     ConfigParserData& configInfo = pWidgetConfigInfo.configInfo;
611
612     // check if this installation from browser, or not.
613     size_t pos = _currentPath.rfind("/");
614     std::ostringstream infoPath;
615     infoPath << _currentPath.substr(pos + 1);
616
617     if (infoPath.str() != WRT_WIDGET_CONFIG_FILE_NAME) {
618         if (_currentPath.empty() || baseFolder.empty()) {
619             return false;
620         }
621         // in case of general installation using wgt archive
622         if (!parseConfigurationFileWidget(configInfo, _currentPath))
623         {
624             return false;
625         }
626     } else {
627         // in case of browser installation
628         if (!parseConfigurationFileBrowser(configInfo, _currentPath))
629         {
630             return false;
631         }
632     }
633
634     if (!fillWidgetConfig(pWidgetConfigInfo, configInfo)) {
635         return false;
636     }
637     return true;
638 }
639
640 bool TaskWidgetConfig::fillWidgetConfig(
641     WrtDB::WidgetRegisterInfo& pWidgetConfigInfo,
642     WrtDB::ConfigParserData& configInfo)
643 {
644     if (!!configInfo.widget_id) {
645         if (!pWidgetConfigInfo.guid) {
646             pWidgetConfigInfo.guid = configInfo.widget_id;
647         } else {
648             if (pWidgetConfigInfo.guid != configInfo.widget_id) {
649                 LogError("Invalid archive");
650                 return false;
651             }
652         }
653     }
654     if (!!configInfo.tizenAppId) {
655         if (DPL::ToUTF8String(pWidgetConfigInfo.tzAppid).compare(
656                 DPL::ToUTF8String(*configInfo.tizenAppId)) < 0)
657         {
658             LogError("Invalid archive - Tizen App ID not same error");
659             return false;
660         }
661     }
662     if (!!configInfo.tizenPkgId) {
663         if (pWidgetConfigInfo.tzPkgid != *configInfo.tizenPkgId) {
664             LogError("Invalid archive - Tizen Pkg ID not same error");
665             return false;
666         }
667     }
668     if (!!configInfo.version) {
669         if (!pWidgetConfigInfo.version) {
670             pWidgetConfigInfo.version = configInfo.version;
671         } else {
672             if (pWidgetConfigInfo.version != configInfo.version) {
673                 LogError("Invalid archive");
674                 return false;
675             }
676         }
677     }
678     if (!!configInfo.minVersionRequired) {
679         pWidgetConfigInfo.minVersion = configInfo.minVersionRequired;
680     } else if (!!configInfo.tizenMinVersionRequired) {
681         pWidgetConfigInfo.minVersion = configInfo.tizenMinVersionRequired;
682     }
683     return true;
684 }
685
686 void TaskWidgetConfig::processFile(
687     const std::string& path,
688     WrtDB::WidgetRegisterInfo &
689     widgetConfiguration)
690 {
691     if (!locateAndParseConfigurationFile(path, widgetConfiguration,
692                                          DEFAULT_LANGUAGE))
693     {
694         LogWarning("Widget archive: Failed while parsing config file");
695         ThrowMsg(Exception::ConfigParseFailed, path);
696     }
697 }
698 } //namespace WidgetInstall
699 } //namespace Jobs