21fcc724e9dd637b0a3427a9fc0b6c0daaaebd27
[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(const char * const pkg_name,
345                                          void* userdata,
346                                          WrtInstallerStatusCallback status_cb,
347                                          WrtProgressCallback progress_cb)
348     {
349         UNHANDLED_EXCEPTION_HANDLER_BEGIN
350         {
351             std::string widgetPkgName(pkg_name);
352             LogInfo("[WRT-API] UNINSTALL WIDGET: " << widgetPkgName);
353             // Post uninstallation event
354             CONTROLLER_POST_EVENT(
355                 Logic::InstallerController,
356                 InstallerControllerEvents::UninstallWidgetEvent(
357                     widgetPkgName,
358                     WidgetUninstallationStruct(
359                         InstallerCallbacksTranslate::uninstallFinishedCallback,
360                         InstallerCallbacksTranslate::installProgressCallback,
361                         new InstallerCallbacksTranslate::StatusCallbackStruct(
362                             userdata, status_cb, progress_cb))));
363         }
364         UNHANDLED_EXCEPTION_HANDLER_END
365     }
366
367     EXPORT_API void wrt_install_plugin(
368         const char *pluginDir,
369         void *user_param,
370         WrtPluginInstallerStatusCallback status_cb,
371         WrtProgressCallback progress_cb)
372     {
373         UNHANDLED_EXCEPTION_HANDLER_BEGIN
374         {
375             LogInfo("[WRT-API] INSTALL PLUGIN: " << pluginDir);
376             //Private data for status callback
377             //Resource is free in pluginInstallFinishedCallback
378             InstallerCallbacksTranslate::PluginStatusCallbackStruct*
379             callbackStruct =
380                 new InstallerCallbacksTranslate::PluginStatusCallbackStruct(
381                     user_param, status_cb, progress_cb);
382
383             CONTROLLER_POST_EVENT(
384                 Logic::InstallerController,
385                 InstallerControllerEvents::InstallPluginEvent(
386                     std::string(pluginDir),
387                     PluginInstallerStruct(
388                         InstallerCallbacksTranslate::
389                         pluginInstallFinishedCallback,
390                         InstallerCallbacksTranslate::
391                         installProgressCallback, callbackStruct)));
392         }
393         UNHANDLED_EXCEPTION_HANDLER_END
394     }
395
396     EXPORT_API void wrt_install_all_plugins(
397         WrtAllPluginInstalledCallback installed_cb,
398         void *user_param)
399     {
400         UNHANDLED_EXCEPTION_HANDLER_BEGIN
401         {
402             std::string installRequest =
403                 std::string(GlobalConfig::GetPluginInstallInitializerName());
404
405             LogDebug("Install new plugins");
406
407             Try {
408                 DPL::Semaphore lock(PLUGIN_INSTALL_SEMAPHORE);
409             }
410             Catch(DPL::Semaphore::Exception::Base){
411                 LogError("Failed to create installation lock");
412                 return;
413             }
414
415             struct stat tmp;
416
417             if (-1 == stat(installRequest.c_str(), &tmp) ||
418                     !S_ISREG(tmp.st_mode))
419             {
420                 if (ENOENT == errno) {
421                     LogDebug("Plugin installation not required");
422
423                     LogDebug("Call SetAllinstallPluginCallback");
424                     installed_cb(user_param);
425
426                     DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
427                     return;
428                 }
429                 LogWarning("Opening installation request file failed");
430             }
431
432             std::string PLUGIN_PATH =
433                 std::string(GlobalConfig::GetDevicePluginPath());
434
435             DIR *dir;
436             dir = opendir(PLUGIN_PATH.c_str());
437             if (!dir) {
438                 DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
439                 return;
440             }
441
442             LogInfo("Plugin DIRECTORY IS" << PLUGIN_PATH);
443             struct dirent* libdir;
444
445             errno = 0;
446
447             std::list<std::string> pluginsPaths;
448
449             while ((libdir = readdir(dir)) != 0) {
450                 if (strcmp(libdir->d_name, ".") == 0 ||
451                     strcmp(libdir->d_name, "..") == 0)
452                 {
453                     continue;
454                 }
455
456                 std::string path = PLUGIN_PATH;
457                 path += "/";
458                 path += libdir->d_name;
459
460                 struct stat tmp;
461
462                 if (stat(path.c_str(), &tmp) == -1) {
463                     LogError("Failed to open file" << path);
464                     continue;
465                 }
466
467                 if (!S_ISDIR(tmp.st_mode)) {
468                     LogError("Not a directory" << path);
469                     continue;
470                 }
471
472                 pluginsPaths.push_back(path);
473             }
474
475             wrt_count_plugin = pluginsPaths.size();
476
477             FOREACH(it, pluginsPaths) {
478                 wrt_plugin_data *plugin_data = new wrt_plugin_data;
479
480                 plugin_data->plugin_installed_cb = installed_cb;
481                 plugin_data->plugin_path = const_cast<char*>(it->c_str());
482                 plugin_data->user_data = user_param;
483
484                 wrt_install_plugin(
485                     it->c_str(), static_cast<void*>(plugin_data),
486                     plugin_install_status_cb,
487                     plugin_install_progress_cb);
488             }
489
490             if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
491                 LogError("Failed to close dir: " << PLUGIN_PATH << " with error: "
492                         << DPL::GetErrnoString());
493             }
494
495             if (0 != unlink(installRequest.c_str())) {
496                 LogError("Failed to remove file initializing plugin "
497                          "installation");
498             }
499
500             Try {
501                 DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
502             }
503             Catch(DPL::Semaphore::Exception::Base){
504                 LogInfo("Failed to remove installation lock");
505             }
506         }
507         UNHANDLED_EXCEPTION_HANDLER_END
508     }
509
510     EXPORT_API int wrt_installer_init_for_tests(void *userdata,
511                             WrtInstallerInitCallback callback)
512     {
513         // Set DPL/LOG MID
514         DPL::Log::LogSystemSingleton::Instance().SetTag("WRT");
515
516         try
517         {
518             LogInfo("[WRT-API] INITIALIZING WRT INSTALLER...");
519             LogInfo("[WRT-API] BUILD: " << __TIMESTAMP__);
520
521             // Touch InstallerController Singleton
522             InstallerMainThreadSingleton::Instance().
523                 TouchArchitectureOnlyInstaller();
524
525             // Check paths
526             if (!checkPaths()) {
527                 if (callback) {
528                     callback(WRT_ERROR_NO_PATH, userdata);
529                 }
530                 return TRUE;
531             }
532
533             CONTROLLER_POST_SYNC_EVENT(
534                     Logic::InstallerController,
535                     InstallerControllerEvents::
536                     InitializeEvent());
537
538             if (callback) {
539                 LogInfo("[WRT-API] WRT INSTALLER INITIALIZATION CALLBACK");
540                 callback(WRT_SUCCESS, userdata);
541             }
542         }
543         catch (const DPL::Exception& ex)
544         {
545             LogError("Internal Error during Init:");
546             DPL::Exception::DisplayKnownException(ex);
547             if (callback) {
548                 callback(WRT_ERROR_INTERNAL, userdata);
549             }
550             return FALSE;
551         }
552
553         // OK
554         return TRUE;
555     }
556
557     EXPORT_API void wrt_installer_shutdown_for_tests()
558     {
559         try
560         {
561             LogInfo("[WRT-API] DEINITIALIZING WRT INSTALLER...");
562
563             // Installer termination
564             CONTROLLER_POST_SYNC_EVENT(
565                     Logic::InstallerController,
566                     InstallerControllerEvents::
567                     TerminateEvent());
568
569             // Global deinit check
570             LogInfo("Cleanup libxml2 global values.");
571             xmlCleanupParser();
572         }
573         catch (const DPL::Exception& ex)
574         {
575             LogError("Internal Error during Shutdown:");
576             DPL::Exception::DisplayKnownException(ex);
577         }
578     }
579
580     EXPORT_API WrtErrStatus wrt_get_widget_by_guid(std::string & pkgname,
581                                                    const std::string guid)
582     {
583         try
584         {
585             LogInfo("[WRT-API] GETTING WIDGET PACKAGE NAME BY WidgetID : "
586                     << guid);
587
588             WidgetGUID widget_guid = DPL::FromUTF8String(guid);
589             WrtDB::WidgetDAOReadOnly dao(widget_guid);
590             pkgname = DPL::ToUTF8String(*dao.getPkgname());
591             return WRT_SUCCESS;
592         }
593         catch (WidgetDAOReadOnly::Exception::WidgetNotExist)
594         {
595             LogError("Error package name is not found");
596             return WRT_ERROR_PKGNAME_NOT_FOUND;
597         }
598         catch (const DPL::Exception& ex)
599         {
600             LogError("Internal Error during get widget id by package name");
601             DPL::Exception::DisplayKnownException(ex);
602             return WRT_ERROR_INTERNAL;
603         }
604     }
605 #ifdef __cplusplus
606 }
607 #endif