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