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