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