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