Update wrt-installer_0.0.54
[framework/web/wrt-installer.git] / src / wrt-installer / wrt_installer_api.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        wrt_installer_api.cpp
18  * @author      Chung Jihoon (jihoon.chung@samsung.com)
19  * @version     1.0
20  * @brief       This file contains definitions of wrt installer api
21  */
22 #include <stdlib.h>
23 #include <list>
24 #include <string>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <dpl/exception.h>
29 #include <dpl/log/log.h>
30 #include <dpl/assert.h>
31 #include <dpl/semaphore.h>
32 #include <dpl/sstream.h>
33 #include <libxml/parser.h>
34 #include <vconf.h>
35
36 #include <wrt_installer_api.h>
37 #include <installer_callbacks_translate.h>
38 #include <installer_controller.h>
39 #include <language_subtag_rst_tree.h>
40 #include <dpl/localization/localization_utils.h>
41 #include <dpl/wrt-dao-ro/global_config.h>
42 #include <dpl/utils/widget_version.h>
43 #include <dpl/popup/popup_manager.h>
44 #include <dpl/popup/popup_controller.h>
45 #include <wrt_type.h>
46 #include <dpl/localization/w3c_file_localization.h>
47 #include <dpl/wrt-dao-ro/WrtDatabase.h>
48 #include <vcore/VCore.h>
49 #include <installer_main_thread.h>
50
51 using namespace WrtDB;
52
53 #undef TRUE
54 #undef FALSE
55 #define TRUE 0
56 #define FALSE -1
57
58 #ifdef __cplusplus
59
60 #define EXPORT_API __attribute__((visibility("default")))
61 extern "C"
62 {
63 #endif
64     inline WidgetUpdateMode::Type translateWidgetUpdateMode(
65             wrt_widget_update_mode_t updateMode)
66     {
67         WidgetUpdateMode::Type result = WidgetUpdateMode::Zero;
68
69         if (updateMode & WRT_WIM_NOT_INSTALLED) {
70             result = result | WidgetUpdateMode::NotInstalled;
71         }
72
73         if (updateMode & WRT_WIM_INCOMING_VERSION_NOT_STD) {
74             result = result | WidgetUpdateMode::IncomingVersionNotStd;
75         }
76
77         if (updateMode & WRT_WIM_EXISTING_VERSION_NOT_STD) {
78             result = result | WidgetUpdateMode::ExistingVersionNotStd;
79         }
80
81         if (updateMode & WRT_WIM_BOTH_VERSIONS_NOT_STD) {
82             result = result | WidgetUpdateMode::BothVersionsNotStd;
83         }
84
85         if (updateMode & WRT_WIM_EXISTING_VERSION_OLDER) {
86             result = result | WidgetUpdateMode::ExistingVersionOlder;
87         }
88
89         if (updateMode & WRT_WIM_EXISTING_VERSION_EQUAL) {
90             result = result | WidgetUpdateMode::ExistingVersionEqual;
91         }
92
93         if (updateMode & WRT_WIM_EXISTING_VERSION_NEWER) {
94             result = result | WidgetUpdateMode::ExistingVersionNewer;
95         }
96
97         return result;
98     }
99
100     void localizationSetting()
101     {
102         char* lang = vconf_get_str(VCONFKEY_LANGSET);
103         if (!lang) {
104             LogError("Cannot get locale settings from vconf");
105         } else {
106             LogDebug("Language set to: " << lang);
107
108             using namespace LocalizationUtils;
109
110             LanguageTagsList list;
111             list.push_back(DPL::FromUTF8String(lang));
112             SetSystemLanguageTags(list);
113
114             LogDebug("LanguageChanged to " << lang);
115         }
116     }
117
118     const char PLUGIN_INSTALL_SEMAPHORE[] = "/.wrt_plugin_install_lock";
119     static int wrt_count_plugin;
120
121     static std::string cutOffFileName(const std::string& path)
122     {
123         size_t found = path.find_last_of("/");
124         if (found == std::string::npos) {
125             return path;
126         } else {
127             return path.substr(0, found);
128         }
129     }
130
131     static bool checkPath(const std::string& path)
132     {
133         struct stat st;
134         if (0 == stat(path.c_str(), &st) && S_ISDIR(st.st_mode)) {
135             return true;
136         }
137         LogError("Cannot access directory [ " << path << " ]");
138         return false;
139     }
140
141     static bool checkPaths()
142     {
143         bool if_ok = true;
144         if_ok &= (checkPath(cutOffFileName(
145                 GlobalConfig::GetWrtDatabaseFilePath())));
146         if (!if_ok) {
147             LogError(
148                 "Path <" << GlobalConfig::GetWrtDatabaseFilePath() <<
149                 "> does not exist.");
150         }
151
152         if_ok &= (checkPath(GlobalConfig::GetDevicePluginPath()));
153         if (!if_ok) {
154             LogError(
155                 "Path <" << GlobalConfig::GetDevicePluginPath() <<
156                 "> does not exist.");
157         }
158
159         if_ok &= (checkPath(GlobalConfig::GetFactoryInstalledWidgetPath()));
160         if (!if_ok) {
161             LogError(
162                 "Path <" << GlobalConfig::GetFactoryInstalledWidgetPath() <<
163                 "> does not exist.");
164         }
165
166         if_ok &= (checkPath(GlobalConfig::GetUserInstalledWidgetPath()));
167         if (!if_ok) {
168             LogError(
169                 "Path <" << GlobalConfig::GetUserInstalledWidgetPath() <<
170                 "> does not exist.");
171         }
172         return if_ok;
173     }
174
175     void plugin_install_status_cb(WrtErrStatus status,
176                                   void* userparam)
177     {
178         Assert(userparam);
179
180         wrt_plugin_data *plugin_data = static_cast<wrt_plugin_data*>(userparam);
181
182         if (--wrt_count_plugin < 1) {
183             LogDebug("All plugins installation completed");
184
185             LogDebug("Call SetAllinstallpluginsCallback");
186             plugin_data->plugin_installed_cb(plugin_data->user_data);
187         }
188
189         if (status == WRT_SUCCESS) {
190             LogInfo(
191                 "plugin installation is successful: " <<
192                 plugin_data->plugin_path);
193             return;
194         }
195
196         LogError("Fail to install plugin : " << plugin_data->plugin_path);
197
198         switch (status) {
199         case WRT_PLUGIN_INSTALLER_ERROR_WRONG_PATH:
200             LogError("Failed : Plugin install path is wrong");
201             break;
202         case WRT_PLUGIN_INSTALLER_ERROR_METAFILE:
203             LogError("Failed : Plugin Metafile Error");
204             break;
205         case WRT_PLUGIN_INSTALLER_ERROR_ALREADY_INSTALLED:
206             LogError("Failed : This Plugin is already installed");
207             break;
208         case WRT_PLUGIN_INSTALLER_ERROR_LIBRARY_ERROR:
209             LogError("Failed : Library Error. Missing symbol or structures");
210             break;
211         case WRT_PLUGIN_INSTALLER_ERROR_WAITING:
212             LogError("Failed : Waiting for plugin dependencies");
213             break;
214         case WRT_PLUGIN_INSTALLER_ERROR_LOCK:
215             LogError("Failed : Lock Error");
216             break;
217         case WRT_PLUGIN_INSTALLER_ERROR_UNKNOWN:
218             LogError("Failed : Unkown Error");
219             break;
220         default:
221             break;
222         }
223     }
224
225     void plugin_install_progress_cb(float percent,
226                                     const char* description,
227                                     void* userdata)
228     {
229         char *plugin_path = static_cast<char*>(userdata);
230
231         LogInfo("Install plugin : " << plugin_path <<
232                 ", Progress : " << percent <<
233                 ", Description : " << description);
234     }
235
236     EXPORT_API int wrt_installer_init(void *userdata,
237                             WrtInstallerInitCallback callback)
238     {
239         // Set DPL/LOG MID
240         DPL::Log::LogSystemSingleton::Instance().SetTag("WRT");
241
242         try
243         {
244             LogInfo("[WRT-API] INITIALIZING WRT INSTALLER...");
245             LogInfo("[WRT-API] BUILD: " << __TIMESTAMP__);
246
247             // Touch InstallerController Singleton
248             InstallerMainThreadSingleton::Instance().TouchArchitecture();
249
250             // Check paths
251             if (!checkPaths()) {
252                 if (callback) {
253                     callback(WRT_ERROR_NO_PATH, userdata);
254                 }
255                 return TRUE;
256             }
257
258             // Initialize ValidationCore - this must be done before AttachDatabases
259             ValidationCore::VCoreInit(
260                     std::string(GlobalConfig::GetFingerprintListFile()),
261                     std::string(GlobalConfig::GetFingerprintListSchema()),
262                     std::string(GlobalConfig::GetVCoreDatabaseFilePath()));
263
264             InstallerMainThreadSingleton::Instance().AttachDatabases();
265
266             //checking for correct DB version
267 //            if (!WrtDB::WrtDatabase::CheckTableExist(DB_CHECKSUM_STR)) {
268 //                LogError("WRONG VERSION OF WRT DATABASE");
269 //                Assert(false && "WRONG VERSION OF WRT DATABASE");
270 //                return FALSE;
271 //            }
272             LogWarning("Database check not implemented!");
273
274             LogInfo("Prepare libxml2 to work in multithreaded program.");
275             xmlInitParser();
276
277             // Initialize Language Subtag registry
278             LanguageSubtagRstTreeSingleton::Instance().Initialize();
279             localizationSetting();
280
281             // Installer init
282             CONTROLLER_POST_SYNC_EVENT(
283                     Logic::InstallerController,
284                     InstallerControllerEvents::
285                     InitializeEvent());
286
287             // Install deferred widget packages
288             CONTROLLER_POST_EVENT(
289                     Logic::InstallerController,
290                     InstallerControllerEvents::
291                     InstallDeferredWidgetPackagesEvent());
292
293             if (callback) {
294                 LogInfo("[WRT-API] WRT INSTALLER INITIALIZATION CALLBACK");
295                 callback(WRT_SUCCESS, userdata);
296             }
297         }
298         catch (const DPL::Exception& ex)
299         {
300             LogError("Internal Error during Init:");
301             DPL::Exception::DisplayKnownException(ex);
302             if (callback) {
303                 callback(WRT_ERROR_INTERNAL, userdata);
304             }
305             return FALSE;
306         }
307         // OK
308         return TRUE;
309     }
310
311     EXPORT_API void wrt_installer_shutdown()
312     {
313         try
314         {
315             LogInfo("[WRT-API] DEINITIALIZING WRT INSTALLER...");
316
317             // Installer termination
318             CONTROLLER_POST_SYNC_EVENT(
319                     Logic::InstallerController,
320                     InstallerControllerEvents::
321                     TerminateEvent());
322
323             InstallerMainThreadSingleton::Instance().DetachDatabases();
324
325             // This must be done after DetachDatabase
326             ValidationCore::VCoreDeinit();
327
328             // Global deinit check
329             LogInfo("Cleanup libxml2 global values.");
330             xmlCleanupParser();
331
332         }
333         catch (const DPL::Exception& ex)
334         {
335             LogError("Internal Error during Shutdown:");
336             DPL::Exception::DisplayKnownException(ex);
337         }
338     }
339
340     EXPORT_API void wrt_install_widget(const char *path,
341                                        void* userdata,
342                                        WrtInstallerStatusCallback status_cb,
343                                        WrtProgressCallback progress_cb,
344                                        wrt_widget_update_mode_t update_mode,
345                                        bool quiet)
346     {
347         UNHANDLED_EXCEPTION_HANDLER_BEGIN
348         {
349             LogInfo("[WRT-API] INSTALL WIDGET: " << path);
350             // Post installation event
351             CONTROLLER_POST_EVENT(
352                 Logic::InstallerController,
353                 InstallerControllerEvents::InstallWidgetEvent(
354                     path, WidgetInstallationStruct(
355                         InstallerCallbacksTranslate::installFinishedCallback,
356                         InstallerCallbacksTranslate::installProgressCallback,
357                         new InstallerCallbacksTranslate::StatusCallbackStruct(
358                             userdata, status_cb, progress_cb),
359                         translateWidgetUpdateMode(update_mode),
360                         quiet)));
361         }
362         UNHANDLED_EXCEPTION_HANDLER_END
363     }
364
365     EXPORT_API void wrt_uninstall_widget(int widget_handle,
366                                          void* userdata,
367                                          WrtInstallerStatusCallback status_cb,
368                                          WrtProgressCallback progress_cb)
369     {
370         UNHANDLED_EXCEPTION_HANDLER_BEGIN
371         {
372             LogInfo("[WRT-API] UNINSTALL WIDGET: " << widget_handle);
373             // Post uninstallation event
374             CONTROLLER_POST_EVENT(
375                 Logic::InstallerController,
376                 InstallerControllerEvents::UninstallWidgetEvent(
377                     widget_handle,
378                     WidgetUninstallationStruct(
379                         InstallerCallbacksTranslate::uninstallFinishedCallback,
380                         InstallerCallbacksTranslate::installProgressCallback,
381                         new InstallerCallbacksTranslate::StatusCallbackStruct(
382                             userdata, status_cb, progress_cb))));
383         }
384         UNHANDLED_EXCEPTION_HANDLER_END
385     }
386
387     EXPORT_API void wrt_install_plugin(
388         const char *pluginDir,
389         void *user_param,
390         WrtPluginInstallerStatusCallback status_cb,
391         WrtProgressCallback progress_cb)
392     {
393         UNHANDLED_EXCEPTION_HANDLER_BEGIN
394         {
395             LogInfo("[WRT-API] INSTALL PLUGIN: " << pluginDir);
396             //Private data for status callback
397             //Resource is free in pluginInstallFinishedCallback
398             InstallerCallbacksTranslate::PluginStatusCallbackStruct*
399             callbackStruct =
400                 new InstallerCallbacksTranslate::PluginStatusCallbackStruct(
401                     user_param, status_cb, progress_cb);
402
403             CONTROLLER_POST_EVENT(
404                 Logic::InstallerController,
405                 InstallerControllerEvents::InstallPluginEvent(
406                     std::string(pluginDir),
407                     PluginInstallerStruct(
408                         InstallerCallbacksTranslate::
409                         pluginInstallFinishedCallback,
410                         InstallerCallbacksTranslate::
411                         installProgressCallback, callbackStruct)));
412         }
413         UNHANDLED_EXCEPTION_HANDLER_END
414     }
415
416     EXPORT_API void wrt_install_all_plugins(
417         WrtAllPluginInstalledCallback installed_cb,
418         void *user_param)
419     {
420         UNHANDLED_EXCEPTION_HANDLER_BEGIN
421         {
422             std::string installRequest =
423                 std::string(GlobalConfig::GetPluginInstallInitializerName());
424
425             LogDebug("Install new plugins");
426
427             Try {
428                 DPL::Semaphore lock(PLUGIN_INSTALL_SEMAPHORE);
429             }
430             Catch(DPL::Semaphore::Exception::Base){
431                 LogError("Failed to create installation lock");
432                 return;
433             }
434
435             struct stat tmp;
436
437             if (-1 == stat(installRequest.c_str(), &tmp) ||
438                     !S_ISREG(tmp.st_mode))
439             {
440                 if (ENOENT == errno) {
441                     LogDebug("Plugin installation not required");
442
443                     LogDebug("Call SetAllinstallPluginCallback");
444                     installed_cb(user_param);
445
446                     DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
447                     return;
448                 }
449                 LogWarning("Opening installation request file failed");
450             }
451
452             std::string PLUGIN_PATH =
453                 std::string(GlobalConfig::GetDevicePluginPath());
454
455             DIR *dir;
456             dir = opendir(PLUGIN_PATH.c_str());
457             if (!dir) {
458                 DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
459                 return;
460             }
461
462             LogInfo("Plugin DIRECTORY IS" << PLUGIN_PATH);
463             struct dirent* libdir;
464
465             errno = 0;
466
467             std::list<std::string> pluginsPaths;
468
469             while ((libdir = readdir(dir)) != 0) {
470                 if (strcmp(libdir->d_name, ".") == 0 ||
471                     strcmp(libdir->d_name, "..") == 0)
472                 {
473                     continue;
474                 }
475
476                 std::string path = PLUGIN_PATH;
477                 path += "/";
478                 path += libdir->d_name;
479
480                 struct stat tmp;
481
482                 if (stat(path.c_str(), &tmp) == -1) {
483                     LogError("Failed to open file" << path);
484                     continue;
485                 }
486
487                 if (!S_ISDIR(tmp.st_mode)) {
488                     LogError("Not a directory" << path);
489                     continue;
490                 }
491
492                 pluginsPaths.push_back(path);
493             }
494
495             wrt_count_plugin = pluginsPaths.size();
496
497             FOREACH(it, pluginsPaths) {
498                 wrt_plugin_data *plugin_data = new wrt_plugin_data;
499
500                 plugin_data->plugin_installed_cb = installed_cb;
501                 plugin_data->plugin_path = const_cast<char*>(it->c_str());
502                 plugin_data->user_data = user_param;
503
504                 wrt_install_plugin(
505                     it->c_str(), static_cast<void*>(plugin_data),
506                     plugin_install_status_cb,
507                     plugin_install_progress_cb);
508             }
509
510             if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
511                 LogError("Failed to close dir: " << dir);
512             }
513
514             if (0 != unlink(installRequest.c_str())) {
515                 LogError("Failed to remove file initializing plugin "
516                          "installation");
517             }
518
519             Try {
520                 DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
521             }
522             Catch(DPL::Semaphore::Exception::Base){
523                 LogInfo("Failed to remove installation lock");
524             }
525         }
526         UNHANDLED_EXCEPTION_HANDLER_END
527     }
528
529     EXPORT_API int wrt_installer_init_for_tests(void *userdata,
530                             WrtInstallerInitCallback callback)
531     {
532         // Set DPL/LOG MID
533         DPL::Log::LogSystemSingleton::Instance().SetTag("WRT");
534
535         try
536         {
537             LogInfo("[WRT-API] INITIALIZING WRT INSTALLER...");
538             LogInfo("[WRT-API] BUILD: " << __TIMESTAMP__);
539
540             // Touch InstallerController Singleton
541             InstallerMainThreadSingleton::Instance().
542                 TouchArchitectureOnlyInstaller();
543
544             // Check paths
545             if (!checkPaths()) {
546                 if (callback) {
547                     callback(WRT_ERROR_NO_PATH, userdata);
548                 }
549                 return TRUE;
550             }
551
552             CONTROLLER_POST_SYNC_EVENT(
553                     Logic::InstallerController,
554                     InstallerControllerEvents::
555                     InitializeEvent());
556
557             if (callback) {
558                 LogInfo("[WRT-API] WRT INSTALLER INITIALIZATION CALLBACK");
559                 callback(WRT_SUCCESS, userdata);
560             }
561         }
562         catch (const DPL::Exception& ex)
563         {
564             LogError("Internal Error during Init:");
565             DPL::Exception::DisplayKnownException(ex);
566             if (callback) {
567                 callback(WRT_ERROR_INTERNAL, userdata);
568             }
569             return FALSE;
570         }
571
572         // OK
573         return TRUE;
574     }
575
576     EXPORT_API void wrt_installer_shutdown_for_tests()
577     {
578         try
579         {
580             LogInfo("[WRT-API] DEINITIALIZING WRT INSTALLER...");
581
582             // Installer termination
583             CONTROLLER_POST_SYNC_EVENT(
584                     Logic::InstallerController,
585                     InstallerControllerEvents::
586                     TerminateEvent());
587
588             // Global deinit check
589             LogInfo("Cleanup libxml2 global values.");
590             xmlCleanupParser();
591         }
592         catch (const DPL::Exception& ex)
593         {
594             LogError("Internal Error during Shutdown:");
595             DPL::Exception::DisplayKnownException(ex);
596         }
597     }
598
599     EXPORT_API WrtErrStatus wrt_get_widget_by_pkgname(const std::string pkgname,
600             int *widget_handle)
601     {
602         try
603         {
604             LogInfo("[WRT-API] GETTING WIDGET HANDLE BY PKG NAME : "
605                     << pkgname);
606
607             WidgetHandle handle = WidgetDAOReadOnly::getHandle(
608                     DPL::FromASCIIString(pkgname));
609             *widget_handle = static_cast<int>(handle);
610             return WRT_SUCCESS;
611         }
612         catch (WidgetDAOReadOnly::Exception::WidgetNotExist)
613         {
614             LogError("Error package name is not found");
615             return WRT_ERROR_PKGNAME_NOT_FOUND;
616         }
617         catch (const DPL::Exception& ex)
618         {
619             LogError("Internal Error during get widget id by package name");
620             DPL::Exception::DisplayKnownException(ex);
621             return WRT_ERROR_INTERNAL;
622         }
623     }
624
625     EXPORT_API WrtErrStatus wrt_get_widget_by_guid(const std::string guid,
626             int *widget_handle)
627     {
628         try
629         {
630             LogInfo("[WRT-API] GETTING WIDGET HANDLE BY WidgetID : "
631                     << guid);
632
633             WidgetGUID widget_guid = DPL::FromUTF8String(guid);
634             WidgetHandle handle = WidgetDAOReadOnly::getHandle(widget_guid);
635             *widget_handle = static_cast<int>(handle);
636             return WRT_SUCCESS;
637         }
638         catch (WidgetDAOReadOnly::Exception::WidgetNotExist)
639         {
640             LogError("Error package name is not found");
641             return WRT_ERROR_PKGNAME_NOT_FOUND;
642         }
643         catch (const DPL::Exception& ex)
644         {
645             LogError("Internal Error during get widget id by package name");
646             DPL::Exception::DisplayKnownException(ex);
647             return WRT_ERROR_INTERNAL;
648         }
649     }
650 #ifdef __cplusplus
651 }
652 #endif