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