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