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