Add set removable for manifest when CSC installation
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_manifest_file.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_manifest_file.cpp
18  * @author  Pawel Sikorski (p.sikorski@samgsung.com)
19  * @version
20  * @brief
21  */
22
23 //SYSTEM INCLUDES
24 #include <unistd.h>
25 #include <string>
26 #include <dpl/assert.h>
27 #include <dirent.h>
28 #include <fstream>
29 #include <ail.h>
30
31 //WRT INCLUDES
32 #include <widget_install/task_manifest_file.h>
33 #include <widget_install/job_widget_install.h>
34 #include <widget_install/widget_install_errors.h>
35 #include <widget_install/widget_install_context.h>
36 #include <web_provider_livebox_info.h>
37 #include <web_provider_plugin_info.h>
38 #include <dpl/wrt-dao-ro/global_config.h>
39 #include <dpl/log/log.h>
40 #include <dpl/file_input.h>
41 #include <dpl/errno_string.h>
42 #include <dpl/file_output.h>
43 #include <dpl/copy.h>
44 #include <dpl/exception.h>
45 #include <dpl/foreach.h>
46 #include <dpl/sstream.h>
47 #include <dpl/string.h>
48 #include <dpl/optional.h>
49 #include <dpl/utils/wrt_utility.h>
50 #include <map>
51 #include <libxml_utils.h>
52 #include <pkgmgr/pkgmgr_parser.h>
53 #include <dpl/localization/LanguageTagsProvider.h>
54
55 #define DEFAULT_ICON_NAME   "icon.png"
56
57 using namespace WrtDB;
58
59 namespace {
60 typedef std::map<DPL::String, DPL::String> LanguageTagMap;
61
62 const char* const STR_TRUE = "true";
63 const char* const STR_FALSE = "false";
64 const char* const STR_NODISPLAY = "nodisplay";
65
66 LanguageTagMap getLanguageTagMap()
67 {
68     LanguageTagMap map;
69
70 #define ADD(tag, l_tag) map.insert(std::make_pair(L###tag, L###l_tag));
71 #include "languages.def"
72 #undef ADD
73
74     return map;
75 }
76
77 DPL::OptionalString getLangTag(const DPL::String& tag)
78 {
79     static LanguageTagMap TagsMap =
80         getLanguageTagMap();
81
82     DPL::String langTag = tag;
83
84     LogDebug("Trying to map language tag: " << langTag);
85     size_t pos = langTag.find_first_of(L'_');
86     if (pos != DPL::String::npos) {
87         langTag.erase(pos);
88     }
89     DPL::OptionalString ret;
90
91     LanguageTagMap::iterator it = TagsMap.find(langTag);
92     if (it != TagsMap.end()) {
93         ret = it->second;
94     }
95     LogDebug("Mapping IANA Language tag to language tag: " <<
96              langTag << " -> " << ret);
97
98     return ret;
99 }
100 }
101
102 namespace Jobs {
103 namespace WidgetInstall {
104 const char * TaskManifestFile::encoding = "UTF-8";
105
106 TaskManifestFile::TaskManifestFile(InstallerContext &inCont) :
107     DPL::TaskDecl<TaskManifestFile>(this),
108     m_context(inCont),
109     writer(NULL)
110 {
111     if (m_context.isUpdateMode) {
112         // for widget update.
113         AddStep(&TaskManifestFile::stepBackupIconFiles);
114         AddStep(&TaskManifestFile::stepCopyIconFiles);
115         AddStep(&TaskManifestFile::stepCopyLiveboxFiles);
116         AddStep(&TaskManifestFile::stepCreateExecFile);
117         AddStep(&TaskManifestFile::stepGenerateManifest);
118         AddStep(&TaskManifestFile::stepParseManifest);
119
120         AddAbortStep(&TaskManifestFile::stepAbortIconFiles);
121     } else {
122         AddStep(&TaskManifestFile::stepCopyIconFiles);
123         AddStep(&TaskManifestFile::stepCopyLiveboxFiles);
124         AddStep(&TaskManifestFile::stepCreateExecFile);
125         AddStep(&TaskManifestFile::stepGenerateManifest);
126         AddStep(&TaskManifestFile::stepParseManifest);
127
128         AddAbortStep(&TaskManifestFile::stepAbortParseManifest);
129     }
130 }
131
132 TaskManifestFile::~TaskManifestFile()
133 {}
134
135 void TaskManifestFile::stepCreateExecFile()
136 {
137     std::string exec = m_context.locations->getExecFile();
138     std::string clientExeStr = GlobalConfig::GetWrtClientExec();
139
140 #ifdef MULTIPROCESS_SERVICE_SUPPORT
141     //default widget
142     std::stringstream postfix;
143     postfix << AppControlPrefix::PROCESS_PREFIX << 0;
144     std::string controlExec = exec;
145     controlExec.append(postfix.str());
146
147     errno = 0;
148     if (symlink(clientExeStr.c_str(), controlExec.c_str()) != 0)
149     {
150         int error = errno;
151         if (error)
152             LogPedantic("Failed to make a symbolic name for a file "
153                     << "[" <<  DPL::GetErrnoString(error) << "]");
154     }
155
156     // app-control widgets
157     unsigned int indexMax = 0;
158     FOREACH(it, m_context.widgetConfig.configInfo.appControlList) {
159         if (it->m_index > indexMax) {
160             indexMax = it->m_index;
161         }
162     }
163
164     for (std::size_t i = 1; i <= indexMax; ++i) {
165         std::stringstream postfix;
166         postfix << AppControlPrefix::PROCESS_PREFIX << i;
167         std::string controlExec = exec;
168         controlExec.append(postfix.str());
169         errno = 0;
170         if (symlink(clientExeStr.c_str(), controlExec.c_str()) != 0) {
171             int error = errno;
172             if (error) {
173                 LogPedantic("Failed to make a symbolic name for a file "
174                     << "[" <<  DPL::GetErrnoString(error) << "]");
175             }
176         }
177     }
178 #else
179     //default widget
180     LogInfo("link -s " << clientExeStr << " " << exec);
181     errno = 0;
182     if (symlink(clientExeStr.c_str(), exec.c_str()) != 0)
183     {
184         int error = errno;
185         if (error)
186             LogPedantic("Failed to make a symbolic name for a file "
187                     << "[" <<  DPL::GetErrnoString(error) << "]");
188     }
189 #endif
190     m_context.job->UpdateProgress(
191             InstallerContext::INSTALL_CREATE_EXECFILE,
192             "Widget execfile creation Finished");
193 }
194
195 void TaskManifestFile::stepCopyIconFiles()
196 {
197     LogDebug("CopyIconFiles");
198
199     //This function copies icon to desktop icon path. For each locale avaliable
200     //which there is at least one icon in widget for, icon file is copied.
201     //Coping prioritize last positions when coping. If there is several icons
202     //with given locale, the one, that will be copied, will be icon
203     //which is declared by <icon> tag later than the others in config.xml of
204     // widget
205
206     std::vector<Locale> generatedLocales;
207
208     WrtDB::WidgetRegisterInfo::LocalizedIconList & icons =
209         m_context.widgetConfig.localizationData.icons;
210
211     //reversed: last <icon> has highest priority to be copied if it has given
212     // locale (TODO: why was that working that way?)
213     for (WrtDB::WidgetRegisterInfo::LocalizedIconList::const_reverse_iterator
214          icon = icons.rbegin();
215          icon != icons.rend();
216          ++icon)
217     {
218         FOREACH(locale, icon->availableLocales)
219         {
220             DPL::String src = icon->src;
221             LogDebug("Icon for locale: " << *locale << "is : " << src);
222
223             if (std::find(generatedLocales.begin(), generatedLocales.end(),
224                           *locale) != generatedLocales.end())
225             {
226                 LogDebug("Skipping - has that locale");
227                 continue;
228             } else {
229                 generatedLocales.push_back(*locale);
230             }
231
232             std::ostringstream sourceFile;
233             std::ostringstream targetFile;
234
235             sourceFile << m_context.locations->getSourceDir() << "/";
236
237             if (!locale->empty()) {
238                 sourceFile << "locales/" << *locale << "/";
239             }
240
241             sourceFile << src;
242
243             targetFile << GlobalConfig::GetUserWidgetDesktopIconPath() << "/";
244             targetFile << getIconTargetFilename(*locale);
245
246             if (m_context.widgetConfig.packagingType ==
247                 WrtDB::PKG_TYPE_HOSTED_WEB_APP)
248             {
249                 m_context.locations->setIconTargetFilenameForLocale(
250                     targetFile.str());
251             }
252
253             LogDebug("Copying icon: " << sourceFile.str() <<
254                      " -> " << targetFile.str());
255
256             icon_list.push_back(targetFile.str());
257
258             Try
259             {
260                 DPL::FileInput input(sourceFile.str());
261                 DPL::FileOutput output(targetFile.str());
262                 DPL::Copy(&input, &output);
263             }
264
265             Catch(DPL::FileInput::Exception::Base)
266             {
267                 // Error while opening or closing source file
268                 //ReThrowMsg(InstallerException::CopyIconFailed,
269                 // sourceFile.str());
270                 LogError(
271                     "Copying widget's icon failed. Widget's icon will not be" \
272                     "available from Main Screen");
273             }
274
275             Catch(DPL::FileOutput::Exception::Base)
276             {
277                 // Error while opening or closing target file
278                 //ReThrowMsg(InstallerException::CopyIconFailed,
279                 // targetFile.str());
280                 LogError(
281                     "Copying widget's icon failed. Widget's icon will not be" \
282                     "available from Main Screen");
283             }
284
285             Catch(DPL::CopyFailed)
286             {
287                 // Error while copying
288                 //ReThrowMsg(InstallerException::CopyIconFailed,
289                 // targetFile.str());
290                 LogError(
291                     "Copying widget's icon failed. Widget's icon will not be" \
292                     "available from Main Screen");
293             }
294         }
295     }
296
297     m_context.job->UpdateProgress(
298         InstallerContext::INSTALL_COPY_ICONFILE,
299         "Widget iconfile copy Finished");
300 }
301
302 void TaskManifestFile::stepCopyLiveboxFiles()
303 {
304     LogDebug("Copy Livebox Files");
305
306     using namespace WrtDB;
307     ConfigParserData &data = m_context.widgetConfig.configInfo;
308     ConfigParserData::LiveboxList liveBoxList = data.m_livebox;
309
310     if (liveBoxList.size() <= 0) {
311         return;
312     }
313
314     std::ostringstream sourceFile;
315     std::ostringstream targetFile;
316
317     FOREACH (boxIt, liveBoxList) {
318         boxSizeType boxSizeList = (**boxIt).m_boxInfo.m_boxSize;
319         FOREACH (sizeIt, boxSizeList) {
320             std::string preview = DPL::ToUTF8String((*sizeIt).second);
321             if (preview.empty()) {
322                 continue;
323             }
324             // copy preview image to shared directory
325             sourceFile << m_context.locations->getSourceDir() << "/";
326             sourceFile << preview;
327             targetFile << m_context.locations->getSharedDataDir() << "/";
328             targetFile << (**boxIt).m_liveboxId << ".";
329             targetFile << DPL::ToUTF8String((*sizeIt).first) << ".preview.png";
330
331             DPL::FileInput input(sourceFile.str());
332             DPL::FileOutput output(targetFile.str());
333             DPL::Copy(&input, &output);
334
335             // clear stream objects
336             sourceFile.str("");
337             targetFile.str("");
338         }
339         // check this livebox has icon element
340         std::string icon = DPL::ToUTF8String((**boxIt).m_icon);
341         if (icon.empty()) {
342             continue;
343         }
344         // copy icon to shared directory
345         sourceFile << m_context.locations->getSourceDir() << "/";
346         sourceFile << icon;
347         targetFile << m_context.locations->getSharedDataDir() << "/";
348         targetFile << (**boxIt).m_liveboxId << ".icon.png";
349
350         DPL::FileInput input(sourceFile.str());
351         DPL::FileOutput output(targetFile.str());
352         DPL::Copy(&input, &output);
353
354         // clear stream objects
355         sourceFile.str("");
356         targetFile.str("");
357     }
358
359     m_context.job->UpdateProgress(
360         InstallerContext::INSTALL_COPY_LIVEBOX_FILES,
361         "Livebox files copy Finished");
362 }
363
364 void TaskManifestFile::stepBackupIconFiles()
365 {
366     LogDebug("Backup Icon Files");
367
368     backup_dir << m_context.locations->getBackupDir() << "/";
369
370     backupIconFiles();
371
372     m_context.job->UpdateProgress(
373         InstallerContext::INSTALL_BACKUP_ICONFILE,
374         "New Widget icon file backup Finished");
375 }
376
377 void TaskManifestFile::stepAbortIconFiles()
378 {
379     LogDebug("Abrot Icon Files");
380     FOREACH(it, icon_list)
381     {
382         LogDebug("Remove Update Icon : " << (*it));
383         unlink((*it).c_str());
384     }
385
386     std::ostringstream b_icon_dir;
387     b_icon_dir << backup_dir.str() << "icons";
388
389     std::list<std::string> fileList;
390     getFileList(b_icon_dir.str().c_str(), fileList);
391
392     FOREACH(back_icon, fileList)
393     {
394         std::ostringstream res_file;
395         res_file << GlobalConfig::GetUserWidgetDesktopIconPath();
396         res_file << "/" << (*back_icon);
397
398         std::ostringstream backup_file;
399         backup_file << b_icon_dir.str() << "/" << (*back_icon);
400
401         Try
402         {
403             DPL::FileInput input(backup_file.str());
404             DPL::FileOutput output(res_file.str());
405             DPL::Copy(&input, &output);
406         }
407         Catch(DPL::FileInput::Exception::Base)
408         {
409             LogError("Restoration icon File Failed." << backup_file.str()
410                                                      << " to " << res_file.str());
411         }
412
413         Catch(DPL::FileOutput::Exception::Base)
414         {
415             LogError("Restoration icon File Failed." << backup_file.str()
416                                                      << " to " << res_file.str());
417         }
418         Catch(DPL::CopyFailed)
419         {
420             LogError("Restoration icon File Failed." << backup_file.str()
421                                                      << " to " << res_file.str());
422         }
423     }
424 }
425
426 DPL::String TaskManifestFile::getIconTargetFilename(
427     const DPL::String& languageTag) const
428 {
429     DPL::OStringStream filename;
430     TizenAppId appid = m_context.widgetConfig.tzAppid;
431
432     filename << DPL::ToUTF8String(appid).c_str();
433
434     if (!languageTag.empty()) {
435         DPL::OptionalString tag = getLangTag(languageTag); // translate en ->
436                                                            // en_US etc
437         if (tag.IsNull()) {
438             tag = languageTag;
439         }
440         DPL::String locale =
441             LanguageTagsProvider::BCP47LanguageTagToLocale(*tag);
442
443         if (locale.empty()) {
444             filename << L"." << languageTag;
445         } else {
446             filename << L"." << locale;
447         }
448     }
449
450     filename << L".png";
451     return filename.str();
452 }
453
454 void TaskManifestFile::saveLocalizedKey(std::ofstream &file,
455                                         const DPL::String& key,
456                                         const DPL::String& languageTag)
457 {
458     DPL::String locale =
459         LanguageTagsProvider::BCP47LanguageTagToLocale(languageTag);
460
461     file << key;
462     if (!locale.empty()) {
463         file << "[" << locale << "]";
464     }
465     file << "=";
466 }
467
468 void TaskManifestFile::backupIconFiles()
469 {
470     LogInfo("Backup Icon Files");
471
472     std::ostringstream b_icon_dir;
473     b_icon_dir << backup_dir.str() << "icons";
474
475     LogDebug("Create icon backup folder : " << b_icon_dir.str());
476     WrtUtilMakeDir(b_icon_dir.str());
477
478     std::list<std::string> fileList;
479     getFileList(GlobalConfig::GetUserWidgetDesktopIconPath(), fileList);
480     std::string appid = DPL::ToUTF8String(m_context.widgetConfig.tzAppid);
481
482     FOREACH(it, fileList)
483     {
484         if (0 == (strncmp((*it).c_str(), appid.c_str(),
485                           strlen(appid.c_str()))))
486         {
487             std::ostringstream icon_file, backup_icon;
488             icon_file << GlobalConfig::GetUserWidgetDesktopIconPath();
489             icon_file << "/" << (*it);
490
491             backup_icon << b_icon_dir.str() << "/" << (*it);
492
493             LogDebug("Backup icon file " << icon_file.str() << " to " <<
494                      backup_icon.str());
495             Try
496             {
497                 DPL::FileInput input(icon_file.str());
498                 DPL::FileOutput output(backup_icon.str());
499                 DPL::Copy(&input, &output);
500             }
501             Catch(DPL::FileInput::Exception::Base)
502             {
503                 LogError("Backup Desktop File Failed.");
504                 ReThrowMsg(Exceptions::BackupFailed, icon_file.str());
505             }
506
507             Catch(DPL::FileOutput::Exception::Base)
508             {
509                 LogError("Backup Desktop File Failed.");
510                 ReThrowMsg(Exceptions::BackupFailed, backup_icon.str());
511             }
512             Catch(DPL::CopyFailed)
513             {
514                 LogError("Backup Desktop File Failed.");
515                 ReThrowMsg(Exceptions::BackupFailed, backup_icon.str());
516             }
517             unlink((*it).c_str());
518         }
519     }
520 }
521
522 void TaskManifestFile::getFileList(const char* path,
523                                    std::list<std::string> &list)
524 {
525     DIR* dir = opendir(path);
526     if (!dir) {
527         LogError("icon directory doesn't exist");
528         ThrowMsg(Exceptions::FileOperationFailed, path);
529     }
530
531     struct dirent entry;
532     struct dirent *result;
533     int return_code;
534     errno = 0;
535     for (return_code = readdir_r(dir, &entry, &result);
536             result != NULL && return_code == 0;
537             return_code = readdir_r(dir, &entry, &result))
538     {
539         if (strcmp(entry.d_name, ".") == 0 ||
540             strcmp(entry.d_name, "..") == 0)
541         {
542             continue;
543         }
544         std::string file_name = entry.d_name;
545         list.push_back(file_name);
546     }
547
548     if (return_code != 0 || errno != 0) {
549         LogError("readdir_r() failed with " << DPL::GetErrnoString());
550     }
551
552     if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
553         LogError("Failed to close dir: " << path << " with error: "
554                                          << DPL::GetErrnoString());
555     }
556 }
557
558 void TaskManifestFile::stepGenerateManifest()
559 {
560     TizenPkgId pkgid = m_context.widgetConfig.tzPkgid;
561     manifest_name = pkgid + L".xml";
562     manifest_file += L"/tmp/" + manifest_name;
563
564     //libxml - init and check
565     LibxmlSingleton::Instance().init();
566
567     writeManifest(manifest_file);
568
569     std::ostringstream destFile;
570     if (m_context.mode.rootPath == InstallMode::RootPath::RO) {
571         destFile << "/usr/share/packages" << "/"; //TODO constant with path
572     } else {
573         destFile << "/opt/share/packages" << "/"; //TODO constant with path
574     }
575
576     destFile << DPL::ToUTF8String(manifest_name);
577     commit_manifest = destFile.str();
578     LogDebug("Commiting manifest file : " << commit_manifest);
579
580     m_context.job->UpdateProgress(
581         InstallerContext::INSTALL_CREATE_MANIFEST,
582         "Widget Manifest Creation Finished");
583 }
584
585 void TaskManifestFile::stepParseManifest()
586 {
587     int code = 0;
588
589     char* updateTags[3] = {NULL, };
590
591     if (!m_context.mode.removable) {
592         updateTags[0] = "preload=false";
593         updateTags[1] = "removable=false";
594         updateTags[2] = NULL;
595
596     }
597
598     if (!access(commit_manifest.c_str(), F_OK) == 0) {
599         commitManifest();
600         code = pkgmgr_parser_parse_manifest_for_installation(
601                 commit_manifest.c_str(), (updateTags[0] == NULL) ? NULL : updateTags);
602
603         if (code != 0) {
604             LogError("Manifest parser error: " << code);
605             ThrowMsg(Exceptions::ManifestInvalid, "Parser returncode: " << code);
606         }
607     } else {
608         if (m_context.widgetConfig.packagingType !=
609                 PKG_TYPE_HYBRID_WEB_APP)
610         {
611             commitManifest();
612             code = pkgmgr_parser_parse_manifest_for_upgrade(
613                     commit_manifest.c_str(), (updateTags[0] == NULL) ? NULL : updateTags);
614
615             if (code != 0) {
616                 LogError("Manifest parser error: " << code);
617                 ThrowMsg(Exceptions::ManifestInvalid, "Parser returncode: " << code);
618             }
619
620         }
621     }
622
623     m_context.job->UpdateProgress(
624             InstallerContext::INSTALL_CREATE_MANIFEST,
625             "Widget Manifest Parsing Finished");
626     LogDebug("Manifest parsed");
627 }
628
629 void TaskManifestFile::commitManifest()
630 {
631
632     if (!(m_context.mode.rootPath == InstallMode::RootPath::RO &&
633                 m_context.mode.installTime == InstallMode::InstallTime::PRELOAD
634                 && m_context.mode.extension == InstallMode::ExtensionType::DIR)) {
635         LogInfo("cp " << manifest_file << " " << commit_manifest);
636
637         DPL::FileInput input(DPL::ToUTF8String(manifest_file));
638         DPL::FileOutput output(commit_manifest);
639         DPL::Copy(&input, &output);
640         LogDebug("Manifest writen to: " << commit_manifest);
641
642         //removing temp file
643         unlink((DPL::ToUTF8String(manifest_file)).c_str());
644         manifest_file = DPL::FromUTF8String(commit_manifest);
645     }
646 }
647
648 void TaskManifestFile::writeManifest(const DPL::String & path)
649 {
650     LogDebug("Generating manifest file : " << path);
651     Manifest manifest;
652     UiApplication uiApp;
653
654 #ifdef MULTIPROCESS_SERVICE_SUPPORT
655     //default widget content
656     std::stringstream postfix;
657     // index 0 is reserved
658     postfix << AppControlPrefix::PROCESS_PREFIX << 0;
659     setWidgetExecPath(uiApp, postfix.str());
660     setWidgetName(manifest, uiApp);
661     setWidgetIds(manifest, uiApp);
662     setWidgetIcons(uiApp);
663     setWidgetDescription(manifest);
664     setWidgetManifest(manifest);
665     setWidgetOtherInfo(uiApp);
666     setAppCategory(uiApp);
667     setMetadata(uiApp);
668     setLiveBoxInfo(manifest);
669     setAccount(manifest);
670     setPrivilege(manifest);
671     manifest.addUiApplication(uiApp);
672
673     //app-control content
674     ConfigParserData::AppControlInfoList appControlList =
675         m_context.widgetConfig.configInfo.appControlList;
676     FOREACH(it, appControlList) {
677         UiApplication uiApp;
678
679         uiApp.setTaskmanage(true);
680         uiApp.setNodisplay(true);
681 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
682         uiApp.setTaskmanage(ConfigParserData::AppControlInfo::Disposition::INLINE != it->m_disposition);
683         uiApp.setMultiple(ConfigParserData::AppControlInfo::Disposition::INLINE == it->m_disposition);
684 #endif
685         std::stringstream postfix;
686         postfix << AppControlPrefix::PROCESS_PREFIX << it->m_index;
687         setWidgetExecPath(uiApp, postfix.str());
688         setWidgetName(manifest, uiApp);
689         setWidgetIds(manifest, uiApp);
690         setWidgetIcons(uiApp);
691         setAppControlInfo(uiApp, *it);
692         setAppCategory(uiApp);
693         setMetadata(uiApp);
694         manifest.addUiApplication(uiApp);
695     }
696 #else
697     //default widget content
698     setWidgetExecPath(uiApp);
699     setWidgetName(manifest, uiApp);
700     setWidgetIds(manifest, uiApp);
701     setWidgetIcons(uiApp);
702     setWidgetDescription(manifest);
703     setWidgetManifest(manifest);
704     setWidgetOtherInfo(uiApp);
705     setAppControlsInfo(uiApp);
706     setAppCategory(uiApp);
707     setMetadata(uiApp);
708     setLiveBoxInfo(manifest);
709     setAccount(manifest);
710     setPrivilege(manifest);
711
712     manifest.addUiApplication(uiApp);
713 #endif
714
715     manifest.generate(path);
716     LogDebug("Manifest file serialized");
717 }
718
719 void TaskManifestFile::setWidgetExecPath(UiApplication & uiApp,
720                                          const std::string &postfix)
721 {
722     std::string exec = m_context.locations->getExecFile();
723     if (!postfix.empty()) {
724         exec.append(postfix);
725     }
726     LogDebug("exec = " << exec);
727     uiApp.setExec(DPL::FromASCIIString(exec));
728 }
729
730 void TaskManifestFile::setWidgetName(Manifest & manifest,
731                                      UiApplication & uiApp)
732 {
733     bool defaultNameSaved = false;
734
735     DPL::OptionalString defaultLocale =
736         m_context.widgetConfig.configInfo.defaultlocale;
737     std::pair<DPL::String,
738               WrtDB::ConfigParserData::LocalizedData> defaultLocalizedData;
739     //labels
740     FOREACH(localizedData, m_context.widgetConfig.configInfo.localizedDataSet)
741     {
742         Locale i = localizedData->first;
743         DPL::OptionalString tag = getLangTag(i); // translate en -> en_US etc
744         if (tag.IsNull()) {
745             tag = i;
746         }
747         DPL::OptionalString name = localizedData->second.name;
748         generateWidgetName(manifest, uiApp, tag, name, defaultNameSaved);
749
750         //store default locale localized data
751         if (!!defaultLocale && defaultLocale == i) {
752             defaultLocalizedData = *localizedData;
753         }
754     }
755
756     if (!!defaultLocale && !defaultNameSaved) {
757         DPL::OptionalString name = defaultLocalizedData.second.name;
758         generateWidgetName(manifest,
759                            uiApp,
760                            DPL::OptionalString::Null,
761                            name,
762                            defaultNameSaved);
763     }
764 }
765
766 void TaskManifestFile::setWidgetIds(Manifest & manifest,
767                                     UiApplication & uiApp,
768                                     const std::string &postfix)
769 {
770     //appid
771     TizenAppId appid = m_context.widgetConfig.tzAppid;
772     if (!postfix.empty()) {
773         appid = DPL::FromUTF8String(DPL::ToUTF8String(appid).append(postfix));
774     }
775     uiApp.setAppid(appid);
776
777     //extraid
778     if (!!m_context.widgetConfig.guid) {
779         uiApp.setExtraid(*m_context.widgetConfig.guid);
780     } else {
781         if (!appid.empty()) {
782             uiApp.setExtraid(DPL::String(L"http://") + appid);
783         }
784     }
785
786     //type
787     uiApp.setType(DPL::FromASCIIString("webapp"));
788     manifest.setType(L"wgt");
789 }
790
791 void TaskManifestFile::generateWidgetName(Manifest & manifest,
792                                           UiApplication &uiApp,
793                                           const DPL::OptionalString& tag,
794                                           DPL::OptionalString name,
795                                           bool & defaultNameSaved)
796 {
797     if (!!name) {
798         if (!!tag) {
799             DPL::String locale =
800                 LanguageTagsProvider::BCP47LanguageTagToLocale(*tag);
801
802             if (!locale.empty()) {
803                 uiApp.addLabel(LabelType(*name, *tag));
804             } else {
805                 uiApp.addLabel(LabelType(*name));
806                 manifest.addLabel(LabelType(*name));
807             }
808         } else {
809             defaultNameSaved = true;
810             uiApp.addLabel(LabelType(*name));
811             manifest.addLabel(LabelType(*name));
812         }
813     }
814 }
815
816 void TaskManifestFile::setWidgetIcons(UiApplication & uiApp)
817 {
818     //TODO this file will need to be updated when user locale preferences
819     //changes.
820     bool defaultIconSaved = false;
821
822     DPL::OptionalString defaultLocale =
823         m_context.widgetConfig.configInfo.defaultlocale;
824
825     std::vector<Locale> generatedLocales;
826     WrtDB::WidgetRegisterInfo::LocalizedIconList & icons =
827         m_context.widgetConfig.localizationData.icons;
828
829     //reversed: last <icon> has highest priority to be writen to manifest if it
830     // has given locale (TODO: why was that working that way?)
831     for (WrtDB::WidgetRegisterInfo::LocalizedIconList::const_reverse_iterator
832          icon = icons.rbegin();
833          icon != icons.rend();
834          ++icon)
835     {
836         FOREACH(locale, icon->availableLocales)
837         {
838             if (std::find(generatedLocales.begin(), generatedLocales.end(),
839                           *locale) != generatedLocales.end())
840             {
841                 LogDebug("Skipping - has that locale - already in manifest");
842                 continue;
843             } else {
844                 generatedLocales.push_back(*locale);
845             }
846
847             DPL::OptionalString tag = getLangTag(*locale); // translate en ->
848                                                            // en_US etc
849             if (tag.IsNull()) {
850                 tag = *locale;
851             }
852
853             generateWidgetIcon(uiApp, tag, *locale, defaultIconSaved);
854         }
855     }
856     if (!!defaultLocale && !defaultIconSaved) {
857         generateWidgetIcon(uiApp, DPL::OptionalString::Null,
858                            DPL::String(),
859                            defaultIconSaved);
860     }
861 }
862
863 void TaskManifestFile::generateWidgetIcon(UiApplication & uiApp,
864                                           const DPL::OptionalString& tag,
865                                           const DPL::String& language,
866                                           bool & defaultIconSaved)
867 {
868     DPL::String locale;
869     if (!!tag) {
870         locale = LanguageTagsProvider::BCP47LanguageTagToLocale(*tag);
871     } else {
872         defaultIconSaved = true;
873     }
874
875     DPL::String iconText;
876     iconText += getIconTargetFilename(language);
877
878     if (!locale.empty()) {
879         uiApp.addIcon(IconType(iconText, locale));
880     } else {
881         uiApp.addIcon(IconType(iconText));
882     }
883     std::ostringstream iconPath;
884     iconPath << GlobalConfig::GetUserWidgetDesktopIconPath() << "/";
885     iconPath << getIconTargetFilename(locale);
886      m_context.job->SendProgressIconPath(iconPath.str());
887 }
888
889 void TaskManifestFile::setWidgetDescription(Manifest & manifest)
890 {
891     FOREACH(localizedData, m_context.widgetConfig.configInfo.localizedDataSet)
892     {
893         Locale i = localizedData->first;
894         DPL::OptionalString tag = getLangTag(i); // translate en -> en_US etc
895         if (tag.IsNull()) {
896             tag = i;
897         }
898         DPL::OptionalString description = localizedData->second.description;
899         generateWidgetDescription(manifest, tag, description);
900     }
901 }
902
903 void TaskManifestFile::generateWidgetDescription(Manifest & manifest,
904                                                  const DPL::OptionalString& tag,
905                                                   DPL::OptionalString description)
906 {
907     if (!!description) {
908         if (!!tag) {
909             DPL::String locale =
910                 LanguageTagsProvider::BCP47LanguageTagToLocale(*tag);
911             if (!locale.empty()) {
912                 manifest.addDescription(DescriptionType(*description, locale));
913             } else {
914                 manifest.addDescription(DescriptionType(*description));
915             }
916         } else {
917             manifest.addDescription(DescriptionType(*description));
918         }
919     }
920 }
921
922 void TaskManifestFile::setWidgetManifest(Manifest & manifest)
923 {
924     manifest.setPackage(m_context.widgetConfig.tzPkgid);
925
926     if (!!m_context.widgetConfig.version) {
927         manifest.setVersion(*m_context.widgetConfig.version);
928     }
929     DPL::String email = (!!m_context.widgetConfig.configInfo.authorEmail ?
930                          *m_context.widgetConfig.configInfo.authorEmail : L"");
931     DPL::String href = (!!m_context.widgetConfig.configInfo.authorHref ?
932                         *m_context.widgetConfig.configInfo.authorHref : L"");
933     DPL::String name = (!!m_context.widgetConfig.configInfo.authorName ?
934                         *m_context.widgetConfig.configInfo.authorName : L"");
935     manifest.addAuthor(Author(email, href, L"", name));
936 }
937
938 void TaskManifestFile::setWidgetOtherInfo(UiApplication & uiApp)
939 {
940     FOREACH(it, m_context.widgetConfig.configInfo.settingsList)
941     {
942         if (!strcmp(DPL::ToUTF8String(it->m_name).c_str(), STR_NODISPLAY)) {
943             if (!strcmp(DPL::ToUTF8String(it->m_value).c_str(), STR_TRUE)) {
944                 uiApp.setNodisplay(true);
945                 uiApp.setTaskmanage(false);
946             } else {
947                 uiApp.setNodisplay(false);
948                 uiApp.setTaskmanage(true);
949             }
950         }
951     }
952     //TODO
953     //There is no "X-TIZEN-PackageType=wgt"
954     //There is no X-TIZEN-PackageID in manifest "X-TIZEN-PackageID=" <<
955     // DPL::ToUTF8String(*widgetID).c_str()
956     //There is no Comment in pkgmgr "Comment=Widget application"
957     //that were in desktop file
958 }
959
960 void TaskManifestFile::setAppControlsInfo(UiApplication & uiApp)
961 {
962     WrtDB::ConfigParserData::AppControlInfoList appControlList =
963         m_context.widgetConfig.configInfo.appControlList;
964
965     if (appControlList.empty()) {
966         LogInfo("Widget doesn't contain app control");
967         return;
968     }
969
970      // x-tizen-svc=http://tizen.org/appcontrol/operation/pick|NULL|image;
971     FOREACH(it, appControlList) {
972         setAppControlInfo(uiApp, *it);
973     }
974 }
975
976 void TaskManifestFile::setAppControlInfo(UiApplication & uiApp,
977                                          const WrtDB::ConfigParserData::AppControlInfo & service)
978 {
979     // x-tizen-svc=http://tizen.org/appcontrol/operation/pick|NULL|image;
980     AppControl appControl;
981     if (!service.m_operation.empty()) {
982         appControl.addOperation(service.m_operation); //TODO: encapsulation?
983     }
984     if (!service.m_uriList.empty()) {
985         FOREACH(uri, service.m_uriList) {
986             appControl.addUri(*uri);
987         }
988     }
989     if (!service.m_mimeList.empty()) {
990         FOREACH(mime, service.m_mimeList) {
991             appControl.addMime(*mime);
992         }
993     }
994     uiApp.addAppControl(appControl);
995 }
996
997 void TaskManifestFile::setAppCategory(UiApplication &uiApp)
998 {
999     WrtDB::ConfigParserData::CategoryList categoryList =
1000         m_context.widgetConfig.configInfo.categoryList;
1001
1002     if (categoryList.empty()) {
1003         LogInfo("Widget doesn't contain application category");
1004         return;
1005     }
1006     FOREACH(it, categoryList) {
1007         if (!(*it).empty()) {
1008             uiApp.addAppCategory(*it);
1009         }
1010     }
1011 }
1012
1013 void TaskManifestFile::setMetadata(UiApplication &uiApp)
1014 {
1015     WrtDB::ConfigParserData::MetadataList metadataList =
1016         m_context.widgetConfig.configInfo.metadataList;
1017
1018     if (metadataList.empty()) {
1019         LogInfo("Web application doesn't contain metadata");
1020         return;
1021     }
1022     FOREACH(it, metadataList) {
1023         MetadataType metadataType(it->key, it->value);
1024         uiApp.addMetadata(metadataType);
1025     }
1026 }
1027
1028 void TaskManifestFile::stepAbortParseManifest()
1029 {
1030     LogError("[Parse Manifest] Abroting....");
1031
1032     int code = pkgmgr_parser_parse_manifest_for_uninstallation(
1033             DPL::ToUTF8String(manifest_file).c_str(), NULL);
1034
1035     if (0 != code) {
1036         LogWarning("Manifest parser error: " << code);
1037         ThrowMsg(Exceptions::ManifestInvalid, "Parser returncode: " << code);
1038     }
1039     int ret = unlink(DPL::ToUTF8String(manifest_file).c_str());
1040     if (0 != ret) {
1041         LogWarning("No manifest file found: " << manifest_file);
1042     }
1043 }
1044
1045 void TaskManifestFile::setLiveBoxInfo(Manifest& manifest)
1046 {
1047     FOREACH(it, m_context.widgetConfig.configInfo.m_livebox) {
1048         LogInfo("setLiveBoxInfo");
1049         LiveBoxInfo liveBox;
1050         DPL::Optional<WrtDB::ConfigParserData::LiveboxInfo> ConfigInfo = *it;
1051         DPL::String appid = m_context.widgetConfig.tzAppid;
1052
1053         if (ConfigInfo->m_liveboxId != L"") {
1054             size_t found = ConfigInfo->m_liveboxId.find_last_of(L".");
1055             if (found != std::string::npos) {
1056                 if (0 == ConfigInfo->m_liveboxId.compare(0, found, appid)) {
1057                     liveBox.setLiveboxId(ConfigInfo->m_liveboxId);
1058                 } else {
1059                     DPL::String liveboxId =
1060                         appid + DPL::String(L".") + ConfigInfo->m_liveboxId;
1061                     liveBox.setLiveboxId(liveboxId);
1062                 }
1063             } else {
1064                 DPL::String liveboxId =
1065                     appid + DPL::String(L".") + ConfigInfo->m_liveboxId;
1066                 liveBox.setLiveboxId(liveboxId);
1067             }
1068         }
1069
1070         if (ConfigInfo->m_primary != L"") {
1071             liveBox.setPrimary(ConfigInfo->m_primary);
1072         }
1073
1074         if (ConfigInfo->m_updatePeriod != L"") {
1075             liveBox.setUpdatePeriod(ConfigInfo->m_updatePeriod);
1076         }
1077
1078         if (ConfigInfo->m_label != L"") {
1079             liveBox.setLabel(ConfigInfo->m_label);
1080         }
1081
1082         DPL::String defaultLocale =
1083             DPL::FromUTF8String(m_context.locations->getPackageInstallationDir()) +
1084             DPL::String(L"/res/wgt/");
1085
1086         if (ConfigInfo->m_icon != L"") {
1087             DPL::String icon =
1088                 DPL::FromUTF8String(m_context.locations->getSharedDataDir()) +
1089                 DPL::String(L"/") +
1090                 ConfigInfo->m_liveboxId + DPL::String(L".icon.png");
1091             liveBox.setIcon(icon);
1092         }
1093
1094         if (ConfigInfo->m_boxInfo.m_boxSrc.empty() ||
1095             ConfigInfo->m_boxInfo.m_boxSize.empty())
1096         {
1097             LogInfo("Widget doesn't contain box");
1098             return;
1099         } else {
1100             BoxInfoType box;
1101             if (!ConfigInfo->m_boxInfo.m_boxSrc.empty()) {
1102                 if ((0 == ConfigInfo->m_boxInfo.m_boxSrc.compare(0, 4, L"http"))
1103                     || (0 ==
1104                         ConfigInfo->m_boxInfo.m_boxSrc.compare(0, 5, L"https")))
1105                 {
1106                     box.boxSrc = ConfigInfo->m_boxInfo.m_boxSrc;
1107                 } else {
1108                     box.boxSrc = defaultLocale + ConfigInfo->m_boxInfo.m_boxSrc;
1109                 }
1110             }
1111
1112             if (ConfigInfo->m_boxInfo.m_boxMouseEvent == L"true") {
1113                 std::string boxType;
1114                 if (ConfigInfo->m_type == L"") {
1115                     // in case of default livebox
1116                     boxType = web_provider_livebox_get_default_type();
1117                 } else {
1118                     boxType = DPL::ToUTF8String(ConfigInfo->m_type);
1119                 }
1120
1121                 int box_scrollable =
1122                     web_provider_plugin_get_box_scrollable(boxType.c_str());
1123
1124                 if (box_scrollable) {
1125                     box.boxMouseEvent = L"true";
1126                 } else {
1127                     box.boxMouseEvent = L"false";
1128                 }
1129             } else {
1130                 box.boxMouseEvent = L"false";
1131             }
1132
1133             if (ConfigInfo->m_boxInfo.m_boxTouchEffect == L"true") {
1134                 box.boxTouchEffect = L"true";
1135             } else {
1136                 box.boxTouchEffect= L"false";
1137             }
1138
1139             std::list<std::pair<DPL::String, DPL::String> > BoxSizeList
1140                 = ConfigInfo->m_boxInfo.m_boxSize;
1141             FOREACH(im, BoxSizeList) {
1142                 std::pair<DPL::String, DPL::String> boxSize = *im;
1143                 if (!boxSize.second.empty()) {
1144                     boxSize.second =
1145                         DPL::FromUTF8String(m_context.locations->getSharedDataDir()) +
1146                         DPL::String(L"/") +
1147                         ConfigInfo->m_liveboxId + DPL::String(L".") +
1148                         boxSize.first + DPL::String(L".preview.png");
1149                 }
1150                 box.boxSize.push_back(boxSize);
1151             }
1152
1153             if (!ConfigInfo->m_boxInfo.m_pdSrc.empty()
1154                 && !ConfigInfo->m_boxInfo.m_pdWidth.empty()
1155                 && !ConfigInfo->m_boxInfo.m_pdHeight.empty())
1156             {
1157                 if ((0 == ConfigInfo->m_boxInfo.m_pdSrc.compare(0, 4, L"http"))
1158                     || (0 == ConfigInfo->m_boxInfo.m_pdSrc.compare(0, 5, L"https")))
1159                 {
1160                     box.pdSrc = ConfigInfo->m_boxInfo.m_pdSrc;
1161                 } else {
1162                     box.pdSrc = defaultLocale + ConfigInfo->m_boxInfo.m_pdSrc;
1163                 }
1164                 box.pdWidth = ConfigInfo->m_boxInfo.m_pdWidth;
1165                 box.pdHeight = ConfigInfo->m_boxInfo.m_pdHeight;
1166             }
1167             liveBox.setBox(box);
1168         }
1169         manifest.addLivebox(liveBox);
1170     }
1171 }
1172
1173 void TaskManifestFile::setAccount(Manifest& manifest)
1174 {
1175     WrtDB::ConfigParserData::AccountProvider account =
1176         m_context.widgetConfig.configInfo.accountProvider;
1177
1178     AccountProviderType provider;
1179
1180     if (account.m_iconSet.empty()) {
1181         LogInfo("Widget doesn't contain Account");
1182         return;
1183     }
1184     if (account.m_multiAccountSupport) {
1185         provider.multiAccount = L"ture";
1186     } else {
1187         provider.multiAccount = L"false";
1188     }
1189     provider.appid = m_context.widgetConfig.tzAppid;
1190
1191     FOREACH(it, account.m_iconSet) {
1192         std::pair<DPL::String, DPL::String> icon;
1193
1194         if (it->first == ConfigParserData::IconSectionType::DefaultIcon) {
1195             icon.first = L"account";
1196         } else if (it->first == ConfigParserData::IconSectionType::SmallIcon) {
1197             icon.first = L"account-small";
1198         }
1199         icon.second = it->second;
1200
1201         provider.icon.push_back(icon);
1202     }
1203
1204     FOREACH(it, account.m_displayNameSet) {
1205         provider.name.push_back(LabelType(it->second, it->first));
1206     }
1207
1208     FOREACH(it, account.m_capabilityList) {
1209         provider.capability.push_back(*it);
1210     }
1211
1212     Account accountInfo;
1213     accountInfo.addAccountProvider(provider);
1214     manifest.addAccount(accountInfo);
1215 }
1216
1217 void TaskManifestFile::setPrivilege(Manifest& manifest)
1218 {
1219     WrtDB::ConfigParserData::PrivilegeList privileges =
1220         m_context.widgetConfig.configInfo.privilegeList;
1221
1222     PrivilegeType privilege;
1223
1224     FOREACH(it, privileges)
1225     {
1226         privilege.addPrivilegeName(it->name);
1227     }
1228
1229     manifest.addPrivileges(privilege);
1230 }
1231
1232 } //namespace WidgetInstall
1233 } //namespace Jobs