tizen beta release
[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/sstream.h>
32 #include <libxml/parser.h>
33
34 #include <wrt_installer_api.h>
35 #include <installer_callbacks_translate.h>
36 #include <installer_controller.h>
37 #include <security_controller.h>
38 #include <language_subtag_rst_tree.h>
39 #include <dpl/localization/localization_utils.h>
40 #include <dpl/wrt-dao-ro/global_config.h>
41 #include <dpl/utils/widget_version.h>
42 #include <dpl/popup/popup_manager.h>
43 #include <dpl/popup/popup_controller.h>
44 #include <attribute_facade.h>
45 #include <wrt_type.h>
46 #include <dpl/localization/w3c_file_localization.h>
47 #include <dpl/wrt-dao-ro/WrtDatabase.h>
48 #include <vcore/VCore.h>
49 #include <installer_main_thread.h>
50
51 using namespace WrtDB;
52
53 #undef TRUE
54 #undef FALSE
55 #define TRUE 0
56 #define FALSE -1
57
58 #ifdef __cplusplus
59
60 #define EXPORT_API __attribute__((visibility("default")))
61 extern "C"
62 {
63 #endif
64     inline WidgetUpdateMode::Type translateWidgetUpdateMode(
65             wrt_widget_update_mode_t updateMode)
66     {
67         WidgetUpdateMode::Type result = WidgetUpdateMode::Zero;
68
69         if (updateMode & WRT_WIM_NOT_INSTALLED) {
70             result = result | WidgetUpdateMode::NotInstalled;
71         }
72
73         if (updateMode & WRT_WIM_INCOMING_VERSION_NOT_STD) {
74             result = result | WidgetUpdateMode::IncomingVersionNotStd;
75         }
76
77         if (updateMode & WRT_WIM_EXISTING_VERSION_NOT_STD) {
78             result = result | WidgetUpdateMode::ExistingVersionNotStd;
79         }
80
81         if (updateMode & WRT_WIM_BOTH_VERSIONS_NOT_STD) {
82             result = result | WidgetUpdateMode::BothVersionsNotStd;
83         }
84
85         if (updateMode & WRT_WIM_EXISTING_VERSION_OLDER) {
86             result = result | WidgetUpdateMode::ExistingVersionOlder;
87         }
88
89         if (updateMode & WRT_WIM_EXISTING_VERSION_EQUAL) {
90             result = result | WidgetUpdateMode::ExistingVersionEqual;
91         }
92
93         if (updateMode & WRT_WIM_EXISTING_VERSION_NEWER) {
94             result = result | WidgetUpdateMode::ExistingVersionNewer;
95         }
96
97         return result;
98     }
99
100     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::GetFactoryInstalledWidgetPath()));
142         if (!if_ok) {
143             LogError(
144                 "Path <" << GlobalConfig::GetFactoryInstalledWidgetPath() <<
145                 "> does not exist.");
146         }
147
148         if_ok &= (checkPath(GlobalConfig::GetUserInstalledWidgetPath()));
149         if (!if_ok) {
150             LogError(
151                 "Path <" << GlobalConfig::GetUserInstalledWidgetPath() <<
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             InstallerMainThreadSingleton::Instance().AttachDatabases();
241
242             //checking for correct DB version
243 //            if (!WrtDB::WrtDatabase::CheckTableExist(DB_CHECKSUM_STR)) {
244 //                LogError("WRONG VERSION OF WRT DATABASE");
245 //                Assert(false && "WRONG VERSION OF WRT DATABASE");
246 //                return FALSE;
247 //            }
248             LogWarning("Database check not implemented!");
249
250             LogInfo("Prepare libxml2 to work in multithreaded program.");
251             xmlInitParser();
252
253             using namespace DPL::Popup;
254             // Initialize popup manager
255             PopupManagerSingleton::Instance().Initialize(
256                     PopupRendererPtr(new PopupRenderer));
257
258             // Initialize Language Subtag registry
259             LanguageSubtagRstTreeSingleton::Instance().Initialize();
260             LocalizationUtils::Initialize();
261
262             // Initialize ValidationCore
263             ValidationCore::VCoreInit(
264                     std::string(GlobalConfig::GetFingerprintListFile()),
265                     std::string(GlobalConfig::GetFingerprintListSchema()),
266                     std::string(GlobalConfig::GetVCoreDatabaseFilePath()));
267
268             // Security Logic initialization
269             CONTROLLER_POST_SYNC_EVENT(
270                     SecurityController,
271                     SecurityControllerEvents::InitializeSyncEvent());
272
273             // Installer init
274             CONTROLLER_POST_SYNC_EVENT(
275                     InstallerController,
276                     InstallerControllerEvents::
277                     InitializeEvent());
278
279             // Install deferred widget packages
280             CONTROLLER_POST_EVENT(
281                     InstallerController,
282                     InstallerControllerEvents::
283                     InstallDeferredWidgetPackagesEvent());
284
285             if (callback) {
286                 LogInfo("[WRT-API] WRT INSTALLER INITIALIZATION CALLBACK");
287                 callback(WRT_SUCCESS, userdata);
288             }
289         }
290         catch (const DPL::Exception& ex)
291         {
292             LogError("Internal Error during Init:");
293             DPL::Exception::DisplayKnownException(ex);
294             if (callback) {
295                 callback(WRT_ERROR_INTERNAL, userdata);
296             }
297             return FALSE;
298         }
299         // OK
300         return TRUE;
301     }
302
303     EXPORT_API void wrt_installer_shutdown()
304     {
305         try
306         {
307             LogInfo("[WRT-API] DEINITIALIZING WRT INSTALLER...");
308
309             // Deinitialize Security Logic
310             CONTROLLER_POST_SYNC_EVENT(
311                     SecurityController,
312                     SecurityControllerEvents::
313                     TerminateSyncEvent());
314
315             // Installer termination
316             CONTROLLER_POST_SYNC_EVENT(
317                     InstallerController,
318                     InstallerControllerEvents::
319                     TerminateEvent());
320
321             InstallerMainThreadSingleton::Instance().DetachDatabases();
322
323             // Global deinit check
324             LogInfo("Cleanup libxml2 global values.");
325             xmlCleanupParser();
326
327             // Deinitialize popup manager
328             DPL::Popup::PopupManagerSingleton::Instance().Deinitialize();
329         }
330         catch (const DPL::Exception& ex)
331         {
332             LogError("Internal Error during Shutdown:");
333             DPL::Exception::DisplayKnownException(ex);
334         }
335     }
336
337     EXPORT_API void wrt_install_widget(const char *path,
338                                        void* userdata,
339                                        WrtInstallerStatusCallback status_cb,
340                                        WrtProgressCallback progress_cb,
341                                        wrt_widget_update_mode_t update_mode)
342     {
343         UNHANDLED_EXCEPTION_HANDLER_BEGIN
344         {
345             LogInfo("[WRT-API] INSTALL WIDGET: " << path);
346             // Post installation event
347             CONTROLLER_POST_EVENT(
348                 InstallerController,
349                 InstallerControllerEvents::InstallWidgetEvent(
350                     path, WidgetInstallationStruct(
351                         InstallerCallbacksTranslate::installFinishedCallback,
352                         InstallerCallbacksTranslate::installProgressCallback,
353                         new InstallerCallbacksTranslate::StatusCallbackStruct(
354                             userdata, status_cb, progress_cb),
355                         translateWidgetUpdateMode(update_mode))));
356         }
357         UNHANDLED_EXCEPTION_HANDLER_END
358     }
359
360     EXPORT_API void wrt_uninstall_widget(int widget_handle,
361                                          void* userdata,
362                                          WrtInstallerStatusCallback status_cb,
363                                          WrtProgressCallback progress_cb)
364     {
365         UNHANDLED_EXCEPTION_HANDLER_BEGIN
366         {
367             LogInfo("[WRT-API] UNINSTALL WIDGET: " << widget_handle);
368             // Post uninstallation event
369             CONTROLLER_POST_EVENT(
370                 InstallerController,
371                 InstallerControllerEvents::UninstallWidgetEvent(
372                     widget_handle,
373                     WidgetUninstallationStruct(
374                         InstallerCallbacksTranslate::uninstallFinishedCallback,
375                         InstallerCallbacksTranslate::installProgressCallback,
376                         new InstallerCallbacksTranslate::StatusCallbackStruct(
377                             userdata, status_cb, progress_cb))));
378         }
379         UNHANDLED_EXCEPTION_HANDLER_END
380     }
381
382     EXPORT_API void wrt_install_plugin(
383         const char *pluginDir,
384         void *user_param,
385         WrtPluginInstallerStatusCallback status_cb,
386         WrtProgressCallback progress_cb)
387     {
388         UNHANDLED_EXCEPTION_HANDLER_BEGIN
389         {
390             LogInfo("[WRT-API] INSTALL PLUGIN: " << pluginDir);
391             //Private data for status callback
392             //Resource is free in pluginInstallFinishedCallback
393             InstallerCallbacksTranslate::PluginStatusCallbackStruct*
394             callbackStruct =
395                 new InstallerCallbacksTranslate::PluginStatusCallbackStruct(
396                     user_param, status_cb, progress_cb);
397             // Added geolocation feature in FeaturesList DB for installing
398             // widget using gelocation feature.
399             // If other strange features are added, it will be changed
400             // for using all of strange features.
401             if (strcmp(pluginDir,
402                        GlobalConfig::GetW3CGeolocationFeatureName()) == 0)
403             {
404                 CONTROLLER_POST_EVENT(
405                     InstallerController,
406                     InstallerControllerEvents::InstallPluginGeolocationEvent(
407                         PluginInstallerStruct(
408                             InstallerCallbacksTranslate::
409                             pluginInstallFinishedCallback,
410                             InstallerCallbacksTranslate::
411                             installProgressCallback, callbackStruct)));
412             } else {
413                 CONTROLLER_POST_EVENT(
414                     InstallerController,
415                     InstallerControllerEvents::InstallPluginEvent(
416                         std::string(pluginDir),
417                         PluginInstallerStruct(
418                             InstallerCallbacksTranslate::
419                             pluginInstallFinishedCallback,
420                             InstallerCallbacksTranslate::
421                             installProgressCallback, callbackStruct)));
422             }
423         }
424         UNHANDLED_EXCEPTION_HANDLER_END
425     }
426
427     EXPORT_API void wrt_install_all_plugins(
428         WrtAllPluginInstalledCallback installed_cb,
429         void *user_param)
430     {
431         UNHANDLED_EXCEPTION_HANDLER_BEGIN
432         {
433             std::string installRequest =
434                 std::string(GlobalConfig::GetPluginInstallInitializerName());
435
436             LogDebug("Install new plugins");
437
438             Try {
439                 DPL::Semaphore lock(PLUGIN_INSTALL_SEMAPHORE);
440             }
441             Catch(DPL::Semaphore::Exception::Base){
442                 LogError("Failed to create installation lock");
443                 return;
444             }
445
446             struct stat tmp;
447
448             if (-1 == stat(installRequest.c_str(), &tmp) ||
449                     !S_ISREG(tmp.st_mode))
450             {
451                 if (ENOENT == errno) {
452                     LogDebug("Plugin installation not required");
453
454                     LogDebug("Call SetAllinstallPluginCallback");
455                     installed_cb(user_param);
456
457                     DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
458                     return;
459                 }
460                 LogWarning("Opening installation request file failed");
461             }
462
463             std::string PLUGIN_PATH =
464                 std::string(GlobalConfig::GetDevicePluginPath());
465
466             DIR *dir;
467             dir = opendir(PLUGIN_PATH.c_str());
468             if (!dir) {
469                 DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
470                 return;
471             }
472
473             LogInfo("Plugin DIRECTORY IS" << PLUGIN_PATH);
474             struct dirent* libdir;
475
476             errno = 0;
477
478             std::list<std::string> pluginsPaths;
479
480             while ((libdir = readdir(dir)) != 0) {
481                 if (strcmp(libdir->d_name, ".") == 0 ||
482                     strcmp(libdir->d_name, "..") == 0)
483                 {
484                     continue;
485                 }
486
487                 std::string path = PLUGIN_PATH;
488                 path += "/";
489                 path += libdir->d_name;
490
491                 struct stat tmp;
492
493                 if (stat(path.c_str(), &tmp) == -1) {
494                     LogError("Failed to open file" << path);
495                     continue;
496                 }
497
498                 if (!S_ISDIR(tmp.st_mode)) {
499                     LogError("Not a directory" << path);
500                     continue;
501                 }
502
503                 pluginsPaths.push_back(path);
504             }
505
506             wrt_count_plugin = pluginsPaths.size();
507
508             FOREACH(it, pluginsPaths) {
509                 wrt_plugin_data *plugin_data = new wrt_plugin_data;
510
511                 plugin_data->plugin_installed_cb = installed_cb;
512                 plugin_data->plugin_path = const_cast<char*>(it->c_str());
513                 plugin_data->user_data = user_param;
514
515                 wrt_install_plugin(
516                     it->c_str(), static_cast<void*>(plugin_data),
517                     plugin_install_status_cb,
518                     plugin_install_progress_cb);
519             }
520
521             wrt_install_plugin(
522                 GlobalConfig::GetW3CGeolocationFeatureName(), NULL, NULL, NULL);
523
524             if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
525                 LogError("Failed to close dir: " << dir);
526             }
527
528             if (0 != unlink(installRequest.c_str())) {
529                 LogError("Failed to remove file initializing plugin "
530                          "installation");
531             }
532
533             Try {
534                 DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
535             }
536             Catch(DPL::Semaphore::Exception::Base){
537                 LogInfo("Failed to remove installation lock");
538             }
539         }
540         UNHANDLED_EXCEPTION_HANDLER_END
541     }
542
543     EXPORT_API int wrt_installer_init_for_tests(void *userdata,
544                             WrtInstallerInitCallback callback)
545     {
546         // Set DPL/LOG MID
547         DPL::Log::LogSystemSingleton::Instance().SetTag("WRT");
548
549         try
550         {
551             LogInfo("[WRT-API] INITIALIZING WRT INSTALLER...");
552             LogInfo("[WRT-API] BUILD: " << __TIMESTAMP__);
553
554             // Touch InstallerController Singleton
555             InstallerMainThreadSingleton::Instance().
556                 TouchArchitectureOnlyInstaller();
557
558             // Check paths
559             if (!checkPaths()) {
560                 if (callback) {
561                     callback(WRT_ERROR_NO_PATH, userdata);
562                 }
563                 return TRUE;
564             }
565
566             CONTROLLER_POST_SYNC_EVENT(
567                     InstallerController,
568                     InstallerControllerEvents::
569                     InitializeEvent());
570
571             if (callback) {
572                 LogInfo("[WRT-API] WRT INSTALLER INITIALIZATION CALLBACK");
573                 callback(WRT_SUCCESS, userdata);
574             }
575         }
576         catch (const DPL::Exception& ex)
577         {
578             LogError("Internal Error during Init:");
579             DPL::Exception::DisplayKnownException(ex);
580             if (callback) {
581                 callback(WRT_ERROR_INTERNAL, userdata);
582             }
583             return FALSE;
584         }
585
586         // OK
587         return TRUE;
588     }
589
590     EXPORT_API void wrt_installer_shutdown_for_tests()
591     {
592         try
593         {
594             LogInfo("[WRT-API] DEINITIALIZING WRT INSTALLER...");
595
596             // Installer termination
597             CONTROLLER_POST_SYNC_EVENT(
598                     InstallerController,
599                     InstallerControllerEvents::
600                     TerminateEvent());
601
602             // Global deinit check
603             LogInfo("Cleanup libxml2 global values.");
604             xmlCleanupParser();
605         }
606         catch (const DPL::Exception& ex)
607         {
608             LogError("Internal Error during Shutdown:");
609             DPL::Exception::DisplayKnownException(ex);
610         }
611     }
612
613     EXPORT_API WrtErrStatus wrt_get_widget_by_pkgname(const std::string pkgname,
614             int *widget_handle)
615     {
616         try
617         {
618             LogInfo("[WRT-API] GETTING WIDGET HANDLE BY PKG NAME : "
619                     << pkgname);
620
621             WidgetHandle handle = WidgetDAO::getHandle(
622                     DPL::FromASCIIString(pkgname));
623             *widget_handle = static_cast<int>(handle);
624             return WRT_SUCCESS;
625         }
626         catch (WidgetDAOReadOnly::Exception::WidgetNotExist)
627         {
628             LogError("Error package name is not found");
629             return WRT_ERROR_PKGNAME_NOT_FOUND;
630         }
631         catch (const DPL::Exception& ex)
632         {
633             LogError("Internal Error during get widget id by package name");
634             DPL::Exception::DisplayKnownException(ex);
635             return WRT_ERROR_INTERNAL;
636         }
637     }
638
639     EXPORT_API WrtErrStatus wrt_get_widget_by_guid(const std::string guid,
640             int *widget_handle)
641     {
642         try
643         {
644             LogInfo("[WRT-API] GETTING WIDGET HANDLE BY WidgetID : "
645                     << guid);
646
647             WidgetGUID widget_guid = DPL::FromUTF8String(guid);
648             WidgetHandle handle = WidgetDAO::getHandle(widget_guid);
649             *widget_handle = static_cast<int>(handle);
650             return WRT_SUCCESS;
651         }
652         catch (WidgetDAOReadOnly::Exception::WidgetNotExist)
653         {
654             LogError("Error package name is not found");
655             return WRT_ERROR_PKGNAME_NOT_FOUND;
656         }
657         catch (const DPL::Exception& ex)
658         {
659             LogError("Internal Error during get widget id by package name");
660             DPL::Exception::DisplayKnownException(ex);
661             return WRT_ERROR_INTERNAL;
662         }
663     }
664 #ifdef __cplusplus
665 }
666 #endif