[Release] wrt-installer_0.1.23
[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 #ifdef __cplusplus
52
53 #define EXPORT_API __attribute__((visibility("default")))
54 extern "C"
55 {
56 #endif
57 inline InstallMode::Type translateInstallMode(
58     WrtInstallMode installMode)
59 {
60     if (WRT_INSTALL_MODE_INSTALL_WGT == installMode) {
61         return InstallMode::INSTALL_MODE_WGT;
62     } else if (WRT_INSTALL_MODE_INSTALL_DIRECTORY == installMode) {
63         return InstallMode::INSTALL_MODE_DIRECTORY;
64     } else if (WRT_INSTALL_MODE_INSTALL_PRELOAD == installMode) {
65         return InstallMode::INSTALL_MODE_PRELOAD;
66     }
67     Assert(true && "wrong argument is inputed");
68 }
69
70 const char PLUGIN_INSTALL_SEMAPHORE[] = "/.wrt_plugin_install_lock";
71 static int wrt_count_plugin;
72
73 static std::string cutOffFileName(const std::string& path)
74 {
75     size_t found = path.find_last_of("/");
76     if (found == std::string::npos) {
77         return path;
78     } else {
79         return path.substr(0, found);
80     }
81 }
82
83 static bool checkPath(const std::string& path)
84 {
85     struct stat st;
86     if (0 == stat(path.c_str(), &st) && S_ISDIR(st.st_mode)) {
87         return true;
88     }
89     LogError("Cannot access directory [ " << path << " ]");
90     return false;
91 }
92
93 static bool checkPaths()
94 {
95     bool if_ok = true;
96     if_ok &= (checkPath(cutOffFileName(
97                             GlobalConfig::GetWrtDatabaseFilePath())));
98     if (!if_ok) {
99         LogError(
100             "Path <" << GlobalConfig::GetWrtDatabaseFilePath() <<
101             "> does not exist.");
102     }
103
104     if_ok &= (checkPath(GlobalConfig::GetDevicePluginPath()));
105     if (!if_ok) {
106         LogError(
107             "Path <" << GlobalConfig::GetDevicePluginPath() <<
108             "> does not exist.");
109     }
110
111     if_ok &= (checkPath(GlobalConfig::GetUserInstalledWidgetPath()));
112     if (!if_ok) {
113         LogError(
114             "Path <" << GlobalConfig::GetUserInstalledWidgetPath() <<
115             "> does not exist.");
116     }
117
118     if_ok &= (checkPath(GlobalConfig::GetUserPreloadedWidgetPath()));
119     if (!if_ok) {
120         LogError(
121             "Path <" << GlobalConfig::GetUserPreloadedWidgetPath() <<
122             "> does not exist.");
123     }
124     return if_ok;
125 }
126
127 void plugin_install_status_cb(WrtErrStatus status,
128                               void* userparam)
129 {
130     Assert(userparam);
131
132     wrt_plugin_data *plugin_data = static_cast<wrt_plugin_data*>(userparam);
133
134     if (--wrt_count_plugin < 1) {
135         LogDebug("All plugins installation completed");
136
137         LogDebug("Call SetAllinstallpluginsCallback");
138         plugin_data->plugin_installed_cb(plugin_data->user_data);
139     }
140
141     if (status == WRT_SUCCESS) {
142         LogInfo(
143             "plugin installation is successful: " <<
144             plugin_data->plugin_path);
145         return;
146     }
147
148     LogError("Fail to install plugin : " << plugin_data->plugin_path);
149
150     switch (status) {
151     case WRT_INSTALLER_ERROR_PLUGIN_INSTALLATION_FAILED:
152         LogError("Failed : Plugin install path is wrong");
153         break;
154     case WRT_INSTALLER_ERROR_UNKNOWN:
155         LogError("Failed : Unkown Error");
156         break;
157     default:
158         break;
159     }
160 }
161
162 void plugin_install_progress_cb(float percent,
163                                 const char* description,
164                                 void* userdata)
165 {
166     char *plugin_path = static_cast<char*>(userdata);
167
168     LogInfo("Install plugin : " << plugin_path <<
169             ", Progress : " << percent <<
170             ", Description : " << description);
171 }
172
173 EXPORT_API void wrt_installer_init(void *userdata,
174                                   WrtInstallerInitCallback callback)
175 {
176     // Set DPL/LOG MID
177     DPL::Log::LogSystemSingleton::Instance().SetTag("WRT");
178
179     try {
180         LogInfo("[WRT-API] INITIALIZING WRT INSTALLER...");
181         LogInfo("[WRT-API] BUILD: " << __TIMESTAMP__);
182
183         // Touch InstallerController Singleton
184         InstallerMainThreadSingleton::Instance().TouchArchitecture();
185
186         // Check paths
187         if (!checkPaths()) {
188             if (callback) {
189                 callback(WRT_INSTALLER_ERROR_FATAL_ERROR, userdata);
190             }
191             return;
192         }
193
194         // Initialize ValidationCore - this must be done before AttachDatabases
195         ValidationCore::VCoreInit(
196             std::string(GlobalConfig::GetFingerprintListFile()),
197             std::string(GlobalConfig::GetFingerprintListSchema()),
198             std::string(GlobalConfig::GetVCoreDatabaseFilePath()));
199
200         InstallerMainThreadSingleton::Instance().AttachDatabases();
201
202         LogInfo("Prepare libxml2 to work in multithreaded program.");
203         xmlInitParser();
204
205         // Initialize Language Subtag registry
206         LanguageSubtagRstTreeSingleton::Instance().Initialize();
207
208         // Installer init
209         CONTROLLER_POST_SYNC_EVENT(
210             Logic::InstallerController,
211             InstallerControllerEvents::
212                 InitializeEvent());
213
214         // Install deferred widget packages
215         CONTROLLER_POST_EVENT(
216             Logic::InstallerController,
217             InstallerControllerEvents::
218                 InstallDeferredWidgetPackagesEvent());
219
220         if (callback) {
221             LogInfo("[WRT-API] WRT INSTALLER INITIALIZATION CALLBACK");
222             callback(WRT_SUCCESS, userdata);
223         }
224     } catch (const DPL::Exception& ex) {
225         LogError("Internal Error during Init:");
226         DPL::Exception::DisplayKnownException(ex);
227         if (callback) {
228             callback(WRT_INSTALLER_ERROR_FATAL_ERROR, userdata);
229             return;
230         }
231     }
232     return;
233 }
234
235 EXPORT_API void wrt_installer_shutdown()
236 {
237     try {
238         LogInfo("[WRT-API] DEINITIALIZING WRT INSTALLER...");
239
240         // Installer termination
241         CONTROLLER_POST_SYNC_EVENT(
242             Logic::InstallerController,
243             InstallerControllerEvents::
244                 TerminateEvent());
245
246         InstallerMainThreadSingleton::Instance().DetachDatabases();
247
248         // This must be done after DetachDatabase
249         ValidationCore::VCoreDeinit();
250
251         // Global deinit check
252         LogInfo("Cleanup libxml2 global values.");
253         xmlCleanupParser();
254     } catch (const DPL::Exception& ex) {
255         LogError("Internal Error during Shutdown:");
256         DPL::Exception::DisplayKnownException(ex);
257     }
258 }
259
260 EXPORT_API void wrt_install_widget(
261     const char *path,
262     void* userdata,
263     WrtInstallerStatusCallback status_cb,
264     WrtProgressCallback progress_cb,
265     WrtInstallMode installMode,
266     bool quiet,
267     std::shared_ptr<PackageManager::
268                         IPkgmgrSignal> pkgmgrInterface
269     )
270 {
271     UNHANDLED_EXCEPTION_HANDLER_BEGIN
272     {
273         LogInfo("[WRT-API] INSTALL WIDGET: " << path);
274         // Post installation event
275         CONTROLLER_POST_EVENT(
276             Logic::InstallerController,
277             InstallerControllerEvents::InstallWidgetEvent(
278                 path, WidgetInstallationStruct(
279                     InstallerCallbacksTranslate::installFinishedCallback,
280                     InstallerCallbacksTranslate::installProgressCallback,
281                     new InstallerCallbacksTranslate::StatusCallbackStruct(
282                         userdata, status_cb, progress_cb),
283                     translateInstallMode(installMode),
284                     quiet,
285                     pkgmgrInterface)));
286     }
287     UNHANDLED_EXCEPTION_HANDLER_END
288 }
289
290 EXPORT_API void wrt_uninstall_widget(
291     const char * const tzAppid,
292     void* userdata,
293     WrtInstallerStatusCallback status_cb,
294     WrtProgressCallback progress_cb,
295     std::shared_ptr<PackageManager::
296                         IPkgmgrSignal> pkgmgrSignalInterface)
297 {
298     UNHANDLED_EXCEPTION_HANDLER_BEGIN
299     {
300         std::string tizenAppid(tzAppid);
301         LogInfo("[WRT-API] UNINSTALL WIDGET: " << tizenAppid);
302         // Post uninstallation event
303         CONTROLLER_POST_EVENT(
304             Logic::InstallerController,
305             InstallerControllerEvents::UninstallWidgetEvent(
306                 tizenAppid,
307                 WidgetUninstallationStruct(
308                     InstallerCallbacksTranslate::uninstallFinishedCallback,
309                     InstallerCallbacksTranslate::installProgressCallback,
310                     new InstallerCallbacksTranslate::StatusCallbackStruct(
311                         userdata, status_cb, progress_cb),
312                     pkgmgrSignalInterface
313                     )
314                 )
315             );
316     }
317     UNHANDLED_EXCEPTION_HANDLER_END
318 }
319
320 EXPORT_API void wrt_install_plugin(
321     const char *pluginDir,
322     void *user_param,
323     WrtPluginInstallerStatusCallback status_cb,
324     WrtProgressCallback progress_cb)
325 {
326     UNHANDLED_EXCEPTION_HANDLER_BEGIN
327     {
328         LogInfo("[WRT-API] INSTALL PLUGIN: " << pluginDir);
329         //Private data for status callback
330         //Resource is free in pluginInstallFinishedCallback
331         InstallerCallbacksTranslate::PluginStatusCallbackStruct*
332         callbackStruct =
333             new InstallerCallbacksTranslate::PluginStatusCallbackStruct(
334                 user_param, status_cb, progress_cb);
335
336         CONTROLLER_POST_EVENT(
337             Logic::InstallerController,
338             InstallerControllerEvents::InstallPluginEvent(
339                 std::string(pluginDir),
340                 PluginInstallerStruct(
341                     InstallerCallbacksTranslate::
342                         pluginInstallFinishedCallback,
343                     InstallerCallbacksTranslate::
344                         installProgressCallback, callbackStruct)));
345     }
346     UNHANDLED_EXCEPTION_HANDLER_END
347 }
348
349 EXPORT_API void wrt_install_all_plugins(
350     WrtAllPluginInstalledCallback installed_cb,
351     void *user_param)
352 {
353     UNHANDLED_EXCEPTION_HANDLER_BEGIN
354     {
355         std::string installRequest =
356             std::string(GlobalConfig::GetPluginInstallInitializerName());
357
358         LogDebug("Install new plugins");
359
360         Try {
361             DPL::Semaphore lock(PLUGIN_INSTALL_SEMAPHORE);
362         }
363         Catch(DPL::Semaphore::Exception::Base){
364             LogError("Failed to create installation lock");
365             return;
366         }
367
368         struct stat tmp;
369
370         if (-1 == stat(installRequest.c_str(), &tmp) ||
371             !S_ISREG(tmp.st_mode))
372         {
373             if (ENOENT == errno) {
374                 LogDebug("Plugin installation not required");
375
376                 LogDebug("Call SetAllinstallPluginCallback");
377                 installed_cb(user_param);
378
379                 DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
380                 return;
381             }
382             LogWarning("Opening installation request file failed");
383         }
384
385         std::string PLUGIN_PATH =
386             std::string(GlobalConfig::GetDevicePluginPath());
387
388         DIR *dir;
389         dir = opendir(PLUGIN_PATH.c_str());
390         if (!dir) {
391             DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
392             return;
393         }
394
395         LogInfo("Plugin DIRECTORY IS" << PLUGIN_PATH);
396         struct dirent libdir;
397         struct dirent *result;
398         int return_code;
399
400         errno = 0;
401
402         std::list<std::string> pluginsPaths;
403
404         for (return_code = readdir_r(dir, &libdir, &result);
405                     result != NULL && return_code == 0;
406                     return_code = readdir_r(dir, &libdir, &result))
407         {
408             if (strcmp(libdir.d_name, ".") == 0 ||
409                 strcmp(libdir.d_name, "..") == 0)
410             {
411                 continue;
412             }
413
414             std::string path = PLUGIN_PATH;
415             path += "/";
416             path += libdir.d_name;
417
418             struct stat tmp;
419
420             if (stat(path.c_str(), &tmp) == -1) {
421                 LogError("Failed to open file" << path);
422                 continue;
423             }
424
425             if (!S_ISDIR(tmp.st_mode)) {
426                 LogError("Not a directory" << path);
427                 continue;
428             }
429
430             pluginsPaths.push_back(path);
431         }
432
433         wrt_count_plugin = pluginsPaths.size();
434
435         FOREACH(it, pluginsPaths) {
436             wrt_plugin_data *plugin_data = new wrt_plugin_data;
437
438             plugin_data->plugin_installed_cb = installed_cb;
439             plugin_data->plugin_path = const_cast<char*>(it->c_str());
440             plugin_data->user_data = user_param;
441
442             wrt_install_plugin(
443                 it->c_str(), static_cast<void*>(plugin_data),
444                 plugin_install_status_cb,
445                 plugin_install_progress_cb);
446         }
447
448         if (return_code != 0 || errno != 0) {
449             LogError("readdir_r() failed with " << DPL::GetErrnoString());
450         }
451
452         errno = 0;
453         if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
454             LogError("Failed to close dir: " << PLUGIN_PATH << " with error: "
455                                              << DPL::GetErrnoString());
456         }
457
458         if (0 != unlink(installRequest.c_str())) {
459             LogError("Failed to remove file initializing plugin "
460                      "installation");
461         }
462
463         Try {
464             DPL::Semaphore::Remove(PLUGIN_INSTALL_SEMAPHORE);
465         }
466         Catch(DPL::Semaphore::Exception::Base){
467             LogInfo("Failed to remove installation lock");
468         }
469     }
470     UNHANDLED_EXCEPTION_HANDLER_END
471 }
472
473 #ifdef __cplusplus
474 }
475 #endif