tizen beta release
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_desktop_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_desktop_file.cpp
18  * @author  Pawel Sikorski (p.sikorski@samgsung.com)
19  * @version
20  * @brief
21  */
22
23 //SYSTEM INCLUDES
24 #include <string>
25 #include <dpl/assert.h>
26
27 //WRT INCLUDES
28 #include <widget_install/task_desktop_file.h>
29 #include <widget_install/job_widget_install.h>
30 #include <widget_install/widget_install_errors.h>
31 #include <widget_install/widget_install_context.h>
32 #include <dpl/wrt-dao-ro/global_config.h>
33 #include <dpl/log/log.h>
34 #include <dpl/file_input.h>
35 #include <dpl/file_output.h>
36 #include <dpl/copy.h>
37 #include <dpl/exception.h>
38 #include <dpl/foreach.h>
39 #include <dpl/sstream.h>
40 #include <dpl/string.h>
41 #include <dpl/optional.h>
42 #include <map>
43
44 using namespace WrtDB;
45
46 namespace {
47 typedef std::map<DPL::String, DPL::String> LanguageTagMap;
48
49 LanguageTagMap getLanguageTagMap()
50 {
51     LanguageTagMap map;
52
53 #define ADD(tag, l_tag) map.insert(std::make_pair(L ## # tag, L ## # l_tag));
54 #include "languages.def"
55 #undef ADD
56
57     return map;
58 }
59
60 DPL::OptionalString getLangTag(const DPL::String& tag)
61 {
62     static LanguageTagMap TagsMap =
63         getLanguageTagMap();
64
65     DPL::String langTag = tag;
66
67     LogDebug("Trying to map language tag: " << langTag);
68     size_t pos = langTag.find_first_of(L'_');
69     if (pos != DPL::String::npos) {
70         langTag.erase(pos);
71     }
72     DPL::OptionalString ret;
73
74     LanguageTagMap::iterator it = TagsMap.find(langTag);
75     if (it != TagsMap.end()) {
76         ret = it->second;
77     }
78     LogDebug("Mapping IANA Language tag to language tag: " <<
79              langTag << " -> " << ret);
80
81     return ret;
82 }
83 }
84
85 namespace Jobs {
86 namespace WidgetInstall {
87 TaskDesktopFile::TaskDesktopFile(InstallerContext &inCont) :
88     DPL::TaskDecl<TaskDesktopFile>(this),
89     m_context(inCont)
90 {
91     AddStep(&TaskDesktopFile::stepCopyIconFiles);
92     AddStep(&TaskDesktopFile::stepCreateDesktopFile);
93     AddStep(&TaskDesktopFile::stepCreateExecFile);
94     AddStep(&TaskDesktopFile::stepFinalize);
95 }
96
97 TaskDesktopFile::~TaskDesktopFile()
98 {
99 }
100
101 void TaskDesktopFile::stepCreateDesktopFile()
102 {
103     DPL::OptionalString pkgname = m_context.widgetConfig.pkgname;
104     desktop_name << pkgname << ".desktop";
105     desktop_file << "/tmp/" << desktop_name.str();
106     LogInfo("desktop file : " << desktop_file.str());
107     std::ofstream file(desktop_file.str().c_str());
108
109     saveWidgetType(file);
110     saveWidgetExecPath(file);
111     saveWidgetName(file);
112     saveWidgetIcons(file);
113     saveWidgetVersion(file);
114     saveWidgetOtherInfo(file);
115     saveAppServiceInfo(file);
116
117     file.close();
118
119     moveDesktopFile();
120
121     m_context.job->UpdateProgress(
122         InstallerContext::INSTALL_CREATE_DESKTOP,
123         "Widget Desktop Creation Finished");
124 }
125
126 void TaskDesktopFile::stepCreateExecFile()
127 {
128     //ln -s /usr/bin/wrt-client {widget-handle}
129
130     std::ostringstream real_path;
131     DPL::OptionalString pkgname = m_context.widgetConfig.pkgname;
132     if (pkgname.IsNull()) {
133         ThrowMsg(Exceptions::InternalError, "No Package name exists.");
134     }
135
136     real_path << GlobalConfig::GetUserInstalledWidgetPath() << "/";
137     real_path << pkgname << "/";
138     real_path << GlobalConfig::GetUserWidgetExecPath() << "/" <<
139     m_context.widgetHandle;
140     std::string wrt_client = GlobalConfig::GetWrtClientExec();
141
142     LogInfo("link -s " << wrt_client << " " << real_path.str());
143     symlink(wrt_client.c_str(), real_path.str().c_str());
144
145     m_context.job->UpdateProgress(
146         InstallerContext::INSTALL_CREATE_EXECFILE,
147         "Widget execfile creation Finished");
148 }
149
150 void TaskDesktopFile::stepCopyIconFiles()
151 {
152     LogDebug("CopyIconFiles");
153
154     DPL::OptionalString pkgname = m_context.widgetConfig.pkgname;
155     if (pkgname.IsNull()) {
156         ThrowMsg(Exceptions::InternalError, "No Package name exists.");
157     }
158
159     Assert(!!m_context.widgetHandle);
160     WidgetDAO dao(*m_context.widgetHandle);
161     WidgetDAO::WidgetLocalizedIconList locList = dao.getLocalizedIconList();
162     WidgetDAO::WidgetIconList list = dao.getIconList();
163     FOREACH(it, locList)
164     {
165         DPL::String i = it->widgetLocale;
166         DPL::OptionalString src;
167         FOREACH(icon, list)
168         {
169             if (icon->iconId == it->iconId) {
170                 src = icon->iconSrc;
171             }
172         }
173         LogDebug("Icon for locale: " << i << "is : " << src);
174
175         std::ostringstream sourceFile;
176         std::ostringstream targetFile;
177
178         if (!!src) {
179             sourceFile << GlobalConfig::GetUserInstalledWidgetPath() << "/";
180             sourceFile << pkgname << "/";
181             sourceFile << GlobalConfig::GetWidgetSrcPath() << "/";
182
183             targetFile << GlobalConfig::GetUserInstalledWidgetPath() << "/";
184             targetFile << pkgname << "/";
185             targetFile << GlobalConfig::GetUserWidgetDesktopIconPath() << "/";
186
187             if (!i.empty()) {
188                 sourceFile << "locales/" << i << "/";
189             }
190             sourceFile << *src;
191             targetFile << getIconTargetFilename(i);
192
193         } else {
194             //Use WRT default (not from the widget) only if widget default (not
195             // localized) doesn't exist.
196             if (i.empty()) {
197                 LogError("Using Default Icon for widget");
198                 sourceFile << GlobalConfig::GetUserWidgetDefaultIconFile();
199             } else {
200                 continue;
201             }
202         }
203
204         LogDebug("Copying icon: " << sourceFile.str() <<
205                  " -> " << targetFile.str());
206
207         Try
208         {
209             DPL::FileInput input(sourceFile.str());
210             DPL::FileOutput output(targetFile.str());
211             DPL::Copy(&input, &output);
212         }
213
214         Catch(DPL::FileInput::Exception::Base)
215         {
216             // Error while opening or closing source file
217             //ReThrowMsg(InstallerException::CopyIconFailed, sourceFile.str());
218             LogError(
219                 "Copying widget's icon failed. Widget's icon will not be"\
220                 "available from Main Screen");
221         }
222
223         Catch(DPL::FileOutput::Exception::Base)
224         {
225             // Error while opening or closing target file
226             //ReThrowMsg(InstallerException::CopyIconFailed, targetFile.str());
227             LogError(
228                 "Copying widget's icon failed. Widget's icon will not be"\
229                 "available from Main Screen");
230         }
231
232         Catch(DPL::CopyFailed)
233         {
234             // Error while copying
235             //ReThrowMsg(InstallerException::CopyIconFailed, targetFile.str());
236             LogError(
237                 "Copying widget's icon failed. Widget's icon will not be"\
238                 "available from Main Screen");
239         }
240     }
241
242     m_context.job->UpdateProgress(
243         InstallerContext::INSTALL_COPY_ICONFILE,
244         "Widget iconfile copy Finished");
245 }
246
247 void TaskDesktopFile::moveDesktopFile()
248 {
249     std::ostringstream destFile;
250     destFile << GlobalConfig::GetUserWidgetDesktopPath() << "/";
251     destFile << desktop_name.str();
252     LogInfo("cp " << desktop_file.str() << " " << destFile.str());
253     Try
254     {
255         DPL::FileInput input(desktop_file.str());
256         DPL::FileOutput output(destFile.str());
257         DPL::Copy(&input, &output);
258     }
259
260     Catch(DPL::FileInput::Exception::Base)
261     {
262         // Error while opening or closing source file
263         //        ReThrowMsg(InstallerException::CopyIconFailed,
264         //                   desktop_file.str());
265         LogError(
266             "Creating Desktop File Failed. Widget's icon will not be available"\
267             "from Main Screen");
268     }
269
270     Catch(DPL::FileOutput::Exception::Base)
271     {
272         // Error while opening or closing target file
273         //        ReThrowMsg(InstallerException::CopyIconFailed,
274         //                   destFile.str());
275         LogError(
276             "Creating Desktop File Failed. Widget's icon will not be available"\
277             "from Main Screen");
278     }
279
280     Catch(DPL::CopyFailed)
281     {
282         // Error while copying
283         //        ReThrowMsg(InstallerException::CopyIconFailed,
284         //                   destFile.str());
285         LogError(
286             "Creating Desktop File Failed. Widget's icon will not be available"\
287             "from Main Screen");
288     }
289
290     //removing temp file
291     unlink(desktop_file.str().c_str());
292 }
293
294 void TaskDesktopFile::saveWidgetType(std::ofstream &file)
295 {
296     file << "Type=" << "Application" << std::endl;
297 }
298
299 void TaskDesktopFile::saveWidgetExecPath(std::ofstream &file)
300 {
301     DPL::OptionalString pkgname = m_context.widgetConfig.pkgname;
302     if (pkgname.IsNull()) {
303         ThrowMsg(Exceptions::InternalError, "No Package name exists.");
304     }
305
306     file << "Exec=";
307     file << GlobalConfig::GetUserInstalledWidgetPath() << "/";
308     file << pkgname << "/";
309     file << GlobalConfig::GetUserWidgetExecPath() << "/";
310     file << m_context.widgetHandle << std::endl;
311 }
312
313 void TaskDesktopFile::saveWidgetVersion(std::ofstream &file)
314 {
315     DPL::OptionalString widget_version = m_context.widgetConfig.version;
316     file << "Version=" << widget_version << std::endl;
317 }
318
319 void TaskDesktopFile::saveWidgetName(std::ofstream &file)
320 {
321     Assert(!!m_context.widgetHandle);
322     WidgetDAO dao(*m_context.widgetHandle);
323     LanguageTagsList languageTags(dao.getLanguageTags());
324     FOREACH(i, languageTags)
325     {
326         DPL::OptionalString tag = getLangTag(*i);// translate en -> en_US etc
327         if (tag.IsNull()) { tag = *i; }
328
329         saveLocalizedKey(file, L"Name", *tag);
330
331         DPL::OptionalString name = dao.getLocalizedInfo(*i).name;
332         if (!!name) {
333             file << *name;
334         } else {
335             file << "Widget " << *m_context.widgetHandle;
336         }
337         file << std::endl;
338     }
339 }
340
341 void TaskDesktopFile::saveWidgetIcons(std::ofstream &file)
342 {
343     //TODO this file will need to be updated when user locale preferences
344     //changes.
345     Assert(!!m_context.widgetHandle);
346     WidgetDAO dao(*m_context.widgetHandle);
347
348     WidgetDAO::WidgetLocalizedIconList locList = dao.getLocalizedIconList();
349     WidgetDAO::WidgetIconList list = dao.getIconList();
350
351     LanguageTagsList languageTags(dao.getLanguageTags());
352     FOREACH(it, locList)
353     {
354         DPL::String i = it->widgetLocale;
355         DPL::OptionalString tag = getLangTag(i); // translate en -> en_US etc
356         if (tag.IsNull()) { tag = i; }
357
358         saveLocalizedKey(file, L"Icon", *tag);
359
360         DPL::OptionalString src;
361         FOREACH(icon, list)
362         {
363             if (icon->iconId == it->iconId) {
364                 src = icon->iconSrc;
365             }
366         }
367         if (!!src) {
368             //If menuscreen need use absolute path of widget's icon, comment out
369             //the following lines.
370             //file << GlobalConfig::GetUserInstalledWidgetPath() << "/";
371             //file << WRT_WIDGET_PKGNAME_PREFIX << m_context.widgetHandle
372             //     << "/";
373             //file << GlobalConfig::GetUserWidgetDesktopIconPath() << "/";
374             file << getIconTargetFilename(i) << std::endl;
375         }
376     }
377 }
378
379 DPL::String TaskDesktopFile::getIconTargetFilename(
380         const DPL::String& languageTag) const
381 {
382     DPL::OStringStream filename;
383     DPL::Optional<DPL::String> pkgname = m_context.widgetConfig.pkgname;
384     if (pkgname.IsNull()) {
385         ThrowMsg(Exceptions::InternalError, "No Package name exists.");
386     }
387
388     filename << DPL::ToUTF8String(*pkgname).c_str();
389
390     if (!languageTag.empty()) {
391         DPL::OptionalString tag = getLangTag(languageTag); // translate en -> en_US etc
392         if (tag.IsNull()) { tag = languageTag; }
393         DPL::String locale =
394             LocalizationUtils::BCP47LanguageTagToLocale(*tag);
395
396        if(locale.empty()) {
397             filename << L"." << languageTag;
398         } else {
399             filename << L"." << locale;
400         }
401     }
402
403     filename << L".png";
404     return filename.str();
405 }
406
407 void TaskDesktopFile::saveWidgetOtherInfo(std::ofstream &file)
408 {
409     DPL::Optional<DPL::String> widgetID = m_context.widgetConfig.guid;
410
411     //    /* network */
412     //    strncat(desktop, format_network, strlen(format_network));
413     //    //TODO -- get the network value from the widget
414     //    strncat(desktop, "True", 4);
415     //    strncat(desktop, line, strlen(line));
416
417     /* Comment */
418     file << "Comment=Widget application" << std::endl;
419
420     /* bg_schedule */
421     //file << "BG_SCHEDULE=True" << std::endl;
422
423     /* visible */
424     file << "Visible=True" << std::endl;
425
426     file << "X-SLP-BaseLayoutWidth=720" << std::endl;
427     file << "X-SLP-BaseLayoutHeight=1280" << std::endl;
428     file << "X-SLP-IsHorizontalScale=True" << std::endl;
429     file << "X-SLP-PackageType=wgt" << std::endl;
430     if (!widgetID.IsNull()) {
431         file << "X-SLP-PackageID=" << DPL::ToUTF8String(*widgetID).c_str() << std::endl;
432     }
433 }
434
435 void TaskDesktopFile::saveAppServiceInfo(std::ofstream &file)
436 {
437     Assert(!!m_context.widgetHandle);
438     WidgetDAOReadOnly dao(*m_context.widgetHandle);
439     WidgetApplicationServiceList appServiceList;
440     dao.getAppServiceList(appServiceList);
441
442     if (appServiceList.empty()) {
443         LogInfo("Widget doesn't contain application service");
444         return;
445     }
446
447     // X-SLP-SVC=operation:scheme:mime;
448     file << "X-SLP-SVC=";
449     FOREACH(it, appServiceList) {
450         file << DPL::ToUTF8String(it->operation).c_str() << ":";
451         if (it->scheme.empty()) {
452             file << "NULL" << ":";
453         } else {
454             file << DPL::ToUTF8String(it->scheme).c_str() << ":";
455         }
456         if (it->mime.empty()) {
457             file << "NULL" << ";";
458         } else {
459             file << DPL::ToUTF8String(it->mime).c_str() << ";";
460         }
461     }
462 }
463
464 void TaskDesktopFile::stepFinalize()
465 {
466     LogInfo("Finished DesktopFile step");
467 }
468
469 void TaskDesktopFile::saveLocalizedKey(std::ofstream &file,
470         const DPL::String& key,
471         const DPL::String& languageTag)
472 {
473     DPL::String locale =
474         LocalizationUtils::BCP47LanguageTagToLocale(languageTag);
475
476     file << key;
477     if (!locale.empty()) {
478         file << "[" << locale << "]";
479     }
480     file << "=";
481 }
482 } //namespace WidgetInstall
483 } //namespace Jobs